Beispiel #1
0
    def reload_workspace_name(self, workspace_name):
        self.workspace_name = workspace_name
        display = workspace_name

        if not self.timestamped:
            if not self.is_shared:
                shared_message = _("TEXT_WORKSPACE_IS_PRIVATE")
            elif not self.is_owner:
                shared_message = _("TEXT_WORKSPACE_IS_OWNED_BY_user").format(
                    user=self.owner.short_user_display)
            elif len(self.others) == 1:
                (user, ) = self.others
                shared_message = _("TEXT_WORKSPACE_IS_SHARED_WITH_user"
                                   ).format(user=user.short_user_display)
            else:
                n = len(self.others)
                assert n > 1
                shared_message = _(
                    "TEXT_WORKSPACE_IS_SHARED_WITH_n_USERS").format(n=n)
            display += " ({})".format(shared_message)
        else:
            display += "-" + _("TEXT_WORKSPACE_IS_TIMESTAMPED_date").format(
                date=format_datetime(self.workspace_fs.timestamp))
        self.label_title.setToolTip(display)
        if len(display) > 20:
            display = display[:20] + "..."
        self.label_title.setText(display)
Beispiel #2
0
 def _on_claimer_error(self, job):
     if self.claimer_job is not job:
         return
     assert job
     assert job.is_finished()
     assert job.status != "ok"
     # This callback can be called after the creation of a new claimer job in the case
     # of a restart, due to Qt signals being called later.
     if job.status == "cancelled":
         return
     # Safety net for concurrency issues
     if self.claimer_job is not job:
         return
     self.claimer_job = None
     msg = ""
     exc = None
     if job.status == "invitation-not-found":
         msg = _("TEXT_CLAIM_DEVICE_INVITATION_NOT_FOUND")
     elif self.claim_job.status == "backend-not-available":
         msg = _("TEXT_INVITATION_BACKEND_NOT_AVAILABLE")
     else:
         msg = _("TEXT_CLAIM_DEVICE_UNKNOWN_ERROR")
     if job.exc:
         exc = job.exc.params.get("origin", None)
     self.rejected.emit()
     show_error(self, msg, exception=exc)
Beispiel #3
0
    def __init__(self, jobs_ctx, greeter):
        super().__init__()
        self.setupUi(self)
        self.jobs_ctx = jobs_ctx
        self.greeter = greeter
        self.get_requests_job = None
        self.create_user_job = None

        self.widget_info.hide()
        self.label_waiting.show()

        self.line_edit_user_full_name.textChanged.connect(self.check_infos)
        self.line_edit_user_email.textChanged.connect(self.check_infos)
        self.line_edit_device.textChanged.connect(self.check_infos)

        # self.combo_profile.addItem(_("TEXT_USER_PROFILE_OUTSIDER"), UserProfile.OUTSIDER)
        self.combo_profile.addItem(_("TEXT_USER_PROFILE_STANDARD"),
                                   UserProfile.STANDARD)
        self.combo_profile.addItem(_("TEXT_USER_PROFILE_ADMIN"),
                                   UserProfile.ADMIN)
        self.combo_profile.setCurrentIndex(0)

        self.get_requests_success.connect(self._on_get_requests_success)
        self.get_requests_error.connect(self._on_get_requests_error)
        self.create_user_success.connect(self._on_create_user_success)
        self.create_user_error.connect(self._on_create_user_error)
        self.button_create_user.clicked.connect(self._on_create_user_clicked)

        self.get_requests_job = self.jobs_ctx.submit_job(
            ThreadSafeQtSignal(self, "get_requests_success", QtToTrioJob),
            ThreadSafeQtSignal(self, "get_requests_error", QtToTrioJob),
            self.greeter.get_claim_requests,
        )
Beispiel #4
0
    def _on_connection_state_changed(self,
                                     status,
                                     status_exc,
                                     allow_systray=True):
        text = None
        icon = None
        tooltip = None
        notif = None
        disconnected = None

        self.menu.label_organization_name.hide()
        self.menu.label_organization_size.clear()
        if status in (BackendConnStatus.READY, BackendConnStatus.INITIALIZING):
            if status == BackendConnStatus.READY and self.client.device.is_admin:
                self._get_organization_stats()
            tooltip = text = _("TEXT_BACKEND_STATE_CONNECTED")
            icon = QPixmap(":/icons/images/material/cloud_queue.svg")

        elif status == BackendConnStatus.LOST:
            tooltip = text = _("TEXT_BACKEND_STATE_DISCONNECTED")
            icon = QPixmap(":/icons/images/material/cloud_off.svg")
            disconnected = True

        elif status == BackendConnStatus.REFUSED:
            disconnected = True
            cause = status_exc.__cause__
            if isinstance(cause, HandshakeAPIVersionError):
                tooltip = _("TEXT_BACKEND_STATE_API_MISMATCH_versions").format(
                    versions=", ".join(
                        [str(v.version) for v in cause.backend_versions]))
            elif isinstance(cause, HandshakeRevokedDevice):
                tooltip = _("TEXT_BACKEND_STATE_REVOKED_DEVICE")
                notif = ("REVOKED", tooltip)
                self.new_notification.emit(*notif)
            elif isinstance(cause, HandshakeOrganizationExpired):
                tooltip = _("TEXT_BACKEND_STATE_ORGANIZATION_EXPIRED")
            else:
                tooltip = _("TEXT_BACKEND_STATE_UNKNOWN")
            text = _("TEXT_BACKEND_STATE_DISCONNECTED")
            icon = QPixmap(":/icons/images/material/cloud_off.svg")
            notif = ("WARNING", tooltip)

        elif status == BackendConnStatus.CRASHED:
            text = _("TEXT_BACKEND_STATE_DISCONNECTED")
            tooltip = _("TEXT_BACKEND_STATE_CRASHED_cause").format(
                cause=str(status_exc.__cause__))
            icon = QPixmap(":/icons/images/material/cloud_off.svg")
            notif = ("ERROR", tooltip)
            disconnected = True

        self.menu.set_connection_state(text, tooltip, icon)
        if notif:
            self.new_notification.emit(*notif)
        if allow_systray and disconnected:
            self.systray_notification.emit(
                "guardata",
                _("TEXT_SYSTRAY_BACKEND_DISCONNECT_organization").format(
                    organization=self.client.device.organization_id),
                5000,
            )
Beispiel #5
0
 def _define_shortcuts(self):
     self.shortcut_close = QShortcut(QKeySequence(QKeySequence.Close), self)
     self.shortcut_close.activated.connect(
         self._shortcut_proxy(self.close_current_tab))
     self.shortcut_new_tab = QShortcut(QKeySequence(QKeySequence.AddTab),
                                       self)
     self.shortcut_new_tab.activated.connect(
         self._shortcut_proxy(self._on_add_instance_clicked))
     self.shortcut_settings = QShortcut(QKeySequence(_("Ctrl+K")), self)
     self.shortcut_settings.activated.connect(
         self._shortcut_proxy(self._show_settings))
     self.shortcut_menu = QShortcut(QKeySequence(_("Alt+E")), self)
     self.shortcut_menu.activated.connect(
         self._shortcut_proxy(self._show_menu))
     # self.shortcut_help = QShortcut(QKeySequence(QKeySequence.HelpContents), self)
     # self.shortcut_help.activated.connect(self._shortcut_proxy(self._on_show_doc_clicked))
     self.shortcut_quit = QShortcut(QKeySequence(QKeySequence.Quit), self)
     self.shortcut_quit.activated.connect(
         self._shortcut_proxy(self.close_app))
     self.shortcut_create_org = QShortcut(QKeySequence(QKeySequence.New),
                                          self)
     self.shortcut_create_org.activated.connect(
         self._shortcut_proxy(self._on_create_org_clicked))
     self.shortcut_join_org = QShortcut(QKeySequence(QKeySequence.Open),
                                        self)
     self.shortcut_join_org.activated.connect(
         self._shortcut_proxy(self._on_join_org_clicked))
     shortcut = QShortcut(QKeySequence(QKeySequence.NextChild), self)
     shortcut.activated.connect(self._shortcut_proxy(self._cycle_tabs(1)))
     shortcut = QShortcut(QKeySequence(QKeySequence.PreviousChild), self)
     shortcut.activated.connect(self._shortcut_proxy(self._cycle_tabs(-1)))
Beispiel #6
0
    def __init__(self, jobs_ctx, greeter, invite_addr, client):
        super().__init__()
        self.setupUi(self)
        self.jobs_ctx = jobs_ctx
        self.greeter = greeter
        self.invite_addr = invite_addr
        self.client = client

        self.wait_peer_job = None
        self.wait_peer_success.connect(self._on_wait_peer_success)
        self.wait_peer_error.connect(self._on_wait_peer_error)
        self.send_email_success.connect(self._on_send_email_success)
        self.send_email_error.connect(self._on_send_email_error)
        self.button_start.clicked.connect(self._on_button_start_clicked)
        self.button_send_email.clicked.connect(
            self._on_button_send_email_clicked)
        # Hide the send email button if the user has no human_handle (hand hence no email)
        if not self.client.device.human_handle:
            self.button_send_email.hide()
            self.label_instructions.setText(
                _("TEXT_GREET_DEVICE_INSTRUCTIONS_NO_EMAIL"))
        else:
            self.label_instructions.setText(
                _("TEXT_GREET_DEVICE_INSTRUCTIONS_email").format(
                    email=self.client.device.human_handle.email))
        self.button_copy_addr.clicked.connect(self._on_copy_addr_clicked)
Beispiel #7
0
    def user_info(self, val):
        profiles_txt = {
            UserProfile.OUTSIDER: _("TEXT_USER_PROFILE_OUTSIDER"),
            UserProfile.STANDARD: _("TEXT_USER_PROFILE_STANDARD"),
            UserProfile.ADMIN: _("TEXT_USER_PROFILE_ADMIN"),
        }

        self._user_info = val
        if self.user_info.is_revoked:
            self.setToolTip(_("TEXT_USER_IS_REVOKED"))
            self.widget.setStyleSheet("background-color: #DDDDDD;")
        else:
            self.setToolTip("")
            self.widget.setStyleSheet("background-color: #FFFFFF;")
        if self.user_info.human_handle:
            self.label_email.setText(
                ensure_string_size(self.user_info.human_handle.email, 260,
                                   self.label_email.font()))
            self.label_email.setToolTip(self.user_info.human_handle.email)

        self.label_username.setText(
            ensure_string_size(self.user_info.short_user_display, 260,
                               self.label_username.font()))
        self.label_username.setToolTip(self.user_info.short_user_display)
        self.label_role.setText(profiles_txt[self.user_info.profile])
Beispiel #8
0
 def _on_rename_error(self, job):
     if job.exc.params.get("multi"):
         show_error(self,
                    _("TEXT_FILE_RENAME_MULTIPLE_ERROR"),
                    exception=job.exc)
     else:
         show_error(self, _("TEXT_FILE_RENAME_ERROR"), exception=job.exc)
Beispiel #9
0
        def _on_url_input_finished(return_code, url):
            if not return_code or url is None:
                return
            if url == "":
                show_error(self, _("TEXT_JOIN_ORG_INVALID_URL"))
                return

            action_addr = None
            try:
                action_addr = BackendActionAddr.from_url(url.strip())
            except ValueError as exc:
                show_error(self, _("TEXT_INVALID_URL"), exception=exc)
                return

            if isinstance(action_addr, BackendOrganizationBootstrapAddr):
                self._on_bootstrap_org_clicked(action_addr)
            elif isinstance(action_addr, BackendInvitationAddr):
                if action_addr.invitation_type == InvitationType.USER:
                    self._on_claim_user_clicked(action_addr)
                elif action_addr.invitation_type == InvitationType.DEVICE:
                    self._on_claim_device_clicked(action_addr)
                else:
                    show_error(self, _("TEXT_INVALID_URL"))
            else:
                show_error(self, _("TEXT_INVALID_URL"))
Beispiel #10
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,
            )
Beispiel #11
0
 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"))
Beispiel #12
0
 def on_tab_state_changed(self, tab, state):
     idx = self.tab_center.indexOf(tab)
     if idx == -1:
         return
     if state == "login":
         if self._get_login_tab_index() != -1:
             self.tab_center.removeTab(idx)
         else:
             self.tab_center.setTabToolTip(
                 idx, _("TEXT_TAB_TITLE_LOG_IN_SCREEN"))
             self.tab_center.setTabText(idx,
                                        _("TEXT_TAB_TITLE_LOG_IN_SCREEN"))
             self.tab_center.setStyleSheet(
                 "QTabBar::tab {min-width:7em;padding:4px;}")
     elif state == "logout":
         self.tab_center.removeTab(idx)
         idx = self._get_login_tab_index()
         if idx == -1:
             self.add_instance()
         else:
             tab_widget = self.tab_center.widget(idx)
             log_widget = None if not tab_widget else tab_widget.get_login_widget(
             )
             if log_widget:
                 log_widget.reload_devices()
     elif state == "connected":
         device = tab.current_device
         tab_name = (
             f"{device.organization_id} - {device.short_user_display} - {device.device_display}"
         )
         self.tab_center.setTabToolTip(idx, tab_name)
         self.tab_center.setTabText(idx, tab_name)
     if self.tab_center.count() == 1:
         self.tab_center.setTabsClosable(False)
     self._toggle_add_tab_button()
Beispiel #13
0
 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()
Beispiel #14
0
    def add_instance(self, start_arg: Optional[str] = None):
        action_addr = None
        if start_arg:
            try:
                action_addr = BackendActionAddr.from_url(start_arg)
            except ValueError as exc:
                show_error(self, _("TEXT_INVALID_URL"), exception=exc)

        # Do not open a new logging widget if the organisation is already opened
        if (action_addr
                and isinstance(action_addr, BackendOrganizationFileLinkAddr)
                and self.tab_center.count()):
            self.go_to_file_link(action_addr)
            return

        self.switch_to_login_tab()

        self.show_top()
        if action_addr and isinstance(action_addr,
                                      BackendOrganizationFileLinkAddr):
            # Organization is not connected, login is required
            return
        elif action_addr:
            if isinstance(action_addr, BackendOrganizationBootstrapAddr):
                self._on_bootstrap_org_clicked(action_addr)
            elif isinstance(action_addr, BackendInvitationAddr):
                if action_addr.invitation_type == InvitationType.USER:
                    self._on_claim_user_clicked(action_addr)
                elif action_addr.invitation_type == InvitationType.DEVICE:
                    self._on_claim_device_clicked(action_addr)
                else:
                    show_error(self, _("TEXT_INVALID_URL"))
                    return
Beispiel #15
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)
Beispiel #16
0
    def goto_file_clicked(self):
        def _on_file_link_input_finished(return_code, file_link):
            if not return_code or not file_link:
                return
            url = None
            try:
                url = BackendOrganizationFileLinkAddr.from_url(file_link)
            except ValueError as exc:
                show_error(self,
                           _("TEXT_WORKSPACE_GOTO_FILE_LINK_INVALID_LINK"),
                           exception=exc)
                return

            for widget in self._iter_workspace_buttons():
                if widget.workspace_fs.workspace_id == url.workspace_id:
                    self.load_workspace(widget.workspace_fs,
                                        path=url.path,
                                        selected=True)
                    return
            show_error(self,
                       _("TEXT_WORKSPACE_GOTO_FILE_LINK_WORKSPACE_NOT_FOUND"))

        get_text_input(
            self,
            _("TEXT_WORKSPACE_GOTO_FILE_LINK_TITLE"),
            _("TEXT_WORKSPACE_GOTO_FILE_LINK_INSTRUCTIONS"),
            placeholder=_("TEXT_WORKSPACE_GOTO_FILE_LINK_PLACEHOLDER"),
            default_text="",
            button_text=_("ACTION_GOTO_FILE_LINK"),
            on_finished=_on_file_link_input_finished,
        )
Beispiel #17
0
    def login_with_password(self, key_file, password):
        message = None
        exception = None
        try:
            device = load_device_with_password(key_file, password)
            if guardataApp.is_device_connected(
                    device.organization_addr.organization_id,
                    device.device_id):
                message = _("TEXT_LOGIN_ERROR_ALREADY_CONNECTED")
            else:
                self.start_client(device)
        except LocalDeviceError as exc:
            message = _("TEXT_LOGIN_ERROR_AUTHENTICATION_FAILED")
            exception = exc

        except (RuntimeError, MountpointConfigurationError,
                MountpointDriverCrash) as exc:
            message = _("TEXT_LOGIN_MOUNTPOINT_ERROR")
            exception = exc

        except Exception as exc:
            message = _("TEXT_LOGIN_UNKNOWN_ERROR")
            exception = exc
            logger.exception("Unhandled error during login")
        finally:
            if message:
                show_error(self, message, exception=exception)
                self.login_failed.emit()
Beispiel #18
0
 def on_client_run_error(self):
     assert self.running_client_job.is_finished()
     if self.client:
         self.client.event_bus.disconnect(ClientEvent.GUI_CONFIG_CHANGED,
                                          self.on_client_config_updated)
     if self.running_client_job.status is not None:
         if isinstance(self.running_client_job.exc, HandshakeRevokedDevice):
             show_error(
                 self,
                 _("TEXT_LOGIN_ERROR_DEVICE_REVOKED"),
                 exception=self.running_client_job.exc,
             )
         elif isinstance(self.running_client_job.exc,
                         MountpointWinfspNotAvailable):
             show_error(
                 self,
                 _("TEXT_LOGIN_ERROR_WINFSP_NOT_AVAILABLE"),
                 exception=self.running_client_job.exc,
             )
         elif isinstance(self.running_client_job.exc,
                         MountpointFuseNotAvailable):
             show_error(
                 self,
                 _("TEXT_LOGIN_ERROR_FUSE_NOT_AVAILABLE"),
                 exception=self.running_client_job.exc,
             )
         else:
             logger.exception("Unhandled error",
                              exc_info=self.running_client_job.exc)
             show_error(self,
                        _("TEXT_LOGIN_UNKNOWN_ERROR"),
                        exception=self.running_client_job.exc)
     self.running_client_job = None
     self.logged_out.emit()
Beispiel #19
0
 def show_context_menu(self, pos):
     global_pos = self.mapToGlobal(pos)
     menu = QMenu(self)
     action = menu.addAction(_("ACTION_USER_INVITE_COPY_ADDR"))
     action.triggered.connect(self.copy_addr)
     action = menu.addAction(_("ACTION_USER_INVITE_COPY_EMAIL"))
     action.triggered.connect(self.copy_email)
     menu.exec_(global_pos)
Beispiel #20
0
 def on_create_error(self, job):
     if job.status == "invalid-name":
         show_error(self,
                    _("TEXT_WORKSPACE_CREATE_NEW_INVALID_NAME"),
                    exception=job.exc)
     else:
         show_error(self,
                    _("TEXT_WORKSPACE_CREATE_NEW_UNKNOWN_ERROR"),
                    exception=job.exc)
Beispiel #21
0
 def switch_icon(self):
     icon = self._draw_pixmap(self.source, self.isSelected(), self.is_synced, self.is_confined)
     self.setIcon(QIcon(icon))
     if self.is_confined:
         self.setToolTip(_("TEXT_FILE_ITEM_IS_CONFINED_TOOLTIP"))
     elif self.is_synced:
         self.setToolTip(_("TEXT_FILE_ITEM_IS_SYNCED_TOOLTIP"))
     else:
         self.setToolTip(_("TEXT_FILE_ITEM_IS_NOT_SYNCED_TOOLTIP"))
Beispiel #22
0
    def __init__(self,
                 jobs_ctx,
                 event_bus,
                 config,
                 minimize_on_close: bool = False,
                 **kwargs):
        super().__init__(**kwargs)
        self.setupUi(self)

        self.setMenuBar(None)
        self.jobs_ctx = jobs_ctx
        self.event_bus = event_bus
        self.config = config
        self.minimize_on_close = minimize_on_close
        # Explain only once that the app stays in background
        self.minimize_on_close_notif_already_send = False
        self.force_close = False
        self.need_close = False
        self.event_bus.connect(ClientEvent.GUI_CONFIG_CHANGED,
                               self.on_config_updated)
        self.setWindowTitle(
            _("TEXT_GUARDATA_WINDOW_TITLE_version").format(
                version=GUARDATA_VERSION))
        self.foreground_needed.connect(self._on_foreground_needed)
        self.new_instance_needed.connect(self._on_new_instance_needed)
        self.tab_center.tabCloseRequested.connect(self.close_tab)

        self.menu_button = Button()
        self.menu_button.setCursor(Qt.PointingHandCursor)
        self.menu_button.setIcon(QIcon(":/icons/images/material/menu.svg"))
        self.menu_button.setIconSize(QSize(24, 24))
        self.menu_button.setText(_("ACTION_MAIN_MENU_SHOW"))
        self.menu_button.setObjectName("MenuButton")
        self.menu_button.setProperty("color", QColor(0x00, 0x92, 0xFF))
        self.menu_button.setProperty("hover_color", QColor(0x00, 0x70, 0xDD))
        self.menu_button.setStyleSheet(
            "#MenuButton {background: none; border: none; color: #2185d0;}"
            "#MenuButton:hover {color: #0070DD;}")
        self.menu_button.apply_style()
        self.menu_button.clicked.connect(self._show_menu)
        self.tab_center.setCornerWidget(self.menu_button, Qt.TopRightCorner)

        self.add_tab_button = Button()
        self.add_tab_button.setCursor(Qt.PointingHandCursor)
        self.add_tab_button.setIcon(QIcon(":/icons/images/material/add.svg"))
        self.add_tab_button.setIconSize(QSize(24, 24))
        self.add_tab_button.setProperty("color", QColor(0x00, 0x92, 0xFF))
        self.add_tab_button.setProperty("hover_color",
                                        QColor(0x00, 0x70, 0xDD))
        self.add_tab_button.setStyleSheet("background: none; border: none;")
        self.add_tab_button.apply_style()
        self.add_tab_button.clicked.connect(self._on_add_instance_clicked)
        self.tab_center.setCornerWidget(self.add_tab_button, Qt.TopLeftCorner)

        self.tab_center.currentChanged.connect(self.on_current_tab_changed)
        self._define_shortcuts()
        self.ensurePolished()
Beispiel #23
0
 def on_rename_error(self, job):
     if job.status == "invalid-name":
         show_error(self,
                    _("TEXT_WORKSPACE_RENAME_INVALID_NAME"),
                    exception=job.exc)
     else:
         show_error(self,
                    _("TEXT_WORKSPACE_RENAME_UNKNOWN_ERROR"),
                    exception=job.exc)
Beispiel #24
0
def get_role_translation(user_role):
    ROLES_TRANSLATIONS = {
        WorkspaceRole.READER: _("TEXT_WORKSPACE_ROLE_READER"),
        WorkspaceRole.CONTRIBUTOR: _("TEXT_WORKSPACE_ROLE_CONTRIBUTOR"),
        WorkspaceRole.MANAGER: _("TEXT_WORKSPACE_ROLE_MANAGER"),
        WorkspaceRole.OWNER: _("TEXT_WORKSPACE_ROLE_OWNER"),
        NOT_SHARED_KEY: _("TEXT_WORKSPACE_ROLE_NOT_SHARED"),
    }
    return ROLES_TRANSLATIONS[user_role]
Beispiel #25
0
 def _on_delete_error(self, job):
     if not getattr(job.exc, "params", None):
         return
     if job.exc.params.get("multi"):
         show_error(self,
                    _("TEXT_FILE_DELETE_MULTIPLE_ERROR"),
                    exception=job.exc)
     else:
         show_error(self, _("TEXT_FILE_DELETE_ERROR"), exception=job.exc)
Beispiel #26
0
async def test_delete_dirs(aqtbot, running_backend, logged_gui_with_workspace,
                           monkeypatch, input_patcher):
    w_f = logged_gui_with_workspace.test_get_files_widget()

    assert w_f is not None
    async with aqtbot.wait_signal(w_f.folder_stat_success):
        pass
    assert w_f.table_files.rowCount() == 1

    await create_directories(logged_gui_with_workspace, aqtbot, monkeypatch,
                             ["Dir1", "Dir2", "Dir3"], input_patcher)

    assert w_f.table_files.rowCount() == 4

    # Delete one directory first
    await aqtbot.run(w_f.table_files.setRangeSelected,
                     QtWidgets.QTableWidgetSelectionRange(1, 0, 1, 0), True)
    assert len(w_f.table_files.selected_files()) == 1
    input_patcher.patch_question(
        "guardata.client.gui.files_widget.ask_question",
        QtWidgets.QDialog.Accepted,
        _("ACTION_FILE_DELETE"),
    )
    async with aqtbot.wait_signals(
        [w_f.delete_success, w_f.folder_stat_success]):
        w_f.table_files.delete_clicked.emit()

    # Wait until the file widget is refreshed by the timer
    while w_f.update_timer.isActive():
        async with aqtbot.wait_signal(w_f.folder_stat_success, timeout=3000):
            pass

    assert w_f.table_files.rowCount() == 3

    # Then delete two
    await aqtbot.run(w_f.table_files.setRangeSelected,
                     QtWidgets.QTableWidgetSelectionRange(1, 0, 2, 0), True)
    assert len(w_f.table_files.selected_files()) == 2
    input_patcher.patch_question(
        "guardata.client.gui.files_widget.ask_question",
        QtWidgets.QDialog.Accepted,
        _("ACTION_FILE_DELETE_MULTIPLE"),
    )
    async with aqtbot.wait_signals(
        [w_f.delete_success, w_f.folder_stat_success]):
        w_f.table_files.delete_clicked.emit()

    # Wait until the file widget is refreshed by the timer
    while w_f.update_timer.isActive():
        async with aqtbot.wait_signal(w_f.folder_stat_success, timeout=3000):
            pass

    assert w_f.table_files.rowCount() == 1
    for i in range(5):
        assert w_f.table_files.item(
            0, i).data(TYPE_DATA_INDEX) == FileType.ParentWorkspace
Beispiel #27
0
def get_filesize(bytesize):
    SYSTEM = [
        (1024**4, _("TEXT_FILE_SIZE_TB")),
        (1024**3, _("TEXT_FILE_SIZE_GB")),
        (1024**2, _("TEXT_FILE_SIZE_MB")),
        (1024**1, _("TEXT_FILE_SIZE_KB")),
        (1024**0, _("TEXT_FILE_SIZE_B")),
    ]

    return size(bytesize, system=SYSTEM)
Beispiel #28
0
    def _on_invite_error(self, job):
        assert job.is_finished()
        assert job.status != "ok"

        status = job.status
        if status == "offline":
            errmsg = _("TEXT_INVITE_DEVICE_INVITE_OFFLINE")
        else:
            errmsg = _("TEXT_INVITE_DEVICE_INVITE_ERROR")

        show_error(self, errmsg, exception=job.exc)
Beispiel #29
0
 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],
         )
Beispiel #30
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,
            )