def _init_ui(self): self._ui.pushButton.setEnabled(False) self._ui.comboBox.addItem(tr("---Select Subject---")) self._ui.comboBox.addItem(tr("Technical Question")) self._ui.comboBox.addItem(tr("Other Question")) self._ui.comboBox.addItem(tr("Feedback")) self._ui.comboBox.setCurrentIndex(self._selected_index) palette = self._ui.comboBox.palette() palette.setColor(QPalette.HighlightedText, QColor(self.DROPDOWN_COLOR)) palette.setColor(QPalette.Highlight, QColor(self.DROPDOWN_BACKGROUND_COLOR)) self._ui.comboBox.setPalette(palette) palette = self._ui.comboBox.view().palette() palette.setColor(QPalette.HighlightedText, QColor(self.DROPDOWN_COLOR)) palette.setColor(QPalette.Highlight, QColor(self.DROPDOWN_BACKGROUND_COLOR)) self._ui.comboBox.view().setPalette(palette) self._set_tooltip() self._ui.comboBox.currentIndexChanged.connect(self._on_index_changed) self._ui.plainTextEdit.textChanged.connect(self._set_tooltip) self._ui.pushButton.clicked.connect(self._on_send_clicked) self._ui.text_label.linkActivated.connect(self._on_link_activated) self._sending_error.connect(self._clear_pipe_state) self._set_fonts()
def _init_ui(self): self._icon_urls = { 'add_file': [ ':/images/transfers/add_file.svg', ':/images/transfers/add_file_hovered.svg' ], 'link_insert': [ ':/images/transfers/link_insert.svg', ':/images/transfers/link_insert_hovered.svg' ], 'revert': [':/images/revert.svg', ':/images/transfers/revert_clicked.svg'], 'pause': [':/images/pause.svg', ':/images/pause_hovered.svg'], 'play': [':/images/play.svg', ':/images/play_hovered.svg'], } ui = self._ui self._dialog.setWindowFlags(Qt.Dialog) self._dialog.setAttribute(Qt.WA_TranslucentBackground) self._dialog.setAttribute(Qt.WA_MacFrameworkScaled) self._set_file_list_options(ui.downloads_list) self._set_file_list_options(ui.uploads_list) ui.downloads_list.verticalScrollBar().valueChanged.connect( self.on_downloads_scroll_changed) ui.uploads_list.verticalScrollBar().valueChanged.connect( self.on_uploads_scroll_changed) self._old_main_resize_event = ui.centralwidget.resizeEvent ui.centralwidget.resizeEvent = self._main_resize_event self._set_fonts() ui.add_button.enterEvent = lambda _: \ self._enter_leave(ui.add_button, 'add_file') ui.add_button.leaveEvent = lambda _: \ self._enter_leave(ui.add_button, 'add_file', False) ui.insert_link_button.enterEvent = lambda _: \ self._enter_leave(ui.insert_link_button, 'link_insert') ui.insert_link_button.leaveEvent = lambda _: \ self._enter_leave(ui.insert_link_button, 'link_insert', False) ui.revert_all_button.enterEvent = lambda _: \ self._enter_leave(ui.revert_all_button, 'revert') ui.revert_all_button.leaveEvent = lambda _: \ self._enter_leave(ui.revert_all_button, 'revert', False) ui.pause_all_button.enterEvent = lambda _: \ self._enter_leave(ui.pause_all_button, 'play' if self._paused_state == self.PAUSED else 'pause') ui.pause_all_button.leaveEvent = lambda _: \ self._enter_leave(ui.pause_all_button, 'play' if self._paused_state == self.PAUSED else 'pause', False) if self._paused_state == self.PAUSED: ui.pause_all_button.setText(tr("Resume all")) ui.pause_all_button.setIcon(QIcon(":/images/play.svg")) else: ui.pause_all_button.setText(tr("Pause all ")) ui.pause_all_button.setIcon(QIcon(":/images/pause.svg"))
def _on_share_paths_cb(paths, share_links, error_info='', move=False, save_to_clipboard=True, context=''): ''' Callback to be called after processing of 'share_path' shell command @param paths Filesystem paths [list] @param share_links Links URLs [list] or None if links getting failed ''' if share_links: if save_to_clipboard: Application.show_tray_notification( tr("URL(s) for downloading copied to clipboard"), tr("Sharing")) else: params.ipc_ws_server.on_paths_links(paths, share_links, context, move) elif paths: try: share_names = list(map(lambda p: get_relpath(p)[1], paths)) signals.share_path_failed.emit(share_names) except Exception as e: logger.warning( "on_share_paths_cb, share_path_failed exception: %s", e) Application.show_tray_notification( tr("Sharing {} file(s) failed: {}").format(len(paths), error_info), tr("Sharing"))
def _on_menu_clicked(self, index, action_name, action_type): node_id, \ node_name, \ is_online, \ is_itself, \ is_wiped = self._model.get_node_id_online_itself(index) if action_name == "hideNode" and is_online: self.show_tray_notification.emit( tr("Action unavailable for online node")) return if (action_name == "hideNode" or action_type == "wipe"): if action_name == "hideNode": alert_str = tr( '"{}" node will be removed ' 'from list of devices. Files will not be wiped.'.format( node_name)) else: alert_str = tr( 'All files from "{}" node\'s ' 'pvtbox secured folder will be wiped. '.format(node_name)) if not self._user_confirmed_action(alert_str): return if not is_itself: self._nodes_actions[node_id].add((action_name, action_type)) self.management_action.emit(action_name, action_type, node_id, is_itself)
def _on_update_ready(self, ready): if not ready: return logger.debug("on_update_ready") self.show_tray_notification.emit( tr("Application will restart automatically in one minute"), tr("Pvtbox is going to update")) QTimer.singleShot(60 * 1000, self._update_install.emit)
def on_size_speed_changed(self, download_speed, download_size, upload_speed, upload_size): self._ui.download_speed_value.setText( tr("{}/s").format(format_with_units(download_speed))) self._ui.download_size_value.setText(format_with_units(download_size)) self._ui.upload_speed_value.setText( tr("{}/s").format(format_with_units(upload_speed))) self._ui.upload_size_value.setText(format_with_units(upload_size))
def _show_error(self, error_text=''): if not error_text: link_text = self._ui.link_line_edit.text() error_text = tr("Please insert share link") \ if not self._password_mode and not link_text \ else tr("Invalid link") if not self._password_mode \ else tr("Password can not be empty") if not link_text \ else tr("Wrong password") self._ui.error_label.setText(error_text) self._ui.link_line_edit.setFocus()
def show_copying_failed(path): ''' Shows message when copying of file/dir into sync directory failed @param path Filesystem path [unicode] ''' name = op.basename(path) Application.show_tray_notification( tr("Failed to copy '{}' into sync directory").format(name), tr("Shell"))
def _set_tooltip(self): if not self._selected_index: tooltip = tr("Please select subject") self._ui.pushButton.setEnabled(False) elif not self._ui.plainTextEdit.document().toPlainText(): tooltip = tr("Message can't be empty") self._ui.pushButton.setEnabled(False) else: tooltip = tr("Click to send message") self._ui.pushButton.setEnabled(True) self._ui.pushButton.setToolTip(tooltip)
def archive(): # uses function attributes to track progress # archive.size, archive.progress, archive.stop logs_dir = get_bases_dir(self._config.sync_directory) log_files = glob("{}{}*.log".format(logs_dir, os.sep)) log_sizes = list(map(os.path.getsize, log_files)) # mark overall size archive.size = sum(log_sizes) old_archives = glob("{}{}2*_logs.zip".format(logs_dir, os.sep)) try: list(map(remove_file, old_archives)) except Exception as e: logger.warning("Can't delete old archives. Reason: (%s)", e) if get_free_space(logs_dir) < archive.size // 5: # archive.size // 5 is approx future archive size msg = tr("Insufficient disk space to archive logs. " "Please clean disk") self._parent.show_tray_notification(msg) self._sending_error.emit() raise SendingError(msg) archive_name = time.strftime('%Y%m%d_%H%M%S_logs.zip') archive_path = "{}{}{}".format(logs_dir, os.sep, archive_name) archive_dir = op.dirname(archive_path) f = zipfile.ZipFile(archive_path, "w", compression=zipfile.ZIP_DEFLATED, compresslevel=9) try: with cwd(archive_dir): for i, log_file in enumerate(log_files): if not op.isfile(log_file): continue f.write(op.basename(log_file)) # mark progress archive.progress += log_sizes[i] if archive.stop: return except Exception as e: msg = tr("Can't archive logs.") logger.warning(msg + " Reason: (%s)", e) self._parent.show_tray_notification(msg) self._sending_error.emit() raise SendingError(msg) finally: f.close() if archive.stop: remove_file(archive_path) return archive_path
def _accept_collaboration_invitation(self, colleague_id): self._parent.show_tray_notification(tr("Accepting invitation...")) res = self._parent.web_api.accept_invitation(colleague_id) msg = tr("Can't send invitation accept") if res and "result" in res: if res["result"] == "success": msg = tr("Invitation accepted successfully") else: msg = str(res.get("info", msg)) self._parent.show_tray_notification(msg)
def _change_mode(self): assert not self._password_mode, \ "Must not be in password mode in changing mode" logger.debug("Changing to password mode") self._password_mode = True self._dialog.setWindowTitle(tr("Insert password")) self._link = self._ui.link_line_edit.text() self._ui.link_line_edit.setText('') self._ui.link_line_edit.setPlaceholderText(tr("Insert password here")) self._ui.link_line_edit.setEchoMode(QLineEdit.Password) self._hide_error()
def _on_send_clicked(self): self._dialog.setEnabled(False) self._pipe = ProgressPipe(self, self._ui.pushButton, timeout=1000, final_text=tr("Sent"), final_timeout=500) self._pipe.pipe_finished.connect(self._on_pipe_finished) if self._ui.checkBox.isChecked(): self._pipe.add_task(tr("Compressing"), self._archive_logs()) self._pipe.add_task(tr("Uploading"), self._upload_file()) self._pipe.add_task(tr("Sending"), self._send_message()) self._pipe.start()
def _user_confirmed_action(self, alert_str): msg = tr("<b>Are</b> you <b>sure</b>?<br><br>{}".format(alert_str)) userAnswer = msgbox(msg, title=' ', buttons=[ (tr('Cancel'), 'Cancel'), (tr('Yes'), 'Yes'), ], parent=self._dialog, default_index=0, enable_close_button=True) return userAnswer == 'Yes'
def remove(self, colleague_id): self._parent.show_tray_notification( tr("Deleting colleague from collaboration...")) res = self._parent.web_api.colleague_delete(self._uuid, colleague_id) msg = tr("Can't delete colleague from collaboration") if res and "result" in res: if res["result"] == "success": msg = tr("Colleague deleted successfully") else: msg = str(res.get("info", msg)) self._parent.show_tray_notification(msg) self._query_info()
def _set_revert_button_options(self, revert_button, obj_id, is_created, is_shared, is_http_download, is_file, rel_path, size): revert_text = tr("Delete") if is_created \ else tr('Revert') if not is_shared and not is_http_download \ else tr("Cancel") revert_button.setText(revert_text + ' ') revert_button.setIcon( QIcon(':images/transfers/{}_{}.svg'.format( revert_button.text().strip().lower(), 'active' if revert_button.is_entered else 'inactive'))) tooltip_text = tr("Action disabled while sync paused") \ if not is_http_download and self._paused_state == self.PAUSED \ else tr("Delete file and cancel download") if is_created \ else tr("Revert changes and cancel download") \ if not is_shared and not is_http_download \ else tr("Cancel shared file download") if is_shared \ else tr("You can cancel upload from web panel") revert_button.setToolTip(tooltip_text) revert_button.setStyleSheet( 'QPushButton {{margin: 0;border: 0; text-align:right center;' 'color: {0};}} ' 'QPushButton:!enabled {{color: #aaaaaa;}}'.format( '#333333' if not revert_button.is_entered else '#f9af61' if not is_created else 'red')) revert_button.setEnabled(not is_http_download and self._paused_state != self.PAUSED) revert_button.setProperty( "properties", [is_created, is_shared, is_file, rel_path, obj_id, size])
def leave_collaboration(self): self._parent.show_tray_notification( tr("Leaving collaboration...")) uuid = self._uuid self._close_dialog.emit() res = self._parent.web_api.collaboration_leave(uuid) msg = tr("Can't leave collaboration") if res and "result" in res: if res["result"] == "success": msg = tr("Successfully leaved collaboration") else: msg = str(res.get("info", msg)) self._parent.show_tray_notification(msg)
def cancel_collaboration(self): self._parent.show_tray_notification( tr("Deleting collaboration...")) uuid = self._uuid self._close_dialog.emit() res = self._parent.web_api.collaboration_cancel(uuid) msg = tr("Can't delete collaboration") if res and "result" in res: if res["result"] == "success": msg = tr("Collaboration deleted successfully") else: msg = str(res.get("info", msg)) self._parent.show_tray_notification(msg)
def _setup_buttons(self): if self._current_index == 0: self._ui.prev_button.setDisabled(True) self._ui.prev_button.setStyleSheet( "border: 0; color:#ffffff; text-align:left;") else: self._ui.prev_button.setDisabled(False) self._ui.prev_button.setStyleSheet( "border: 0; color:#222222; text-align:left;") if self._current_index + 1 == self._slides_count: self._ui.next_button.setText(tr("GOT IT")) else: self._ui.next_button.setText(tr("NEXT")) self._setup_points()
def block_path_slot(paths): ''' Callback to be called after processing 'block_path' shell command @param path Filesystem path [unicode] ''' # Request share cancelling if cancel_sharing(paths): Application.show_tray_notification(tr("Sharing cancelled"), tr("Sharing")) else: Application.show_tray_notification(tr("Failed to cancel path sharing"), tr("Sharing"))
def add_colleague(self, colleague_email, to_edit): self._parent.show_tray_notification( tr("Adding colleague to collaboration...")) access_type = "edit" if to_edit else "view" res = self._parent.web_api.colleague_add( self._uuid, colleague_email, access_type) msg = tr("Can't add colleague to collaboration") if res and "result" in res: if res["result"] == "success": msg = tr("Colleague added successfully") else: msg = str(res.get("info", msg)) self._parent.show_tray_notification(msg) self._query_info()
def _query_info(self): logger.debug("Querying collaboration info") self._querying = True collaboration_info = dict() res = self._parent.web_api.collaboration_info(self._uuid) was_error = True msg = tr("Can't get collaboration info") if res and "result" in res: if res["result"] == "success": was_error = False collaboration_info = res['data'] logger.debug("Got collaboration info %s", collaboration_info) if not collaboration_info: collaboration_info = {'collaboration_is_owner': True} else: if "info" in res: msg = res.get("info", msg) logger.warning("No collaboration info: %s", res) else: logger.warning('Result not returned for collaboration info query') if was_error: self._parent.show_tray_notification(msg) return self._collaboration_info_got.emit(collaboration_info) self._querying = False
def _clear_pipe_state(self): self._dialog.setEnabled(True) try: self._pipe.pipe_finished.disconnect(self._on_pipe_finished) except Exception as e: logger.warning("Can't disconnect signal: %s", e) self._ui.pushButton.setText(tr("SEND"))
def _on_open_link_cb(path, share_link): ''' Callback to be called after processing 'open_link' shell command @param path Filesystem path [unicode] @param share_link Link URL [unicode] or None if link getting failed ''' # Open URL in the web browser (if any) if share_link: webbrowser.open_new(share_link) else: name = op.basename(path) Application.show_tray_notification( tr("Failed to share file: {}").format(name), tr("Sharing"))
def show_collaboration_settings(self, path, uuid): if self._cfg.license_type == FREE_LICENSE: self._parent.show_tray_notification( tr("Collaborations not available for free license")) return if self._collaboration_settings_dialog or \ not self._parent.is_logged_in() or \ self._parent.dialogs_opened(): reason = "dialog already opened" \ if self._collaboration_settings_dialog else "user logged out" \ if not self._parent.is_logged_in() else "other dialog opened" logger.warning("Can't show collaboration settings. Reason: %s", reason) return self._path = path self._uuid = uuid self._collaboration_settings_dialog = CollaborationSettingsDialog( self, self._parent_window, self._colleagues, self._path, self._dp) self.query_collaboration_info() # show dialog on top self._parent_window.setWindowFlag(Qt.WindowStaysOnTopHint, True) self._parent.show() self._parent_window.setWindowFlag(Qt.WindowStaysOnTopHint, False) self._parent.show() self._collaboration_settings_dialog.show() self.clear()
def _parse_response(self, response): try: data = json.loads(response) err_code = data.get("errcode", '') info = data.get("info", '') if err_code == 'SHARE_WRONG_PASSWORD': success = None if not self._password_mode else False error = '' elif err_code == 'LOCKED_CAUSE_TOO_MANY_BAD_LOGIN': success = False error = tr('Locked after too many incorrect attempts') elif err_code == 'SHARE_NOT_FOUND': success = False error = '' else: success = False error = info if info else self._cant_validate except Exception as e: logger.warning("Can't parse response (%s). reason: %s", response, e) success = False error = self._cant_validate return success, error
def grant_edit(self, colleague_id, to_edit): start_msg = tr("Adding edit permission to collaboration...") \ if to_edit else tr("Removing edit permission to collaboration...") self._parent.show_tray_notification(start_msg) access_type = "edit" if to_edit else "view" res = self._parent.web_api.colleague_edit( self._uuid, colleague_id, access_type) msg = tr("Can't change edit permission to collaboration") if res and "result" in res: if res["result"] == "success": msg = tr("Edit permission changed successfully") else: msg = str(res.get("info", msg)) self._parent.show_tray_notification(msg) self._query_info()
def migration_failed(error): logger.warning("Migration failed with error: %s", error) msgbox(error, tr('Migration to new Pvtbox folder error'), parent=dialog) dialog.cancel() self._migration_cancelled = True done()
def _convert_value(self, param_name, value, row_data=None): if value is None: return "Unknown" if param_name == 'device_type': if value == 'desktop': return tr('PC') elif value == 'phone': return tr('Mobile') elif param_name == 'is_online': if value: return tr('Yes') else: return tr('No') elif param_name == 'node_name' and row_data.get('is_itself'): return "{} ({})".format(value, tr("this node")) elif param_name == 'disk_usage': return format_with_units(value) elif param_name == 'download_speed' or param_name == 'upload_speed': return u"{}/s".format(format_with_units(value)) elif param_name == 'node_status': if not isinstance(value, int): value = int(value) return tr(self.NODE_STATUSES[value]) elif param_name == 'manage': if value: return tr('\nmanage...\n') else: return '' return str(value)
def _show_feedback_form(self): if self._is_opened: self._feedback_timer.setInterval(self.SHORT_FEEDBACK_INTERVAL) self._feedback_timer.start() return self._feedback_mode = True self._selected_index = 3 self._dialog.closeEvent = self._close_event window_title = self._dialog.windowTitle() label_text = self._ui.text_label.text() feedback_text = tr("Please leave your feedback for Pvtbox") self._ui.text_label.setText( "<html><head/><body><p>{}</p></body></html>".format(feedback_text)) self._dialog.setWindowTitle(tr("Feedback")) self.show() self._dialog.setWindowTitle(window_title) self._ui.text_label.setText(label_text)