Refactor SettingsDialog into SettingsTab

This commit is contained in:
Micah Lee 2021-10-20 18:56:37 -07:00
parent 7a45f801d9
commit 55d6ac4e3d
No known key found for this signature in database
GPG key ID: 403C2657CD994F73
4 changed files with 115 additions and 121 deletions

View file

@ -24,8 +24,6 @@ from PySide2 import QtCore, QtWidgets, QtGui
from . import strings from . import strings
from .tor_connection_dialog import TorConnectionDialog from .tor_connection_dialog import TorConnectionDialog
from .tor_settings_dialog import TorSettingsDialog
from .settings_dialog import SettingsDialog
from .widgets import Alert from .widgets import Alert
from .update_checker import UpdateThread from .update_checker import UpdateThread
from .tab_widget import TabWidget from .tab_widget import TabWidget
@ -245,21 +243,22 @@ class MainWindow(QtWidgets.QMainWindow):
def open_tor_settings(self): def open_tor_settings(self):
""" """
Open the TorSettingsDialog. Open the TorSettingsTab
""" """
self.common.log("MainWindow", "open_tor_settings") self.common.log("MainWindow", "open_tor_settings")
d = TorSettingsDialog(self.common) # d = TorSettingsDialog(self.common)
d.settings_saved.connect(self.settings_have_changed) # d.settings_saved.connect(self.settings_have_changed)
d.exec_() # d.exec_()
def open_settings(self): def open_settings(self):
""" """
Open the SettingsDialog. Open the SettingsTab
""" """
self.common.log("MainWindow", "open_settings") self.common.log("MainWindow", "open_settings")
d = SettingsDialog(self.common) self.tabs.open_settings_tab()
d.settings_saved.connect(self.settings_have_changed) # d = SettingsDialog(self.common)
d.exec_() # d.settings_saved.connect(self.settings_have_changed)
# d.exec_()
def settings_have_changed(self): def settings_have_changed(self):
self.common.log("OnionShareGui", "settings_have_changed") self.common.log("OnionShareGui", "settings_have_changed")

View file

@ -19,57 +19,34 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from PySide2 import QtCore, QtWidgets, QtGui from PySide2 import QtCore, QtWidgets, QtGui
from PySide2.QtCore import Slot, Qt
from PySide2.QtGui import QPalette, QColor
import sys import sys
import platform import platform
import datetime import datetime
import re import re
import os import os
from onionshare_cli.settings import Settings from onionshare_cli.settings import Settings
from onionshare_cli.onion import (
Onion,
TorErrorInvalidSetting,
TorErrorAutomatic,
TorErrorSocketPort,
TorErrorSocketFile,
TorErrorMissingPassword,
TorErrorUnreadableCookieFile,
TorErrorAuthError,
TorErrorProtocolError,
BundledTorTimeout,
BundledTorBroken,
TorTooOldEphemeral,
TorTooOldStealth,
PortNotAvailable,
)
from . import strings from . import strings
from .widgets import Alert from .widgets import Alert
from .update_checker import UpdateThread from .update_checker import UpdateThread
from .tor_connection_dialog import TorConnectionDialog
from .gui_common import GuiCommon from .gui_common import GuiCommon
class SettingsDialog(QtWidgets.QDialog): class SettingsTab(QtWidgets.QWidget):
""" """
Settings dialog. Settings dialog.
""" """
settings_saved = QtCore.Signal() settings_saved = QtCore.Signal()
def __init__(self, common): def __init__(self, common, tab_id):
super(SettingsDialog, self).__init__() super(SettingsTab, self).__init__()
self.common = common self.common = common
self.common.log("SettingsTab", "__init__")
self.common.log("SettingsDialog", "__init__")
self.setModal(True)
self.setWindowTitle(strings._("gui_settings_window_title"))
self.setWindowIcon(QtGui.QIcon(GuiCommon.get_resource_path("images/logo.png")))
self.system = platform.system() self.system = platform.system()
self.tab_id = tab_id
# Automatic updates options # Automatic updates options
@ -146,31 +123,26 @@ class SettingsDialog(QtWidgets.QDialog):
# Buttons # Buttons
self.save_button = QtWidgets.QPushButton(strings._("gui_settings_button_save")) self.save_button = QtWidgets.QPushButton(strings._("gui_settings_button_save"))
self.save_button.clicked.connect(self.save_clicked) self.save_button.clicked.connect(self.save_clicked)
self.cancel_button = QtWidgets.QPushButton(
strings._("gui_settings_button_cancel")
)
self.cancel_button.clicked.connect(self.cancel_clicked)
buttons_layout = QtWidgets.QHBoxLayout() buttons_layout = QtWidgets.QHBoxLayout()
buttons_layout.addStretch() buttons_layout.addStretch()
buttons_layout.addWidget(self.save_button) buttons_layout.addWidget(self.save_button)
buttons_layout.addWidget(self.cancel_button)
# Layout # Layout
layout = QtWidgets.QVBoxLayout() layout = QtWidgets.QVBoxLayout()
layout.addStretch()
layout.addWidget(autoupdate_group) layout.addWidget(autoupdate_group)
if autoupdate_group.isVisible(): if autoupdate_group.isVisible():
layout.addSpacing(20) layout.addSpacing(20)
layout.addLayout(language_layout) layout.addLayout(language_layout)
layout.addLayout(theme_layout) layout.addLayout(theme_layout)
layout.addSpacing(20) layout.addSpacing(20)
layout.addStretch()
layout.addWidget(version_label) layout.addWidget(version_label)
layout.addWidget(help_label) layout.addWidget(help_label)
layout.addSpacing(20) layout.addSpacing(20)
layout.addLayout(buttons_layout) layout.addLayout(buttons_layout)
layout.addStretch()
self.setLayout(layout) self.setLayout(layout)
self.cancel_button.setFocus()
self.reload_settings() self.reload_settings()
@ -199,7 +171,7 @@ class SettingsDialog(QtWidgets.QDialog):
""" """
Check for Updates button clicked. Manually force an update check. Check for Updates button clicked. Manually force an update check.
""" """
self.common.log("SettingsDialog", "check_for_updates") self.common.log("SettingsTab", "check_for_updates")
# Disable buttons # Disable buttons
self._disable_buttons() self._disable_buttons()
self.common.gui.qtapp.processEvents() self.common.gui.qtapp.processEvents()
@ -261,7 +233,7 @@ class SettingsDialog(QtWidgets.QDialog):
""" """
Save button clicked. Save current settings to disk. Save button clicked. Save current settings to disk.
""" """
self.common.log("SettingsDialog", "save_clicked") self.common.log("SettingsTab", "save_clicked")
def changed(s1, s2, keys): def changed(s1, s2, keys):
""" """
@ -301,30 +273,12 @@ class SettingsDialog(QtWidgets.QDialog):
self.settings_saved.emit() self.settings_saved.emit()
self.close() self.close()
def cancel_clicked(self):
"""
Cancel button clicked.
"""
self.common.log("SettingsDialog", "cancel_clicked")
if (
not self.common.gui.local_only
and not self.common.gui.onion.is_authenticated()
):
Alert(
self.common,
strings._("gui_tor_connection_canceled"),
QtWidgets.QMessageBox.Warning,
)
sys.exit()
else:
self.close()
def help_clicked(self): def help_clicked(self):
""" """
Help button clicked. Help button clicked.
""" """
self.common.log("SettingsDialog", "help_clicked") self.common.log("SettingsTab", "help_clicked")
SettingsDialog.open_help() SettingsTab.open_help()
@staticmethod @staticmethod
def open_help(): def open_help():
@ -335,7 +289,7 @@ class SettingsDialog(QtWidgets.QDialog):
""" """
Return a Settings object that's full of values from the settings dialog. Return a Settings object that's full of values from the settings dialog.
""" """
self.common.log("SettingsDialog", "settings_from_fields") self.common.log("SettingsTab", "settings_from_fields")
settings = Settings(self.common) settings = Settings(self.common)
settings.load() # To get the last update timestamp settings.load() # To get the last update timestamp
@ -351,7 +305,7 @@ class SettingsDialog(QtWidgets.QDialog):
return settings return settings
def _update_autoupdate_timestamp(self, autoupdate_timestamp): def _update_autoupdate_timestamp(self, autoupdate_timestamp):
self.common.log("SettingsDialog", "_update_autoupdate_timestamp") self.common.log("SettingsTab", "_update_autoupdate_timestamp")
if autoupdate_timestamp: if autoupdate_timestamp:
dt = datetime.datetime.fromtimestamp(autoupdate_timestamp) dt = datetime.datetime.fromtimestamp(autoupdate_timestamp)
@ -363,18 +317,16 @@ class SettingsDialog(QtWidgets.QDialog):
) )
def _disable_buttons(self): def _disable_buttons(self):
self.common.log("SettingsDialog", "_disable_buttons") self.common.log("SettingsTab", "_disable_buttons")
self.check_for_updates_button.setEnabled(False) self.check_for_updates_button.setEnabled(False)
self.save_button.setEnabled(False) self.save_button.setEnabled(False)
self.cancel_button.setEnabled(False)
def _enable_buttons(self): def _enable_buttons(self):
self.common.log("SettingsDialog", "_enable_buttons") self.common.log("SettingsTab", "_enable_buttons")
# We can't check for updates if we're still not connected to Tor # We can't check for updates if we're still not connected to Tor
if not self.common.gui.onion.connected_to_tor: if not self.common.gui.onion.connected_to_tor:
self.check_for_updates_button.setEnabled(False) self.check_for_updates_button.setEnabled(False)
else: else:
self.check_for_updates_button.setEnabled(True) self.check_for_updates_button.setEnabled(True)
self.save_button.setEnabled(True) self.save_button.setEnabled(True)
self.cancel_button.setEnabled(True)

View file

@ -26,6 +26,8 @@ from . import strings
from .tab import Tab from .tab import Tab
from .threads import EventHandlerThread from .threads import EventHandlerThread
from .gui_common import GuiCommon from .gui_common import GuiCommon
from .tor_settings_tab import TorSettingsTab
from .settings_tab import SettingsTab
class TabWidget(QtWidgets.QTabWidget): class TabWidget(QtWidgets.QTabWidget):
@ -116,6 +118,11 @@ class TabWidget(QtWidgets.QTabWidget):
# Active tab was changed # Active tab was changed
tab_id = self.currentIndex() tab_id = self.currentIndex()
self.common.log("TabWidget", "tab_changed", f"Tab was changed to {tab_id}") self.common.log("TabWidget", "tab_changed", f"Tab was changed to {tab_id}")
# If it's Settings or Tor Settings, ignore
if self.is_settings_tab(tab_id):
return
try: try:
mode = self.tabs[tab_id].get_mode() mode = self.tabs[tab_id].get_mode()
if mode: if mode:
@ -160,20 +167,7 @@ class TabWidget(QtWidgets.QTabWidget):
# In macOS, manually create a close button because tabs don't seem to have them otherwise # In macOS, manually create a close button because tabs don't seem to have them otherwise
if self.common.platform == "Darwin": if self.common.platform == "Darwin":
self.macos_create_close_button(tab, index)
def close_tab():
self.tabBar().tabCloseRequested.emit(self.indexOf(tab))
tab.close_button = QtWidgets.QPushButton()
tab.close_button.setFlat(True)
tab.close_button.setFixedWidth(40)
tab.close_button.setIcon(
QtGui.QIcon(GuiCommon.get_resource_path("images/close_tab.png"))
)
tab.close_button.clicked.connect(close_tab)
self.tabBar().setTabButton(
index, QtWidgets.QTabBar.RightSide, tab.close_button
)
tab.init(mode_settings) tab.init(mode_settings)
@ -187,6 +181,25 @@ class TabWidget(QtWidgets.QTabWidget):
# Bring the window to front, in case this is being added by an event # Bring the window to front, in case this is being added by an event
self.bring_to_front.emit() self.bring_to_front.emit()
def open_settings_tab(self):
self.common.log("TabWidget", "open_settings_tab")
# See if a settings tab is already open, and if so switch to it
for index in range(self.count()):
if self.is_settings_tab(index):
self.setCurrentIndex(index)
return
settings_tab = SettingsTab(self.common, self.current_tab_id)
self.tabs[self.current_tab_id] = settings_tab
self.current_tab_id += 1
index = self.addTab(settings_tab, strings._("gui_settings_window_title"))
self.setCurrentIndex(index)
# In macOS, manually create a close button because tabs don't seem to have them otherwise
if self.common.platform == "Darwin":
self.macos_create_close_button(settings_tab, index)
def change_title(self, tab_id, title): def change_title(self, tab_id, title):
shortened_title = title shortened_title = title
if len(shortened_title) > 11: if len(shortened_title) > 11:
@ -224,9 +237,10 @@ class TabWidget(QtWidgets.QTabWidget):
# Figure out the order of persistent tabs to save in settings # Figure out the order of persistent tabs to save in settings
persistent_tabs = [] persistent_tabs = []
for index in range(self.count()): for index in range(self.count()):
tab = self.widget(index) if not self.is_settings_tab(index):
if tab.settings.get("persistent", "enabled"): tab = self.widget(index)
persistent_tabs.append(tab.settings.id) if tab.settings.get("persistent", "enabled"):
persistent_tabs.append(tab.settings.id)
# Only save if tabs have actually moved # Only save if tabs have actually moved
if persistent_tabs != self.common.settings.get("persistent_tabs"): if persistent_tabs != self.common.settings.get("persistent_tabs"):
self.common.settings.set("persistent_tabs", persistent_tabs) self.common.settings.set("persistent_tabs", persistent_tabs)
@ -235,11 +249,8 @@ class TabWidget(QtWidgets.QTabWidget):
def close_tab(self, index): def close_tab(self, index):
self.common.log("TabWidget", "close_tab", f"{index}") self.common.log("TabWidget", "close_tab", f"{index}")
tab = self.widget(index) tab = self.widget(index)
if tab.close_tab():
# If the tab is persistent, delete the settings file from disk
if tab.settings.get("persistent", "enabled"):
tab.settings.delete()
if self.is_settings_tab(index):
# Remove the tab # Remove the tab
self.removeTab(index) self.removeTab(index)
del self.tabs[tab.tab_id] del self.tabs[tab.tab_id]
@ -248,7 +259,21 @@ class TabWidget(QtWidgets.QTabWidget):
if self.count() == 0: if self.count() == 0:
self.new_tab_clicked() self.new_tab_clicked()
self.save_persistent_tabs() else:
if tab.close_tab():
# If the tab is persistent, delete the settings file from disk
if tab.settings.get("persistent", "enabled"):
tab.settings.delete()
self.save_persistent_tabs()
# Remove the tab
self.removeTab(index)
del self.tabs[tab.tab_id]
# If the last tab is closed, open a new one
if self.count() == 0:
self.new_tab_clicked()
def are_tabs_active(self): def are_tabs_active(self):
""" """
@ -273,6 +298,28 @@ class TabWidget(QtWidgets.QTabWidget):
super(TabWidget, self).resizeEvent(event) super(TabWidget, self).resizeEvent(event)
self.move_new_tab_button() self.move_new_tab_button()
def macos_create_close_button(self, tab, index):
def close_tab():
self.tabBar().tabCloseRequested.emit(self.indexOf(tab))
close_button = QtWidgets.QPushButton()
close_button.setFlat(True)
close_button.setFixedWidth(40)
close_button.setIcon(
QtGui.QIcon(GuiCommon.get_resource_path("images/close_tab.png"))
)
close_button.clicked.connect(close_tab)
self.tabBar().setTabButton(index, QtWidgets.QTabBar.RightSide, tab.close_button)
def is_settings_tab(self, tab_id):
if tab_id not in self.tabs:
return True
return (
type(self.tabs[tab_id]) is SettingsTab
or type(self.tabs[tab_id]) is TorSettingsTab
)
class TabBar(QtWidgets.QTabBar): class TabBar(QtWidgets.QTabBar):
""" """

View file

@ -34,25 +34,21 @@ from .moat_dialog import MoatDialog
from .gui_common import GuiCommon from .gui_common import GuiCommon
class TorSettingsDialog(QtWidgets.QDialog): class TorSettingsTab(QtWidgets.QWidget):
""" """
Settings dialog. Settings dialog.
""" """
settings_saved = QtCore.Signal() settings_saved = QtCore.Signal()
def __init__(self, common): def __init__(self, common, tab_id):
super(TorSettingsDialog, self).__init__() super(TorSettingsTab, self).__init__()
self.common = common self.common = common
self.common.log("TorSettingsTab", "__init__")
self.common.log("TorSettingsDialog", "__init__")
self.setModal(True)
self.setWindowTitle(strings._("gui_tor_settings_window_title"))
self.setWindowIcon(QtGui.QIcon(GuiCommon.get_resource_path("images/logo.png")))
self.system = platform.system() self.system = platform.system()
self.tab_id = tab_id
# Connection type: either automatic, control port, or socket file # Connection type: either automatic, control port, or socket file
@ -443,7 +439,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
""" """
Connection type bundled was toggled Connection type bundled was toggled
""" """
self.common.log("TorSettingsDialog", "connection_type_bundled_toggled") self.common.log("TorSettingsTab", "connection_type_bundled_toggled")
if checked: if checked:
self.tor_settings_group.hide() self.tor_settings_group.hide()
self.connection_type_socks.hide() self.connection_type_socks.hide()
@ -495,7 +491,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
""" """
Request new bridge button clicked Request new bridge button clicked
""" """
self.common.log("TorSettingsDialog", "bridge_moat_button_clicked") self.common.log("TorSettingsTab", "bridge_moat_button_clicked")
moat_dialog = MoatDialog(self.common) moat_dialog = MoatDialog(self.common)
moat_dialog.got_bridges.connect(self.bridge_moat_got_bridges) moat_dialog.got_bridges.connect(self.bridge_moat_got_bridges)
@ -505,7 +501,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
""" """
Got new bridges from moat Got new bridges from moat
""" """
self.common.log("TorSettingsDialog", "bridge_moat_got_bridges") self.common.log("TorSettingsTab", "bridge_moat_got_bridges")
self.bridge_moat_textbox.document().setPlainText(bridges) self.bridge_moat_textbox.document().setPlainText(bridges)
self.bridge_moat_textbox.show() self.bridge_moat_textbox.show()
@ -522,7 +518,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
""" """
Connection type automatic was toggled. If checked, hide authentication fields. Connection type automatic was toggled. If checked, hide authentication fields.
""" """
self.common.log("TorSettingsDialog", "connection_type_automatic_toggled") self.common.log("TorSettingsTab", "connection_type_automatic_toggled")
if checked: if checked:
self.tor_settings_group.hide() self.tor_settings_group.hide()
self.connection_type_socks.hide() self.connection_type_socks.hide()
@ -533,7 +529,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
Connection type control port was toggled. If checked, show extra fields Connection type control port was toggled. If checked, show extra fields
for Tor control address and port. If unchecked, hide those extra fields. for Tor control address and port. If unchecked, hide those extra fields.
""" """
self.common.log("TorSettingsDialog", "connection_type_control_port_toggled") self.common.log("TorSettingsTab", "connection_type_control_port_toggled")
if checked: if checked:
self.tor_settings_group.show() self.tor_settings_group.show()
self.connection_type_control_port_extras.show() self.connection_type_control_port_extras.show()
@ -547,7 +543,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
Connection type socket file was toggled. If checked, show extra fields Connection type socket file was toggled. If checked, show extra fields
for socket file. If unchecked, hide those extra fields. for socket file. If unchecked, hide those extra fields.
""" """
self.common.log("TorSettingsDialog", "connection_type_socket_file_toggled") self.common.log("TorSettingsTab", "connection_type_socket_file_toggled")
if checked: if checked:
self.tor_settings_group.show() self.tor_settings_group.show()
self.connection_type_socket_file_extras.show() self.connection_type_socket_file_extras.show()
@ -560,7 +556,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
""" """
Authentication option no authentication was toggled. Authentication option no authentication was toggled.
""" """
self.common.log("TorSettingsDialog", "authenticate_no_auth_toggled") self.common.log("TorSettingsTab", "authenticate_no_auth_toggled")
if checked: if checked:
self.authenticate_password_extras.hide() self.authenticate_password_extras.hide()
else: else:
@ -571,7 +567,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
Test Tor Settings button clicked. With the given settings, see if we can Test Tor Settings button clicked. With the given settings, see if we can
successfully connect and authenticate to Tor. successfully connect and authenticate to Tor.
""" """
self.common.log("TorSettingsDialog", "test_tor_clicked") self.common.log("TorSettingsTab", "test_tor_clicked")
settings = self.settings_from_fields() settings = self.settings_from_fields()
if not settings: if not settings:
return return
@ -605,7 +601,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
""" """
Save button clicked. Save current settings to disk. Save button clicked. Save current settings to disk.
""" """
self.common.log("TorSettingsDialog", "save_clicked") self.common.log("TorSettingsTab", "save_clicked")
def changed(s1, s2, keys): def changed(s1, s2, keys):
""" """
@ -628,7 +624,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
if not self.common.gui.local_only: if not self.common.gui.local_only:
if self.common.gui.onion.is_authenticated(): if self.common.gui.onion.is_authenticated():
self.common.log( self.common.log(
"TorSettingsDialog", "save_clicked", "Connected to Tor" "TorSettingsTab", "save_clicked", "Connected to Tor"
) )
if changed( if changed(
@ -654,7 +650,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
else: else:
self.common.log( self.common.log(
"TorSettingsDialog", "save_clicked", "Not connected to Tor" "TorSettingsTab", "save_clicked", "Not connected to Tor"
) )
# Tor isn't connected, so try connecting # Tor isn't connected, so try connecting
reboot_onion = True reboot_onion = True
@ -663,7 +659,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
if reboot_onion: if reboot_onion:
# Reinitialize the Onion object # Reinitialize the Onion object
self.common.log( self.common.log(
"TorSettingsDialog", "save_clicked", "rebooting the Onion" "TorSettingsTab", "save_clicked", "rebooting the Onion"
) )
self.common.gui.onion.cleanup() self.common.gui.onion.cleanup()
@ -671,7 +667,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
tor_con.start() tor_con.start()
self.common.log( self.common.log(
"TorSettingsDialog", "TorSettingsTab",
"save_clicked", "save_clicked",
f"Onion done rebooting, connected to Tor: {self.common.gui.onion.connected_to_tor}", f"Onion done rebooting, connected to Tor: {self.common.gui.onion.connected_to_tor}",
) )
@ -694,7 +690,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
""" """
Cancel button clicked. Cancel button clicked.
""" """
self.common.log("TorSettingsDialog", "cancel_clicked") self.common.log("TorSettingsTab", "cancel_clicked")
if ( if (
not self.common.gui.local_only not self.common.gui.local_only
and not self.common.gui.onion.is_authenticated() and not self.common.gui.onion.is_authenticated()
@ -712,7 +708,7 @@ class TorSettingsDialog(QtWidgets.QDialog):
""" """
Return a Settings object that's full of values from the settings dialog. Return a Settings object that's full of values from the settings dialog.
""" """
self.common.log("TorSettingsDialog", "settings_from_fields") self.common.log("TorSettingsTab", "settings_from_fields")
settings = Settings(self.common) settings = Settings(self.common)
settings.load() # To get the last update timestamp settings.load() # To get the last update timestamp
@ -833,13 +829,13 @@ class TorSettingsDialog(QtWidgets.QDialog):
return settings return settings
def closeEvent(self, e): def closeEvent(self, e):
self.common.log("TorSettingsDialog", "closeEvent") self.common.log("TorSettingsTab", "closeEvent")
# On close, if Tor isn't connected, then quit OnionShare altogether # On close, if Tor isn't connected, then quit OnionShare altogether
if not self.common.gui.local_only: if not self.common.gui.local_only:
if not self.common.gui.onion.is_authenticated(): if not self.common.gui.onion.is_authenticated():
self.common.log( self.common.log(
"TorSettingsDialog", "TorSettingsTab",
"closeEvent", "closeEvent",
"Closing while not connected to Tor", "Closing while not connected to Tor",
) )