Exemple #1
0
    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"))
Exemple #3
0
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()
Exemple #8
0
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"))
Exemple #9
0
 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)
Exemple #10
0
        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
Exemple #11
0
    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()
Exemple #13
0
 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()
Exemple #20
0
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
Exemple #23
0
 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"))
Exemple #24
0
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()
Exemple #28
0
 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()
Exemple #29
0
    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)
Exemple #30
0
    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)