Move the share-related event logic from OnionShareGui.event_callback into ShareMode methods, and other various bugfixes related to the refactor

This commit is contained in:
Micah Lee 2018-04-24 09:21:23 -07:00
parent a232cfdbde
commit 1d7ec585ee
No known key found for this signature in database
GPG Key ID: 403C2657CD994F73
2 changed files with 120 additions and 81 deletions

View File

@ -44,8 +44,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.common = common self.common = common
self.common.log('OnionShareGui', '__init__') self.common.log('OnionShareGui', '__init__')
self._initSystemTray()
self.web = web self.web = web
self.onion = onion self.onion = onion
self.qtapp = qtapp self.qtapp = qtapp
@ -53,7 +51,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.local_only = local_only self.local_only = local_only
self.mode = self.MODE_SHARE self.mode = self.MODE_SHARE
self.new_download = False # For scrolling to the bottom of the downloads list
self.setWindowTitle('OnionShare') self.setWindowTitle('OnionShare')
self.setWindowIcon(QtGui.QIcon(self.common.get_resource_path('images/logo.png'))) self.setWindowIcon(QtGui.QIcon(self.common.get_resource_path('images/logo.png')))
@ -63,6 +60,24 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.config = config self.config = config
self.common.load_settings(self.config) self.common.load_settings(self.config)
# System tray
menu = QtWidgets.QMenu()
self.settings_action = menu.addAction(strings._('gui_settings_window_title', True))
self.settings_action.triggered.connect(self.open_settings)
help_action = menu.addAction(strings._('gui_settings_button_help', True))
help_action.triggered.connect(SettingsDialog.help_clicked)
exit_action = menu.addAction(strings._('systray_menu_exit', True))
exit_action.triggered.connect(self.close)
self.system_tray = QtWidgets.QSystemTrayIcon(self)
# The convention is Mac systray icons are always grayscale
if self.common.platform == 'Darwin':
self.system_tray.setIcon(QtGui.QIcon(self.common.get_resource_path('images/logo_grayscale.png')))
else:
self.system_tray.setIcon(QtGui.QIcon(self.common.get_resource_path('images/logo.png')))
self.system_tray.setContextMenu(menu)
self.system_tray.show()
# Mode switcher, to switch between share files and receive files # Mode switcher, to switch between share files and receive files
self.mode_switcher_selected_style = """ self.mode_switcher_selected_style = """
QPushButton { QPushButton {
@ -141,7 +156,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.status_bar.insertWidget(0, self.server_share_status_label) self.status_bar.insertWidget(0, self.server_share_status_label)
# Share and receive mode widgets # Share and receive mode widgets
self.share_mode = ShareMode(self.common, filenames, qtapp, app, web, self.status_bar, self.server_share_status_label) self.share_mode = ShareMode(self.common, filenames, qtapp, app, web, self.status_bar, self.server_share_status_label, self.system_tray)
self.share_mode.server_status.server_started.connect(self.update_server_status_indicator) 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) self.share_mode.server_status.server_stopped.connect(self.update_server_status_indicator)
self.share_mode.start_server_finished.connect(self.update_server_status_indicator) self.share_mode.start_server_finished.connect(self.update_server_status_indicator)
@ -238,24 +253,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.server_status_image_label.setPixmap(QtGui.QPixmap.fromImage(self.server_status_image_stopped)) self.server_status_image_label.setPixmap(QtGui.QPixmap.fromImage(self.server_status_image_stopped))
self.server_status_label.setText(strings._('gui_status_indicator_stopped', True)) self.server_status_label.setText(strings._('gui_status_indicator_stopped', True))
def _initSystemTray(self):
menu = QtWidgets.QMenu()
self.settingsAction = menu.addAction(strings._('gui_settings_window_title', True))
self.settingsAction.triggered.connect(self.open_settings)
self.helpAction = menu.addAction(strings._('gui_settings_button_help', True))
self.helpAction.triggered.connect(SettingsDialog.help_clicked)
self.exitAction = menu.addAction(strings._('systray_menu_exit', True))
self.exitAction.triggered.connect(self.close)
self.systemTray = QtWidgets.QSystemTrayIcon(self)
# The convention is Mac systray icons are always grayscale
if self.common.platform == 'Darwin':
self.systemTray.setIcon(QtGui.QIcon(self.common.get_resource_path('images/logo_grayscale.png')))
else:
self.systemTray.setIcon(QtGui.QIcon(self.common.get_resource_path('images/logo.png')))
self.systemTray.setContextMenu(menu)
self.systemTray.show()
def stop_server_finished(self): def stop_server_finished(self):
# When the server stopped, cleanup the ephemeral onion service # When the server stopped, cleanup the ephemeral onion service
self.onion.cleanup(stop_tor=False) self.onion.cleanup(stop_tor=False)
@ -309,6 +306,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
def reload_settings(): def reload_settings():
self.common.log('OnionShareGui', 'open_settings', 'settings have changed, reloading') self.common.log('OnionShareGui', 'open_settings', 'settings have changed, reloading')
self.common.settings.load() self.common.settings.load()
# We might've stopped the main requests timer if a Tor connection failed. # We might've stopped the main requests timer if a Tor connection failed.
# If we've reloaded settings, we probably succeeded in obtaining a new # If we've reloaded settings, we probably succeeded in obtaining a new
# connection. If so, restart the timer. # connection. If so, restart the timer.
@ -322,16 +320,17 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.primary_action.show() self.primary_action.show()
self.info_widget.show() self.info_widget.show()
self.status_bar.clearMessage() self.status_bar.clearMessage()
# If we switched off the shutdown timeout setting, ensure the widget is hidden. # If we switched off the shutdown timeout setting, ensure the widget is hidden.
if not self.common.settings.get('shutdown_timeout'): if not self.common.settings.get('shutdown_timeout'):
self.server_status.shutdown_timeout_container.hide() self.share_mode.server_status.shutdown_timeout_container.hide()
d = SettingsDialog(self.common, self.onion, self.qtapp, self.config, self.local_only) d = SettingsDialog(self.common, self.onion, self.qtapp, self.config, self.local_only)
d.settings_saved.connect(reload_settings) d.settings_saved.connect(reload_settings)
d.exec_() d.exec_()
# When settings close, refresh the server status UI # When settings close, refresh the server status UI
self.server_status.update() self.share_mode.server_status.update()
def check_for_updates(self): def check_for_updates(self):
""" """
@ -357,19 +356,11 @@ class OnionShareGui(QtWidgets.QMainWindow):
# Have we lost connection to Tor somehow? # Have we lost connection to Tor somehow?
if not self.onion.is_authenticated(): if not self.onion.is_authenticated():
self.timer.stop() self.timer.stop()
if self.server_status.status != self.server_status.STATUS_STOPPED:
self.server_status.stop_server()
self.primary_action.hide()
self.info_widget.hide()
self.status_bar.showMessage(strings._('gui_tor_connection_lost', True)) self.status_bar.showMessage(strings._('gui_tor_connection_lost', True))
if self.systemTray.supportsMessages() and self.settings.get('systray_notifications'): if self.system_tray.supportsMessages() and self.settings.get('systray_notifications'):
self.systemTray.showMessage(strings._('gui_tor_connection_lost', True), strings._('gui_tor_connection_error_settings', True)) self.system_tray.showMessage(strings._('gui_tor_connection_lost', True), strings._('gui_tor_connection_error_settings', True))
# scroll to the bottom of the dl progress bar log pane self.share_mode.handle_tor_broke()
# if a new download has been added
if self.new_download:
self.share_mode.downloads.downloads_container.vbar.setValue(self.downloads.downloads_container.vbar.maximum())
self.new_download = False
events = [] events = []
@ -383,54 +374,19 @@ class OnionShareGui(QtWidgets.QMainWindow):
for event in events: for event in events:
if event["type"] == self.web.REQUEST_LOAD: if event["type"] == self.web.REQUEST_LOAD:
self.status_bar.showMessage(strings._('download_page_loaded', True)) self.share_mode.handle_request_load(event)
elif event["type"] == self.web.REQUEST_DOWNLOAD: elif event["type"] == self.web.REQUEST_DOWNLOAD:
self.downloads.no_downloads_label.hide() self.share_mode.handle_request_download(event)
self.downloads.add_download(event["data"]["id"], web.zip_filesize)
self.new_download = True
self.downloads_in_progress += 1
self.update_downloads_in_progress(self.downloads_in_progress)
if self.systemTray.supportsMessages() and self.common.settings.get('systray_notifications'):
self.systemTray.showMessage(strings._('systray_download_started_title', True), strings._('systray_download_started_message', True))
elif event["type"] == self.web.REQUEST_RATE_LIMIT: elif event["type"] == self.web.REQUEST_RATE_LIMIT:
self.stop_server() self.share_mode.handle_request_rate_limit(event)
Alert(self.common, strings._('error_rate_limit'), QtWidgets.QMessageBox.Critical)
elif event["type"] == self.web.REQUEST_PROGRESS: elif event["type"] == self.web.REQUEST_PROGRESS:
self.downloads.update_download(event["data"]["id"], event["data"]["bytes"]) self.share_mode.handle_request_progress(event)
# is the download complete?
if event["data"]["bytes"] == self.web.zip_filesize:
if self.systemTray.supportsMessages() and self.common.settings.get('systray_notifications'):
self.systemTray.showMessage(strings._('systray_download_completed_title', True), strings._('systray_download_completed_message', True))
# Update the total 'completed downloads' info
self.downloads_completed += 1
self.update_downloads_completed(self.downloads_completed)
# Update the 'in progress downloads' info
self.downloads_in_progress -= 1
self.update_downloads_in_progress(self.downloads_in_progress)
# close on finish?
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))
else:
if self.server_status.status == self.server_status.STATUS_STOPPED:
self.downloads.cancel_download(event["data"]["id"])
self.downloads_in_progress = 0
self.update_downloads_in_progress(self.downloads_in_progress)
elif event["type"] == self.web.REQUEST_CANCELED: elif event["type"] == self.web.REQUEST_CANCELED:
self.downloads.cancel_download(event["data"]["id"]) self.share_mode.handle_request_canceled(event)
# Update the 'in progress downloads' info
self.downloads_in_progress -= 1
self.update_downloads_in_progress(self.downloads_in_progress)
if self.systemTray.supportsMessages() and self.common.settings.get('systray_notifications'):
self.systemTray.showMessage(strings._('systray_download_canceled_title', True), strings._('systray_download_canceled_message', True))
elif event["path"] != '/favicon.ico': elif event["path"] != '/favicon.ico':
self.status_bar.showMessage('[#{0:d}] {1:s}: {2:s}'.format(self.web.error404_count, strings._('other_page_loaded', True), event["path"])) self.status_bar.showMessage('[#{0:d}] {1:s}: {2:s}'.format(self.web.error404_count, strings._('other_page_loaded', True), event["path"]))
@ -445,16 +401,16 @@ class OnionShareGui(QtWidgets.QMainWindow):
When the URL gets copied to the clipboard, display this in the status bar. When the URL gets copied to the clipboard, display this in the status bar.
""" """
self.common.log('OnionShareGui', 'copy_url') self.common.log('OnionShareGui', 'copy_url')
if self.systemTray.supportsMessages() and self.common.settings.get('systray_notifications'): if self.system_tray.supportsMessages() and self.common.settings.get('systray_notifications'):
self.systemTray.showMessage(strings._('gui_copied_url_title', True), strings._('gui_copied_url', True)) self.system_tray.showMessage(strings._('gui_copied_url_title', True), strings._('gui_copied_url', True))
def copy_hidservauth(self): def copy_hidservauth(self):
""" """
When the stealth onion service HidServAuth gets copied to the clipboard, display this in the status bar. When the stealth onion service HidServAuth gets copied to the clipboard, display this in the status bar.
""" """
self.common.log('OnionShareGui', 'copy_hidservauth') self.common.log('OnionShareGui', 'copy_hidservauth')
if self.systemTray.supportsMessages() and self.common.settings.get('systray_notifications'): if self.system_tray.supportsMessages() and self.common.settings.get('systray_notifications'):
self.systemTray.showMessage(strings._('gui_copied_hidservauth_title', True), strings._('gui_copied_hidservauth', True)) self.system_tray.showMessage(strings._('gui_copied_hidservauth_title', True), strings._('gui_copied_hidservauth', True))
def clear_message(self): def clear_message(self):
""" """
@ -476,7 +432,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.receive_mode_button.show() self.receive_mode_button.show()
# Disable settings menu action when server is active # Disable settings menu action when server is active
self.settingsAction.setEnabled(not active) self.settings_action.setEnabled(not active)
def closeEvent(self, e): def closeEvent(self, e):
self.common.log('OnionShareGui', 'closeEvent') self.common.log('OnionShareGui', 'closeEvent')

View File

@ -30,6 +30,7 @@ from .file_selection import FileSelection
from .server_status import ServerStatus from .server_status import ServerStatus
from .downloads import Downloads from .downloads import Downloads
from .onion_thread import OnionThread from .onion_thread import OnionThread
from .alert import Alert
class ShareMode(QtWidgets.QWidget): class ShareMode(QtWidgets.QWidget):
@ -43,7 +44,7 @@ class ShareMode(QtWidgets.QWidget):
starting_server_error = QtCore.pyqtSignal(str) starting_server_error = QtCore.pyqtSignal(str)
set_share_server_active = QtCore.pyqtSignal(bool) set_share_server_active = QtCore.pyqtSignal(bool)
def __init__(self, common, filenames, qtapp, app, web, status_bar, server_share_status_label): def __init__(self, common, filenames, qtapp, app, web, status_bar, server_share_status_label, system_tray):
super(ShareMode, self).__init__() super(ShareMode, self).__init__()
self.common = common self.common = common
self.qtapp = qtapp self.qtapp = qtapp
@ -52,6 +53,7 @@ class ShareMode(QtWidgets.QWidget):
self.status_bar = status_bar self.status_bar = status_bar
self.server_share_status_label = server_share_status_label self.server_share_status_label = server_share_status_label
self.system_tray = system_tray
# File selection # File selection
self.file_selection = FileSelection(self.common) self.file_selection = FileSelection(self.common)
@ -87,6 +89,7 @@ class ShareMode(QtWidgets.QWidget):
self.downloads = Downloads(self.common) self.downloads = Downloads(self.common)
self.downloads_in_progress = 0 self.downloads_in_progress = 0
self.downloads_completed = 0 self.downloads_completed = 0
self.new_download = False # For scrolling to the bottom of the downloads list
# Info label along top of screen # Info label along top of screen
self.info_layout = QtWidgets.QHBoxLayout() self.info_layout = QtWidgets.QHBoxLayout()
@ -144,6 +147,11 @@ class ShareMode(QtWidgets.QWidget):
""" """
This method is called regularly on a timer while share mode is active. This method is called regularly on a timer while share mode is active.
""" """
# Scroll to the bottom of the download progress bar log pane if a new download has been added
if self.new_download:
self.downloads.downloads_container.vbar.setValue(self.downloads.downloads_container.vbar.maximum())
self.new_download = False
# If the auto-shutdown timer has stopped, stop the server # If the auto-shutdown timer has stopped, stop the server
if self.server_status.status == self.server_status.STATUS_STARTED: if self.server_status.status == self.server_status.STATUS_STARTED:
if self.app.shutdown_timer and self.common.settings.get('shutdown_timeout'): if self.app.shutdown_timer and self.common.settings.get('shutdown_timeout'):
@ -162,6 +170,81 @@ class ShareMode(QtWidgets.QWidget):
self.status_bar.clearMessage() self.status_bar.clearMessage()
self.server_share_status_label.setText(strings._('timeout_download_still_running', True)) self.server_share_status_label.setText(strings._('timeout_download_still_running', True))
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.primary_action.hide()
self.info_widget.hide()
def handle_request_load(self, event):
"""
Handle REQUEST_LOAD event.
"""
self.status_bar.showMessage(strings._('download_page_loaded', True))
def handle_request_download(self, event):
"""
Handle REQUEST_DOWNLOAD event.
"""
self.downloads.no_downloads_label.hide()
self.downloads.add_download(event["data"]["id"], self.web.zip_filesize)
self.new_download = True
self.downloads_in_progress += 1
self.update_downloads_in_progress(self.downloads_in_progress)
if self.system_tray.supportsMessages() and self.common.settings.get('systray_notifications'):
self.system_tray.showMessage(strings._('systray_download_started_title', True), strings._('systray_download_started_message', True))
def handle_request_rate_limit(self, event):
"""
Handle REQUEST_RATE_LIMIT event.
"""
self.stop_server()
Alert(self.common, strings._('error_rate_limit'), QtWidgets.QMessageBox.Critical)
def handle_request_progress(self, event):
"""
Handle REQUEST_PROGRESS event.
"""
self.downloads.update_download(event["data"]["id"], event["data"]["bytes"])
# Is the download complete?
if event["data"]["bytes"] == self.web.zip_filesize:
if self.system_tray.supportsMessages() and self.common.settings.get('systray_notifications'):
self.system_tray.showMessage(strings._('systray_download_completed_title', True), strings._('systray_download_completed_message', True))
# Update the total 'completed downloads' info
self.downloads_completed += 1
self.update_downloads_completed(self.downloads_completed)
# Update the 'in progress downloads' info
self.downloads_in_progress -= 1
self.update_downloads_in_progress(self.downloads_in_progress)
# close on finish?
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))
else:
if self.server_status.status == self.server_status.STATUS_STOPPED:
self.downloads.cancel_download(event["data"]["id"])
self.downloads_in_progress = 0
self.update_downloads_in_progress(self.downloads_in_progress)
def handle_request_canceled(self, event):
"""
Handle REQUEST_CANCELED event.
"""
self.downloads.cancel_download(event["data"]["id"])
# Update the 'in progress downloads' info
self.downloads_in_progress -= 1
self.update_downloads_in_progress(self.downloads_in_progress)
if self.system_tray.supportsMessages() and self.common.settings.get('systray_notifications'):
self.system_tray.showMessage(strings._('systray_download_canceled_title', True), strings._('systray_download_canceled_message', True))
def update_primary_action(self): def update_primary_action(self):
# Show or hide primary action layout # Show or hide primary action layout
file_count = self.file_selection.file_list.count() file_count = self.file_selection.file_list.count()