From bd12a1de3da432f968ed3aebb9bb494ef8a1229b Mon Sep 17 00:00:00 2001 From: Zlatin Balevsky Date: Sun, 23 Jun 2019 06:59:52 +0100 Subject: [PATCH] pause/resume downloads --- .../muwire/core/download/Downloader.groovy | 13 ++++++-- .../com/muwire/gui/MainFrameController.groovy | 6 ++++ .../com/muwire/gui/MainFrameModel.groovy | 4 +++ .../views/com/muwire/gui/MainFrameView.groovy | 33 +++++++++++++++++-- 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/core/src/main/groovy/com/muwire/core/download/Downloader.groovy b/core/src/main/groovy/com/muwire/core/download/Downloader.groovy index 6e80ebba..3f465d9c 100644 --- a/core/src/main/groovy/com/muwire/core/download/Downloader.groovy +++ b/core/src/main/groovy/com/muwire/core/download/Downloader.groovy @@ -25,7 +25,7 @@ import net.i2p.util.ConcurrentHashSet @Log public class Downloader { - public enum DownloadState { CONNECTING, HASHLIST, DOWNLOADING, FAILED, CANCELLED, FINISHED } + public enum DownloadState { CONNECTING, HASHLIST, DOWNLOADING, FAILED, CANCELLED, PAUSED, FINISHED } private enum WorkerState { CONNECTING, HASHLIST, DOWNLOADING, FINISHED} private static final ExecutorService executorService = Executors.newCachedThreadPool({r -> @@ -53,7 +53,7 @@ public class Downloader { private final Set successfulDestinations = new ConcurrentHashSet<>() - private volatile boolean cancelled + private volatile boolean cancelled, paused private final AtomicBoolean eventFired = new AtomicBoolean() private boolean piecesFileClosed @@ -136,6 +136,9 @@ public class Downloader { public DownloadState getCurrentState() { if (cancelled) return DownloadState.CANCELLED + if (paused) + return DownloadState.PAUSED + boolean allFinished = true activeWorkers.values().each { allFinished &= it.currentState == WorkerState.FINISHED @@ -183,6 +186,11 @@ public class Downloader { pieces.clearAll() } + public void pause() { + paused = true + stop() + } + void stop() { activeWorkers.values().each { it.cancel() @@ -203,6 +211,7 @@ public class Downloader { def worker = activeWorkers.get(destination) if (worker != null) { if (worker.currentState == WorkerState.FINISHED) { + paused = false def newWorker = new DownloadWorker(destination) activeWorkers.put(destination, newWorker) executorService.submit(newWorker) diff --git a/gui/griffon-app/controllers/com/muwire/gui/MainFrameController.groovy b/gui/griffon-app/controllers/com/muwire/gui/MainFrameController.groovy index 5031abff..5a2c1932 100644 --- a/gui/griffon-app/controllers/com/muwire/gui/MainFrameController.groovy +++ b/gui/griffon-app/controllers/com/muwire/gui/MainFrameController.groovy @@ -165,6 +165,12 @@ class MainFrameController { def downloader = model.downloads[selectedDownload()].downloader downloader.resume() } + + @ControllerAction + void pause() { + def downloader = model.downloads[selectedDownload()].downloader + downloader.pause() + } private void markTrust(String tableName, TrustLevel level, def list) { int row = builder.getVariable(tableName).getSelectedRow() diff --git a/gui/griffon-app/models/com/muwire/gui/MainFrameModel.groovy b/gui/griffon-app/models/com/muwire/gui/MainFrameModel.groovy index 983b6751..48b0fc7c 100644 --- a/gui/griffon-app/models/com/muwire/gui/MainFrameModel.groovy +++ b/gui/griffon-app/models/com/muwire/gui/MainFrameModel.groovy @@ -68,6 +68,8 @@ class MainFrameModel { @Observable boolean trustButtonsEnabled @Observable boolean cancelButtonEnabled @Observable boolean retryButtonEnabled + @Observable boolean pauseButtonEnabled + @Observable String resumeButtonText private final Set infoHashes = new HashSet<>() @@ -168,6 +170,8 @@ class MainFrameModel { watched.addAll(core.muOptions.watchedDirectories) builder.getVariable("watched-directories-table").model.fireTableDataChanged() watched.each { core.eventBus.publish(new FileSharedEvent(file : new File(it))) } + + resumeButtonText = "Retry" } }) diff --git a/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy b/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy index 0f0a399b..021d6573 100644 --- a/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy +++ b/gui/griffon-app/views/com/muwire/gui/MainFrameView.groovy @@ -135,8 +135,9 @@ class MainFrameView { } } panel (constraints : BorderLayout.SOUTH) { + button(text: "Pause", enabled : bind {model.pauseButtonEnabled}, pauseAction) button(text: "Cancel", enabled : bind {model.cancelButtonEnabled }, cancelAction ) - button(text: "Retry", enabled : bind {model.retryButtonEnabled}, resumeAction) + button(text: bind { model.resumeButtonText }, enabled : bind {model.retryButtonEnabled}, resumeAction) } } } @@ -295,6 +296,7 @@ class MainFrameView { if (selectedRow < 0) { model.cancelButtonEnabled = false model.retryButtonEnabled = false + model.pauseButtonEnabled = false return } def downloader = model.downloads[selectedRow]?.downloader @@ -305,15 +307,25 @@ class MainFrameView { case Downloader.DownloadState.DOWNLOADING : case Downloader.DownloadState.HASHLIST: model.cancelButtonEnabled = true + model.pauseButtonEnabled = true model.retryButtonEnabled = false break case Downloader.DownloadState.FAILED: model.cancelButtonEnabled = true model.retryButtonEnabled = true + model.resumeButtonText = "Retry" + model.pauseButtonEnabled = false + break + case Downloader.DownloadState.PAUSED: + model.cancelButtonEnabled = true + model.retryButtonEnabled = true + model.resumeButtonText = "Resume" + model.pauseButtonEnabled = false break default: model.cancelButtonEnabled = false model.retryButtonEnabled = false + model.pauseButtonEnabled = false } }) @@ -421,21 +433,32 @@ class MainFrameView { int selected = selectedDownloaderRow() if (selected < 0) return + boolean pauseEnabled = false boolean cancelEnabled = false boolean retryEnabled = false + String resumeText = "Retry" Downloader downloader = model.downloads[selected].downloader switch(downloader.currentState) { case Downloader.DownloadState.DOWNLOADING: case Downloader.DownloadState.HASHLIST: case Downloader.DownloadState.CONNECTING: + pauseEnabled = true cancelEnabled = true retryEnabled = false break case Downloader.DownloadState.FAILED: + pauseEnabled = false cancelEnabled = true retryEnabled = true break + case Downloader.DownloadState.PAUSED: + pauseEnabled = false + cancelEnabled = true + retryEnabled = true + resumeText = "Resume" + break default : + pauseEnabled = false cancelEnabled = false retryEnabled = false } @@ -450,6 +473,12 @@ class MainFrameView { }) menu.add(copyHashToClipboard) + if (pauseEnabled) { + JMenuItem pause = new JMenuItem("Pause") + pause.addActionListener({mvcGroup.controller.pause()}) + menu.add(pause) + } + if (cancelEnabled) { JMenuItem cancel = new JMenuItem("Cancel") cancel.addActionListener({mvcGroup.controller.cancel()}) @@ -457,7 +486,7 @@ class MainFrameView { } if (retryEnabled) { - JMenuItem retry = new JMenuItem("Retry") + JMenuItem retry = new JMenuItem(resumeText) retry.addActionListener({mvcGroup.controller.resume()}) menu.add(retry) }