From fc1902c1ee768e6573324d1ad0cfb8d086c432cd Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 12:51:30 -0700 Subject: [PATCH 01/50] Refactor how Mode layouts work, so the downstream Mode has more control over the UI --- onionshare_gui/mode.py | 19 ++++++------------- onionshare_gui/receive_mode/__init__.py | 16 ++++++++++++---- onionshare_gui/share_mode/__init__.py | 14 +++++++++++--- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/onionshare_gui/mode.py b/onionshare_gui/mode.py index 6b156f7e..d91b2e64 100644 --- a/onionshare_gui/mode.py +++ b/onionshare_gui/mode.py @@ -72,24 +72,17 @@ class Mode(QtWidgets.QWidget): self.starting_server_step3.connect(self.start_server_step3) self.starting_server_error.connect(self.start_server_error) - # Primary action layout + # Primary action + # Note: It's up to the downstream Mode to add this to its layout self.primary_action_layout = QtWidgets.QVBoxLayout() self.primary_action_layout.addWidget(self.server_status) self.primary_action = QtWidgets.QWidget() self.primary_action.setLayout(self.primary_action_layout) - # Layout - self.layout = QtWidgets.QVBoxLayout() - self.layout.addWidget(self.primary_action) - # Hack to allow a minimum width on self.layout - min_width_widget = QtWidgets.QWidget() - min_width_widget.setMinimumWidth(450) - self.layout.addWidget(min_width_widget) - - self.horizontal_layout_wrapper = QtWidgets.QHBoxLayout() - self.horizontal_layout_wrapper.addLayout(self.layout) - - self.setLayout(self.horizontal_layout_wrapper) + # Hack to allow a minimum width on the main layout + # Note: It's up to the downstream Mode to add this to its layout + self.min_width_widget = QtWidgets.QWidget() + self.min_width_widget.setMinimumWidth(450) def init(self): """ diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/receive_mode/__init__.py index 590dec65..f2a82e54 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/receive_mode/__init__.py @@ -76,11 +76,19 @@ class ReceiveMode(Mode): self.receive_info.setMinimumHeight(80) self.receive_info.setWordWrap(True) + # Main layout + self.main_layout = QtWidgets.QVBoxLayout() + self.main_layout.addWidget(self.info_widget) + self.main_layout.addWidget(self.receive_info) + self.main_layout.addWidget(self.primary_action) + self.main_layout.addStretch() + self.main_layout.addWidget(self.min_width_widget) + # Layout - self.layout.insertWidget(0, self.receive_info) - self.layout.insertWidget(0, self.info_widget) - self.layout.addStretch() - self.horizontal_layout_wrapper.addWidget(self.uploads) + self.layout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.main_layout) + self.layout.addWidget(self.uploads) + self.setLayout(self.layout) def get_stop_server_shutdown_timeout_text(self): """ diff --git a/onionshare_gui/share_mode/__init__.py b/onionshare_gui/share_mode/__init__.py index 90fce49a..8a937f1d 100644 --- a/onionshare_gui/share_mode/__init__.py +++ b/onionshare_gui/share_mode/__init__.py @@ -106,10 +106,18 @@ class ShareMode(Mode): # Status bar, zip progress bar self._zip_progress_bar = None + # Main layout + self.main_layout = QtWidgets.QVBoxLayout() + self.main_layout.addWidget(self.info_widget) + self.main_layout.addLayout(self.file_selection) + self.main_layout.addWidget(self.primary_action) + self.main_layout.addWidget(self.min_width_widget) + # Layout - self.layout.insertLayout(0, self.file_selection) - self.layout.insertWidget(0, self.info_widget) - self.horizontal_layout_wrapper.addWidget(self.downloads) + self.layout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.main_layout) + self.layout.addWidget(self.downloads) + self.setLayout(self.layout) # Always start with focus on file selection self.file_selection.setFocus() From ddcbed451c2697e8b39ad7baf47c1518dd32b5d5 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 13:18:18 -0700 Subject: [PATCH 02/50] Hide the uploads and downloads by default, and make the mode switcher hide before showing, to prevent weird window resizing --- onionshare_gui/onionshare_gui.py | 3 +-- onionshare_gui/receive_mode/__init__.py | 1 + onionshare_gui/share_mode/__init__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 83f3a7e0..79565edd 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -55,7 +55,6 @@ class OnionShareGui(QtWidgets.QMainWindow): self.setWindowTitle('OnionShare') self.setWindowIcon(QtGui.QIcon(self.common.get_resource_path('images/logo.png'))) - self.setMinimumWidth(850) # Load settings self.config = config @@ -194,8 +193,8 @@ class OnionShareGui(QtWidgets.QMainWindow): self.share_mode_button.setStyleSheet(self.common.css['mode_switcher_selected_style']) self.receive_mode_button.setStyleSheet(self.common.css['mode_switcher_unselected_style']) - self.share_mode.show() self.receive_mode.hide() + self.share_mode.show() else: self.share_mode_button.setStyleSheet(self.common.css['mode_switcher_unselected_style']) self.receive_mode_button.setStyleSheet(self.common.css['mode_switcher_selected_style']) diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/receive_mode/__init__.py index f2a82e54..80bd9cad 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/receive_mode/__init__.py @@ -48,6 +48,7 @@ class ReceiveMode(Mode): # Uploads self.uploads = Uploads(self.common) + self.uploads.hide() self.uploads_in_progress = 0 self.uploads_completed = 0 self.new_upload = False # For scrolling to the bottom of the uploads list diff --git a/onionshare_gui/share_mode/__init__.py b/onionshare_gui/share_mode/__init__.py index 8a937f1d..c097d75a 100644 --- a/onionshare_gui/share_mode/__init__.py +++ b/onionshare_gui/share_mode/__init__.py @@ -72,6 +72,7 @@ class ShareMode(Mode): # Downloads self.downloads = Downloads(self.common) + self.downloads.hide() self.downloads_in_progress = 0 self.downloads_completed = 0 @@ -96,7 +97,6 @@ class ShareMode(Mode): self.info_widget = QtWidgets.QWidget() self.info_widget.setLayout(self.info_layout) - self.info_widget.hide() # Primary action layout self.primary_action_layout.addWidget(self.filesize_warning) From edbbe9377cac09d1c6063e23a09f68d925fa6acd Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 13:24:44 -0700 Subject: [PATCH 03/50] Add a toggle downloads button to share mode, and add new toggle upload and download images --- onionshare_gui/share_mode/__init__.py | 15 +++++++++++++++ share/images/downloads_toggle.png | Bin 0 -> 380 bytes share/images/downloads_toggle_selected.png | Bin 0 -> 468 bytes share/images/uploads_toggle.png | Bin 0 -> 389 bytes share/images/uploads_toggle_selected.png | Bin 0 -> 473 bytes 5 files changed, 15 insertions(+) create mode 100644 share/images/downloads_toggle.png create mode 100644 share/images/downloads_toggle_selected.png create mode 100644 share/images/uploads_toggle.png create mode 100644 share/images/uploads_toggle_selected.png diff --git a/onionshare_gui/share_mode/__init__.py b/onionshare_gui/share_mode/__init__.py index c097d75a..7e444137 100644 --- a/onionshare_gui/share_mode/__init__.py +++ b/onionshare_gui/share_mode/__init__.py @@ -89,11 +89,20 @@ class ShareMode(Mode): self.update_downloads_completed() self.update_downloads_in_progress() + self.info_toggle_button = QtWidgets.QPushButton() + self.info_toggle_button.setDefault(False) + self.info_toggle_button.setFixedWidth(30) + self.info_toggle_button.setFixedHeight(30) + self.info_toggle_button.setFlat(True) + self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle.png')) ) + self.info_toggle_button.clicked.connect(self.toggle_downloads) + self.info_layout = QtWidgets.QHBoxLayout() self.info_layout.addWidget(self.info_label) self.info_layout.addStretch() self.info_layout.addWidget(self.info_in_progress_downloads_count) self.info_layout.addWidget(self.info_completed_downloads_count) + self.info_layout.addWidget(self.info_toggle_button) self.info_widget = QtWidgets.QWidget() self.info_widget.setLayout(self.info_layout) @@ -353,6 +362,12 @@ class ShareMode(Mode): self.info_in_progress_downloads_count.setText(' {1:d}'.format(image, self.downloads_in_progress)) self.info_in_progress_downloads_count.setToolTip(strings._('info_in_progress_downloads_tooltip', True).format(self.downloads_in_progress)) + def toggle_downloads(self): + """ + Toggle showing and hiding the Downloads widget + """ + pass + @staticmethod def _compute_total_size(filenames): total_size = 0 diff --git a/share/images/downloads_toggle.png b/share/images/downloads_toggle.png new file mode 100644 index 0000000000000000000000000000000000000000..846ececb367e96250c0f48218be55aba4a76b1a1 GIT binary patch literal 380 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPdr;G@g6&%$AH35qVFC(D|_}@I;7oC^gF*}4f}GxzNVDIkBl-}8P}UM9tkP>Ccm={ zp7egs;qUqZ4NE323GCb)BE)Q3@L*2#$9w(7d-4wc`8)r!%rtJc`3L+>IMv zCQrGYDRDJ;$Ghi8irFUlHEvh=cfC1N%VcwV3D@<+$NQq*T@Je(pV4a3{Mm=I_Xlga XzWd9M4j1nN!->Ju)z4*}Q$iB}!flz# literal 0 HcmV?d00001 diff --git a/share/images/downloads_toggle_selected.png b/share/images/downloads_toggle_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..127ce20806c715eaecbfce44f6a5907f5c769abc GIT binary patch literal 468 zcmV;_0W1EAP)!ax{?-(K5mfWe8FsFPvnLZ}hLPatt~Xq(QCCj1c=V)QQnmVwRxU?{|B zNE{548X^G(Bcyj}&p{ywrSx6y%Xi=V*D08|`Z`>#Ma%Yg7 zl4HzXXI;Sr0RV|gVLF#SZ9Fs{6DQFrImUc2_W&SuoGM0{{{d{nzLsQZuzD#1arl?S z_jO~l+pGbAvS|2k{uKy95Qv0%s>Me+p_VVuj4O6IuqBWH0000< KMNUMnLSTX_O~}&# literal 0 HcmV?d00001 diff --git a/share/images/uploads_toggle.png b/share/images/uploads_toggle.png new file mode 100644 index 0000000000000000000000000000000000000000..87303c9ffb4b08be932a0f38109ab8559b8ed668 GIT binary patch literal 389 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPdr;G@%@Twi_92giFg*;sxLo81BPEz!CaTGXS|K7&p zf=X6^-m1WsgGrlyFdj+TZ5Fxl#M0G=I@Jzu`OUzdcG=Z&Tf`Pg(+YV9maRRT_H6%s z@Ave(bAO)CFHhgDpd1>@E?2uVJuP1|J}~$X%bKbe%r`t8#e|L?KcKsT^G`(ur-i`8 zN{)w?+yPgEA28iuh-*xJAYH-u>%hK_5@!y6(S}uVjP3`-3)s&zIQz$2ZQy^?b)t;p zq1*yt*#rh1CShZ1{rI!V!ryuRJu*z-;yL?9?Yq%D>0R5IBxc^6!nQL#gz?EeOXi>7 z%d%_sW;Dm0yRwpTP3p6^OIIa_%3iPRI#I*4XZj~?yK};|Gp1G-@Yeit&sw~8ncSA3 gnx@T1M5VrR%L@9=OnY-s8W>;zopr0Bru3NdN!< literal 0 HcmV?d00001 diff --git a/share/images/uploads_toggle_selected.png b/share/images/uploads_toggle_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..0ba52cffb17cc54bd2870e13b946544be6326818 GIT binary patch literal 473 zcmV;~0Ve*5P)u`GL1Cu-RzAm`=b`fGgw0I|c^3t{Aa^|rbNfcRP^Fp1dWicnVScd6-ffTEC z$K5)1pgZo?S&G$s0%3a&f}2Z2Sq`MY|E@dO?%w9vp#Q%h=jDN%mj_WC;<~^V5y;fz z;s^kUKt8;Mol&O=0I^NLm>GAVa6rNLG}w$D;-1(#kdCE$Zwrz5{C$1^GdYWv3kMYo P00000NkvXXu0mjf=2^q% literal 0 HcmV?d00001 From 4bec79f4944e1222d2f79c7a11668a80da497872 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 13:43:10 -0700 Subject: [PATCH 04/50] Toggle showing uploads and downloads for both share and receive modes --- onionshare_gui/mode.py | 1 + onionshare_gui/onionshare_gui.py | 7 +++++++ onionshare_gui/receive_mode/__init__.py | 28 ++++++++++++++++++++++++- onionshare_gui/share_mode/__init__.py | 19 ++++++++++++++--- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/onionshare_gui/mode.py b/onionshare_gui/mode.py index d91b2e64..6da83318 100644 --- a/onionshare_gui/mode.py +++ b/onionshare_gui/mode.py @@ -36,6 +36,7 @@ class Mode(QtWidgets.QWidget): starting_server_step3 = QtCore.pyqtSignal() starting_server_error = QtCore.pyqtSignal(str) set_server_active = QtCore.pyqtSignal(bool) + adjust_size = QtCore.pyqtSignal() def __init__(self, common, qtapp, app, status_bar, server_status_label, system_tray, filenames=None, local_only=False): super(Mode, self).__init__() diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 79565edd..a95b75c9 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -132,6 +132,7 @@ class OnionShareGui(QtWidgets.QMainWindow): 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_server_active.connect(self.set_server_active) + self.share_mode.adjust_size.connect(self.adjust_size) # Receive mode self.receive_mode = ReceiveMode(self.common, qtapp, app, self.status_bar, self.server_status_label, self.system_tray, None, self.local_only) @@ -146,6 +147,7 @@ class OnionShareGui(QtWidgets.QMainWindow): self.receive_mode.server_status.url_copied.connect(self.copy_url) self.receive_mode.server_status.hidservauth_copied.connect(self.copy_hidservauth) self.receive_mode.set_server_active.connect(self.set_server_active) + self.receive_mode.adjust_size.connect(self.adjust_size) self.update_mode_switcher() self.update_server_status_indicator() @@ -442,6 +444,11 @@ class OnionShareGui(QtWidgets.QMainWindow): # Disable settings menu action when server is active self.settings_action.setEnabled(not active) + def adjust_size(self): + self.share_mode.adjustSize() + self.receive_mode.adjustSize() + self.adjustSize() + def closeEvent(self, e): self.common.log('OnionShareGui', 'closeEvent') try: diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/receive_mode/__init__.py index 80bd9cad..efad618a 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/receive_mode/__init__.py @@ -63,10 +63,19 @@ class ReceiveMode(Mode): self.update_uploads_completed() self.update_uploads_in_progress() + self.info_toggle_button = QtWidgets.QPushButton() + self.info_toggle_button.setDefault(False) + self.info_toggle_button.setFixedWidth(30) + self.info_toggle_button.setFixedHeight(30) + self.info_toggle_button.setFlat(True) + self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle.png')) ) + self.info_toggle_button.clicked.connect(self.toggle_uploads) + self.info_layout = QtWidgets.QHBoxLayout() self.info_layout.addStretch() self.info_layout.addWidget(self.info_in_progress_uploads_count) self.info_layout.addWidget(self.info_completed_uploads_count) + self.info_layout.addWidget(self.info_toggle_button) self.info_widget = QtWidgets.QWidget() self.info_widget.setLayout(self.info_layout) @@ -226,4 +235,21 @@ class ReceiveMode(Mode): self.info_widget.hide() # Resize window - self.adjustSize() + self.adjust_size.emit() + + def toggle_uploads(self): + """ + Toggle showing and hiding the Uploads widget + """ + self.common.log('ReceiveMode', 'toggle_uploads') + + if self.uploads.isVisible(): + self.uploads.hide() + self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle.png')) ) + self.info_toggle_button.setFlat(True) + else: + self.uploads.show() + self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle_selected.png')) ) + self.info_toggle_button.setFlat(False) + + self.adjust_size.emit() diff --git a/onionshare_gui/share_mode/__init__.py b/onionshare_gui/share_mode/__init__.py index 7e444137..cf33e8b1 100644 --- a/onionshare_gui/share_mode/__init__.py +++ b/onionshare_gui/share_mode/__init__.py @@ -226,7 +226,7 @@ class ShareMode(Mode): Stop the compression thread on cancel """ if self.compress_thread: - self.common.log('OnionShareGui', 'cancel_server: quitting compress thread') + self.common.log('ShareMode', 'cancel_server: quitting compress thread') self.compress_thread.quit() def handle_tor_broke_custom(self): @@ -305,6 +305,8 @@ class ShareMode(Mode): self.info_widget.show() def update_primary_action(self): + self.common.log('ShareMode', 'update_primary_action') + # Show or hide primary action layout file_count = self.file_selection.file_list.count() if file_count > 0: @@ -328,7 +330,7 @@ class ShareMode(Mode): self.info_widget.hide() # Resize window - self.adjustSize() + self.adjust_size.emit() def reset_info_counters(self): """ @@ -366,7 +368,18 @@ class ShareMode(Mode): """ Toggle showing and hiding the Downloads widget """ - pass + self.common.log('ShareMode', 'toggle_downloads') + + if self.downloads.isVisible(): + self.downloads.hide() + self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle.png')) ) + self.info_toggle_button.setFlat(True) + else: + self.downloads.show() + self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle_selected.png')) ) + self.info_toggle_button.setFlat(False) + + self.adjust_size.emit() @staticmethod def _compute_total_size(filenames): From e29bb99f16f69be68dbee1667400a3a99451bd56 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 15:05:43 -0700 Subject: [PATCH 05/50] OnionShareGui.adjust_size now recursively runs adjustSize() on all widgets --- onionshare_gui/onionshare_gui.py | 31 +++++++++++++++++++++++-- onionshare_gui/receive_mode/__init__.py | 10 ++++---- onionshare_gui/share_mode/__init__.py | 10 ++++---- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index a95b75c9..5469c57c 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -445,8 +445,35 @@ class OnionShareGui(QtWidgets.QMainWindow): self.settings_action.setEnabled(not active) def adjust_size(self): - self.share_mode.adjustSize() - self.receive_mode.adjustSize() + """ + Recursively adjust size on all widgets + """ + # Recursively adjust sizes for the modes + def adjust_size_layout(layout): + count = layout.count() + for i in range(count): + item = layout.itemAt(i) + if item: + child_widget = item.widget() + if child_widget: + adjust_size_widget(child_widget) + child_layout = item.layout() + if child_layout: + adjust_size_layout(child_layout) + + def adjust_size_widget(widget): + layout = widget.layout() + if layout: + adjust_size_layout(layout) + # Processing Qt events before adjusting size makes each .adjustSize() actually count + self.qtapp.processEvents() + widget.adjustSize() + + # Adjust sizes of each mode + for mode in [self.share_mode, self.receive_mode]: + adjust_size_widget(mode) + + # Adjust window size self.adjustSize() def closeEvent(self, e): diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/receive_mode/__init__.py index efad618a..dab37ef2 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/receive_mode/__init__.py @@ -94,11 +94,11 @@ class ReceiveMode(Mode): self.main_layout.addStretch() self.main_layout.addWidget(self.min_width_widget) - # Layout - self.layout = QtWidgets.QHBoxLayout() - self.layout.addLayout(self.main_layout) - self.layout.addWidget(self.uploads) - self.setLayout(self.layout) + # Wrapper layout + self.wrapper_layout = QtWidgets.QHBoxLayout() + self.wrapper_layout.addLayout(self.main_layout) + self.wrapper_layout.addWidget(self.uploads) + self.setLayout(self.wrapper_layout) def get_stop_server_shutdown_timeout_text(self): """ diff --git a/onionshare_gui/share_mode/__init__.py b/onionshare_gui/share_mode/__init__.py index cf33e8b1..c0cb6d39 100644 --- a/onionshare_gui/share_mode/__init__.py +++ b/onionshare_gui/share_mode/__init__.py @@ -122,11 +122,11 @@ class ShareMode(Mode): self.main_layout.addWidget(self.primary_action) self.main_layout.addWidget(self.min_width_widget) - # Layout - self.layout = QtWidgets.QHBoxLayout() - self.layout.addLayout(self.main_layout) - self.layout.addWidget(self.downloads) - self.setLayout(self.layout) + # Wrapper layout + self.wrapper_layout = QtWidgets.QHBoxLayout() + self.wrapper_layout.addLayout(self.main_layout) + self.wrapper_layout.addWidget(self.downloads) + self.setLayout(self.wrapper_layout) # Always start with focus on file selection self.file_selection.setFocus() From cddc8c06d4ebfbec16479f2945343b36c6386ed9 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 15:30:37 -0700 Subject: [PATCH 06/50] Modes now get to choose a new minimum window width when resizing --- onionshare_gui/mode.py | 21 ++++++++++++++++++++- onionshare_gui/onionshare_gui.py | 14 ++++++++++---- onionshare_gui/receive_mode/__init__.py | 10 ++++++++-- onionshare_gui/share_mode/__init__.py | 10 ++++++++-- 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/onionshare_gui/mode.py b/onionshare_gui/mode.py index 6da83318..bd247568 100644 --- a/onionshare_gui/mode.py +++ b/onionshare_gui/mode.py @@ -36,7 +36,7 @@ class Mode(QtWidgets.QWidget): starting_server_step3 = QtCore.pyqtSignal() starting_server_error = QtCore.pyqtSignal(str) set_server_active = QtCore.pyqtSignal(bool) - adjust_size = QtCore.pyqtSignal() + adjust_size = QtCore.pyqtSignal(int) def __init__(self, common, qtapp, app, status_bar, server_status_label, system_tray, filenames=None, local_only=False): super(Mode, self).__init__() @@ -332,3 +332,22 @@ class Mode(QtWidgets.QWidget): Handle REQUEST_UPLOAD_FINISHED event. """ pass + + def resize_window(self): + """ + We call this to force the OnionShare window to resize itself to be smaller. + For this to do anything, the Mode needs to override it and call: + + self.adjust_size.emit(min_width) + + It can calculate min_width (the new minimum window width) based on what + widgets are visible. + """ + pass + + def show(self): + """ + Always resize the window after showing this Mode widget. + """ + super(Mode, self).show() + self.resize_window() diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 5469c57c..e2d95dab 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -168,6 +168,9 @@ class OnionShareGui(QtWidgets.QMainWindow): self.setCentralWidget(central_widget) self.show() + # Adjust window size, to start with a minimum window width + self.adjust_size(450) + # The server isn't active yet self.set_server_active(False) @@ -444,10 +447,14 @@ class OnionShareGui(QtWidgets.QMainWindow): # Disable settings menu action when server is active self.settings_action.setEnabled(not active) - def adjust_size(self): + def adjust_size(self, min_width): """ - Recursively adjust size on all widgets + Recursively adjust size on all widgets. min_width is the new minimum width + of the window. """ + self.common.log("OnionShareGui", "adjust_size", "min_width={}".format(min_width)) + self.setMinimumWidth(min_width) + # Recursively adjust sizes for the modes def adjust_size_layout(layout): count = layout.count() @@ -465,8 +472,6 @@ class OnionShareGui(QtWidgets.QMainWindow): layout = widget.layout() if layout: adjust_size_layout(layout) - # Processing Qt events before adjusting size makes each .adjustSize() actually count - self.qtapp.processEvents() widget.adjustSize() # Adjust sizes of each mode @@ -474,6 +479,7 @@ class OnionShareGui(QtWidgets.QMainWindow): adjust_size_widget(mode) # Adjust window size + self.qtapp.processEvents() self.adjustSize() def closeEvent(self, e): diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/receive_mode/__init__.py index dab37ef2..e30ef519 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/receive_mode/__init__.py @@ -235,7 +235,7 @@ class ReceiveMode(Mode): self.info_widget.hide() # Resize window - self.adjust_size.emit() + self.resize_window() def toggle_uploads(self): """ @@ -252,4 +252,10 @@ class ReceiveMode(Mode): self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle_selected.png')) ) self.info_toggle_button.setFlat(False) - self.adjust_size.emit() + self.resize_window() + + def resize_window(self): + min_width = 450 + if self.uploads.isVisible(): + min_width += 300 + self.adjust_size.emit(min_width) diff --git a/onionshare_gui/share_mode/__init__.py b/onionshare_gui/share_mode/__init__.py index c0cb6d39..cc0a9f32 100644 --- a/onionshare_gui/share_mode/__init__.py +++ b/onionshare_gui/share_mode/__init__.py @@ -330,7 +330,7 @@ class ShareMode(Mode): self.info_widget.hide() # Resize window - self.adjust_size.emit() + self.resize_window() def reset_info_counters(self): """ @@ -379,7 +379,13 @@ class ShareMode(Mode): self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle_selected.png')) ) self.info_toggle_button.setFlat(False) - self.adjust_size.emit() + self.resize_window() + + def resize_window(self): + min_width = 450 + if self.downloads.isVisible(): + min_width += 300 + self.adjust_size.emit(min_width) @staticmethod def _compute_total_size(filenames): From f056ce576eee6ff5ea97b32a3642272052733a03 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 15:47:49 -0700 Subject: [PATCH 07/50] Refactor share mode info widget into its own file and custom class, and run .show_more() and .show_less() instead of .show() and .hide() --- onionshare_gui/share_mode/__init__.py | 100 ++++----------------- onionshare_gui/share_mode/info.py | 120 ++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 83 deletions(-) create mode 100644 onionshare_gui/share_mode/info.py diff --git a/onionshare_gui/share_mode/__init__.py b/onionshare_gui/share_mode/__init__.py index cc0a9f32..a8828497 100644 --- a/onionshare_gui/share_mode/__init__.py +++ b/onionshare_gui/share_mode/__init__.py @@ -28,6 +28,7 @@ from onionshare.web import Web from .file_selection import FileSelection from .downloads import Downloads from .threads import CompressThread +from .info import Info from ..mode import Mode from ..widgets import Alert @@ -77,35 +78,7 @@ class ShareMode(Mode): self.downloads_completed = 0 # Information about share, and show downloads button - self.info_label = QtWidgets.QLabel() - self.info_label.setStyleSheet(self.common.css['mode_info_label']) - - self.info_in_progress_downloads_count = QtWidgets.QLabel() - self.info_in_progress_downloads_count.setStyleSheet(self.common.css['mode_info_label']) - - self.info_completed_downloads_count = QtWidgets.QLabel() - self.info_completed_downloads_count.setStyleSheet(self.common.css['mode_info_label']) - - self.update_downloads_completed() - self.update_downloads_in_progress() - - self.info_toggle_button = QtWidgets.QPushButton() - self.info_toggle_button.setDefault(False) - self.info_toggle_button.setFixedWidth(30) - self.info_toggle_button.setFixedHeight(30) - self.info_toggle_button.setFlat(True) - self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle.png')) ) - self.info_toggle_button.clicked.connect(self.toggle_downloads) - - self.info_layout = QtWidgets.QHBoxLayout() - self.info_layout.addWidget(self.info_label) - self.info_layout.addStretch() - self.info_layout.addWidget(self.info_in_progress_downloads_count) - self.info_layout.addWidget(self.info_completed_downloads_count) - self.info_layout.addWidget(self.info_toggle_button) - - self.info_widget = QtWidgets.QWidget() - self.info_widget.setLayout(self.info_layout) + self.info = Info(self.common, self) # Primary action layout self.primary_action_layout.addWidget(self.filesize_warning) @@ -117,7 +90,7 @@ class ShareMode(Mode): # Main layout self.main_layout = QtWidgets.QVBoxLayout() - self.main_layout.addWidget(self.info_widget) + self.main_layout.addWidget(self.info) self.main_layout.addLayout(self.file_selection) self.main_layout.addWidget(self.primary_action) self.main_layout.addWidget(self.min_width_widget) @@ -218,7 +191,7 @@ class ShareMode(Mode): self.filesize_warning.hide() self.downloads_in_progress = 0 self.downloads_completed = 0 - self.update_downloads_in_progress() + self.info.update_downloads_in_progress() self.file_selection.file_list.adjustSize() def cancel_server_custom(self): @@ -234,7 +207,7 @@ class ShareMode(Mode): Connection to Tor broke. """ self.primary_action.hide() - self.info_widget.hide() + self.info.show_less() def handle_request_load(self, event): """ @@ -252,7 +225,7 @@ class ShareMode(Mode): filesize = self.web.share_mode.download_filesize self.downloads.add(event["data"]["id"], filesize) self.downloads_in_progress += 1 - self.update_downloads_in_progress() + self.info.update_downloads_in_progress() self.system_tray.showMessage(strings._('systray_download_started_title', True), strings._('systray_download_started_message', True)) @@ -268,10 +241,10 @@ class ShareMode(Mode): # Update the total 'completed downloads' info self.downloads_completed += 1 - self.update_downloads_completed() + self.info.update_downloads_completed() # Update the 'in progress downloads' info self.downloads_in_progress -= 1 - self.update_downloads_in_progress() + self.info.update_downloads_in_progress() # Close on finish? if self.common.settings.get('close_after_first_download'): @@ -282,7 +255,7 @@ class ShareMode(Mode): if self.server_status.status == self.server_status.STATUS_STOPPED: self.downloads.cancel(event["data"]["id"]) self.downloads_in_progress = 0 - self.update_downloads_in_progress() + self.info.update_downloads_in_progress() def handle_request_canceled(self, event): """ @@ -292,7 +265,7 @@ class ShareMode(Mode): # Update the 'in progress downloads' info self.downloads_in_progress -= 1 - self.update_downloads_in_progress() + self.info.update_downloads_in_progress() self.system_tray.showMessage(strings._('systray_download_canceled_title', True), strings._('systray_download_canceled_message', True)) def on_reload_settings(self): @@ -302,7 +275,7 @@ class ShareMode(Mode): """ if self.server_status.file_selection.get_num_files() > 0: self.primary_action.show() - self.info_widget.show() + self.info.show_more() def update_primary_action(self): self.common.log('ShareMode', 'update_primary_action') @@ -311,7 +284,7 @@ class ShareMode(Mode): file_count = self.file_selection.file_list.count() if file_count > 0: self.primary_action.show() - self.info_widget.show() + self.info.show_more() # Update the file count in the info label total_size_bytes = 0 @@ -321,13 +294,13 @@ class ShareMode(Mode): total_size_readable = self.common.human_readable_filesize(total_size_bytes) if file_count > 1: - self.info_label.setText(strings._('gui_file_info', True).format(file_count, total_size_readable)) + self.info.update_label(strings._('gui_file_info', True).format(file_count, total_size_readable)) else: - self.info_label.setText(strings._('gui_file_info_single', True).format(file_count, total_size_readable)) + self.info.update_label(strings._('gui_file_info_single', True).format(file_count, total_size_readable)) else: self.primary_action.hide() - self.info_widget.hide() + self.info.show_less() # Resize window self.resize_window() @@ -338,49 +311,10 @@ class ShareMode(Mode): """ self.downloads_completed = 0 self.downloads_in_progress = 0 - self.update_downloads_completed() - self.update_downloads_in_progress() + self.info.update_downloads_completed() + self.info.update_downloads_in_progress() self.downloads.reset() - def update_downloads_completed(self): - """ - Update the 'Downloads completed' info widget. - """ - if self.downloads_completed == 0: - image = self.common.get_resource_path('images/share_completed_none.png') - else: - image = self.common.get_resource_path('images/share_completed.png') - self.info_completed_downloads_count.setText(' {1:d}'.format(image, self.downloads_completed)) - self.info_completed_downloads_count.setToolTip(strings._('info_completed_downloads_tooltip', True).format(self.downloads_completed)) - - def update_downloads_in_progress(self): - """ - Update the 'Downloads in progress' info widget. - """ - if self.downloads_in_progress == 0: - image = self.common.get_resource_path('images/share_in_progress_none.png') - else: - image = self.common.get_resource_path('images/share_in_progress.png') - self.info_in_progress_downloads_count.setText(' {1:d}'.format(image, self.downloads_in_progress)) - self.info_in_progress_downloads_count.setToolTip(strings._('info_in_progress_downloads_tooltip', True).format(self.downloads_in_progress)) - - def toggle_downloads(self): - """ - Toggle showing and hiding the Downloads widget - """ - self.common.log('ShareMode', 'toggle_downloads') - - if self.downloads.isVisible(): - self.downloads.hide() - self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle.png')) ) - self.info_toggle_button.setFlat(True) - else: - self.downloads.show() - self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle_selected.png')) ) - self.info_toggle_button.setFlat(False) - - self.resize_window() - def resize_window(self): min_width = 450 if self.downloads.isVisible(): diff --git a/onionshare_gui/share_mode/info.py b/onionshare_gui/share_mode/info.py new file mode 100644 index 00000000..548d70e3 --- /dev/null +++ b/onionshare_gui/share_mode/info.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +""" +OnionShare | https://onionshare.org/ + +Copyright (C) 2014-2018 Micah Lee + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +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 . +""" +from PyQt5 import QtCore, QtWidgets, QtGui + +from onionshare import strings + + +class Info(QtWidgets.QWidget): + """ + Share mode information widget + """ + def __init__(self, common, share_mode): + super(Info, self).__init__() + self.common = common + self.share_mode = share_mode + + # Label + self.label = QtWidgets.QLabel() + self.label.setStyleSheet(self.common.css['mode_info_label']) + + # In prorgess and completed labels + self.in_progress_downloads_count = QtWidgets.QLabel() + self.in_progress_downloads_count.setStyleSheet(self.common.css['mode_info_label']) + self.completed_downloads_count = QtWidgets.QLabel() + self.completed_downloads_count.setStyleSheet(self.common.css['mode_info_label']) + + # Toggle button + self.toggle_button = QtWidgets.QPushButton() + self.toggle_button.setDefault(False) + self.toggle_button.setFixedWidth(30) + self.toggle_button.setFixedHeight(30) + self.toggle_button.setFlat(True) + self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle.png')) ) + self.toggle_button.clicked.connect(self.toggle_downloads) + + # Info layout + layout = QtWidgets.QHBoxLayout() + layout.addWidget(self.label) + layout.addStretch() + layout.addWidget(self.in_progress_downloads_count) + layout.addWidget(self.completed_downloads_count) + layout.addWidget(self.toggle_button) + self.setLayout(layout) + + self.update_downloads_completed() + self.update_downloads_in_progress() + + def update_label(self, s): + """ + Updates the text of the label. + """ + self.label.setText(s) + + def update_downloads_completed(self): + """ + Update the 'Downloads completed' info widget. + """ + if self.share_mode.downloads_completed == 0: + image = self.common.get_resource_path('images/share_completed_none.png') + else: + image = self.common.get_resource_path('images/share_completed.png') + self.completed_downloads_count.setText(' {1:d}'.format(image, self.share_mode.downloads_completed)) + self.completed_downloads_count.setToolTip(strings._('info_completed_downloads_tooltip', True).format(self.share_mode.downloads_completed)) + + def update_downloads_in_progress(self): + """ + Update the 'Downloads in progress' info widget. + """ + if self.share_mode.downloads_in_progress == 0: + image = self.common.get_resource_path('images/share_in_progress_none.png') + else: + image = self.common.get_resource_path('images/share_in_progress.png') + self.in_progress_downloads_count.setText(' {1:d}'.format(image, self.share_mode.downloads_in_progress)) + self.in_progress_downloads_count.setToolTip(strings._('info_in_progress_downloads_tooltip', True).format(self.share_mode.downloads_in_progress)) + + def toggle_downloads(self): + """ + Toggle showing and hiding the Downloads widget + """ + self.common.log('ShareMode', 'toggle_downloads') + + if self.share_mode.downloads.isVisible(): + self.share_mode.downloads.hide() + self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle.png')) ) + self.toggle_button.setFlat(True) + else: + self.share_mode.downloads.show() + self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle_selected.png')) ) + self.toggle_button.setFlat(False) + + self.share_mode.resize_window() + + def show_less(self): + """ + Remove clutter widgets that aren't necessary. + """ + self.label.hide() + + def show_more(self): + """ + Show all widgets. + """ + self.label.show() From 35065106efa934fac95991d1b593704e47bb12b5 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 16:00:22 -0700 Subject: [PATCH 08/50] Refactor receive mode into using an info widget too --- onionshare_gui/onionshare_gui.py | 1 - onionshare_gui/receive_mode/__init__.py | 88 +++---------------- onionshare_gui/receive_mode/info.py | 109 ++++++++++++++++++++++++ onionshare_gui/share_mode/__init__.py | 4 +- onionshare_gui/share_mode/info.py | 16 ++-- 5 files changed, 133 insertions(+), 85 deletions(-) create mode 100644 onionshare_gui/receive_mode/info.py diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index e2d95dab..7cc368b8 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -452,7 +452,6 @@ class OnionShareGui(QtWidgets.QMainWindow): Recursively adjust size on all widgets. min_width is the new minimum width of the window. """ - self.common.log("OnionShareGui", "adjust_size", "min_width={}".format(min_width)) self.setMinimumWidth(min_width) # Recursively adjust sizes for the modes diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/receive_mode/__init__.py index e30ef519..83113805 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/receive_mode/__init__.py @@ -23,6 +23,7 @@ from onionshare import strings from onionshare.web import Web from .uploads import Uploads +from .info import ReceiveModeInfo from ..mode import Mode class ReceiveMode(Mode): @@ -54,32 +55,8 @@ class ReceiveMode(Mode): self.new_upload = False # For scrolling to the bottom of the uploads list # Information about share, and show uploads button - self.info_in_progress_uploads_count = QtWidgets.QLabel() - self.info_in_progress_uploads_count.setStyleSheet(self.common.css['mode_info_label']) - - self.info_completed_uploads_count = QtWidgets.QLabel() - self.info_completed_uploads_count.setStyleSheet(self.common.css['mode_info_label']) - - self.update_uploads_completed() - self.update_uploads_in_progress() - - self.info_toggle_button = QtWidgets.QPushButton() - self.info_toggle_button.setDefault(False) - self.info_toggle_button.setFixedWidth(30) - self.info_toggle_button.setFixedHeight(30) - self.info_toggle_button.setFlat(True) - self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle.png')) ) - self.info_toggle_button.clicked.connect(self.toggle_uploads) - - self.info_layout = QtWidgets.QHBoxLayout() - self.info_layout.addStretch() - self.info_layout.addWidget(self.info_in_progress_uploads_count) - self.info_layout.addWidget(self.info_completed_uploads_count) - self.info_layout.addWidget(self.info_toggle_button) - - self.info_widget = QtWidgets.QWidget() - self.info_widget.setLayout(self.info_layout) - self.info_widget.hide() + self.info = ReceiveModeInfo(self.common, self) + self.info.show_less() # Receive mode info self.receive_info = QtWidgets.QLabel(strings._('gui_receive_mode_warning', True)) @@ -88,7 +65,7 @@ class ReceiveMode(Mode): # Main layout self.main_layout = QtWidgets.QVBoxLayout() - self.main_layout.addWidget(self.info_widget) + self.main_layout.addWidget(self.info) self.main_layout.addWidget(self.receive_info) self.main_layout.addWidget(self.primary_action) self.main_layout.addStretch() @@ -137,7 +114,7 @@ class ReceiveMode(Mode): Connection to Tor broke. """ self.primary_action.hide() - self.info_widget.hide() + self.info.show_less() def handle_request_load(self, event): """ @@ -151,7 +128,7 @@ class ReceiveMode(Mode): """ self.uploads.add(event["data"]["id"], event["data"]["content_length"]) self.uploads_in_progress += 1 - self.update_uploads_in_progress() + self.info.update_uploads_in_progress() self.system_tray.showMessage(strings._('systray_upload_started_title', True), strings._('systray_upload_started_message', True)) @@ -181,17 +158,17 @@ class ReceiveMode(Mode): self.uploads.finished(event["data"]["id"]) # Update the total 'completed uploads' info self.uploads_completed += 1 - self.update_uploads_completed() + self.info.update_uploads_completed() # Update the 'in progress uploads' info self.uploads_in_progress -= 1 - self.update_uploads_in_progress() + self.info.update_uploads_in_progress() def on_reload_settings(self): """ We should be ok to re-enable the 'Start Receive Mode' button now. """ self.primary_action.show() - self.info_widget.show() + self.info.show_more() def reset_info_counters(self): """ @@ -199,61 +176,22 @@ class ReceiveMode(Mode): """ self.uploads_completed = 0 self.uploads_in_progress = 0 - self.update_uploads_completed() - self.update_uploads_in_progress() + self.info.update_uploads_completed() + self.info.update_uploads_in_progress() self.uploads.reset() - def update_uploads_completed(self): - """ - Update the 'Uploads completed' info widget. - """ - if self.uploads_completed == 0: - image = self.common.get_resource_path('images/share_completed_none.png') - else: - image = self.common.get_resource_path('images/share_completed.png') - self.info_completed_uploads_count.setText(' {1:d}'.format(image, self.uploads_completed)) - self.info_completed_uploads_count.setToolTip(strings._('info_completed_uploads_tooltip', True).format(self.uploads_completed)) - - def update_uploads_in_progress(self): - """ - Update the 'Uploads in progress' info widget. - """ - if self.uploads_in_progress == 0: - image = self.common.get_resource_path('images/share_in_progress_none.png') - else: - image = self.common.get_resource_path('images/share_in_progress.png') - self.info_in_progress_uploads_count.setText(' {1:d}'.format(image, self.uploads_in_progress)) - self.info_in_progress_uploads_count.setToolTip(strings._('info_in_progress_uploads_tooltip', True).format(self.uploads_in_progress)) - def update_primary_action(self): self.common.log('ReceiveMode', 'update_primary_action') # Show the info widget when the server is active if self.server_status.status == self.server_status.STATUS_STARTED: - self.info_widget.show() + self.info.show_more() else: - self.info_widget.hide() + self.info.show_less() # Resize window self.resize_window() - def toggle_uploads(self): - """ - Toggle showing and hiding the Uploads widget - """ - self.common.log('ReceiveMode', 'toggle_uploads') - - if self.uploads.isVisible(): - self.uploads.hide() - self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle.png')) ) - self.info_toggle_button.setFlat(True) - else: - self.uploads.show() - self.info_toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle_selected.png')) ) - self.info_toggle_button.setFlat(False) - - self.resize_window() - def resize_window(self): min_width = 450 if self.uploads.isVisible(): diff --git a/onionshare_gui/receive_mode/info.py b/onionshare_gui/receive_mode/info.py new file mode 100644 index 00000000..0f5bc298 --- /dev/null +++ b/onionshare_gui/receive_mode/info.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +""" +OnionShare | https://onionshare.org/ + +Copyright (C) 2014-2018 Micah Lee + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +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 . +""" +from PyQt5 import QtCore, QtWidgets, QtGui + +from onionshare import strings + + +class ReceiveModeInfo(QtWidgets.QWidget): + """ + Receive mode information widget + """ + def __init__(self, common, receive_mode): + super(ReceiveModeInfo, self).__init__() + self.common = common + self.receive_mode = receive_mode + + # In progress and completed labels + self.in_progress_uploads_count = QtWidgets.QLabel() + self.in_progress_uploads_count.setStyleSheet(self.common.css['mode_info_label']) + self.completed_uploads_count = QtWidgets.QLabel() + self.completed_uploads_count.setStyleSheet(self.common.css['mode_info_label']) + + # Toggle button + self.toggle_button = QtWidgets.QPushButton() + self.toggle_button.setDefault(False) + self.toggle_button.setFixedWidth(30) + self.toggle_button.setFixedHeight(30) + self.toggle_button.setFlat(True) + self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle.png')) ) + self.toggle_button.clicked.connect(self.toggle_uploads) + + # Layout + layout = QtWidgets.QHBoxLayout() + layout.addStretch() + layout.addWidget(self.in_progress_uploads_count) + layout.addWidget(self.completed_uploads_count) + layout.addWidget(self.toggle_button) + self.setLayout(layout) + + self.update_uploads_completed() + self.update_uploads_in_progress() + + def update_uploads_completed(self): + """ + Update the 'Uploads completed' info widget. + """ + if self.receive_mode.uploads_completed == 0: + image = self.common.get_resource_path('images/share_completed_none.png') + else: + image = self.common.get_resource_path('images/share_completed.png') + self.completed_uploads_count.setText(' {1:d}'.format(image, self.receive_mode.uploads_completed)) + self.completed_uploads_count.setToolTip(strings._('info_completed_uploads_tooltip', True).format(self.receive_mode.uploads_completed)) + + def update_uploads_in_progress(self): + """ + Update the 'Uploads in progress' info widget. + """ + if self.receive_mode.uploads_in_progress == 0: + image = self.common.get_resource_path('images/share_in_progress_none.png') + else: + image = self.common.get_resource_path('images/share_in_progress.png') + self.in_progress_uploads_count.setText(' {1:d}'.format(image, self.receive_mode.uploads_in_progress)) + self.in_progress_uploads_count.setToolTip(strings._('info_in_progress_uploads_tooltip', True).format(self.receive_mode.uploads_in_progress)) + + def toggle_uploads(self): + """ + Toggle showing and hiding the Uploads widget + """ + self.common.log('ReceiveModeInfo', 'toggle_uploads') + + if self.receive_mode.uploads.isVisible(): + self.receive_mode.uploads.hide() + self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle.png')) ) + self.toggle_button.setFlat(True) + else: + self.receive_mode.uploads.show() + self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle_selected.png')) ) + self.toggle_button.setFlat(False) + + self.receive_mode.resize_window() + + def show_less(self): + """ + Remove clutter widgets that aren't necessary. + """ + pass + + def show_more(self): + """ + Show all widgets. + """ + pass diff --git a/onionshare_gui/share_mode/__init__.py b/onionshare_gui/share_mode/__init__.py index a8828497..0504b529 100644 --- a/onionshare_gui/share_mode/__init__.py +++ b/onionshare_gui/share_mode/__init__.py @@ -28,7 +28,7 @@ from onionshare.web import Web from .file_selection import FileSelection from .downloads import Downloads from .threads import CompressThread -from .info import Info +from .info import ShareModeInfo from ..mode import Mode from ..widgets import Alert @@ -78,7 +78,7 @@ class ShareMode(Mode): self.downloads_completed = 0 # Information about share, and show downloads button - self.info = Info(self.common, self) + self.info = ShareModeInfo(self.common, self) # Primary action layout self.primary_action_layout.addWidget(self.filesize_warning) diff --git a/onionshare_gui/share_mode/info.py b/onionshare_gui/share_mode/info.py index 548d70e3..3ee12a95 100644 --- a/onionshare_gui/share_mode/info.py +++ b/onionshare_gui/share_mode/info.py @@ -22,20 +22,21 @@ from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings -class Info(QtWidgets.QWidget): +class ShareModeInfo(QtWidgets.QWidget): """ Share mode information widget """ def __init__(self, common, share_mode): - super(Info, self).__init__() + super(ShareModeInfo, self).__init__() self.common = common self.share_mode = share_mode # Label + self.label_text = "" self.label = QtWidgets.QLabel() self.label.setStyleSheet(self.common.css['mode_info_label']) - # In prorgess and completed labels + # In progress and completed labels self.in_progress_downloads_count = QtWidgets.QLabel() self.in_progress_downloads_count.setStyleSheet(self.common.css['mode_info_label']) self.completed_downloads_count = QtWidgets.QLabel() @@ -66,7 +67,8 @@ class Info(QtWidgets.QWidget): """ Updates the text of the label. """ - self.label.setText(s) + self.label_text = s + self.label.setText(self.label_text) def update_downloads_completed(self): """ @@ -94,7 +96,7 @@ class Info(QtWidgets.QWidget): """ Toggle showing and hiding the Downloads widget """ - self.common.log('ShareMode', 'toggle_downloads') + self.common.log('ShareModeInfo', 'toggle_downloads') if self.share_mode.downloads.isVisible(): self.share_mode.downloads.hide() @@ -111,10 +113,10 @@ class Info(QtWidgets.QWidget): """ Remove clutter widgets that aren't necessary. """ - self.label.hide() + self.label.setText("") def show_more(self): """ Show all widgets. """ - self.label.show() + self.label.setText(self.label_text) From 08ac4137c7b70e20bc28016eddbe3197bceb3a6b Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 16:06:14 -0700 Subject: [PATCH 09/50] Process Qt events once more, to prevent weird size issues before adjusting size --- onionshare_gui/mode.py | 1 + onionshare_gui/onionshare_gui.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/onionshare_gui/mode.py b/onionshare_gui/mode.py index bd247568..0fba029b 100644 --- a/onionshare_gui/mode.py +++ b/onionshare_gui/mode.py @@ -350,4 +350,5 @@ class Mode(QtWidgets.QWidget): Always resize the window after showing this Mode widget. """ super(Mode, self).show() + self.qtapp.processEvents() self.resize_window() diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 7cc368b8..51190ea3 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -454,7 +454,6 @@ class OnionShareGui(QtWidgets.QMainWindow): """ self.setMinimumWidth(min_width) - # Recursively adjust sizes for the modes def adjust_size_layout(layout): count = layout.count() for i in range(count): From c0e6968b2bcf8f7c490db375980fbef976d15e7d Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 17:01:48 -0700 Subject: [PATCH 10/50] Attempting to redesign Downloads --- onionshare/common.py | 15 +++++ onionshare_gui/share_mode/downloads.py | 74 +++++++++++++++++-------- share/images/downloads.png | Bin 0 -> 2120 bytes share/images/downloads_transparent.png | Bin 0 -> 2138 bytes share/images/uploads.png | Bin 0 -> 2076 bytes share/images/uploads_transparent.png | Bin 0 -> 2096 bytes share/locale/en.json | 4 +- 7 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 share/images/downloads.png create mode 100644 share/images/downloads_transparent.png create mode 100644 share/images/uploads.png create mode 100644 share/images/uploads_transparent.png diff --git a/onionshare/common.py b/onionshare/common.py index 28b282c2..78b6e2d7 100644 --- a/onionshare/common.py +++ b/onionshare/common.py @@ -248,6 +248,15 @@ class Common(object): border-radius: 5px; }""", + 'downloads_uploads': """ + background-color: #ffffff; + """, + + 'downloads_uploads_empty_text': """ + QLabel { + color: #999999; + }""", + 'downloads_uploads_label': """ QLabel { font-weight: bold; @@ -255,6 +264,12 @@ class Common(object): text-align: center; }""", + 'downloads_uploads_clear': """ + QPushButton { + color: #3f7fcf; + } + """, + 'downloads_uploads_progress_bar': """ QProgressBar { border: 1px solid #4e064f; diff --git a/onionshare_gui/share_mode/downloads.py b/onionshare_gui/share_mode/downloads.py index a34796f1..3da88bc4 100644 --- a/onionshare_gui/share_mode/downloads.py +++ b/onionshare_gui/share_mode/downloads.py @@ -89,33 +89,64 @@ class Downloads(QtWidgets.QScrollArea): self.downloads = {} - self.setWindowTitle(strings._('gui_downloads', True)) - self.setWidgetResizable(True) - self.setMinimumHeight(150) self.setMinimumWidth(350) - self.setWindowIcon(QtGui.QIcon(common.get_resource_path('images/logo.png'))) - self.setWindowFlags(QtCore.Qt.Sheet | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.CustomizeWindowHint) + self.setStyleSheet(self.common.css['downloads_uploads']) + + # Scroll bar self.vbar = self.verticalScrollBar() self.vbar.rangeChanged.connect(self.resizeScroll) + # When there are no downloads + empty_image = QtWidgets.QLabel() + empty_image.setAlignment(QtCore.Qt.AlignCenter) + empty_image.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/downloads_transparent.png')))) + empty_text = QtWidgets.QLabel(strings._('gui_no_downloads', True)) + empty_text.setAlignment(QtCore.Qt.AlignCenter) + empty_text.setStyleSheet(self.common.css['downloads_uploads_empty_text']) + empty_layout = QtWidgets.QVBoxLayout() + empty_layout.addStretch() + empty_layout.addWidget(empty_image) + empty_layout.addWidget(empty_text) + empty_layout.addStretch() + self.empty = QtWidgets.QWidget() + self.empty.setLayout(empty_layout) + + # When there are downloads downloads_label = QtWidgets.QLabel(strings._('gui_downloads', True)) downloads_label.setStyleSheet(self.common.css['downloads_uploads_label']) - self.no_downloads_label = QtWidgets.QLabel(strings._('gui_no_downloads', True)) - self.clear_history_button = QtWidgets.QPushButton(strings._('gui_clear_history', True)) - self.clear_history_button.clicked.connect(self.reset) - self.clear_history_button.hide() + clear_button = QtWidgets.QPushButton(strings._('gui_clear_history', True)) + clear_button.setStyleSheet(self.common.css['downloads_uploads_clear']) + clear_button.setFlat(True) + clear_button.clicked.connect(self.reset) + download_header = QtWidgets.QHBoxLayout() + download_header.addWidget(downloads_label) + download_header.addStretch() + download_header.addWidget(clear_button) + self.not_empty = QtWidgets.QWidget() + self.not_empty.setLayout(download_header) self.downloads_layout = QtWidgets.QVBoxLayout() - widget = QtWidgets.QWidget() + # Layout + self.widget = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() - layout.addWidget(downloads_label) - layout.addWidget(self.no_downloads_label) - layout.addWidget(self.clear_history_button) + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(self.empty) + layout.addWidget(self.not_empty) layout.addLayout(self.downloads_layout) layout.addStretch() - widget.setLayout(layout) - self.setWidget(widget) + self.widget.setLayout(layout) + self.setWidget(self.widget) + + # Reset once at the beginning + self.reset() + + def resizeEvent(self, event): + """ + When the widget resizes, resize the inner widget to match + """ + #self.empty.resize(self.width()-2, self.width()-2) + pass def resizeScroll(self, minimum, maximum): """ @@ -127,10 +158,9 @@ class Downloads(QtWidgets.QScrollArea): """ Add a new download progress bar. """ - # Hide the no_downloads_label - self.no_downloads_label.hide() - # Show the clear_history_button - self.clear_history_button.show() + # Hide empty, show not empty + self.empty.hide() + self.not_empty.show() # Add it to the list download = Download(self.common, download_id, total_bytes) @@ -158,6 +188,6 @@ class Downloads(QtWidgets.QScrollArea): download.progress_bar.close() self.downloads = {} - self.no_downloads_label.show() - self.clear_history_button.hide() - self.resize(self.sizeHint()) + # Hide not empty, show empty + self.not_empty.hide() + self.empty.show() diff --git a/share/images/downloads.png b/share/images/downloads.png new file mode 100644 index 0000000000000000000000000000000000000000..ad879b6e0f80dbfa3c82459e645d52f1412caf3a GIT binary patch literal 2120 zcmV-O2)Fl%P)T2h~YL zK~#9!?VVp}Th|@OKf01F)%Kl{W9HOJRQTP1#AYs39JVKz!snZXaxM?&=_zZ zm;n9(M1XPN0T5L+_1{iigUbPE+kqf(0B{3dgGJ5)kAe4qAyrd9S#tmtS!o4!0mp#~ zi_Oger+~1ksaIAlKt)!3qDkJg0a`YgJAjC)sWVm>kSv1tCU6(H;~+eQ?K{9-QK!=O zK+(U2fhtN<)4(n>`$?CH@a~Ecbu}oeYU;O30-z!*2Z7T-EvrjY!0W1}{@zF-ZiDcC z3-kj%R-b%;67UA?%4XiEQ1HP|n z>SQ4&d5SP}--OviDQbhbHlOJpC|ujWhT)}74I6=&s;NoSny?}(U)j}cTYuI{*Bf2b zt*--Ma(t4Dzq-hkKVGq|Ijfqw(X>%mbh6*Gqvi+SI!I?0UO3pkBtdgr}eWlgz5a*zgIPkQcwXNS+Z^|(y>vT~7#oX4`>6x$E zXUZ`qt5&ecAD~!Ov3+46nM|5;j0M^(nB?t&VJB*tm`|8;j719P1yC$JI*1z?)@8IdwBFK=J6YqRc0!Dg>()9=OX) zE1i9veE8oF7ym+oA^Z(~%dgJg;3qT~T4uYmuhVQZyV3zXZdU32m;34J>st0%TX!3S z*9Y19!dA=RZGB-YgVzUX>uy{2c~@T-{g?aAGFaA57#X0w zr`>dT?LF-bj0{j)pMLVRt$CZ7o>;LESTA^B(5#YEJug+B3J<}zgY=y0F%4eNsUCuF z2k}&R4Areb1(yOmU}v!EcDvbqXg9q>y@t!`9qMKGq20LMZfw>80FQXZY?*bJ%ldbY zBuS!WUkdXwJRz-E^sD?b7LluRZ~yOS4gU0}m^3VVEV|6li!>ty6QIqPxSq=q)B(fCYb zLFM23=RHEtn?6hZsf7M^sHx2$^n8eiUp_48oW^Gwsqxq3Jg&xHQ!u=TUp}+~9>97D zXtSc^;Il!-J|8RSoP2I#p*MQ$^D%>Bn9?#_g-O9h-CAzIvNuFCMef z#1;vVt+a5m<0Rqt!?v#DC6h_Q?}s_ranfp24IZGe8xs1)Jx8?=E9NVkV!V9x7YTjWqvJXgJd^i>b(>1KXzKI8ZEbMtg>>2@66l92C#1Vqu_3wB(wi5MO0I*5K2UGZJ?vnUjY_Pn;I*a0IWqf~$q;At)W^(0Bc)iehvNox4{^)te{yw&91L-sjG7mnv&K4W4*Ft)eVsuW` z)T4#~3W(Q$rvEc|qpGGh=bSI+Tbi9oCrUthC!Hv#Jy|Jh(w;1VIkSc#&Z?SP(3bdO zCasO=X_D4lvlZ8d)c|9ne;8e31I9-5Y{3P|&^v8wB*e)Xs$`8hjaZJvBOe94fv?0o zakb?ToC1!hnmS;lka7x8gEDR9Q&eaNrM(n34eT%ro~a&~;*D>jC$A`#{0m>BFNXG; yU2r)Occ}tQfmu!kZz9a{j}e#%bJhPG#{U3#k;&MKJ6Qq%0000Iz^0 literal 0 HcmV?d00001 diff --git a/share/images/downloads_transparent.png b/share/images/downloads_transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..9920709707a9dc6e3e9c59f5d5ab9d6a1fc21026 GIT binary patch literal 2138 zcmV-g2&MOlP)=0V#(1<@OiE*7j4;iR5Kw_Yf-r8INVe=$BZP}&P^H+)daJlf zESbKzYQ;mKNt8n6C>NC=IWJL^CbHyFaTB3F7?L;zVGwB^HU-&f8ia-L0)q*@?e<}3 z$r|r^XLjeZ>+E0J7thSO{N_97eCIoJjyAzdRI1o`a^@dw@@VEf20@w^}1O!0LG07Pq3S0n&R876S-~cL;QVmoAJ9KDvDhhlG ze64EgrGf>hNQzf)jv)u2%?I-+a81?J>4E{MNJ=fRRqxC4LAQW2s-~XIYk+$H)&eXd zKQ#rsV`V?-u@GJda36)C>#C-9=LJATQZ@ngfRDn`1n{w{spoP@M9dLh1Mno^rSRkh zWZ5T|h9|=p9S5jLN-OXPg|C&ePhJzA44-$T2`iGa1b9xLDJ&#uz+0-OerM*PZ2YtR z3lJW9o%Y*ifx6}Gw_xg(@0tM)8?{6;7WkY~@akIX==rLLzMFmY-Rz_1s~+lF>YM^7 z>UFhl5YY#WA30I_XJ2}j=B{SS{NGPvmXs}F(^H#}0utx`dCrMq_>2xLq5*gfPK~y8 zEp;??Hc?VqGPj_jNae$oXk!|e&R=q(IDR88j$pt^-sV)>se7i5QmHiU^-`&nx@R0~ z$^hGR23hxk^-h*{`Gd8K_5*rXOi0QF#~EAhNMwm^VII-B$W^)UQaib|)gI-|4}m{?LQ zDzy?zuW12>ii|QUloFu6^e7bhWR4%`tmar?m6f?PcQxM)2K3$RqrJPGz>0wFwF|5W z(B9oXEAQs6W~;NQN(FF-RjD65evrLgduO}zt@U&dcC+sBb+*A<_xL)x2fL|nojrNj z+qIX2#}8VW)s9&Jbth4<%JMes+>m;9zTD5D{zEi|8ZC#{7;5BD{~`R#{VA_+*tx+< zOB520bpqOEt5Uw#^6r&)k(b~rK|-%uH(rHa4H0}LhEK>0=hul|YItmfq7tfoZSC;!6kTn5!aD%Mu8>fu$kLyShFoci!o)~=CRS4Nb5^3M}* z&CbdVs)P8;{Z#+78bPqf;Af_1_~_V2y#D;_PW2LAQTE9{i}%g;H?OlN&T?hs3Xj!4 zhUm3+<}fue#cRKPjo!cXI?_exygUN&O)QRS;QayG9&Ka%#<*o^j^7xk?a?*{-XCzJ z4#~zQ5dSXDQAI{0?5o^o+E+~HxXhI;q@60u2 z>nl3o;~CNaMA;`V1J=4(iiEGYdi`p{_dDR@8PRE1n{cv@1dkYASa-3#{IU19!qq(NO z>xEs^?5@chcmRt_7E`mkhFvf0%67m=%jjN!*K(cOHMTX{7IDr+f*{b?)|gAPh3^mk zNexgx8stna1)XoFk=vTDYz8CpXYM^dWsa%nM}tfi$KW}dN_A{Xy0-RCwz=HaZs#q5 z9LtuHNlJjalXyLwT>9VcCmPK^pFA3k(*JgUwvS&=ch*eWrLpj2_+PS5-j2x=IfgF` zbARRiJh0{g%U9lVabrH~`;2#Ae3!}ZCe1!Rp=#>kbQd$h`4~{l)fc4AKuinV!}+TyNutsne>a{$t*kl_`brWcZ@&lh*+L9~ivaVf15R<*VS0W#%$_}r2K(}dv?r>s;Q=SV0 zl(POLOFv6y)dCtYda`*i>!ui<44;>Maw)K~z~P-XGTK@WFv-Qa39P2@&Jdgc`c+Lm zl}jSUBS3Rh@eta40+yV@BZ#NKO7WMvPa$l)B_Iy+W{Z&7*Gw=0ABUh2rv!Y z0saSsf!n}cU{WaJt77%RQ3PmD0*8S^fD>@(EOH)L0{#Jngd+a4=>WeTPgBup0?2+B-ko?pFXt`kS1j0fQb7oW^nFQ|?a1;2vi11MB{v5cew#nWW zsLpT0z!vPOSs-BKJn1kH-c5By-3Xc#ig?5p0A-K-JK!9!m5rq+@Ul?E-}MyY)Cun| zz-hqE#*-V6eJQ{r6R~tS3q?F+qy>%ueydvl`oCYN{)yEt<>bU9Fa7K#DgoBe2XD34Du8~q@7gU;b&^9?wYWFhi^Gw7P$UuwnzlAsX^Dq(Ios=5 z;5n;W*&1qH7aoAa;h;6tY9+vPnk>-DciZ-!b{d{;DCn8-e~r`e%Z{SIJ3DejRX(+% zW#`AvQ}=kCre~+FPZ8W5vx14Pu_*Rf|m+?{la#uOQw}P~sZ7~zzgDRt}08Lvs zT0^buJF*XFnbWl1Im?{vJF?GgH)ju&oqSF%<%CFb&!oz z!_y6%A3JYG(QT^$s*bavGrJZaFOf(Xa*qYRV!6s}#R3l-S$gMZodx@N(_c(;KXQNF z`|d~XGyTPM!McEKu)IM5UkkyS3jdQf&Xx`5pZ8*yK(0D=Z ztbMeW11Am`3Gfhrq;4^Drcc6Jb@0T&g5X{G@CqHxg$D&Xnmf4i;gy0Q7SgtSR%6*C z?wZ{?{DNQb*ULv`<(NcIzOH1^3_v?a} z3bDVtpQWXxVl4CztN=6$-o-N)b6#IuSS0jHh_1FS!+O!x)z)D{ibXWe9R$x)TXNv$%A{g(A@WPhTLPJ1|*WF9&Mp} zx9%BokA#RZrGZyuOjKJ)QCHag$7_qTgF`07EbwpRf#b9;u1f4W#ycp2iQ zvqBM-%K-ldJYRB=3)0&{5x-w{szN0m>n<4S3PH*SOW7mGDDK%_Tf)oYcP^l@^;!+Sfw8I8U|i9qGETYoBhx4$KUM7TkXZQ#RUmiTD0cFkF(4P4w#>vCvqpk z=;cv9e*5FRo$x$9u&wM?U3Hfc!`M^hq2a=OU4Q68nNjo> zw=#UwhcF})H0V;(i%s~O{kDMzP~on?-|VO9#U`x_Mpj1Y0K>qydK%k!q_G$uxz~^4 zND_@l8ubiYR5szP0M*nWx_04g@z^!rMDDib8Rh9rPoJ{JRD>cnkyJkbOQR?mXS$Dfa-~yNiDVXb@vgE$885M9*@)4t$9bpWVT#0S!a9oY*@6= zntI>pW%TkWvALLS;Kk-*j9wn4_l;gHk4JOmm{~7p!pnueCo3}wZ@%y*Q`e?8tRtO) zLH5OGy{FYf$D1L&i5C4;DB=ZO09A;V9{IP4@;dTw+oTgkmf=Y!N@-8@T3`yyxlIgl zUMQlV#5-DET5CwAN!oP7R_z;R1B|Hi!{{bkFdjm~Mk`(WBsPhQv#zU>)92Jvb2t|6 z_qlwx)c3@VmP0TK92biCqn<)aDL{3~u*j#{pqQ;$fp|9!fRG5>T}i4LWsKZK7n^Lz7ZUQ9{+wiYrk8EkbJrak87F#EzXk z_?o$i9sBzJ$#w8o@{8}e=g-H#bI$MlwTmT`syRA3Ug zqkSfUDIhGX^2Ab=!L4z*Y^Km5KxB zfE%(Ze_gNuC7PS7N9QC8(aM+4N_w>`iL zoT(^q!pwHkWg@(G-~kFlMlO6+h0A319GeDoL%9o5p;x-8Hx4>@z4}~WW zAc|hGOo=F0Z3ig%q~8PUDSTClUa?k*D4*L>g(aV~5@^##3d>0<@TRQFKj?WWAOCFM zGK7a#rhS%Kpk{gdOc;7OT`}Nju9m3B0^96_=U?Nec2h02n`-f|@!JW|t(Db03)DJ{ zpV?J{*U!Dq!#{ucN8eo=y~ayhU$PVAH?k@pHw;j7Rkqk=b)m09cvhtMie{s;>|MW? z@ONRmAbuvRa&O)MH78lJE4S}YypPMZ_-{HlH%D_tvz?YGFXn7#YXf)KmCKG$M^<XHmcZhnaKIiZ?8)^`LCGyeVKeA=SB6`JNC=umC&K9W6 zs@O6y&~?6xz>@*p?**O=&~?7cE-QRMW0G?f-eX6uLSKfc*-(@B`!ySC2z?o{3*w%f z0BVz=md@w-*Z4X0?I|kPRT_?~a$O~-zCC4!ued^ElNq2k4ZqpSTr@u0NcZJ#$}7rE zi?h6t9;geQ-CP67y%j+#WYunzm5!lM06a zHEdN8N`SAFh%%K4U1g=dDU6phT3x1pu|B z$4yqj+y3-+1i|{nIhV^t_4;bo)~&S)qD%COHlBiDCiEMR>k7rt4v(8uC`XhjvlW1!F%E!l>o0~Hwj19h`kaVn*&`dRxW5dUE z`*^pm-eNL5nKj&Gc#>OJ^)2gGuB+tO@G;X3JQd(ZBfoO0cJ1Fq)uUCqtZrmrgtkD= zbC|RR+87xa(Us4tN2}Pif0vm6HzrN7Vt(~C(%?V0|2bXo2G0y~xaF|!bPl&1X7J3Q zE{J;amSZ)p@Q~P_=S~*LuHG^pk27?3h}ZVMmUkS|NHJ;8yd1M~!YOgDv|U=IhH4lr>${chjUp;1mBIc;{b zs|DbvX2;sOvva|(-FLi?_WE|NT)1LceY$et3hnjn^d0Y8V0oQ8JFQ4^wM+6zoj7E% z{O#*+<9l%NO%Ljr%I=!oI7HtIEdQMbR>~)s;XL2RDiwe^Gkf9tK`F-O5=b0kDN2V@ zjZGl2FV1lpGZMx|#RL*Z030E~BbXA#M$HH$&Ycx4FhAXN6u`SvcTEXnqrP@j6~2A* zwkct3?1iTU5=TZIq5hNoOsmrwpHHjP^q=fsa(F4t$dmwtN$d+=dVnYT8F*`eXe7Ge zSu_%5;H?4rPb@9K6nHTp>{cSmjOY~`oHC@l^zTcIe?Ly$V|A=twGx1_|BP|+;7QIN zJ?j+91Bl70Jm3P5e9}|EFN-d+E)C17{6W&G8Y%L~+F{JsNOB~CcKkD5#Fe$$CKXQ} znN4-;&lQp7?6luwmAcRD2C&VHgiFgy+4+Z^G_*9}U*pGH=7l+k&Dzu1yFG4j!OZjw z;qStH{Ev_M@NXaH?1bmAz;@#vY(^4#QXP?Cp1e#uGGE!~f{}=zH2dG^Qa?wae%Y0>y?GzTvTaL3l7w2D}vcOcd zt3jg0K6v41GTpT)nd;h!d{bF$GGM7?FmGv@qy?xsiR1aC($n2TJnlT7JRXnJ)1CK@ zi1AE!&19TFP$J3&(JR)Y^G1$qUtFVdT_q3IK9ums9OA}&^3P9r=hb(J{1DOm`i!i~ zM>9Rl2B#05$6eJil{fzQ2G=iNFIY!94TH>`Pqw%1JaFwmWj%16wT>wf<*MivYk`XU z4Bj`gDxb;fU*-~%c6We!AHh>|xi2ASfSTUKAyfYrE2fn-w;3C~u{&uyoE7k7RsOTC zAz~hh99^c>S=Gv>OL;Hz+kKae4IReud|u4EDk>4>bI~i70aXPK@3UNbThjrixH$g> zYAC!r1ZRLAS(S&3L{hv0)S!x&&^ifV3drI$$RCbyHtKO-;+X2Jg* a#{U3{;?ogoegf_Q0000 Date: Fri, 28 Sep 2018 18:30:32 -0700 Subject: [PATCH 11/50] Got empty Downloads looking good --- onionshare/common.py | 13 +++++++++-- onionshare_gui/share_mode/downloads.py | 31 +++++++++++++------------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/onionshare/common.py b/onionshare/common.py index 78b6e2d7..3489c3e6 100644 --- a/onionshare/common.py +++ b/onionshare/common.py @@ -248,8 +248,15 @@ class Common(object): border-radius: 5px; }""", - 'downloads_uploads': """ - background-color: #ffffff; + 'downloads_uploads_empty': """ + QWidget { + background-color: #ffffff; + border: 1px solid #999999; + } + QWidget QLabel { + background-color: none; + border: 0px; + } """, 'downloads_uploads_empty_text': """ @@ -262,6 +269,8 @@ class Common(object): font-weight: bold; font-size 14px; text-align: center; + background-color: none; + border: none; }""", 'downloads_uploads_clear': """ diff --git a/onionshare_gui/share_mode/downloads.py b/onionshare_gui/share_mode/downloads.py index 3da88bc4..fcf8bc8e 100644 --- a/onionshare_gui/share_mode/downloads.py +++ b/onionshare_gui/share_mode/downloads.py @@ -78,7 +78,7 @@ class Download(object): self.started) -class Downloads(QtWidgets.QScrollArea): +class Downloads(QtWidgets.QWidget): """ The downloads chunk of the GUI. This lists all of the active download progress bars. @@ -90,11 +90,6 @@ class Downloads(QtWidgets.QScrollArea): self.downloads = {} self.setMinimumWidth(350) - self.setStyleSheet(self.common.css['downloads_uploads']) - - # Scroll bar - self.vbar = self.verticalScrollBar() - self.vbar.rangeChanged.connect(self.resizeScroll) # When there are no downloads empty_image = QtWidgets.QLabel() @@ -109,6 +104,7 @@ class Downloads(QtWidgets.QScrollArea): empty_layout.addWidget(empty_text) empty_layout.addStretch() self.empty = QtWidgets.QWidget() + self.empty.setStyleSheet(self.common.css['downloads_uploads_empty']) self.empty.setLayout(empty_layout) # When there are downloads @@ -122,25 +118,29 @@ class Downloads(QtWidgets.QScrollArea): download_header.addWidget(downloads_label) download_header.addStretch() download_header.addWidget(clear_button) - self.not_empty = QtWidgets.QWidget() - self.not_empty.setLayout(download_header) - self.downloads_layout = QtWidgets.QVBoxLayout() + not_empty_layout = QtWidgets.QVBoxLayout() + not_empty_layout.addLayout(download_header) + not_empty_layout.addLayout(self.downloads_layout) + self.not_empty = QtWidgets.QWidget() + self.not_empty.setLayout(not_empty_layout) # Layout - self.widget = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.empty) layout.addWidget(self.not_empty) - layout.addLayout(self.downloads_layout) - layout.addStretch() - self.widget.setLayout(layout) - self.setWidget(self.widget) + self.setLayout(layout) # Reset once at the beginning self.reset() + """ + # Scroll bar + self.vbar = self.verticalScrollBar() + self.vbar.rangeChanged.connect(self.resizeScroll) + """ + def resizeEvent(self, event): """ When the widget resizes, resize the inner widget to match @@ -152,7 +152,8 @@ class Downloads(QtWidgets.QScrollArea): """ Scroll to the bottom of the window when the range changes. """ - self.vbar.setValue(maximum) + pass + #self.vbar.setValue(maximum) def add(self, download_id, total_bytes): """ From 71149c2937ba52429ef4360caaff28fc547e8380 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 18:48:12 -0700 Subject: [PATCH 12/50] Refactor Downloads to use an internal QListWidget to list the progess bars --- onionshare_gui/share_mode/downloads.py | 83 +++++++++++++++++++------- 1 file changed, 63 insertions(+), 20 deletions(-) diff --git a/onionshare_gui/share_mode/downloads.py b/onionshare_gui/share_mode/downloads.py index fcf8bc8e..855827b1 100644 --- a/onionshare_gui/share_mode/downloads.py +++ b/onionshare_gui/share_mode/downloads.py @@ -78,6 +78,59 @@ class Download(object): self.started) +class DownloadList(QtWidgets.QListWidget): + """ + List of download progess bars. + """ + def __init__(self, common): + super(DownloadList, self).__init__() + self.common = common + + self.downloads = {} + + self.setMinimumHeight(205) + self.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) + self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) + + def add(self, download_id, total_bytes): + """ + Add a new download progress bar. + """ + download = Download(self.common, download_id, total_bytes) + self.downloads[download_id] = download + + item = QtWidgets.QListWidgetItem() + self.addItem(item) + self.setItemWidget(item, download.progress_bar) + + def update(self, download_id, downloaded_bytes): + """ + Update the progress of a download progress bar. + """ + self.downloads[download_id].update(downloaded_bytes) + + def cancel(self, download_id): + """ + Update a download progress bar to show that it has been canceled. + """ + self.downloads[download_id].cancel() + + def reset(self): + """ + Reset the downloads back to zero + """ + # Remove all items from list + while True: + item = self.takeItem(0) + if not item: + break + + # Close all progress bars + for download in self.downloads.values(): + download.progress_bar.close() + self.downloads = {} + + class Downloads(QtWidgets.QWidget): """ The downloads chunk of the GUI. This lists all of the active download @@ -87,8 +140,6 @@ class Downloads(QtWidgets.QWidget): super(Downloads, self).__init__() self.common = common - self.downloads = {} - self.setMinimumWidth(350) # When there are no downloads @@ -108,6 +159,9 @@ class Downloads(QtWidgets.QWidget): self.empty.setLayout(empty_layout) # When there are downloads + self.download_list = DownloadList(self.common) + + # Download header downloads_label = QtWidgets.QLabel(strings._('gui_downloads', True)) downloads_label.setStyleSheet(self.common.css['downloads_uploads_label']) clear_button = QtWidgets.QPushButton(strings._('gui_clear_history', True)) @@ -118,10 +172,11 @@ class Downloads(QtWidgets.QWidget): download_header.addWidget(downloads_label) download_header.addStretch() download_header.addWidget(clear_button) - self.downloads_layout = QtWidgets.QVBoxLayout() + + # Download layout not_empty_layout = QtWidgets.QVBoxLayout() not_empty_layout.addLayout(download_header) - not_empty_layout.addLayout(self.downloads_layout) + not_empty_layout.addWidget(self.download_list) self.not_empty = QtWidgets.QWidget() self.not_empty.setLayout(not_empty_layout) @@ -141,13 +196,6 @@ class Downloads(QtWidgets.QWidget): self.vbar.rangeChanged.connect(self.resizeScroll) """ - def resizeEvent(self, event): - """ - When the widget resizes, resize the inner widget to match - """ - #self.empty.resize(self.width()-2, self.width()-2) - pass - def resizeScroll(self, minimum, maximum): """ Scroll to the bottom of the window when the range changes. @@ -164,30 +212,25 @@ class Downloads(QtWidgets.QWidget): self.not_empty.show() # Add it to the list - download = Download(self.common, download_id, total_bytes) - self.downloads[download_id] = download - self.downloads_layout.addWidget(download.progress_bar) + self.download_list.add(download_id, total_bytes) def update(self, download_id, downloaded_bytes): """ Update the progress of a download progress bar. """ - self.downloads[download_id].update(downloaded_bytes) + self.download_list.update(download_id, downloaded_bytes) def cancel(self, download_id): """ Update a download progress bar to show that it has been canceled. """ - self.downloads[download_id].cancel() + self.download_list.cancel(download_id) def reset(self): """ Reset the downloads back to zero """ - for download in self.downloads.values(): - self.downloads_layout.removeWidget(download.progress_bar) - download.progress_bar.close() - self.downloads = {} + self.download_list.reset() # Hide not empty, show empty self.not_empty.hide() From 9a05eef49495f7100f2103a3fcbfae6b0928b748 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 19:05:26 -0700 Subject: [PATCH 13/50] Slightly improve Downloads progress bar style, but still needs spacing --- onionshare/common.py | 2 +- onionshare_gui/share_mode/downloads.py | 13 ------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/onionshare/common.py b/onionshare/common.py index 3489c3e6..6662ca4e 100644 --- a/onionshare/common.py +++ b/onionshare/common.py @@ -285,7 +285,7 @@ class Common(object): background-color: #ffffff !important; text-align: center; color: #9b9b9b; - font-size: 12px; + font-size: 14px; } QProgressBar::chunk { background-color: #4e064f; diff --git a/onionshare_gui/share_mode/downloads.py b/onionshare_gui/share_mode/downloads.py index 855827b1..73e8faf5 100644 --- a/onionshare_gui/share_mode/downloads.py +++ b/onionshare_gui/share_mode/downloads.py @@ -190,19 +190,6 @@ class Downloads(QtWidgets.QWidget): # Reset once at the beginning self.reset() - """ - # Scroll bar - self.vbar = self.verticalScrollBar() - self.vbar.rangeChanged.connect(self.resizeScroll) - """ - - def resizeScroll(self, minimum, maximum): - """ - Scroll to the bottom of the window when the range changes. - """ - pass - #self.vbar.setValue(maximum) - def add(self, download_id, total_bytes): """ Add a new download progress bar. From e87263353f2cfae32eb965d2e5b8c1cdfc898e20 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 19:54:46 -0700 Subject: [PATCH 14/50] Added an indicator count for share mode --- onionshare/common.py | 10 ++++++++++ onionshare_gui/share_mode/__init__.py | 1 + onionshare_gui/share_mode/info.py | 26 ++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/onionshare/common.py b/onionshare/common.py index 6662ca4e..43a6ac43 100644 --- a/onionshare/common.py +++ b/onionshare/common.py @@ -279,6 +279,16 @@ class Common(object): } """, + 'download_uploads_indicator': """ + QLabel { + color: #ffffff; + background-color: #f44449; + font-weight: bold; + padding: 5px; + border-radius: 5px; + font-size: 10px; + }""", + 'downloads_uploads_progress_bar': """ QProgressBar { border: 1px solid #4e064f; diff --git a/onionshare_gui/share_mode/__init__.py b/onionshare_gui/share_mode/__init__.py index 0504b529..58801c45 100644 --- a/onionshare_gui/share_mode/__init__.py +++ b/onionshare_gui/share_mode/__init__.py @@ -224,6 +224,7 @@ class ShareMode(Mode): else: filesize = self.web.share_mode.download_filesize self.downloads.add(event["data"]["id"], filesize) + self.info.update_indicator(True) self.downloads_in_progress += 1 self.info.update_downloads_in_progress() diff --git a/onionshare_gui/share_mode/info.py b/onionshare_gui/share_mode/info.py index 3ee12a95..a191933d 100644 --- a/onionshare_gui/share_mode/info.py +++ b/onionshare_gui/share_mode/info.py @@ -51,12 +51,19 @@ class ShareModeInfo(QtWidgets.QWidget): self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle.png')) ) self.toggle_button.clicked.connect(self.toggle_downloads) + # Keep track of indicator + self.indicator_count = 0 + self.indicator_label = QtWidgets.QLabel() + self.indicator_label.setStyleSheet(self.common.css['download_uploads_indicator']) + self.update_indicator() + # Info layout layout = QtWidgets.QHBoxLayout() layout.addWidget(self.label) layout.addStretch() layout.addWidget(self.in_progress_downloads_count) layout.addWidget(self.completed_downloads_count) + layout.addWidget(self.indicator_label) layout.addWidget(self.toggle_button) self.setLayout(layout) @@ -70,6 +77,21 @@ class ShareModeInfo(QtWidgets.QWidget): self.label_text = s self.label.setText(self.label_text) + def update_indicator(self, increment=False): + """ + Update the display of the indicator count. If increment is True, then + only increment the counter if Downloads is hidden. + """ + if increment and not self.share_mode.downloads.isVisible(): + self.indicator_count += 1 + + self.indicator_label.setText("{}".format(self.indicator_count)) + + if self.indicator_count == 0: + self.indicator_label.hide() + else: + self.indicator_label.show() + def update_downloads_completed(self): """ Update the 'Downloads completed' info widget. @@ -107,6 +129,10 @@ class ShareModeInfo(QtWidgets.QWidget): self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle_selected.png')) ) self.toggle_button.setFlat(False) + # Reset the indicator count + self.indicator_count = 0 + self.update_indicator() + self.share_mode.resize_window() def show_less(self): From 709eeeac5f5805e63279ec68eeee5fde31ef345d Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 28 Sep 2018 22:03:48 -0700 Subject: [PATCH 15/50] Starting to implement the new Uploads UI, but not done --- onionshare_gui/receive_mode/__init__.py | 1 + onionshare_gui/receive_mode/info.py | 26 ++++ onionshare_gui/receive_mode/uploads.py | 191 ++++++++++++++++-------- onionshare_gui/share_mode/downloads.py | 2 + onionshare_gui/share_mode/info.py | 2 +- share/locale/en.json | 2 +- 6 files changed, 157 insertions(+), 67 deletions(-) diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/receive_mode/__init__.py index 83113805..2f61b2ca 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/receive_mode/__init__.py @@ -127,6 +127,7 @@ class ReceiveMode(Mode): Handle REQUEST_STARTED event. """ self.uploads.add(event["data"]["id"], event["data"]["content_length"]) + self.info.update_indicator(True) self.uploads_in_progress += 1 self.info.update_uploads_in_progress() diff --git a/onionshare_gui/receive_mode/info.py b/onionshare_gui/receive_mode/info.py index 0f5bc298..bc4aada8 100644 --- a/onionshare_gui/receive_mode/info.py +++ b/onionshare_gui/receive_mode/info.py @@ -46,17 +46,39 @@ class ReceiveModeInfo(QtWidgets.QWidget): self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle.png')) ) self.toggle_button.clicked.connect(self.toggle_uploads) + # Keep track of indicator + self.indicator_count = 0 + self.indicator_label = QtWidgets.QLabel() + self.indicator_label.setStyleSheet(self.common.css['download_uploads_indicator']) + self.update_indicator() + # Layout layout = QtWidgets.QHBoxLayout() layout.addStretch() layout.addWidget(self.in_progress_uploads_count) layout.addWidget(self.completed_uploads_count) + layout.addWidget(self.indicator_label) layout.addWidget(self.toggle_button) self.setLayout(layout) self.update_uploads_completed() self.update_uploads_in_progress() + def update_indicator(self, increment=False): + """ + Update the display of the indicator count. If increment is True, then + only increment the counter if Uploads is hidden. + """ + if increment and not self.receive_mode.uploads.isVisible(): + self.indicator_count += 1 + + self.indicator_label.setText("{}".format(self.indicator_count)) + + if self.indicator_count == 0: + self.indicator_label.hide() + else: + self.indicator_label.show() + def update_uploads_completed(self): """ Update the 'Uploads completed' info widget. @@ -94,6 +116,10 @@ class ReceiveModeInfo(QtWidgets.QWidget): self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle_selected.png')) ) self.toggle_button.setFlat(False) + # Reset the indicator count + self.indicator_count = 0 + self.update_indicator() + self.receive_mode.resize_window() def show_less(self): diff --git a/onionshare_gui/receive_mode/uploads.py b/onionshare_gui/receive_mode/uploads.py index 48574cc7..8cda2e61 100644 --- a/onionshare_gui/receive_mode/uploads.py +++ b/onionshare_gui/receive_mode/uploads.py @@ -206,69 +206,30 @@ class Upload(QtWidgets.QWidget): self.label.setText(text) -class Uploads(QtWidgets.QScrollArea): +class UploadList(QtWidgets.QListWidget): """ - The uploads chunk of the GUI. This lists all of the active upload - progress bars, as well as information about each upload. + List of upload progess bars. """ def __init__(self, common): - super(Uploads, self).__init__() + super(UploadList, self).__init__() self.common = common - self.common.log('Uploads', '__init__') - - self.resizeEvent = None self.uploads = {} - self.setWindowTitle(strings._('gui_uploads', True)) - self.setWidgetResizable(True) - self.setMinimumHeight(150) - self.setMinimumWidth(350) - self.setWindowIcon(QtGui.QIcon(common.get_resource_path('images/logo.png'))) - self.setWindowFlags(QtCore.Qt.Sheet | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.CustomizeWindowHint) - self.vbar = self.verticalScrollBar() - self.vbar.rangeChanged.connect(self.resizeScroll) - - uploads_label = QtWidgets.QLabel(strings._('gui_uploads', True)) - uploads_label.setStyleSheet(self.common.css['downloads_uploads_label']) - self.no_uploads_label = QtWidgets.QLabel(strings._('gui_no_uploads', True)) - self.clear_history_button = QtWidgets.QPushButton(strings._('gui_clear_history', True)) - self.clear_history_button.clicked.connect(self.reset) - self.clear_history_button.hide() - - - self.uploads_layout = QtWidgets.QVBoxLayout() - - widget = QtWidgets.QWidget() - layout = QtWidgets.QVBoxLayout() - layout.addWidget(uploads_label) - layout.addWidget(self.no_uploads_label) - layout.addWidget(self.clear_history_button) - layout.addLayout(self.uploads_layout) - layout.addStretch() - widget.setLayout(layout) - self.setWidget(widget) - - def resizeScroll(self, minimum, maximum): - """ - Scroll to the bottom of the window when the range changes. - """ - self.vbar.setValue(maximum) + self.setMinimumHeight(205) + self.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) + self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) def add(self, upload_id, content_length): """ - Add a new upload. + Add a new upload progress bar. """ - self.common.log('Uploads', 'add', 'upload_id: {}, content_length: {}'.format(upload_id, content_length)) - # Hide the no_uploads_label - self.no_uploads_label.hide() - # Show the clear_history_button - self.clear_history_button.show() - - # Add it to the list upload = Upload(self.common, upload_id, content_length) self.uploads[upload_id] = upload - self.uploads_layout.addWidget(upload) + + item = QtWidgets.QListWidgetItem() + self.addItem(item) + self.setItemWidget(item, upload) def update(self, upload_id, progress): """ @@ -299,22 +260,122 @@ class Uploads(QtWidgets.QScrollArea): """ Reset the uploads back to zero """ - self.common.log('Uploads', 'reset') + # Remove all items from list + while True: + item = self.takeItem(0) + if not item: + break + + # Close all progress bars for upload in self.uploads.values(): - upload.close() - self.uploads_layout.removeWidget(upload) + upload.progress_bar.close() self.uploads = {} - self.no_uploads_label.show() - self.clear_history_button.hide() - self.resize(self.sizeHint()) - def resizeEvent(self, event): - width = self.frameGeometry().width() - try: - for upload in self.uploads.values(): - for item in upload.files.values(): - item.filename_label.setText(textwrap.fill(item.filename, 30)) - item.adjustSize() - except: - pass +class Uploads(QtWidgets.QWidget): + """ + The uploads chunk of the GUI. This lists all of the active upload + progress bars, as well as information about each upload. + """ + def __init__(self, common): + super(Uploads, self).__init__() + self.common = common + self.common.log('Uploads', '__init__') + + self.setMinimumWidth(350) + + # When there are no uploads + empty_image = QtWidgets.QLabel() + empty_image.setAlignment(QtCore.Qt.AlignCenter) + empty_image.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/uploads_transparent.png')))) + empty_text = QtWidgets.QLabel(strings._('gui_no_uploads', True)) + empty_text.setAlignment(QtCore.Qt.AlignCenter) + empty_text.setStyleSheet(self.common.css['downloads_uploads_empty_text']) + empty_layout = QtWidgets.QVBoxLayout() + empty_layout.addStretch() + empty_layout.addWidget(empty_image) + empty_layout.addWidget(empty_text) + empty_layout.addStretch() + self.empty = QtWidgets.QWidget() + self.empty.setStyleSheet(self.common.css['downloads_uploads_empty']) + self.empty.setLayout(empty_layout) + + # When there are uploads + self.upload_list = UploadList(self.common) + + # Upload header + uploads_label = QtWidgets.QLabel(strings._('gui_uploads', True)) + uploads_label.setStyleSheet(self.common.css['downloads_uploads_label']) + clear_button = QtWidgets.QPushButton(strings._('gui_clear_history', True)) + clear_button.setStyleSheet(self.common.css['downloads_uploads_clear']) + clear_button.setFlat(True) + clear_button.clicked.connect(self.reset) + upload_header = QtWidgets.QHBoxLayout() + upload_header.addWidget(uploads_label) + upload_header.addStretch() + upload_header.addWidget(clear_button) + + # Upload layout + not_empty_layout = QtWidgets.QVBoxLayout() + not_empty_layout.addLayout(upload_header) + not_empty_layout.addWidget(self.upload_list) + self.not_empty = QtWidgets.QWidget() + self.not_empty.setLayout(not_empty_layout) + + # Layout + layout = QtWidgets.QVBoxLayout() + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(self.empty) + layout.addWidget(self.not_empty) + self.setLayout(layout) + + # Reset once at the beginning + self.reset() + + def add(self, upload_id, content_length): + """ + Add a new upload. + """ + self.common.log('Uploads', 'add', 'upload_id: {}, content_length: {}'.format(upload_id, content_length)) + + # Hide empty, show not empty + self.empty.hide() + self.not_empty.show() + + # Add it to the list + self.upload_list.add(upload_id, content_length) + + def update(self, upload_id, progress): + """ + Update the progress of an upload. + """ + self.upload_list.update(upload_id, progress) + + def rename(self, upload_id, old_filename, new_filename): + """ + Rename a file, which happens if the filename already exists in downloads_dir. + """ + self.upload_list.rename(upload_id, old_filename, new_filename) + + def finished(self, upload_id): + """ + An upload has finished. + """ + self.upload_list.finished(upload_id) + + def cancel(self, upload_id): + """ + Update an upload progress bar to show that it has been canceled. + """ + self.common.log('Uploads', 'cancel', 'upload_id: {}'.format(upload_id)) + self.upload_list.cancel(upload_id) + + def reset(self): + """ + Reset the uploads back to zero + """ + self.upload_list.reset() + + # Hide not empty, show empty + self.not_empty.hide() + self.empty.show() diff --git a/onionshare_gui/share_mode/downloads.py b/onionshare_gui/share_mode/downloads.py index 73e8faf5..bb2376ef 100644 --- a/onionshare_gui/share_mode/downloads.py +++ b/onionshare_gui/share_mode/downloads.py @@ -194,6 +194,8 @@ class Downloads(QtWidgets.QWidget): """ Add a new download progress bar. """ + self.common.log('Downloads', 'add', 'download_id: {}, content_length: {}'.format(download_id, content_length)) + # Hide empty, show not empty self.empty.hide() self.not_empty.show() diff --git a/onionshare_gui/share_mode/info.py b/onionshare_gui/share_mode/info.py index a191933d..f8a68df7 100644 --- a/onionshare_gui/share_mode/info.py +++ b/onionshare_gui/share_mode/info.py @@ -57,7 +57,7 @@ class ShareModeInfo(QtWidgets.QWidget): self.indicator_label.setStyleSheet(self.common.css['download_uploads_indicator']) self.update_indicator() - # Info layout + # Layout layout = QtWidgets.QHBoxLayout() layout.addWidget(self.label) layout.addStretch() diff --git a/share/locale/en.json b/share/locale/en.json index 5821eea2..c7beb6ba 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -175,7 +175,7 @@ "systray_download_page_loaded_message": "A user loaded the download page", "systray_upload_page_loaded_message": "A user loaded the upload page", "gui_uploads": "Upload History", - "gui_no_uploads": "No uploads yet.", + "gui_no_uploads": "No Uploads Yet", "gui_clear_history": "Clear All", "gui_upload_in_progress": "Upload Started {}", "gui_upload_finished_range": "Uploaded {} to {}", From 4aed7c0f9d1f272b9bd408cea6752cc4a115dc5b Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sat, 29 Sep 2018 12:00:22 -0700 Subject: [PATCH 16/50] Use correct variable name for Downloads --- onionshare_gui/share_mode/downloads.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/onionshare_gui/share_mode/downloads.py b/onionshare_gui/share_mode/downloads.py index bb2376ef..e567443a 100644 --- a/onionshare_gui/share_mode/downloads.py +++ b/onionshare_gui/share_mode/downloads.py @@ -92,11 +92,11 @@ class DownloadList(QtWidgets.QListWidget): self.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) - def add(self, download_id, total_bytes): + def add(self, download_id, content_length): """ Add a new download progress bar. """ - download = Download(self.common, download_id, total_bytes) + download = Download(self.common, download_id, content_length) self.downloads[download_id] = download item = QtWidgets.QListWidgetItem() @@ -190,7 +190,7 @@ class Downloads(QtWidgets.QWidget): # Reset once at the beginning self.reset() - def add(self, download_id, total_bytes): + def add(self, download_id, content_length): """ Add a new download progress bar. """ @@ -201,7 +201,7 @@ class Downloads(QtWidgets.QWidget): self.not_empty.show() # Add it to the list - self.download_list.add(download_id, total_bytes) + self.download_list.add(download_id, content_length) def update(self, download_id, downloaded_bytes): """ From ffad77930f881de67381cbf9de12fadacdcc17df Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sat, 29 Sep 2018 12:19:01 -0700 Subject: [PATCH 17/50] Switch Downloads from QListWidget to QScrollArea --- onionshare_gui/share_mode/downloads.py | 44 ++++++++++++++++---------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/onionshare_gui/share_mode/downloads.py b/onionshare_gui/share_mode/downloads.py index e567443a..8eade23c 100644 --- a/onionshare_gui/share_mode/downloads.py +++ b/onionshare_gui/share_mode/downloads.py @@ -23,8 +23,9 @@ from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings -class Download(object): +class Download(QtWidgets.QWidget): def __init__(self, common, download_id, total_bytes): + super(Download, self).__init__() self.common = common self.download_id = download_id @@ -32,6 +33,8 @@ class Download(object): self.total_bytes = total_bytes self.downloaded_bytes = 0 + self.setStyleSheet('QWidget { border: 1px solid red; }') + # Progress bar self.progress_bar = QtWidgets.QProgressBar() self.progress_bar.setTextVisible(True) @@ -43,6 +46,11 @@ class Download(object): self.progress_bar.setStyleSheet(self.common.css['downloads_uploads_progress_bar']) self.progress_bar.total_bytes = total_bytes + # Layout + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.progress_bar) + self.setLayout(layout) + # Start at 0 self.update(0) @@ -78,9 +86,9 @@ class Download(object): self.started) -class DownloadList(QtWidgets.QListWidget): +class DownloadList(QtWidgets.QScrollArea): """ - List of download progess bars. + List of download progress bars. """ def __init__(self, common): super(DownloadList, self).__init__() @@ -88,9 +96,20 @@ class DownloadList(QtWidgets.QListWidget): self.downloads = {} - self.setMinimumHeight(205) - self.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) - self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) + self.downloads_layout = QtWidgets.QVBoxLayout() + self.downloads_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize) + widget = QtWidgets.QWidget() + widget.setLayout(self.downloads_layout) + self.setWidget(widget) + + self.setBackgroundRole(QtGui.QPalette.Light) + self.verticalScrollBar().rangeChanged.connect(self.resizeScroll) + + def resizeScroll(self, minimum, maximum): + """ + Scroll to the bottom of the window when the range changes. + """ + self.verticalScrollBar().setValue(maximum) def add(self, download_id, content_length): """ @@ -98,10 +117,7 @@ class DownloadList(QtWidgets.QListWidget): """ download = Download(self.common, download_id, content_length) self.downloads[download_id] = download - - item = QtWidgets.QListWidgetItem() - self.addItem(item) - self.setItemWidget(item, download.progress_bar) + self.downloads_layout.addWidget(download) def update(self, download_id, downloaded_bytes): """ @@ -119,14 +135,8 @@ class DownloadList(QtWidgets.QListWidget): """ Reset the downloads back to zero """ - # Remove all items from list - while True: - item = self.takeItem(0) - if not item: - break - - # Close all progress bars for download in self.downloads.values(): + self.downloads_layout.removeWidget(download.progress_bar) download.progress_bar.close() self.downloads = {} From d87115d21e8fc11979e416b9308019c9a7866bfe Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sat, 29 Sep 2018 13:41:12 -0700 Subject: [PATCH 18/50] Fix Downloads scroll area so internal widget is always the right size --- onionshare_gui/share_mode/downloads.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/onionshare_gui/share_mode/downloads.py b/onionshare_gui/share_mode/downloads.py index 8eade23c..50e7f0ef 100644 --- a/onionshare_gui/share_mode/downloads.py +++ b/onionshare_gui/share_mode/downloads.py @@ -96,12 +96,24 @@ class DownloadList(QtWidgets.QScrollArea): self.downloads = {} + # The layout that holds all of the downloads self.downloads_layout = QtWidgets.QVBoxLayout() + self.downloads_layout.setContentsMargins(0, 0, 0, 0) self.downloads_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize) - widget = QtWidgets.QWidget() - widget.setLayout(self.downloads_layout) - self.setWidget(widget) + # Wrapper layout that also contains a stretch + wrapper_layout = QtWidgets.QVBoxLayout() + wrapper_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize) + wrapper_layout.addLayout(self.downloads_layout) + wrapper_layout.addStretch() + + # The internal widget of the scroll area + widget = QtWidgets.QWidget() + widget.setLayout(wrapper_layout) + self.setWidget(widget) + self.setWidgetResizable(True) + + # Other scroll area settings self.setBackgroundRole(QtGui.QPalette.Light) self.verticalScrollBar().rangeChanged.connect(self.resizeScroll) From fa4ebbf263f02a07315972b805fd111e19463550 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sat, 29 Sep 2018 13:47:00 -0700 Subject: [PATCH 19/50] Convert Uploads to a QScrollArea also --- onionshare_gui/receive_mode/uploads.py | 44 +++++++++++++++++--------- onionshare_gui/share_mode/downloads.py | 2 +- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/onionshare_gui/receive_mode/uploads.py b/onionshare_gui/receive_mode/uploads.py index 8cda2e61..f08b35cc 100644 --- a/onionshare_gui/receive_mode/uploads.py +++ b/onionshare_gui/receive_mode/uploads.py @@ -206,7 +206,7 @@ class Upload(QtWidgets.QWidget): self.label.setText(text) -class UploadList(QtWidgets.QListWidget): +class UploadList(QtWidgets.QScrollArea): """ List of upload progess bars. """ @@ -216,9 +216,32 @@ class UploadList(QtWidgets.QListWidget): self.uploads = {} - self.setMinimumHeight(205) - self.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) - self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) + # The layout that holds all of the uploads + self.uploads_layout = QtWidgets.QVBoxLayout() + self.uploads_layout.setContentsMargins(0, 0, 0, 0) + self.uploads_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize) + + # Wrapper layout that also contains a stretch + wrapper_layout = QtWidgets.QVBoxLayout() + wrapper_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize) + wrapper_layout.addLayout(self.uploads_layout) + wrapper_layout.addStretch() + + # The internal widget of the scroll area + widget = QtWidgets.QWidget() + widget.setLayout(wrapper_layout) + self.setWidget(widget) + self.setWidgetResizable(True) + + # Other scroll area settings + self.setBackgroundRole(QtGui.QPalette.Light) + self.verticalScrollBar().rangeChanged.connect(self.resizeScroll) + + def resizeScroll(self, minimum, maximum): + """ + Scroll to the bottom of the window when the range changes. + """ + self.verticalScrollBar().setValue(maximum) def add(self, upload_id, content_length): """ @@ -226,10 +249,7 @@ class UploadList(QtWidgets.QListWidget): """ upload = Upload(self.common, upload_id, content_length) self.uploads[upload_id] = upload - - item = QtWidgets.QListWidgetItem() - self.addItem(item) - self.setItemWidget(item, upload) + self.uploads_layout.addWidget(upload) def update(self, upload_id, progress): """ @@ -260,14 +280,8 @@ class UploadList(QtWidgets.QListWidget): """ Reset the uploads back to zero """ - # Remove all items from list - while True: - item = self.takeItem(0) - if not item: - break - - # Close all progress bars for upload in self.uploads.values(): + self.uploads_layout.removeWidget(upload) upload.progress_bar.close() self.uploads = {} diff --git a/onionshare_gui/share_mode/downloads.py b/onionshare_gui/share_mode/downloads.py index 50e7f0ef..e78231ad 100644 --- a/onionshare_gui/share_mode/downloads.py +++ b/onionshare_gui/share_mode/downloads.py @@ -148,7 +148,7 @@ class DownloadList(QtWidgets.QScrollArea): Reset the downloads back to zero """ for download in self.downloads.values(): - self.downloads_layout.removeWidget(download.progress_bar) + self.downloads_layout.removeWidget(download) download.progress_bar.close() self.downloads = {} From 4b3a68bb655c20ab2ccd6bfe8f9c492bcbd02ea9 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sat, 29 Sep 2018 14:40:55 -0700 Subject: [PATCH 20/50] Got the indicator label to display in the correct location for share mode --- onionshare/common.py | 5 +++-- onionshare_gui/share_mode/info.py | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/onionshare/common.py b/onionshare/common.py index 43a6ac43..fb3b1e7a 100644 --- a/onionshare/common.py +++ b/onionshare/common.py @@ -284,9 +284,10 @@ class Common(object): color: #ffffff; background-color: #f44449; font-weight: bold; - padding: 5px; - border-radius: 5px; font-size: 10px; + padding: 2px; + border-radius: 8px; + text-align: center; }""", 'downloads_uploads_progress_bar': """ diff --git a/onionshare_gui/share_mode/info.py b/onionshare_gui/share_mode/info.py index f8a68df7..b69820d6 100644 --- a/onionshare_gui/share_mode/info.py +++ b/onionshare_gui/share_mode/info.py @@ -45,7 +45,7 @@ class ShareModeInfo(QtWidgets.QWidget): # Toggle button self.toggle_button = QtWidgets.QPushButton() self.toggle_button.setDefault(False) - self.toggle_button.setFixedWidth(30) + self.toggle_button.setFixedWidth(35) self.toggle_button.setFixedHeight(30) self.toggle_button.setFlat(True) self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle.png')) ) @@ -53,17 +53,24 @@ class ShareModeInfo(QtWidgets.QWidget): # Keep track of indicator self.indicator_count = 0 - self.indicator_label = QtWidgets.QLabel() + self.indicator_label = QtWidgets.QLabel(parent=self.toggle_button) self.indicator_label.setStyleSheet(self.common.css['download_uploads_indicator']) self.update_indicator() + """ + # Add it to the toggle button + toggle_button_layout = QtWidgets.QHBoxLayout() + toggle_button_layout.addSpacing(10) + toggle_button_layout.addWidget(self.indicator_label) + self.toggle_button.setLayout(toggle_button_layout) + """ + # Layout layout = QtWidgets.QHBoxLayout() layout.addWidget(self.label) layout.addStretch() layout.addWidget(self.in_progress_downloads_count) layout.addWidget(self.completed_downloads_count) - layout.addWidget(self.indicator_label) layout.addWidget(self.toggle_button) self.setLayout(layout) @@ -90,6 +97,8 @@ class ShareModeInfo(QtWidgets.QWidget): if self.indicator_count == 0: self.indicator_label.hide() else: + size = self.indicator_label.sizeHint() + self.indicator_label.setGeometry(35-size.width(), 0, size.width(), size.height()) self.indicator_label.show() def update_downloads_completed(self): From b4de634b7ac3a12450bc99a5e962dab16f486778 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sat, 29 Sep 2018 14:43:13 -0700 Subject: [PATCH 21/50] Fix indicator label display for receive mode --- onionshare_gui/receive_mode/info.py | 7 ++++--- onionshare_gui/share_mode/info.py | 8 -------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/onionshare_gui/receive_mode/info.py b/onionshare_gui/receive_mode/info.py index bc4aada8..c23f8496 100644 --- a/onionshare_gui/receive_mode/info.py +++ b/onionshare_gui/receive_mode/info.py @@ -40,7 +40,7 @@ class ReceiveModeInfo(QtWidgets.QWidget): # Toggle button self.toggle_button = QtWidgets.QPushButton() self.toggle_button.setDefault(False) - self.toggle_button.setFixedWidth(30) + self.toggle_button.setFixedWidth(35) self.toggle_button.setFixedHeight(30) self.toggle_button.setFlat(True) self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle.png')) ) @@ -48,7 +48,7 @@ class ReceiveModeInfo(QtWidgets.QWidget): # Keep track of indicator self.indicator_count = 0 - self.indicator_label = QtWidgets.QLabel() + self.indicator_label = QtWidgets.QLabel(parent=self.toggle_button) self.indicator_label.setStyleSheet(self.common.css['download_uploads_indicator']) self.update_indicator() @@ -57,7 +57,6 @@ class ReceiveModeInfo(QtWidgets.QWidget): layout.addStretch() layout.addWidget(self.in_progress_uploads_count) layout.addWidget(self.completed_uploads_count) - layout.addWidget(self.indicator_label) layout.addWidget(self.toggle_button) self.setLayout(layout) @@ -77,6 +76,8 @@ class ReceiveModeInfo(QtWidgets.QWidget): if self.indicator_count == 0: self.indicator_label.hide() else: + size = self.indicator_label.sizeHint() + self.indicator_label.setGeometry(35-size.width(), 0, size.width(), size.height()) self.indicator_label.show() def update_uploads_completed(self): diff --git a/onionshare_gui/share_mode/info.py b/onionshare_gui/share_mode/info.py index b69820d6..c692649c 100644 --- a/onionshare_gui/share_mode/info.py +++ b/onionshare_gui/share_mode/info.py @@ -57,14 +57,6 @@ class ShareModeInfo(QtWidgets.QWidget): self.indicator_label.setStyleSheet(self.common.css['download_uploads_indicator']) self.update_indicator() - """ - # Add it to the toggle button - toggle_button_layout = QtWidgets.QHBoxLayout() - toggle_button_layout.addSpacing(10) - toggle_button_layout.addWidget(self.indicator_label) - self.toggle_button.setLayout(toggle_button_layout) - """ - # Layout layout = QtWidgets.QHBoxLayout() layout.addWidget(self.label) From 8ca34fadd9895b7e2b16c13e5d315cc40e396c97 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sat, 29 Sep 2018 14:49:06 -0700 Subject: [PATCH 22/50] Fix crash when clicking Help from the systray --- onionshare_gui/onionshare_gui.py | 2 +- onionshare_gui/settings_dialog.py | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 51190ea3..dd15fe12 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -65,7 +65,7 @@ class OnionShareGui(QtWidgets.QMainWindow): 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) + help_action.triggered.connect(SettingsDialog.open_help) exit_action = menu.addAction(strings._('systray_menu_exit', True)) exit_action.triggered.connect(self.close) diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index 3cd25d31..39f08128 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -883,8 +883,12 @@ class SettingsDialog(QtWidgets.QDialog): Help button clicked. """ self.common.log('SettingsDialog', 'help_clicked') - help_site = 'https://github.com/micahflee/onionshare/wiki' - QtGui.QDesktopServices.openUrl(QtCore.QUrl(help_site)) + SettingsDialog.open_help() + + @staticmethod + def open_help(): + help_url = 'https://github.com/micahflee/onionshare/wiki' + QtGui.QDesktopServices.openUrl(QtCore.QUrl(help_url)) def settings_from_fields(self): """ From 39dd0862d4c02391fa32bf5fd97b0ec721425abb Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sat, 29 Sep 2018 15:12:05 -0700 Subject: [PATCH 23/50] Increase minimum window with to 460, and store it in a variable to stop repeating myself --- onionshare_gui/mode.py | 4 ++-- onionshare_gui/onionshare_gui.py | 4 +++- onionshare_gui/receive_mode/__init__.py | 2 +- onionshare_gui/share_mode/__init__.py | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/onionshare_gui/mode.py b/onionshare_gui/mode.py index 0fba029b..1a961149 100644 --- a/onionshare_gui/mode.py +++ b/onionshare_gui/mode.py @@ -50,7 +50,7 @@ class Mode(QtWidgets.QWidget): self.filenames = filenames - self.setMinimumWidth(450) + self.setMinimumWidth(self.common.min_window_width) # The web object gets created in init() self.web = None @@ -83,7 +83,7 @@ class Mode(QtWidgets.QWidget): # Hack to allow a minimum width on the main layout # Note: It's up to the downstream Mode to add this to its layout self.min_width_widget = QtWidgets.QWidget() - self.min_width_widget.setMinimumWidth(450) + self.min_width_widget.setMinimumWidth(self.common.min_window_width) def init(self): """ diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index dd15fe12..ced53ede 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -45,6 +45,7 @@ class OnionShareGui(QtWidgets.QMainWindow): self.common = common self.common.log('OnionShareGui', '__init__') + self.common.min_window_width = 460 self.onion = onion self.qtapp = qtapp @@ -169,7 +170,7 @@ class OnionShareGui(QtWidgets.QMainWindow): self.show() # Adjust window size, to start with a minimum window width - self.adjust_size(450) + self.adjust_size(self.common.min_window_width) # The server isn't active yet self.set_server_active(False) @@ -474,6 +475,7 @@ class OnionShareGui(QtWidgets.QMainWindow): # Adjust sizes of each mode for mode in [self.share_mode, self.receive_mode]: + self.qtapp.processEvents() adjust_size_widget(mode) # Adjust window size diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/receive_mode/__init__.py index 2f61b2ca..6430382b 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/receive_mode/__init__.py @@ -194,7 +194,7 @@ class ReceiveMode(Mode): self.resize_window() def resize_window(self): - min_width = 450 + min_width = self.common.min_window_width if self.uploads.isVisible(): min_width += 300 self.adjust_size.emit(min_width) diff --git a/onionshare_gui/share_mode/__init__.py b/onionshare_gui/share_mode/__init__.py index 58801c45..c44e8beb 100644 --- a/onionshare_gui/share_mode/__init__.py +++ b/onionshare_gui/share_mode/__init__.py @@ -317,7 +317,7 @@ class ShareMode(Mode): self.downloads.reset() def resize_window(self): - min_width = 450 + min_width = self.common.min_window_width if self.downloads.isVisible(): min_width += 300 self.adjust_size.emit(min_width) From 4710eaee4c35b46e4117021bf197a2f9aa07b666 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sat, 29 Sep 2018 18:24:11 -0700 Subject: [PATCH 24/50] Fix local GUI tests so they pass --- tests_gui_local/commontests.py | 47 +++++++++------ .../onionshare_receive_mode_upload_test.py | 12 ++-- ...re_receive_mode_upload_test_public_mode.py | 22 ++++--- .../onionshare_share_mode_download_test.py | 52 ++++++++++------- ...re_share_mode_download_test_public_mode.py | 52 ++++++++++------- ...hare_share_mode_download_test_stay_open.py | 58 +++++++++++-------- .../onionshare_slug_persistent_test.py | 42 ++++++++------ tests_gui_local/onionshare_timer_test.py | 8 +-- 8 files changed, 171 insertions(+), 122 deletions(-) diff --git a/tests_gui_local/commontests.py b/tests_gui_local/commontests.py index de1ad9ab..870c2dbe 100644 --- a/tests_gui_local/commontests.py +++ b/tests_gui_local/commontests.py @@ -24,19 +24,13 @@ class CommonTests(object): '''Test that the status bar is visible''' self.assertTrue(self.gui.status_bar.isVisible()) - def test_info_widget_is_not_visible(self, mode): - '''Test that the info widget along top of screen is not shown''' - if mode == 'receive': - self.assertFalse(self.gui.receive_mode.info_widget.isVisible()) + def test_info_widget_shows_less(self, mode): + '''Test that minimum information (no label) is displayed in the info bar''' if mode == 'share': - self.assertFalse(self.gui.share_mode.info_widget.isVisible()) - - def test_info_widget_is_visible(self, mode): - '''Test that the info widget along top of screen is shown''' + self.assertFalse(self.gui.share_mode.info.label.text() == "") if mode == 'receive': - self.assertTrue(self.gui.receive_mode.info_widget.isVisible()) - if mode == 'share': - self.assertTrue(self.gui.share_mode.info_widget.isVisible()) + # There's no minimal display in receive mode + self.assertTrue(False) def test_click_mode(self, mode): '''Test that we can switch Mode by clicking the button''' @@ -47,14 +41,30 @@ class CommonTests(object): QtTest.QTest.mouseClick(self.gui.share_mode_button, QtCore.Qt.LeftButton) self.assertTrue(self.gui.mode, self.gui.MODE_SHARE) + def test_click_toggle_history(self, mode): + '''Test that we can toggle Download or Upload history by clicking the toggle button''' + if mode == 'receive': + currently_visible = self.gui.receive_mode.uploads.isVisible() + QtTest.QTest.mouseClick(self.gui.receive_mode.info.toggle_button, QtCore.Qt.LeftButton) + self.assertEqual(self.gui.receive_mode.uploads.isVisible(), not currently_visible) + if mode == 'share': + currently_visible = self.gui.receive_mode.uploads.isVisible() + QtTest.QTest.mouseClick(self.gui.share_mode.info.toggle_button, QtCore.Qt.LeftButton) + self.assertEqual(self.gui.share_mode.downloads.isVisible(), not currently_visible) + + def test_history_is_not_visible(self, mode): + '''Test that the History section is not visible''' + if mode == 'receive': + self.assertFalse(self.gui.receive_mode.uploads.isVisible()) + if mode == 'share': + self.assertFalse(self.gui.share_mode.downloads.isVisible()) + def test_history_is_visible(self, mode): - '''Test that the History section is visible and that the relevant widget is present''' + '''Test that the History section is visible''' if mode == 'receive': self.assertTrue(self.gui.receive_mode.uploads.isVisible()) - self.assertTrue(self.gui.receive_mode.uploads.no_uploads_label.isVisible()) if mode == 'share': self.assertTrue(self.gui.share_mode.downloads.isVisible()) - self.assertTrue(self.gui.share_mode.downloads.no_downloads_label.isVisible()) def test_server_working_on_start_button_pressed(self, mode): '''Test we can start the service''' @@ -161,11 +171,11 @@ class CommonTests(object): def test_history_widgets_present(self, mode): '''Test that the relevant widgets are present in the history view after activity has taken place''' if mode == 'receive': - self.assertFalse(self.gui.receive_mode.uploads.no_uploads_label.isVisible()) - self.assertTrue(self.gui.receive_mode.uploads.clear_history_button.isVisible()) + self.assertFalse(self.gui.receive_mode.uploads.empty.isVisible()) + self.assertTrue(self.gui.receive_mode.uploads.not_empty.isVisible()) if mode == 'share': - self.assertFalse(self.gui.share_mode.downloads.no_downloads_label.isVisible()) - self.assertTrue(self.gui.share_mode.downloads.clear_history_button.isVisible()) + self.assertFalse(self.gui.share_mode.downloads.empty.isVisible()) + self.assertTrue(self.gui.share_mode.downloads.not_empty.isVisible()) def test_counter_incremented(self, mode, count): '''Test that the counter has incremented''' @@ -304,4 +314,3 @@ class CommonTests(object): def test_add_button_visible(self): '''Test that the add button should be visible''' self.assertTrue(self.gui.share_mode.server_status.file_selection.add_button.isVisible()) - diff --git a/tests_gui_local/onionshare_receive_mode_upload_test.py b/tests_gui_local/onionshare_receive_mode_upload_test.py index 2aa2ed94..b53d5c06 100644 --- a/tests_gui_local/onionshare_receive_mode_upload_test.py +++ b/tests_gui_local/onionshare_receive_mode_upload_test.py @@ -94,15 +94,19 @@ class OnionShareGuiTest(unittest.TestCase): def test_server_status_bar_is_visible(self): CommonTests.test_server_status_bar_is_visible(self) - @pytest.mark.run(order=5) - def test_info_widget_is_not_visible(self): - CommonTests.test_info_widget_is_not_visible(self, 'receive') - @pytest.mark.run(order=6) def test_click_mode(self): CommonTests.test_click_mode(self, 'receive') + @pytest.mark.run(order=6) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'receive') + @pytest.mark.run(order=7) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'receive') + + @pytest.mark.run(order=8) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'receive') diff --git a/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py b/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py index 30a290e7..5e5a6b77 100644 --- a/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py +++ b/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py @@ -95,34 +95,38 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_server_status_bar_is_visible(self) @pytest.mark.run(order=5) - def test_info_widget_is_not_visible(self): - CommonTests.test_info_widget_is_not_visible(self, 'receive') - - @pytest.mark.run(order=6) def test_click_mode(self): CommonTests.test_click_mode(self, 'receive') + @pytest.mark.run(order=6) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'receive') + @pytest.mark.run(order=7) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'receive') + + @pytest.mark.run(order=8) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'receive') - @pytest.mark.run(order=8) + @pytest.mark.run(order=9) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'receive') - @pytest.mark.run(order=9) + @pytest.mark.run(order=10) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'receive') - @pytest.mark.run(order=10) + @pytest.mark.run(order=11) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=12) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'receive') - @pytest.mark.run(order=12) + @pytest.mark.run(order=13) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) diff --git a/tests_gui_local/onionshare_share_mode_download_test.py b/tests_gui_local/onionshare_share_mode_download_test.py index c546fb61..40df6d98 100644 --- a/tests_gui_local/onionshare_share_mode_download_test.py +++ b/tests_gui_local/onionshare_share_mode_download_test.py @@ -97,90 +97,98 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_file_selection_widget_has_a_file(self) @pytest.mark.run(order=6) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) def test_add_a_file_and_delete_using_its_delete_widget(self): CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) - @pytest.mark.run(order=10) + @pytest.mark.run(order=12) def test_file_selection_widget_readd_files(self): CommonTests.test_file_selection_widget_readd_files(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=19) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', False) - @pytest.mark.run(order=18) + @pytest.mark.run(order=20) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'share') - @pytest.mark.run(order=19) + @pytest.mark.run(order=21) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'share') - @pytest.mark.run(order=20) + @pytest.mark.run(order=22) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=21) + @pytest.mark.run(order=23) def test_web_page(self): CommonTests.test_web_page(self, 'share', 'Total size', False) - @pytest.mark.run(order=22) + @pytest.mark.run(order=24) def test_download_share(self): CommonTests.test_download_share(self, False) - @pytest.mark.run(order=23) + @pytest.mark.run(order=25) def test_history_widgets_present(self): CommonTests.test_history_widgets_present(self, 'share') - @pytest.mark.run(order=24) + @pytest.mark.run(order=26) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', False) - @pytest.mark.run(order=25) + @pytest.mark.run(order=27) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=26) + @pytest.mark.run(order=28) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'share', False) - @pytest.mark.run(order=27) + @pytest.mark.run(order=29) def test_add_button_visible(self): CommonTests.test_add_button_visible(self) diff --git a/tests_gui_local/onionshare_share_mode_download_test_public_mode.py b/tests_gui_local/onionshare_share_mode_download_test_public_mode.py index 764b5885..73d4c999 100644 --- a/tests_gui_local/onionshare_share_mode_download_test_public_mode.py +++ b/tests_gui_local/onionshare_share_mode_download_test_public_mode.py @@ -97,90 +97,98 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_file_selection_widget_has_a_file(self) @pytest.mark.run(order=6) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) def test_add_a_file_and_delete_using_its_delete_widget(self): CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) - @pytest.mark.run(order=10) + @pytest.mark.run(order=12) def test_file_selection_widget_readd_files(self): CommonTests.test_file_selection_widget_readd_files(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=19) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', True) - @pytest.mark.run(order=18) + @pytest.mark.run(order=20) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'share') - @pytest.mark.run(order=19) + @pytest.mark.run(order=21) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'share') - @pytest.mark.run(order=20) + @pytest.mark.run(order=22) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=21) + @pytest.mark.run(order=23) def test_web_page(self): CommonTests.test_web_page(self, 'share', 'Total size', True) - @pytest.mark.run(order=22) + @pytest.mark.run(order=24) def test_download_share(self): CommonTests.test_download_share(self, True) - @pytest.mark.run(order=23) + @pytest.mark.run(order=25) def test_history_widgets_present(self): CommonTests.test_history_widgets_present(self, 'share') - @pytest.mark.run(order=24) + @pytest.mark.run(order=26) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', False) - @pytest.mark.run(order=25) + @pytest.mark.run(order=27) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=26) + @pytest.mark.run(order=28) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'share', False) - @pytest.mark.run(order=27) + @pytest.mark.run(order=29) def test_add_button_visible(self): CommonTests.test_add_button_visible(self) diff --git a/tests_gui_local/onionshare_share_mode_download_test_stay_open.py b/tests_gui_local/onionshare_share_mode_download_test_stay_open.py index b92ff097..e849d224 100644 --- a/tests_gui_local/onionshare_share_mode_download_test_stay_open.py +++ b/tests_gui_local/onionshare_share_mode_download_test_stay_open.py @@ -97,102 +97,110 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_file_selection_widget_has_a_file(self) @pytest.mark.run(order=6) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) def test_add_a_file_and_delete_using_its_delete_widget(self): CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) - @pytest.mark.run(order=10) + @pytest.mark.run(order=12) def test_file_selection_widget_readd_files(self): CommonTests.test_file_selection_widget_readd_files(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=19) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', True) - @pytest.mark.run(order=18) + @pytest.mark.run(order=20) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'share') - @pytest.mark.run(order=19) + @pytest.mark.run(order=21) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'share') - @pytest.mark.run(order=20) + @pytest.mark.run(order=22) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=21) + @pytest.mark.run(order=23) def test_web_page(self): CommonTests.test_web_page(self, 'share', 'Total size', True) - @pytest.mark.run(order=22) + @pytest.mark.run(order=24) def test_download_share(self): CommonTests.test_download_share(self, True) - @pytest.mark.run(order=23) + @pytest.mark.run(order=25) def test_history_widgets_present(self): CommonTests.test_history_widgets_present(self, 'share') - @pytest.mark.run(order=24) + @pytest.mark.run(order=26) def test_counter_incremented(self): CommonTests.test_counter_incremented(self, 'share', 1) - @pytest.mark.run(order=25) + @pytest.mark.run(order=27) def test_download_share_again(self): CommonTests.test_download_share(self, True) - @pytest.mark.run(order=26) + @pytest.mark.run(order=28) def test_counter_incremented_again(self): CommonTests.test_counter_incremented(self, 'share', 2) - @pytest.mark.run(order=27) + @pytest.mark.run(order=29) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', True) - @pytest.mark.run(order=28) + @pytest.mark.run(order=30) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=29) + @pytest.mark.run(order=31) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'share', True) - @pytest.mark.run(order=30) + @pytest.mark.run(order=32) def test_add_button_visible(self): CommonTests.test_add_button_visible(self) diff --git a/tests_gui_local/onionshare_slug_persistent_test.py b/tests_gui_local/onionshare_slug_persistent_test.py index 1e5614dc..5b53f7e0 100644 --- a/tests_gui_local/onionshare_slug_persistent_test.py +++ b/tests_gui_local/onionshare_slug_persistent_test.py @@ -94,68 +94,76 @@ class OnionShareGuiTest(unittest.TestCase): def test_server_status_bar_is_visible(self): CommonTests.test_server_status_bar_is_visible(self) - @pytest.mark.run(order=5) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') - @pytest.mark.run(order=6) + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=7) + @pytest.mark.run(order=10) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=11) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=9) + @pytest.mark.run(order=12) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=10) + @pytest.mark.run(order=13) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=11) + @pytest.mark.run(order=14) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=12) + @pytest.mark.run(order=15) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', False) global slug slug = self.gui.share_mode.server_status.web.slug - @pytest.mark.run(order=13) + @pytest.mark.run(order=16) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=14) + @pytest.mark.run(order=17) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', True) - @pytest.mark.run(order=15) + @pytest.mark.run(order=18) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=16) + @pytest.mark.run(order=19) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'share', True) - @pytest.mark.run(order=17) + @pytest.mark.run(order=20) def test_server_started_again(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') CommonTests.test_server_status_indicator_says_starting(self, 'share') CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=18) + @pytest.mark.run(order=21) def test_have_same_slug(self): '''Test that we have the same slug''' self.assertEqual(self.gui.share_mode.server_status.web.slug, slug) - @pytest.mark.run(order=19) + @pytest.mark.run(order=22) def test_server_is_stopped_again(self): CommonTests.test_server_is_stopped(self, 'share', True) CommonTests.test_web_service_is_stopped(self) diff --git a/tests_gui_local/onionshare_timer_test.py b/tests_gui_local/onionshare_timer_test.py index 1a5134e2..701d9a21 100644 --- a/tests_gui_local/onionshare_timer_test.py +++ b/tests_gui_local/onionshare_timer_test.py @@ -97,12 +97,12 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_file_selection_widget_has_a_file(self) @pytest.mark.run(order=6) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) - def test_history_is_visible(self): - CommonTests.test_history_is_visible(self, 'share') + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') @pytest.mark.run(order=8) def test_set_timeout(self): From d8c225a9c627ffd45c56d96569faaa4f863acb37 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sat, 29 Sep 2018 18:58:27 -0700 Subject: [PATCH 25/50] Begin refactoring Tor tests to inherit from local tests --- tests_gui_local/__init__.py | 8 + tests_gui_tor/commontests.py | 311 +---------------------------------- 2 files changed, 10 insertions(+), 309 deletions(-) diff --git a/tests_gui_local/__init__.py b/tests_gui_local/__init__.py index e69de29b..76e5b1b9 100644 --- a/tests_gui_local/__init__.py +++ b/tests_gui_local/__init__.py @@ -0,0 +1,8 @@ +from .onionshare_receive_mode_upload_test_public_mode import OnionShareGuiTest as ReceiveMoveUploadTestPublicMode +from .onionshare_receive_mode_upload_test import OnionShareGuiTest as ReceiveModeUploadTest +from .onionshare_share_mode_download_test_public_mode import OnionShareGuiTest as ShareModeDownloadTestPublicMode +from .onionshare_share_mode_download_test import OnionShareGuiTest as ShareModeDownloadTest +from .onionshare_share_mode_download_test_stay_open import OnionShareGuiTest as ShareModeDownloadTestStayOpen +from .onionshare_slug_persistent_test import OnionShareGuiTest as SlugPersistentTest +from .onionshare_timer_test import OnionShareGuiTest as TimerTest +from .commontests import CommonTests diff --git a/tests_gui_tor/commontests.py b/tests_gui_tor/commontests.py index a0d9bf5f..ea37279f 100644 --- a/tests_gui_tor/commontests.py +++ b/tests_gui_tor/commontests.py @@ -7,207 +7,13 @@ import zipfile from PyQt5 import QtCore, QtTest from onionshare import strings -class CommonTests(object): - def test_gui_loaded(self): - '''Test that the GUI actually is shown''' - self.assertTrue(self.gui.show) - - def test_windowTitle_seen(self): - '''Test that the window title is OnionShare''' - self.assertEqual(self.gui.windowTitle(), 'OnionShare') - - def test_settings_button_is_visible(self): - '''Test that the settings button is visible''' - self.assertTrue(self.gui.settings_button.isVisible()) - - def test_server_status_bar_is_visible(self): - '''Test that the status bar is visible''' - self.assertTrue(self.gui.status_bar.isVisible()) - - def test_info_widget_is_not_visible(self, mode): - '''Test that the info widget along top of screen is not shown''' - if mode == 'receive': - self.assertFalse(self.gui.receive_mode.info_widget.isVisible()) - if mode == 'share': - self.assertFalse(self.gui.share_mode.info_widget.isVisible()) - - def test_info_widget_is_visible(self, mode): - '''Test that the info widget along top of screen is shown''' - if mode == 'receive': - self.assertTrue(self.gui.receive_mode.info_widget.isVisible()) - if mode == 'share': - self.assertTrue(self.gui.share_mode.info_widget.isVisible()) - - def test_click_mode(self, mode): - '''Test that we can switch Mode by clicking the button''' - if mode == 'receive': - QtTest.QTest.mouseClick(self.gui.receive_mode_button, QtCore.Qt.LeftButton) - self.assertTrue(self.gui.mode, self.gui.MODE_RECEIVE) - if mode == 'share': - QtTest.QTest.mouseClick(self.gui.share_mode_button, QtCore.Qt.LeftButton) - self.assertTrue(self.gui.mode, self.gui.MODE_SHARE) - - def test_history_is_visible(self, mode): - '''Test that the History section is visible and that the relevant widget is present''' - if mode == 'receive': - self.assertTrue(self.gui.receive_mode.uploads.isVisible()) - self.assertTrue(self.gui.receive_mode.uploads.no_uploads_label.isVisible()) - if mode == 'share': - self.assertTrue(self.gui.share_mode.downloads.isVisible()) - self.assertTrue(self.gui.share_mode.downloads.no_downloads_label.isVisible()) - - def test_server_working_on_start_button_pressed(self, mode): - '''Test we can start the service''' - # Should be in SERVER_WORKING state - if mode == 'receive': - QtTest.QTest.mouseClick(self.gui.receive_mode.server_status.server_button, QtCore.Qt.LeftButton) - self.assertEqual(self.gui.receive_mode.server_status.status, 1) - if mode == 'share': - QtTest.QTest.mouseClick(self.gui.share_mode.server_status.server_button, QtCore.Qt.LeftButton) - self.assertEqual(self.gui.share_mode.server_status.status, 1) - - def test_server_status_indicator_says_starting(self, mode): - '''Test that the Server Status indicator shows we are Starting''' - if mode == 'receive': - self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_share_working', True)) - if mode == 'share': - self.assertEquals(self.gui.share_mode.server_status_label.text(), strings._('gui_status_indicator_share_working', True)) - - def test_settings_button_is_hidden(self): - '''Test that the settings button is hidden when the server starts''' - self.assertFalse(self.gui.settings_button.isVisible()) - - def test_a_server_is_started(self, mode): - '''Test that the server has started''' - QtTest.QTest.qWait(45000) - # Should now be in SERVER_STARTED state - if mode == 'receive': - self.assertEqual(self.gui.receive_mode.server_status.status, 2) - if mode == 'share': - self.assertEqual(self.gui.share_mode.server_status.status, 2) - - def test_a_web_server_is_running(self): - '''Test that the web server has started''' - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - - self.assertEqual(sock.connect_ex(('127.0.0.1',self.gui.app.port)), 0) - - def test_have_a_slug(self, mode, public_mode): - '''Test that we have a valid slug''' - if mode == 'receive': - if not public_mode: - self.assertRegex(self.gui.receive_mode.server_status.web.slug, r'(\w+)-(\w+)') - else: - self.assertIsNone(self.gui.receive_mode.server_status.web.slug, r'(\w+)-(\w+)') - if mode == 'share': - if not public_mode: - self.assertRegex(self.gui.share_mode.server_status.web.slug, r'(\w+)-(\w+)') - else: - self.assertIsNone(self.gui.share_mode.server_status.web.slug, r'(\w+)-(\w+)') +from tests_gui_local import CommonTests as LocalCommonTests +class CommonTests(LocalCommonTests): def test_have_an_onion_service(self): '''Test that we have a valid Onion URL''' self.assertRegex(self.gui.app.onion_host, r'[a-z2-7].onion') - def test_url_description_shown(self, mode): - '''Test that the URL label is showing''' - if mode == 'receive': - self.assertTrue(self.gui.receive_mode.server_status.url_description.isVisible()) - if mode == 'share': - self.assertTrue(self.gui.share_mode.server_status.url_description.isVisible()) - - def test_have_copy_url_button(self, mode): - '''Test that the Copy URL button is shown''' - if mode == 'receive': - self.assertTrue(self.gui.receive_mode.server_status.copy_url_button.isVisible()) - if mode == 'share': - self.assertTrue(self.gui.share_mode.server_status.copy_url_button.isVisible()) - - def test_server_status_indicator_says_started(self, mode): - '''Test that the Server Status indicator shows we are started''' - if mode == 'receive': - self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_started', True)) - if mode == 'share': - self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_share_started', True)) - - def test_web_page(self, mode, string, public_mode): - '''Test that the web page contains a string''' - (socks_address, socks_port) = self.gui.app.onion.get_tor_socks_port() - socks.set_default_proxy(socks.SOCKS5, socks_address, socks_port) - - s = socks.socksocket() - s.settimeout(60) - s.connect((self.gui.app.onion_host, 80)) - - if not public_mode: - if mode == 'receive': - path = '/{}'.format(self.gui.receive_mode.server_status.web.slug) - if mode == 'share': - path = '/{}'.format(self.gui.share_mode.server_status.web.slug) - else: - path = '/' - - http_request = 'GET {} HTTP/1.0\r\n'.format(path) - http_request += 'Host: {}\r\n'.format(self.gui.app.onion_host) - http_request += '\r\n' - s.sendall(http_request.encode('utf-8')) - - with open('/tmp/webpage', 'wb') as file_to_write: - while True: - data = s.recv(1024) - if not data: - break - file_to_write.write(data) - file_to_write.close() - - f = open('/tmp/webpage') - self.assertTrue(string in f.read()) - f.close() - - def test_history_widgets_present(self, mode): - '''Test that the relevant widgets are present in the history view after activity has taken place''' - if mode == 'receive': - self.assertFalse(self.gui.receive_mode.uploads.no_uploads_label.isVisible()) - self.assertTrue(self.gui.receive_mode.uploads.clear_history_button.isVisible()) - if mode == 'share': - self.assertFalse(self.gui.share_mode.downloads.no_downloads_label.isVisible()) - self.assertTrue(self.gui.share_mode.downloads.clear_history_button.isVisible()) - - def test_counter_incremented(self, mode, count): - '''Test that the counter has incremented''' - if mode == 'receive': - self.assertEquals(self.gui.receive_mode.uploads_completed, count) - if mode == 'share': - self.assertEquals(self.gui.share_mode.downloads_completed, count) - - def test_server_is_stopped(self, mode, stay_open): - '''Test that the server stops when we click Stop''' - if mode == 'receive': - QtTest.QTest.mouseClick(self.gui.receive_mode.server_status.server_button, QtCore.Qt.LeftButton) - self.assertEquals(self.gui.receive_mode.server_status.status, 0) - if mode == 'share': - if stay_open: - QtTest.QTest.mouseClick(self.gui.share_mode.server_status.server_button, QtCore.Qt.LeftButton) - self.assertEquals(self.gui.share_mode.server_status.status, 0) - - def test_web_service_is_stopped(self): - '''Test that the web server also stopped''' - QtTest.QTest.qWait(2000) - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - - # We should be closed by now. Fail if not! - self.assertNotEqual(sock.connect_ex(('127.0.0.1',self.gui.app.port)), 0) - - def test_server_status_indicator_says_closed(self, mode, stay_open): - '''Test that the Server Status indicator shows we closed''' - if mode == 'receive': - self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_stopped', True)) - if mode == 'share': - if stay_open: - self.assertEquals(self.gui.share_mode.server_status_label.text(), strings._('gui_status_indicator_share_stopped', True)) - else: - self.assertEquals(self.gui.share_mode.server_status_label.text(), strings._('closing_automatically', True)) - def test_cancel_the_share(self, mode): '''Test that we can cancel this share before it's started up ''' if mode == 'share': @@ -222,119 +28,6 @@ class CommonTests(object): QtTest.QTest.mouseRelease(self.gui.receive_mode.server_status.server_button, QtCore.Qt.LeftButton) self.assertEqual(self.gui.receive_mode.server_status.status, 0) - - # Auto-stop timer tests - def test_set_timeout(self, mode, timeout): - '''Test that the timeout can be set''' - timer = QtCore.QDateTime.currentDateTime().addSecs(timeout) - if mode == 'receive': - self.gui.receive_mode.server_status.shutdown_timeout.setDateTime(timer) - self.assertTrue(self.gui.receive_mode.server_status.shutdown_timeout.dateTime(), timer) - if mode == 'share': - self.gui.share_mode.server_status.shutdown_timeout.setDateTime(timer) - self.assertTrue(self.gui.share_mode.server_status.shutdown_timeout.dateTime(), timer) - - def test_timeout_widget_hidden(self, mode): - '''Test that the timeout widget is hidden when share has started''' - if mode == 'receive': - self.assertFalse(self.gui.receive_mode.server_status.shutdown_timeout_container.isVisible()) - if mode == 'share': - self.assertFalse(self.gui.share_mode.server_status.shutdown_timeout_container.isVisible()) - - def test_server_timed_out(self, mode, wait): - '''Test that the server has timed out after the timer ran out''' - QtTest.QTest.qWait(wait) - # We should have timed out now - if mode == 'receive': - self.assertEqual(self.gui.receive_mode.server_status.status, 0) - if mode == 'share': - self.assertEqual(self.gui.share_mode.server_status.status, 0) - - # Receive-specific tests - def test_upload_file(self, public_mode, expected_file): - '''Test that we can upload the file''' - (socks_address, socks_port) = self.gui.app.onion.get_tor_socks_port() - session = requests.session() - session.proxies = {} - session.proxies['http'] = 'socks5h://{}:{}'.format(socks_address, socks_port) - - files = {'file[]': open('/tmp/test.txt', 'rb')} - if not public_mode: - path = 'http://{}/{}/upload'.format(self.gui.app.onion_host, self.gui.receive_mode.web.slug) - else: - path = 'http://{}/upload'.format(self.gui.app.onion_host) - response = session.post(path, files=files) - QtTest.QTest.qWait(4000) - self.assertTrue(os.path.isfile(expected_file)) - - # Share-specific tests - def test_file_selection_widget_has_a_file(self): - '''Test that the number of files in the list is 1''' - self.assertEqual(self.gui.share_mode.server_status.file_selection.get_num_files(), 1) - - def test_deleting_only_file_hides_delete_button(self): - '''Test that clicking on the file item shows the delete button. Test that deleting the only item in the list hides the delete button''' - rect = self.gui.share_mode.server_status.file_selection.file_list.visualItemRect(self.gui.share_mode.server_status.file_selection.file_list.item(0)) - QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.file_list.viewport(), QtCore.Qt.LeftButton, pos=rect.center()) - # Delete button should be visible - self.assertTrue(self.gui.share_mode.server_status.file_selection.delete_button.isVisible()) - # Click delete, and since there's no more files, the delete button should be hidden - QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.delete_button, QtCore.Qt.LeftButton) - self.assertFalse(self.gui.share_mode.server_status.file_selection.delete_button.isVisible()) - - def test_add_a_file_and_delete_using_its_delete_widget(self): - '''Test that we can also delete a file by clicking on its [X] widget''' - self.gui.share_mode.server_status.file_selection.file_list.add_file('/etc/hosts') - QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.file_list.item(0).item_button, QtCore.Qt.LeftButton) - self.assertEquals(self.gui.share_mode.server_status.file_selection.get_num_files(), 0) - - def test_file_selection_widget_readd_files(self): - '''Re-add some files to the list so we can share''' - self.gui.share_mode.server_status.file_selection.file_list.add_file('/etc/hosts') - self.gui.share_mode.server_status.file_selection.file_list.add_file('/tmp/test.txt') - self.assertEqual(self.gui.share_mode.server_status.file_selection.get_num_files(), 2) - - def test_add_delete_buttons_hidden(self): - '''Test that the add and delete buttons are hidden when the server starts''' - self.assertFalse(self.gui.share_mode.server_status.file_selection.add_button.isVisible()) - self.assertFalse(self.gui.share_mode.server_status.file_selection.delete_button.isVisible()) - - def test_download_share(self, public_mode): - '''Test that we can download the share''' - (socks_address, socks_port) = self.gui.app.onion.get_tor_socks_port() - socks.set_default_proxy(socks.SOCKS5, socks_address, socks_port) - - s = socks.socksocket() - s.settimeout(60) - s.connect((self.gui.app.onion_host, 80)) - - if public_mode: - path = '/download' - else: - path = '{}/download'.format(self.gui.share_mode.web.slug) - - http_request = 'GET {} HTTP/1.0\r\n'.format(path) - http_request += 'Host: {}\r\n'.format(self.gui.app.onion_host) - http_request += '\r\n' - s.sendall(http_request.encode('utf-8')) - - with open('/tmp/download.zip', 'wb') as file_to_write: - while True: - data = s.recv(1024) - if not data: - break - file_to_write.write(data) - file_to_write.close() - - zip = zipfile.ZipFile('/tmp/download.zip') - QtTest.QTest.qWait(4000) - self.assertEquals('onionshare', zip.read('test.txt').decode('utf-8')) - - def test_add_button_visible(self): - '''Test that the add button should be visible''' - self.assertTrue(self.gui.share_mode.server_status.file_selection.add_button.isVisible()) - - # Stealth tests def test_copy_have_hidserv_auth_button(self, mode): '''Test that the Copy HidservAuth button is shown''' From f5c7acf8f260679a9fec4b9772e8d8bb8d8d41e4 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 30 Sep 2018 10:57:13 -0700 Subject: [PATCH 26/50] Fix Tor tests so they pass, too --- tests_gui_local/__init__.py | 7 --- tests_gui_tor/commontests.py | 9 +++ .../onionshare_receive_mode_upload_test.py | 36 ++++++----- ...re_receive_mode_upload_test_public_mode.py | 46 +++++++------- ...onionshare_share_mode_cancel_share_test.py | 8 --- .../onionshare_share_mode_download_test.py | 16 ++--- ...re_share_mode_download_test_public_mode.py | 54 ++++++++++------- ...hare_share_mode_download_test_stay_open.py | 60 +++++++++++-------- .../onionshare_share_mode_persistent_test.py | 46 ++++++++------ .../onionshare_share_mode_stealth_test.py | 44 ++++++++------ ...e_share_mode_tor_connection_killed_test.py | 46 ++++++++------ tests_gui_tor/onionshare_timer_test.py | 28 +++++---- .../onionshare_tor_connection_killed_test.py | 46 ++++++++------ 13 files changed, 252 insertions(+), 194 deletions(-) diff --git a/tests_gui_local/__init__.py b/tests_gui_local/__init__.py index 76e5b1b9..bb2b2182 100644 --- a/tests_gui_local/__init__.py +++ b/tests_gui_local/__init__.py @@ -1,8 +1 @@ -from .onionshare_receive_mode_upload_test_public_mode import OnionShareGuiTest as ReceiveMoveUploadTestPublicMode -from .onionshare_receive_mode_upload_test import OnionShareGuiTest as ReceiveModeUploadTest -from .onionshare_share_mode_download_test_public_mode import OnionShareGuiTest as ShareModeDownloadTestPublicMode -from .onionshare_share_mode_download_test import OnionShareGuiTest as ShareModeDownloadTest -from .onionshare_share_mode_download_test_stay_open import OnionShareGuiTest as ShareModeDownloadTestStayOpen -from .onionshare_slug_persistent_test import OnionShareGuiTest as SlugPersistentTest -from .onionshare_timer_test import OnionShareGuiTest as TimerTest from .commontests import CommonTests diff --git a/tests_gui_tor/commontests.py b/tests_gui_tor/commontests.py index ea37279f..a1e420fd 100644 --- a/tests_gui_tor/commontests.py +++ b/tests_gui_tor/commontests.py @@ -10,6 +10,15 @@ from onionshare import strings from tests_gui_local import CommonTests as LocalCommonTests class CommonTests(LocalCommonTests): + def test_a_server_is_started(self, mode): + '''Test that the server has started (overriding from local tests to wait for longer)''' + QtTest.QTest.qWait(45000) + # Should now be in SERVER_STARTED state + if mode == 'receive': + self.assertEqual(self.gui.receive_mode.server_status.status, 2) + if mode == 'share': + self.assertEqual(self.gui.share_mode.server_status.status, 2) + def test_have_an_onion_service(self): '''Test that we have a valid Onion URL''' self.assertRegex(self.gui.app.onion_host, r'[a-z2-7].onion') diff --git a/tests_gui_tor/onionshare_receive_mode_upload_test.py b/tests_gui_tor/onionshare_receive_mode_upload_test.py index 5be400e2..7c340037 100644 --- a/tests_gui_tor/onionshare_receive_mode_upload_test.py +++ b/tests_gui_tor/onionshare_receive_mode_upload_test.py @@ -94,15 +94,19 @@ class OnionShareGuiTest(unittest.TestCase): def test_server_status_bar_is_visible(self): CommonTests.test_server_status_bar_is_visible(self) - @pytest.mark.run(order=5) - def test_info_widget_is_not_visible(self): - CommonTests.test_info_widget_is_not_visible(self, 'receive') - @pytest.mark.run(order=6) def test_click_mode(self): CommonTests.test_click_mode(self, 'receive') + @pytest.mark.run(order=6) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'receive') + @pytest.mark.run(order=7) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'receive') + + @pytest.mark.run(order=8) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'receive') @@ -134,51 +138,51 @@ class OnionShareGuiTest(unittest.TestCase): def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=16) + @pytest.mark.run(order=20) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'receive') - @pytest.mark.run(order=17) + @pytest.mark.run(order=21) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'receive') - @pytest.mark.run(order=18) + @pytest.mark.run(order=22) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'receive') - @pytest.mark.run(order=19) + @pytest.mark.run(order=23) def test_web_page(self): CommonTests.test_web_page(self, 'receive', 'Select the files you want to send, then click', False) - @pytest.mark.run(order=20) + @pytest.mark.run(order=24) def test_upload_file(self): CommonTests.test_upload_file(self, False, '/tmp/OnionShare/test.txt') - @pytest.mark.run(order=21) + @pytest.mark.run(order=25) def test_history_widgets_present(self): CommonTests.test_history_widgets_present(self, 'receive') - @pytest.mark.run(order=22) + @pytest.mark.run(order=26) def test_counter_incremented(self): CommonTests.test_counter_incremented(self, 'receive', 1) - @pytest.mark.run(order=23) + @pytest.mark.run(order=27) def test_upload_same_file_is_renamed(self): CommonTests.test_upload_file(self, False, '/tmp/OnionShare/test-2.txt') - @pytest.mark.run(order=24) + @pytest.mark.run(order=28) def test_upload_count_incremented_again(self): CommonTests.test_counter_incremented(self, 'receive', 2) - @pytest.mark.run(order=25) + @pytest.mark.run(order=29) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'receive', False) - @pytest.mark.run(order=26) + @pytest.mark.run(order=30) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=27) + @pytest.mark.run(order=31) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) diff --git a/tests_gui_tor/onionshare_receive_mode_upload_test_public_mode.py b/tests_gui_tor/onionshare_receive_mode_upload_test_public_mode.py index 9c9553a4..65bf5c89 100644 --- a/tests_gui_tor/onionshare_receive_mode_upload_test_public_mode.py +++ b/tests_gui_tor/onionshare_receive_mode_upload_test_public_mode.py @@ -95,34 +95,38 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_server_status_bar_is_visible(self) @pytest.mark.run(order=5) - def test_info_widget_is_not_visible(self): - CommonTests.test_info_widget_is_not_visible(self, 'receive') - - @pytest.mark.run(order=6) def test_click_mode(self): CommonTests.test_click_mode(self, 'receive') + @pytest.mark.run(order=6) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'receive') + @pytest.mark.run(order=7) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'receive') + + @pytest.mark.run(order=8) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'receive') - @pytest.mark.run(order=8) + @pytest.mark.run(order=9) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'receive') - @pytest.mark.run(order=9) + @pytest.mark.run(order=10) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'receive') - @pytest.mark.run(order=10) + @pytest.mark.run(order=11) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=12) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'receive') - @pytest.mark.run(order=12) + @pytest.mark.run(order=13) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) @@ -134,51 +138,51 @@ class OnionShareGuiTest(unittest.TestCase): def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=16) + @pytest.mark.run(order=20) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'receive') - @pytest.mark.run(order=17) + @pytest.mark.run(order=21) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'receive') - @pytest.mark.run(order=18) + @pytest.mark.run(order=22) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'receive') - @pytest.mark.run(order=19) + @pytest.mark.run(order=23) def test_web_page(self): CommonTests.test_web_page(self, 'receive', 'Select the files you want to send, then click', True) - @pytest.mark.run(order=20) + @pytest.mark.run(order=24) def test_upload_file(self): CommonTests.test_upload_file(self, True, '/tmp/OnionShare/test.txt') - @pytest.mark.run(order=21) + @pytest.mark.run(order=25) def test_history_widgets_present(self): CommonTests.test_history_widgets_present(self, 'receive') - @pytest.mark.run(order=22) + @pytest.mark.run(order=26) def test_counter_incremented(self): CommonTests.test_counter_incremented(self, 'receive', 1) - @pytest.mark.run(order=23) + @pytest.mark.run(order=27) def test_upload_same_file_is_renamed(self): CommonTests.test_upload_file(self, True, '/tmp/OnionShare/test-2.txt') - @pytest.mark.run(order=24) + @pytest.mark.run(order=28) def test_upload_count_incremented_again(self): CommonTests.test_counter_incremented(self, 'receive', 2) - @pytest.mark.run(order=25) + @pytest.mark.run(order=29) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'receive', False) - @pytest.mark.run(order=26) + @pytest.mark.run(order=30) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=27) + @pytest.mark.run(order=31) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) diff --git a/tests_gui_tor/onionshare_share_mode_cancel_share_test.py b/tests_gui_tor/onionshare_share_mode_cancel_share_test.py index 466109d7..cdab8f85 100644 --- a/tests_gui_tor/onionshare_share_mode_cancel_share_test.py +++ b/tests_gui_tor/onionshare_share_mode_cancel_share_test.py @@ -96,14 +96,6 @@ class OnionShareGuiTest(unittest.TestCase): def test_file_selection_widget_has_a_file(self): CommonTests.test_file_selection_widget_has_a_file(self) - @pytest.mark.run(order=6) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') - - @pytest.mark.run(order=7) - def test_history_is_visible(self): - CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) diff --git a/tests_gui_tor/onionshare_share_mode_download_test.py b/tests_gui_tor/onionshare_share_mode_download_test.py index 1c8e1b6c..2bf26690 100644 --- a/tests_gui_tor/onionshare_share_mode_download_test.py +++ b/tests_gui_tor/onionshare_share_mode_download_test.py @@ -97,20 +97,20 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_file_selection_widget_has_a_file(self) @pytest.mark.run(order=6) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) - def test_history_is_visible(self): - CommonTests.test_history_is_visible(self, 'share') + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') @pytest.mark.run(order=8) - def test_deleting_only_file_hides_delete_button(self): - CommonTests.test_deleting_only_file_hides_delete_button(self) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') @pytest.mark.run(order=9) - def test_add_a_file_and_delete_using_its_delete_widget(self): - CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') @pytest.mark.run(order=10) def test_file_selection_widget_readd_files(self): diff --git a/tests_gui_tor/onionshare_share_mode_download_test_public_mode.py b/tests_gui_tor/onionshare_share_mode_download_test_public_mode.py index c292e729..4792994d 100644 --- a/tests_gui_tor/onionshare_share_mode_download_test_public_mode.py +++ b/tests_gui_tor/onionshare_share_mode_download_test_public_mode.py @@ -97,94 +97,102 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_file_selection_widget_has_a_file(self) @pytest.mark.run(order=6) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) def test_add_a_file_and_delete_using_its_delete_widget(self): CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) - @pytest.mark.run(order=10) + @pytest.mark.run(order=12) def test_file_selection_widget_readd_files(self): CommonTests.test_file_selection_widget_readd_files(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=19) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', True) - @pytest.mark.run(order=18) + @pytest.mark.run(order=20) def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=19) + @pytest.mark.run(order=21) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'share') - @pytest.mark.run(order=20) + @pytest.mark.run(order=22) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'share') - @pytest.mark.run(order=21) + @pytest.mark.run(order=23) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=22) + @pytest.mark.run(order=24) def test_web_page(self): CommonTests.test_web_page(self, 'share', 'Total size', True) - @pytest.mark.run(order=23) + @pytest.mark.run(order=25) def test_download_share(self): CommonTests.test_download_share(self, True) - @pytest.mark.run(order=24) + @pytest.mark.run(order=26) def test_history_widgets_present(self): CommonTests.test_history_widgets_present(self, 'share') - @pytest.mark.run(order=25) + @pytest.mark.run(order=27) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', False) - @pytest.mark.run(order=26) + @pytest.mark.run(order=28) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=27) + @pytest.mark.run(order=29) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'share', False) - @pytest.mark.run(order=28) + @pytest.mark.run(order=30) def test_add_button_visible(self): CommonTests.test_add_button_visible(self) diff --git a/tests_gui_tor/onionshare_share_mode_download_test_stay_open.py b/tests_gui_tor/onionshare_share_mode_download_test_stay_open.py index 7838316f..92d52169 100644 --- a/tests_gui_tor/onionshare_share_mode_download_test_stay_open.py +++ b/tests_gui_tor/onionshare_share_mode_download_test_stay_open.py @@ -97,106 +97,114 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_file_selection_widget_has_a_file(self) @pytest.mark.run(order=6) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) def test_add_a_file_and_delete_using_its_delete_widget(self): CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) - @pytest.mark.run(order=10) + @pytest.mark.run(order=12) def test_file_selection_widget_readd_files(self): CommonTests.test_file_selection_widget_readd_files(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=19) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', True) - @pytest.mark.run(order=18) + @pytest.mark.run(order=20) def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=19) + @pytest.mark.run(order=21) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'share') - @pytest.mark.run(order=20) + @pytest.mark.run(order=22) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'share') - @pytest.mark.run(order=21) + @pytest.mark.run(order=23) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=22) + @pytest.mark.run(order=24) def test_web_page(self): CommonTests.test_web_page(self, 'share', 'Total size', True) - @pytest.mark.run(order=23) + @pytest.mark.run(order=25) def test_download_share(self): CommonTests.test_download_share(self, True) - @pytest.mark.run(order=24) + @pytest.mark.run(order=26) def test_history_widgets_present(self): CommonTests.test_history_widgets_present(self, 'share') - @pytest.mark.run(order=25) + @pytest.mark.run(order=27) def test_counter_incremented(self): CommonTests.test_counter_incremented(self, 'share', 1) - @pytest.mark.run(order=26) + @pytest.mark.run(order=28) def test_download_share_again(self): CommonTests.test_download_share(self, True) - @pytest.mark.run(order=27) + @pytest.mark.run(order=29) def test_counter_incremented_again(self): CommonTests.test_counter_incremented(self, 'share', 2) - @pytest.mark.run(order=28) + @pytest.mark.run(order=30) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', True) - @pytest.mark.run(order=29) + @pytest.mark.run(order=31) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=30) + @pytest.mark.run(order=32) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'share', True) - @pytest.mark.run(order=31) + @pytest.mark.run(order=33) def test_add_button_visible(self): CommonTests.test_add_button_visible(self) diff --git a/tests_gui_tor/onionshare_share_mode_persistent_test.py b/tests_gui_tor/onionshare_share_mode_persistent_test.py index 3cffaab6..6b9fbe16 100644 --- a/tests_gui_tor/onionshare_share_mode_persistent_test.py +++ b/tests_gui_tor/onionshare_share_mode_persistent_test.py @@ -95,79 +95,87 @@ class OnionShareGuiTest(unittest.TestCase): def test_server_status_bar_is_visible(self): CommonTests.test_server_status_bar_is_visible(self) - @pytest.mark.run(order=5) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') - @pytest.mark.run(order=6) + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=7) + @pytest.mark.run(order=10) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=11) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=9) + @pytest.mark.run(order=12) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=10) + @pytest.mark.run(order=13) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=11) + @pytest.mark.run(order=14) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=12) + @pytest.mark.run(order=15) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', False) global slug slug = self.gui.share_mode.server_status.web.slug - @pytest.mark.run(order=13) + @pytest.mark.run(order=16) def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) global onion_host onion_host = self.gui.app.onion_host - @pytest.mark.run(order=14) + @pytest.mark.run(order=17) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=15) + @pytest.mark.run(order=18) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', True) - @pytest.mark.run(order=16) + @pytest.mark.run(order=19) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=20) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'share', True) - @pytest.mark.run(order=18) + @pytest.mark.run(order=21) def test_server_started_again(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') CommonTests.test_server_status_indicator_says_starting(self, 'share') CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=19) + @pytest.mark.run(order=22) def test_have_same_slug(self): '''Test that we have the same slug''' self.assertEqual(self.gui.share_mode.server_status.web.slug, slug) - @pytest.mark.run(order=20) + @pytest.mark.run(order=23) def test_have_same_onion(self): '''Test that we have the same onion''' self.assertEqual(self.gui.app.onion_host, onion_host) - @pytest.mark.run(order=21) + @pytest.mark.run(order=24) def test_server_is_stopped_again(self): CommonTests.test_server_is_stopped(self, 'share', True) CommonTests.test_web_service_is_stopped(self) diff --git a/tests_gui_tor/onionshare_share_mode_stealth_test.py b/tests_gui_tor/onionshare_share_mode_stealth_test.py index aaf6fbc6..876efde2 100644 --- a/tests_gui_tor/onionshare_share_mode_stealth_test.py +++ b/tests_gui_tor/onionshare_share_mode_stealth_test.py @@ -97,74 +97,82 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_file_selection_widget_has_a_file(self) @pytest.mark.run(order=6) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) def test_add_a_file_and_delete_using_its_delete_widget(self): CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) - @pytest.mark.run(order=10) + @pytest.mark.run(order=12) def test_file_selection_widget_readd_files(self): CommonTests.test_file_selection_widget_readd_files(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=19) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', False) - @pytest.mark.run(order=18) + @pytest.mark.run(order=20) def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=19) + @pytest.mark.run(order=21) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'share') - @pytest.mark.run(order=20) + @pytest.mark.run(order=22) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'share') - @pytest.mark.run(order=21) + @pytest.mark.run(order=23) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=22) + @pytest.mark.run(order=24) def test_copy_have_hidserv_auth_button(self): CommonTests.test_copy_have_hidserv_auth_button(self, 'share') - @pytest.mark.run(order=23) + @pytest.mark.run(order=25) def test_hidserv_auth_string(self): CommonTests.test_hidserv_auth_string(self) diff --git a/tests_gui_tor/onionshare_share_mode_tor_connection_killed_test.py b/tests_gui_tor/onionshare_share_mode_tor_connection_killed_test.py index 861b7ccc..37abc825 100644 --- a/tests_gui_tor/onionshare_share_mode_tor_connection_killed_test.py +++ b/tests_gui_tor/onionshare_share_mode_tor_connection_killed_test.py @@ -97,78 +97,86 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_file_selection_widget_has_a_file(self) @pytest.mark.run(order=6) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) def test_add_a_file_and_delete_using_its_delete_widget(self): CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) - @pytest.mark.run(order=10) + @pytest.mark.run(order=12) def test_file_selection_widget_readd_files(self): CommonTests.test_file_selection_widget_readd_files(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=19) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', False) - @pytest.mark.run(order=18) + @pytest.mark.run(order=20) def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=19) + @pytest.mark.run(order=21) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'share') - @pytest.mark.run(order=20) + @pytest.mark.run(order=22) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'share') - @pytest.mark.run(order=21) + @pytest.mark.run(order=23) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=22) + @pytest.mark.run(order=24) def test_tor_killed_statusbar_message_shown(self): CommonTests.test_tor_killed_statusbar_message_shown(self, 'share') - @pytest.mark.run(order=23) + @pytest.mark.run(order=25) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', False) - @pytest.mark.run(order=24) + @pytest.mark.run(order=26) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) diff --git a/tests_gui_tor/onionshare_timer_test.py b/tests_gui_tor/onionshare_timer_test.py index b76106d9..2b64b998 100644 --- a/tests_gui_tor/onionshare_timer_test.py +++ b/tests_gui_tor/onionshare_timer_test.py @@ -97,42 +97,50 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_file_selection_widget_has_a_file(self) @pytest.mark.run(order=6) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_set_timeout(self): CommonTests.test_set_timeout(self, 'share', 120) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=10) + @pytest.mark.run(order=12) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_timeout_widget_hidden(self): CommonTests.test_timeout_widget_hidden(self, 'share') - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_timeout(self): CommonTests.test_server_timed_out(self, 'share', 125000) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) diff --git a/tests_gui_tor/onionshare_tor_connection_killed_test.py b/tests_gui_tor/onionshare_tor_connection_killed_test.py index 861b7ccc..37abc825 100644 --- a/tests_gui_tor/onionshare_tor_connection_killed_test.py +++ b/tests_gui_tor/onionshare_tor_connection_killed_test.py @@ -97,78 +97,86 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_file_selection_widget_has_a_file(self) @pytest.mark.run(order=6) - def test_info_widget_is_visible(self): - CommonTests.test_info_widget_is_visible(self, 'share') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) def test_add_a_file_and_delete_using_its_delete_widget(self): CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) - @pytest.mark.run(order=10) + @pytest.mark.run(order=12) def test_file_selection_widget_readd_files(self): CommonTests.test_file_selection_widget_readd_files(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=19) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', False) - @pytest.mark.run(order=18) + @pytest.mark.run(order=20) def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=19) + @pytest.mark.run(order=21) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'share') - @pytest.mark.run(order=20) + @pytest.mark.run(order=22) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'share') - @pytest.mark.run(order=21) + @pytest.mark.run(order=23) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=22) + @pytest.mark.run(order=24) def test_tor_killed_statusbar_message_shown(self): CommonTests.test_tor_killed_statusbar_message_shown(self, 'share') - @pytest.mark.run(order=23) + @pytest.mark.run(order=25) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', False) - @pytest.mark.run(order=24) + @pytest.mark.run(order=26) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) From 3fd75819953e18a652f0746b68e7ec99eeb9c4ba Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 30 Sep 2018 11:41:07 -0700 Subject: [PATCH 27/50] Test the history indicator widget, in local GUI tests --- tests_gui_local/commontests.py | 53 +++++++++++++++++++ .../onionshare_receive_mode_upload_test.py | 8 ++- ...re_receive_mode_upload_test_public_mode.py | 8 ++- .../onionshare_share_mode_download_test.py | 6 +++ ...re_share_mode_download_test_public_mode.py | 6 +++ ...hare_share_mode_download_test_stay_open.py | 6 +++ .../onionshare_slug_persistent_test.py | 6 +++ 7 files changed, 89 insertions(+), 4 deletions(-) diff --git a/tests_gui_local/commontests.py b/tests_gui_local/commontests.py index 870c2dbe..21e8cfad 100644 --- a/tests_gui_local/commontests.py +++ b/tests_gui_local/commontests.py @@ -52,6 +52,59 @@ class CommonTests(object): QtTest.QTest.mouseClick(self.gui.share_mode.info.toggle_button, QtCore.Qt.LeftButton) self.assertEqual(self.gui.share_mode.downloads.isVisible(), not currently_visible) + def test_history_indicator(self, mode, public_mode): + '''Test that we can make sure the history is toggled off, do an action, and the indiciator works''' + if mode == 'receive': + # Make sure history is toggled off + if self.gui.receive_mode.uploads.isVisible(): + QtTest.QTest.mouseClick(self.gui.receive_mode.info.toggle_button, QtCore.Qt.LeftButton) + self.assertFalse(self.gui.receive_mode.uploads.isVisible()) + + # Indicator should not be visible yet + self.assertFalse(self.gui.receive_mode.info.indicator_label.isVisible()) + + # Upload a file + files = {'file[]': open('/tmp/test.txt', 'rb')} + if not public_mode: + path = 'http://127.0.0.1:{}/{}/upload'.format(self.gui.app.port, self.gui.receive_mode.web.slug) + else: + path = 'http://127.0.0.1:{}/upload'.format(self.gui.app.port) + response = requests.post(path, files=files) + QtTest.QTest.qWait(2000) + + # Indicator should be visible, have a value of "1" + self.assertTrue(self.gui.receive_mode.info.indicator_label.isVisible()) + self.assertEqual(self.gui.receive_mode.info.indicator_label.text(), "1") + + # Toggle history back on, indicator should be hidden again + QtTest.QTest.mouseClick(self.gui.receive_mode.info.toggle_button, QtCore.Qt.LeftButton) + self.assertFalse(self.gui.receive_mode.info.indicator_label.isVisible()) + + if mode == 'share': + # Make sure history is toggled off + if self.gui.share_mode.downloads.isVisible(): + QtTest.QTest.mouseClick(self.gui.share_mode.info.toggle_button, QtCore.Qt.LeftButton) + self.assertFalse(self.gui.share_mode.downloads.isVisible()) + + # Indicator should not be visible yet + self.assertFalse(self.gui.share_mode.info.indicator_label.isVisible()) + + # Download files + if public_mode: + url = "http://127.0.0.1:{}/download".format(self.gui.app.port) + else: + url = "http://127.0.0.1:{}/{}/download".format(self.gui.app.port, self.gui.share_mode.web.slug) + r = requests.get(url) + QtTest.QTest.qWait(2000) + + # Indicator should be visible, have a value of "1" + self.assertTrue(self.gui.share_mode.info.indicator_label.isVisible()) + self.assertEqual(self.gui.share_mode.info.indicator_label.text(), "1") + + # Toggle history back on, indicator should be hidden again + QtTest.QTest.mouseClick(self.gui.share_mode.info.toggle_button, QtCore.Qt.LeftButton) + self.assertFalse(self.gui.share_mode.info.indicator_label.isVisible()) + def test_history_is_not_visible(self, mode): '''Test that the History section is not visible''' if mode == 'receive': diff --git a/tests_gui_local/onionshare_receive_mode_upload_test.py b/tests_gui_local/onionshare_receive_mode_upload_test.py index b53d5c06..19674aa3 100644 --- a/tests_gui_local/onionshare_receive_mode_upload_test.py +++ b/tests_gui_local/onionshare_receive_mode_upload_test.py @@ -171,14 +171,18 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_counter_incremented(self, 'receive', 2) @pytest.mark.run(order=24) + def test_history_indicator(self): + CommonTests.test_history_indicator(self, 'receive', False) + + @pytest.mark.run(order=25) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'receive', False) - @pytest.mark.run(order=25) + @pytest.mark.run(order=26) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=26) + @pytest.mark.run(order=27) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) diff --git a/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py b/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py index 5e5a6b77..e3f85731 100644 --- a/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py +++ b/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py @@ -171,14 +171,18 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_counter_incremented(self, 'receive', 2) @pytest.mark.run(order=24) + def test_history_indicator(self): + CommonTests.test_history_indicator(self, 'receive', True) + + @pytest.mark.run(order=25) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'receive', False) - @pytest.mark.run(order=25) + @pytest.mark.run(order=26) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=26) + @pytest.mark.run(order=27) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) diff --git a/tests_gui_local/onionshare_share_mode_download_test.py b/tests_gui_local/onionshare_share_mode_download_test.py index 40df6d98..c4a60101 100644 --- a/tests_gui_local/onionshare_share_mode_download_test.py +++ b/tests_gui_local/onionshare_share_mode_download_test.py @@ -192,6 +192,12 @@ class OnionShareGuiTest(unittest.TestCase): def test_add_button_visible(self): CommonTests.test_add_button_visible(self) + @pytest.mark.run(order=30) + def test_history_indicator(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_history_indicator(self, 'share', False) + if __name__ == "__main__": unittest.main() diff --git a/tests_gui_local/onionshare_share_mode_download_test_public_mode.py b/tests_gui_local/onionshare_share_mode_download_test_public_mode.py index 73d4c999..a10ee4c2 100644 --- a/tests_gui_local/onionshare_share_mode_download_test_public_mode.py +++ b/tests_gui_local/onionshare_share_mode_download_test_public_mode.py @@ -192,6 +192,12 @@ class OnionShareGuiTest(unittest.TestCase): def test_add_button_visible(self): CommonTests.test_add_button_visible(self) + @pytest.mark.run(order=30) + def test_history_indicator(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_history_indicator(self, 'share', True) + if __name__ == "__main__": unittest.main() diff --git a/tests_gui_local/onionshare_share_mode_download_test_stay_open.py b/tests_gui_local/onionshare_share_mode_download_test_stay_open.py index e849d224..8426c264 100644 --- a/tests_gui_local/onionshare_share_mode_download_test_stay_open.py +++ b/tests_gui_local/onionshare_share_mode_download_test_stay_open.py @@ -204,6 +204,12 @@ class OnionShareGuiTest(unittest.TestCase): def test_add_button_visible(self): CommonTests.test_add_button_visible(self) + @pytest.mark.run(order=33) + def test_history_indicator(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_history_indicator(self, 'share', True) + if __name__ == "__main__": unittest.main() diff --git a/tests_gui_local/onionshare_slug_persistent_test.py b/tests_gui_local/onionshare_slug_persistent_test.py index 5b53f7e0..9fb623dd 100644 --- a/tests_gui_local/onionshare_slug_persistent_test.py +++ b/tests_gui_local/onionshare_slug_persistent_test.py @@ -168,6 +168,12 @@ class OnionShareGuiTest(unittest.TestCase): CommonTests.test_server_is_stopped(self, 'share', True) CommonTests.test_web_service_is_stopped(self) + @pytest.mark.run(order=23) + def test_history_indicator(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_history_indicator(self, 'share', False) + if __name__ == "__main__": unittest.main() From 7c61483ae9adea7e5b78bc45249bba8afb9efc92 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 14:48:15 -0700 Subject: [PATCH 28/50] Move Mode module into its own folder --- onionshare_gui/{mode.py => mode/__init__.py} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename onionshare_gui/{mode.py => mode/__init__.py} (99%) diff --git a/onionshare_gui/mode.py b/onionshare_gui/mode/__init__.py similarity index 99% rename from onionshare_gui/mode.py rename to onionshare_gui/mode/__init__.py index 1a961149..cfbb235b 100644 --- a/onionshare_gui/mode.py +++ b/onionshare_gui/mode/__init__.py @@ -22,9 +22,9 @@ from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings from onionshare.common import ShutdownTimer -from .server_status import ServerStatus -from .threads import OnionThread -from .widgets import Alert +from ..server_status import ServerStatus +from ..threads import OnionThread +from ..widgets import Alert class Mode(QtWidgets.QWidget): """ From 801d8b965c693b310a8c4ec5e419564577041b69 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 14:54:51 -0700 Subject: [PATCH 29/50] Move ShareMode and ReceiveMode into Mode module --- onionshare_gui/{ => mode}/receive_mode/__init__.py | 2 +- onionshare_gui/{ => mode}/receive_mode/info.py | 0 onionshare_gui/{ => mode}/receive_mode/uploads.py | 2 +- onionshare_gui/{ => mode}/share_mode/__init__.py | 4 ++-- onionshare_gui/{ => mode}/share_mode/downloads.py | 0 onionshare_gui/{ => mode}/share_mode/file_selection.py | 2 +- onionshare_gui/{ => mode}/share_mode/info.py | 0 onionshare_gui/{ => mode}/share_mode/threads.py | 0 onionshare_gui/onionshare_gui.py | 4 ++-- setup.py | 5 +++-- 10 files changed, 10 insertions(+), 9 deletions(-) rename onionshare_gui/{ => mode}/receive_mode/__init__.py (99%) rename onionshare_gui/{ => mode}/receive_mode/info.py (100%) rename onionshare_gui/{ => mode}/receive_mode/uploads.py (99%) rename onionshare_gui/{ => mode}/share_mode/__init__.py (99%) rename onionshare_gui/{ => mode}/share_mode/downloads.py (100%) rename onionshare_gui/{ => mode}/share_mode/file_selection.py (99%) rename onionshare_gui/{ => mode}/share_mode/info.py (100%) rename onionshare_gui/{ => mode}/share_mode/threads.py (100%) diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/mode/receive_mode/__init__.py similarity index 99% rename from onionshare_gui/receive_mode/__init__.py rename to onionshare_gui/mode/receive_mode/__init__.py index 6430382b..96c76dbf 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/mode/receive_mode/__init__.py @@ -24,7 +24,7 @@ from onionshare.web import Web from .uploads import Uploads from .info import ReceiveModeInfo -from ..mode import Mode +from .. import Mode class ReceiveMode(Mode): """ diff --git a/onionshare_gui/receive_mode/info.py b/onionshare_gui/mode/receive_mode/info.py similarity index 100% rename from onionshare_gui/receive_mode/info.py rename to onionshare_gui/mode/receive_mode/info.py diff --git a/onionshare_gui/receive_mode/uploads.py b/onionshare_gui/mode/receive_mode/uploads.py similarity index 99% rename from onionshare_gui/receive_mode/uploads.py rename to onionshare_gui/mode/receive_mode/uploads.py index f08b35cc..c445be47 100644 --- a/onionshare_gui/receive_mode/uploads.py +++ b/onionshare_gui/mode/receive_mode/uploads.py @@ -24,7 +24,7 @@ from datetime import datetime from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings -from ..widgets import Alert +from ...widgets import Alert class File(QtWidgets.QWidget): diff --git a/onionshare_gui/share_mode/__init__.py b/onionshare_gui/mode/share_mode/__init__.py similarity index 99% rename from onionshare_gui/share_mode/__init__.py rename to onionshare_gui/mode/share_mode/__init__.py index c44e8beb..c301037b 100644 --- a/onionshare_gui/share_mode/__init__.py +++ b/onionshare_gui/mode/share_mode/__init__.py @@ -29,8 +29,8 @@ from .file_selection import FileSelection from .downloads import Downloads from .threads import CompressThread from .info import ShareModeInfo -from ..mode import Mode -from ..widgets import Alert +from .. import Mode +from ...widgets import Alert class ShareMode(Mode): """ diff --git a/onionshare_gui/share_mode/downloads.py b/onionshare_gui/mode/share_mode/downloads.py similarity index 100% rename from onionshare_gui/share_mode/downloads.py rename to onionshare_gui/mode/share_mode/downloads.py diff --git a/onionshare_gui/share_mode/file_selection.py b/onionshare_gui/mode/share_mode/file_selection.py similarity index 99% rename from onionshare_gui/share_mode/file_selection.py rename to onionshare_gui/mode/share_mode/file_selection.py index 628ad5ef..d59df234 100644 --- a/onionshare_gui/share_mode/file_selection.py +++ b/onionshare_gui/mode/share_mode/file_selection.py @@ -22,7 +22,7 @@ from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings -from ..widgets import Alert, AddFileDialog +from ...widgets import Alert, AddFileDialog class DropHereLabel(QtWidgets.QLabel): """ diff --git a/onionshare_gui/share_mode/info.py b/onionshare_gui/mode/share_mode/info.py similarity index 100% rename from onionshare_gui/share_mode/info.py rename to onionshare_gui/mode/share_mode/info.py diff --git a/onionshare_gui/share_mode/threads.py b/onionshare_gui/mode/share_mode/threads.py similarity index 100% rename from onionshare_gui/share_mode/threads.py rename to onionshare_gui/mode/share_mode/threads.py diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index ced53ede..6a7eb63a 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -23,8 +23,8 @@ from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings from onionshare.web import Web -from .share_mode import ShareMode -from .receive_mode import ReceiveMode +from .mode.share_mode import ShareMode +from .mode.receive_mode import ReceiveMode from .tor_connection_dialog import TorConnectionDialog from .settings_dialog import SettingsDialog diff --git a/setup.py b/setup.py index 94213f7c..86b71f82 100644 --- a/setup.py +++ b/setup.py @@ -69,8 +69,9 @@ setup( 'onionshare', 'onionshare.web', 'onionshare_gui', - 'onionshare_gui.share_mode', - 'onionshare_gui.receive_mode' + 'onionshare_gui.mode', + 'onionshare_gui.mode.share_mode', + 'onionshare_gui.mode.receive_mode' ], include_package_data=True, scripts=['install/scripts/onionshare', 'install/scripts/onionshare-gui'], From 5a8cb2ac9dd3eadc5540f42766c779789304f3d1 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 15:20:22 -0700 Subject: [PATCH 30/50] In ShareMode, remove the ShareModeInfo widget and replace with a customized ToggleHistory widget --- onionshare_gui/mode/share_mode/__init__.py | 54 ++++++++----- onionshare_gui/mode/toggle_history.py | 88 ++++++++++++++++++++++ 2 files changed, 124 insertions(+), 18 deletions(-) create mode 100644 onionshare_gui/mode/toggle_history.py diff --git a/onionshare_gui/mode/share_mode/__init__.py b/onionshare_gui/mode/share_mode/__init__.py index c301037b..f7ba2760 100644 --- a/onionshare_gui/mode/share_mode/__init__.py +++ b/onionshare_gui/mode/share_mode/__init__.py @@ -28,8 +28,9 @@ from onionshare.web import Web from .file_selection import FileSelection from .downloads import Downloads from .threads import CompressThread -from .info import ShareModeInfo +#from .info import ShareModeInfo from .. import Mode +from ..toggle_history import ToggleHistory from ...widgets import Alert class ShareMode(Mode): @@ -78,7 +79,24 @@ class ShareMode(Mode): self.downloads_completed = 0 # Information about share, and show downloads button - self.info = ShareModeInfo(self.common, self) + #self.info = ShareModeInfo(self.common, self) + + # Info label + self.info_label = QtWidgets.QLabel() + self.info_label.hide() + + # Toggle history + self.toggle_history = ToggleHistory( + self.common, self, self.downloads, + QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle.png')), + QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle_selected.png')) + ) + + # Top bar + top_bar_layout = QtWidgets.QHBoxLayout() + top_bar_layout.addWidget(self.info_label) + top_bar_layout.addStretch() + top_bar_layout.addWidget(self.toggle_history) # Primary action layout self.primary_action_layout.addWidget(self.filesize_warning) @@ -90,7 +108,7 @@ class ShareMode(Mode): # Main layout self.main_layout = QtWidgets.QVBoxLayout() - self.main_layout.addWidget(self.info) + self.main_layout.addLayout(top_bar_layout) self.main_layout.addLayout(self.file_selection) self.main_layout.addWidget(self.primary_action) self.main_layout.addWidget(self.min_width_widget) @@ -191,7 +209,7 @@ class ShareMode(Mode): self.filesize_warning.hide() self.downloads_in_progress = 0 self.downloads_completed = 0 - self.info.update_downloads_in_progress() + #self.info.update_downloads_in_progress() self.file_selection.file_list.adjustSize() def cancel_server_custom(self): @@ -207,7 +225,7 @@ class ShareMode(Mode): Connection to Tor broke. """ self.primary_action.hide() - self.info.show_less() + self.info_label.hide() def handle_request_load(self, event): """ @@ -224,9 +242,9 @@ class ShareMode(Mode): else: filesize = self.web.share_mode.download_filesize self.downloads.add(event["data"]["id"], filesize) - self.info.update_indicator(True) + self.toggle_history.update_indicator(True) self.downloads_in_progress += 1 - self.info.update_downloads_in_progress() + #self.info.update_downloads_in_progress() self.system_tray.showMessage(strings._('systray_download_started_title', True), strings._('systray_download_started_message', True)) @@ -242,10 +260,10 @@ class ShareMode(Mode): # Update the total 'completed downloads' info self.downloads_completed += 1 - self.info.update_downloads_completed() + #self.info.update_downloads_completed() # Update the 'in progress downloads' info self.downloads_in_progress -= 1 - self.info.update_downloads_in_progress() + #self.info.update_downloads_in_progress() # Close on finish? if self.common.settings.get('close_after_first_download'): @@ -256,7 +274,7 @@ class ShareMode(Mode): if self.server_status.status == self.server_status.STATUS_STOPPED: self.downloads.cancel(event["data"]["id"]) self.downloads_in_progress = 0 - self.info.update_downloads_in_progress() + #self.info.update_downloads_in_progress() def handle_request_canceled(self, event): """ @@ -266,7 +284,7 @@ class ShareMode(Mode): # Update the 'in progress downloads' info self.downloads_in_progress -= 1 - self.info.update_downloads_in_progress() + #self.info.update_downloads_in_progress() self.system_tray.showMessage(strings._('systray_download_canceled_title', True), strings._('systray_download_canceled_message', True)) def on_reload_settings(self): @@ -276,7 +294,7 @@ class ShareMode(Mode): """ if self.server_status.file_selection.get_num_files() > 0: self.primary_action.show() - self.info.show_more() + self.info_label.show() def update_primary_action(self): self.common.log('ShareMode', 'update_primary_action') @@ -285,7 +303,7 @@ class ShareMode(Mode): file_count = self.file_selection.file_list.count() if file_count > 0: self.primary_action.show() - self.info.show_more() + self.info_label.show() # Update the file count in the info label total_size_bytes = 0 @@ -295,13 +313,13 @@ class ShareMode(Mode): total_size_readable = self.common.human_readable_filesize(total_size_bytes) if file_count > 1: - self.info.update_label(strings._('gui_file_info', True).format(file_count, total_size_readable)) + self.info_label.setText(strings._('gui_file_info', True).format(file_count, total_size_readable)) else: - self.info.update_label(strings._('gui_file_info_single', True).format(file_count, total_size_readable)) + self.info_label.setText(strings._('gui_file_info_single', True).format(file_count, total_size_readable)) else: self.primary_action.hide() - self.info.show_less() + self.info_label.hide() # Resize window self.resize_window() @@ -312,8 +330,8 @@ class ShareMode(Mode): """ self.downloads_completed = 0 self.downloads_in_progress = 0 - self.info.update_downloads_completed() - self.info.update_downloads_in_progress() + #self.info.update_downloads_completed() + #self.info.update_downloads_in_progress() self.downloads.reset() def resize_window(self): diff --git a/onionshare_gui/mode/toggle_history.py b/onionshare_gui/mode/toggle_history.py new file mode 100644 index 00000000..81ecde86 --- /dev/null +++ b/onionshare_gui/mode/toggle_history.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +""" +OnionShare | https://onionshare.org/ + +Copyright (C) 2014-2018 Micah Lee + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +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 . +""" +from PyQt5 import QtCore, QtWidgets, QtGui + +from onionshare import strings + + +class ToggleHistory(QtWidgets.QPushButton): + """ + Widget for toggling download/upload history on or off, as well as keeping track + of the indicator counter + """ + def __init__(self, common, current_mode, history_widget, icon, selected_icon): + super(ToggleHistory, self).__init__() + self.common = common + self.current_mode = current_mode + self.history_widget = history_widget + self.icon = icon + self.selected_icon = selected_icon + + # Toggle button + self.setDefault(False) + self.setFixedWidth(35) + self.setFixedHeight(30) + self.setFlat(True) + self.setIcon(icon) + self.clicked.connect(self.toggle_clicked) + + # Keep track of indicator + self.indicator_count = 0 + self.indicator_label = QtWidgets.QLabel(parent=self) + self.indicator_label.setStyleSheet(self.common.css['download_uploads_indicator']) + self.update_indicator() + + def update_indicator(self, increment=False): + """ + Update the display of the indicator count. If increment is True, then + only increment the counter if Downloads is hidden. + """ + if increment and not self.history_widget.isVisible(): + self.indicator_count += 1 + + self.indicator_label.setText("{}".format(self.indicator_count)) + + if self.indicator_count == 0: + self.indicator_label.hide() + else: + size = self.indicator_label.sizeHint() + self.indicator_label.setGeometry(35-size.width(), 0, size.width(), size.height()) + self.indicator_label.show() + + def toggle_clicked(self): + """ + Toggle showing and hiding the history widget + """ + self.common.log('ToggleHistory', 'toggle_clicked') + + if self.history_widget.isVisible(): + self.history_widget.hide() + self.setIcon(self.icon) + self.setFlat(True) + else: + self.history_widget.show() + self.setIcon(self.selected_icon) + self.setFlat(False) + + # Reset the indicator count + self.indicator_count = 0 + self.update_indicator() + + self.current_mode.resize_window() From 484c33902fb6ddc6a5262e0e025b8b86c2854283 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 17:35:15 -0700 Subject: [PATCH 31/50] Make ShareMode just use a History object directly, instead of defining its own Downloads class --- onionshare_gui/mode/history.py | 328 ++++++++++++++++++++ onionshare_gui/mode/share_mode/__init__.py | 34 +- onionshare_gui/mode/share_mode/downloads.py | 248 --------------- onionshare_gui/mode/toggle_history.py | 88 ------ 4 files changed, 348 insertions(+), 350 deletions(-) create mode 100644 onionshare_gui/mode/history.py delete mode 100644 onionshare_gui/mode/share_mode/downloads.py delete mode 100644 onionshare_gui/mode/toggle_history.py diff --git a/onionshare_gui/mode/history.py b/onionshare_gui/mode/history.py new file mode 100644 index 00000000..31b4a646 --- /dev/null +++ b/onionshare_gui/mode/history.py @@ -0,0 +1,328 @@ +# -*- coding: utf-8 -*- +""" +OnionShare | https://onionshare.org/ + +Copyright (C) 2014-2018 Micah Lee + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +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 time +from PyQt5 import QtCore, QtWidgets, QtGui + +from onionshare import strings + + +class HistoryItem(QtWidgets.QWidget): + """ + The base history item + """ + def __init__(self): + super(HistoryItem, self).__init__() + + def update(self): + pass + + def cancel(self): + pass + + +class DownloadHistoryItem(HistoryItem): + """ + Download history item, for share mode + """ + def __init__(self, common, id, total_bytes): + super(DownloadHistoryItem, self).__init__() + self.common = common + + self.id = id + self.started = time.time() + self.total_bytes = total_bytes + self.downloaded_bytes = 0 + + self.setStyleSheet('QWidget { border: 1px solid red; }') + + # Progress bar + self.progress_bar = QtWidgets.QProgressBar() + self.progress_bar.setTextVisible(True) + self.progress_bar.setAttribute(QtCore.Qt.WA_DeleteOnClose) + self.progress_bar.setAlignment(QtCore.Qt.AlignHCenter) + self.progress_bar.setMinimum(0) + self.progress_bar.setMaximum(total_bytes) + self.progress_bar.setValue(0) + self.progress_bar.setStyleSheet(self.common.css['downloads_uploads_progress_bar']) + self.progress_bar.total_bytes = total_bytes + + # Layout + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.progress_bar) + self.setLayout(layout) + + # Start at 0 + self.update(0) + + def update(self, downloaded_bytes): + self.downloaded_bytes = downloaded_bytes + + self.progress_bar.setValue(downloaded_bytes) + if downloaded_bytes == self.progress_bar.total_bytes: + pb_fmt = strings._('gui_download_upload_progress_complete').format( + self.common.format_seconds(time.time() - self.started)) + else: + elapsed = time.time() - self.started + if elapsed < 10: + # Wait a couple of seconds for the download rate to stabilize. + # This prevents a "Windows copy dialog"-esque experience at + # the beginning of the download. + pb_fmt = strings._('gui_download_upload_progress_starting').format( + self.common.human_readable_filesize(downloaded_bytes)) + else: + pb_fmt = strings._('gui_download_upload_progress_eta').format( + self.common.human_readable_filesize(downloaded_bytes), + self.estimated_time_remaining) + + self.progress_bar.setFormat(pb_fmt) + + def cancel(self): + self.progress_bar.setFormat(strings._('gui_canceled')) + + @property + def estimated_time_remaining(self): + return self.common.estimated_time_remaining(self.downloaded_bytes, + self.total_bytes, + self.started) + + +class HistoryItemList(QtWidgets.QScrollArea): + """ + List of items + """ + def __init__(self, common): + super(HistoryItemList, self).__init__() + self.common = common + + self.items = {} + + # The layout that holds all of the items + self.items_layout = QtWidgets.QVBoxLayout() + self.items_layout.setContentsMargins(0, 0, 0, 0) + self.items_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize) + + # Wrapper layout that also contains a stretch + wrapper_layout = QtWidgets.QVBoxLayout() + wrapper_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize) + wrapper_layout.addLayout(self.items_layout) + wrapper_layout.addStretch() + + # The internal widget of the scroll area + widget = QtWidgets.QWidget() + widget.setLayout(wrapper_layout) + self.setWidget(widget) + self.setWidgetResizable(True) + + # Other scroll area settings + self.setBackgroundRole(QtGui.QPalette.Light) + self.verticalScrollBar().rangeChanged.connect(self.resizeScroll) + + def resizeScroll(self, minimum, maximum): + """ + Scroll to the bottom of the window when the range changes. + """ + self.verticalScrollBar().setValue(maximum) + + def add(self, id, item): + """ + Add a new item. Override this method. + """ + self.items[id] = item + self.items_layout.addWidget(item) + + def update(self, id, data): + """ + Update an item. Override this method. + """ + self.items[id].update(data) + + def cancel(self, id): + """ + Cancel an item. Override this method. + """ + self.items[id].cancel() + + def reset(self): + """ + Reset all items, emptying the list. Override this method. + """ + for item in self.items.values(): + self.items_layout.removeWidget(item) + self.items = {} + + +class History(QtWidgets.QWidget): + """ + A history of what's happened so far in this mode. This contains an internal + object full of a scrollable list of items. + """ + def __init__(self, common, empty_image, empty_text, header_text): + super(History, self).__init__() + self.common = common + + self.setMinimumWidth(350) + + # When there are no items + self.empty_image = QtWidgets.QLabel() + self.empty_image.setAlignment(QtCore.Qt.AlignCenter) + self.empty_image.setPixmap(empty_image) + self.empty_text = QtWidgets.QLabel(empty_text) + self.empty_text.setAlignment(QtCore.Qt.AlignCenter) + self.empty_text.setStyleSheet(self.common.css['downloads_uploads_empty_text']) + empty_layout = QtWidgets.QVBoxLayout() + empty_layout.addStretch() + empty_layout.addWidget(self.empty_image) + empty_layout.addWidget(self.empty_text) + empty_layout.addStretch() + self.empty = QtWidgets.QWidget() + self.empty.setStyleSheet(self.common.css['downloads_uploads_empty']) + self.empty.setLayout(empty_layout) + + # Header + self.header_label = QtWidgets.QLabel(header_text) + self.header_label.setStyleSheet(self.common.css['downloads_uploads_label']) + clear_button = QtWidgets.QPushButton(strings._('gui_clear_history', True)) + clear_button.setStyleSheet(self.common.css['downloads_uploads_clear']) + clear_button.setFlat(True) + clear_button.clicked.connect(self.reset) + header_layout = QtWidgets.QHBoxLayout() + header_layout.addWidget(self.header_label) + header_layout.addStretch() + header_layout.addWidget(clear_button) + + # When there are items + self.item_list = HistoryItemList(self.common) + self.not_empty_layout = QtWidgets.QVBoxLayout() + self.not_empty_layout.addLayout(header_layout) + self.not_empty_layout.addWidget(self.item_list) + self.not_empty = QtWidgets.QWidget() + self.not_empty.setLayout(self.not_empty_layout) + + # Layout + layout = QtWidgets.QVBoxLayout() + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(self.empty) + layout.addWidget(self.not_empty) + self.setLayout(layout) + + # Reset once at the beginning + self.reset() + + def add(self, id, item): + """ + Add a new item. + """ + self.common.log('History', 'add', 'id: {}, item: {}'.format(id, item)) + + # Hide empty, show not empty + self.empty.hide() + self.not_empty.show() + + # Add it to the list + self.item_list.add(id, item) + + + def update(self, id, data): + """ + Update an item. + """ + self.item_list.update(id, data) + + def cancel(self, id): + """ + Cancel an item. + """ + self.item_list.cancel(id) + + def reset(self): + """ + Reset all items. + """ + self.item_list.reset() + + # Hide not empty, show empty + self.not_empty.hide() + self.empty.show() + + +class ToggleHistory(QtWidgets.QPushButton): + """ + Widget for toggling showing or hiding the history, as well as keeping track + of the indicator counter if it's hidden + """ + def __init__(self, common, current_mode, history_widget, icon, selected_icon): + super(ToggleHistory, self).__init__() + self.common = common + self.current_mode = current_mode + self.history_widget = history_widget + self.icon = icon + self.selected_icon = selected_icon + + # Toggle button + self.setDefault(False) + self.setFixedWidth(35) + self.setFixedHeight(30) + self.setFlat(True) + self.setIcon(icon) + self.clicked.connect(self.toggle_clicked) + + # Keep track of indicator + self.indicator_count = 0 + self.indicator_label = QtWidgets.QLabel(parent=self) + self.indicator_label.setStyleSheet(self.common.css['download_uploads_indicator']) + self.update_indicator() + + def update_indicator(self, increment=False): + """ + Update the display of the indicator count. If increment is True, then + only increment the counter if Downloads is hidden. + """ + if increment and not self.history_widget.isVisible(): + self.indicator_count += 1 + + self.indicator_label.setText("{}".format(self.indicator_count)) + + if self.indicator_count == 0: + self.indicator_label.hide() + else: + size = self.indicator_label.sizeHint() + self.indicator_label.setGeometry(35-size.width(), 0, size.width(), size.height()) + self.indicator_label.show() + + def toggle_clicked(self): + """ + Toggle showing and hiding the history widget + """ + self.common.log('ToggleHistory', 'toggle_clicked') + + if self.history_widget.isVisible(): + self.history_widget.hide() + self.setIcon(self.icon) + self.setFlat(True) + else: + self.history_widget.show() + self.setIcon(self.selected_icon) + self.setFlat(False) + + # Reset the indicator count + self.indicator_count = 0 + self.update_indicator() + + self.current_mode.resize_window() diff --git a/onionshare_gui/mode/share_mode/__init__.py b/onionshare_gui/mode/share_mode/__init__.py index f7ba2760..bae4bec8 100644 --- a/onionshare_gui/mode/share_mode/__init__.py +++ b/onionshare_gui/mode/share_mode/__init__.py @@ -26,13 +26,12 @@ from onionshare.common import Common from onionshare.web import Web from .file_selection import FileSelection -from .downloads import Downloads from .threads import CompressThread -#from .info import ShareModeInfo from .. import Mode -from ..toggle_history import ToggleHistory +from ..history import History, ToggleHistory, DownloadHistoryItem from ...widgets import Alert + class ShareMode(Mode): """ Parts of the main window UI for sharing files. @@ -72,9 +71,14 @@ class ShareMode(Mode): self.filesize_warning.setStyleSheet(self.common.css['share_filesize_warning']) self.filesize_warning.hide() - # Downloads - self.downloads = Downloads(self.common) - self.downloads.hide() + # Download history + self.history = History( + self.common, + QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/downloads_transparent.png'))), + strings._('gui_no_downloads'), + strings._('gui_downloads') + ) + self.history.hide() self.downloads_in_progress = 0 self.downloads_completed = 0 @@ -87,7 +91,7 @@ class ShareMode(Mode): # Toggle history self.toggle_history = ToggleHistory( - self.common, self, self.downloads, + self.common, self, self.history, QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle.png')), QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle_selected.png')) ) @@ -116,7 +120,7 @@ class ShareMode(Mode): # Wrapper layout self.wrapper_layout = QtWidgets.QHBoxLayout() self.wrapper_layout.addLayout(self.main_layout) - self.wrapper_layout.addWidget(self.downloads) + self.wrapper_layout.addWidget(self.history) self.setLayout(self.wrapper_layout) # Always start with focus on file selection @@ -241,7 +245,9 @@ class ShareMode(Mode): filesize = self.web.share_mode.gzip_filesize else: filesize = self.web.share_mode.download_filesize - self.downloads.add(event["data"]["id"], filesize) + + item = DownloadHistoryItem(self.common, event["data"]["id"], filesize) + self.history.add(event["data"]["id"], item) self.toggle_history.update_indicator(True) self.downloads_in_progress += 1 #self.info.update_downloads_in_progress() @@ -252,7 +258,7 @@ class ShareMode(Mode): """ Handle REQUEST_PROGRESS event. """ - self.downloads.update(event["data"]["id"], event["data"]["bytes"]) + self.history.update(event["data"]["id"], event["data"]["bytes"]) # Is the download complete? if event["data"]["bytes"] == self.web.share_mode.filesize: @@ -272,7 +278,7 @@ class ShareMode(Mode): self.server_status_label.setText(strings._('closing_automatically', True)) else: if self.server_status.status == self.server_status.STATUS_STOPPED: - self.downloads.cancel(event["data"]["id"]) + self.history.cancel(event["data"]["id"]) self.downloads_in_progress = 0 #self.info.update_downloads_in_progress() @@ -280,7 +286,7 @@ class ShareMode(Mode): """ Handle REQUEST_CANCELED event. """ - self.downloads.cancel(event["data"]["id"]) + self.history.cancel(event["data"]["id"]) # Update the 'in progress downloads' info self.downloads_in_progress -= 1 @@ -332,11 +338,11 @@ class ShareMode(Mode): self.downloads_in_progress = 0 #self.info.update_downloads_completed() #self.info.update_downloads_in_progress() - self.downloads.reset() + self.history.reset() def resize_window(self): min_width = self.common.min_window_width - if self.downloads.isVisible(): + if self.history.isVisible(): min_width += 300 self.adjust_size.emit(min_width) diff --git a/onionshare_gui/mode/share_mode/downloads.py b/onionshare_gui/mode/share_mode/downloads.py deleted file mode 100644 index e78231ad..00000000 --- a/onionshare_gui/mode/share_mode/downloads.py +++ /dev/null @@ -1,248 +0,0 @@ -# -*- coding: utf-8 -*- -""" -OnionShare | https://onionshare.org/ - -Copyright (C) 2014-2018 Micah Lee - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -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 time -from PyQt5 import QtCore, QtWidgets, QtGui - -from onionshare import strings - - -class Download(QtWidgets.QWidget): - def __init__(self, common, download_id, total_bytes): - super(Download, self).__init__() - self.common = common - - self.download_id = download_id - self.started = time.time() - self.total_bytes = total_bytes - self.downloaded_bytes = 0 - - self.setStyleSheet('QWidget { border: 1px solid red; }') - - # Progress bar - self.progress_bar = QtWidgets.QProgressBar() - self.progress_bar.setTextVisible(True) - self.progress_bar.setAttribute(QtCore.Qt.WA_DeleteOnClose) - self.progress_bar.setAlignment(QtCore.Qt.AlignHCenter) - self.progress_bar.setMinimum(0) - self.progress_bar.setMaximum(total_bytes) - self.progress_bar.setValue(0) - self.progress_bar.setStyleSheet(self.common.css['downloads_uploads_progress_bar']) - self.progress_bar.total_bytes = total_bytes - - # Layout - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.progress_bar) - self.setLayout(layout) - - # Start at 0 - self.update(0) - - def update(self, downloaded_bytes): - self.downloaded_bytes = downloaded_bytes - - self.progress_bar.setValue(downloaded_bytes) - if downloaded_bytes == self.progress_bar.total_bytes: - pb_fmt = strings._('gui_download_upload_progress_complete').format( - self.common.format_seconds(time.time() - self.started)) - else: - elapsed = time.time() - self.started - if elapsed < 10: - # Wait a couple of seconds for the download rate to stabilize. - # This prevents a "Windows copy dialog"-esque experience at - # the beginning of the download. - pb_fmt = strings._('gui_download_upload_progress_starting').format( - self.common.human_readable_filesize(downloaded_bytes)) - else: - pb_fmt = strings._('gui_download_upload_progress_eta').format( - self.common.human_readable_filesize(downloaded_bytes), - self.estimated_time_remaining) - - self.progress_bar.setFormat(pb_fmt) - - def cancel(self): - self.progress_bar.setFormat(strings._('gui_canceled')) - - @property - def estimated_time_remaining(self): - return self.common.estimated_time_remaining(self.downloaded_bytes, - self.total_bytes, - self.started) - - -class DownloadList(QtWidgets.QScrollArea): - """ - List of download progress bars. - """ - def __init__(self, common): - super(DownloadList, self).__init__() - self.common = common - - self.downloads = {} - - # The layout that holds all of the downloads - self.downloads_layout = QtWidgets.QVBoxLayout() - self.downloads_layout.setContentsMargins(0, 0, 0, 0) - self.downloads_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize) - - # Wrapper layout that also contains a stretch - wrapper_layout = QtWidgets.QVBoxLayout() - wrapper_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize) - wrapper_layout.addLayout(self.downloads_layout) - wrapper_layout.addStretch() - - # The internal widget of the scroll area - widget = QtWidgets.QWidget() - widget.setLayout(wrapper_layout) - self.setWidget(widget) - self.setWidgetResizable(True) - - # Other scroll area settings - self.setBackgroundRole(QtGui.QPalette.Light) - self.verticalScrollBar().rangeChanged.connect(self.resizeScroll) - - def resizeScroll(self, minimum, maximum): - """ - Scroll to the bottom of the window when the range changes. - """ - self.verticalScrollBar().setValue(maximum) - - def add(self, download_id, content_length): - """ - Add a new download progress bar. - """ - download = Download(self.common, download_id, content_length) - self.downloads[download_id] = download - self.downloads_layout.addWidget(download) - - def update(self, download_id, downloaded_bytes): - """ - Update the progress of a download progress bar. - """ - self.downloads[download_id].update(downloaded_bytes) - - def cancel(self, download_id): - """ - Update a download progress bar to show that it has been canceled. - """ - self.downloads[download_id].cancel() - - def reset(self): - """ - Reset the downloads back to zero - """ - for download in self.downloads.values(): - self.downloads_layout.removeWidget(download) - download.progress_bar.close() - self.downloads = {} - - -class Downloads(QtWidgets.QWidget): - """ - The downloads chunk of the GUI. This lists all of the active download - progress bars. - """ - def __init__(self, common): - super(Downloads, self).__init__() - self.common = common - - self.setMinimumWidth(350) - - # When there are no downloads - empty_image = QtWidgets.QLabel() - empty_image.setAlignment(QtCore.Qt.AlignCenter) - empty_image.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/downloads_transparent.png')))) - empty_text = QtWidgets.QLabel(strings._('gui_no_downloads', True)) - empty_text.setAlignment(QtCore.Qt.AlignCenter) - empty_text.setStyleSheet(self.common.css['downloads_uploads_empty_text']) - empty_layout = QtWidgets.QVBoxLayout() - empty_layout.addStretch() - empty_layout.addWidget(empty_image) - empty_layout.addWidget(empty_text) - empty_layout.addStretch() - self.empty = QtWidgets.QWidget() - self.empty.setStyleSheet(self.common.css['downloads_uploads_empty']) - self.empty.setLayout(empty_layout) - - # When there are downloads - self.download_list = DownloadList(self.common) - - # Download header - downloads_label = QtWidgets.QLabel(strings._('gui_downloads', True)) - downloads_label.setStyleSheet(self.common.css['downloads_uploads_label']) - clear_button = QtWidgets.QPushButton(strings._('gui_clear_history', True)) - clear_button.setStyleSheet(self.common.css['downloads_uploads_clear']) - clear_button.setFlat(True) - clear_button.clicked.connect(self.reset) - download_header = QtWidgets.QHBoxLayout() - download_header.addWidget(downloads_label) - download_header.addStretch() - download_header.addWidget(clear_button) - - # Download layout - not_empty_layout = QtWidgets.QVBoxLayout() - not_empty_layout.addLayout(download_header) - not_empty_layout.addWidget(self.download_list) - self.not_empty = QtWidgets.QWidget() - self.not_empty.setLayout(not_empty_layout) - - # Layout - layout = QtWidgets.QVBoxLayout() - layout.setContentsMargins(0, 0, 0, 0) - layout.addWidget(self.empty) - layout.addWidget(self.not_empty) - self.setLayout(layout) - - # Reset once at the beginning - self.reset() - - def add(self, download_id, content_length): - """ - Add a new download progress bar. - """ - self.common.log('Downloads', 'add', 'download_id: {}, content_length: {}'.format(download_id, content_length)) - - # Hide empty, show not empty - self.empty.hide() - self.not_empty.show() - - # Add it to the list - self.download_list.add(download_id, content_length) - - def update(self, download_id, downloaded_bytes): - """ - Update the progress of a download progress bar. - """ - self.download_list.update(download_id, downloaded_bytes) - - def cancel(self, download_id): - """ - Update a download progress bar to show that it has been canceled. - """ - self.download_list.cancel(download_id) - - def reset(self): - """ - Reset the downloads back to zero - """ - self.download_list.reset() - - # Hide not empty, show empty - self.not_empty.hide() - self.empty.show() diff --git a/onionshare_gui/mode/toggle_history.py b/onionshare_gui/mode/toggle_history.py deleted file mode 100644 index 81ecde86..00000000 --- a/onionshare_gui/mode/toggle_history.py +++ /dev/null @@ -1,88 +0,0 @@ -# -*- coding: utf-8 -*- -""" -OnionShare | https://onionshare.org/ - -Copyright (C) 2014-2018 Micah Lee - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -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 . -""" -from PyQt5 import QtCore, QtWidgets, QtGui - -from onionshare import strings - - -class ToggleHistory(QtWidgets.QPushButton): - """ - Widget for toggling download/upload history on or off, as well as keeping track - of the indicator counter - """ - def __init__(self, common, current_mode, history_widget, icon, selected_icon): - super(ToggleHistory, self).__init__() - self.common = common - self.current_mode = current_mode - self.history_widget = history_widget - self.icon = icon - self.selected_icon = selected_icon - - # Toggle button - self.setDefault(False) - self.setFixedWidth(35) - self.setFixedHeight(30) - self.setFlat(True) - self.setIcon(icon) - self.clicked.connect(self.toggle_clicked) - - # Keep track of indicator - self.indicator_count = 0 - self.indicator_label = QtWidgets.QLabel(parent=self) - self.indicator_label.setStyleSheet(self.common.css['download_uploads_indicator']) - self.update_indicator() - - def update_indicator(self, increment=False): - """ - Update the display of the indicator count. If increment is True, then - only increment the counter if Downloads is hidden. - """ - if increment and not self.history_widget.isVisible(): - self.indicator_count += 1 - - self.indicator_label.setText("{}".format(self.indicator_count)) - - if self.indicator_count == 0: - self.indicator_label.hide() - else: - size = self.indicator_label.sizeHint() - self.indicator_label.setGeometry(35-size.width(), 0, size.width(), size.height()) - self.indicator_label.show() - - def toggle_clicked(self): - """ - Toggle showing and hiding the history widget - """ - self.common.log('ToggleHistory', 'toggle_clicked') - - if self.history_widget.isVisible(): - self.history_widget.hide() - self.setIcon(self.icon) - self.setFlat(True) - else: - self.history_widget.show() - self.setIcon(self.selected_icon) - self.setFlat(False) - - # Reset the indicator count - self.indicator_count = 0 - self.update_indicator() - - self.current_mode.resize_window() From bc573209d9be256822bee00dec6c1376ee197a98 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 18:09:02 -0700 Subject: [PATCH 32/50] Delete Info widget, and move completed and in progress widgets into the header of history --- onionshare_gui/mode/history.py | 68 ++++++++-- onionshare_gui/mode/share_mode/__init__.py | 40 +++--- onionshare_gui/mode/share_mode/info.py | 149 --------------------- share/locale/en.json | 4 +- 4 files changed, 72 insertions(+), 189 deletions(-) delete mode 100644 onionshare_gui/mode/share_mode/info.py diff --git a/onionshare_gui/mode/history.py b/onionshare_gui/mode/history.py index 31b4a646..a28340a4 100644 --- a/onionshare_gui/mode/history.py +++ b/onionshare_gui/mode/history.py @@ -179,6 +179,30 @@ class History(QtWidgets.QWidget): self.setMinimumWidth(350) + # In progress and completed counters + self.in_progress_count = 0 + self.completed_count = 0 + + # In progress and completed labels + self.in_progress_label = QtWidgets.QLabel() + self.in_progress_label.setStyleSheet(self.common.css['mode_info_label']) + self.completed_label = QtWidgets.QLabel() + self.completed_label.setStyleSheet(self.common.css['mode_info_label']) + + # Header + self.header_label = QtWidgets.QLabel(header_text) + self.header_label.setStyleSheet(self.common.css['downloads_uploads_label']) + clear_button = QtWidgets.QPushButton(strings._('gui_clear_history', True)) + clear_button.setStyleSheet(self.common.css['downloads_uploads_clear']) + clear_button.setFlat(True) + clear_button.clicked.connect(self.reset) + header_layout = QtWidgets.QHBoxLayout() + header_layout.addWidget(self.header_label) + header_layout.addStretch() + header_layout.addWidget(self.in_progress_label) + header_layout.addWidget(self.completed_label) + header_layout.addWidget(clear_button) + # When there are no items self.empty_image = QtWidgets.QLabel() self.empty_image.setAlignment(QtCore.Qt.AlignCenter) @@ -195,22 +219,9 @@ class History(QtWidgets.QWidget): self.empty.setStyleSheet(self.common.css['downloads_uploads_empty']) self.empty.setLayout(empty_layout) - # Header - self.header_label = QtWidgets.QLabel(header_text) - self.header_label.setStyleSheet(self.common.css['downloads_uploads_label']) - clear_button = QtWidgets.QPushButton(strings._('gui_clear_history', True)) - clear_button.setStyleSheet(self.common.css['downloads_uploads_clear']) - clear_button.setFlat(True) - clear_button.clicked.connect(self.reset) - header_layout = QtWidgets.QHBoxLayout() - header_layout.addWidget(self.header_label) - header_layout.addStretch() - header_layout.addWidget(clear_button) - # When there are items self.item_list = HistoryItemList(self.common) self.not_empty_layout = QtWidgets.QVBoxLayout() - self.not_empty_layout.addLayout(header_layout) self.not_empty_layout.addWidget(self.item_list) self.not_empty = QtWidgets.QWidget() self.not_empty.setLayout(self.not_empty_layout) @@ -218,12 +229,15 @@ class History(QtWidgets.QWidget): # Layout layout = QtWidgets.QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) + layout.addLayout(header_layout) layout.addWidget(self.empty) layout.addWidget(self.not_empty) self.setLayout(layout) # Reset once at the beginning self.reset() + self.update_completed() + self.update_in_progress() def add(self, id, item): """ @@ -261,6 +275,34 @@ class History(QtWidgets.QWidget): self.not_empty.hide() self.empty.show() + # Reset counters + self.completed_count = 0 + self.in_progress_count = 0 + self.update_completed() + self.update_in_progress() + + def update_completed(self): + """ + Update the 'completed' widget. + """ + if self.completed_count == 0: + image = self.common.get_resource_path('images/share_completed_none.png') + else: + image = self.common.get_resource_path('images/share_completed.png') + self.completed_label.setText(' {1:d}'.format(image, self.completed_count)) + self.completed_label.setToolTip(strings._('history_completed_tooltip').format(self.completed_count)) + + def update_in_progress(self): + """ + Update the 'in progress' widget. + """ + if self.in_progress_count == 0: + image = self.common.get_resource_path('images/share_in_progress_none.png') + else: + image = self.common.get_resource_path('images/share_in_progress.png') + self.in_progress_label.setText(' {1:d}'.format(image, self.in_progress_count)) + self.in_progress_label.setToolTip(strings._('history_in_progress_tooltip', True).format(self.in_progress_count)) + class ToggleHistory(QtWidgets.QPushButton): """ diff --git a/onionshare_gui/mode/share_mode/__init__.py b/onionshare_gui/mode/share_mode/__init__.py index bae4bec8..0bf094c0 100644 --- a/onionshare_gui/mode/share_mode/__init__.py +++ b/onionshare_gui/mode/share_mode/__init__.py @@ -79,11 +79,6 @@ class ShareMode(Mode): strings._('gui_downloads') ) self.history.hide() - self.downloads_in_progress = 0 - self.downloads_completed = 0 - - # Information about share, and show downloads button - #self.info = ShareModeInfo(self.common, self) # Info label self.info_label = QtWidgets.QLabel() @@ -211,9 +206,9 @@ class ShareMode(Mode): self._zip_progress_bar = None self.filesize_warning.hide() - self.downloads_in_progress = 0 - self.downloads_completed = 0 - #self.info.update_downloads_in_progress() + self.history.in_progress_count = 0 + self.history.completed_count = 0 + self.history.update_in_progress() self.file_selection.file_list.adjustSize() def cancel_server_custom(self): @@ -249,8 +244,8 @@ class ShareMode(Mode): item = DownloadHistoryItem(self.common, event["data"]["id"], filesize) self.history.add(event["data"]["id"], item) self.toggle_history.update_indicator(True) - self.downloads_in_progress += 1 - #self.info.update_downloads_in_progress() + self.history.in_progress_count += 1 + self.history.update_in_progress() self.system_tray.showMessage(strings._('systray_download_started_title', True), strings._('systray_download_started_message', True)) @@ -264,12 +259,11 @@ class ShareMode(Mode): if event["data"]["bytes"] == self.web.share_mode.filesize: 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.info.update_downloads_completed() - # Update the 'in progress downloads' info - self.downloads_in_progress -= 1 - #self.info.update_downloads_in_progress() + # Update completed and in progress labels + self.history.completed_count += 1 + self.history.in_progress_count -= 1 + self.history.update_completed() + self.history.update_in_progress() # Close on finish? if self.common.settings.get('close_after_first_download'): @@ -279,8 +273,8 @@ class ShareMode(Mode): else: if self.server_status.status == self.server_status.STATUS_STOPPED: self.history.cancel(event["data"]["id"]) - self.downloads_in_progress = 0 - #self.info.update_downloads_in_progress() + self.history.in_progress_count = 0 + self.history.update_in_progress() def handle_request_canceled(self, event): """ @@ -288,9 +282,9 @@ class ShareMode(Mode): """ self.history.cancel(event["data"]["id"]) - # Update the 'in progress downloads' info - self.downloads_in_progress -= 1 - #self.info.update_downloads_in_progress() + # Update in progress count + self.history.in_progress_count -= 1 + self.history.update_in_progress() self.system_tray.showMessage(strings._('systray_download_canceled_title', True), strings._('systray_download_canceled_message', True)) def on_reload_settings(self): @@ -334,10 +328,6 @@ class ShareMode(Mode): """ Set the info counters back to zero. """ - self.downloads_completed = 0 - self.downloads_in_progress = 0 - #self.info.update_downloads_completed() - #self.info.update_downloads_in_progress() self.history.reset() def resize_window(self): diff --git a/onionshare_gui/mode/share_mode/info.py b/onionshare_gui/mode/share_mode/info.py deleted file mode 100644 index c692649c..00000000 --- a/onionshare_gui/mode/share_mode/info.py +++ /dev/null @@ -1,149 +0,0 @@ -# -*- coding: utf-8 -*- -""" -OnionShare | https://onionshare.org/ - -Copyright (C) 2014-2018 Micah Lee - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -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 . -""" -from PyQt5 import QtCore, QtWidgets, QtGui - -from onionshare import strings - - -class ShareModeInfo(QtWidgets.QWidget): - """ - Share mode information widget - """ - def __init__(self, common, share_mode): - super(ShareModeInfo, self).__init__() - self.common = common - self.share_mode = share_mode - - # Label - self.label_text = "" - self.label = QtWidgets.QLabel() - self.label.setStyleSheet(self.common.css['mode_info_label']) - - # In progress and completed labels - self.in_progress_downloads_count = QtWidgets.QLabel() - self.in_progress_downloads_count.setStyleSheet(self.common.css['mode_info_label']) - self.completed_downloads_count = QtWidgets.QLabel() - self.completed_downloads_count.setStyleSheet(self.common.css['mode_info_label']) - - # Toggle button - self.toggle_button = QtWidgets.QPushButton() - self.toggle_button.setDefault(False) - self.toggle_button.setFixedWidth(35) - self.toggle_button.setFixedHeight(30) - self.toggle_button.setFlat(True) - self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle.png')) ) - self.toggle_button.clicked.connect(self.toggle_downloads) - - # Keep track of indicator - self.indicator_count = 0 - self.indicator_label = QtWidgets.QLabel(parent=self.toggle_button) - self.indicator_label.setStyleSheet(self.common.css['download_uploads_indicator']) - self.update_indicator() - - # Layout - layout = QtWidgets.QHBoxLayout() - layout.addWidget(self.label) - layout.addStretch() - layout.addWidget(self.in_progress_downloads_count) - layout.addWidget(self.completed_downloads_count) - layout.addWidget(self.toggle_button) - self.setLayout(layout) - - self.update_downloads_completed() - self.update_downloads_in_progress() - - def update_label(self, s): - """ - Updates the text of the label. - """ - self.label_text = s - self.label.setText(self.label_text) - - def update_indicator(self, increment=False): - """ - Update the display of the indicator count. If increment is True, then - only increment the counter if Downloads is hidden. - """ - if increment and not self.share_mode.downloads.isVisible(): - self.indicator_count += 1 - - self.indicator_label.setText("{}".format(self.indicator_count)) - - if self.indicator_count == 0: - self.indicator_label.hide() - else: - size = self.indicator_label.sizeHint() - self.indicator_label.setGeometry(35-size.width(), 0, size.width(), size.height()) - self.indicator_label.show() - - def update_downloads_completed(self): - """ - Update the 'Downloads completed' info widget. - """ - if self.share_mode.downloads_completed == 0: - image = self.common.get_resource_path('images/share_completed_none.png') - else: - image = self.common.get_resource_path('images/share_completed.png') - self.completed_downloads_count.setText(' {1:d}'.format(image, self.share_mode.downloads_completed)) - self.completed_downloads_count.setToolTip(strings._('info_completed_downloads_tooltip', True).format(self.share_mode.downloads_completed)) - - def update_downloads_in_progress(self): - """ - Update the 'Downloads in progress' info widget. - """ - if self.share_mode.downloads_in_progress == 0: - image = self.common.get_resource_path('images/share_in_progress_none.png') - else: - image = self.common.get_resource_path('images/share_in_progress.png') - self.in_progress_downloads_count.setText(' {1:d}'.format(image, self.share_mode.downloads_in_progress)) - self.in_progress_downloads_count.setToolTip(strings._('info_in_progress_downloads_tooltip', True).format(self.share_mode.downloads_in_progress)) - - def toggle_downloads(self): - """ - Toggle showing and hiding the Downloads widget - """ - self.common.log('ShareModeInfo', 'toggle_downloads') - - if self.share_mode.downloads.isVisible(): - self.share_mode.downloads.hide() - self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle.png')) ) - self.toggle_button.setFlat(True) - else: - self.share_mode.downloads.show() - self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle_selected.png')) ) - self.toggle_button.setFlat(False) - - # Reset the indicator count - self.indicator_count = 0 - self.update_indicator() - - self.share_mode.resize_window() - - def show_less(self): - """ - Remove clutter widgets that aren't necessary. - """ - self.label.setText("") - - def show_more(self): - """ - Show all widgets. - """ - self.label.setText(self.label_text) diff --git a/share/locale/en.json b/share/locale/en.json index c7beb6ba..3537b0a2 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -151,8 +151,8 @@ "gui_status_indicator_receive_started": "Receiving", "gui_file_info": "{} files, {}", "gui_file_info_single": "{} file, {}", - "info_in_progress_downloads_tooltip": "{} download(s) in progress", - "info_completed_downloads_tooltip": "{} download(s) completed", + "history_in_progress_tooltip": "{} in progress", + "history_completed_tooltip": "{} completed", "info_in_progress_uploads_tooltip": "{} upload(s) in progress", "info_completed_uploads_tooltip": "{} upload(s) completed", "error_cannot_create_downloads_dir": "Could not create receive mode folder: {}", From 38e62d85288c9947f089b6ba80dc3146178d2a3a Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 18:20:13 -0700 Subject: [PATCH 33/50] The History header is now only shown if there are items again, and the clear history button resets everything. Also, reset hides individual items because, for some reason, they still show up otherwise. --- onionshare_gui/mode/history.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/onionshare_gui/mode/history.py b/onionshare_gui/mode/history.py index a28340a4..0f8ccdca 100644 --- a/onionshare_gui/mode/history.py +++ b/onionshare_gui/mode/history.py @@ -165,6 +165,7 @@ class HistoryItemList(QtWidgets.QScrollArea): """ for item in self.items.values(): self.items_layout.removeWidget(item) + item.hide() self.items = {} @@ -222,6 +223,7 @@ class History(QtWidgets.QWidget): # When there are items self.item_list = HistoryItemList(self.common) self.not_empty_layout = QtWidgets.QVBoxLayout() + self.not_empty_layout.addLayout(header_layout) self.not_empty_layout.addWidget(self.item_list) self.not_empty = QtWidgets.QWidget() self.not_empty.setLayout(self.not_empty_layout) @@ -229,15 +231,12 @@ class History(QtWidgets.QWidget): # Layout layout = QtWidgets.QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) - layout.addLayout(header_layout) layout.addWidget(self.empty) layout.addWidget(self.not_empty) self.setLayout(layout) # Reset once at the beginning self.reset() - self.update_completed() - self.update_in_progress() def add(self, id, item): """ @@ -252,7 +251,6 @@ class History(QtWidgets.QWidget): # Add it to the list self.item_list.add(id, item) - def update(self, id, data): """ Update an item. From 1b1ade63daf937b5de9e40f61fb5f523ca56c81a Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 18:49:09 -0700 Subject: [PATCH 34/50] Start fixing the GUI tests. Also, refactor CommonTests to pass in a Mode object instead of the string "share" or "receive" --- tests_gui_local/commontests.py | 182 +++++------------- ...re_share_mode_download_test_public_mode.py | 38 ++-- 2 files changed, 69 insertions(+), 151 deletions(-) diff --git a/tests_gui_local/commontests.py b/tests_gui_local/commontests.py index 21e8cfad..5ceee668 100644 --- a/tests_gui_local/commontests.py +++ b/tests_gui_local/commontests.py @@ -6,6 +6,9 @@ import zipfile from PyQt5 import QtCore, QtTest from onionshare import strings +from onionshare_gui.mode.receive_mode import ReceiveMode +from onionshare_gui.mode.share_mode import ShareMode + class CommonTests(object): def test_gui_loaded(self): @@ -24,71 +27,42 @@ class CommonTests(object): '''Test that the status bar is visible''' self.assertTrue(self.gui.status_bar.isVisible()) - def test_info_widget_shows_less(self, mode): - '''Test that minimum information (no label) is displayed in the info bar''' - if mode == 'share': - self.assertFalse(self.gui.share_mode.info.label.text() == "") - if mode == 'receive': - # There's no minimal display in receive mode - self.assertTrue(False) - def test_click_mode(self, mode): '''Test that we can switch Mode by clicking the button''' - if mode == 'receive': + if type(mode) == ReceiveMode: QtTest.QTest.mouseClick(self.gui.receive_mode_button, QtCore.Qt.LeftButton) self.assertTrue(self.gui.mode, self.gui.MODE_RECEIVE) - if mode == 'share': + if type(mode) == ShareMode: QtTest.QTest.mouseClick(self.gui.share_mode_button, QtCore.Qt.LeftButton) self.assertTrue(self.gui.mode, self.gui.MODE_SHARE) def test_click_toggle_history(self, mode): '''Test that we can toggle Download or Upload history by clicking the toggle button''' - if mode == 'receive': - currently_visible = self.gui.receive_mode.uploads.isVisible() - QtTest.QTest.mouseClick(self.gui.receive_mode.info.toggle_button, QtCore.Qt.LeftButton) - self.assertEqual(self.gui.receive_mode.uploads.isVisible(), not currently_visible) - if mode == 'share': - currently_visible = self.gui.receive_mode.uploads.isVisible() - QtTest.QTest.mouseClick(self.gui.share_mode.info.toggle_button, QtCore.Qt.LeftButton) - self.assertEqual(self.gui.share_mode.downloads.isVisible(), not currently_visible) + currently_visible = mode.history.isVisible() + QtTest.QTest.mouseClick(mode.toggle_history, QtCore.Qt.LeftButton) + self.assertEqual(mode.history.isVisible(), not currently_visible) def test_history_indicator(self, mode, public_mode): '''Test that we can make sure the history is toggled off, do an action, and the indiciator works''' - if mode == 'receive': - # Make sure history is toggled off - if self.gui.receive_mode.uploads.isVisible(): - QtTest.QTest.mouseClick(self.gui.receive_mode.info.toggle_button, QtCore.Qt.LeftButton) - self.assertFalse(self.gui.receive_mode.uploads.isVisible()) + # Make sure history is toggled off + if mode.history.isVisible(): + QtTest.QTest.mouseClick(mode.toggle_history, QtCore.Qt.LeftButton) + self.assertFalse(mode.history.isVisible()) - # Indicator should not be visible yet - self.assertFalse(self.gui.receive_mode.info.indicator_label.isVisible()) + # Indicator should not be visible yet + self.assertFalse(mode.toggle_history.indicator_label.isVisible()) + if type(mode) == ReceiveMode: # Upload a file files = {'file[]': open('/tmp/test.txt', 'rb')} if not public_mode: - path = 'http://127.0.0.1:{}/{}/upload'.format(self.gui.app.port, self.gui.receive_mode.web.slug) + path = 'http://127.0.0.1:{}/{}/upload'.format(self.gui.app.port, mode.web.slug) else: path = 'http://127.0.0.1:{}/upload'.format(self.gui.app.port) response = requests.post(path, files=files) QtTest.QTest.qWait(2000) - # Indicator should be visible, have a value of "1" - self.assertTrue(self.gui.receive_mode.info.indicator_label.isVisible()) - self.assertEqual(self.gui.receive_mode.info.indicator_label.text(), "1") - - # Toggle history back on, indicator should be hidden again - QtTest.QTest.mouseClick(self.gui.receive_mode.info.toggle_button, QtCore.Qt.LeftButton) - self.assertFalse(self.gui.receive_mode.info.indicator_label.isVisible()) - - if mode == 'share': - # Make sure history is toggled off - if self.gui.share_mode.downloads.isVisible(): - QtTest.QTest.mouseClick(self.gui.share_mode.info.toggle_button, QtCore.Qt.LeftButton) - self.assertFalse(self.gui.share_mode.downloads.isVisible()) - - # Indicator should not be visible yet - self.assertFalse(self.gui.share_mode.info.indicator_label.isVisible()) - + if type(mode) == ShareMode: # Download files if public_mode: url = "http://127.0.0.1:{}/download".format(self.gui.app.port) @@ -97,44 +71,31 @@ class CommonTests(object): r = requests.get(url) QtTest.QTest.qWait(2000) - # Indicator should be visible, have a value of "1" - self.assertTrue(self.gui.share_mode.info.indicator_label.isVisible()) - self.assertEqual(self.gui.share_mode.info.indicator_label.text(), "1") + # Indicator should be visible, have a value of "1" + self.assertTrue(mode.toggle_history.indicator_label.isVisible()) + self.assertEqual(mode.toggle_history.indicator_label.text(), "1") - # Toggle history back on, indicator should be hidden again - QtTest.QTest.mouseClick(self.gui.share_mode.info.toggle_button, QtCore.Qt.LeftButton) - self.assertFalse(self.gui.share_mode.info.indicator_label.isVisible()) + # Toggle history back on, indicator should be hidden again + QtTest.QTest.mouseClick(mode.toggle_history, QtCore.Qt.LeftButton) + self.assertFalse(mode.toggle_history.indicator_label.isVisible()) def test_history_is_not_visible(self, mode): '''Test that the History section is not visible''' - if mode == 'receive': - self.assertFalse(self.gui.receive_mode.uploads.isVisible()) - if mode == 'share': - self.assertFalse(self.gui.share_mode.downloads.isVisible()) + self.assertFalse(mode.history.isVisible()) def test_history_is_visible(self, mode): '''Test that the History section is visible''' - if mode == 'receive': - self.assertTrue(self.gui.receive_mode.uploads.isVisible()) - if mode == 'share': - self.assertTrue(self.gui.share_mode.downloads.isVisible()) + self.assertTrue(mode.history.isVisible()) def test_server_working_on_start_button_pressed(self, mode): '''Test we can start the service''' # Should be in SERVER_WORKING state - if mode == 'receive': - QtTest.QTest.mouseClick(self.gui.receive_mode.server_status.server_button, QtCore.Qt.LeftButton) - self.assertEqual(self.gui.receive_mode.server_status.status, 1) - if mode == 'share': - QtTest.QTest.mouseClick(self.gui.share_mode.server_status.server_button, QtCore.Qt.LeftButton) - self.assertEqual(self.gui.share_mode.server_status.status, 1) + QtTest.QTest.mouseClick(mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEqual(mode.server_status.status, 1) def test_server_status_indicator_says_starting(self, mode): '''Test that the Server Status indicator shows we are Starting''' - if mode == 'receive': - self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_share_working', True)) - if mode == 'share': - self.assertEquals(self.gui.share_mode.server_status_label.text(), strings._('gui_status_indicator_share_working', True)) + self.assertEquals(mode.server_status_label.text(), strings._('gui_status_indicator_share_working', True)) def test_settings_button_is_hidden(self): '''Test that the settings button is hidden when the server starts''' @@ -144,10 +105,7 @@ class CommonTests(object): '''Test that the server has started''' QtTest.QTest.qWait(2000) # Should now be in SERVER_STARTED state - if mode == 'receive': - self.assertEqual(self.gui.receive_mode.server_status.status, 2) - if mode == 'share': - self.assertEqual(self.gui.share_mode.server_status.status, 2) + self.assertEqual(mode.server_status.status, 2) def test_a_web_server_is_running(self): '''Test that the web server has started''' @@ -157,38 +115,26 @@ class CommonTests(object): def test_have_a_slug(self, mode, public_mode): '''Test that we have a valid slug''' - if mode == 'receive': - if not public_mode: - self.assertRegex(self.gui.receive_mode.server_status.web.slug, r'(\w+)-(\w+)') - else: - self.assertIsNone(self.gui.receive_mode.server_status.web.slug, r'(\w+)-(\w+)') - if mode == 'share': - if not public_mode: - self.assertRegex(self.gui.share_mode.server_status.web.slug, r'(\w+)-(\w+)') - else: - self.assertIsNone(self.gui.share_mode.server_status.web.slug, r'(\w+)-(\w+)') + if not public_mode: + self.assertRegex(mode.server_status.web.slug, r'(\w+)-(\w+)') + else: + self.assertIsNone(mode.server_status.web.slug, r'(\w+)-(\w+)') def test_url_description_shown(self, mode): '''Test that the URL label is showing''' - if mode == 'receive': - self.assertTrue(self.gui.receive_mode.server_status.url_description.isVisible()) - if mode == 'share': - self.assertTrue(self.gui.share_mode.server_status.url_description.isVisible()) + self.assertTrue(mode.server_status.url_description.isVisible()) def test_have_copy_url_button(self, mode): '''Test that the Copy URL button is shown''' - if mode == 'receive': - self.assertTrue(self.gui.receive_mode.server_status.copy_url_button.isVisible()) - if mode == 'share': - self.assertTrue(self.gui.share_mode.server_status.copy_url_button.isVisible()) + self.assertTrue(mode.server_status.copy_url_button.isVisible()) def test_server_status_indicator_says_started(self, mode): '''Test that the Server Status indicator shows we are started''' - if mode == 'receive': - self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_started', True)) - if mode == 'share': - self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_share_started', True)) + if type(mode) == ReceiveMode: + self.assertEquals(mode.server_status_label.text(), strings._('gui_status_indicator_receive_started', True)) + if type(mode) == ShareMode: + self.assertEquals(mode.server_status_label.text(), strings._('gui_status_indicator_share_started', True)) def test_web_page(self, mode, string, public_mode): '''Test that the web page contains a string''' @@ -197,10 +143,7 @@ class CommonTests(object): s.connect(('127.0.0.1', self.gui.app.port)) if not public_mode: - if mode == 'receive': - path = '/{}'.format(self.gui.receive_mode.server_status.web.slug) - if mode == 'share': - path = '/{}'.format(self.gui.share_mode.server_status.web.slug) + path = '/{}'.format(mode.server_status.web.slug) else: path = '/' @@ -223,29 +166,18 @@ class CommonTests(object): def test_history_widgets_present(self, mode): '''Test that the relevant widgets are present in the history view after activity has taken place''' - if mode == 'receive': - self.assertFalse(self.gui.receive_mode.uploads.empty.isVisible()) - self.assertTrue(self.gui.receive_mode.uploads.not_empty.isVisible()) - if mode == 'share': - self.assertFalse(self.gui.share_mode.downloads.empty.isVisible()) - self.assertTrue(self.gui.share_mode.downloads.not_empty.isVisible()) + self.assertFalse(mode.history.empty.isVisible()) + self.assertTrue(mode.history.not_empty.isVisible()) def test_counter_incremented(self, mode, count): '''Test that the counter has incremented''' - if mode == 'receive': - self.assertEquals(self.gui.receive_mode.uploads_completed, count) - if mode == 'share': - self.assertEquals(self.gui.share_mode.downloads_completed, count) + self.assertEquals(mode.uploads_completed, count) def test_server_is_stopped(self, mode, stay_open): '''Test that the server stops when we click Stop''' - if mode == 'receive': - QtTest.QTest.mouseClick(self.gui.receive_mode.server_status.server_button, QtCore.Qt.LeftButton) - self.assertEquals(self.gui.receive_mode.server_status.status, 0) - if mode == 'share': - if stay_open: - QtTest.QTest.mouseClick(self.gui.share_mode.server_status.server_button, QtCore.Qt.LeftButton) - self.assertEquals(self.gui.share_mode.server_status.status, 0) + if type(mode) == ReceiveMode or (type(mode) == ShareMode and stay_open): + QtTest.QTest.mouseClick(mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEquals(mode.server_status.status, 0) def test_web_service_is_stopped(self): '''Test that the web server also stopped''' @@ -257,9 +189,9 @@ class CommonTests(object): def test_server_status_indicator_says_closed(self, mode, stay_open): '''Test that the Server Status indicator shows we closed''' - if mode == 'receive': + if type(mode) == ReceiveMode: self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_stopped', True)) - if mode == 'share': + if type(mode) == ShareMode: if stay_open: self.assertEquals(self.gui.share_mode.server_status_label.text(), strings._('gui_status_indicator_share_stopped', True)) else: @@ -269,28 +201,18 @@ class CommonTests(object): def test_set_timeout(self, mode, timeout): '''Test that the timeout can be set''' timer = QtCore.QDateTime.currentDateTime().addSecs(timeout) - if mode == 'receive': - self.gui.receive_mode.server_status.shutdown_timeout.setDateTime(timer) - self.assertTrue(self.gui.receive_mode.server_status.shutdown_timeout.dateTime(), timer) - if mode == 'share': - self.gui.share_mode.server_status.shutdown_timeout.setDateTime(timer) - self.assertTrue(self.gui.share_mode.server_status.shutdown_timeout.dateTime(), timer) + mode.server_status.shutdown_timeout.setDateTime(timer) + self.assertTrue(mode.server_status.shutdown_timeout.dateTime(), timer) def test_timeout_widget_hidden(self, mode): '''Test that the timeout widget is hidden when share has started''' - if mode == 'receive': - self.assertFalse(self.gui.receive_mode.server_status.shutdown_timeout_container.isVisible()) - if mode == 'share': - self.assertFalse(self.gui.share_mode.server_status.shutdown_timeout_container.isVisible()) + self.assertFalse(mode.server_status.shutdown_timeout_container.isVisible()) def test_server_timed_out(self, mode, wait): '''Test that the server has timed out after the timer ran out''' QtTest.QTest.qWait(wait) # We should have timed out now - if mode == 'receive': - self.assertEqual(self.gui.receive_mode.server_status.status, 0) - if mode == 'share': - self.assertEqual(self.gui.share_mode.server_status.status, 0) + self.assertEqual(mode.server_status.status, 0) # Receive-specific tests def test_upload_file(self, public_mode, expected_file): diff --git a/tests_gui_local/onionshare_share_mode_download_test_public_mode.py b/tests_gui_local/onionshare_share_mode_download_test_public_mode.py index a10ee4c2..82f1989c 100644 --- a/tests_gui_local/onionshare_share_mode_download_test_public_mode.py +++ b/tests_gui_local/onionshare_share_mode_download_test_public_mode.py @@ -96,21 +96,17 @@ class OnionShareGuiTest(unittest.TestCase): def test_file_selection_widget_has_a_file(self): CommonTests.test_file_selection_widget_has_a_file(self) - @pytest.mark.run(order=6) - def test_info_widget_shows_less(self): - CommonTests.test_info_widget_shows_less(self, 'share') - @pytest.mark.run(order=7) def test_history_is_not_visible(self): - CommonTests.test_history_is_not_visible(self, 'share') + CommonTests.test_history_is_not_visible(self, self.gui.share_mode) @pytest.mark.run(order=8) def test_click_toggle_history(self): - CommonTests.test_click_toggle_history(self, 'share') + CommonTests.test_click_toggle_history(self, self.gui.share_mode) @pytest.mark.run(order=9) def test_history_is_visible(self): - CommonTests.test_history_is_visible(self, 'share') + CommonTests.test_history_is_visible(self, self.gui.share_mode) @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): @@ -126,11 +122,11 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'share') + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): - CommonTests.test_server_status_indicator_says_starting(self, 'share') + CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode) @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): @@ -142,7 +138,7 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=17) def test_a_server_is_started(self): - CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_a_server_is_started(self, self.gui.share_mode) @pytest.mark.run(order=18) def test_a_web_server_is_running(self): @@ -150,23 +146,23 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=19) def test_have_a_slug(self): - CommonTests.test_have_a_slug(self, 'share', True) + CommonTests.test_have_a_slug(self, self.gui.share_mode, True) @pytest.mark.run(order=20) def test_url_description_shown(self): - CommonTests.test_url_description_shown(self, 'share') + CommonTests.test_url_description_shown(self, self.gui.share_mode) @pytest.mark.run(order=21) def test_have_copy_url_button(self): - CommonTests.test_have_copy_url_button(self, 'share') + CommonTests.test_have_copy_url_button(self, self.gui.share_mode) @pytest.mark.run(order=22) def test_server_status_indicator_says_started(self): - CommonTests.test_server_status_indicator_says_started(self, 'share') + CommonTests.test_server_status_indicator_says_started(self, self.gui.share_mode) @pytest.mark.run(order=23) def test_web_page(self): - CommonTests.test_web_page(self, 'share', 'Total size', True) + CommonTests.test_web_page(self, self.gui.share_mode, 'Total size', True) @pytest.mark.run(order=24) def test_download_share(self): @@ -174,11 +170,11 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=25) def test_history_widgets_present(self): - CommonTests.test_history_widgets_present(self, 'share') + CommonTests.test_history_widgets_present(self, self.gui.share_mode) @pytest.mark.run(order=26) def test_server_is_stopped(self): - CommonTests.test_server_is_stopped(self, 'share', False) + CommonTests.test_server_is_stopped(self, self.gui.share_mode, False) @pytest.mark.run(order=27) def test_web_service_is_stopped(self): @@ -186,7 +182,7 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=28) def test_server_status_indicator_says_closed(self): - CommonTests.test_server_status_indicator_says_closed(self, 'share', False) + CommonTests.test_server_status_indicator_says_closed(self, self.gui.share_mode, False) @pytest.mark.run(order=29) def test_add_button_visible(self): @@ -194,9 +190,9 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=30) def test_history_indicator(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'share') - CommonTests.test_a_server_is_started(self, 'share') - CommonTests.test_history_indicator(self, 'share', True) + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + CommonTests.test_a_server_is_started(self, self.gui.share_mode) + CommonTests.test_history_indicator(self, self.gui.share_mode, True) if __name__ == "__main__": From 4d217e84032cd9af64d1a1371ce75a08a5de47e9 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 20:37:54 -0700 Subject: [PATCH 35/50] Refactor CommonTests to pass in actual Mode objects, and fix all tests. Now all ShareMode tests pass --- tests_gui_local/commontests.py | 2 +- .../onionshare_receive_mode_upload_test.py | 36 ++++++++-------- ...re_receive_mode_upload_test_public_mode.py | 36 ++++++++-------- .../onionshare_share_mode_download_test.py | 38 ++++++++--------- ...hare_share_mode_download_test_stay_open.py | 42 +++++++++---------- .../onionshare_slug_persistent_test.py | 38 ++++++++--------- tests_gui_local/onionshare_timer_test.py | 18 ++++---- 7 files changed, 97 insertions(+), 113 deletions(-) diff --git a/tests_gui_local/commontests.py b/tests_gui_local/commontests.py index 5ceee668..d311c7bb 100644 --- a/tests_gui_local/commontests.py +++ b/tests_gui_local/commontests.py @@ -171,7 +171,7 @@ class CommonTests(object): def test_counter_incremented(self, mode, count): '''Test that the counter has incremented''' - self.assertEquals(mode.uploads_completed, count) + self.assertEquals(mode.history.completed_count, count) def test_server_is_stopped(self, mode, stay_open): '''Test that the server stops when we click Stop''' diff --git a/tests_gui_local/onionshare_receive_mode_upload_test.py b/tests_gui_local/onionshare_receive_mode_upload_test.py index 19674aa3..1ce91ba2 100644 --- a/tests_gui_local/onionshare_receive_mode_upload_test.py +++ b/tests_gui_local/onionshare_receive_mode_upload_test.py @@ -96,27 +96,27 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=6) def test_click_mode(self): - CommonTests.test_click_mode(self, 'receive') + CommonTests.test_click_mode(self, self.gui.receive_mode) @pytest.mark.run(order=6) def test_history_is_not_visible(self): - CommonTests.test_history_is_not_visible(self, 'receive') + CommonTests.test_history_is_not_visible(self, self.gui.receive_mode) @pytest.mark.run(order=7) def test_click_toggle_history(self): - CommonTests.test_click_toggle_history(self, 'receive') + CommonTests.test_click_toggle_history(self, self.gui.receive_mode) @pytest.mark.run(order=8) def test_history_is_visible(self): - CommonTests.test_history_is_visible(self, 'receive') + CommonTests.test_history_is_visible(self, self.gui.receive_mode) @pytest.mark.run(order=8) def test_server_working_on_start_button_pressed(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'receive') + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.receive_mode) @pytest.mark.run(order=9) def test_server_status_indicator_says_starting(self): - CommonTests.test_server_status_indicator_says_starting(self, 'receive') + CommonTests.test_server_status_indicator_says_starting(self, self.gui.receive_mode) @pytest.mark.run(order=10) def test_settings_button_is_hidden(self): @@ -124,7 +124,7 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=11) def test_a_server_is_started(self): - CommonTests.test_a_server_is_started(self, 'receive') + CommonTests.test_a_server_is_started(self, self.gui.receive_mode) @pytest.mark.run(order=12) def test_a_web_server_is_running(self): @@ -132,23 +132,23 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=14) def test_have_a_slug(self): - CommonTests.test_have_a_slug(self, 'receive', False) + CommonTests.test_have_a_slug(self, self.gui.receive_mode, False) @pytest.mark.run(order=15) def test_url_description_shown(self): - CommonTests.test_url_description_shown(self, 'receive') + CommonTests.test_url_description_shown(self, self.gui.receive_mode) @pytest.mark.run(order=16) def test_have_copy_url_button(self): - CommonTests.test_have_copy_url_button(self, 'receive') + CommonTests.test_have_copy_url_button(self, self.gui.receive_mode) @pytest.mark.run(order=17) def test_server_status_indicator_says_started(self): - CommonTests.test_server_status_indicator_says_started(self, 'receive') + CommonTests.test_server_status_indicator_says_started(self, self.gui.receive_mode) @pytest.mark.run(order=18) def test_web_page(self): - CommonTests.test_web_page(self, 'receive', 'Select the files you want to send, then click', False) + CommonTests.test_web_page(self, self.gui.receive_mode, 'Select the files you want to send, then click', False) @pytest.mark.run(order=19) def test_upload_file(self): @@ -156,11 +156,11 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=20) def test_history_widgets_present(self): - CommonTests.test_history_widgets_present(self, 'receive') + CommonTests.test_history_widgets_present(self, self.gui.receive_mode) @pytest.mark.run(order=21) def test_counter_incremented(self): - CommonTests.test_counter_incremented(self, 'receive', 1) + CommonTests.test_counter_incremented(self, self.gui.receive_mode, 1) @pytest.mark.run(order=22) def test_upload_same_file_is_renamed(self): @@ -168,15 +168,15 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=23) def test_upload_count_incremented_again(self): - CommonTests.test_counter_incremented(self, 'receive', 2) + CommonTests.test_counter_incremented(self, self.gui.receive_mode, 2) @pytest.mark.run(order=24) def test_history_indicator(self): - CommonTests.test_history_indicator(self, 'receive', False) + CommonTests.test_history_indicator(self, self.gui.receive_mode, False) @pytest.mark.run(order=25) def test_server_is_stopped(self): - CommonTests.test_server_is_stopped(self, 'receive', False) + CommonTests.test_server_is_stopped(self, self.gui.receive_mode, False) @pytest.mark.run(order=26) def test_web_service_is_stopped(self): @@ -184,7 +184,7 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=27) def test_server_status_indicator_says_closed(self): - CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) + CommonTests.test_server_status_indicator_says_closed(self, self.gui.receive_mode, False) if __name__ == "__main__": unittest.main() diff --git a/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py b/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py index e3f85731..6591a884 100644 --- a/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py +++ b/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py @@ -96,27 +96,27 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=5) def test_click_mode(self): - CommonTests.test_click_mode(self, 'receive') + CommonTests.test_click_mode(self, self.gui.receive_mode) @pytest.mark.run(order=6) def test_history_is_not_visible(self): - CommonTests.test_history_is_not_visible(self, 'receive') + CommonTests.test_history_is_not_visible(self, self.gui.receive_mode) @pytest.mark.run(order=7) def test_click_toggle_history(self): - CommonTests.test_click_toggle_history(self, 'receive') + CommonTests.test_click_toggle_history(self, self.gui.receive_mode) @pytest.mark.run(order=8) def test_history_is_visible(self): - CommonTests.test_history_is_visible(self, 'receive') + CommonTests.test_history_is_visible(self, self.gui.receive_mode) @pytest.mark.run(order=9) def test_server_working_on_start_button_pressed(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'receive') + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.receive_mode) @pytest.mark.run(order=10) def test_server_status_indicator_says_starting(self): - CommonTests.test_server_status_indicator_says_starting(self, 'receive') + CommonTests.test_server_status_indicator_says_starting(self, self.gui.receive_mode) @pytest.mark.run(order=11) def test_settings_button_is_hidden(self): @@ -124,7 +124,7 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=12) def test_a_server_is_started(self): - CommonTests.test_a_server_is_started(self, 'receive') + CommonTests.test_a_server_is_started(self, self.gui.receive_mode) @pytest.mark.run(order=13) def test_a_web_server_is_running(self): @@ -132,23 +132,23 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=14) def test_have_a_slug(self): - CommonTests.test_have_a_slug(self, 'receive', True) + CommonTests.test_have_a_slug(self, self.gui.receive_mode, True) @pytest.mark.run(order=15) def test_url_description_shown(self): - CommonTests.test_url_description_shown(self, 'receive') + CommonTests.test_url_description_shown(self, self.gui.receive_mode) @pytest.mark.run(order=16) def test_have_copy_url_button(self): - CommonTests.test_have_copy_url_button(self, 'receive') + CommonTests.test_have_copy_url_button(self, self.gui.receive_mode) @pytest.mark.run(order=17) def test_server_status_indicator_says_started(self): - CommonTests.test_server_status_indicator_says_started(self, 'receive') + CommonTests.test_server_status_indicator_says_started(self, self.gui.receive_mode) @pytest.mark.run(order=18) def test_web_page(self): - CommonTests.test_web_page(self, 'receive', 'Select the files you want to send, then click', True) + CommonTests.test_web_page(self, self.gui.receive_mode, 'Select the files you want to send, then click', True) @pytest.mark.run(order=19) def test_upload_file(self): @@ -156,11 +156,11 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=20) def test_history_widgets_present(self): - CommonTests.test_history_widgets_present(self, 'receive') + CommonTests.test_history_widgets_present(self, self.gui.receive_mode) @pytest.mark.run(order=21) def test_counter_incremented(self): - CommonTests.test_counter_incremented(self, 'receive', 1) + CommonTests.test_counter_incremented(self, self.gui.receive_mode, 1) @pytest.mark.run(order=22) def test_upload_same_file_is_renamed(self): @@ -168,15 +168,15 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=23) def test_upload_count_incremented_again(self): - CommonTests.test_counter_incremented(self, 'receive', 2) + CommonTests.test_counter_incremented(self, self.gui.receive_mode, 2) @pytest.mark.run(order=24) def test_history_indicator(self): - CommonTests.test_history_indicator(self, 'receive', True) + CommonTests.test_history_indicator(self, self.gui.receive_mode, True) @pytest.mark.run(order=25) def test_server_is_stopped(self): - CommonTests.test_server_is_stopped(self, 'receive', False) + CommonTests.test_server_is_stopped(self, self.gui.receive_mode, False) @pytest.mark.run(order=26) def test_web_service_is_stopped(self): @@ -184,7 +184,7 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=27) def test_server_status_indicator_says_closed(self): - CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) + CommonTests.test_server_status_indicator_says_closed(self, self.gui.receive_mode, False) if __name__ == "__main__": unittest.main() diff --git a/tests_gui_local/onionshare_share_mode_download_test.py b/tests_gui_local/onionshare_share_mode_download_test.py index c4a60101..6842f1a6 100644 --- a/tests_gui_local/onionshare_share_mode_download_test.py +++ b/tests_gui_local/onionshare_share_mode_download_test.py @@ -96,21 +96,17 @@ class OnionShareGuiTest(unittest.TestCase): def test_file_selection_widget_has_a_file(self): CommonTests.test_file_selection_widget_has_a_file(self) - @pytest.mark.run(order=6) - def test_info_widget_shows_less(self): - CommonTests.test_info_widget_shows_less(self, 'share') - @pytest.mark.run(order=7) def test_history_is_not_visible(self): - CommonTests.test_history_is_not_visible(self, 'share') + CommonTests.test_history_is_not_visible(self, self.gui.share_mode) @pytest.mark.run(order=8) def test_click_toggle_history(self): - CommonTests.test_click_toggle_history(self, 'share') + CommonTests.test_click_toggle_history(self, self.gui.share_mode) @pytest.mark.run(order=9) def test_history_is_visible(self): - CommonTests.test_history_is_visible(self, 'share') + CommonTests.test_history_is_visible(self, self.gui.share_mode) @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): @@ -126,11 +122,11 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'share') + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): - CommonTests.test_server_status_indicator_says_starting(self, 'share') + CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode) @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): @@ -142,7 +138,7 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=17) def test_a_server_is_started(self): - CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_a_server_is_started(self, self.gui.share_mode) @pytest.mark.run(order=18) def test_a_web_server_is_running(self): @@ -150,23 +146,23 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=19) def test_have_a_slug(self): - CommonTests.test_have_a_slug(self, 'share', False) + CommonTests.test_have_a_slug(self, self.gui.share_mode, False) @pytest.mark.run(order=20) def test_url_description_shown(self): - CommonTests.test_url_description_shown(self, 'share') + CommonTests.test_url_description_shown(self, self.gui.share_mode) @pytest.mark.run(order=21) def test_have_copy_url_button(self): - CommonTests.test_have_copy_url_button(self, 'share') + CommonTests.test_have_copy_url_button(self, self.gui.share_mode) @pytest.mark.run(order=22) def test_server_status_indicator_says_started(self): - CommonTests.test_server_status_indicator_says_started(self, 'share') + CommonTests.test_server_status_indicator_says_started(self, self.gui.share_mode) @pytest.mark.run(order=23) def test_web_page(self): - CommonTests.test_web_page(self, 'share', 'Total size', False) + CommonTests.test_web_page(self, self.gui.share_mode, 'Total size', False) @pytest.mark.run(order=24) def test_download_share(self): @@ -174,11 +170,11 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=25) def test_history_widgets_present(self): - CommonTests.test_history_widgets_present(self, 'share') + CommonTests.test_history_widgets_present(self, self.gui.share_mode) @pytest.mark.run(order=26) def test_server_is_stopped(self): - CommonTests.test_server_is_stopped(self, 'share', False) + CommonTests.test_server_is_stopped(self, self.gui.share_mode, False) @pytest.mark.run(order=27) def test_web_service_is_stopped(self): @@ -186,7 +182,7 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=28) def test_server_status_indicator_says_closed(self): - CommonTests.test_server_status_indicator_says_closed(self, 'share', False) + CommonTests.test_server_status_indicator_says_closed(self, self.gui.share_mode, False) @pytest.mark.run(order=29) def test_add_button_visible(self): @@ -194,9 +190,9 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=30) def test_history_indicator(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'share') - CommonTests.test_a_server_is_started(self, 'share') - CommonTests.test_history_indicator(self, 'share', False) + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + CommonTests.test_a_server_is_started(self, self.gui.share_mode) + CommonTests.test_history_indicator(self, self.gui.share_mode, False) if __name__ == "__main__": diff --git a/tests_gui_local/onionshare_share_mode_download_test_stay_open.py b/tests_gui_local/onionshare_share_mode_download_test_stay_open.py index 8426c264..df9bc857 100644 --- a/tests_gui_local/onionshare_share_mode_download_test_stay_open.py +++ b/tests_gui_local/onionshare_share_mode_download_test_stay_open.py @@ -96,21 +96,17 @@ class OnionShareGuiTest(unittest.TestCase): def test_file_selection_widget_has_a_file(self): CommonTests.test_file_selection_widget_has_a_file(self) - @pytest.mark.run(order=6) - def test_info_widget_shows_less(self): - CommonTests.test_info_widget_shows_less(self, 'share') - @pytest.mark.run(order=7) def test_history_is_not_visible(self): - CommonTests.test_history_is_not_visible(self, 'share') + CommonTests.test_history_is_not_visible(self, self.gui.share_mode) @pytest.mark.run(order=8) def test_click_toggle_history(self): - CommonTests.test_click_toggle_history(self, 'share') + CommonTests.test_click_toggle_history(self, self.gui.share_mode) @pytest.mark.run(order=9) def test_history_is_visible(self): - CommonTests.test_history_is_visible(self, 'share') + CommonTests.test_history_is_visible(self, self.gui.share_mode) @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): @@ -126,11 +122,11 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'share') + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): - CommonTests.test_server_status_indicator_says_starting(self, 'share') + CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode) @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): @@ -142,7 +138,7 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=17) def test_a_server_is_started(self): - CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_a_server_is_started(self, self.gui.share_mode) @pytest.mark.run(order=18) def test_a_web_server_is_running(self): @@ -150,23 +146,23 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=19) def test_have_a_slug(self): - CommonTests.test_have_a_slug(self, 'share', True) + CommonTests.test_have_a_slug(self, self.gui.share_mode, True) @pytest.mark.run(order=20) def test_url_description_shown(self): - CommonTests.test_url_description_shown(self, 'share') + CommonTests.test_url_description_shown(self, self.gui.share_mode) @pytest.mark.run(order=21) def test_have_copy_url_button(self): - CommonTests.test_have_copy_url_button(self, 'share') + CommonTests.test_have_copy_url_button(self, self.gui.share_mode) @pytest.mark.run(order=22) def test_server_status_indicator_says_started(self): - CommonTests.test_server_status_indicator_says_started(self, 'share') + CommonTests.test_server_status_indicator_says_started(self, self.gui.share_mode) @pytest.mark.run(order=23) def test_web_page(self): - CommonTests.test_web_page(self, 'share', 'Total size', True) + CommonTests.test_web_page(self, self.gui.share_mode, 'Total size', True) @pytest.mark.run(order=24) def test_download_share(self): @@ -174,11 +170,11 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=25) def test_history_widgets_present(self): - CommonTests.test_history_widgets_present(self, 'share') + CommonTests.test_history_widgets_present(self, self.gui.share_mode) @pytest.mark.run(order=26) def test_counter_incremented(self): - CommonTests.test_counter_incremented(self, 'share', 1) + CommonTests.test_counter_incremented(self, self.gui.share_mode, 1) @pytest.mark.run(order=27) def test_download_share_again(self): @@ -186,11 +182,11 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=28) def test_counter_incremented_again(self): - CommonTests.test_counter_incremented(self, 'share', 2) + CommonTests.test_counter_incremented(self, self.gui.share_mode, 2) @pytest.mark.run(order=29) def test_server_is_stopped(self): - CommonTests.test_server_is_stopped(self, 'share', True) + CommonTests.test_server_is_stopped(self, self.gui.share_mode, True) @pytest.mark.run(order=30) def test_web_service_is_stopped(self): @@ -198,7 +194,7 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=31) def test_server_status_indicator_says_closed(self): - CommonTests.test_server_status_indicator_says_closed(self, 'share', True) + CommonTests.test_server_status_indicator_says_closed(self, self.gui.share_mode, True) @pytest.mark.run(order=32) def test_add_button_visible(self): @@ -206,9 +202,9 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=33) def test_history_indicator(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'share') - CommonTests.test_a_server_is_started(self, 'share') - CommonTests.test_history_indicator(self, 'share', True) + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + CommonTests.test_a_server_is_started(self, self.gui.share_mode) + CommonTests.test_history_indicator(self, self.gui.share_mode, True) if __name__ == "__main__": diff --git a/tests_gui_local/onionshare_slug_persistent_test.py b/tests_gui_local/onionshare_slug_persistent_test.py index 9fb623dd..5b825dad 100644 --- a/tests_gui_local/onionshare_slug_persistent_test.py +++ b/tests_gui_local/onionshare_slug_persistent_test.py @@ -94,29 +94,25 @@ class OnionShareGuiTest(unittest.TestCase): def test_server_status_bar_is_visible(self): CommonTests.test_server_status_bar_is_visible(self) - @pytest.mark.run(order=6) - def test_info_widget_shows_less(self): - CommonTests.test_info_widget_shows_less(self, 'share') - @pytest.mark.run(order=7) def test_history_is_not_visible(self): - CommonTests.test_history_is_not_visible(self, 'share') + CommonTests.test_history_is_not_visible(self, self.gui.share_mode) @pytest.mark.run(order=8) def test_click_toggle_history(self): - CommonTests.test_click_toggle_history(self, 'share') + CommonTests.test_click_toggle_history(self, self.gui.share_mode) @pytest.mark.run(order=9) def test_history_is_visible(self): - CommonTests.test_history_is_visible(self, 'share') + CommonTests.test_history_is_visible(self, self.gui.share_mode) @pytest.mark.run(order=10) def test_server_working_on_start_button_pressed(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'share') + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) @pytest.mark.run(order=11) def test_server_status_indicator_says_starting(self): - CommonTests.test_server_status_indicator_says_starting(self, 'share') + CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode) @pytest.mark.run(order=12) def test_settings_button_is_hidden(self): @@ -124,7 +120,7 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=13) def test_a_server_is_started(self): - CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_a_server_is_started(self, self.gui.share_mode) @pytest.mark.run(order=14) def test_a_web_server_is_running(self): @@ -132,17 +128,17 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=15) def test_have_a_slug(self): - CommonTests.test_have_a_slug(self, 'share', False) + CommonTests.test_have_a_slug(self, self.gui.share_mode, False) global slug slug = self.gui.share_mode.server_status.web.slug @pytest.mark.run(order=16) def test_server_status_indicator_says_started(self): - CommonTests.test_server_status_indicator_says_started(self, 'share') + CommonTests.test_server_status_indicator_says_started(self, self.gui.share_mode) @pytest.mark.run(order=17) def test_server_is_stopped(self): - CommonTests.test_server_is_stopped(self, 'share', True) + CommonTests.test_server_is_stopped(self, self.gui.share_mode, True) @pytest.mark.run(order=18) def test_web_service_is_stopped(self): @@ -150,13 +146,13 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=19) def test_server_status_indicator_says_closed(self): - CommonTests.test_server_status_indicator_says_closed(self, 'share', True) + CommonTests.test_server_status_indicator_says_closed(self, self.gui.share_mode, True) @pytest.mark.run(order=20) def test_server_started_again(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'share') - CommonTests.test_server_status_indicator_says_starting(self, 'share') - CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode) + CommonTests.test_a_server_is_started(self, self.gui.share_mode) @pytest.mark.run(order=21) def test_have_same_slug(self): @@ -165,14 +161,14 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=22) def test_server_is_stopped_again(self): - CommonTests.test_server_is_stopped(self, 'share', True) + CommonTests.test_server_is_stopped(self, self.gui.share_mode, True) CommonTests.test_web_service_is_stopped(self) @pytest.mark.run(order=23) def test_history_indicator(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'share') - CommonTests.test_a_server_is_started(self, 'share') - CommonTests.test_history_indicator(self, 'share', False) + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + CommonTests.test_a_server_is_started(self, self.gui.share_mode) + CommonTests.test_history_indicator(self, self.gui.share_mode, False) if __name__ == "__main__": diff --git a/tests_gui_local/onionshare_timer_test.py b/tests_gui_local/onionshare_timer_test.py index 701d9a21..4aaaf364 100644 --- a/tests_gui_local/onionshare_timer_test.py +++ b/tests_gui_local/onionshare_timer_test.py @@ -96,29 +96,25 @@ class OnionShareGuiTest(unittest.TestCase): def test_file_selection_widget_has_a_file(self): CommonTests.test_file_selection_widget_has_a_file(self) - @pytest.mark.run(order=6) - def test_info_widget_shows_less(self): - CommonTests.test_info_widget_shows_less(self, 'share') - @pytest.mark.run(order=7) def test_history_is_not_visible(self): - CommonTests.test_history_is_not_visible(self, 'share') + CommonTests.test_history_is_not_visible(self, self.gui.share_mode) @pytest.mark.run(order=8) def test_set_timeout(self): - CommonTests.test_set_timeout(self, 'share', 5) + CommonTests.test_set_timeout(self, self.gui.share_mode, 5) @pytest.mark.run(order=9) def test_server_working_on_start_button_pressed(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'share') + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) @pytest.mark.run(order=10) def test_server_status_indicator_says_starting(self): - CommonTests.test_server_status_indicator_says_starting(self, 'share') + CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode) @pytest.mark.run(order=11) def test_a_server_is_started(self): - CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_a_server_is_started(self, self.gui.share_mode) @pytest.mark.run(order=12) def test_a_web_server_is_running(self): @@ -126,11 +122,11 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=13) def test_timeout_widget_hidden(self): - CommonTests.test_timeout_widget_hidden(self, 'share') + CommonTests.test_timeout_widget_hidden(self, self.gui.share_mode) @pytest.mark.run(order=14) def test_timeout(self): - CommonTests.test_server_timed_out(self, 'share', 10000) + CommonTests.test_server_timed_out(self, self.gui.share_mode, 10000) @pytest.mark.run(order=15) def test_web_service_is_stopped(self): From c9beb694f2aaf3d9afcc7272f73eaf4eabe6a603 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 21:14:20 -0700 Subject: [PATCH 36/50] Update ReceiveMode to use History directly, and now all GUI tests pass --- onionshare_gui/mode/history.py | 182 +++++++++ onionshare_gui/mode/receive_mode/__init__.py | 97 ++--- onionshare_gui/mode/receive_mode/uploads.py | 395 ------------------- 3 files changed, 234 insertions(+), 440 deletions(-) delete mode 100644 onionshare_gui/mode/receive_mode/uploads.py diff --git a/onionshare_gui/mode/history.py b/onionshare_gui/mode/history.py index 0f8ccdca..4f5b2cef 100644 --- a/onionshare_gui/mode/history.py +++ b/onionshare_gui/mode/history.py @@ -18,6 +18,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ import time +import subprocess +from datetime import datetime from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings @@ -103,6 +105,186 @@ class DownloadHistoryItem(HistoryItem): self.started) +class UploadHistoryItemFile(QtWidgets.QWidget): + def __init__(self, common, filename): + super(UploadHistoryItemFile, self).__init__() + self.common = common + + self.common.log('UploadHistoryItemFile', '__init__', 'filename: {}'.format(filename)) + + self.filename = filename + self.started = datetime.now() + + # Filename label + self.filename_label = QtWidgets.QLabel(self.filename) + self.filename_label_width = self.filename_label.width() + + # File size label + self.filesize_label = QtWidgets.QLabel() + self.filesize_label.setStyleSheet(self.common.css['receive_file_size']) + self.filesize_label.hide() + + # Folder button + folder_pixmap = QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/open_folder.png'))) + folder_icon = QtGui.QIcon(folder_pixmap) + self.folder_button = QtWidgets.QPushButton() + self.folder_button.clicked.connect(self.open_folder) + self.folder_button.setIcon(folder_icon) + self.folder_button.setIconSize(folder_pixmap.rect().size()) + self.folder_button.setFlat(True) + self.folder_button.hide() + + # Layouts + layout = QtWidgets.QHBoxLayout() + layout.addWidget(self.filename_label) + layout.addWidget(self.filesize_label) + layout.addStretch() + layout.addWidget(self.folder_button) + self.setLayout(layout) + + def update(self, uploaded_bytes, complete): + self.filesize_label.setText(self.common.human_readable_filesize(uploaded_bytes)) + self.filesize_label.show() + + if complete: + self.folder_button.show() + + def rename(self, new_filename): + self.filename = new_filename + self.filename_label.setText(self.filename) + + def open_folder(self): + """ + Open the downloads folder, with the file selected, in a cross-platform manner + """ + self.common.log('UploadHistoryItemFile', 'open_folder') + + abs_filename = os.path.join(self.common.settings.get('downloads_dir'), self.filename) + + # Linux + if self.common.platform == 'Linux' or self.common.platform == 'BSD': + try: + # If nautilus is available, open it + subprocess.Popen(['nautilus', abs_filename]) + except: + Alert(self.common, strings._('gui_open_folder_error_nautilus').format(abs_filename)) + + # macOS + elif self.common.platform == 'Darwin': + # TODO: Implement opening folder with file selected in macOS + # This seems helpful: https://stackoverflow.com/questions/3520493/python-show-in-finder + self.common.log('UploadHistoryItemFile', 'open_folder', 'not implemented for Darwin yet') + + # Windows + elif self.common.platform == 'Windows': + # TODO: Implement opening folder with file selected in Windows + # This seems helpful: https://stackoverflow.com/questions/6631299/python-opening-a-folder-in-explorer-nautilus-mac-thingie + self.common.log('UploadHistoryItemFile', 'open_folder', 'not implemented for Windows yet') + + +class UploadHistoryItem(HistoryItem): + def __init__(self, common, id, content_length): + super(UploadHistoryItem, self).__init__() + self.common = common + self.id = id + self.content_length = content_length + self.started = datetime.now() + + # Label + self.label = QtWidgets.QLabel(strings._('gui_upload_in_progress', True).format(self.started.strftime("%b %d, %I:%M%p"))) + + # Progress bar + self.progress_bar = QtWidgets.QProgressBar() + self.progress_bar.setTextVisible(True) + self.progress_bar.setAttribute(QtCore.Qt.WA_DeleteOnClose) + self.progress_bar.setAlignment(QtCore.Qt.AlignHCenter) + self.progress_bar.setMinimum(0) + self.progress_bar.setValue(0) + self.progress_bar.setStyleSheet(self.common.css['downloads_uploads_progress_bar']) + + # This layout contains file widgets + self.files_layout = QtWidgets.QVBoxLayout() + self.files_layout.setContentsMargins(0, 0, 0, 0) + files_widget = QtWidgets.QWidget() + files_widget.setStyleSheet(self.common.css['receive_file']) + files_widget.setLayout(self.files_layout) + + # Layout + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label) + layout.addWidget(self.progress_bar) + layout.addWidget(files_widget) + layout.addStretch() + self.setLayout(layout) + + # We're also making a dictionary of file widgets, to make them easier to access + self.files = {} + + def update(self, data): + """ + Using the progress from Web, update the progress bar and file size labels + for each file + """ + if data['action'] == 'progress': + total_uploaded_bytes = 0 + for filename in data['progress']: + total_uploaded_bytes += data['progress'][filename]['uploaded_bytes'] + + # Update the progress bar + self.progress_bar.setMaximum(self.content_length) + self.progress_bar.setValue(total_uploaded_bytes) + + elapsed = datetime.now() - self.started + if elapsed.seconds < 10: + pb_fmt = strings._('gui_download_upload_progress_starting').format( + self.common.human_readable_filesize(total_uploaded_bytes)) + else: + estimated_time_remaining = self.common.estimated_time_remaining( + total_uploaded_bytes, + self.content_length, + self.started.timestamp()) + pb_fmt = strings._('gui_download_upload_progress_eta').format( + self.common.human_readable_filesize(total_uploaded_bytes), + estimated_time_remaining) + + # Using list(progress) to avoid "RuntimeError: dictionary changed size during iteration" + for filename in list(data['progress']): + # Add a new file if needed + if filename not in self.files: + self.files[filename] = UploadHistoryItemFile(self.common, filename) + self.files_layout.addWidget(self.files[filename]) + + # Update the file + self.files[filename].update(data['progress'][filename]['uploaded_bytes'], data['progress'][filename]['complete']) + + elif data['action'] == 'rename': + self.files[data['old_filename']].rename(data['new_filename']) + self.files[data['new_filename']] = self.files.pop(data['old_filename']) + + elif data['action'] == 'finished': + # Hide the progress bar + self.progress_bar.hide() + + # Change the label + self.ended = self.started = datetime.now() + if self.started.year == self.ended.year and self.started.month == self.ended.month and self.started.day == self.ended.day: + if self.started.hour == self.ended.hour and self.started.minute == self.ended.minute: + text = strings._('gui_upload_finished', True).format( + self.started.strftime("%b %d, %I:%M%p") + ) + else: + text = strings._('gui_upload_finished_range', True).format( + self.started.strftime("%b %d, %I:%M%p"), + self.ended.strftime("%I:%M%p") + ) + else: + text = strings._('gui_upload_finished_range', True).format( + self.started.strftime("%b %d, %I:%M%p"), + self.ended.strftime("%b %d, %I:%M%p") + ) + self.label.setText(text) + + class HistoryItemList(QtWidgets.QScrollArea): """ List of items diff --git a/onionshare_gui/mode/receive_mode/__init__.py b/onionshare_gui/mode/receive_mode/__init__.py index 96c76dbf..ffa259e7 100644 --- a/onionshare_gui/mode/receive_mode/__init__.py +++ b/onionshare_gui/mode/receive_mode/__init__.py @@ -22,8 +22,7 @@ from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings from onionshare.web import Web -from .uploads import Uploads -from .info import ReceiveModeInfo +from ..history import History, ToggleHistory, UploadHistoryItem from .. import Mode class ReceiveMode(Mode): @@ -47,26 +46,36 @@ class ReceiveMode(Mode): self.server_status.web = self.web self.server_status.update() - # Uploads - self.uploads = Uploads(self.common) - self.uploads.hide() - self.uploads_in_progress = 0 - self.uploads_completed = 0 - self.new_upload = False # For scrolling to the bottom of the uploads list + # Upload history + self.history = History( + self.common, + QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/uploads_transparent.png'))), + strings._('gui_no_uploads'), + strings._('gui_uploads') + ) + self.history.hide() - # Information about share, and show uploads button - self.info = ReceiveModeInfo(self.common, self) - self.info.show_less() + # Toggle history + self.toggle_history = ToggleHistory( + self.common, self, self.history, + QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle.png')), + QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle_selected.png')) + ) - # Receive mode info - self.receive_info = QtWidgets.QLabel(strings._('gui_receive_mode_warning', True)) - self.receive_info.setMinimumHeight(80) - self.receive_info.setWordWrap(True) + # Receive mode warning + receive_warning = QtWidgets.QLabel(strings._('gui_receive_mode_warning', True)) + receive_warning.setMinimumHeight(80) + receive_warning.setWordWrap(True) + + # Top bar + top_bar_layout = QtWidgets.QHBoxLayout() + top_bar_layout.addStretch() + top_bar_layout.addWidget(self.toggle_history) # Main layout self.main_layout = QtWidgets.QVBoxLayout() - self.main_layout.addWidget(self.info) - self.main_layout.addWidget(self.receive_info) + self.main_layout.addLayout(top_bar_layout) + self.main_layout.addWidget(receive_warning) self.main_layout.addWidget(self.primary_action) self.main_layout.addStretch() self.main_layout.addWidget(self.min_width_widget) @@ -74,7 +83,7 @@ class ReceiveMode(Mode): # Wrapper layout self.wrapper_layout = QtWidgets.QHBoxLayout() self.wrapper_layout.addLayout(self.main_layout) - self.wrapper_layout.addWidget(self.uploads) + self.wrapper_layout.addWidget(self.history) self.setLayout(self.wrapper_layout) def get_stop_server_shutdown_timeout_text(self): @@ -114,7 +123,7 @@ class ReceiveMode(Mode): Connection to Tor broke. """ self.primary_action.hide() - self.info.show_less() + #self.info.show_less() def handle_request_load(self, event): """ @@ -126,10 +135,11 @@ class ReceiveMode(Mode): """ Handle REQUEST_STARTED event. """ - self.uploads.add(event["data"]["id"], event["data"]["content_length"]) - self.info.update_indicator(True) - self.uploads_in_progress += 1 - self.info.update_uploads_in_progress() + item = UploadHistoryItem(self.common, event["data"]["id"], event["data"]["content_length"]) + self.history.add(event["data"]["id"], item) + self.toggle_history.update_indicator(True) + self.history.in_progress_count += 1 + self.history.update_in_progress() self.system_tray.showMessage(strings._('systray_upload_started_title', True), strings._('systray_upload_started_message', True)) @@ -137,7 +147,10 @@ class ReceiveMode(Mode): """ Handle REQUEST_PROGRESS event. """ - self.uploads.update(event["data"]["id"], event["data"]["progress"]) + self.history.update(event["data"]["id"], { + 'action': 'progress', + 'progress': event["data"]["progress"] + }) def handle_request_close_server(self, event): """ @@ -150,51 +163,45 @@ class ReceiveMode(Mode): """ Handle REQUEST_UPLOAD_FILE_RENAMED event. """ - self.uploads.rename(event["data"]["id"], event["data"]["old_filename"], event["data"]["new_filename"]) + self.history.update(event["data"]["id"], { + 'action': 'rename', + 'old_filename': event["data"]["old_filename"], + 'new_filename': event["data"]["new_filename"] + }) def handle_request_upload_finished(self, event): """ Handle REQUEST_UPLOAD_FINISHED event. """ - self.uploads.finished(event["data"]["id"]) - # Update the total 'completed uploads' info - self.uploads_completed += 1 - self.info.update_uploads_completed() - # Update the 'in progress uploads' info - self.uploads_in_progress -= 1 - self.info.update_uploads_in_progress() + self.history.update(event["data"]["id"], { + 'action': 'finished' + }) + self.history.completed_count += 1 + self.history.in_progress_count -= 1 + self.history.update_completed() + self.history.update_in_progress() def on_reload_settings(self): """ We should be ok to re-enable the 'Start Receive Mode' button now. """ self.primary_action.show() - self.info.show_more() + #self.info.show_more() def reset_info_counters(self): """ Set the info counters back to zero. """ - self.uploads_completed = 0 - self.uploads_in_progress = 0 - self.info.update_uploads_completed() - self.info.update_uploads_in_progress() - self.uploads.reset() + self.history.reset() def update_primary_action(self): self.common.log('ReceiveMode', 'update_primary_action') - # Show the info widget when the server is active - if self.server_status.status == self.server_status.STATUS_STARTED: - self.info.show_more() - else: - self.info.show_less() - # Resize window self.resize_window() def resize_window(self): min_width = self.common.min_window_width - if self.uploads.isVisible(): + if self.history.isVisible(): min_width += 300 self.adjust_size.emit(min_width) diff --git a/onionshare_gui/mode/receive_mode/uploads.py b/onionshare_gui/mode/receive_mode/uploads.py deleted file mode 100644 index c445be47..00000000 --- a/onionshare_gui/mode/receive_mode/uploads.py +++ /dev/null @@ -1,395 +0,0 @@ -# -*- coding: utf-8 -*- -""" -OnionShare | https://onionshare.org/ - -Copyright (C) 2014-2018 Micah Lee - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -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 os -import subprocess -import textwrap -from datetime import datetime -from PyQt5 import QtCore, QtWidgets, QtGui - -from onionshare import strings -from ...widgets import Alert - - -class File(QtWidgets.QWidget): - def __init__(self, common, filename): - super(File, self).__init__() - self.common = common - - self.common.log('File', '__init__', 'filename: {}'.format(filename)) - - self.filename = filename - self.started = datetime.now() - - # Filename label - self.filename_label = QtWidgets.QLabel(self.filename) - self.filename_label_width = self.filename_label.width() - - # File size label - self.filesize_label = QtWidgets.QLabel() - self.filesize_label.setStyleSheet(self.common.css['receive_file_size']) - self.filesize_label.hide() - - # Folder button - folder_pixmap = QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/open_folder.png'))) - folder_icon = QtGui.QIcon(folder_pixmap) - self.folder_button = QtWidgets.QPushButton() - self.folder_button.clicked.connect(self.open_folder) - self.folder_button.setIcon(folder_icon) - self.folder_button.setIconSize(folder_pixmap.rect().size()) - self.folder_button.setFlat(True) - self.folder_button.hide() - - # Layouts - layout = QtWidgets.QHBoxLayout() - layout.addWidget(self.filename_label) - layout.addWidget(self.filesize_label) - layout.addStretch() - layout.addWidget(self.folder_button) - self.setLayout(layout) - - def update(self, uploaded_bytes, complete): - self.filesize_label.setText(self.common.human_readable_filesize(uploaded_bytes)) - self.filesize_label.show() - - if complete: - self.folder_button.show() - - def rename(self, new_filename): - self.filename = new_filename - self.filename_label.setText(self.filename) - - def open_folder(self): - """ - Open the downloads folder, with the file selected, in a cross-platform manner - """ - self.common.log('File', 'open_folder') - - abs_filename = os.path.join(self.common.settings.get('downloads_dir'), self.filename) - - # Linux - if self.common.platform == 'Linux' or self.common.platform == 'BSD': - try: - # If nautilus is available, open it - subprocess.Popen(['nautilus', abs_filename]) - except: - Alert(self.common, strings._('gui_open_folder_error_nautilus').format(abs_filename)) - - # macOS - elif self.common.platform == 'Darwin': - # TODO: Implement opening folder with file selected in macOS - # This seems helpful: https://stackoverflow.com/questions/3520493/python-show-in-finder - self.common.log('File', 'open_folder', 'not implemented for Darwin yet') - - # Windows - elif self.common.platform == 'Windows': - # TODO: Implement opening folder with file selected in Windows - # This seems helpful: https://stackoverflow.com/questions/6631299/python-opening-a-folder-in-explorer-nautilus-mac-thingie - self.common.log('File', 'open_folder', 'not implemented for Windows yet') - - -class Upload(QtWidgets.QWidget): - def __init__(self, common, upload_id, content_length): - super(Upload, self).__init__() - self.common = common - self.upload_id = upload_id - self.content_length = content_length - self.started = datetime.now() - - # Label - self.label = QtWidgets.QLabel(strings._('gui_upload_in_progress', True).format(self.started.strftime("%b %d, %I:%M%p"))) - - # Progress bar - self.progress_bar = QtWidgets.QProgressBar() - self.progress_bar.setTextVisible(True) - self.progress_bar.setAttribute(QtCore.Qt.WA_DeleteOnClose) - self.progress_bar.setAlignment(QtCore.Qt.AlignHCenter) - self.progress_bar.setMinimum(0) - self.progress_bar.setValue(0) - self.progress_bar.setStyleSheet(self.common.css['downloads_uploads_progress_bar']) - - # This layout contains file widgets - self.files_layout = QtWidgets.QVBoxLayout() - self.files_layout.setContentsMargins(0, 0, 0, 0) - files_widget = QtWidgets.QWidget() - files_widget.setStyleSheet(self.common.css['receive_file']) - files_widget.setLayout(self.files_layout) - - # Layout - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.label) - layout.addWidget(self.progress_bar) - layout.addWidget(files_widget) - layout.addStretch() - self.setLayout(layout) - - # We're also making a dictionary of file widgets, to make them easier to access - self.files = {} - - def update(self, progress): - """ - Using the progress from Web, update the progress bar and file size labels - for each file - """ - total_uploaded_bytes = 0 - for filename in progress: - total_uploaded_bytes += progress[filename]['uploaded_bytes'] - - # Update the progress bar - self.progress_bar.setMaximum(self.content_length) - self.progress_bar.setValue(total_uploaded_bytes) - - elapsed = datetime.now() - self.started - if elapsed.seconds < 10: - pb_fmt = strings._('gui_download_upload_progress_starting').format( - self.common.human_readable_filesize(total_uploaded_bytes)) - else: - estimated_time_remaining = self.common.estimated_time_remaining( - total_uploaded_bytes, - self.content_length, - self.started.timestamp()) - pb_fmt = strings._('gui_download_upload_progress_eta').format( - self.common.human_readable_filesize(total_uploaded_bytes), - estimated_time_remaining) - - # Using list(progress) to avoid "RuntimeError: dictionary changed size during iteration" - for filename in list(progress): - # Add a new file if needed - if filename not in self.files: - self.files[filename] = File(self.common, filename) - self.files_layout.addWidget(self.files[filename]) - - # Update the file - self.files[filename].update(progress[filename]['uploaded_bytes'], progress[filename]['complete']) - - def rename(self, old_filename, new_filename): - self.files[old_filename].rename(new_filename) - self.files[new_filename] = self.files.pop(old_filename) - - def finished(self): - # Hide the progress bar - self.progress_bar.hide() - - # Change the label - self.ended = self.started = datetime.now() - if self.started.year == self.ended.year and self.started.month == self.ended.month and self.started.day == self.ended.day: - if self.started.hour == self.ended.hour and self.started.minute == self.ended.minute: - text = strings._('gui_upload_finished', True).format( - self.started.strftime("%b %d, %I:%M%p") - ) - else: - text = strings._('gui_upload_finished_range', True).format( - self.started.strftime("%b %d, %I:%M%p"), - self.ended.strftime("%I:%M%p") - ) - else: - text = strings._('gui_upload_finished_range', True).format( - self.started.strftime("%b %d, %I:%M%p"), - self.ended.strftime("%b %d, %I:%M%p") - ) - self.label.setText(text) - - -class UploadList(QtWidgets.QScrollArea): - """ - List of upload progess bars. - """ - def __init__(self, common): - super(UploadList, self).__init__() - self.common = common - - self.uploads = {} - - # The layout that holds all of the uploads - self.uploads_layout = QtWidgets.QVBoxLayout() - self.uploads_layout.setContentsMargins(0, 0, 0, 0) - self.uploads_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize) - - # Wrapper layout that also contains a stretch - wrapper_layout = QtWidgets.QVBoxLayout() - wrapper_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize) - wrapper_layout.addLayout(self.uploads_layout) - wrapper_layout.addStretch() - - # The internal widget of the scroll area - widget = QtWidgets.QWidget() - widget.setLayout(wrapper_layout) - self.setWidget(widget) - self.setWidgetResizable(True) - - # Other scroll area settings - self.setBackgroundRole(QtGui.QPalette.Light) - self.verticalScrollBar().rangeChanged.connect(self.resizeScroll) - - def resizeScroll(self, minimum, maximum): - """ - Scroll to the bottom of the window when the range changes. - """ - self.verticalScrollBar().setValue(maximum) - - def add(self, upload_id, content_length): - """ - Add a new upload progress bar. - """ - upload = Upload(self.common, upload_id, content_length) - self.uploads[upload_id] = upload - self.uploads_layout.addWidget(upload) - - def update(self, upload_id, progress): - """ - Update the progress of an upload. - """ - self.uploads[upload_id].update(progress) - - def rename(self, upload_id, old_filename, new_filename): - """ - Rename a file, which happens if the filename already exists in downloads_dir. - """ - self.uploads[upload_id].rename(old_filename, new_filename) - - def finished(self, upload_id): - """ - An upload has finished. - """ - self.uploads[upload_id].finished() - - def cancel(self, upload_id): - """ - Update an upload progress bar to show that it has been canceled. - """ - self.common.log('Uploads', 'cancel', 'upload_id: {}'.format(upload_id)) - self.uploads[upload_id].cancel() - - def reset(self): - """ - Reset the uploads back to zero - """ - for upload in self.uploads.values(): - self.uploads_layout.removeWidget(upload) - upload.progress_bar.close() - self.uploads = {} - - -class Uploads(QtWidgets.QWidget): - """ - The uploads chunk of the GUI. This lists all of the active upload - progress bars, as well as information about each upload. - """ - def __init__(self, common): - super(Uploads, self).__init__() - self.common = common - self.common.log('Uploads', '__init__') - - self.setMinimumWidth(350) - - # When there are no uploads - empty_image = QtWidgets.QLabel() - empty_image.setAlignment(QtCore.Qt.AlignCenter) - empty_image.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/uploads_transparent.png')))) - empty_text = QtWidgets.QLabel(strings._('gui_no_uploads', True)) - empty_text.setAlignment(QtCore.Qt.AlignCenter) - empty_text.setStyleSheet(self.common.css['downloads_uploads_empty_text']) - empty_layout = QtWidgets.QVBoxLayout() - empty_layout.addStretch() - empty_layout.addWidget(empty_image) - empty_layout.addWidget(empty_text) - empty_layout.addStretch() - self.empty = QtWidgets.QWidget() - self.empty.setStyleSheet(self.common.css['downloads_uploads_empty']) - self.empty.setLayout(empty_layout) - - # When there are uploads - self.upload_list = UploadList(self.common) - - # Upload header - uploads_label = QtWidgets.QLabel(strings._('gui_uploads', True)) - uploads_label.setStyleSheet(self.common.css['downloads_uploads_label']) - clear_button = QtWidgets.QPushButton(strings._('gui_clear_history', True)) - clear_button.setStyleSheet(self.common.css['downloads_uploads_clear']) - clear_button.setFlat(True) - clear_button.clicked.connect(self.reset) - upload_header = QtWidgets.QHBoxLayout() - upload_header.addWidget(uploads_label) - upload_header.addStretch() - upload_header.addWidget(clear_button) - - # Upload layout - not_empty_layout = QtWidgets.QVBoxLayout() - not_empty_layout.addLayout(upload_header) - not_empty_layout.addWidget(self.upload_list) - self.not_empty = QtWidgets.QWidget() - self.not_empty.setLayout(not_empty_layout) - - # Layout - layout = QtWidgets.QVBoxLayout() - layout.setContentsMargins(0, 0, 0, 0) - layout.addWidget(self.empty) - layout.addWidget(self.not_empty) - self.setLayout(layout) - - # Reset once at the beginning - self.reset() - - def add(self, upload_id, content_length): - """ - Add a new upload. - """ - self.common.log('Uploads', 'add', 'upload_id: {}, content_length: {}'.format(upload_id, content_length)) - - # Hide empty, show not empty - self.empty.hide() - self.not_empty.show() - - # Add it to the list - self.upload_list.add(upload_id, content_length) - - def update(self, upload_id, progress): - """ - Update the progress of an upload. - """ - self.upload_list.update(upload_id, progress) - - def rename(self, upload_id, old_filename, new_filename): - """ - Rename a file, which happens if the filename already exists in downloads_dir. - """ - self.upload_list.rename(upload_id, old_filename, new_filename) - - def finished(self, upload_id): - """ - An upload has finished. - """ - self.upload_list.finished(upload_id) - - def cancel(self, upload_id): - """ - Update an upload progress bar to show that it has been canceled. - """ - self.common.log('Uploads', 'cancel', 'upload_id: {}'.format(upload_id)) - self.upload_list.cancel(upload_id) - - def reset(self): - """ - Reset the uploads back to zero - """ - self.upload_list.reset() - - # Hide not empty, show empty - self.not_empty.hide() - self.empty.show() From 656784dfa94627121c8b75c588f555a61a223ae3 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 21:28:10 -0700 Subject: [PATCH 37/50] Remove obsolete ReceiveModeInfo file --- onionshare_gui/mode/receive_mode/info.py | 136 ----------------------- 1 file changed, 136 deletions(-) delete mode 100644 onionshare_gui/mode/receive_mode/info.py diff --git a/onionshare_gui/mode/receive_mode/info.py b/onionshare_gui/mode/receive_mode/info.py deleted file mode 100644 index c23f8496..00000000 --- a/onionshare_gui/mode/receive_mode/info.py +++ /dev/null @@ -1,136 +0,0 @@ -# -*- coding: utf-8 -*- -""" -OnionShare | https://onionshare.org/ - -Copyright (C) 2014-2018 Micah Lee - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -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 . -""" -from PyQt5 import QtCore, QtWidgets, QtGui - -from onionshare import strings - - -class ReceiveModeInfo(QtWidgets.QWidget): - """ - Receive mode information widget - """ - def __init__(self, common, receive_mode): - super(ReceiveModeInfo, self).__init__() - self.common = common - self.receive_mode = receive_mode - - # In progress and completed labels - self.in_progress_uploads_count = QtWidgets.QLabel() - self.in_progress_uploads_count.setStyleSheet(self.common.css['mode_info_label']) - self.completed_uploads_count = QtWidgets.QLabel() - self.completed_uploads_count.setStyleSheet(self.common.css['mode_info_label']) - - # Toggle button - self.toggle_button = QtWidgets.QPushButton() - self.toggle_button.setDefault(False) - self.toggle_button.setFixedWidth(35) - self.toggle_button.setFixedHeight(30) - self.toggle_button.setFlat(True) - self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle.png')) ) - self.toggle_button.clicked.connect(self.toggle_uploads) - - # Keep track of indicator - self.indicator_count = 0 - self.indicator_label = QtWidgets.QLabel(parent=self.toggle_button) - self.indicator_label.setStyleSheet(self.common.css['download_uploads_indicator']) - self.update_indicator() - - # Layout - layout = QtWidgets.QHBoxLayout() - layout.addStretch() - layout.addWidget(self.in_progress_uploads_count) - layout.addWidget(self.completed_uploads_count) - layout.addWidget(self.toggle_button) - self.setLayout(layout) - - self.update_uploads_completed() - self.update_uploads_in_progress() - - def update_indicator(self, increment=False): - """ - Update the display of the indicator count. If increment is True, then - only increment the counter if Uploads is hidden. - """ - if increment and not self.receive_mode.uploads.isVisible(): - self.indicator_count += 1 - - self.indicator_label.setText("{}".format(self.indicator_count)) - - if self.indicator_count == 0: - self.indicator_label.hide() - else: - size = self.indicator_label.sizeHint() - self.indicator_label.setGeometry(35-size.width(), 0, size.width(), size.height()) - self.indicator_label.show() - - def update_uploads_completed(self): - """ - Update the 'Uploads completed' info widget. - """ - if self.receive_mode.uploads_completed == 0: - image = self.common.get_resource_path('images/share_completed_none.png') - else: - image = self.common.get_resource_path('images/share_completed.png') - self.completed_uploads_count.setText(' {1:d}'.format(image, self.receive_mode.uploads_completed)) - self.completed_uploads_count.setToolTip(strings._('info_completed_uploads_tooltip', True).format(self.receive_mode.uploads_completed)) - - def update_uploads_in_progress(self): - """ - Update the 'Uploads in progress' info widget. - """ - if self.receive_mode.uploads_in_progress == 0: - image = self.common.get_resource_path('images/share_in_progress_none.png') - else: - image = self.common.get_resource_path('images/share_in_progress.png') - self.in_progress_uploads_count.setText(' {1:d}'.format(image, self.receive_mode.uploads_in_progress)) - self.in_progress_uploads_count.setToolTip(strings._('info_in_progress_uploads_tooltip', True).format(self.receive_mode.uploads_in_progress)) - - def toggle_uploads(self): - """ - Toggle showing and hiding the Uploads widget - """ - self.common.log('ReceiveModeInfo', 'toggle_uploads') - - if self.receive_mode.uploads.isVisible(): - self.receive_mode.uploads.hide() - self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle.png')) ) - self.toggle_button.setFlat(True) - else: - self.receive_mode.uploads.show() - self.toggle_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle_selected.png')) ) - self.toggle_button.setFlat(False) - - # Reset the indicator count - self.indicator_count = 0 - self.update_indicator() - - self.receive_mode.resize_window() - - def show_less(self): - """ - Remove clutter widgets that aren't necessary. - """ - pass - - def show_more(self): - """ - Show all widgets. - """ - pass From bc8759bc77864fceeab22e0d4038ce0750c3cc07 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 21:46:16 -0700 Subject: [PATCH 38/50] Properly close items inside the item list, instead of just hiding them --- onionshare_gui/mode/history.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onionshare_gui/mode/history.py b/onionshare_gui/mode/history.py index 4f5b2cef..ff31e3a9 100644 --- a/onionshare_gui/mode/history.py +++ b/onionshare_gui/mode/history.py @@ -347,7 +347,7 @@ class HistoryItemList(QtWidgets.QScrollArea): """ for item in self.items.values(): self.items_layout.removeWidget(item) - item.hide() + item.close() self.items = {} From 49e371d503ff05f95aeef358118fd74ba39a58fe Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Mon, 8 Oct 2018 10:59:11 +1100 Subject: [PATCH 39/50] adjust widget sizes when switching mode --- onionshare_gui/onionshare_gui.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 6a7eb63a..35088ebe 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -200,12 +200,14 @@ class OnionShareGui(QtWidgets.QMainWindow): self.receive_mode_button.setStyleSheet(self.common.css['mode_switcher_unselected_style']) self.receive_mode.hide() + self.adjust_size(self.common.min_window_width) self.share_mode.show() else: self.share_mode_button.setStyleSheet(self.common.css['mode_switcher_unselected_style']) self.receive_mode_button.setStyleSheet(self.common.css['mode_switcher_selected_style']) self.share_mode.hide() + self.adjust_size(self.common.min_window_width) self.receive_mode.show() self.update_server_status_indicator() From 50c0d91c5751c96d1dfc51055ed37ff166abe416 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 21:57:45 -0700 Subject: [PATCH 40/50] Missing imports --- onionshare_gui/mode/history.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/onionshare_gui/mode/history.py b/onionshare_gui/mode/history.py index ff31e3a9..07121363 100644 --- a/onionshare_gui/mode/history.py +++ b/onionshare_gui/mode/history.py @@ -19,10 +19,12 @@ along with this program. If not, see . """ import time import subprocess +import os from datetime import datetime from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings +from ..widgets import Alert class HistoryItem(QtWidgets.QWidget): From 5a2ca669a111604f46201627ea420a59ec9a9899 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 22:07:19 -0700 Subject: [PATCH 41/50] Rip out all of the adjust size logic and let Qt just handle it --- onionshare_gui/mode/__init__.py | 25 +----------- onionshare_gui/mode/receive_mode/__init__.py | 9 ---- onionshare_gui/mode/share_mode/__init__.py | 9 ---- onionshare_gui/onionshare_gui.py | 43 +------------------- 4 files changed, 2 insertions(+), 84 deletions(-) diff --git a/onionshare_gui/mode/__init__.py b/onionshare_gui/mode/__init__.py index cfbb235b..0971ff32 100644 --- a/onionshare_gui/mode/__init__.py +++ b/onionshare_gui/mode/__init__.py @@ -36,7 +36,6 @@ class Mode(QtWidgets.QWidget): starting_server_step3 = QtCore.pyqtSignal() starting_server_error = QtCore.pyqtSignal(str) set_server_active = QtCore.pyqtSignal(bool) - adjust_size = QtCore.pyqtSignal(int) def __init__(self, common, qtapp, app, status_bar, server_status_label, system_tray, filenames=None, local_only=False): super(Mode, self).__init__() @@ -50,8 +49,6 @@ class Mode(QtWidgets.QWidget): self.filenames = filenames - self.setMinimumWidth(self.common.min_window_width) - # The web object gets created in init() self.web = None @@ -83,7 +80,7 @@ class Mode(QtWidgets.QWidget): # Hack to allow a minimum width on the main layout # Note: It's up to the downstream Mode to add this to its layout self.min_width_widget = QtWidgets.QWidget() - self.min_width_widget.setMinimumWidth(self.common.min_window_width) + self.min_width_widget.setMinimumWidth(600) def init(self): """ @@ -332,23 +329,3 @@ class Mode(QtWidgets.QWidget): Handle REQUEST_UPLOAD_FINISHED event. """ pass - - def resize_window(self): - """ - We call this to force the OnionShare window to resize itself to be smaller. - For this to do anything, the Mode needs to override it and call: - - self.adjust_size.emit(min_width) - - It can calculate min_width (the new minimum window width) based on what - widgets are visible. - """ - pass - - def show(self): - """ - Always resize the window after showing this Mode widget. - """ - super(Mode, self).show() - self.qtapp.processEvents() - self.resize_window() diff --git a/onionshare_gui/mode/receive_mode/__init__.py b/onionshare_gui/mode/receive_mode/__init__.py index ffa259e7..66e0bbe7 100644 --- a/onionshare_gui/mode/receive_mode/__init__.py +++ b/onionshare_gui/mode/receive_mode/__init__.py @@ -196,12 +196,3 @@ class ReceiveMode(Mode): def update_primary_action(self): self.common.log('ReceiveMode', 'update_primary_action') - - # Resize window - self.resize_window() - - def resize_window(self): - min_width = self.common.min_window_width - if self.history.isVisible(): - min_width += 300 - self.adjust_size.emit(min_width) diff --git a/onionshare_gui/mode/share_mode/__init__.py b/onionshare_gui/mode/share_mode/__init__.py index 0bf094c0..b3d7c549 100644 --- a/onionshare_gui/mode/share_mode/__init__.py +++ b/onionshare_gui/mode/share_mode/__init__.py @@ -321,21 +321,12 @@ class ShareMode(Mode): self.primary_action.hide() self.info_label.hide() - # Resize window - self.resize_window() - def reset_info_counters(self): """ Set the info counters back to zero. """ self.history.reset() - def resize_window(self): - min_width = self.common.min_window_width - if self.history.isVisible(): - min_width += 300 - self.adjust_size.emit(min_width) - @staticmethod def _compute_total_size(filenames): total_size = 0 diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 35088ebe..9a71ae28 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -45,7 +45,7 @@ class OnionShareGui(QtWidgets.QMainWindow): self.common = common self.common.log('OnionShareGui', '__init__') - self.common.min_window_width = 460 + self.setMinimumWidth(700) self.onion = onion self.qtapp = qtapp @@ -133,7 +133,6 @@ class OnionShareGui(QtWidgets.QMainWindow): 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_server_active.connect(self.set_server_active) - self.share_mode.adjust_size.connect(self.adjust_size) # Receive mode self.receive_mode = ReceiveMode(self.common, qtapp, app, self.status_bar, self.server_status_label, self.system_tray, None, self.local_only) @@ -148,7 +147,6 @@ class OnionShareGui(QtWidgets.QMainWindow): self.receive_mode.server_status.url_copied.connect(self.copy_url) self.receive_mode.server_status.hidservauth_copied.connect(self.copy_hidservauth) self.receive_mode.set_server_active.connect(self.set_server_active) - self.receive_mode.adjust_size.connect(self.adjust_size) self.update_mode_switcher() self.update_server_status_indicator() @@ -169,9 +167,6 @@ class OnionShareGui(QtWidgets.QMainWindow): self.setCentralWidget(central_widget) self.show() - # Adjust window size, to start with a minimum window width - self.adjust_size(self.common.min_window_width) - # The server isn't active yet self.set_server_active(False) @@ -200,14 +195,12 @@ class OnionShareGui(QtWidgets.QMainWindow): self.receive_mode_button.setStyleSheet(self.common.css['mode_switcher_unselected_style']) self.receive_mode.hide() - self.adjust_size(self.common.min_window_width) self.share_mode.show() else: self.share_mode_button.setStyleSheet(self.common.css['mode_switcher_unselected_style']) self.receive_mode_button.setStyleSheet(self.common.css['mode_switcher_selected_style']) self.share_mode.hide() - self.adjust_size(self.common.min_window_width) self.receive_mode.show() self.update_server_status_indicator() @@ -450,40 +443,6 @@ class OnionShareGui(QtWidgets.QMainWindow): # Disable settings menu action when server is active self.settings_action.setEnabled(not active) - def adjust_size(self, min_width): - """ - Recursively adjust size on all widgets. min_width is the new minimum width - of the window. - """ - self.setMinimumWidth(min_width) - - def adjust_size_layout(layout): - count = layout.count() - for i in range(count): - item = layout.itemAt(i) - if item: - child_widget = item.widget() - if child_widget: - adjust_size_widget(child_widget) - child_layout = item.layout() - if child_layout: - adjust_size_layout(child_layout) - - def adjust_size_widget(widget): - layout = widget.layout() - if layout: - adjust_size_layout(layout) - widget.adjustSize() - - # Adjust sizes of each mode - for mode in [self.share_mode, self.receive_mode]: - self.qtapp.processEvents() - adjust_size_widget(mode) - - # Adjust window size - self.qtapp.processEvents() - self.adjustSize() - def closeEvent(self, e): self.common.log('OnionShareGui', 'closeEvent') try: From 9aa982563ba2bfe71d56221d5137e857d1425fe2 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 7 Oct 2018 22:09:57 -0700 Subject: [PATCH 42/50] Remove one more reference to resize_window --- onionshare_gui/mode/history.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/onionshare_gui/mode/history.py b/onionshare_gui/mode/history.py index 07121363..cf944aa0 100644 --- a/onionshare_gui/mode/history.py +++ b/onionshare_gui/mode/history.py @@ -548,5 +548,3 @@ class ToggleHistory(QtWidgets.QPushButton): # Reset the indicator count self.indicator_count = 0 self.update_indicator() - - self.current_mode.resize_window() From 6227c6cbc540078deaff627a1c70e907009dff00 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Tue, 9 Oct 2018 20:51:10 -0700 Subject: [PATCH 43/50] Set min width and height so everything always looks good, and change onion address to monospace font --- onionshare/common.py | 1 + onionshare_gui/onionshare_gui.py | 3 ++- onionshare_gui/server_status.py | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/onionshare/common.py b/onionshare/common.py index fb3b1e7a..96f9d2ad 100644 --- a/onionshare/common.py +++ b/onionshare/common.py @@ -211,6 +211,7 @@ class Common(object): color: #000000; padding: 10px; border: 1px solid #666666; + font-size: 12px; } """, diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 9a71ae28..3175f0f9 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -45,7 +45,8 @@ class OnionShareGui(QtWidgets.QMainWindow): self.common = common self.common.log('OnionShareGui', '__init__') - self.setMinimumWidth(700) + self.setMinimumWidth(820) + self.setMinimumHeight(530) self.onion = onion self.qtapp = qtapp diff --git a/onionshare_gui/server_status.py b/onionshare_gui/server_status.py index 32135ca4..99aaa9f1 100644 --- a/onionshare_gui/server_status.py +++ b/onionshare_gui/server_status.py @@ -90,20 +90,20 @@ class ServerStatus(QtWidgets.QWidget): self.server_button.clicked.connect(self.server_button_clicked) # URL layout - url_font = QtGui.QFont() + url_font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont) self.url_description = QtWidgets.QLabel() self.url_description.setWordWrap(True) self.url_description.setMinimumHeight(50) self.url = QtWidgets.QLabel() self.url.setFont(url_font) self.url.setWordWrap(True) - self.url.setMinimumHeight(65) self.url.setMinimumSize(self.url.sizeHint()) self.url.setStyleSheet(self.common.css['server_status_url']) self.copy_url_button = QtWidgets.QPushButton(strings._('gui_copy_url', True)) self.copy_url_button.setFlat(True) self.copy_url_button.setStyleSheet(self.common.css['server_status_url_buttons']) + self.copy_url_button.setMinimumHeight(65) self.copy_url_button.clicked.connect(self.copy_url) self.copy_hidservauth_button = QtWidgets.QPushButton(strings._('gui_copy_hidservauth', True)) self.copy_hidservauth_button.setFlat(True) From b982a9a24895f14dcb92289f7010e1a80d453557 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Tue, 9 Oct 2018 21:15:42 -0700 Subject: [PATCH 44/50] Actually, the window needs to be taller --- onionshare_gui/onionshare_gui.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 3175f0f9..1e03bc3e 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -46,7 +46,7 @@ class OnionShareGui(QtWidgets.QMainWindow): self.common = common self.common.log('OnionShareGui', '__init__') self.setMinimumWidth(820) - self.setMinimumHeight(530) + self.setMinimumHeight(620) self.onion = onion self.qtapp = qtapp @@ -154,7 +154,7 @@ class OnionShareGui(QtWidgets.QMainWindow): # Layouts contents_layout = QtWidgets.QVBoxLayout() - contents_layout.setContentsMargins(10, 10, 10, 10) + contents_layout.setContentsMargins(10, 0, 10, 0) contents_layout.addWidget(self.receive_mode) contents_layout.addWidget(self.share_mode) From 90172c913b025d011e05794902a55e4f478ffc76 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Tue, 9 Oct 2018 21:18:26 -0700 Subject: [PATCH 45/50] Stop hiding the share mode info label when tor breaks --- onionshare_gui/mode/receive_mode/__init__.py | 1 - onionshare_gui/mode/share_mode/__init__.py | 1 - 2 files changed, 2 deletions(-) diff --git a/onionshare_gui/mode/receive_mode/__init__.py b/onionshare_gui/mode/receive_mode/__init__.py index 66e0bbe7..e312a55b 100644 --- a/onionshare_gui/mode/receive_mode/__init__.py +++ b/onionshare_gui/mode/receive_mode/__init__.py @@ -123,7 +123,6 @@ class ReceiveMode(Mode): Connection to Tor broke. """ self.primary_action.hide() - #self.info.show_less() def handle_request_load(self, event): """ diff --git a/onionshare_gui/mode/share_mode/__init__.py b/onionshare_gui/mode/share_mode/__init__.py index b3d7c549..1c1f33ae 100644 --- a/onionshare_gui/mode/share_mode/__init__.py +++ b/onionshare_gui/mode/share_mode/__init__.py @@ -224,7 +224,6 @@ class ShareMode(Mode): Connection to Tor broke. """ self.primary_action.hide() - self.info_label.hide() def handle_request_load(self, event): """ From 5616a6a965b8662e20b5608788e3e17a1eb22af0 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Tue, 9 Oct 2018 21:49:05 -0700 Subject: [PATCH 46/50] Make the history indicator label circular again --- onionshare/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onionshare/common.py b/onionshare/common.py index 96f9d2ad..cab1e747 100644 --- a/onionshare/common.py +++ b/onionshare/common.py @@ -287,7 +287,7 @@ class Common(object): font-weight: bold; font-size: 10px; padding: 2px; - border-radius: 8px; + border-radius: 7px; text-align: center; }""", From 56e5c8b90879d7c7053e506fe9d913736717539a Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Tue, 9 Oct 2018 22:21:03 -0700 Subject: [PATCH 47/50] Add "download started" date/time to download history progress bars --- onionshare_gui/mode/history.py | 7 +++++-- share/locale/en.json | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/onionshare_gui/mode/history.py b/onionshare_gui/mode/history.py index cf944aa0..8cfa0ed5 100644 --- a/onionshare_gui/mode/history.py +++ b/onionshare_gui/mode/history.py @@ -50,11 +50,13 @@ class DownloadHistoryItem(HistoryItem): self.common = common self.id = id - self.started = time.time() self.total_bytes = total_bytes self.downloaded_bytes = 0 + self.started = time.time() + self.started_dt = datetime.fromtimestamp(self.started) - self.setStyleSheet('QWidget { border: 1px solid red; }') + # Label + self.label = QtWidgets.QLabel(strings._('gui_download_in_progress').format(self.started_dt.strftime("%b %d, %I:%M%p"))) # Progress bar self.progress_bar = QtWidgets.QProgressBar() @@ -69,6 +71,7 @@ class DownloadHistoryItem(HistoryItem): # Layout layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label) layout.addWidget(self.progress_bar) self.setLayout(layout) diff --git a/share/locale/en.json b/share/locale/en.json index 3537b0a2..e5d9a3be 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -180,5 +180,6 @@ "gui_upload_in_progress": "Upload Started {}", "gui_upload_finished_range": "Uploaded {} to {}", "gui_upload_finished": "Uploaded {}", + "gui_download_in_progress": "Download Started {}", "gui_open_folder_error_nautilus": "Cannot open folder because nautilus is not available. The file is here: {}" } From 85de803fda9a94e8721c94b2448043c6a30a1a03 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Wed, 10 Oct 2018 16:49:42 +1100 Subject: [PATCH 48/50] Raise minimumHeight again to account for overlap issues on MacOS caused by Mac's Qt widget padding --- onionshare_gui/onionshare_gui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 1e03bc3e..e672d74e 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -46,7 +46,7 @@ class OnionShareGui(QtWidgets.QMainWindow): self.common = common self.common.log('OnionShareGui', '__init__') self.setMinimumWidth(820) - self.setMinimumHeight(620) + self.setMinimumHeight(650) self.onion = onion self.qtapp = qtapp From beda37df06722cfa6163897a9f2ad3388084886b Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Wed, 10 Oct 2018 18:09:43 +1100 Subject: [PATCH 49/50] Remove commented out obsolete code --- onionshare_gui/mode/receive_mode/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/onionshare_gui/mode/receive_mode/__init__.py b/onionshare_gui/mode/receive_mode/__init__.py index e312a55b..b73acca2 100644 --- a/onionshare_gui/mode/receive_mode/__init__.py +++ b/onionshare_gui/mode/receive_mode/__init__.py @@ -185,7 +185,6 @@ class ReceiveMode(Mode): We should be ok to re-enable the 'Start Receive Mode' button now. """ self.primary_action.show() - #self.info.show_more() def reset_info_counters(self): """ From 753380663b5344e0b653ac8279143764b17ed465 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Wed, 10 Oct 2018 18:16:08 -0700 Subject: [PATCH 50/50] Final few tweaks to make this look perfect in macOS --- onionshare_gui/mode/share_mode/file_selection.py | 3 ++- onionshare_gui/onionshare_gui.py | 2 +- onionshare_gui/server_status.py | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/onionshare_gui/mode/share_mode/file_selection.py b/onionshare_gui/mode/share_mode/file_selection.py index d59df234..6bfa7dbf 100644 --- a/onionshare_gui/mode/share_mode/file_selection.py +++ b/onionshare_gui/mode/share_mode/file_selection.py @@ -89,7 +89,7 @@ class FileList(QtWidgets.QListWidget): self.setAcceptDrops(True) self.setIconSize(QtCore.QSize(32, 32)) self.setSortingEnabled(True) - self.setMinimumHeight(205) + self.setMinimumHeight(160) self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) self.drop_here_image = DropHereLabel(self.common, self, True) self.drop_here_text = DropHereLabel(self.common, self, False) @@ -261,6 +261,7 @@ class FileList(QtWidgets.QListWidget): # Item info widget, with a white background item_info_layout = QtWidgets.QHBoxLayout() + item_info_layout.setContentsMargins(0, 0, 0, 0) item_info_layout.addWidget(item_size) item_info_layout.addWidget(item.item_button) item_info = QtWidgets.QWidget() diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index e672d74e..c2e6657b 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -46,7 +46,7 @@ class OnionShareGui(QtWidgets.QMainWindow): self.common = common self.common.log('OnionShareGui', '__init__') self.setMinimumWidth(820) - self.setMinimumHeight(650) + self.setMinimumHeight(660) self.onion = onion self.qtapp = qtapp diff --git a/onionshare_gui/server_status.py b/onionshare_gui/server_status.py index 99aaa9f1..0267d826 100644 --- a/onionshare_gui/server_status.py +++ b/onionshare_gui/server_status.py @@ -142,12 +142,12 @@ class ServerStatus(QtWidgets.QWidget): When the widget is resized, try and adjust the display of a v3 onion URL. """ try: - self.get_url() + # Wrap the URL label url_length=len(self.get_url()) if url_length > 60: width = self.frameGeometry().width() if width < 530: - wrapped_onion_url = textwrap.fill(self.get_url(), 50) + wrapped_onion_url = textwrap.fill(self.get_url(), 46) self.url.setText(wrapped_onion_url) else: self.url.setText(self.get_url())