def on_restore_link_activated(self): self.recovery_key_importer = RecoveryKeyImporter(self.page_1) self.recovery_key_importer.done.connect(self.on_import_done) self.recovery_key_importer.do_import()
class WelcomeDialog(QStackedWidget): def __init__(self, gui, known_gateways=None): super(WelcomeDialog, self).__init__() self.gui = gui self.known_gateways = known_gateways self.gateway = None self.setup_runner = None self.recovery_key_importer = None self.use_tor = False self.prompt_to_export = True self.resize(400, 500) self.setWindowTitle(APP_NAME) self.page_1 = WelcomeWidget(self) self.page_2 = ProgressBarWidget() self.page_3 = TahoeConfigForm() self.addWidget(self.page_1) self.addWidget(self.page_2) self.addWidget(self.page_3) self.lineedit = self.page_1.lineedit self.checkbox = self.page_1.invite_code_widget.checkbox self.cancel_button = self.page_2.cancel_button self.finish_button = self.page_2.finish_button self.buttonbox = self.page_3.buttonbox self.restore_link = self.page_1.restore_link self.configure_link = self.page_1.configure_link self.preferences_button = self.page_1.preferences_button self.shortcut_close = QShortcut(QKeySequence.Close, self) self.shortcut_close.activated.connect(self.close) self.shortcut_quit = QShortcut(QKeySequence.Quit, self) self.shortcut_quit.activated.connect(self.close) self.lineedit.go.connect(self.go) self.lineedit.error.connect(self.show_error) self.checkbox.stateChanged.connect(self.on_checkbox_state_changed) self.cancel_button.clicked.connect(self.cancel_button_clicked) self.finish_button.clicked.connect(self.finish_button_clicked) self.buttonbox.accepted.connect(self.on_accepted) self.buttonbox.rejected.connect(self.reset) self.restore_link.linkActivated.connect(self.on_restore_link_activated) self.configure_link.linkActivated.connect( self.on_configure_link_activated) self.preferences_button.clicked.connect( self.gui.show_preferences_window) def on_checkbox_state_changed(self, state): self.use_tor = bool(state) log.debug("use_tor=%s", self.use_tor) if state: self.page_2.tor_label.show() self.page_2.progressbar.setStyleSheet( 'QProgressBar::chunk { background-color: #7D4698; }') else: self.page_2.tor_label.hide() self.page_2.progressbar.setStyleSheet('') def on_configure_link_activated(self): self.setCurrentIndex(2) def update_progress(self, message): self.page_2.update_progress(message) def show_error(self, message): self.page_1.show_error(message) def reset(self): self.page_1.reset() self.page_2.reset() self.page_3.reset() self.setCurrentIndex(0) def load_service_icon(self, filepath): pixmap = QPixmap(filepath).scaled(100, 100) self.page_2.icon_overlay.setPixmap(pixmap) def handle_failure(self, failure): log.error(str(failure)) if failure.type == CancelledError: if self.page_2.progressbar.value() <= 2: show_failure(failure, self) self.show_error("Invite timed out") self.reset() return show_failure(failure, self) if failure.type == ServerConnectionError: self.show_error("Server connection error") if failure.type == WelcomeError: self.show_error("Invite refused") elif failure.type == WrongPasswordError: self.show_error("Invite confirmation failed") elif failure.type == UpgradeRequiredError: self.show_error("Upgrade required") else: self.show_error(str(failure.type.__name__)) self.reset() def on_done(self, gateway): self.gateway = gateway self.page_2.progressbar.setValue(self.page_2.progressbar.maximum()) self.finish_button.show() def on_already_joined(self, grid_name): QMessageBox.information( self, "Already connected", 'You are already connected to "{}"'.format(grid_name)) self.close() def verify_settings(self, settings, from_wormhole=True): self.show() self.raise_() settings = validate_settings(settings, self.known_gateways, self, from_wormhole) self.setup_runner = SetupRunner(self.known_gateways, self.use_tor) steps = self.setup_runner.calculate_total_steps(settings) + 2 self.page_2.progressbar.setMaximum(steps) self.setup_runner.grid_already_joined.connect(self.on_already_joined) self.setup_runner.update_progress.connect(self.update_progress) self.setup_runner.got_icon.connect(self.load_service_icon) self.setup_runner.client_started.connect( lambda gateway: self.gui.populate([gateway])) self.setup_runner.done.connect(self.on_done) d = self.setup_runner.run(settings) d.addErrback(self.handle_failure) def on_import_done(self, settings): if settings.get('hide-ip'): self.on_checkbox_state_changed(1) # Toggle Tor checkbox "on" self.setCurrentIndex(1) self.page_2.progressbar.setValue(1) self.update_progress('Verifying invitation code...') self.prompt_to_export = False self.verify_settings(settings, from_wormhole=False) def on_restore_link_activated(self): self.recovery_key_importer = RecoveryKeyImporter(self.page_1) self.recovery_key_importer.done.connect(self.on_import_done) self.recovery_key_importer.do_import() def go(self, code): self.setCurrentIndex(1) self.page_2.progressbar.setValue(1) self.update_progress('Verifying invitation code...') if code.split('-')[0] == "0": settings = get_settings_from_cheatcode(code[2:]) if settings: self.verify_settings(settings) return d = wormhole_receive(code, self.use_tor) # pylint: disable=assignment-from-no-return d.addCallback(self.verify_settings) d.addErrback(self.handle_failure) reactor.callLater(30, d.cancel) def cancel_button_clicked(self): if self.page_2.is_complete(): self.finish_button_clicked() return msgbox = QMessageBox(self) msgbox.setIcon(QMessageBox.Question) msgbox.setWindowTitle("Cancel setup?") msgbox.setText("Are you sure you wish to cancel the setup process?") msgbox.setInformativeText( "If you cancel, you may need to obtain a new invite code.") msgbox.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msgbox.setDefaultButton(QMessageBox.No) if msgbox.exec_() == QMessageBox.Yes: self.reset() def on_accepted(self): settings = self.page_3.get_settings() msg = QMessageBox() msg.setIcon(QMessageBox.Warning) msg.setWindowTitle(APP_NAME) msg.setStandardButtons(QMessageBox.Ok) if not settings['nickname']: msg.setText("Please enter a name.") msg.exec_() elif not settings['introducer']: msg.setText("Please enter an Introducer fURL.") msg.exec_() elif not is_valid_furl(settings['introducer']): msg.setText("Please enter a valid Introducer fURL.") msg.exec_() else: self.setCurrentIndex(1) self.verify_settings(settings, from_wormhole=False) def prompt_for_export(self, gateway): msg = QMessageBox(self) msg.setIcon(QMessageBox.Warning) msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg.setDefaultButton(QMessageBox.Yes) button_export = msg.button(QMessageBox.Yes) button_export.setText("&Export...") button_skip = msg.button(QMessageBox.No) button_skip.setText("&Skip") msg.setWindowTitle("Export Recovery Key?") # "Now that {} is configured..." msg.setText( "Before uploading any folders to {}, it is recommended that you " "export a Recovery Key and store it in a safe location (such as " "an encrypted USB drive or password manager).".format( gateway.name)) msg.setInformativeText( "{} does not have access to your folders, and cannot restore " "access to them. But with a Recovery Key, you can restore access " "to uploaded folders in case something goes wrong (e.g., hardware " "failure, accidental data-loss).<p><p><a href={}>More information." "..</a>".format(gateway.name, global_settings['help']['recovery_url'])) #msg.setText( # "Before uploading any folders to {}, it is <b>strongly " # "recommended</b> that you <i>export a Recovery Key</i> and store " # "it in a safe and secure location (such as an encrypted USB drive)" # ".<p><p>Possessing a Recovery Key will allow you to restore " # "access to any of the folders you've uploaded to {} in the event " # "that something goes wrong (e.g., hardware failure, accidental " # "data-loss).".format(gateway.name, gateway.name)) #msg.setDetailedText( # "A 'Recovery Key' is a small file that contains enough information" # " to re-establish a connection with your storage provider and " # "restore your previously-uploaded folders. Because access to this " # "file is sufficient to access to any of the the data you've " # "stored, it is important that you keep this file safe and secure; " # "do not share your Recovery Key with anybody!") reply = msg.exec_() if reply == QMessageBox.Yes: self.gui.main_window.export_recovery_key() # XXX else: # TODO: Nag user; "Are you sure?" pass def finish_button_clicked(self): self.gui.show() self.close() if self.prompt_to_export: self.prompt_for_export(self.gateway) self.reset() def enterEvent(self, event): event.accept() self.lineedit.update_action_button() def closeEvent(self, event): if self.gui.main_window.gateways: event.accept() else: event.ignore() msgbox = QMessageBox(self) msgbox.setIcon(QMessageBox.Question) msgbox.setWindowTitle("Exit setup?") msgbox.setText("Are you sure you wish to exit?") msgbox.setInformativeText( "{} has not yet been configured.".format(APP_NAME)) msgbox.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msgbox.setDefaultButton(QMessageBox.No) if msgbox.exec_() == QMessageBox.Yes: QCoreApplication.instance().quit()