コード例 #1
0
    def showMaximized(self, skip_dialogs=False):
        super().showMaximized()
        QCoreApplication.processEvents()

        # Used with the --diagnose option
        if skip_dialogs:
            return

        # At the very first launch
        if self.config.gui_first_launch:
            r = ask_question(
                self,
                _("TEXT_ERROR_REPORTING_TITLE"),
                _("TEXT_ERROR_REPORTING_INSTRUCTIONS"),
                [_("ACTION_ERROR_REPORTING_ACCEPT"), _("ACTION_NO")],
            )

            # Acknowledge the changes
            self.event_bus.send(
                "gui.config.changed",
                gui_first_launch=False,
                gui_last_version=PARSEC_VERSION,
                telemetry_enabled=r == _("ACTION_ERROR_REPORTING_ACCEPT"),
            )

        # For each parsec update
        if self.config.gui_last_version and self.config.gui_last_version != PARSEC_VERSION:

            # Update from parsec `<1.14` to `>=1.14`
            if LooseVersion(self.config.gui_last_version) < "1.14":

                # Revert the acrobat reader workaround
                if (
                    platform.system() == "Windows"
                    and win_registry.is_acrobat_reader_dc_present()
                    and not win_registry.get_acrobat_app_container_enabled()
                ):
                    win_registry.del_acrobat_app_container_enabled()

            # Acknowledge the changes
            self.event_bus.send("gui.config.changed", gui_last_version=PARSEC_VERSION)

        telemetry.init(self.config)

        devices = list_available_devices(self.config.config_dir)
        if not len(devices):
            r = ask_question(
                self,
                _("TEXT_KICKSTART_PARSEC_WHAT_TO_DO_TITLE"),
                _("TEXT_KICKSTART_PARSEC_WHAT_TO_DO_INSTRUCTIONS"),
                [
                    _("ACTION_NO_DEVICE_CREATE_ORGANIZATION"),
                    _("ACTION_NO_DEVICE_JOIN_ORGANIZATION"),
                ],
                radio_mode=True,
            )
            if r == _("ACTION_NO_DEVICE_JOIN_ORGANIZATION"):
                self._on_join_org_clicked()
            elif r == _("ACTION_NO_DEVICE_CREATE_ORGANIZATION"):
                self._on_create_org_clicked()
コード例 #2
0
 def delete_files(self):
     files = self.table_files.selected_files()
     if len(files) == 1:
         result = ask_question(
             self,
             _("TEXT_FILE_DELETE_TITLE"),
             _("TEXT_FILE_DELETE_INSTRUCTIONS_name").format(
                 name=files[0].name),
             [_("ACTION_FILE_DELETE"),
              _("ACTION_CANCEL")],
         )
     else:
         result = ask_question(
             self,
             _("TEXT_FILE_DELETE_MULTIPLE_TITLE_count").format(
                 count=len(files)),
             _("TEXT_FILE_DELETE_MULTIPLE_INSTRUCTIONS_count").format(
                 count=len(files)),
             [_("ACTION_FILE_DELETE_MULTIPLE"),
              _("ACTION_CANCEL")],
         )
     if result != _("ACTION_FILE_DELETE_MULTIPLE") and result != _(
             "ACTION_FILE_DELETE"):
         return
     self.jobs_ctx.submit_job(
         ThreadSafeQtSignal(self, "delete_success", QtToTrioJob),
         ThreadSafeQtSignal(self, "delete_error", QtToTrioJob),
         _do_delete,
         workspace_fs=self.workspace_fs,
         files=[(self.current_directory / f.name, f.type) for f in files],
     )
コード例 #3
0
 def open_question_large(self):
     custom_dialogs.ask_question(
         self,
         title=SMALL_TEXT,
         message=LARGE_TEXT,
         button_texts=["BUTTON1", "BUTTON2", "BUTTON3"],
     )
コード例 #4
0
 def close_tab(self, index, force=False):
     tab = self.tab_center.widget(index)
     if not force:
         r = True
         if tab and tab.is_logged_in:
             r = ask_question(
                 self,
                 _("TEXT_TAB_CLOSE_TITLE"),
                 _("TEXT_TAB_CLOSE_INSTRUCTIONS"),
                 [_("ACTION_TAB_CLOSE_CONFIRM"), _("ACTION_CANCEL")],
             )
         elif self.tab_center.tabText(index) != _("TEXT_TAB_TITLE_LOG_IN_SCREEN"):
             r = ask_question(
                 self,
                 _("TEXT_TAB_CLOSE_TITLE"),
                 _("TEXT_TAB_CLOSE_INSTRUCTIONS"),
                 [_("ACTION_TAB_CLOSE_CONFIRM"), _("ACTION_CANCEL")],
             )
         if r != _("ACTION_TAB_CLOSE_CONFIRM"):
             return
     self.tab_center.removeTab(index)
     if not tab:
         return
     tab.logout()
     if self.tab_center.count() == 1:
         self.tab_center.setTabsClosable(False)
コード例 #5
0
    def closeEvent(self, event: QCloseEvent) -> None:
        if self.minimize_on_close and not self.need_close:
            self.hide()
            event.ignore()

            # This notification is disabled on Mac since minimizing apps on
            # close is the standard behaviour on this OS.
            if not self.minimize_on_close_notif_already_send and sys.platform != "darwin":
                self.minimize_on_close_notif_already_send = True
                self.systray_notification.emit(
                    "Parsec", _("TEXT_TRAY_PARSEC_STILL_RUNNING_MESSAGE"), 2000
                )
        else:
            if self.config.gui_confirmation_before_close and not self.force_close:
                result = ask_question(
                    self if self.isVisible() else None,
                    _("TEXT_PARSEC_QUIT_TITLE"),
                    _("TEXT_PARSEC_QUIT_INSTRUCTIONS"),
                    [_("ACTION_PARSEC_QUIT_CONFIRM"), _("ACTION_CANCEL")],
                )
                if result != _("ACTION_PARSEC_QUIT_CONFIRM"):
                    event.ignore()
                    self.force_close = False
                    self.need_close = False
                    return

            state = self.saveGeometry()
            self.event_bus.send(CoreEvent.GUI_CONFIG_CHANGED, gui_geometry=state)
            self.close_all_tabs()
            event.accept()
            QApplication.quit()
コード例 #6
0
ファイル: main_window.py プロジェクト: shalevy1/parsec-cloud
    def closeEvent(self, event):
        if self.minimize_on_close and not self.need_close:
            self.hide()
            event.ignore()
            if not self.minimize_on_close_notif_already_send:
                self.minimize_on_close_notif_already_send = True
                self.systray_notification.emit(
                    "Parsec", _("TEXT_TRAY_PARSEC_STILL_RUNNING_MESSAGE"),
                    2000)
        else:
            if self.config.gui_confirmation_before_close and not self.force_close:
                result = ask_question(
                    self if self.isVisible() else None,
                    _("TEXT_PARSEC_QUIT_TITLE"),
                    _("TEXT_PARSEC_QUIT_INSTRUCTIONS"),
                    [_("ACTION_PARSEC_QUIT_CONFIRM"),
                     _("ACTION_CANCEL")],
                )
                if result != _("ACTION_PARSEC_QUIT_CONFIRM"):
                    event.ignore()
                    self.force_close = False
                    self.need_close = False
                    return

            state = self.saveGeometry()
            self.event_bus.send(CoreEvent.GUI_CONFIG_CHANGED,
                                gui_geometry=state)
            self.close_all_tabs()
            event.accept()
            QApplication.quit()
コード例 #7
0
    def _on_import_key(self):
        key_file, _ = QFileDialog.getOpenFileName(
            parent=self,
            caption=translate("ACTION_IMPORT_KEY"),
            filter=translate("IMPORT_KEY_FILTERS"),
            initialFilter=translate("IMPORT_KEY_INITIAL_FILTER"),
        )
        if not key_file:
            return
        new_device = load_device_file(Path(key_file))
        if new_device is None:
            show_error(self, translate("TEXT_INVALID_DEVICE_KEY"))
            return
        rep = ask_question(
            parent=self,
            title=translate("ASK_IMPORT_KEY"),
            message=translate("TEXT_IMPORT_KEY_CONFIRM_organization-user-device").format(
                organization=new_device.organization_id,
                user=new_device.short_user_display,
                device=new_device.device_label,
            ),
            button_texts=(translate("ACTION_IMPORT_YES"), translate("ACTION_IMPORT_NO")),
        )
        if rep == translate("ACTION_IMPORT_YES"):
            key_name = new_device.slughash + ".keys"
            dest = get_devices_dir(self.config.config_dir).joinpath(key_name)
            if self._overwrite_key(dest):

                shutil.copyfile(
                    new_device.key_file_path,
                    os.path.join(get_devices_dir(self.config.config_dir), key_name),
                )
                self.reload_devices()
                self.key_imported.emit()
コード例 #8
0
ファイル: main_window.py プロジェクト: shalevy1/parsec-cloud
 def close_tab(self, index, force=False):
     tab = self.tab_center.widget(index)
     if not force:
         r = _("ACTION_TAB_CLOSE_CONFIRM")
         if tab and tab.is_logged_in:
             r = ask_question(
                 self,
                 _("TEXT_TAB_CLOSE_TITLE"),
                 _("TEXT_TAB_CLOSE_INSTRUCTIONS_device").format(
                     device=
                     f"{tab.core.device.short_user_display} - {tab.core.device.device_display}"
                 ),
                 [_("ACTION_TAB_CLOSE_CONFIRM"),
                  _("ACTION_CANCEL")],
             )
         if r != _("ACTION_TAB_CLOSE_CONFIRM"):
             return
     self.tab_center.removeTab(index)
     if not tab:
         return
     tab.logout()
     self.reload_login_devices()
     if self.tab_center.count() == 1:
         self.tab_center.setTabsClosable(False)
     self._toggle_add_tab_button()
コード例 #9
0
    def showMaximized(self, skip_dialogs=False):
        super().showMaximized()
        QCoreApplication.processEvents()

        # Used with the --diagnose option
        if skip_dialogs:
            return

        # At the very first launch
        if self.config.gui_first_launch:
            r = ask_question(
                self,
                _("TEXT_ERROR_REPORTING_TITLE"),
                _("TEXT_ERROR_REPORTING_INSTRUCTIONS"),
                [_("ACTION_ERROR_REPORTING_ACCEPT"), _("ACTION_NO")],
            )

            # Acknowledge the changes
            self.event_bus.send(
                "gui.config.changed",
                gui_first_launch=False,
                gui_last_version=PARSEC_VERSION,
                telemetry_enabled=r == _("ACTION_ERROR_REPORTING_ACCEPT"),
            )

        # For each parsec update
        if self.config.gui_last_version != PARSEC_VERSION:

            # Ask for acrobat reader workaround
            if (
                platform.system() == "Windows"
                and win_registry.is_acrobat_reader_dc_present()
                and win_registry.get_acrobat_app_container_enabled()
            ):
                r = ask_question(
                    self,
                    _("TEXT_ACROBAT_CONTAINERS_DISABLE_TITLE"),
                    _("TEXT_ACROBAT_CONTAINERS_DISABLE_INSTRUCTIONS"),
                    [_("ACTION_ACROBAT_CONTAINERS_DISABLE_ACCEPT"), _("ACTION_NO")],
                )
                if r == _("ACTION_ACROBAT_CONTAINERS_DISABLE_ACCEPT"):
                    win_registry.set_acrobat_app_container_enabled(False)

            # Acknowledge the changes
            self.event_bus.send("gui.config.changed", gui_last_version=PARSEC_VERSION)

        telemetry.init(self.config)
コード例 #10
0
 def _overwrite_key(self, dest):
     if dest.exists():
         rep = ask_question(
             parent=self,
             title=translate("ASK_OVERWRITE_KEY"),
             message=translate("TEXT_OVERWRITE_KEY"),
             button_texts=(translate("ACTION_OVERWRITE_KEY_YES"), translate("ACTION_IMPORT_NO")),
         )
         return rep == translate("ACTION_OVERWRITE_KEY_YES")
     return True
コード例 #11
0
ファイル: main_window.py プロジェクト: Scille/parsec-cloud
 def _on_manage_keys(self) -> None:
     devices = [device for device in list_available_devices(self.config.config_dir)]
     options = [_("ACTION_CANCEL"), _("ACTION_RECOVER_DEVICE")]
     if len(devices):
         options.append(_("ACTION_CREATE_RECOVERY_DEVICE"))
     result = ask_question(
         self, _("TEXT_DEVICE_RECOVERY_TITLE"), _("TEXT_DEVICE_RECOVERY_QUESTION"), options
     )
     if result == _("ACTION_RECOVER_DEVICE"):
         DeviceRecoveryImportWidget.show_modal(
             self.config, self.jobs_ctx, parent=self, on_finished=self.reload_login_devices
         )
     elif result == _("ACTION_CREATE_RECOVERY_DEVICE"):
         DeviceRecoveryExportWidget.show_modal(self.config, self.jobs_ctx, devices, parent=self)
コード例 #12
0
 def delete_workspace(self, workspace_fs):
     if isinstance(workspace_fs, WorkspaceFSTimestamped):
         self.unmount_workspace(workspace_fs.workspace_id, workspace_fs.timestamp)
         return
     else:
         workspace_name = self.jobs_ctx.run_sync(workspace_fs.get_workspace_name)
         result = ask_question(
             self,
             _("TEXT_WORKSPACE_DELETE_TITLE"),
             _("TEXT_WORKSPACE_DELETE_INSTRUCTIONS_workspace").format(workspace=workspace_name),
             [_("ACTION_DELETE_WORKSPACE_CONFIRM"), _("ACTION_CANCEL")],
         )
         if result != _("ACTION_DELETE_WORKSPACE_CONFIRM"):
             return
コード例 #13
0
ファイル: main_window.py プロジェクト: Scille/parsec-cloud
    def show_window(self, skip_dialogs: bool = False) -> None:
        try:
            if not self.restoreGeometry(self.config.gui_geometry):
                self.showMaximized()
        except TypeError:
            self.showMaximized()

        QCoreApplication.processEvents()

        # Used with the --diagnose option
        if skip_dialogs:
            return

        # At the very first launch
        if self.config.gui_first_launch:
            r = ask_question(
                self,
                _("TEXT_ENABLE_TELEMETRY_TITLE"),
                _("TEXT_ENABLE_TELEMETRY_INSTRUCTIONS"),
                [_("ACTION_ENABLE_TELEMETRY_ACCEPT"), _("ACTION_ENABLE_TELEMETRY_REFUSE")],
                oriented_question=True,
            )

            # Acknowledge the changes
            self.event_bus.send(
                CoreEvent.GUI_CONFIG_CHANGED,
                gui_first_launch=False,
                gui_last_version=PARSEC_VERSION,
                telemetry_enabled=r == _("ACTION_ENABLE_TELEMETRY_ACCEPT"),
            )

        # For each parsec update
        if self.config.gui_last_version and self.config.gui_last_version != PARSEC_VERSION:

            # Update from parsec `<1.14` to `>=1.14`
            if LooseVersion(self.config.gui_last_version) < "1.14":

                # Revert the acrobat reader workaround
                if (
                    sys.platform == "win32"
                    and win_registry.is_acrobat_reader_dc_present()
                    and not win_registry.get_acrobat_app_container_enabled()
                ):
                    win_registry.del_acrobat_app_container_enabled()

            # Acknowledge the changes
            self.event_bus.send(CoreEvent.GUI_CONFIG_CHANGED, gui_last_version=PARSEC_VERSION)

        telemetry.init(self.config)
コード例 #14
0
ファイル: users_widget.py プロジェクト: imbi7py/parsec-cloud
 def revoke_user(self, user_info):
     result = ask_question(
         self,
         _("TEXT_USER_REVOCATION_TITLE"),
         _("TEXT_USER_REVOCATION_INSTRUCTIONS_user").format(user=user_info.short_user_display),
         [_("ACTION_USER_REVOCATION_CONFIRM"), _("ACTION_CANCEL")],
     )
     if result != _("ACTION_USER_REVOCATION_CONFIRM"):
         return
     self.jobs_ctx.submit_job(
         ThreadSafeQtSignal(self, "revoke_success", QtToTrioJob),
         ThreadSafeQtSignal(self, "revoke_error", QtToTrioJob),
         _do_revoke_user,
         core=self.core,
         user_info=user_info,
     )
コード例 #15
0
ファイル: users_widget.py プロジェクト: imbi7py/parsec-cloud
 def cancel_invitation(self, token):
     r = ask_question(
         self,
         _("TEXT_USER_INVITE_CANCEL_INVITE_QUESTION_TITLE"),
         _("TEXT_USER_INVITE_CANCEL_INVITE_QUESTION_CONTENT"),
         [_("TEXT_USER_INVITE_CANCEL_INVITE_ACCEPT"), _("ACTION_NO")],
     )
     if r != _("TEXT_USER_INVITE_CANCEL_INVITE_ACCEPT"):
         return
     self.jobs_ctx.submit_job(
         ThreadSafeQtSignal(self, "cancel_invitation_success", QtToTrioJob),
         ThreadSafeQtSignal(self, "cancel_invitation_error", QtToTrioJob),
         _do_cancel_invitation,
         core=self.core,
         token=token,
     )
コード例 #16
0
    def reencrypt_workspace(self, workspace_id, user_revoked, role_revoked):
        if workspace_id in self.reencrypting or (not user_revoked
                                                 and not role_revoked):
            return

        question = ""
        if user_revoked:
            question += "{}\n".format(
                _("TEXT_WORKSPACE_NEED_REENCRYPTION_BECAUSE_USER_REVOKED"))
        if role_revoked:
            question += "{}\n".format(
                _("TEXT_WORKSPACE_NEED_REENCRYPTION_BECAUSE_USER_REMOVED"))
        question += _("TEXT_WORKSPACE_NEED_REENCRYPTION_INSTRUCTIONS")

        r = ask_question(
            self,
            _("TEXT_WORKSPACE_NEED_REENCRYPTION_TITLE"),
            question,
            [_("ACTION_WORKSPACE_REENCRYPTION_CONFIRM"),
             _("ACTION_CANCEL")],
        )
        if r != _("ACTION_WORKSPACE_REENCRYPTION_CONFIRM"):
            return

        async def _reencrypt(on_progress, workspace_id):
            job = await self.core.user_fs.workspace_start_reencryption(
                workspace_id)
            while True:
                total, done = await job.do_one_batch(size=1)
                on_progress.emit(workspace_id, total, done)
                if total == done:
                    break
            return workspace_id

        self.reencrypting.add(workspace_id)

        self.jobs_ctx.submit_job(
            ThreadSafeQtSignal(self, "workspace_reencryption_success",
                               QtToTrioJob),
            ThreadSafeQtSignal(self, "workspace_reencryption_error",
                               QtToTrioJob),
            _reencrypt,
            on_progress=ThreadSafeQtSignal(self,
                                           "workspace_reencryption_progress",
                                           EntryID, int, int),
            workspace_id=workspace_id,
        )
コード例 #17
0
 def open_files(self):
     files = self.table_files.selected_files()
     if len(files) == 1:
         self.desktop_open_files([files[0].name])
     else:
         result = ask_question(
             self,
             _("TEXT_FILE_OPEN_MULTIPLE_TITLE_count").format(
                 count=len(files)),
             _("TEXT_FILE_OPEN_MULTIPLE_INSTRUCTIONS_count").format(
                 count=len(files)),
             [_("ACTION_FILE_OPEN_MULTIPLE"),
              _("ACTION_CANCEL")],
         )
         if result != _("ACTION_FILE_OPEN_MULTIPLE"):
             return
         self.desktop_open_files([f.name for f in files])
コード例 #18
0
ファイル: main_window.py プロジェクト: Scille/parsec-cloud
 async def _on_finished() -> None:
     nonlocal widget
     # It's safe to access the widget status here since this does not perform a Qt call.
     # But the underlying C++ widget might already be deleted so we should make sure not
     # not do anything Qt related with this widget.
     if not widget.status:
         return
     device, auth_method, password = widget.status
     self.reload_login_devices()
     await self.try_login(device, auth_method, password)
     answer = ask_question(
         self,
         _("TEXT_CLAIM_USER_SUCCESSFUL_TITLE"),
         _("TEXT_CLAIM_USER_SUCCESSFUL"),
         [_("ACTION_CREATE_RECOVERY_DEVICE"), _("ACTION_NO")],
         oriented_question=True,
     )
     if answer == _("ACTION_CREATE_RECOVERY_DEVICE"):
         DeviceRecoveryExportWidget.show_modal(self.config, self.jobs_ctx, [device], self)
コード例 #19
0
ファイル: users_widget.py プロジェクト: Scille/parsec-cloud
 def cancel_invitation(self, token):
     r = ask_question(
         self,
         _("TEXT_USER_INVITE_CANCEL_INVITE_QUESTION_TITLE"),
         _("TEXT_USER_INVITE_CANCEL_INVITE_QUESTION_CONTENT"),
         [
             _("TEXT_USER_INVITE_CANCEL_INVITE_ACCEPT"),
             _("ACTION_ENABLE_TELEMETRY_REFUSE")
         ],
     )
     if r != _("TEXT_USER_INVITE_CANCEL_INVITE_ACCEPT"):
         return
     self.jobs_ctx.submit_job(
         self.cancel_invitation_success,
         self.cancel_invitation_error,
         _do_cancel_invitation,
         core=self.core,
         token=token,
     )
コード例 #20
0
    def on_remove_user_clicked(self, user):
        r = ask_question(
            parent=self,
            title=_("TEXT_WORKSPACE_SHARING_UNSHARE_TITLE"),
            message=_("TEXT_WORKSPACE_SHARING_UNSHARE_INSTRUCTIONS_user").format(user=user),
            button_texts=[_("ACTION_WORKSPACE_UNSHARE_CONFIRM"), _("ACTION_CANCEL")],
        )
        if r != _("ACTION_WORKSPACE_UNSHARE_CONFIRM"):
            return

        self.jobs_ctx.submit_job(
            ThreadSafeQtSignal(self, "unshare_success", QtToTrioJob),
            ThreadSafeQtSignal(self, "unshare_error", QtToTrioJob),
            _do_share_workspace,
            user_fs=self.user_fs,
            workspace_fs=self.workspace_fs,
            user=user,
            role=None,
        )
コード例 #21
0
ファイル: users_widget.py プロジェクト: Scille/parsec-cloud
 def revoke_user(self, user_info):
     result = ask_question(
         self,
         _("TEXT_USER_REVOCATION_TITLE"),
         _("TEXT_USER_REVOCATION_INSTRUCTIONS_user").format(
             user=user_info.short_user_display),
         [_("ACTION_USER_REVOCATION_CONFIRM"),
          _("ACTION_CANCEL")],
         oriented_question=True,
         dangerous_yes=True,
     )
     if result != _("ACTION_USER_REVOCATION_CONFIRM"):
         return
     self.jobs_ctx.submit_job(
         self.revoke_success,
         self.revoke_error,
         _do_revoke_user,
         core=self.core,
         user_info=user_info,
     )
コード例 #22
0
    def closeEvent(self, event):
        if self.minimize_on_close and not self.need_close:
            self.hide()
            event.ignore()
            self.systray_notification.emit("Parsec", _("TEXT_TRAY_PARSEC_STILL_RUNNING_MESSAGE"))
        else:
            if self.config.gui_confirmation_before_close and not self.force_close:
                result = ask_question(
                    self if self.isVisible() else None,
                    _("TEXT_PARSEC_QUIT_TITLE"),
                    _("TEXT_PARSEC_QUIT_INSTRUCTIONS"),
                    [_("ACTION_PARSEC_QUIT_CONFIRM"), _("ACTION_CANCEL")],
                )
                if result != _("ACTION_PARSEC_QUIT_CONFIRM"):
                    event.ignore()
                    self.force_close = False
                    self.need_close = False
                    return

            self.close_all_tabs()
            event.accept()
            QApplication.quit()
コード例 #23
0
 def open_files(self):
     files = self.table_files.selected_files()
     if len(files) == 1:
         if not self.open_file(files[0][2]):
             show_error(
                 self,
                 _("TEXT_FILE_OPEN_ERROR_file").format(file=files[0][2]))
     else:
         result = ask_question(
             self,
             _("TEXT_FILE_OPEN_MULTIPLE_TITLE_count").format(
                 count=len(files)),
             _("TEXT_FILE_OPEN_MULTIPLE_INSTRUCTIONS_count").format(
                 count=len(files)),
             [_("ACTION_FILE_OPEN_MULTIPLE"),
              _("ACTION_CANCEL")],
         )
         if result != _("ACTION_FILE_OPEN_MULTIPLE"):
             return
         success = True
         for f in files:
             success &= self.open_file(f[2])
         if not success:
             show_error(self, _("TEXT_FILE_OPEN_MULTIPLE_ERROR"))
コード例 #24
0
 def delete_workspace(self, workspace_fs):
     if isinstance(workspace_fs, WorkspaceFSTimestamped):
         self.jobs_ctx.submit_job(
             ThreadSafeQtSignal(self, "workspace_unmounted", QtToTrioJob),
             ThreadSafeQtSignal(self, "mount_error", QtToTrioJob),
             _do_workspace_unmount,
             core=self.core,
             workspace_id=workspace_fs.workspace_id,
             timestamp=workspace_fs.timestamp,
         )
         return
     else:
         workspace_name = self.jobs_ctx.run_sync(
             workspace_fs.get_workspace_name)
         result = ask_question(
             self,
             _("TEXT_WORKSPACE_DELETE_TITLE"),
             _("TEXT_WORKSPACE_DELETE_INSTRUCTIONS_workspace").format(
                 workspace=workspace_name),
             [_("ACTION_DELETE_WORKSPACE_CONFIRM"),
              _("ACTION_CANCEL")],
         )
         if result != _("ACTION_DELETE_WORKSPACE_CONFIRM"):
             return
コード例 #25
0
    def reencrypt_workspace(self, workspace_id, user_revoked, role_revoked,
                            reencryption_already_in_progress):
        if workspace_id in self.reencrypting or (
                not user_revoked and not role_revoked
                and not reencryption_already_in_progress):
            return

        question = ""
        if user_revoked:
            question += "{}\n".format(
                _("TEXT_WORKSPACE_NEED_REENCRYPTION_BECAUSE_USER_REVOKED"))
        if role_revoked:
            question += "{}\n".format(
                _("TEXT_WORKSPACE_NEED_REENCRYPTION_BECAUSE_USER_REMOVED"))
        question += _("TEXT_WORKSPACE_NEED_REENCRYPTION_INSTRUCTIONS")

        r = ask_question(
            self,
            _("TEXT_WORKSPACE_NEED_REENCRYPTION_TITLE"),
            question,
            [_("ACTION_WORKSPACE_REENCRYPTION_CONFIRM"),
             _("ACTION_CANCEL")],
        )
        if r != _("ACTION_WORKSPACE_REENCRYPTION_CONFIRM"):
            return

        @contextmanager
        def _handle_fs_errors():
            try:
                yield
            except FSBackendOfflineError as exc:
                raise JobResultError(ret=workspace_id,
                                     status="offline-backend",
                                     origin=exc)
            except FSWorkspaceNoAccess as exc:
                raise JobResultError(ret=workspace_id,
                                     status="access-error",
                                     origin=exc)
            except FSWorkspaceNotFoundError as exc:
                raise JobResultError(ret=workspace_id,
                                     status="not-found",
                                     origin=exc)
            except FSError as exc:
                raise JobResultError(ret=workspace_id,
                                     status="fs-error",
                                     origin=exc)

        async def _reencrypt(on_progress, workspace_id):
            with _handle_fs_errors():
                if reencryption_already_in_progress:
                    job = await self.core.user_fs.workspace_continue_reencryption(
                        workspace_id)
                else:
                    job = await self.core.user_fs.workspace_start_reencryption(
                        workspace_id)
            while True:
                with _handle_fs_errors():
                    total, done = await job.do_one_batch()
                on_progress.emit(workspace_id, total, done)
                if total == done:
                    break
            return workspace_id

        self.reencrypting.add(workspace_id)

        self.jobs_ctx.submit_job(
            ThreadSafeQtSignal(self, "workspace_reencryption_success",
                               QtToTrioJob),
            ThreadSafeQtSignal(self, "workspace_reencryption_error",
                               QtToTrioJob),
            _reencrypt,
            on_progress=ThreadSafeQtSignal(self,
                                           "workspace_reencryption_progress",
                                           EntryID, int, int),
            workspace_id=workspace_id,
        )
コード例 #26
0
    async def make_enrollment_request(self):
        # Catch all errors
        try:
            self.button_ask_to_join.setEnabled(False)

            # Try the enrollment submission without the force flag
            try:
                self.context = await self.context.submit(
                    config_dir=self.config.config_dir,
                    requested_device_label=DeviceLabel(
                        self.line_edit_device.text()),
                    force=False,
                )

            # This certificate has already been submitted
            except PkiEnrollmentSubmitCertificateAlreadySubmittedError:

                # Prompt for permission to force
                answer = ask_question(
                    self,
                    translate("TEXT_ENROLLMENT_SUBMIT_ALREADY_EXISTS_TITLE"),
                    translate(
                        "TEXT_ENROLLMENT_SUBMIT_ALREADY_EXISTS_QUESTION"),
                    [
                        translate("ACTION_ENROLLMENT_FORCE"),
                        translate("ACTION_NO")
                    ],
                    oriented_question=True,
                )

                # No permission, we're done
                if answer != translate("ACTION_ENROLLMENT_FORCE"):
                    return

                # Submit the enrollment with the force flag
                self.context = await self.context.submit(
                    config_dir=self.config.config_dir,
                    requested_device_label=DeviceLabel(
                        self.line_edit_device.text()),
                    force=True,
                )
        except PkiEnrollmentCertificatePinCodeUnavailableError:
            # User declined to provide a PIN code (cancelled the prompt). We do nothing.
            pass
        # Email already attributed to an active user
        except PkiEnrollmentSubmitCertificateEmailAlreadyUsedError as exc:
            show_error(self,
                       translate("TEXT_ENROLLMENT_SUBMIT_FAILED_EMAIL_USED"),
                       exc)
        # Enrollment submission failed
        except Exception as exc:
            show_error(self, translate("TEXT_ENROLLMENT_SUBMIT_FAILED"), exc)

        # Enrollment submission is a success
        else:
            self.status = True
            self.dialog.accept()

        # In all cases, restore the button status
        finally:
            self.button_ask_to_join.setEnabled(True)
コード例 #27
0
    def show_window(
        self, skip_dialogs: bool = False, invitation_link: Optional[str] = None
    ) -> None:
        try:
            if not self.restoreGeometry(self.config.gui_geometry):
                self.showMaximized()
        except TypeError:
            self.showMaximized()

        QCoreApplication.processEvents()

        # Used with the --diagnose option
        if skip_dialogs:
            return

        # At the very first launch
        if self.config.gui_first_launch:
            r = ask_question(
                self,
                _("TEXT_ENABLE_TELEMETRY_TITLE"),
                _("TEXT_ENABLE_TELEMETRY_INSTRUCTIONS"),
                [_("ACTION_ENABLE_TELEMETRY_ACCEPT"), _("ACTION_ENABLE_TELEMETRY_REFUSE")],
                oriented_question=True,
            )

            # Acknowledge the changes
            self.event_bus.send(
                CoreEvent.GUI_CONFIG_CHANGED,
                gui_first_launch=False,
                gui_last_version=PARSEC_VERSION,
                telemetry_enabled=r == _("ACTION_ENABLE_TELEMETRY_ACCEPT"),
            )

        # For each parsec update
        if self.config.gui_last_version and self.config.gui_last_version != PARSEC_VERSION:

            # Update from parsec `<1.14` to `>=1.14`
            if LooseVersion(self.config.gui_last_version) < "1.14":

                # Revert the acrobat reader workaround
                if (
                    sys.platform == "win32"
                    and win_registry.is_acrobat_reader_dc_present()
                    and not win_registry.get_acrobat_app_container_enabled()
                ):
                    win_registry.del_acrobat_app_container_enabled()

            # Acknowledge the changes
            self.event_bus.send(CoreEvent.GUI_CONFIG_CHANGED, gui_last_version=PARSEC_VERSION)

        telemetry.init(self.config)

        devices = list_available_devices(self.config.config_dir)
        if not len(devices) and not invitation_link:
            r = ask_question(
                self,
                _("TEXT_KICKSTART_PARSEC_WHAT_TO_DO_TITLE"),
                _("TEXT_KICKSTART_PARSEC_WHAT_TO_DO_INSTRUCTIONS"),
                [
                    _("ACTION_NO_DEVICE_CREATE_ORGANIZATION"),
                    _("ACTION_NO_DEVICE_JOIN_ORGANIZATION"),
                ],
                radio_mode=True,
            )
            if r == _("ACTION_NO_DEVICE_JOIN_ORGANIZATION"):
                self._on_join_org_clicked()
            elif r == _("ACTION_NO_DEVICE_CREATE_ORGANIZATION"):
                self._on_create_org_clicked()