summaryrefslogtreecommitdiff
path: root/onionshare_gui/mode
diff options
context:
space:
mode:
Diffstat (limited to 'onionshare_gui/mode')
-rw-r--r--onionshare_gui/mode/__init__.py161
-rw-r--r--onionshare_gui/mode/file_selection.py (renamed from onionshare_gui/mode/share_mode/file_selection.py)93
-rw-r--r--onionshare_gui/mode/history.py371
-rw-r--r--onionshare_gui/mode/receive_mode/__init__.py107
-rw-r--r--onionshare_gui/mode/share_mode/__init__.py92
-rw-r--r--onionshare_gui/mode/share_mode/threads.py21
-rw-r--r--onionshare_gui/mode/website_mode/__init__.py266
7 files changed, 871 insertions, 240 deletions
diff --git a/onionshare_gui/mode/__init__.py b/onionshare_gui/mode/__init__.py
index 8f5ff32b..04709dc2 100644
--- a/onionshare_gui/mode/__init__.py
+++ b/onionshare_gui/mode/__init__.py
@@ -22,15 +22,19 @@ from PyQt5 import QtCore, QtWidgets, QtGui
from onionshare import strings
from onionshare.common import AutoStopTimer
+from .history import IndividualFileHistoryItem
+
from ..server_status import ServerStatus
from ..threads import OnionThread
-from ..threads import AutoStartTimer
+from ..threads import AutoStartTimer
from ..widgets import Alert
+
class Mode(QtWidgets.QWidget):
"""
- The class that ShareMode and ReceiveMode inherit from.
+ The class that all modes inherit from
"""
+
start_server_finished = QtCore.pyqtSignal()
stop_server_finished = QtCore.pyqtSignal()
starting_server_step2 = QtCore.pyqtSignal()
@@ -39,7 +43,17 @@ class Mode(QtWidgets.QWidget):
starting_server_early = QtCore.pyqtSignal()
set_server_active = QtCore.pyqtSignal(bool)
- def __init__(self, common, qtapp, app, status_bar, server_status_label, system_tray, filenames=None, local_only=False):
+ def __init__(
+ self,
+ common,
+ qtapp,
+ app,
+ status_bar,
+ server_status_label,
+ system_tray,
+ filenames=None,
+ local_only=False,
+ ):
super(Mode, self).__init__()
self.common = common
self.qtapp = qtapp
@@ -63,7 +77,9 @@ class Mode(QtWidgets.QWidget):
self.startup_thread = None
# Server status
- self.server_status = ServerStatus(self.common, self.qtapp, self.app, None, self.local_only)
+ self.server_status = ServerStatus(
+ self.common, self.qtapp, self.app, None, self.local_only
+ )
self.server_status.server_started.connect(self.start_server)
self.server_status.server_stopped.connect(self.stop_server)
self.server_status.server_canceled.connect(self.cancel_server)
@@ -96,16 +112,26 @@ class Mode(QtWidgets.QWidget):
"""
Returns a human-friendly time delta from given seconds.
"""
- days = secs//86400
- hours = (secs - days*86400)//3600
- minutes = (secs - days*86400 - hours*3600)//60
- seconds = secs - days*86400 - hours*3600 - minutes*60
+ days = secs // 86400
+ hours = (secs - days * 86400) // 3600
+ minutes = (secs - days * 86400 - hours * 3600) // 60
+ seconds = secs - days * 86400 - hours * 3600 - minutes * 60
if not seconds:
- seconds = '0'
- result = ("{0}{1}, ".format(days, strings._('days_first_letter')) if days else "") + \
- ("{0}{1}, ".format(hours, strings._('hours_first_letter')) if hours else "") + \
- ("{0}{1}, ".format(minutes, strings._('minutes_first_letter')) if minutes else "") + \
- "{0}{1}".format(seconds, strings._('seconds_first_letter'))
+ seconds = "0"
+ result = (
+ ("{0}{1}, ".format(days, strings._("days_first_letter")) if days else "")
+ + (
+ "{0}{1}, ".format(hours, strings._("hours_first_letter"))
+ if hours
+ else ""
+ )
+ + (
+ "{0}{1}, ".format(minutes, strings._("minutes_first_letter"))
+ if minutes
+ else ""
+ )
+ + "{0}{1}".format(seconds, strings._("seconds_first_letter"))
+ )
return result
@@ -118,25 +144,45 @@ class Mode(QtWidgets.QWidget):
if self.server_status.autostart_timer_datetime:
now = QtCore.QDateTime.currentDateTime()
if self.server_status.local_only:
- seconds_remaining = now.secsTo(self.server_status.autostart_timer_widget.dateTime())
+ seconds_remaining = now.secsTo(
+ self.server_status.autostart_timer_widget.dateTime()
+ )
else:
- seconds_remaining = now.secsTo(self.server_status.autostart_timer_datetime.replace(second=0, microsecond=0))
+ seconds_remaining = now.secsTo(
+ self.server_status.autostart_timer_datetime.replace(
+ second=0, microsecond=0
+ )
+ )
# Update the server button
if seconds_remaining > 0:
- self.server_status.server_button.setText(strings._('gui_waiting_to_start').format(self.human_friendly_time(seconds_remaining)))
+ self.server_status.server_button.setText(
+ strings._("gui_waiting_to_start").format(
+ self.human_friendly_time(seconds_remaining)
+ )
+ )
else:
- self.server_status.server_button.setText(strings._('gui_please_wait'))
+ self.server_status.server_button.setText(
+ strings._("gui_please_wait")
+ )
# If the auto-stop timer has stopped, stop the server
if self.server_status.status == ServerStatus.STATUS_STARTED:
- if self.app.autostop_timer_thread and self.common.settings.get('autostop_timer'):
+ if self.app.autostop_timer_thread and self.common.settings.get(
+ "autostop_timer"
+ ):
if self.autostop_timer_datetime_delta > 0:
now = QtCore.QDateTime.currentDateTime()
- seconds_remaining = now.secsTo(self.server_status.autostop_timer_datetime)
+ seconds_remaining = now.secsTo(
+ self.server_status.autostop_timer_datetime
+ )
# Update the server button
server_button_text = self.get_stop_server_autostop_timer_text()
- self.server_status.server_button.setText(server_button_text.format(self.human_friendly_time(seconds_remaining)))
+ self.server_status.server_button.setText(
+ server_button_text.format(
+ self.human_friendly_time(seconds_remaining)
+ )
+ )
self.status_bar.clearMessage()
if not self.app.autostop_timer_thread.is_alive():
@@ -166,22 +212,22 @@ class Mode(QtWidgets.QWidget):
Start the onionshare server. This uses multiple threads to start the Tor onion
server and the web app.
"""
- self.common.log('Mode', 'start_server')
+ self.common.log("Mode", "start_server")
self.start_server_custom()
self.set_server_active.emit(True)
- self.app.set_stealth(self.common.settings.get('use_stealth'))
+ self.app.set_stealth(self.common.settings.get("use_stealth"))
# Clear the status bar
self.status_bar.clearMessage()
- self.server_status_label.setText('')
+ self.server_status_label.setText("")
# Ensure we always get a new random port each time we might launch an OnionThread
self.app.port = None
# Start the onion thread. If this share was scheduled for a future date,
- # the OnionThread will start and exit 'early' to obtain the port, slug
+ # the OnionThread will start and exit 'early' to obtain the port, password
# and onion address, but it will not start the WebThread yet.
if self.server_status.autostart_timer_datetime:
self.start_onion_thread(obtain_onion_early=True)
@@ -190,7 +236,7 @@ class Mode(QtWidgets.QWidget):
# If scheduling a share, delay starting the real share
if self.server_status.autostart_timer_datetime:
- self.common.log('Mode', 'start_server', 'Starting auto-start timer')
+ self.common.log("Mode", "start_server", "Starting auto-start timer")
self.startup_thread = AutoStartTimer(self)
# Once the timer has finished, start the real share, with a WebThread
self.startup_thread.success.connect(self.start_scheduled_service)
@@ -199,7 +245,7 @@ class Mode(QtWidgets.QWidget):
self.startup_thread.start()
def start_onion_thread(self, obtain_onion_early=False):
- self.common.log('Mode', 'start_server', 'Starting an onion thread')
+ self.common.log("Mode", "start_server", "Starting an onion thread")
self.obtain_onion_early = obtain_onion_early
self.onion_thread = OnionThread(self)
self.onion_thread.success.connect(self.starting_server_step2.emit)
@@ -211,7 +257,7 @@ class Mode(QtWidgets.QWidget):
# We start a new OnionThread with the saved scheduled key from settings
self.common.settings.load()
self.obtain_onion_early = obtain_onion_early
- self.common.log('Mode', 'start_server', 'Starting a scheduled onion thread')
+ self.common.log("Mode", "start_server", "Starting a scheduled onion thread")
self.onion_thread = OnionThread(self)
self.onion_thread.success.connect(self.starting_server_step2.emit)
self.onion_thread.error.connect(self.starting_server_error.emit)
@@ -235,7 +281,7 @@ class Mode(QtWidgets.QWidget):
"""
Step 2 in starting the onionshare server.
"""
- self.common.log('Mode', 'start_server_step2')
+ self.common.log("Mode", "start_server_step2")
self.start_server_step2_custom()
@@ -255,22 +301,28 @@ class Mode(QtWidgets.QWidget):
"""
Step 3 in starting the onionshare server.
"""
- self.common.log('Mode', 'start_server_step3')
+ self.common.log("Mode", "start_server_step3")
self.start_server_step3_custom()
- if self.common.settings.get('autostop_timer'):
+ if self.common.settings.get("autostop_timer"):
# Convert the date value to seconds between now and then
now = QtCore.QDateTime.currentDateTime()
- self.autostop_timer_datetime_delta = now.secsTo(self.server_status.autostop_timer_datetime)
+ self.autostop_timer_datetime_delta = now.secsTo(
+ self.server_status.autostop_timer_datetime
+ )
# Start the auto-stop timer
if self.autostop_timer_datetime_delta > 0:
- self.app.autostop_timer_thread = AutoStopTimer(self.common, self.autostop_timer_datetime_delta)
+ self.app.autostop_timer_thread = AutoStopTimer(
+ self.common, self.autostop_timer_datetime_delta
+ )
self.app.autostop_timer_thread.start()
# The auto-stop timer has actually already passed since the user clicked Start. Probably the Onion service took too long to start.
else:
self.stop_server()
- self.start_server_error(strings._('gui_server_started_after_autostop_timer'))
+ self.start_server_error(
+ strings._("gui_server_started_after_autostop_timer")
+ )
def start_server_step3_custom(self):
"""
@@ -282,7 +334,7 @@ class Mode(QtWidgets.QWidget):
"""
If there's an error when trying to start the onion service
"""
- self.common.log('Mode', 'start_server_error')
+ self.common.log("Mode", "start_server_error")
Alert(self.common, error, QtWidgets.QMessageBox.Warning)
self.set_server_active.emit(False)
@@ -303,16 +355,16 @@ class Mode(QtWidgets.QWidget):
"""
self.cancel_server_custom()
if self.startup_thread:
- self.common.log('Mode', 'cancel_server: quitting startup thread')
+ self.common.log("Mode", "cancel_server: quitting startup thread")
self.startup_thread.canceled = True
self.app.onion.scheduled_key = None
self.app.onion.scheduled_auth_cookie = None
self.startup_thread.quit()
if self.onion_thread:
- self.common.log('Mode', 'cancel_server: quitting onion thread')
+ self.common.log("Mode", "cancel_server: quitting onion thread")
self.onion_thread.quit()
if self.web_thread:
- self.common.log('Mode', 'cancel_server: quitting web thread')
+ self.common.log("Mode", "cancel_server: quitting web thread")
self.web_thread.quit()
self.stop_server()
@@ -326,7 +378,7 @@ class Mode(QtWidgets.QWidget):
"""
Stop the onionshare server.
"""
- self.common.log('Mode', 'stop_server')
+ self.common.log("Mode", "stop_server")
if self.server_status.status != ServerStatus.STATUS_STOPPED:
try:
@@ -380,7 +432,9 @@ class Mode(QtWidgets.QWidget):
Handle REQUEST_RATE_LIMIT event.
"""
self.stop_server()
- Alert(self.common, strings._('error_rate_limit'), QtWidgets.QMessageBox.Critical)
+ Alert(
+ self.common, strings._("error_rate_limit"), QtWidgets.QMessageBox.Critical
+ )
def handle_request_progress(self, event):
"""
@@ -417,3 +471,32 @@ class Mode(QtWidgets.QWidget):
Handle REQUEST_UPLOAD_CANCELED event.
"""
pass
+
+ def handle_request_individual_file_started(self, event):
+ """
+ Handle REQUEST_INDVIDIDUAL_FILES_STARTED event.
+ Used in both Share and Website modes, so implemented here.
+ """
+ self.toggle_history.update_indicator(True)
+ self.history.requests_count += 1
+ self.history.update_requests()
+
+ item = IndividualFileHistoryItem(self.common, event["data"], event["path"])
+ self.history.add(event["data"]["id"], item)
+
+ def handle_request_individual_file_progress(self, event):
+ """
+ Handle REQUEST_INDVIDIDUAL_FILES_PROGRESS event.
+ Used in both Share and Website modes, so implemented here.
+ """
+ self.history.update(event["data"]["id"], event["data"]["bytes"])
+
+ if self.server_status.status == self.server_status.STATUS_STOPPED:
+ self.history.cancel(event["data"]["id"])
+
+ def handle_request_individual_file_canceled(self, event):
+ """
+ Handle REQUEST_INDVIDIDUAL_FILES_CANCELED event.
+ Used in both Share and Website modes, so implemented here.
+ """
+ self.history.cancel(event["data"]["id"])
diff --git a/onionshare_gui/mode/share_mode/file_selection.py b/onionshare_gui/mode/file_selection.py
index 0d4229fe..c505dc03 100644
--- a/onionshare_gui/mode/share_mode/file_selection.py
+++ b/onionshare_gui/mode/file_selection.py
@@ -22,13 +22,15 @@ from PyQt5 import QtCore, QtWidgets, QtGui
from onionshare import strings
-from ...widgets import Alert, AddFileDialog
+from ..widgets import Alert, AddFileDialog
+
class DropHereLabel(QtWidgets.QLabel):
"""
When there are no files or folders in the FileList yet, display the
'drop files here' message and graphic.
"""
+
def __init__(self, common, parent, image=False):
self.parent = parent
super(DropHereLabel, self).__init__(parent=parent)
@@ -39,10 +41,16 @@ class DropHereLabel(QtWidgets.QLabel):
self.setAlignment(QtCore.Qt.AlignCenter)
if image:
- self.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/logo_transparent.png'))))
+ self.setPixmap(
+ QtGui.QPixmap.fromImage(
+ QtGui.QImage(
+ self.common.get_resource_path("images/logo_transparent.png")
+ )
+ )
+ )
else:
- self.setText(strings._('gui_drag_and_drop'))
- self.setStyleSheet(self.common.css['share_file_selection_drop_here_label'])
+ self.setText(strings._("gui_drag_and_drop"))
+ self.setStyleSheet(self.common.css["share_file_selection_drop_here_label"])
self.hide()
@@ -57,6 +65,7 @@ class DropCountLabel(QtWidgets.QLabel):
While dragging files over the FileList, this counter displays the
number of files you're dragging.
"""
+
def __init__(self, common, parent):
self.parent = parent
super(DropCountLabel, self).__init__(parent=parent)
@@ -65,8 +74,8 @@ class DropCountLabel(QtWidgets.QLabel):
self.setAcceptDrops(True)
self.setAlignment(QtCore.Qt.AlignCenter)
- self.setText(strings._('gui_drag_and_drop'))
- self.setStyleSheet(self.common.css['share_file_selection_drop_count_label'])
+ self.setText(strings._("gui_drag_and_drop"))
+ self.setStyleSheet(self.common.css["share_file_selection_drop_count_label"])
self.hide()
def dragEnterEvent(self, event):
@@ -78,6 +87,7 @@ class FileList(QtWidgets.QListWidget):
"""
The list of files and folders in the GUI.
"""
+
files_dropped = QtCore.pyqtSignal()
files_updated = QtCore.pyqtSignal()
@@ -139,7 +149,7 @@ class FileList(QtWidgets.QListWidget):
if self.count() > 0:
# Add and delete an empty item, to force all items to get redrawn
# This is ugly, but the only way I could figure out how to proceed
- item = QtWidgets.QListWidgetItem('fake item')
+ item = QtWidgets.QListWidgetItem("fake item")
self.addItem(item)
self.takeItem(self.row(item))
self.update()
@@ -149,21 +159,27 @@ class FileList(QtWidgets.QListWidget):
# and extend based on the overall width minus that amount.
for index in range(self.count()):
metrics = QtGui.QFontMetrics(self.item(index).font())
- elided = metrics.elidedText(self.item(index).basename, QtCore.Qt.ElideRight, self.width() - 200)
+ elided = metrics.elidedText(
+ self.item(index).basename, QtCore.Qt.ElideRight, self.width() - 200
+ )
self.item(index).setText(elided)
-
def dragEnterEvent(self, event):
"""
dragEnterEvent for dragging files and directories into the widget.
"""
if event.mimeData().hasUrls:
- self.setStyleSheet(self.common.css['share_file_list_drag_enter'])
+ self.setStyleSheet(self.common.css["share_file_list_drag_enter"])
count = len(event.mimeData().urls())
- self.drop_count.setText('+{}'.format(count))
+ self.drop_count.setText("+{}".format(count))
size_hint = self.drop_count.sizeHint()
- self.drop_count.setGeometry(self.width() - size_hint.width() - 10, self.height() - size_hint.height() - 10, size_hint.width(), size_hint.height())
+ self.drop_count.setGeometry(
+ self.width() - size_hint.width() - 10,
+ self.height() - size_hint.height() - 10,
+ size_hint.width(),
+ size_hint.height(),
+ )
self.drop_count.show()
event.accept()
else:
@@ -173,7 +189,7 @@ class FileList(QtWidgets.QListWidget):
"""
dragLeaveEvent for dragging files and directories into the widget.
"""
- self.setStyleSheet(self.common.css['share_file_list_drag_leave'])
+ self.setStyleSheet(self.common.css["share_file_list_drag_leave"])
self.drop_count.hide()
event.accept()
self.update()
@@ -201,7 +217,7 @@ class FileList(QtWidgets.QListWidget):
else:
event.ignore()
- self.setStyleSheet(self.common.css['share_file_list_drag_leave'])
+ self.setStyleSheet(self.common.css["share_file_list_drag_leave"])
self.drop_count.hide()
self.files_dropped.emit()
@@ -238,12 +254,14 @@ class FileList(QtWidgets.QListWidget):
# Item's filename attribute and size labels
item.filename = filename
item_size = QtWidgets.QLabel(size_readable)
- item_size.setStyleSheet(self.common.css['share_file_list_item_size'])
+ item_size.setStyleSheet(self.common.css["share_file_list_item_size"])
- item.basename = os.path.basename(filename.rstrip('/'))
+ item.basename = os.path.basename(filename.rstrip("/"))
# Use the basename as the method with which to sort the list
metrics = QtGui.QFontMetrics(item.font())
- elided = metrics.elidedText(item.basename, QtCore.Qt.ElideRight, self.sizeHint().width())
+ elided = metrics.elidedText(
+ item.basename, QtCore.Qt.ElideRight, self.sizeHint().width()
+ )
item.setData(QtCore.Qt.DisplayRole, elided)
# Item's delete button
@@ -255,9 +273,13 @@ class FileList(QtWidgets.QListWidget):
item.item_button = QtWidgets.QPushButton()
item.item_button.setDefault(False)
item.item_button.setFlat(True)
- item.item_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/file_delete.png')) )
+ item.item_button.setIcon(
+ QtGui.QIcon(self.common.get_resource_path("images/file_delete.png"))
+ )
item.item_button.clicked.connect(delete_item)
- item.item_button.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ item.item_button.setSizePolicy(
+ QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed
+ )
# Item info widget, with a white background
item_info_layout = QtWidgets.QHBoxLayout()
@@ -265,7 +287,7 @@ class FileList(QtWidgets.QListWidget):
item_info_layout.addWidget(item_size)
item_info_layout.addWidget(item.item_button)
item_info = QtWidgets.QWidget()
- item_info.setObjectName('item-info')
+ item_info.setObjectName("item-info")
item_info.setLayout(item_info_layout)
# Create the item's widget and layouts
@@ -288,6 +310,7 @@ class FileSelection(QtWidgets.QVBoxLayout):
The list of files and folders in the GUI, as well as buttons to add and
delete the files and folders.
"""
+
def __init__(self, common, parent):
super(FileSelection, self).__init__()
@@ -303,21 +326,21 @@ class FileSelection(QtWidgets.QVBoxLayout):
self.file_list.files_updated.connect(self.update)
# Buttons
- if self.common.platform == 'Darwin':
+ if self.common.platform == "Darwin":
# The macOS sandbox makes it so the Mac version needs separate add files
# and folders buttons, in order to use native file selection dialogs
- self.add_files_button = QtWidgets.QPushButton(strings._('gui_add_files'))
+ self.add_files_button = QtWidgets.QPushButton(strings._("gui_add_files"))
self.add_files_button.clicked.connect(self.add_files)
- self.add_folder_button = QtWidgets.QPushButton(strings._('gui_add_folder'))
+ self.add_folder_button = QtWidgets.QPushButton(strings._("gui_add_folder"))
self.add_folder_button.clicked.connect(self.add_folder)
else:
- self.add_button = QtWidgets.QPushButton(strings._('gui_add'))
+ self.add_button = QtWidgets.QPushButton(strings._("gui_add"))
self.add_button.clicked.connect(self.add)
- self.delete_button = QtWidgets.QPushButton(strings._('gui_delete'))
+ self.delete_button = QtWidgets.QPushButton(strings._("gui_delete"))
self.delete_button.clicked.connect(self.delete)
button_layout = QtWidgets.QHBoxLayout()
button_layout.addStretch()
- if self.common.platform == 'Darwin':
+ if self.common.platform == "Darwin":
button_layout.addWidget(self.add_files_button)
button_layout.addWidget(self.add_folder_button)
else:
@@ -336,14 +359,14 @@ class FileSelection(QtWidgets.QVBoxLayout):
"""
# All buttons should be hidden if the server is on
if self.server_on:
- if self.common.platform == 'Darwin':
+ if self.common.platform == "Darwin":
self.add_files_button.hide()
self.add_folder_button.hide()
else:
self.add_button.hide()
self.delete_button.hide()
else:
- if self.common.platform == 'Darwin':
+ if self.common.platform == "Darwin":
self.add_files_button.show()
self.add_folder_button.show()
else:
@@ -362,7 +385,7 @@ class FileSelection(QtWidgets.QVBoxLayout):
"""
Add button clicked.
"""
- file_dialog = AddFileDialog(self.common, caption=strings._('gui_choose_items'))
+ file_dialog = AddFileDialog(self.common, caption=strings._("gui_choose_items"))
if file_dialog.exec_() == QtWidgets.QDialog.Accepted:
for filename in file_dialog.selectedFiles():
self.file_list.add_file(filename)
@@ -374,7 +397,9 @@ class FileSelection(QtWidgets.QVBoxLayout):
"""
Add files button clicked.
"""
- files = QtWidgets.QFileDialog.getOpenFileNames(self.parent, caption=strings._('gui_choose_items'))
+ files = QtWidgets.QFileDialog.getOpenFileNames(
+ self.parent, caption=strings._("gui_choose_items")
+ )
filenames = files[0]
for filename in filenames:
self.file_list.add_file(filename)
@@ -383,9 +408,11 @@ class FileSelection(QtWidgets.QVBoxLayout):
"""
Add folder button clicked.
"""
- filename = QtWidgets.QFileDialog.getExistingDirectory(self.parent,
- caption=strings._('gui_choose_items'),
- options=QtWidgets.QFileDialog.ShowDirsOnly)
+ filename = QtWidgets.QFileDialog.getExistingDirectory(
+ self.parent,
+ caption=strings._("gui_choose_items"),
+ options=QtWidgets.QFileDialog.ShowDirsOnly,
+ )
self.file_list.add_file(filename)
def delete(self):
diff --git a/onionshare_gui/mode/history.py b/onionshare_gui/mode/history.py
index 1546cb68..85eec7e4 100644
--- a/onionshare_gui/mode/history.py
+++ b/onionshare_gui/mode/history.py
@@ -31,6 +31,7 @@ class HistoryItem(QtWidgets.QWidget):
"""
The base history item
"""
+
STATUS_STARTED = 0
STATUS_FINISHED = 1
STATUS_CANCELED = 2
@@ -49,34 +50,42 @@ class HistoryItem(QtWidgets.QWidget):
When an item finishes, returns a string displaying the start/end datetime range.
started is a datetime object.
"""
- return self._get_label_text('gui_all_modes_transfer_finished', 'gui_all_modes_transfer_finished_range', started)
+ return self._get_label_text(
+ "gui_all_modes_transfer_finished",
+ "gui_all_modes_transfer_finished_range",
+ started,
+ )
def get_canceled_label_text(self, started):
"""
When an item is canceled, returns a string displaying the start/end datetime range.
started is a datetime object.
"""
- return self._get_label_text('gui_all_modes_transfer_canceled', 'gui_all_modes_transfer_canceled_range', started)
+ return self._get_label_text(
+ "gui_all_modes_transfer_canceled",
+ "gui_all_modes_transfer_canceled_range",
+ started,
+ )
def _get_label_text(self, string_name, string_range_name, started):
"""
Return a string that contains a date, or date range.
"""
ended = datetime.now()
- if started.year == ended.year and started.month == ended.month and started.day == ended.day:
+ if (
+ started.year == ended.year
+ and started.month == ended.month
+ and started.day == ended.day
+ ):
if started.hour == ended.hour and started.minute == ended.minute:
- text = strings._(string_name).format(
- started.strftime("%b %d, %I:%M%p")
- )
+ text = strings._(string_name).format(started.strftime("%b %d, %I:%M%p"))
else:
text = strings._(string_range_name).format(
- started.strftime("%b %d, %I:%M%p"),
- ended.strftime("%I:%M%p")
+ started.strftime("%b %d, %I:%M%p"), ended.strftime("%I:%M%p")
)
else:
text = strings._(string_range_name).format(
- started.strftime("%b %d, %I:%M%p"),
- ended.strftime("%b %d, %I:%M%p")
+ started.strftime("%b %d, %I:%M%p"), ended.strftime("%b %d, %I:%M%p")
)
return text
@@ -85,6 +94,7 @@ class ShareHistoryItem(HistoryItem):
"""
Download history item, for share mode
"""
+
def __init__(self, common, id, total_bytes):
super(ShareHistoryItem, self).__init__()
self.common = common
@@ -97,7 +107,11 @@ class ShareHistoryItem(HistoryItem):
self.status = HistoryItem.STATUS_STARTED
# Label
- self.label = QtWidgets.QLabel(strings._('gui_all_modes_transfer_started').format(self.started_dt.strftime("%b %d, %I:%M%p")))
+ self.label = QtWidgets.QLabel(
+ strings._("gui_all_modes_transfer_started").format(
+ self.started_dt.strftime("%b %d, %I:%M%p")
+ )
+ )
# Progress bar
self.progress_bar = QtWidgets.QProgressBar()
@@ -107,7 +121,9 @@ class ShareHistoryItem(HistoryItem):
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.setStyleSheet(
+ self.common.css["downloads_uploads_progress_bar"]
+ )
self.progress_bar.total_bytes = total_bytes
# Layout
@@ -124,8 +140,9 @@ class ShareHistoryItem(HistoryItem):
self.progress_bar.setValue(downloaded_bytes)
if downloaded_bytes == self.progress_bar.total_bytes:
- pb_fmt = strings._('gui_all_modes_progress_complete').format(
- self.common.format_seconds(time.time() - self.started))
+ pb_fmt = strings._("gui_all_modes_progress_complete").format(
+ self.common.format_seconds(time.time() - self.started)
+ )
# Change the label
self.label.setText(self.get_finished_label_text(self.started_dt))
@@ -137,24 +154,26 @@ class ShareHistoryItem(HistoryItem):
# 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_all_modes_progress_starting').format(
- self.common.human_readable_filesize(downloaded_bytes))
+ pb_fmt = strings._("gui_all_modes_progress_starting").format(
+ self.common.human_readable_filesize(downloaded_bytes)
+ )
else:
- pb_fmt = strings._('gui_all_modes_progress_eta').format(
+ pb_fmt = strings._("gui_all_modes_progress_eta").format(
self.common.human_readable_filesize(downloaded_bytes),
- self.estimated_time_remaining)
+ self.estimated_time_remaining,
+ )
self.progress_bar.setFormat(pb_fmt)
def cancel(self):
- self.progress_bar.setFormat(strings._('gui_canceled'))
+ self.progress_bar.setFormat(strings._("gui_canceled"))
self.status = HistoryItem.STATUS_CANCELED
@property
def estimated_time_remaining(self):
- return self.common.estimated_time_remaining(self.downloaded_bytes,
- self.total_bytes,
- self.started)
+ return self.common.estimated_time_remaining(
+ self.downloaded_bytes, self.total_bytes, self.started
+ )
class ReceiveHistoryItemFile(QtWidgets.QWidget):
@@ -162,7 +181,9 @@ class ReceiveHistoryItemFile(QtWidgets.QWidget):
super(ReceiveHistoryItemFile, self).__init__()
self.common = common
- self.common.log('ReceiveHistoryItemFile', '__init__', 'filename: {}'.format(filename))
+ self.common.log(
+ "ReceiveHistoryItemFile", "__init__", "filename: {}".format(filename)
+ )
self.filename = filename
self.dir = None
@@ -174,11 +195,13 @@ class ReceiveHistoryItemFile(QtWidgets.QWidget):
# File size label
self.filesize_label = QtWidgets.QLabel()
- self.filesize_label.setStyleSheet(self.common.css['receive_file_size'])
+ 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_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)
@@ -213,29 +236,37 @@ class ReceiveHistoryItemFile(QtWidgets.QWidget):
"""
Open the downloads folder, with the file selected, in a cross-platform manner
"""
- self.common.log('ReceiveHistoryItemFile', 'open_folder')
+ self.common.log("ReceiveHistoryItemFile", "open_folder")
if not self.dir:
- self.common.log('ReceiveHistoryItemFile', 'open_folder', "dir has not been set yet, can't open folder")
+ self.common.log(
+ "ReceiveHistoryItemFile",
+ "open_folder",
+ "dir has not been set yet, can't open folder",
+ )
return
abs_filename = os.path.join(self.dir, self.filename)
# Linux
- if self.common.platform == 'Linux' or self.common.platform == 'BSD':
+ if self.common.platform == "Linux" or self.common.platform == "BSD":
try:
# If nautilus is available, open it
- subprocess.Popen(['nautilus', abs_filename])
+ subprocess.Popen(["nautilus", abs_filename])
except:
- Alert(self.common, strings._('gui_open_folder_error_nautilus').format(abs_filename))
+ Alert(
+ self.common,
+ strings._("gui_open_folder_error_nautilus").format(abs_filename),
+ )
# macOS
- elif self.common.platform == 'Darwin':
- subprocess.call(['open', '-R', abs_filename])
+ elif self.common.platform == "Darwin":
+ subprocess.call(["open", "-R", abs_filename])
# Windows
- elif self.common.platform == 'Windows':
- subprocess.Popen(['explorer', '/select,{}'.format(abs_filename)])
+ elif self.common.platform == "Windows":
+ subprocess.Popen(["explorer", "/select,{}".format(abs_filename)])
+
class ReceiveHistoryItem(HistoryItem):
def __init__(self, common, id, content_length):
@@ -247,7 +278,11 @@ class ReceiveHistoryItem(HistoryItem):
self.status = HistoryItem.STATUS_STARTED
# Label
- self.label = QtWidgets.QLabel(strings._('gui_all_modes_transfer_started').format(self.started.strftime("%b %d, %I:%M%p")))
+ self.label = QtWidgets.QLabel(
+ strings._("gui_all_modes_transfer_started").format(
+ self.started.strftime("%b %d, %I:%M%p")
+ )
+ )
# Progress bar
self.progress_bar = QtWidgets.QProgressBar()
@@ -256,13 +291,15 @@ class ReceiveHistoryItem(HistoryItem):
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'])
+ 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.setStyleSheet(self.common.css["receive_file"])
files_widget.setLayout(self.files_layout)
# Layout
@@ -281,10 +318,10 @@ class ReceiveHistoryItem(HistoryItem):
Using the progress from Web, update the progress bar and file size labels
for each file
"""
- if data['action'] == 'progress':
+ if data["action"] == "progress":
total_uploaded_bytes = 0
- for filename in data['progress']:
- total_uploaded_bytes += data['progress'][filename]['uploaded_bytes']
+ for filename in data["progress"]:
+ total_uploaded_bytes += data["progress"][filename]["uploaded_bytes"]
# Update the progress bar
self.progress_bar.setMaximum(self.content_length)
@@ -292,35 +329,39 @@ class ReceiveHistoryItem(HistoryItem):
elapsed = datetime.now() - self.started
if elapsed.seconds < 10:
- pb_fmt = strings._('gui_all_modes_progress_starting').format(
- self.common.human_readable_filesize(total_uploaded_bytes))
+ pb_fmt = strings._("gui_all_modes_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_all_modes_progress_eta').format(
+ total_uploaded_bytes, self.content_length, self.started.timestamp()
+ )
+ pb_fmt = strings._("gui_all_modes_progress_eta").format(
self.common.human_readable_filesize(total_uploaded_bytes),
- estimated_time_remaining)
+ estimated_time_remaining,
+ )
# Using list(progress) to avoid "RuntimeError: dictionary changed size during iteration"
- for filename in list(data['progress']):
+ for filename in list(data["progress"]):
# Add a new file if needed
if filename not in self.files:
self.files[filename] = ReceiveHistoryItemFile(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'])
+ 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"] == "rename":
+ self.files[data["old_filename"]].rename(data["new_filename"])
+ self.files[data["new_filename"]] = self.files.pop(data["old_filename"])
- elif data['action'] == 'set_dir':
- self.files[data['filename']].set_dir(data['dir'])
+ elif data["action"] == "set_dir":
+ self.files[data["filename"]].set_dir(data["dir"])
- elif data['action'] == 'finished':
+ elif data["action"] == "finished":
# Change the status
self.status = HistoryItem.STATUS_FINISHED
@@ -330,7 +371,7 @@ class ReceiveHistoryItem(HistoryItem):
# Change the label
self.label.setText(self.get_finished_label_text(self.started))
- elif data['action'] == 'canceled':
+ elif data["action"] == "canceled":
# Change the status
self.status = HistoryItem.STATUS_CANCELED
@@ -341,10 +382,128 @@ class ReceiveHistoryItem(HistoryItem):
self.label.setText(self.get_canceled_label_text(self.started))
+class IndividualFileHistoryItem(HistoryItem):
+ """
+ Individual file history item, for share mode viewing of individual files
+ """
+
+ def __init__(self, common, data, path):
+ super(IndividualFileHistoryItem, self).__init__()
+ self.status = HistoryItem.STATUS_STARTED
+ self.common = common
+
+ self.id = id
+ self.path = path
+ self.total_bytes = 0
+ self.downloaded_bytes = 0
+ self.started = time.time()
+ self.started_dt = datetime.fromtimestamp(self.started)
+ self.status = HistoryItem.STATUS_STARTED
+
+ self.directory_listing = "directory_listing" in data
+
+ # Labels
+ self.timestamp_label = QtWidgets.QLabel(
+ self.started_dt.strftime("%b %d, %I:%M%p")
+ )
+ self.timestamp_label.setStyleSheet(
+ self.common.css["history_individual_file_timestamp_label"]
+ )
+ self.path_label = QtWidgets.QLabel("{}".format(self.path))
+ self.status_code_label = QtWidgets.QLabel()
+
+ # 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.setValue(0)
+ self.progress_bar.setStyleSheet(
+ self.common.css["downloads_uploads_progress_bar"]
+ )
+
+ # Text layout
+ labels_layout = QtWidgets.QHBoxLayout()
+ labels_layout.addWidget(self.timestamp_label)
+ labels_layout.addWidget(self.path_label)
+ labels_layout.addWidget(self.status_code_label)
+ labels_layout.addStretch()
+
+ # Layout
+ layout = QtWidgets.QVBoxLayout()
+ layout.addLayout(labels_layout)
+ layout.addWidget(self.progress_bar)
+ self.setLayout(layout)
+
+ # Is a status code already sent?
+ if "status_code" in data:
+ self.status_code_label.setText("{}".format(data["status_code"]))
+ if data["status_code"] >= 200 and data["status_code"] < 300:
+ self.status_code_label.setStyleSheet(
+ self.common.css["history_individual_file_status_code_label_2xx"]
+ )
+ if data["status_code"] >= 400 and data["status_code"] < 500:
+ self.status_code_label.setStyleSheet(
+ self.common.css["history_individual_file_status_code_label_4xx"]
+ )
+ self.status = HistoryItem.STATUS_FINISHED
+ self.progress_bar.hide()
+ return
+
+ else:
+ self.total_bytes = data["filesize"]
+ self.progress_bar.setMinimum(0)
+ self.progress_bar.setMaximum(data["filesize"])
+ self.progress_bar.total_bytes = data["filesize"]
+
+ # 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:
+ self.status_code_label.setText("200")
+ self.status_code_label.setStyleSheet(
+ self.common.css["history_individual_file_status_code_label_2xx"]
+ )
+ self.progress_bar.hide()
+ self.status = HistoryItem.STATUS_FINISHED
+
+ 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_all_modes_progress_starting").format(
+ self.common.human_readable_filesize(downloaded_bytes)
+ )
+ else:
+ pb_fmt = strings._("gui_all_modes_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"))
+ self.status = HistoryItem.STATUS_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
@@ -404,45 +563,53 @@ class HistoryItemList(QtWidgets.QScrollArea):
Reset all items, emptying the list. Override this method.
"""
for key, item in self.items.copy().items():
- if item.status != HistoryItem.STATUS_STARTED:
- self.items_layout.removeWidget(item)
- item.close()
- del self.items[key]
+ self.items_layout.removeWidget(item)
+ item.close()
+ del self.items[key]
+
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):
+
+ def __init__(self, common, empty_image, empty_text, header_text, mode=""):
super(History, self).__init__()
self.common = common
+ self.mode = mode
self.setMinimumWidth(350)
# In progress and completed counters
self.in_progress_count = 0
self.completed_count = 0
+ self.requests_count = 0
- # In progress and completed labels
+ # In progress, completed, and requests labels
self.in_progress_label = QtWidgets.QLabel()
- self.in_progress_label.setStyleSheet(self.common.css['mode_info_label'])
+ 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'])
+ self.completed_label.setStyleSheet(self.common.css["mode_info_label"])
+ self.requests_label = QtWidgets.QLabel()
+ self.requests_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_all_modes_clear_history'))
- clear_button.setStyleSheet(self.common.css['downloads_uploads_clear'])
- clear_button.setFlat(True)
- clear_button.clicked.connect(self.reset)
+ self.header_label.setStyleSheet(self.common.css["downloads_uploads_label"])
+ self.clear_button = QtWidgets.QPushButton(
+ strings._("gui_all_modes_clear_history")
+ )
+ self.clear_button.setStyleSheet(self.common.css["downloads_uploads_clear"])
+ self.clear_button.setFlat(True)
+ self.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)
+ header_layout.addWidget(self.requests_label)
+ header_layout.addWidget(self.clear_button)
# When there are no items
self.empty_image = QtWidgets.QLabel()
@@ -450,14 +617,14 @@ class History(QtWidgets.QWidget):
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'])
+ 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.setStyleSheet(self.common.css["downloads_uploads_empty"])
self.empty.setLayout(empty_layout)
# When there are items
@@ -482,7 +649,7 @@ class History(QtWidgets.QWidget):
"""
Add a new item.
"""
- self.common.log('History', 'add', 'id: {}, item: {}'.format(id, item))
+ self.common.log("History", "add", "id: {}, item: {}".format(id, item))
# Hide empty, show not empty
self.empty.hide()
@@ -520,27 +687,56 @@ class History(QtWidgets.QWidget):
self.completed_count = 0
self.update_completed()
+ # Reset web requests counter
+ self.requests_count = 0
+ self.update_requests()
+
def update_completed(self):
"""
Update the 'completed' widget.
"""
if self.completed_count == 0:
- image = self.common.get_resource_path('images/share_completed_none.png')
+ image = self.common.get_resource_path("images/history_completed_none.png")
else:
- image = self.common.get_resource_path('images/share_completed.png')
- self.completed_label.setText('<img src="{0:s}" /> {1:d}'.format(image, self.completed_count))
- self.completed_label.setToolTip(strings._('history_completed_tooltip').format(self.completed_count))
+ image = self.common.get_resource_path("images/history_completed.png")
+ self.completed_label.setText(
+ '<img src="{0:s}" /> {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')
+ image = self.common.get_resource_path("images/history_in_progress_none.png")
else:
- image = self.common.get_resource_path('images/share_in_progress.png')
- self.in_progress_label.setText('<img src="{0:s}" /> {1:d}'.format(image, self.in_progress_count))
- self.in_progress_label.setToolTip(strings._('history_in_progress_tooltip').format(self.in_progress_count))
+ image = self.common.get_resource_path("images/history_in_progress.png")
+
+ self.in_progress_label.setText(
+ '<img src="{0:s}" /> {1:d}'.format(image, self.in_progress_count)
+ )
+ self.in_progress_label.setToolTip(
+ strings._("history_in_progress_tooltip").format(self.in_progress_count)
+ )
+
+ def update_requests(self):
+ """
+ Update the 'web requests' widget.
+ """
+ if self.requests_count == 0:
+ image = self.common.get_resource_path("images/history_requests_none.png")
+ else:
+ image = self.common.get_resource_path("images/history_requests.png")
+
+ self.requests_label.setText(
+ '<img src="{0:s}" /> {1:d}'.format(image, self.requests_count)
+ )
+ self.requests_label.setToolTip(
+ strings._("history_requests_tooltip").format(self.requests_count)
+ )
class ToggleHistory(QtWidgets.QPushButton):
@@ -548,6 +744,7 @@ 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
@@ -567,13 +764,15 @@ class ToggleHistory(QtWidgets.QPushButton):
# 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.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.
+ only increment the counter if History is hidden.
"""
if increment and not self.history_widget.isVisible():
self.indicator_count += 1
@@ -584,14 +783,16 @@ class ToggleHistory(QtWidgets.QPushButton):
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.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')
+ self.common.log("ToggleHistory", "toggle_clicked")
if self.history_widget.isVisible():
self.history_widget.hide()
diff --git a/onionshare_gui/mode/receive_mode/__init__.py b/onionshare_gui/mode/receive_mode/__init__.py
index 4c0b49ba..a0507949 100644
--- a/onionshare_gui/mode/receive_mode/__init__.py
+++ b/onionshare_gui/mode/receive_mode/__init__.py
@@ -25,19 +25,21 @@ from onionshare.web import Web
from ..history import History, ToggleHistory, ReceiveHistoryItem
from .. import Mode
+
class ReceiveMode(Mode):
"""
Parts of the main window UI for receiving files.
"""
+
def init(self):
"""
Custom initialization for ReceiveMode.
"""
# Create the Web object
- self.web = Web(self.common, True, 'receive')
+ self.web = Web(self.common, True, "receive")
# Server status
- self.server_status.set_mode('receive')
+ self.server_status.set_mode("receive")
self.server_status.server_started_finished.connect(self.update_primary_action)
self.server_status.server_stopped.connect(self.update_primary_action)
self.server_status.server_canceled.connect(self.update_primary_action)
@@ -49,21 +51,31 @@ class ReceiveMode(Mode):
# Upload history
self.history = History(
self.common,
- QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/receive_icon_transparent.png'))),
- strings._('gui_receive_mode_no_files'),
- strings._('gui_all_modes_history')
+ QtGui.QPixmap.fromImage(
+ QtGui.QImage(
+ self.common.get_resource_path("images/receive_icon_transparent.png")
+ )
+ ),
+ strings._("gui_receive_mode_no_files"),
+ strings._("gui_all_modes_history"),
)
self.history.hide()
# Toggle history
self.toggle_history = ToggleHistory(
- self.common, self, self.history,
- QtGui.QIcon(self.common.get_resource_path('images/receive_icon_toggle.png')),
- QtGui.QIcon(self.common.get_resource_path('images/receive_icon_toggle_selected.png'))
+ self.common,
+ self,
+ self.history,
+ QtGui.QIcon(
+ self.common.get_resource_path("images/receive_icon_toggle.png")
+ ),
+ QtGui.QIcon(
+ self.common.get_resource_path("images/receive_icon_toggle_selected.png")
+ ),
)
# Receive mode warning
- receive_warning = QtWidgets.QLabel(strings._('gui_receive_mode_warning'))
+ receive_warning = QtWidgets.QLabel(strings._("gui_receive_mode_warning"))
receive_warning.setMinimumHeight(80)
receive_warning.setWordWrap(True)
@@ -90,20 +102,25 @@ class ReceiveMode(Mode):
"""
Return the string to put on the stop server button, if there's an auto-stop timer
"""
- return strings._('gui_receive_stop_server_autostop_timer')
+ return strings._("gui_receive_stop_server_autostop_timer")
def autostop_timer_finished_should_stop_server(self):
"""
The auto-stop timer expired, should we stop the server? Returns a bool
"""
# If there were no attempts to upload files, or all uploads are done, we can stop
- if self.web.receive_mode.upload_count == 0 or not self.web.receive_mode.uploads_in_progress:
+ if (
+ self.web.receive_mode.cur_history_id == 0
+ or not self.web.receive_mode.uploads_in_progress
+ ):
self.server_status.stop_server()
- self.server_status_label.setText(strings._('close_on_autostop_timer'))
+ self.server_status_label.setText(strings._("close_on_autostop_timer"))
return True
# An upload is probably still running - hold off on stopping the share, but block new shares.
else:
- self.server_status_label.setText(strings._('gui_receive_mode_autostop_timer_waiting'))
+ self.server_status_label.setText(
+ strings._("gui_receive_mode_autostop_timer_waiting")
+ )
self.web.receive_mode.can_upload = False
return False
@@ -112,8 +129,8 @@ class ReceiveMode(Mode):
Starting the server.
"""
# Reset web counters
- self.web.receive_mode.upload_count = 0
- self.web.error404_count = 0
+ self.web.receive_mode.cur_history_id = 0
+ self.web.reset_invalid_passwords()
# Hide and reset the uploads if we have previously shared
self.reset_info_counters()
@@ -136,56 +153,68 @@ class ReceiveMode(Mode):
"""
Handle REQUEST_LOAD event.
"""
- self.system_tray.showMessage(strings._('systray_page_loaded_title'), strings._('systray_page_loaded_message'))
+ self.system_tray.showMessage(
+ strings._("systray_page_loaded_title"),
+ strings._("systray_page_loaded_message"),
+ )
def handle_request_started(self, event):
"""
Handle REQUEST_STARTED event.
"""
- item = ReceiveHistoryItem(self.common, event["data"]["id"], event["data"]["content_length"])
+ item = ReceiveHistoryItem(
+ 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_receive_started_title'), strings._('systray_receive_started_message'))
+ self.system_tray.showMessage(
+ strings._("systray_receive_started_title"),
+ strings._("systray_receive_started_message"),
+ )
def handle_request_progress(self, event):
"""
Handle REQUEST_PROGRESS event.
"""
- self.history.update(event["data"]["id"], {
- 'action': 'progress',
- 'progress': event["data"]["progress"]
- })
+ self.history.update(
+ event["data"]["id"],
+ {"action": "progress", "progress": event["data"]["progress"]},
+ )
def handle_request_upload_file_renamed(self, event):
"""
Handle REQUEST_UPLOAD_FILE_RENAMED event.
"""
- self.history.update(event["data"]["id"], {
- 'action': 'rename',
- 'old_filename': event["data"]["old_filename"],
- 'new_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_set_dir(self, event):
"""
Handle REQUEST_UPLOAD_SET_DIR event.
"""
- self.history.update(event["data"]["id"], {
- 'action': 'set_dir',
- 'filename': event["data"]["filename"],
- 'dir': event["data"]["dir"]
- })
+ self.history.update(
+ event["data"]["id"],
+ {
+ "action": "set_dir",
+ "filename": event["data"]["filename"],
+ "dir": event["data"]["dir"],
+ },
+ )
def handle_request_upload_finished(self, event):
"""
Handle REQUEST_UPLOAD_FINISHED event.
"""
- self.history.update(event["data"]["id"], {
- 'action': 'finished'
- })
+ self.history.update(event["data"]["id"], {"action": "finished"})
self.history.completed_count += 1
self.history.in_progress_count -= 1
self.history.update_completed()
@@ -195,9 +224,7 @@ class ReceiveMode(Mode):
"""
Handle REQUEST_UPLOAD_CANCELED event.
"""
- self.history.update(event["data"]["id"], {
- 'action': 'canceled'
- })
+ self.history.update(event["data"]["id"], {"action": "canceled"})
self.history.in_progress_count -= 1
self.history.update_in_progress()
@@ -212,6 +239,8 @@ class ReceiveMode(Mode):
Set the info counters back to zero.
"""
self.history.reset()
+ self.toggle_history.indicator_count = 0
+ self.toggle_history.update_indicator()
def update_primary_action(self):
- self.common.log('ReceiveMode', 'update_primary_action')
+ self.common.log("ReceiveMode", "update_primary_action")
diff --git a/onionshare_gui/mode/share_mode/__init__.py b/onionshare_gui/mode/share_mode/__init__.py
index 6cb50b2b..d0cc6a04 100644
--- a/onionshare_gui/mode/share_mode/__init__.py
+++ b/onionshare_gui/mode/share_mode/__init__.py
@@ -25,7 +25,7 @@ from onionshare.onion import *
from onionshare.common import Common
from onionshare.web import Web
-from .file_selection import FileSelection
+from ..file_selection import FileSelection
from .threads import CompressThread
from .. import Mode
from ..history import History, ToggleHistory, ShareHistoryItem
@@ -36,6 +36,7 @@ class ShareMode(Mode):
"""
Parts of the main window UI for sharing files.
"""
+
def init(self):
"""
Custom initialization for ReceiveMode.
@@ -44,7 +45,7 @@ class ShareMode(Mode):
self.compress_thread = None
# Create the Web object
- self.web = Web(self.common, True, 'share')
+ self.web = Web(self.common, True, "share")
# File selection
self.file_selection = FileSelection(self.common, self)
@@ -53,7 +54,7 @@ class ShareMode(Mode):
self.file_selection.file_list.add_file(filename)
# Server status
- self.server_status.set_mode('share', self.file_selection)
+ self.server_status.set_mode("share", self.file_selection)
self.server_status.server_started.connect(self.file_selection.server_started)
self.server_status.server_stopped.connect(self.file_selection.server_stopped)
self.server_status.server_stopped.connect(self.update_primary_action)
@@ -68,15 +69,19 @@ class ShareMode(Mode):
# Filesize warning
self.filesize_warning = QtWidgets.QLabel()
self.filesize_warning.setWordWrap(True)
- self.filesize_warning.setStyleSheet(self.common.css['share_filesize_warning'])
+ self.filesize_warning.setStyleSheet(self.common.css["share_filesize_warning"])
self.filesize_warning.hide()
# Download history
self.history = History(
self.common,
- QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/share_icon_transparent.png'))),
- strings._('gui_share_mode_no_files'),
- strings._('gui_all_modes_history')
+ QtGui.QPixmap.fromImage(
+ QtGui.QImage(
+ self.common.get_resource_path("images/share_icon_transparent.png")
+ )
+ ),
+ strings._("gui_share_mode_no_files"),
+ strings._("gui_all_modes_history"),
)
self.history.hide()
@@ -86,9 +91,13 @@ class ShareMode(Mode):
# Toggle history
self.toggle_history = ToggleHistory(
- self.common, self, self.history,
- QtGui.QIcon(self.common.get_resource_path('images/share_icon_toggle.png')),
- QtGui.QIcon(self.common.get_resource_path('images/share_icon_toggle_selected.png'))
+ self.common,
+ self,
+ self.history,
+ QtGui.QIcon(self.common.get_resource_path("images/share_icon_toggle.png")),
+ QtGui.QIcon(
+ self.common.get_resource_path("images/share_icon_toggle_selected.png")
+ ),
)
# Top bar
@@ -125,20 +134,22 @@ class ShareMode(Mode):
"""
Return the string to put on the stop server button, if there's an auto-stop timer
"""
- return strings._('gui_share_stop_server_autostop_timer')
+ return strings._("gui_share_stop_server_autostop_timer")
def autostop_timer_finished_should_stop_server(self):
"""
The auto-stop timer expired, should we stop the server? Returns a bool
"""
# If there were no attempts to download the share, or all downloads are done, we can stop
- if self.web.share_mode.download_count == 0 or self.web.done:
+ if self.web.share_mode.cur_history_id == 0 or self.web.done:
self.server_status.stop_server()
- self.server_status_label.setText(strings._('close_on_autostop_timer'))
+ self.server_status_label.setText(strings._("close_on_autostop_timer"))
return True
# A download is probably still running - hold off on stopping the share
else:
- self.server_status_label.setText(strings._('gui_share_mode_autostop_timer_waiting'))
+ self.server_status_label.setText(
+ strings._("gui_share_mode_autostop_timer_waiting")
+ )
return False
def start_server_custom(self):
@@ -146,8 +157,8 @@ class ShareMode(Mode):
Starting the server.
"""
# Reset web counters
- self.web.share_mode.download_count = 0
- self.web.error404_count = 0
+ self.web.share_mode.cur_history_id = 0
+ self.web.reset_invalid_passwords()
# Hide and reset the downloads if we have previously shared
self.reset_info_counters()
@@ -162,7 +173,9 @@ class ShareMode(Mode):
for index in range(self.file_selection.file_list.count()):
self.filenames.append(self.file_selection.file_list.item(index).filename)
- self._zip_progress_bar.total_files_size = ShareMode._compute_total_size(self.filenames)
+ self._zip_progress_bar.total_files_size = ShareMode._compute_total_size(
+ self.filenames
+ )
self.status_bar.insertWidget(0, self._zip_progress_bar)
# prepare the files for sending in a new thread
@@ -216,7 +229,7 @@ class ShareMode(Mode):
Stop the compression thread on cancel
"""
if self.compress_thread:
- self.common.log('ShareMode', 'cancel_server: quitting compress thread')
+ self.common.log("ShareMode", "cancel_server: quitting compress thread")
self.compress_thread.quit()
def handle_tor_broke_custom(self):
@@ -225,12 +238,6 @@ class ShareMode(Mode):
"""
self.primary_action.hide()
- def handle_request_load(self, event):
- """
- Handle REQUEST_LOAD event.
- """
- self.system_tray.showMessage(strings._('systray_page_loaded_title'), strings._('systray_page_loaded_message'))
-
def handle_request_started(self, event):
"""
Handle REQUEST_STARTED event.
@@ -246,7 +253,10 @@ class ShareMode(Mode):
self.history.in_progress_count += 1
self.history.update_in_progress()
- self.system_tray.showMessage(strings._('systray_share_started_title'), strings._('systray_share_started_message'))
+ self.system_tray.showMessage(
+ strings._("systray_share_started_title"),
+ strings._("systray_share_started_message"),
+ )
def handle_request_progress(self, event):
"""
@@ -256,7 +266,10 @@ class ShareMode(Mode):
# Is the download complete?
if event["data"]["bytes"] == self.web.share_mode.filesize:
- self.system_tray.showMessage(strings._('systray_share_completed_title'), strings._('systray_share_completed_message'))
+ self.system_tray.showMessage(
+ strings._("systray_share_completed_title"),
+ strings._("systray_share_completed_message"),
+ )
# Update completed and in progress labels
self.history.completed_count += 1
@@ -265,10 +278,10 @@ class ShareMode(Mode):
self.history.update_in_progress()
# Close on finish?
- if self.common.settings.get('close_after_first_download'):
+ if self.common.settings.get("close_after_first_download"):
self.server_status.stop_server()
self.status_bar.clearMessage()
- self.server_status_label.setText(strings._('closing_automatically'))
+ self.server_status_label.setText(strings._("closing_automatically"))
else:
if self.server_status.status == self.server_status.STATUS_STOPPED:
self.history.cancel(event["data"]["id"])
@@ -284,7 +297,10 @@ class ShareMode(Mode):
# Update in progress count
self.history.in_progress_count -= 1
self.history.update_in_progress()
- self.system_tray.showMessage(strings._('systray_share_canceled_title'), strings._('systray_share_canceled_message'))
+ self.system_tray.showMessage(
+ strings._("systray_share_canceled_title"),
+ strings._("systray_share_canceled_message"),
+ )
def on_reload_settings(self):
"""
@@ -296,7 +312,7 @@ class ShareMode(Mode):
self.info_label.show()
def update_primary_action(self):
- self.common.log('ShareMode', 'update_primary_action')
+ self.common.log("ShareMode", "update_primary_action")
# Show or hide primary action layout
file_count = self.file_selection.file_list.count()
@@ -312,9 +328,15 @@ 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').format(file_count, total_size_readable))
+ self.info_label.setText(
+ strings._("gui_file_info").format(file_count, total_size_readable)
+ )
else:
- self.info_label.setText(strings._('gui_file_info_single').format(file_count, total_size_readable))
+ self.info_label.setText(
+ strings._("gui_file_info_single").format(
+ file_count, total_size_readable
+ )
+ )
else:
self.primary_action.hide()
@@ -325,6 +347,8 @@ class ShareMode(Mode):
Set the info counters back to zero.
"""
self.history.reset()
+ self.toggle_history.indicator_count = 0
+ self.toggle_history.update_indicator()
@staticmethod
def _compute_total_size(filenames):
@@ -347,8 +371,8 @@ class ZipProgressBar(QtWidgets.QProgressBar):
self.setMaximumHeight(20)
self.setMinimumWidth(200)
self.setValue(0)
- self.setFormat(strings._('zip_progress_bar_format'))
- self.setStyleSheet(self.common.css['share_zip_progess_bar'])
+ self.setFormat(strings._("zip_progress_bar_format"))
+ self.setStyleSheet(self.common.css["share_zip_progess_bar"])
self._total_files_size = total_files_size
self._processed_size = 0
diff --git a/onionshare_gui/mode/share_mode/threads.py b/onionshare_gui/mode/share_mode/threads.py
index 24e2c242..414c7be1 100644
--- a/onionshare_gui/mode/share_mode/threads.py
+++ b/onionshare_gui/mode/share_mode/threads.py
@@ -24,13 +24,14 @@ class CompressThread(QtCore.QThread):
"""
Compresses files to be shared
"""
+
success = QtCore.pyqtSignal()
error = QtCore.pyqtSignal(str)
def __init__(self, mode):
super(CompressThread, self).__init__()
self.mode = mode
- self.mode.common.log('CompressThread', '__init__')
+ self.mode.common.log("CompressThread", "__init__")
# prepare files to share
def set_processed_size(self, x):
@@ -38,21 +39,21 @@ class CompressThread(QtCore.QThread):
self.mode._zip_progress_bar.update_processed_size_signal.emit(x)
def run(self):
- self.mode.common.log('CompressThread', 'run')
+ self.mode.common.log("CompressThread", "run")
try:
- if self.mode.web.share_mode.set_file_info(self.mode.filenames, processed_size_callback=self.set_processed_size):
- self.success.emit()
- else:
- # Cancelled
- pass
-
- self.mode.app.cleanup_filenames += self.mode.web.share_mode.cleanup_filenames
+ self.mode.web.share_mode.set_file_info(
+ self.mode.filenames, processed_size_callback=self.set_processed_size
+ )
+ self.success.emit()
+ self.mode.app.cleanup_filenames += (
+ self.mode.web.share_mode.cleanup_filenames
+ )
except OSError as e:
self.error.emit(e.strerror)
def cancel(self):
- self.mode.common.log('CompressThread', 'cancel')
+ self.mode.common.log("CompressThread", "cancel")
# Let the Web and ZipWriter objects know that we're canceling compression early
self.mode.web.cancel_compression = True
diff --git a/onionshare_gui/mode/website_mode/__init__.py b/onionshare_gui/mode/website_mode/__init__.py
new file mode 100644
index 00000000..8cd2eca6
--- /dev/null
+++ b/onionshare_gui/mode/website_mode/__init__.py
@@ -0,0 +1,266 @@
+# -*- coding: utf-8 -*-
+"""
+OnionShare | https://onionshare.org/
+
+Copyright (C) 2014-2018 Micah Lee <micah@micahflee.com>
+
+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 <http://www.gnu.org/licenses/>.
+"""
+import os
+import random
+import string
+
+from PyQt5 import QtCore, QtWidgets, QtGui
+
+from onionshare import strings
+from onionshare.onion import *
+from onionshare.common import Common
+from onionshare.web import Web
+
+from ..file_selection import FileSelection
+from .. import Mode
+from ..history import History, ToggleHistory
+from ...widgets import Alert
+
+
+class WebsiteMode(Mode):
+ """
+ Parts of the main window UI for sharing files.
+ """
+
+ success = QtCore.pyqtSignal()
+ error = QtCore.pyqtSignal(str)
+
+ def init(self):
+ """
+ Custom initialization for ReceiveMode.
+ """
+ # Create the Web object
+ self.web = Web(self.common, True, "website")
+
+ # File selection
+ self.file_selection = FileSelection(self.common, self)
+ if self.filenames:
+ for filename in self.filenames:
+ self.file_selection.file_list.add_file(filename)
+
+ # Server status
+ self.server_status.set_mode("website", self.file_selection)
+ self.server_status.server_started.connect(self.file_selection.server_started)
+ self.server_status.server_stopped.connect(self.file_selection.server_stopped)
+ self.server_status.server_stopped.connect(self.update_primary_action)
+ self.server_status.server_canceled.connect(self.file_selection.server_stopped)
+ self.server_status.server_canceled.connect(self.update_primary_action)
+ self.file_selection.file_list.files_updated.connect(self.server_status.update)
+ self.file_selection.file_list.files_updated.connect(self.update_primary_action)
+ # Tell server_status about web, then update
+ self.server_status.web = self.web
+ self.server_status.update()
+
+ # Filesize warning
+ self.filesize_warning = QtWidgets.QLabel()
+ self.filesize_warning.setWordWrap(True)
+ self.filesize_warning.setStyleSheet(self.common.css["share_filesize_warning"])
+ self.filesize_warning.hide()
+
+ # Download history
+ self.history = History(
+ self.common,
+ QtGui.QPixmap.fromImage(
+ QtGui.QImage(
+ self.common.get_resource_path("images/share_icon_transparent.png")
+ )
+ ),
+ strings._("gui_website_mode_no_files"),
+ strings._("gui_all_modes_history"),
+ "website",
+ )
+ self.history.in_progress_label.hide()
+ self.history.completed_label.hide()
+ self.history.hide()
+
+ # Info label
+ self.info_label = QtWidgets.QLabel()
+ self.info_label.hide()
+
+ # Toggle history
+ self.toggle_history = ToggleHistory(
+ self.common,
+ self,
+ self.history,
+ QtGui.QIcon(self.common.get_resource_path("images/share_icon_toggle.png")),
+ QtGui.QIcon(
+ self.common.get_resource_path("images/share_icon_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)
+ self.primary_action.hide()
+ self.update_primary_action()
+
+ # Main layout
+ self.main_layout = QtWidgets.QVBoxLayout()
+ 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)
+
+ # Wrapper layout
+ self.wrapper_layout = QtWidgets.QHBoxLayout()
+ self.wrapper_layout.addLayout(self.main_layout)
+ self.wrapper_layout.addWidget(self.history, stretch=1)
+ self.setLayout(self.wrapper_layout)
+
+ # Always start with focus on file selection
+ self.file_selection.setFocus()
+
+ def get_stop_server_autostop_timer_text(self):
+ """
+ Return the string to put on the stop server button, if there's an auto-stop timer
+ """
+ return strings._("gui_share_stop_server_autostop_timer")
+
+ def autostop_timer_finished_should_stop_server(self):
+ """
+ The auto-stop timer expired, should we stop the server? Returns a bool
+ """
+
+ self.server_status.stop_server()
+ self.server_status_label.setText(strings._("close_on_autostop_timer"))
+ return True
+
+ def start_server_custom(self):
+ """
+ Starting the server.
+ """
+ # Reset web counters
+ self.web.website_mode.visit_count = 0
+ self.web.reset_invalid_passwords()
+
+ # Hide and reset the downloads if we have previously shared
+ self.reset_info_counters()
+
+ def start_server_step2_custom(self):
+ """
+ Step 2 in starting the server. Zipping up files.
+ """
+ self.filenames = []
+ for index in range(self.file_selection.file_list.count()):
+ self.filenames.append(self.file_selection.file_list.item(index).filename)
+
+ # Continue
+ self.starting_server_step3.emit()
+ self.start_server_finished.emit()
+
+ def start_server_step3_custom(self):
+ """
+ Step 3 in starting the server. Display large filesize
+ warning, if applicable.
+ """
+ self.web.website_mode.set_file_info(self.filenames)
+ self.success.emit()
+
+ def start_server_error_custom(self):
+ """
+ Start server error.
+ """
+ if self._zip_progress_bar is not None:
+ self.status_bar.removeWidget(self._zip_progress_bar)
+ self._zip_progress_bar = None
+
+ def stop_server_custom(self):
+ """
+ Stop server.
+ """
+
+ self.filesize_warning.hide()
+ self.history.completed_count = 0
+ self.file_selection.file_list.adjustSize()
+
+ def cancel_server_custom(self):
+ """
+ Log that the server has been cancelled
+ """
+ self.common.log("WebsiteMode", "cancel_server")
+
+ def handle_tor_broke_custom(self):
+ """
+ Connection to Tor broke.
+ """
+ self.primary_action.hide()
+
+ def on_reload_settings(self):
+ """
+ If there were some files listed for sharing, we should be ok to re-enable
+ the 'Start Sharing' button now.
+ """
+ if self.server_status.file_selection.get_num_files() > 0:
+ self.primary_action.show()
+ self.info_label.show()
+
+ def update_primary_action(self):
+ self.common.log("WebsiteMode", "update_primary_action")
+
+ # Show or hide primary action layout
+ file_count = self.file_selection.file_list.count()
+ if file_count > 0:
+ self.primary_action.show()
+ self.info_label.show()
+
+ # Update the file count in the info label
+ total_size_bytes = 0
+ for index in range(self.file_selection.file_list.count()):
+ item = self.file_selection.file_list.item(index)
+ total_size_bytes += item.size_bytes
+ total_size_readable = self.common.human_readable_filesize(total_size_bytes)
+
+ if file_count > 1:
+ self.info_label.setText(
+ strings._("gui_file_info").format(file_count, total_size_readable)
+ )
+ else:
+ self.info_label.setText(
+ strings._("gui_file_info_single").format(
+ file_count, total_size_readable
+ )
+ )
+
+ else:
+ self.primary_action.hide()
+ self.info_label.hide()
+
+ def reset_info_counters(self):
+ """
+ Set the info counters back to zero.
+ """
+ self.history.reset()
+ self.toggle_history.indicator_count = 0
+ self.toggle_history.update_indicator()
+
+ @staticmethod
+ def _compute_total_size(filenames):
+ total_size = 0
+ for filename in filenames:
+ if os.path.isfile(filename):
+ total_size += os.path.getsize(filename)
+ if os.path.isdir(filename):
+ total_size += Common.dir_size(filename)
+ return total_size