diff --git a/src/main/java/com/rarchives/ripme/ripper/AbstractRipper.java b/src/main/java/com/rarchives/ripme/ripper/AbstractRipper.java
index f680d8c4..1bc9f261 100644
--- a/src/main/java/com/rarchives/ripme/ripper/AbstractRipper.java
+++ b/src/main/java/com/rarchives/ripme/ripper/AbstractRipper.java
@@ -42,6 +42,21 @@ public abstract class AbstractRipper
public abstract String getHost();
public abstract String getGID(URL url) throws MalformedURLException;
+ private boolean shouldStop = false;
+
+ public void stop() {
+ shouldStop = true;
+ }
+ public boolean isStopped() {
+ return shouldStop;
+ }
+ protected void stopCheck() throws IOException {
+ if (shouldStop) {
+ threadPool.waitForThreads();
+ throw new IOException("Ripping interrupted");
+ }
+ }
+
/**
* Ensures inheriting ripper can rip this URL, raises exception if not.
* Otherwise initializes working directory and thread pool.
@@ -117,6 +132,11 @@ public abstract class AbstractRipper
* Sub-directory of the working directory to save the images to.
*/
public void addURLToDownload(URL url, String prefix, String subdirectory) {
+ try {
+ stopCheck();
+ } catch (IOException e) {
+ return;
+ }
String saveAs = url.toExternalForm();
saveAs = saveAs.substring(saveAs.lastIndexOf('/')+1);
if (saveAs.indexOf('?') >= 0) { saveAs = saveAs.substring(0, saveAs.indexOf('?')); }
diff --git a/src/main/java/com/rarchives/ripme/ripper/DownloadFileThread.java b/src/main/java/com/rarchives/ripme/ripper/DownloadFileThread.java
index eef29c40..8fdc2133 100644
--- a/src/main/java/com/rarchives/ripme/ripper/DownloadFileThread.java
+++ b/src/main/java/com/rarchives/ripme/ripper/DownloadFileThread.java
@@ -45,6 +45,12 @@ public class DownloadFileThread extends Thread {
* Notifies observers upon completion/error/warn.
*/
public void run() {
+ try {
+ observer.stopCheck();
+ } catch (IOException e) {
+ observer.downloadErrored(url, "Download interrupted");
+ return;
+ }
if (saveAs.exists()) {
if (Utils.getConfigBoolean("file.overwrite", false)) {
logger.info("[!] Deleting existing file" + prettySaveAs);
diff --git a/src/main/java/com/rarchives/ripme/ripper/rippers/ImgurRipper.java b/src/main/java/com/rarchives/ripme/ripper/rippers/ImgurRipper.java
index 90061bf0..693f7729 100644
--- a/src/main/java/com/rarchives/ripme/ripper/rippers/ImgurRipper.java
+++ b/src/main/java/com/rarchives/ripme/ripper/rippers/ImgurRipper.java
@@ -100,6 +100,7 @@ public class ImgurRipper extends AbstractRipper {
index = 0;
ImgurAlbum album = getImgurAlbum(url);
for (ImgurImage imgurImage : album.images) {
+ stopCheck();
String saveAs = workingDir.getCanonicalPath();
if (!saveAs.endsWith(File.separator)) {
saveAs += File.separator;
@@ -217,6 +218,7 @@ public class ImgurRipper extends AbstractRipper {
logger.info("[ ] Retrieving " + url.toExternalForm());
Document doc = Jsoup.connect(url.toExternalForm()).get();
for (Element album : doc.select("div.cover a")) {
+ stopCheck();
if (!album.hasAttr("href")
|| !album.attr("href").contains("imgur.com/a/")) {
continue;
@@ -236,6 +238,7 @@ public class ImgurRipper extends AbstractRipper {
private void ripSubreddit(URL url) throws IOException {
int page = 0;
while (true) {
+ stopCheck();
String pageURL = url.toExternalForm();
if (!pageURL.endsWith("/")) {
pageURL += "/";
diff --git a/src/main/java/com/rarchives/ripme/ui/MainWindow.java b/src/main/java/com/rarchives/ripme/ui/MainWindow.java
index 5610b850..d83f07ad 100644
--- a/src/main/java/com/rarchives/ripme/ui/MainWindow.java
+++ b/src/main/java/com/rarchives/ripme/ui/MainWindow.java
@@ -22,7 +22,6 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
-import java.awt.image.BufferedImage;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
@@ -30,7 +29,6 @@ import java.util.Arrays;
import javax.imageio.ImageIO;
import javax.swing.DefaultListModel;
-import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
@@ -67,7 +65,8 @@ public class MainWindow implements Runnable, RipStatusHandler {
private static JFrame mainFrame;
private static JTextField ripTextfield;
- private static JButton ripButton;
+ private static JButton ripButton,
+ stopButton;
private static JLabel statusLabel;
private static JButton openButton;
@@ -198,14 +197,21 @@ public class MainWindow implements Runnable, RipStatusHandler {
}
ripTextfield = new JTextField("", 20);
- ImageIcon ripIcon = new ImageIcon(mainIcon.getScaledInstance(20, 20, Image.SCALE_SMOOTH));
+ ImageIcon ripIcon = new ImageIcon(mainIcon);
ripButton = new JButton("Rip", ripIcon);
+ stopButton = new JButton("Stop");
+ stopButton.setVisible(false);
+ try {
+ Image stopIcon = ImageIO.read(getClass().getClassLoader().getResource("stop.png"));
+ stopButton.setIcon(new ImageIcon(stopIcon));
+ } catch (Exception e) { }
JPanel ripPanel = new JPanel(new GridBagLayout());
ripPanel.setBorder(emptyBorder);
gbc.gridx = 0; ripPanel.add(new JLabel("URL:", JLabel.RIGHT), gbc);
gbc.gridx = 1; ripPanel.add(ripTextfield, gbc);
gbc.gridx = 2; ripPanel.add(ripButton, gbc);
+ ripPanel.add(stopButton, gbc);
statusLabel = new JLabel("Inactive");
statusLabel.setHorizontalAlignment(JLabel.CENTER);
@@ -329,6 +335,23 @@ public class MainWindow implements Runnable, RipStatusHandler {
private void setupHandlers() {
ripButton.addActionListener(new RipButtonHandler());
ripTextfield.addActionListener(new RipButtonHandler());
+ stopButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent event) {
+ if (ripper != null) {
+ ripper.stop();
+ ripButton.setVisible(true);
+ stopButton.setVisible(false);
+ ripTextfield.setEnabled(true);
+ statusProgress.setValue(0);
+ statusProgress.setVisible(false);
+ mainFrame.pack();
+ statusProgress.setValue(0);
+ status("Ripping interrupted");
+ appendLog("Ripper interrupted", Color.RED);
+ }
+ }
+ });
optionLog.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
@@ -574,7 +597,8 @@ public class MainWindow implements Runnable, RipStatusHandler {
error("Given URL is not valid, expecting http://website.com/page/...");
return null;
}
- ripButton.setEnabled(false);
+ ripButton.setVisible(false);
+ stopButton.setVisible(true);
ripTextfield.setEnabled(false);
statusProgress.setValue(100);
openButton.setVisible(false);
@@ -612,7 +636,8 @@ public class MainWindow implements Runnable, RipStatusHandler {
error("Unable to rip this URL: " + e.getMessage());
}
}
- ripButton.setEnabled(true);
+ ripButton.setVisible(true);
+ stopButton.setVisible(false);
ripTextfield.setEnabled(true);
statusProgress.setValue(0);
mainFrame.pack();
@@ -640,6 +665,9 @@ public class MainWindow implements Runnable, RipStatusHandler {
}
private void handleEvent(StatusEvent evt) {
+ if (ripper.isStopped()) {
+ return;
+ }
RipStatusMessage msg = evt.msg;
int completedPercent = evt.ripper.getCompletionPercentage();
@@ -667,7 +695,8 @@ public class MainWindow implements Runnable, RipStatusHandler {
historyListModel.addElement(ripTextfield.getText());
}
saveHistory();
- ripButton.setEnabled(true);
+ ripButton.setVisible(true);
+ stopButton.setVisible(false);
ripTextfield.setEnabled(true);
statusProgress.setValue(0);
statusProgress.setVisible(false);
@@ -678,9 +707,7 @@ public class MainWindow implements Runnable, RipStatusHandler {
try {
Image folderIcon = ImageIO.read(getClass().getClassLoader().getResource("folder.png"));
openButton.setIcon(new ImageIcon(folderIcon));
- } catch (Exception e) {
- logger.error("Error while setting folder icon", e);
- }
+ } catch (Exception e) { }
appendLog( "Rip complete, saved to " + prettyFile, Color.GREEN);
openButton.setActionCommand(f.toString());
openButton.addActionListener(new ActionListener() {
diff --git a/src/main/resources/icon.png b/src/main/resources/icon.png
index 59192587..606ae39b 100644
Binary files a/src/main/resources/icon.png and b/src/main/resources/icon.png differ
diff --git a/src/main/resources/stop.png b/src/main/resources/stop.png
new file mode 100644
index 00000000..aba7a52c
Binary files /dev/null and b/src/main/resources/stop.png differ