From f4f8ce7f2eb19682c96975b9551cdfd3093e1fa1 Mon Sep 17 00:00:00 2001 From: 4pr0n Date: Thu, 17 Apr 2014 22:11:37 -0700 Subject: [PATCH] Added stop button --- .../ripme/ripper/AbstractRipper.java | 20 ++++++++ .../ripme/ripper/DownloadFileThread.java | 6 +++ .../ripme/ripper/rippers/ImgurRipper.java | 3 ++ .../com/rarchives/ripme/ui/MainWindow.java | 47 ++++++++++++++---- src/main/resources/icon.png | Bin 1381 -> 728 bytes src/main/resources/stop.png | Bin 0 -> 1158 bytes 6 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 src/main/resources/stop.png 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 59192587bb81dc9c752301b5927d3d1177987322..606ae39bcb6e25763a18b25fb25e4728bf10a54c 100644 GIT binary patch literal 728 zcmV;}0w?{6P)P000;W1^@s654Bdt00006VoOIv00000 z008+zyMF)x010qNS#tmY3ljhU3ljkVnw%H_000McNliru-UJc^G%XU0>2&}A03B&m zSad^gZEa<4bN~PV002XBWnpw>WFU8GbZ8()Nlj2>E@cM*00KNoL_t(Y$Gw(4tRYbp z$Il&vVv1Rn>0ZW1bR<3sr36up>QxGbP9Yfy(WoYoP*VvBqS$RjbPAzUAyFWBZ*=!b<%jLVzo2F?X2m@2mmhbo?#fZ2$|34H@Bb5<#0Zq7ss_)?P?Qh zG#X$S=DVng)oOjZDaPY*P$(4d!uxza2w-3n@v0z z3}Cn0iHo#a?Zt#Dl?qsv6}8jr^qn0sT{KN|i;ZpDIC0{{=KxNZZCE%Qrd^+a1AhDV?SWJ(m0Vd_K{A;{KA$JIon=`x zFfhObK}ZLK!NR3WmwI+Wg4F}RdGlsZCX-pdapMN1(`hCM0vLPSgot3OlI-=_3Nc{I?W|X+IBa#ZIj>cXXnqKzw7mSr}FuHi)-2p z27^nLB&wc3EEbzwSy_pws#?-@oy)S^P&|nU0BCr4nDzJf!?LV5bDVRWJb7}+@Auzx zlMrh-`u_3b$Fvi00AP%Ph*&b2#M07|LkIw{XU`tkwmpC6&YjQve*c_9qE;4ch@!ZU zbH4MuW(<~PA)C!sj#D%m{Qy90VPWAyAQ1R55{ZCUD<+(C+D*}7jDd5$r2}BPu9K>& z;_~wH!ra{4$Ki1JUkx}%a_iQudx=D1aDILsqA0%iifWoBy1TneQ&Us?z<~q%xEuWb z{rjD-UcGA0<#G@Np_bC?_EM>|?deF8#05b>M@L6qbb%j9rBd^WMB>T>%knp@T;q@Fx_&p2NF09l z>>2&zb1S}OSvY?DI6|Qian4yHk?3n{YugLJ%x1I2(b3Ug7-QJn+$=?-QLgKH%~LEC z3h3?aEnU8RnTr4*ilRhBhu7EFiHKM=^%D`Ao13wJ|9N=t*3OYJEYBH~AO=WOLaU}pR#>dBv znVFgPTE&ZqAW0Gq9z4hxW6uHD8~`>pHoT^3!Y~YKfIvS0!_id57kzzwE!BLKcaEb+ zkJ9k)FgiOsClp2bivxfl2v1vDTE07X?i`b4nM~6}Wp~x}Uja~^G&7xSaN83R4Gs=M zQ4}W2@=UQ<{2c(qNF;)>v9UaWuT)j_SeErgHk+kt7Zqcy06+#{)goXR2DP@fVrXdS zjTTJPL{n1}8yy|}xxKx8B$vyXV`F25NF?%hB~(>)4#0(ST*Cks02Ip?mrO)*I2_KM zIdjHzi;alz@ZrO%>Qhy<0AO`;a6 zX_{EM{=E=z6DfzT06=mP$!VI_+9>cl6L1kZ1V97O1z=Irw9`8UZ%Bl7!m$S6QvlNd n`~Y?gzN=QL?(Nk6pKX5wcBGug3O-ZU00000NkvXXu0mjfMYw#w diff --git a/src/main/resources/stop.png b/src/main/resources/stop.png new file mode 100644 index 0000000000000000000000000000000000000000..aba7a52cb8cdce595b64049b438419cc41d3e1ec GIT binary patch literal 1158 zcmV;11bO?3P)WFU8GbZ8()Nlj2>E@cM*00ZhtL_t(Y$F)^UNNQ^o z{{9|DZ7R@8jiP8E(E}2%L=a87(L&4zt;NKB0SII|CEf+I0b`2 z>ht*!3WX4jMj?~QAeYObP$&q;asQ6s{rw$VTU*rOaA1FbKc!DjP7ZBrYeP>@56a8S zNh%+bDn+-qx8EiwC%^t3@Q;$7o{leHzCf$h5<BPhYB9TZEkVGPZL?VID z=flg(OOm~*sR>h4QzSDpGd028-QBPK{r!L3+}tpoR4T>L&=BhC>V6Z8#lH*b^ZWhO z<#J(pc^R=-jQMwWcVld9j3g0IN?|Y%jNnwK_C#I zl(HX0b#?W3V_F(IJ3Aq?p51OoZ*Q+E7z_dcN=izgR;%}fxSE<8hH-g$`9Tm0g_uDk z5}~ZDjCDarM+Y$)jf~{+@sWXBt=7H5!opt!Uxh-EkS0bT1OWiYamdI>yx?lJdQT#e zB-hPWOs9vvE#orA8SX)~|eBlA$?Cgxa z%VaVTLXrsp!0YvX1%OyAhSAZ{gq#l!4kpw@=%l~m7>0nE1^~sy#iXR9gc+SqCo8hS zV1P&@Vma4pwX7z!wY6w(Zzn>dxZQ4sQD0yGabb9#$I{XgRjE|$aXOt;ud(m){K z5x#kz$L8iHjYJ~gc^*$sPZ$^&V6hDi4fOi@8a&T`Tr`bFL*k2MHk)y9a6kb-sZ^35 z3)ruHXF&#&Q3k97Z(?)&1Or`iN#`6RaHTuP@tfo0O#lD@Or&CK0e0V z+gn15FDxu1ET5DMXLWUzn$2dszP^5X_f}L?V0wBQrKP3hA2%8RoSvRitJRA537bkd zjzd>h7j!xu$;!(5+{%m>zu!;S*Vl1zae+`Mg!}t@NTpK9<#H&MO0>4NvV4DfC;yl7 YCmKlEbhXJjkpKVy07*qoM6N<$f~g}4Gynhq literal 0 HcmV?d00001