diff --git a/onionshare/mode_settings.py b/onionshare/mode_settings.py index ffc32d06..3b14dbe8 100644 --- a/onionshare/mode_settings.py +++ b/onionshare/mode_settings.py @@ -28,12 +28,13 @@ class ModeSettings: is only one TabSettings, and in the GUI there is a separate TabSettings for each tab """ - def __init__(self, common, filename=None): + def __init__(self, common, filename=None, id=None): self.common = common self.default_settings = { "persistent": { "enabled": False, + "mode": None, "private_key": None, "hidservauth": None, "password": None, @@ -52,7 +53,10 @@ class ModeSettings: self._settings = {} self.just_created = False - self.id = self.common.build_password(3) + if id: + self.id = id + else: + self.id = self.common.build_password(3) self.load(filename) @@ -104,7 +108,6 @@ class ModeSettings: if filename: self.filename = filename else: - # Give it a persistent filename self.filename = os.path.join( self.common.build_persistent_dir(), f"{self.id}.json" ) diff --git a/onionshare/settings.py b/onionshare/settings.py index 11227817..f9348a8e 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -112,6 +112,7 @@ class Settings(object): "tor_bridges_use_obfs4": False, "tor_bridges_use_meek_lite_azure": False, "tor_bridges_use_custom_bridges": "", + "persistent_tabs": [], "locale": None, # this gets defined in fill_in_defaults() } self._settings = {} diff --git a/onionshare_gui/main_window.py b/onionshare_gui/main_window.py index e6f5606e..22035b69 100644 --- a/onionshare_gui/main_window.py +++ b/onionshare_gui/main_window.py @@ -120,8 +120,13 @@ class MainWindow(QtWidgets.QMainWindow): # Tabs self.tabs = TabWidget(self.common, self.system_tray, self.status_bar) - # Start with opening the first tab - self.tabs.new_tab_clicked() + # If we have saved persistent tabs, try opening those + if len(self.common.settings.get("persistent_tabs")) > 0: + for mode_settings_id in self.common.settings.get("persistent_tabs"): + self.tabs.load_tab(mode_settings_id) + else: + # Start with opening the first tab + self.tabs.new_tab_clicked() # Layout layout = QtWidgets.QVBoxLayout() diff --git a/onionshare_gui/tab/mode/__init__.py b/onionshare_gui/tab/mode/__init__.py index e6b07da3..7696f79e 100644 --- a/onionshare_gui/tab/mode/__init__.py +++ b/onionshare_gui/tab/mode/__init__.py @@ -47,7 +47,7 @@ class Mode(QtWidgets.QWidget): def __init__(self, tab): super(Mode, self).__init__() self.tab = tab - self.settings = tab.mode_settings + self.settings = tab.settings self.common = tab.common self.qtapp = self.common.gui.qtapp @@ -69,7 +69,7 @@ class Mode(QtWidgets.QWidget): # Mode settings widget self.mode_settings_widget = ModeSettingsWidget( - self.common, self.tab.tab_id, self.settings + self.common, self.tab, self.settings ) self.mode_settings_widget.change_persistent.connect(self.change_persistent) diff --git a/onionshare_gui/tab/mode/mode_settings_widget.py b/onionshare_gui/tab/mode/mode_settings_widget.py index 867c27cf..462fe728 100644 --- a/onionshare_gui/tab/mode/mode_settings_widget.py +++ b/onionshare_gui/tab/mode/mode_settings_widget.py @@ -29,10 +29,10 @@ class ModeSettingsWidget(QtWidgets.QWidget): change_persistent = QtCore.pyqtSignal(int, bool) - def __init__(self, common, tab_id, mode_settings): + def __init__(self, common, tab, mode_settings): super(ModeSettingsWidget, self).__init__() self.common = common - self.tab_id = tab_id + self.tab = tab self.settings = mode_settings # Downstream Mode need to fill in this layout with its settings @@ -41,24 +41,33 @@ class ModeSettingsWidget(QtWidgets.QWidget): # Persistent self.persistent_checkbox = QtWidgets.QCheckBox() self.persistent_checkbox.clicked.connect(self.persistent_checkbox_clicked) - self.persistent_checkbox.setCheckState(QtCore.Qt.Unchecked) self.persistent_checkbox.setText(strings._("mode_settings_persistent_checkbox")) + if self.settings.get("persistent", "enabled"): + self.persistent_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.persistent_checkbox.setCheckState(QtCore.Qt.Unchecked) # Public self.public_checkbox = QtWidgets.QCheckBox() self.public_checkbox.clicked.connect(self.public_checkbox_clicked) - self.public_checkbox.setCheckState(QtCore.Qt.Unchecked) self.public_checkbox.setText(strings._("mode_settings_public_checkbox")) + if self.settings.get("general", "public"): + self.public_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.public_checkbox.setCheckState(QtCore.Qt.Unchecked) # Whether or not to use an auto-start timer self.autostart_timer_checkbox = QtWidgets.QCheckBox() self.autostart_timer_checkbox.clicked.connect( self.autostart_timer_checkbox_clicked ) - self.autostart_timer_checkbox.setCheckState(QtCore.Qt.Unchecked) self.autostart_timer_checkbox.setText( strings._("mode_settings_autostart_timer_checkbox") ) + if self.settings.get("general", "autostart_timer"): + self.autostart_timer_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.autostart_timer_checkbox.setCheckState(QtCore.Qt.Unchecked) # The autostart timer widget self.autostart_timer_widget = QtWidgets.QDateTimeEdit() @@ -85,10 +94,13 @@ class ModeSettingsWidget(QtWidgets.QWidget): self.autostop_timer_checkbox.clicked.connect( self.autostop_timer_checkbox_clicked ) - self.autostop_timer_checkbox.setCheckState(QtCore.Qt.Unchecked) self.autostop_timer_checkbox.setText( strings._("mode_settings_autostop_timer_checkbox") ) + if self.settings.get("general", "autostop_timer"): + self.autostop_timer_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.autostop_timer_checkbox.setCheckState(QtCore.Qt.Unchecked) # The autostop timer widget self.autostop_timer_widget = QtWidgets.QDateTimeEdit() @@ -114,17 +126,23 @@ class ModeSettingsWidget(QtWidgets.QWidget): self.legacy_checkbox = QtWidgets.QCheckBox() self.legacy_checkbox.clicked.connect(self.legacy_checkbox_clicked) self.legacy_checkbox.clicked.connect(self.update_ui) - self.legacy_checkbox.setCheckState(QtCore.Qt.Unchecked) self.legacy_checkbox.setText(strings._("mode_settings_legacy_checkbox")) + if self.settings.get("general", "legacy"): + self.legacy_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.legacy_checkbox.setCheckState(QtCore.Qt.Unchecked) # Client auth self.client_auth_checkbox = QtWidgets.QCheckBox() self.client_auth_checkbox.clicked.connect(self.client_auth_checkbox_clicked) self.client_auth_checkbox.clicked.connect(self.update_ui) - self.client_auth_checkbox.setCheckState(QtCore.Qt.Unchecked) self.client_auth_checkbox.setText( strings._("mode_settings_client_auth_checkbox") ) + if self.settings.get("general", "client_auth"): + self.client_auth_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.client_auth_checkbox.setCheckState(QtCore.Qt.Unchecked) # Toggle advanced settings self.toggle_advanced_button = QtWidgets.QPushButton() @@ -179,8 +197,10 @@ class ModeSettingsWidget(QtWidgets.QWidget): def persistent_checkbox_clicked(self): self.settings.set("persistent", "enabled", self.persistent_checkbox.isChecked()) - - self.change_persistent.emit(self.tab_id, self.persistent_checkbox.isChecked()) + self.settings.set("persistent", "mode", self.tab.mode) + self.change_persistent.emit( + self.tab.tab_id, self.persistent_checkbox.isChecked() + ) def public_checkbox_clicked(self): self.settings.set("general", "public", self.public_checkbox.isChecked()) diff --git a/onionshare_gui/tab/mode/share_mode/__init__.py b/onionshare_gui/tab/mode/share_mode/__init__.py index 7d195e42..8d9b323a 100644 --- a/onionshare_gui/tab/mode/share_mode/__init__.py +++ b/onionshare_gui/tab/mode/share_mode/__init__.py @@ -55,10 +55,14 @@ class ShareMode(Mode): self.autostop_sharing_checkbox.clicked.connect( self.autostop_sharing_checkbox_clicked ) - self.autostop_sharing_checkbox.setCheckState(QtCore.Qt.Checked) self.autostop_sharing_checkbox.setText( strings._("mode_settings_share_autostop_sharing_checkbox") ) + if self.settings.get("share", "autostop_sharing"): + self.autostop_sharing_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.autostop_sharing_checkbox.setCheckState(QtCore.Qt.Unchecked) + self.mode_settings_widget.mode_specific_layout.addWidget( self.autostop_sharing_checkbox ) diff --git a/onionshare_gui/tab/mode/website_mode/__init__.py b/onionshare_gui/tab/mode/website_mode/__init__.py index 4a099488..db8dbf09 100644 --- a/onionshare_gui/tab/mode/website_mode/__init__.py +++ b/onionshare_gui/tab/mode/website_mode/__init__.py @@ -55,10 +55,14 @@ class WebsiteMode(Mode): # Settings self.disable_csp_checkbox = QtWidgets.QCheckBox() self.disable_csp_checkbox.clicked.connect(self.disable_csp_checkbox_clicked) - self.disable_csp_checkbox.setCheckState(QtCore.Qt.Unchecked) self.disable_csp_checkbox.setText( strings._("mode_settings_website_disable_csp_checkbox") ) + if self.settings.get("website", "disable_csp"): + self.disable_csp_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.disable_csp_checkbox.setCheckState(QtCore.Qt.Unchecked) + self.mode_settings_widget.mode_specific_layout.addWidget( self.disable_csp_checkbox ) diff --git a/onionshare_gui/tab/tab.py b/onionshare_gui/tab/tab.py index 2e9f0df2..04e4bf9d 100644 --- a/onionshare_gui/tab/tab.py +++ b/onionshare_gui/tab/tab.py @@ -43,7 +43,15 @@ class Tab(QtWidgets.QWidget): change_icon = QtCore.pyqtSignal(int, str) change_persistent = QtCore.pyqtSignal(int, bool) - def __init__(self, common, tab_id, system_tray, status_bar, filenames=None): + def __init__( + self, + common, + tab_id, + system_tray, + status_bar, + mode_settings=None, + filenames=None, + ): super(Tab, self).__init__() self.common = common self.common.log("Tab", "__init__") @@ -130,8 +138,19 @@ class Tab(QtWidgets.QWidget): ) self.persistent_image_label.setFixedSize(20, 20) - # Settings for this tab - self.mode_settings = ModeSettings(self.common) + if mode_settings: + # Load this tab + self.settings = mode_settings + mode = self.settings.get("persistent", "mode") + if mode == "share": + self.share_mode_clicked() + elif mode == "receive": + self.receive_mode_clicked() + elif mode == "website": + self.website_mode_clicked() + else: + # This is a new tab + self.settings = ModeSettings(self.common) def share_mode_clicked(self): self.common.log("Tab", "share_mode_clicked") @@ -496,7 +515,7 @@ class Tab(QtWidgets.QWidget): if self.mode is None: return True - if self.mode_settings.get("persistent", "enabled"): + if self.settings.get("persistent", "enabled"): dialog_text = strings._("gui_close_tab_warning_persistent_description") else: server_status = self.get_mode().server_status diff --git a/onionshare_gui/tab_widget.py b/onionshare_gui/tab_widget.py index 29dbda15..2d53ea32 100644 --- a/onionshare_gui/tab_widget.py +++ b/onionshare_gui/tab_widget.py @@ -20,6 +20,7 @@ along with this program. If not, see . from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings +from onionshare.mode_settings import ModeSettings from .tab import Tab @@ -86,15 +87,29 @@ class TabWidget(QtWidgets.QTabWidget): self.new_tab_button.raise_() def new_tab_clicked(self): - # Create the tab + # Create a new tab tab = Tab(self.common, self.tab_id, self.system_tray, self.status_bar) + self.add_tab(tab) + + def load_tab(self, mode_settings_id): + # Load the tab's mode settings + mode_settings = ModeSettings(self.common, id=mode_settings_id) + tab = Tab( + self.common, + self.tab_id, + self.system_tray, + self.status_bar, + mode_settings=mode_settings, + ) + self.add_tab(tab) + + def add_tab(self, tab): tab.change_title.connect(self.change_title) tab.change_icon.connect(self.change_icon) tab.change_persistent.connect(self.change_persistent) self.tabs[self.tab_id] = tab self.tab_id += 1 - # Add it index = self.addTab(tab, "New Tab") self.setCurrentIndex(index) @@ -121,6 +136,18 @@ class TabWidget(QtWidgets.QTabWidget): index, QtWidgets.QTabBar.LeftSide, invisible_widget ) + self.save_persistent_tabs() + + def save_persistent_tabs(self): + # Figure out the order of persistent tabs to save in settings + persistent_tabs = [] + for index in range(self.count()): + tab = self.widget(index) + if tab.settings.get("persistent", "enabled"): + persistent_tabs.append(tab.settings.id) + self.common.settings.set("persistent_tabs", persistent_tabs) + self.common.settings.save() + def close_tab(self, index): self.common.log("TabWidget", "close_tab", f"{index}") tab = self.widget(index) @@ -143,6 +170,13 @@ class TabWidget(QtWidgets.QTabWidget): return True return False + def changeEvent(self, event): + # TODO: later when I have internet, figure out the right event for re-ordering tabs + + # If tabs get move + super(TabWidget, self).changeEvent(event) + self.save_persistent_tabs() + def resizeEvent(self, event): # Make sure to move new tab button on each resize super(TabWidget, self).resizeEvent(event)