diff --git a/onionshare_gui/mode.py b/onionshare_gui/mode.py
index e4269dc6..debd2657 100644
--- a/onionshare_gui/mode.py
+++ b/onionshare_gui/mode.py
@@ -17,13 +17,12 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-import threading
import time
-import os
+import threading
from PyQt5 import QtCore, QtWidgets, QtGui
from onionshare import strings
-from onionshare.common import Common, ShutdownTimer
+from onionshare.common import ShutdownTimer
from .server_status import ServerStatus
from .onion_thread import OnionThread
@@ -38,9 +37,9 @@ class Mode(QtWidgets.QWidget):
starting_server_step2 = QtCore.pyqtSignal()
starting_server_step3 = QtCore.pyqtSignal()
starting_server_error = QtCore.pyqtSignal(str)
- set_share_server_active = QtCore.pyqtSignal(bool)
+ set_server_active = QtCore.pyqtSignal(bool)
- def __init__(self, common, qtapp, app, web, status_bar, server_share_status_label, system_tray, filenames=None):
+ def __init__(self, common, qtapp, app, web, status_bar, server_status_label, system_tray, filenames=None):
super(Mode, self).__init__()
self.common = common
self.qtapp = qtapp
@@ -48,13 +47,13 @@ class Mode(QtWidgets.QWidget):
self.web = web
self.status_bar = status_bar
- self.server_share_status_label = server_share_status_label
+ self.server_status_label = server_status_label
self.system_tray = system_tray
self.filenames = filenames
# Server status
- self.server_status = ServerStatus(self.common, self.qtapp, self.app, self.web, False)
+ self.server_status = ServerStatus(self.common, self.qtapp, self.app, self.web)
self.server_status.server_started.connect(self.start_server)
self.server_status.server_stopped.connect(self.stop_server)
self.server_status.server_canceled.connect(self.cancel_server)
@@ -77,7 +76,7 @@ class Mode(QtWidgets.QWidget):
def init(self):
"""
- Add custom initialization of the mode here.
+ Add custom initialization here.
"""
pass
@@ -92,17 +91,16 @@ class Mode(QtWidgets.QWidget):
Start the onionshare server. This uses multiple threads to start the Tor onion
server and the web app.
"""
- self.common.log('ShareMode', 'start_server')
-
- self.set_share_server_active.emit(True)
+ self.common.log('Mode', 'start_server')
+
+ self.start_server_custom()
+ self.set_server_active.emit(True)
self.app.set_stealth(self.common.settings.get('use_stealth'))
- # Hide and reset the downloads if we have previously shared
- self.downloads.reset_downloads()
- self.reset_info_counters()
+ # Clear the status bar
self.status_bar.clearMessage()
- self.server_share_status_label.setText('')
+ self.server_status_label.setText('')
# Reset web counters
self.web.download_count = 0
@@ -128,64 +126,44 @@ class Mode(QtWidgets.QWidget):
# wait for modules in thread to load, preventing a thread-related cx_Freeze crash
time.sleep(0.2)
- self.common.log('OnionshareGui', 'start_server', 'Starting an onion thread')
+ self.common.log('Mode', 'start_server', 'Starting an onion thread')
self.t = OnionThread(self.common, function=start_onion_service, kwargs={'self': self})
self.t.daemon = True
self.t.start()
+
+ def start_server_custom(self):
+ """
+ Add custom initialization here.
+ """
+ pass
def start_server_step2(self):
"""
- Step 2 in starting the onionshare server. Zipping up files.
+ Step 2 in starting the onionshare server.
"""
- self.common.log('ShareMode', 'start_server_step2')
+ self.common.log('Mode', 'start_server_step2')
- # add progress bar to the status bar, indicating the compressing of files.
- self._zip_progress_bar = ZipProgressBar(0)
- self.filenames = []
- for index in range(self.file_selection.file_list.count()):
- self.filenames.append(self.file_selection.file_list.item(index).filename)
+ self.start_server_step2_custom()
- self._zip_progress_bar.total_files_size = Mode._compute_total_size(self.filenames)
- self.status_bar.insertWidget(0, self._zip_progress_bar)
+ # Nothing to do here.
- # prepare the files for sending in a new thread
- def finish_starting_server(self):
- # prepare files to share
- def _set_processed_size(x):
- if self._zip_progress_bar != None:
- self._zip_progress_bar.update_processed_size_signal.emit(x)
- try:
- self.web.set_file_info(self.filenames, processed_size_callback=_set_processed_size)
- self.app.cleanup_filenames.append(self.web.zip_filename)
-
- # Only continue if the server hasn't been canceled
- if self.server_status.status != self.server_status.STATUS_STOPPED:
- self.starting_server_step3.emit()
- self.start_server_finished.emit()
- except OSError as e:
- self.starting_server_error.emit(e.strerror)
- return
-
- t = threading.Thread(target=finish_starting_server, kwargs={'self': self})
- t.daemon = True
- t.start()
+ # start_server_step2_custom has call these to move on:
+ # self.starting_server_step3.emit()
+ # self.start_server_finished.emit()
+
+ def start_server_step2_custom(self):
+ """
+ Add custom initialization here.
+ """
+ pass
def start_server_step3(self):
"""
- Step 3 in starting the onionshare server. This displays the large filesize
- warning, if applicable.
+ Step 3 in starting the onionshare server.
"""
- self.common.log('ShareMode', 'start_server_step3')
+ self.common.log('Mode', 'start_server_step3')
- # Remove zip progress bar
- if self._zip_progress_bar is not None:
- self.status_bar.removeWidget(self._zip_progress_bar)
- self._zip_progress_bar = None
-
- # warn about sending large files over Tor
- if self.web.zip_filesize >= 157286400: # 150mb
- self.filesize_warning.setText(strings._("large_filesize", True))
- self.filesize_warning.show()
+ self.start_server_step3_custom()
if self.common.settings.get('shutdown_timeout'):
# Convert the date value to seconds between now and then
@@ -200,21 +178,31 @@ class Mode(QtWidgets.QWidget):
self.stop_server()
self.start_server_error(strings._('gui_server_started_after_timeout'))
+ def start_server_step3_custom(self):
+ """
+ Add custom initialization here.
+ """
+ pass
+
def start_server_error(self, error):
"""
If there's an error when trying to start the onion service
"""
- self.common.log('ShareMode', 'start_server_error')
-
- self.set_share_server_active.emit(False)
+ self.common.log('Mode', 'start_server_error')
Alert(self.common, error, QtWidgets.QMessageBox.Warning)
+ self.set_server_active.emit(False)
self.server_status.stop_server()
- if self._zip_progress_bar is not None:
- self.status_bar.removeWidget(self._zip_progress_bar)
- self._zip_progress_bar = None
self.status_bar.clearMessage()
+ self.start_server_error_custom()
+
+ def start_server_error_custom(self):
+ """
+ Add custom initialization here.
+ """
+ pass
+
def cancel_server(self):
"""
Cancel the server while it is preparing to start
@@ -227,7 +215,7 @@ class Mode(QtWidgets.QWidget):
"""
Stop the onionshare server.
"""
- self.common.log('ShareMode', 'stop_server')
+ self.common.log('Mode', 'stop_server')
if self.server_status.status != self.server_status.STATUS_STOPPED:
try:
@@ -237,81 +225,27 @@ class Mode(QtWidgets.QWidget):
pass
self.app.cleanup()
- # Remove the progress bar
- if self._zip_progress_bar is not None:
- self.status_bar.removeWidget(self._zip_progress_bar)
- self._zip_progress_bar = None
+ self.stop_server_custom()
- self.filesize_warning.hide()
- self.downloads_in_progress = 0
- self.downloads_completed = 0
- self.update_downloads_in_progress(0)
- self.file_selection.file_list.adjustSize()
-
- self.set_share_server_active.emit(False)
+ self.set_server_active.emit(False)
self.stop_server_finished.emit()
+
+ def stop_server_custom(self):
+ """
+ Add custom initialization here.
+ """
+ pass
- @staticmethod
- def _compute_total_size(filenames):
- total_size = 0
- for filename in filenames:
- if os.path.isfile(filename):
- total_size += os.path.getsize(filename)
- if os.path.isdir(filename):
- total_size += Common.dir_size(filename)
- return total_size
-
-
-class ZipProgressBar(QtWidgets.QProgressBar):
- update_processed_size_signal = QtCore.pyqtSignal(int)
-
- def __init__(self, total_files_size):
- super(ZipProgressBar, self).__init__()
- self.setMaximumHeight(20)
- self.setMinimumWidth(200)
- self.setValue(0)
- self.setFormat(strings._('zip_progress_bar_format'))
- cssStyleData ="""
- QProgressBar {
- border: 1px solid #4e064f;
- background-color: #ffffff !important;
- text-align: center;
- color: #9b9b9b;
- }
-
- QProgressBar::chunk {
- border: 0px;
- background-color: #4e064f;
- width: 10px;
- }"""
- self.setStyleSheet(cssStyleData)
-
- self._total_files_size = total_files_size
- self._processed_size = 0
-
- self.update_processed_size_signal.connect(self.update_processed_size)
-
- @property
- def total_files_size(self):
- return self._total_files_size
-
- @total_files_size.setter
- def total_files_size(self, val):
- self._total_files_size = val
-
- @property
- def processed_size(self):
- return self._processed_size
-
- @processed_size.setter
- def processed_size(self, val):
- self.update_processed_size(val)
-
- def update_processed_size(self, val):
- self._processed_size = val
- if self.processed_size < self.total_files_size:
- self.setValue(int((self.processed_size * 100) / self.total_files_size))
- elif self.total_files_size != 0:
- self.setValue(100)
- else:
- self.setValue(0)
+ def handle_tor_broke(self):
+ """
+ Handle connection from Tor breaking.
+ """
+ if self.server_status.status != self.server_status.STATUS_STOPPED:
+ self.server_status.stop_server()
+ self.handle_tor_broke_custom()
+
+ def handle_tor_broke_custom(self):
+ """
+ Add custom initialization here.
+ """
+ pass
diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py
index f976013f..1aa38c1c 100644
--- a/onionshare_gui/onionshare_gui.py
+++ b/onionshare_gui/onionshare_gui.py
@@ -152,12 +152,12 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.setStatusBar(self.status_bar)
# Status bar, sharing messages
- self.server_share_status_label = QtWidgets.QLabel('')
- self.server_share_status_label.setStyleSheet('QLabel { font-style: italic; color: #666666; padding: 2px; }')
- self.status_bar.insertWidget(0, self.server_share_status_label)
+ self.server_status_label = QtWidgets.QLabel('')
+ self.server_status_label.setStyleSheet('QLabel { font-style: italic; color: #666666; padding: 2px; }')
+ self.status_bar.insertWidget(0, self.server_status_label)
# Share and receive mode widgets
- self.share_mode = ShareMode(self.common, qtapp, app, web, self.status_bar, self.server_share_status_label, self.system_tray, filenames)
+ self.share_mode = ShareMode(self.common, qtapp, app, web, self.status_bar, self.server_status_label, self.system_tray, filenames)
self.share_mode.init()
self.share_mode.server_status.server_started.connect(self.update_server_status_indicator)
self.share_mode.server_status.server_stopped.connect(self.update_server_status_indicator)
@@ -168,8 +168,8 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.share_mode.server_status.button_clicked.connect(self.clear_message)
self.share_mode.server_status.url_copied.connect(self.copy_url)
self.share_mode.server_status.hidservauth_copied.connect(self.copy_hidservauth)
- self.share_mode.set_share_server_active.connect(self.set_share_server_active)
- self.receive_mode = ReceiveMode(self.common, qtapp, app, web, self.status_bar, self.server_share_status_label, self.system_tray)
+ self.share_mode.set_server_active.connect(self.set_share_server_active)
+ self.receive_mode = ReceiveMode(self.common, qtapp, app, web, self.status_bar, self.server_status_label, self.system_tray)
self.receive_mode.init()
self.update_mode_switcher()
diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/receive_mode/__init__.py
index b25b728f..b7813170 100644
--- a/onionshare_gui/receive_mode/__init__.py
+++ b/onionshare_gui/receive_mode/__init__.py
@@ -44,3 +44,10 @@ class ReceiveMode(Mode):
This method is called regularly on a timer while receive mode is active.
"""
pass
+
+ def start_server_step2_custom(self):
+ """
+ Step 2 in starting the server. Nothing to do here but move on to step 3.
+ """
+ self.starting_server_step3.emit()
+ self.start_server_finished.emit()
diff --git a/onionshare_gui/server_status.py b/onionshare_gui/server_status.py
index 54f54582..602af595 100644
--- a/onionshare_gui/server_status.py
+++ b/onionshare_gui/server_status.py
@@ -39,22 +39,18 @@ class ServerStatus(QtWidgets.QWidget):
STATUS_WORKING = 1
STATUS_STARTED = 2
- def __init__(self, common, qtapp, app, web, share_mode, file_selection=None):
+ def __init__(self, common, qtapp, app, web, file_selection=None):
super(ServerStatus, self).__init__()
self.common = common
self.status = self.STATUS_STOPPED
+ self.share_mode = False # Gets changed in in self.set_share_mode
self.qtapp = qtapp
self.app = app
self.web = web
- # Only used in share mode
- self.share_mode = share_mode
- if self.share_mode:
- self.file_selection = file_selection
-
# Shutdown timeout layout
self.shutdown_timeout_label = QtWidgets.QLabel(strings._('gui_settings_shutdown_timeout', True))
self.shutdown_timeout = QtWidgets.QDateTimeEdit()
@@ -118,6 +114,13 @@ class ServerStatus(QtWidgets.QWidget):
self.setLayout(layout)
self.update()
+
+ def set_share_mode(self, file_selection):
+ """
+ The server status is in share mode.
+ """
+ self.share_mode = True
+ self.file_selection = file_selection
def shutdown_timeout_reset(self):
"""
diff --git a/onionshare_gui/share_mode/__init__.py b/onionshare_gui/share_mode/__init__.py
index 699e469b..0d05da06 100644
--- a/onionshare_gui/share_mode/__init__.py
+++ b/onionshare_gui/share_mode/__init__.py
@@ -17,10 +17,13 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
+import threading
+import os
from PyQt5 import QtCore, QtWidgets, QtGui
from onionshare import strings
from onionshare.onion import *
+from onionshare.common import Common
from .file_selection import FileSelection
from .downloads import Downloads
@@ -43,6 +46,7 @@ class ShareMode(Mode):
self.file_selection.file_list.add_file(filename)
# Server status
+ self.server_status.set_share_mode(self.file_selection)
self.server_status.server_started.connect(self.file_selection.server_started)
self.server_status.server_stopped.connect(self.file_selection.server_stopped)
self.server_status.server_stopped.connect(self.update_primary_action)
@@ -102,8 +106,8 @@ class ShareMode(Mode):
self._zip_progress_bar = None
# Layout
- self.layout.insertWidget(1, self.info_widget)
self.layout.insertLayout(0, self.file_selection)
+ self.layout.insertWidget(0, self.info_widget)
# Always start with focus on file selection
self.file_selection.setFocus()
@@ -129,18 +133,98 @@ class ShareMode(Mode):
if self.web.download_count == 0 or self.web.done:
self.server_status.stop_server()
self.status_bar.clearMessage()
- self.server_share_status_label.setText(strings._('close_on_timeout', True))
+ self.server_status_label.setText(strings._('close_on_timeout', True))
# A download is probably still running - hold off on stopping the share
else:
self.status_bar.clearMessage()
- self.server_share_status_label.setText(strings._('timeout_download_still_running', True))
+ self.server_status_label.setText(strings._('timeout_download_still_running', True))
- def handle_tor_broke(self):
+ def start_server_custom(self):
"""
- Handle connection from Tor breaking.
+ Starting the server.
+ """
+ # Hide and reset the downloads if we have previously shared
+ self.downloads.reset_downloads()
+ self.reset_info_counters()
+
+ def start_server_step2_custom(self):
+ """
+ Step 2 in starting the server. Zipping up files.
+ """
+ # Add progress bar to the status bar, indicating the compressing of files.
+ self._zip_progress_bar = ZipProgressBar(0)
+ self.filenames = []
+ for index in range(self.file_selection.file_list.count()):
+ self.filenames.append(self.file_selection.file_list.item(index).filename)
+
+ self._zip_progress_bar.total_files_size = ShareMode._compute_total_size(self.filenames)
+ self.status_bar.insertWidget(0, self._zip_progress_bar)
+
+ # Prepare the files for sending in a new thread
+ def finish_starting_server(self):
+ # Prepare files to share
+ def _set_processed_size(x):
+ if self._zip_progress_bar != None:
+ self._zip_progress_bar.update_processed_size_signal.emit(x)
+
+ try:
+ self.web.set_file_info(self.filenames, processed_size_callback=_set_processed_size)
+ self.app.cleanup_filenames.append(self.web.zip_filename)
+
+ # Only continue if the server hasn't been canceled
+ if self.server_status.status != self.server_status.STATUS_STOPPED:
+ self.starting_server_step3.emit()
+ self.start_server_finished.emit()
+ except OSError as e:
+ self.starting_server_error.emit(e.strerror)
+ return
+
+ t = threading.Thread(target=finish_starting_server, kwargs={'self': self})
+ t.daemon = True
+ t.start()
+
+ def start_server_step3_custom(self):
+ """
+ Step 3 in starting the server. Remove zip progess bar, and display large filesize
+ warning, if applicable.
+ """
+ # Remove zip progress bar
+ if self._zip_progress_bar is not None:
+ self.status_bar.removeWidget(self._zip_progress_bar)
+ self._zip_progress_bar = None
+
+ # Warn about sending large files over Tor
+ if self.web.zip_filesize >= 157286400: # 150mb
+ self.filesize_warning.setText(strings._("large_filesize", True))
+ self.filesize_warning.show()
+
+ def start_server_error_custom(self):
+ """
+ Start server error.
+ """
+ if self._zip_progress_bar is not None:
+ self.status_bar.removeWidget(self._zip_progress_bar)
+ self._zip_progress_bar = None
+
+ def stop_server_custom(self):
+ """
+ Stop server.
+ """
+ # Remove the progress bar
+ if self._zip_progress_bar is not None:
+ self.status_bar.removeWidget(self._zip_progress_bar)
+ self._zip_progress_bar = None
+
+ self.filesize_warning.hide()
+ self.downloads_in_progress = 0
+ self.downloads_completed = 0
+ self.update_downloads_in_progress(0)
+ self.file_selection.file_list.adjustSize()
+
+ def handle_tor_broke_custom(self):
+ """
+ Connection to Tor broke.
"""
- if self.server_status.status != self.server_status.STATUS_STOPPED:
- self.server_status.stop_server()
self.primary_action.hide()
self.info_widget.hide()
@@ -190,7 +274,7 @@ class ShareMode(Mode):
if not self.web.stay_open:
self.server_status.stop_server()
self.status_bar.clearMessage()
- self.server_share_status_label.setText(strings._('closing_automatically', True))
+ self.server_status_label.setText(strings._('closing_automatically', True))
else:
if self.server_status.status == self.server_status.STATUS_STOPPED:
self.downloads.cancel_download(event["data"]["id"])
@@ -284,4 +368,69 @@ class ShareMode(Mode):
self.info_in_progress_downloads_image = self.common.get_resource_path('images/download_in_progress.png')
self.info_show_downloads.setIcon(QtGui.QIcon(self.common.get_resource_path('images/download_window_green.png')))
self.info_in_progress_downloads_count.setText(' {1:d}'.format(self.info_in_progress_downloads_image, count))
- self.info_in_progress_downloads_count.setToolTip(strings._('info_in_progress_downloads_tooltip', True).format(count))
\ No newline at end of file
+ self.info_in_progress_downloads_count.setToolTip(strings._('info_in_progress_downloads_tooltip', True).format(count))
+
+ @staticmethod
+ def _compute_total_size(filenames):
+ total_size = 0
+ for filename in filenames:
+ if os.path.isfile(filename):
+ total_size += os.path.getsize(filename)
+ if os.path.isdir(filename):
+ total_size += Common.dir_size(filename)
+ return total_size
+
+
+class ZipProgressBar(QtWidgets.QProgressBar):
+ update_processed_size_signal = QtCore.pyqtSignal(int)
+
+ def __init__(self, total_files_size):
+ super(ZipProgressBar, self).__init__()
+ self.setMaximumHeight(20)
+ self.setMinimumWidth(200)
+ self.setValue(0)
+ self.setFormat(strings._('zip_progress_bar_format'))
+ cssStyleData ="""
+ QProgressBar {
+ border: 1px solid #4e064f;
+ background-color: #ffffff !important;
+ text-align: center;
+ color: #9b9b9b;
+ }
+
+ QProgressBar::chunk {
+ border: 0px;
+ background-color: #4e064f;
+ width: 10px;
+ }"""
+ self.setStyleSheet(cssStyleData)
+
+ self._total_files_size = total_files_size
+ self._processed_size = 0
+
+ self.update_processed_size_signal.connect(self.update_processed_size)
+
+ @property
+ def total_files_size(self):
+ return self._total_files_size
+
+ @total_files_size.setter
+ def total_files_size(self, val):
+ self._total_files_size = val
+
+ @property
+ def processed_size(self):
+ return self._processed_size
+
+ @processed_size.setter
+ def processed_size(self, val):
+ self.update_processed_size(val)
+
+ def update_processed_size(self, val):
+ self._processed_size = val
+ if self.processed_size < self.total_files_size:
+ self.setValue(int((self.processed_size * 100) / self.total_files_size))
+ elif self.total_files_size != 0:
+ self.setValue(100)
+ else:
+ self.setValue(0)