def test_load_invalid_locale( self, common_obj, locale_invalid, sys_onionshare_dev_mode): """ load_strings() raises a KeyError for an invalid locale """ with pytest.raises(KeyError): common_obj.settings = Settings(common_obj) common_obj.settings.set('locale', 'XX') strings.load_strings(common_obj)
def set_up(): '''Create the GUI''' # Default settings for the settings GUI tests test_settings = { "no_bridges": False, "tor_bridges_use_custom_bridges": "Bridge 1.2.3.4:56 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\nBridge 5.6.7.8:910 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\nBridge 11.12.13.14:1516 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n", } # Create our test file testfile = open('/tmp/test.txt', 'w') testfile.write('onionshare') testfile.close() common = Common() common.settings = Settings(common) common.define_css() strings.load_strings(common) # Start the Onion testonion = Onion(common) global qtapp qtapp = Application(common) app = OnionShare(common, testonion, True, 0) for key, val in common.settings.default_settings.items(): if key not in test_settings: test_settings[key] = val open('/tmp/settings.json', 'w').write(json.dumps(test_settings)) gui = SettingsDialog(common, testonion, qtapp, '/tmp/settings.json', True) return gui
def test_load_strings_loads_other_languages( self, common_obj, locale_fr, sys_onionshare_dev_mode): """ load_strings() loads other languages in different locales """ common_obj.settings = Settings(common_obj) common_obj.settings.set('locale', 'fr') strings.load_strings(common_obj) assert strings._('preparing_files') == "Compression des fichiers."
def test_load_partial_strings( self, locale_ru, sys_onionshare_dev_mode): strings.load_strings(common) assert strings._("give_this_url") == ( "Отправьте эту ссылку тому человеку, " "которому вы хотите передать файл:") assert strings._('wait_for_hs') == "Waiting for HS to be ready:"
def web_obj(common_obj, mode, num_files=0): """ Creates a Web object, in either share mode or receive mode, ready for testing """ common_obj.settings = Settings(common_obj) strings.load_strings(common_obj) web = Web(common_obj, False, mode) web.generate_slug() web.stay_open = True web.running = True web.app.testing = True # Share mode if mode == 'share': # Add files files = [] for i in range(num_files): with tempfile.NamedTemporaryFile(delete=False) as tmp_file: tmp_file.write(b'*' * 1024) files.append(tmp_file.name) web.share_mode.set_file_info(files) # Receive mode else: pass return web
def main(): """ The main() function implements all of the logic that the GUI version of onionshare uses. """ strings.load_strings() print(strings._('version_string').format(helpers.get_version())) # start the Qt app global qtapp qtapp = Application() # parse arguments parser = argparse.ArgumentParser() parser.add_argument('--local-only', action='store_true', dest='local_only', help=strings._("help_local_only")) parser.add_argument('--stay-open', action='store_true', dest='stay_open', help=strings._("help_stay_open")) parser.add_argument('--debug', action='store_true', dest='debug', help=strings._("help_debug")) parser.add_argument('--transparent', action='store_true', dest='transparent_torification', help=strings._("help_transparent_torification")) parser.add_argument('--filenames', metavar='filenames', nargs='+', help=strings._('help_filename')) args = parser.parse_args() filenames = args.filenames if filenames: for i in range(len(filenames)): filenames[i] = os.path.abspath(filenames[i]) local_only = bool(args.local_only) stay_open = bool(args.stay_open) debug = bool(args.debug) transparent_torification = bool(args.transparent_torification) # create the onionshare icon global window_icon window_icon = QtGui.QIcon(common.get_image_path('logo.png')) # validation if filenames: valid = True for filename in filenames: if not os.path.exists(filename): alert(strings._("not_a_file", True).format(filename)) valid = False if not valid: sys.exit() # start the onionshare app web.set_stay_open(stay_open) web.set_transparent_torification(transparent_torification) app = onionshare.OnionShare(debug, local_only, stay_open, transparent_torification) # clean up when app quits def shutdown(): app.cleanup() qtapp.aboutToQuit.connect(shutdown) # launch the gui gui = OnionShareGui(qtapp, app) gui.send_files(filenames) # all done sys.exit(qtapp.exec_())
def set_up(test_settings): '''Create GUI with given settings''' # Create our test file testfile = open('/tmp/test.txt', 'w') testfile.write('onionshare') testfile.close() # Create a test dir and files if not os.path.exists('/tmp/testdir'): testdir = os.mkdir('/tmp/testdir') testfile = open('/tmp/testdir/test.txt', 'w') testfile.write('onionshare') testfile.close() common = Common() common.settings = Settings(common) common.define_css() strings.load_strings(common) # Get all of the settings in test_settings test_settings['connection_type'] = 'automatic' test_settings['data_dir'] = '/tmp/OnionShare' for key, val in common.settings.default_settings.items(): if key not in test_settings: test_settings[key] = val # Start the Onion testonion = Onion(common) global qtapp qtapp = Application(common) app = OnionShare(common, testonion, False, 0) web = Web(common, False, False) open('/tmp/settings.json', 'w').write(json.dumps(test_settings)) gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt', '/tmp/testdir'], '/tmp/settings.json', False) return gui
def __init__(self, common, onion, qtapp, app, filenames, config=False, local_only=False): super(OnionShareGui, self).__init__() self.common = common self.common.log('OnionShareGui', '__init__') self.setMinimumWidth(820) self.setMinimumHeight(660) self.onion = onion self.qtapp = qtapp self.app = app self.local_only = local_only self.mode = self.MODE_SHARE self.setWindowTitle('OnionShare') self.setWindowIcon(QtGui.QIcon(self.common.get_resource_path('images/logo.png'))) # Load settings, if a custom config was passed in self.config = config if self.config: self.common.load_settings(self.config) else: self.common.load_settings() strings.load_strings(self.common) # System tray menu = QtWidgets.QMenu() self.settings_action = menu.addAction(strings._('gui_settings_window_title')) self.settings_action.triggered.connect(self.open_settings) self.help_action = menu.addAction(strings._('gui_settings_button_help')) self.help_action.triggered.connect(lambda: SettingsDialog.help_clicked(self)) exit_action = menu.addAction(strings._('systray_menu_exit')) exit_action.triggered.connect(self.close) self.system_tray = QtWidgets.QSystemTrayIcon(self) # The convention is Mac systray icons are always grayscale if self.common.platform == 'Darwin': self.system_tray.setIcon(QtGui.QIcon(self.common.get_resource_path('images/logo_grayscale.png'))) else: self.system_tray.setIcon(QtGui.QIcon(self.common.get_resource_path('images/logo.png'))) self.system_tray.setContextMenu(menu) self.system_tray.show() # Mode switcher, to switch between share files and receive files self.share_mode_button = QtWidgets.QPushButton(strings._('gui_mode_share_button')); self.share_mode_button.setFixedHeight(50) self.share_mode_button.clicked.connect(self.share_mode_clicked) self.receive_mode_button = QtWidgets.QPushButton(strings._('gui_mode_receive_button')); self.receive_mode_button.setFixedHeight(50) self.receive_mode_button.clicked.connect(self.receive_mode_clicked) self.settings_button = QtWidgets.QPushButton() self.settings_button.setDefault(False) self.settings_button.setFixedWidth(40) self.settings_button.setFixedHeight(50) self.settings_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/settings.png')) ) self.settings_button.clicked.connect(self.open_settings) self.settings_button.setStyleSheet(self.common.css['settings_button']) mode_switcher_layout = QtWidgets.QHBoxLayout(); mode_switcher_layout.setSpacing(0) mode_switcher_layout.addWidget(self.share_mode_button) mode_switcher_layout.addWidget(self.receive_mode_button) mode_switcher_layout.addWidget(self.settings_button) # Server status indicator on the status bar self.server_status_image_stopped = QtGui.QImage(self.common.get_resource_path('images/server_stopped.png')) self.server_status_image_working = QtGui.QImage(self.common.get_resource_path('images/server_working.png')) self.server_status_image_started = QtGui.QImage(self.common.get_resource_path('images/server_started.png')) self.server_status_image_label = QtWidgets.QLabel() self.server_status_image_label.setFixedWidth(20) self.server_status_label = QtWidgets.QLabel('') self.server_status_label.setStyleSheet(self.common.css['server_status_indicator_label']) server_status_indicator_layout = QtWidgets.QHBoxLayout() server_status_indicator_layout.addWidget(self.server_status_image_label) server_status_indicator_layout.addWidget(self.server_status_label) self.server_status_indicator = QtWidgets.QWidget() self.server_status_indicator.setLayout(server_status_indicator_layout) # Status bar self.status_bar = QtWidgets.QStatusBar() self.status_bar.setSizeGripEnabled(False) self.status_bar.setStyleSheet(self.common.css['status_bar']) self.status_bar.addPermanentWidget(self.server_status_indicator) self.setStatusBar(self.status_bar) # Share mode self.share_mode = ShareMode(self.common, qtapp, app, self.status_bar, self.server_status_label, self.system_tray, filenames, self.local_only) self.share_mode.init() self.share_mode.server_status.server_started.connect(self.update_server_status_indicator) self.share_mode.server_status.server_stopped.connect(self.update_server_status_indicator) self.share_mode.start_server_finished.connect(self.update_server_status_indicator) self.share_mode.stop_server_finished.connect(self.update_server_status_indicator) self.share_mode.stop_server_finished.connect(self.stop_server_finished) self.share_mode.start_server_finished.connect(self.clear_message) self.share_mode.server_status.button_clicked.connect(self.clear_message) self.share_mode.server_status.url_copied.connect(self.copy_url) self.share_mode.server_status.hidservauth_copied.connect(self.copy_hidservauth) self.share_mode.set_server_active.connect(self.set_server_active) # Receive mode self.receive_mode = ReceiveMode(self.common, qtapp, app, self.status_bar, self.server_status_label, self.system_tray, None, self.local_only) self.receive_mode.init() self.receive_mode.server_status.server_started.connect(self.update_server_status_indicator) self.receive_mode.server_status.server_stopped.connect(self.update_server_status_indicator) self.receive_mode.start_server_finished.connect(self.update_server_status_indicator) self.receive_mode.stop_server_finished.connect(self.update_server_status_indicator) self.receive_mode.stop_server_finished.connect(self.stop_server_finished) self.receive_mode.start_server_finished.connect(self.clear_message) self.receive_mode.server_status.button_clicked.connect(self.clear_message) self.receive_mode.server_status.url_copied.connect(self.copy_url) self.receive_mode.server_status.hidservauth_copied.connect(self.copy_hidservauth) self.receive_mode.set_server_active.connect(self.set_server_active) self.update_mode_switcher() self.update_server_status_indicator() # Layouts contents_layout = QtWidgets.QVBoxLayout() contents_layout.setContentsMargins(10, 0, 10, 0) contents_layout.addWidget(self.receive_mode) contents_layout.addWidget(self.share_mode) layout = QtWidgets.QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addLayout(mode_switcher_layout) layout.addLayout(contents_layout) central_widget = QtWidgets.QWidget() central_widget.setLayout(layout) self.setCentralWidget(central_widget) self.show() # The server isn't active yet self.set_server_active(False) # Create the timer self.timer = QtCore.QTimer() self.timer.timeout.connect(self.timer_callback) # Start the "Connecting to Tor" dialog, which calls onion.connect() tor_con = TorConnectionDialog(self.common, self.qtapp, self.onion) tor_con.canceled.connect(self._tor_connection_canceled) tor_con.open_settings.connect(self._tor_connection_open_settings) if not self.local_only: tor_con.start() # Start the timer self.timer.start(500) # After connecting to Tor, check for updates self.check_for_updates()
def __init__(self, common, qtapp, local_only): self.common = common self.qtapp = qtapp self.local_only = local_only # Are we running in a flatpak package? self.is_flatpak = os.path.exists("/.flatpak-info") # Load settings self.common.load_settings() # Load strings strings.load_strings(self.common) # Start the Onion self.onion = Onion(common) # Lock filename self.lock_filename = os.path.join(self.common.build_data_dir(), "lock") # Events filenames self.events_dir = os.path.join(self.common.build_data_dir(), "events") if not os.path.exists(self.events_dir): os.makedirs(self.events_dir, 0o700, True) self.events_filename = os.path.join(self.events_dir, "events") self.css = { # OnionShareGui styles "tab_widget": """ QTabBar::tab { width: 170px; height: 30px; } """, "tab_widget_new_tab_button": """ QPushButton { font-weight: bold; font-size: 20px; }""", "mode_new_tab_button": """ QPushButton { font-weight: bold; font-size: 30px; color: #601f61; }""", "mode_header_label": """ QLabel { color: #333333; font-size: 30px; }""", "settings_button": """ QPushButton { border: 0; border-radius: 0; }""", "server_status_indicator_label": """ QLabel { font-style: italic; color: #666666; padding: 2px; }""", "status_bar": """ QStatusBar { font-style: italic; color: #666666; } QStatusBar::item { border: 0px; }""", # Common styles between modes and their child widgets "mode_settings_toggle_advanced": """ QPushButton { color: #3f7fcf; text-align: left; } """, "mode_info_label": """ QLabel { font-size: 12px; color: #666666; } """, "server_status_url": """ QLabel { background-color: #ffffff; color: #000000; padding: 10px; border: 1px solid #666666; font-size: 12px; } """, "server_status_url_buttons": """ QPushButton { color: #3f7fcf; } """, "server_status_button_stopped": """ QPushButton { background-color: #5fa416; color: #ffffff; padding: 10px 30px 10px 30px; border: 0; border-radius: 5px; }""", "server_status_button_working": """ QPushButton { background-color: #4c8211; color: #ffffff; padding: 10px 30px 10px 30px; border: 0; border-radius: 5px; font-style: italic; }""", "server_status_button_started": """ QPushButton { background-color: #d0011b; color: #ffffff; padding: 10px 30px 10px 30px; border: 0; border-radius: 5px; }""", "downloads_uploads_empty": """ QWidget { background-color: #ffffff; border: 1px solid #999999; } QWidget QLabel { background-color: none; border: 0px; } """, "downloads_uploads_empty_text": """ QLabel { color: #999999; }""", "downloads_uploads_label": """ QLabel { font-weight: bold; font-size 14px; text-align: center; background-color: none; border: none; }""", "downloads_uploads_clear": """ QPushButton { color: #3f7fcf; } """, "download_uploads_indicator": """ QLabel { color: #ffffff; background-color: #f44449; font-weight: bold; font-size: 10px; padding: 2px; border-radius: 7px; text-align: center; }""", "downloads_uploads_progress_bar": """ QProgressBar { border: 1px solid #4e064f; background-color: #ffffff !important; text-align: center; color: #9b9b9b; font-size: 14px; } QProgressBar::chunk { background-color: #4e064f; width: 10px; }""", "history_individual_file_timestamp_label": """ QLabel { color: #666666; }""", "history_individual_file_status_code_label_2xx": """ QLabel { color: #008800; }""", "history_individual_file_status_code_label_4xx": """ QLabel { color: #cc0000; }""", # New tab "new_tab_button_image": """ QLabel { padding: 30px; } """, "new_tab_button_text": """ QLabel { border: 1px solid #efeff0; border-radius: 4px; background-color: #ffffff; text-align: center; color: #4e0d4e; } """, # Share mode and child widget styles "share_delete_all_files_button": """ QPushButton { color: #3f7fcf; } """, "share_zip_progess_bar": """ QProgressBar { border: 1px solid #4e064f; background-color: #ffffff !important; text-align: center; color: #9b9b9b; } QProgressBar::chunk { border: 0px; background-color: #4e064f; width: 10px; }""", "share_filesize_warning": """ QLabel { padding: 10px 0; font-weight: bold; color: #333333; } """, "share_file_selection_drop_here_header_label": """ QLabel { color: #333333; font-size: 30px; }""", "share_file_selection_drop_here_label": """ QLabel { color: #666666; }""", "share_file_selection_drop_count_label": """ QLabel { color: #ffffff; background-color: #f44449; font-weight: bold; padding: 5px 10px; border-radius: 10px; }""", "share_file_list_drag_enter": """ FileList { border: 3px solid #538ad0; } """, "share_file_list_drag_leave": """ FileList { border: none; } """, "share_file_list_item_size": """ QLabel { color: #666666; font-size: 11px; }""", # Receive mode and child widget styles "receive_file": """ QWidget { background-color: #ffffff; } """, "receive_file_size": """ QLabel { color: #666666; font-size: 11px; }""", # Settings dialog "settings_version": """ QLabel { color: #666666; }""", "settings_tor_status": """ QLabel { background-color: #ffffff; color: #000000; padding: 10px; }""", "settings_whats_this": """ QLabel { font-size: 12px; }""", "settings_connect_to_tor": """ QLabel { font-style: italic; }""", }
def settings_obj(sys_onionshare_dev_mode, platform_linux): _common = common.Common() _common.version = 'DUMMY_VERSION_1.2.3' strings.load_strings(_common) return settings.Settings(_common)
def test_load_strings_loads_other_languages(): """load_strings() loads other languages in different locales""" locale.getdefaultlocale = lambda: ('fr_FR', 'UTF-8') strings.load_strings("fr") assert strings._('wait_for_hs') == "En attente du HS:"
def test_load_strings_defaults_to_english( self, locale_en, sys_onionshare_dev_mode): """ load_strings() loads English by default """ strings.load_strings(common) assert strings._('wait_for_hs') == "Waiting for HS to be ready:"
def test_load_partial_strings(self, locale_ru, sys_onionshare_dev_mode): strings.load_strings(common) assert strings._("give_this_url") == ( "Отправьте эту ссылку тому человеку, " "которому вы хотите передать файл:") assert strings._('wait_for_hs') == "Waiting for HS to be ready:"
def test_load_strings_loads_other_languages(self, locale_fr, sys_onionshare_dev_mode): """ load_strings() loads other languages in different locales """ strings.load_strings(common, "fr") assert strings._('wait_for_hs') == "En attente du HS:"
def test_load_strings_defaults_to_english(self, locale_en, sys_onionshare_dev_mode): """ load_strings() loads English by default """ strings.load_strings(common) assert strings._('wait_for_hs') == "Waiting for HS to be ready:"
def main(): """ The main() function implements all of the logic that the GUI version of onionshare uses. """ strings.load_strings(common) print(strings._('version_string').format(common.get_version())) # Start the Qt app global qtapp qtapp = Application() # Parse arguments parser = argparse.ArgumentParser(formatter_class=lambda prog: argparse. HelpFormatter(prog, max_help_position=48)) parser.add_argument('--local-only', action='store_true', dest='local_only', help=strings._("help_local_only")) parser.add_argument('--stay-open', action='store_true', dest='stay_open', help=strings._("help_stay_open")) parser.add_argument('--shutdown-timeout', metavar='<int>', dest='shutdown_timeout', default=0, help=strings._("help_shutdown_timeout")) parser.add_argument('--debug', action='store_true', dest='debug', help=strings._("help_debug")) parser.add_argument('--filenames', metavar='filenames', nargs='+', help=strings._('help_filename')) parser.add_argument('--config', metavar='config', default=False, help=strings._('help_config')) args = parser.parse_args() filenames = args.filenames if filenames: for i in range(len(filenames)): filenames[i] = os.path.abspath(filenames[i]) config = args.config local_only = bool(args.local_only) stay_open = bool(args.stay_open) shutdown_timeout = int(args.shutdown_timeout) debug = bool(args.debug) # Debug mode? if debug: common.set_debug(debug) web.debug_mode() # Validation if filenames: valid = True for filename in filenames: if not os.path.isfile(filename) and not os.path.isdir(filename): Alert(strings._("not_a_file", True).format(filename)) valid = False if not os.access(filename, os.R_OK): Alert(strings._("not_a_readable_file", True).format(filename)) valid = False if not valid: sys.exit() # Start the Onion onion = Onion() # Start the OnionShare app web.set_stay_open(stay_open) app = OnionShare(onion, local_only, stay_open, shutdown_timeout) # Launch the gui gui = OnionShareGui(onion, qtapp, app, filenames, config) # Clean up when app quits def shutdown(): onion.cleanup() app.cleanup() qtapp.aboutToQuit.connect(shutdown) # All done sys.exit(qtapp.exec_())
def test_load_invalid_locale( self, locale_invalid, sys_onionshare_dev_mode): """ load_strings() raises a KeyError for an invalid locale """ with pytest.raises(KeyError): strings.load_strings(common, 'XX')
def test_load_strings_loads_other_languages( self, locale_fr, sys_onionshare_dev_mode): """ load_strings() loads other languages in different locales """ strings.load_strings(common, "fr") assert strings._('wait_for_hs') == "En attente du HS:"
def test_load_strings_defaults_to_english( self, common_obj, locale_en, sys_onionshare_dev_mode): """ load_strings() loads English by default """ common_obj.settings = Settings(common_obj) strings.load_strings(common_obj) assert strings._('preparing_files') == "Compressing files."
def test_load_strings_loads_other_languages(): "load_strings() loads other languages in different locales" locale.getdefaultlocale = lambda: ('fr_FR', 'UTF-8') strings.load_strings("fr") assert strings._('calculating_sha1') == "Calculer une somme de contrôle SHA-1."
def test_load_invalid_locale(self, locale_invalid, sys_onionshare_dev_mode): """ load_strings() raises a KeyError for an invalid locale """ with pytest.raises(KeyError): strings.load_strings(common, 'XX')
def main(): """ The main() function implements all of the logic that the GUI version of onionshare uses. """ strings.load_strings() # start the Qt app global qtapp qtapp = Application() # parse arguments parser = argparse.ArgumentParser() parser.add_argument('--local-only', action='store_true', dest='local_only', help=strings._("help_local_only")) parser.add_argument('--stay-open', action='store_true', dest='stay_open', help=strings._("help_stay_open")) parser.add_argument('--debug', action='store_true', dest='debug', help=strings._("help_debug")) parser.add_argument('--transparent', action='store_true', dest='transparent_torification', help=strings._("help_transparent_torification")) parser.add_argument('--filenames', metavar='filenames', nargs='+', help=strings._('help_filename')) args = parser.parse_args() filenames = args.filenames if filenames: for i in range(len(filenames)): filenames[i] = os.path.abspath(filenames[i]) local_only = bool(args.local_only) stay_open = bool(args.stay_open) debug = bool(args.debug) transparent_torification = bool(args.transparent_torification) # create the onionshare icon global window_icon window_icon = QtGui.QIcon(common.get_image_path('logo.png')) # validation if filenames: valid = True for filename in filenames: if not os.path.exists(filename): alert(strings._("not_a_file", True).format(filename)) valid = False if not valid: sys.exit() # start the onionshare app web.set_stay_open(stay_open) web.set_transparent_torification(transparent_torification) app = onionshare.OnionShare(debug, local_only, stay_open, transparent_torification) # clean up when app quits def shutdown(): app.cleanup() qtapp.connect(qtapp, QtCore.SIGNAL("aboutToQuit()"), shutdown) # launch the gui gui = OnionShareGui(qtapp, app) gui.send_files(filenames) # all done sys.exit(qtapp.exec_())
def test_load_strings_defaults_to_english(): "load_strings() loads English by default" locale.getdefaultlocale = lambda: ('en_US', 'UTF-8') strings.load_strings() assert strings._('calculating_sha1') == "Calculating SHA1 checksum."
def settings_obj(sys_onionshare_dev_mode, platform_linux): _common = common.Common() _common.version = "DUMMY_VERSION_1.2.3" strings.load_strings(_common) return settings.Settings(_common)
def test_load_strings_defaults_to_english(): """load_strings() loads English by default""" locale.getdefaultlocale = lambda: ('en_US', 'UTF-8') strings.load_strings() assert strings._('wait_for_hs') == "Waiting for HS to be ready:"
def __init__(self, common, onion, qtapp, app, filenames, config=False, local_only=False): super(OnionShareGui, self).__init__() self.common = common self.common.log('OnionShareGui', '__init__') self.setMinimumWidth(820) self.setMinimumHeight(660) self.onion = onion self.qtapp = qtapp self.app = app self.local_only = local_only self.mode = self.MODE_SHARE self.setWindowTitle('OnionShare') self.setWindowIcon( QtGui.QIcon(self.common.get_resource_path('images/logo.png'))) # Load settings, if a custom config was passed in self.config = config if self.config: self.common.load_settings(self.config) else: self.common.load_settings() strings.load_strings(self.common) # System tray menu = QtWidgets.QMenu() self.settings_action = menu.addAction( strings._('gui_settings_window_title')) self.settings_action.triggered.connect(self.open_settings) self.help_action = menu.addAction( strings._('gui_settings_button_help')) self.help_action.triggered.connect( lambda: SettingsDialog.help_clicked(self)) exit_action = menu.addAction(strings._('systray_menu_exit')) exit_action.triggered.connect(self.close) self.system_tray = QtWidgets.QSystemTrayIcon(self) # The convention is Mac systray icons are always grayscale if self.common.platform == 'Darwin': self.system_tray.setIcon( QtGui.QIcon( self.common.get_resource_path( 'images/logo_grayscale.png'))) else: self.system_tray.setIcon( QtGui.QIcon(self.common.get_resource_path('images/logo.png'))) self.system_tray.setContextMenu(menu) self.system_tray.show() # Mode switcher, to switch between share files and receive files self.share_mode_button = QtWidgets.QPushButton( strings._('gui_mode_share_button')) self.share_mode_button.setFixedHeight(50) self.share_mode_button.clicked.connect(self.share_mode_clicked) self.receive_mode_button = QtWidgets.QPushButton( strings._('gui_mode_receive_button')) self.receive_mode_button.setFixedHeight(50) self.receive_mode_button.clicked.connect(self.receive_mode_clicked) self.settings_button = QtWidgets.QPushButton() self.settings_button.setDefault(False) self.settings_button.setFixedWidth(40) self.settings_button.setFixedHeight(50) self.settings_button.setIcon( QtGui.QIcon(self.common.get_resource_path('images/settings.png'))) self.settings_button.clicked.connect(self.open_settings) self.settings_button.setStyleSheet(self.common.css['settings_button']) mode_switcher_layout = QtWidgets.QHBoxLayout() mode_switcher_layout.setSpacing(0) mode_switcher_layout.addWidget(self.share_mode_button) mode_switcher_layout.addWidget(self.receive_mode_button) mode_switcher_layout.addWidget(self.settings_button) # Server status indicator on the status bar self.server_status_image_stopped = QtGui.QImage( self.common.get_resource_path('images/server_stopped.png')) self.server_status_image_working = QtGui.QImage( self.common.get_resource_path('images/server_working.png')) self.server_status_image_started = QtGui.QImage( self.common.get_resource_path('images/server_started.png')) self.server_status_image_label = QtWidgets.QLabel() self.server_status_image_label.setFixedWidth(20) self.server_status_label = QtWidgets.QLabel('') self.server_status_label.setStyleSheet( self.common.css['server_status_indicator_label']) server_status_indicator_layout = QtWidgets.QHBoxLayout() server_status_indicator_layout.addWidget( self.server_status_image_label) server_status_indicator_layout.addWidget(self.server_status_label) self.server_status_indicator = QtWidgets.QWidget() self.server_status_indicator.setLayout(server_status_indicator_layout) # Status bar self.status_bar = QtWidgets.QStatusBar() self.status_bar.setSizeGripEnabled(False) self.status_bar.setStyleSheet(self.common.css['status_bar']) self.status_bar.addPermanentWidget(self.server_status_indicator) self.setStatusBar(self.status_bar) # Share mode self.share_mode = ShareMode(self.common, qtapp, app, self.status_bar, self.server_status_label, self.system_tray, filenames, self.local_only) self.share_mode.init() self.share_mode.server_status.server_started.connect( self.update_server_status_indicator) self.share_mode.server_status.server_stopped.connect( self.update_server_status_indicator) self.share_mode.start_server_finished.connect( self.update_server_status_indicator) self.share_mode.stop_server_finished.connect( self.update_server_status_indicator) self.share_mode.stop_server_finished.connect(self.stop_server_finished) self.share_mode.start_server_finished.connect(self.clear_message) self.share_mode.server_status.button_clicked.connect( self.clear_message) self.share_mode.server_status.url_copied.connect(self.copy_url) self.share_mode.server_status.hidservauth_copied.connect( self.copy_hidservauth) self.share_mode.set_server_active.connect(self.set_server_active) # Receive mode self.receive_mode = ReceiveMode(self.common, qtapp, app, self.status_bar, self.server_status_label, self.system_tray, None, self.local_only) self.receive_mode.init() self.receive_mode.server_status.server_started.connect( self.update_server_status_indicator) self.receive_mode.server_status.server_stopped.connect( self.update_server_status_indicator) self.receive_mode.start_server_finished.connect( self.update_server_status_indicator) self.receive_mode.stop_server_finished.connect( self.update_server_status_indicator) self.receive_mode.stop_server_finished.connect( self.stop_server_finished) self.receive_mode.start_server_finished.connect(self.clear_message) self.receive_mode.server_status.button_clicked.connect( self.clear_message) self.receive_mode.server_status.url_copied.connect(self.copy_url) self.receive_mode.server_status.hidservauth_copied.connect( self.copy_hidservauth) self.receive_mode.set_server_active.connect(self.set_server_active) self.update_mode_switcher() self.update_server_status_indicator() # Layouts contents_layout = QtWidgets.QVBoxLayout() contents_layout.setContentsMargins(10, 0, 10, 0) contents_layout.addWidget(self.receive_mode) contents_layout.addWidget(self.share_mode) layout = QtWidgets.QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addLayout(mode_switcher_layout) layout.addLayout(contents_layout) central_widget = QtWidgets.QWidget() central_widget.setLayout(layout) self.setCentralWidget(central_widget) self.show() # The server isn't active yet self.set_server_active(False) # Create the timer self.timer = QtCore.QTimer() self.timer.timeout.connect(self.timer_callback) # Start the "Connecting to Tor" dialog, which calls onion.connect() tor_con = TorConnectionDialog(self.common, self.qtapp, self.onion) tor_con.canceled.connect(self._tor_connection_canceled) tor_con.open_settings.connect(self._tor_connection_open_settings) if not self.local_only: tor_con.start() # Start the timer self.timer.start(500) # After connecting to Tor, check for updates self.check_for_updates()