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, )
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"))
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()
def on_get_version_error(self): if self.versions_job and self.versions_job.status != "cancelled": show_error(self, _("TEXT_FILE_HISTORY_LIST_FAILURE"), exception=self.versions_job.exc) self.versions_job = None self.dialog.reject()
def bootstrap_clicked(self): assert not self.bootstrap_job try: human_handle = HumanHandle(email=self.line_edit_email.text(), label=self.line_edit_login.text()) except ValueError as exc: if hasattr(exc, "args") and len(exc.args) > 0: if exc.args[0] == "Invalid email address": err_msg = "TEXT_BOOTSTRAP_ORG_INVALID_EMAIL" elif exc.args[0] == "Invalid label": err_msg = "TEXT_CLAIM_USER_INVALID_HUMAN_HANDLE" else: err_msg = "TEXT_BOOTSTRAP_ORG_UNKNOWN_FAILURE" else: err_msg = "TEXT_BOOTSTRAP_ORG_UNKNOWN_FAILURE" show_error(self, _(err_msg), exception=exc) return self.bootstrap_job = self.jobs_ctx.submit_job( ThreadSafeQtSignal(self, "bootstrap_success"), ThreadSafeQtSignal(self, "bootstrap_error"), _do_bootstrap_organization, config_dir=self.config.config_dir, password=self.line_edit_password.text(), password_check=self.line_edit_password_check.text(), human_handle=human_handle, device_label=self.line_edit_device.text(), bootstrap_addr=self.addr, ) self.check_infos()
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
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)
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)
def _on_req_error(self): assert self.req_job assert self.req_job.is_finished() assert self.req_job.status != "ok" status = self.req_job.status if status == "cancelled": return errmsg = None if status == "email_already_exists": errmsg = _("TEXT_ORG_WIZARD_EMAIL_ALREADY_EXISTS") elif status == "organization_already_exists": errmsg = _("TEXT_ORG_WIZARD_ORGANIZATION_ALREADY_EXISTS") elif status == "invalid_email": errmsg = _("TEXT_ORG_WIZARD_INVALID_EMAIL") elif status == "invalid_organization_id": errmsg = _("TEXT_ORG_WIZARD_INVALID_ORGANIZATION_ID") elif status == "invalid_response": errmsg = _("TEXT_ORG_WIZARD_INVALID_RESPONSE") elif status == "offline": errmsg = _("TEXT_ORG_WIZARD_OFFLINE") else: errmsg = _("TEXT_ORG_WIZARD_UNKNOWN_FAILURE") exc = self.req_job.exc if exc.params.get("exc"): exc = exc.params.get("exc") show_error(self, errmsg, exception=exc) self.req_job = None self.button_validate.setEnabled(True) self.button_previous.show()
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)
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)
def _on_get_users_error(self, job): assert job.is_finished() assert job.status != "ok" if job.status == "offline": show_error(self, _("TEXT_WORKSPACE_SHARING_OFFLINE")) self.spinner.spinner_movie.stop() self.spinner.hide() self.widget_users.show()
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)
def on_error(self): if self.limits_job and self.limits_job.status != "cancelled": show_error( self, _("TEXT_WORKSPACE_TIMESTAMPED_VERSION_RETRIEVAL_FAILED"), exception=self.limits_job.exc, ) self.limits_job = None self.dialog.reject()
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)
def item_activated(self, file_type, file_name): if file_type == FileType.ParentFolder: self.load(self.current_directory.parent) elif file_type == FileType.ParentWorkspace: self.back_clicked.emit() elif file_type == FileType.File: if not self.open_file(file_name): show_error( self, _("TEXT_FILE_OPEN_ERROR_file").format(file=file_name)) elif file_type == FileType.Folder: self.load(self.current_directory / file_name)
def _on_sharing_updated_qt(self, new_entry, previous_entry): if new_entry is None or new_entry.role is None: # Sharing revoked show_error(self, _("TEXT_FILE_SHARING_REVOKED")) self.back_clicked.emit() elif previous_entry is not None and previous_entry.role is not None: self.current_user_role = new_entry.role self.label_role.setText( get_role_translation(self.current_user_role)) if (previous_entry.role != WorkspaceRole.READER and new_entry.role == WorkspaceRole.READER): show_error(self, _("TEXT_FILE_SHARING_DEMOTED_TO_READER"))
def _on_folder_stat_error(self, job): self.table_files.clear() self.table_files.setStyleSheet("background-color: #FFFFFF;") self.spinner.spinner_movie.stop() self.spinner.hide() if isinstance(job.exc, FSFileNotFoundError): show_error(self, _("TEXT_FILE_FOLDER_NOT_FOUND")) self.table_files.add_parent_workspace() return if self.current_directory == FsPath("/"): self.table_files.add_parent_workspace() else: self.table_files.add_parent_folder()
def _on_invite_user_error(self, job): assert job.is_finished() assert job.status != "ok" status = job.status if status == "offline": errmsg = _("TEXT_INVITE_USER_INVITE_OFFLINE") elif status == "already_member": errmsg = _("TEXT_INVITE_USER_ALREADY_MEMBER_ERROR") else: errmsg = _("TEXT_INVITE_USER_INVITE_ERROR") show_error(self, errmsg, exception=job.exc)
def _find_device_from_addr(self, action_addr, display_error=False): device = None for available_device in list_available_devices(self.config.config_dir): if available_device.organization_id == action_addr.organization_id: device = available_device break if device is None: show_error( self, _("TEXT_FILE_LINK_NOT_IN_ORG_organization").format( organization=action_addr.organization_id), ) return device
def _on_folder_stat_success(self, job): ( self.current_directory, self.current_directory_uuid, files_stats, default_selection, ) = job.ret self.table_files.clear() self.table_files.setStyleSheet("background-color: #FFFFFF;") self.spinner.spinner_movie.stop() self.spinner.hide() old_sort = self.table_files.horizontalHeader().sortIndicatorSection() old_order = self.table_files.horizontalHeader().sortIndicatorOrder() self.table_files.setSortingEnabled(False) if self.current_directory == FsPath("/"): self.table_files.add_parent_workspace() else: self.table_files.add_parent_folder() file_found = False for path, stats in files_stats.items(): selected = False if default_selection and str(path) == default_selection: selected = True file_found = True if stats["type"] == "inconsistency": self.table_files.add_inconsistency(str(path), stats["id"]) elif stats["type"] == "folder": self.table_files.add_folder(str(path), stats["id"], not stats["need_sync"], stats["confined"], selected) else: self.table_files.add_file( str(path), stats["id"], stats["size"], stats["created"], stats["updated"], not stats["need_sync"], stats["confined"], selected, ) self.table_files.sortItems(old_sort, old_order) self.table_files.setSortingEnabled(True) if self.line_edit_search.text(): self.filter_files(self.line_edit_search.text()) if default_selection and not file_found: show_error(self, _("TEXT_FILE_GOTO_LINK_NOT_FOUND")) workspace_name = self.jobs_ctx.run_sync( self.workspace_fs.get_workspace_name) self.folder_changed.emit(str(workspace_name), str(self.current_directory))
def _on_workspace_reencryption_error(self, job): if job.is_cancelled(): return if job.status == "offline-backend": err_msg = _("TEXT_WORKPACE_REENCRYPT_OFFLINE_ERROR") elif job.status == "access-error": err_msg = _("TEXT_WORKPACE_REENCRYPT_ACCESS_ERROR") elif job.status == "not-found": err_msg = _("TEXT_WORKPACE_REENCRYPT_NOT_FOUND_ERROR") elif job.status == "fs-error": err_msg = _("TEXT_WORKPACE_REENCRYPT_FS_ERROR") else: err_msg = _("TEXT_WORKSPACE_REENCRYPT_UNKOWN_ERROR") show_error(self, err_msg, exception=job.exc)
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()
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"))
def _on_list_error(self, job): assert job.is_finished() assert job.status != "ok" status = job.status self.spinner.spinner_movie.stop() self.spinner.hide() if status in ["error", "offline"]: self._flush_users_list() label = QLabel(_("TEXT_USER_LIST_RETRIEVABLE_FAILURE")) label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.layout_users.addWidget(label) return else: errmsg = _("TEXT_USER_LIST_RETRIEVABLE_FAILURE") show_error(self, errmsg, exception=job.exc)
def _on_retrieve_info_error(self, job): if self.retrieve_info_job is not job: return self.retrieve_info_job = None assert job assert job.is_finished() assert job.status != "ok" if job.status != "cancelled": exc = None if job.exc: exc = job.exc.params.get("origin", None) show_error(self, _("TEXT_CLAIM_DEVICE_FAILED_TO_RETRIEVE_INFO"), exception=exc) self.rejected.emit()
def _on_wait_peer_trust_error(self, job): if self.wait_peer_trust_job is not job: return self.wait_peer_trust_job = None assert job assert job.is_finished() assert job.status != "ok" if job.status != "cancelled": exc = None if job.exc: exc = job.exc.params.get("origin", None) show_error(self, _("TEXT_CLAIM_DEVICE_WAIT_PEER_TRUST_ERROR"), exception=exc) self.failed.emit(job)
def on_mount_error(self, job): if isinstance(job.exc, MountpointError): workspace_id = job.arguments.get("workspace_id") timestamp = job.arguments.get("timestamp") wb = self.get_workspace_button(workspace_id, timestamp) if wb: wb.set_mountpoint_state(False) if isinstance(job.exc, MountpointNoDriveAvailable): show_error(self, _("TEXT_WORKSPACE_CANNOT_MOUNT_NO_DRIVE"), exception=job.exc) else: show_error(self, _("TEXT_WORKSPACE_CANNOT_MOUNT"), exception=job.exc)
def _on_signify_trust_error(self, job): if self.signify_trust_job is not job: return self.signify_trust_job = None assert job assert job.is_finished() assert job.status != "ok" if job.status != "cancelled": exc = None msg = _("TEXT_CLAIM_DEVICE_SIGNIFY_TRUST_ERROR") if job.exc: exc = job.exc.params.get("origin", None) if isinstance(exc, InvitePeerResetError): msg = _("TEXT_CLAIM_DEVICE_PEER_RESET") show_error(self, msg, exception=exc) self.failed.emit(job)
def _on_get_greeter_sas_error(self, job): if self.get_greeter_sas_job is not job: return self.get_greeter_sas_job = None assert job assert job.is_finished() assert job.status != "ok" if job.status != "cancelled": exc = None msg = _("TEXT_CLAIM_DEVICE_GET_GREETER_SAS_ERROR") if job.exc: exc = job.exc.params.get("origin", None) if isinstance(exc, InvitePeerResetError): msg = _("TEXT_CLAIM_DEVICE_PEER_RESET") show_error(self, msg, exception=exc) self.failed.emit(job)