示例#1
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:

            def _on_open_file_question_finished(return_code, answer):
                if return_code and answer == _("ACTION_FILE_OPEN_MULTIPLE"):
                    success = True
                    for f in files:
                        success &= self.open_file(f[2])
                    if not success:
                        show_error(self, _("TEXT_FILE_OPEN_MULTIPLE_ERROR"))

            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")],
                on_finished=_on_open_file_question_finished,
            )
示例#2
0
    def close_tab(self, index, force=False):
        def _close_tab(logged):
            self.tab_center.removeTab(index)
            if logged:
                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()

        tab = self.tab_center.widget(index)
        if not force:
            if tab and tab.is_logged_in:

                def _on_tab_close_question_finished(return_code, answer):
                    if return_code and answer == _("ACTION_TAB_CLOSE_CONFIRM"):
                        _close_tab(True)

                ask_question(
                    self,
                    _("TEXT_TAB_CLOSE_TITLE"),
                    _("TEXT_TAB_CLOSE_INSTRUCTIONS_device").format(
                        device=
                        f"{tab.client.device.short_user_display} - {tab.client.device.device_display}"
                    ),
                    [_("ACTION_TAB_CLOSE_CONFIRM"),
                     _("ACTION_CANCEL")],
                    on_finished=_on_tab_close_question_finished,
                )
            elif tab:
                _close_tab(False)
        elif tab:
            _close_tab(tab.is_logged_in)
示例#3
0
    def show_window(self, skip_dialogs=False, invitation_link=""):
        self.show()
        try:
            if not self.restoreGeometry(self.config.gui_geometry):
                self.resize_standard()
        except TypeError:
            self.resize_standard()

        QCoreApplication.processEvents()

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

        # At the very first launch
        if self.config.gui_first_launch:
            self.event_bus.send(
                ClientEvent.GUI_CONFIG_CHANGED,
                gui_first_launch=False,
                gui_last_version=GUARDATA_VERSION,
            )

        # For each guardata update
        if self.config.gui_last_version and self.config.gui_last_version != GUARDATA_VERSION:

            # Acknowledge the changes
            self.event_bus.send(ClientEvent.GUI_CONFIG_CHANGED,
                                gui_last_version=GUARDATA_VERSION)

        devices = list_available_devices(self.config.config_dir)
        if not len(devices) and not invitation_link and platform != "darwin":
            # Add some refresh of async sleep
            # ELse should start once the main window is fully painted (catch ready event)
            self.show_top()

            def _on_bootstrap_question_finished(return_code, answer):
                if not return_code:
                    return
                if answer == _("ACTION_NO_DEVICE_JOIN_ORGANIZATION"):
                    self._on_join_org_clicked()
                elif answer == _("ACTION_NO_DEVICE_CREATE_ORGANIZATION"):
                    self._on_create_org_clicked()

            ask_question(
                self,
                _("TEXT_KICKSTART_GUARDATA_WHAT_TO_DO_TITLE"),
                _("TEXT_KICKSTART_GUARDATA_WHAT_TO_DO_INSTRUCTIONS"),
                [
                    _("ACTION_NO_DEVICE_CREATE_ORGANIZATION"),
                    _("ACTION_NO_DEVICE_JOIN_ORGANIZATION"),
                ],
                on_finished=_on_bootstrap_question_finished,
                radio_mode=True,
            )
示例#4
0
    def revoke_user(self, user_info):
        def _on_revoke_question_finished(return_code, answer):
            if return_code and answer == _("ACTION_USER_REVOCATION_CONFIRM"):
                self.jobs_ctx.submit_job(
                    ThreadSafeQtSignal(self, "revoke_success", QtToTrioJob),
                    ThreadSafeQtSignal(self, "revoke_error", QtToTrioJob),
                    _do_revoke_user,
                    client=self.client,
                    user_info=user_info,
                )

        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")],
            on_finished=_on_revoke_question_finished,
        )
示例#5
0
    def closeEvent(self, event):
        def _on_closing_question_finished(return_code, answer):
            if not return_code or answer != _("ACTION_GUARDATA_QUIT_CONFIRM"):
                event.ignore()
                self.force_close = False
                self.need_close = False
            else:
                state = self.saveGeometry()
                self.event_bus.send(ClientEvent.GUI_CONFIG_CHANGED,
                                    gui_geometry=state)
                self.close_all_tabs()
                event.accept()
                QApplication.quit()

        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(
                    "guardata", _("TEXT_TRAY_GUARDATA_STILL_RUNNING_MESSAGE"),
                    2000)
        else:
            tab = self.tab_center.widget(0)
            if self.tab_center.count() == 1 and (tab and not tab.is_logged_in):
                self.force_close = True
            if self.config.gui_confirmation_before_close and not self.force_close:
                ask_question(
                    self if self.isVisible() else None,
                    _("TEXT_GUARDATA_QUIT_TITLE"),
                    _("TEXT_GUARDATA_QUIT_INSTRUCTIONS"),
                    [_("ACTION_GUARDATA_QUIT_CONFIRM"),
                     _("ACTION_CANCEL")],
                    on_finished=_on_closing_question_finished,
                )
                event.ignore()
            else:
                _on_closing_question_finished(
                    1, _("ACTION_GUARDATA_QUIT_CONFIRM"))
示例#6
0
    def cancel_invitation(self, token):
        def _on_cancel_invitation_question_finished(return_code, answer):
            if return_code and answer == _(
                    "TEXT_USER_INVITE_CANCEL_INVITE_ACCEPT"):
                self.jobs_ctx.submit_job(
                    ThreadSafeQtSignal(self, "cancel_invitation_success",
                                       QtToTrioJob),
                    ThreadSafeQtSignal(self, "cancel_invitation_error",
                                       QtToTrioJob),
                    _do_cancel_invitation,
                    client=self.client,
                    token=token,
                )

        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")],
            on_finished=_on_cancel_invitation_question_finished,
        )
示例#7
0
    def delete_files(self):
        files = self.table_files.selected_files()

        def _on_delete_file_question_finished(return_code, answer):
            if return_code and (answer == _("ACTION_FILE_DELETE")
                                or answer == _("ACTION_FILE_DELETE_MULTIPLE")):
                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],
                )

        if len(files) == 1:
            ask_question(
                self,
                _("TEXT_FILE_DELETE_TITLE"),
                _("TEXT_FILE_DELETE_INSTRUCTIONS_name").format(
                    name=files[0].name),
                [_("ACTION_FILE_DELETE"),
                 _("ACTION_CANCEL")],
                on_finished=_on_delete_file_question_finished,
            )
        else:
            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")],
                on_finished=_on_delete_file_question_finished,
            )
示例#8
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

        def _on_workspace_reencryption_question_finished(return_code, answer):
            if not return_code or answer != _(
                    "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.client.user_fs.workspace_continue_reencryption(
                            workspace_id)
                    else:
                        job = await self.client.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,
            )

        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")

        ask_question(
            self,
            _("TEXT_WORKSPACE_NEED_REENCRYPTION_TITLE"),
            question,
            [_("ACTION_WORKSPACE_REENCRYPTION_CONFIRM"),
             _("ACTION_CANCEL")],
            on_finished=_on_workspace_reencryption_question_finished,
        )