Example #1
0
    def __init__(self, debug_javascript):
        MainWindow.__init__(self, None)
        self.setWindowTitle(_('E-book viewer'))
        self.base_window_title = unicode(self.windowTitle())
        self.setObjectName('EbookViewer')
        self.setWindowIcon(QIcon(I('viewer.png')))
        self.setDockOptions(self.AnimatedDocks | self.AllowTabbedDocks)

        self.centralwidget = c = QWidget(self)
        c.setObjectName('centralwidget')
        self.setCentralWidget(c)
        self.central_layout = cl = QGridLayout(c)
        cl.setSpacing(0)
        c.setLayout(cl), cl.setContentsMargins(0, 0, 0, 0)

        self.view = v = DocumentView(self)
        v.setMinimumSize(100, 100)
        self.view.initialize_view(debug_javascript)
        v.setObjectName('view')
        cl.addWidget(v)

        self.vertical_scrollbar = vs = QScrollBar(c)
        vs.setOrientation(Qt.Vertical), vs.setObjectName("vertical_scrollbar")
        cl.addWidget(vs, 0, 1, 2, 1)

        self.horizontal_scrollbar = hs = QScrollBar(c)
        hs.setOrientation(
            Qt.Horizontal), hs.setObjectName("horizontal_scrollbar")
        cl.addWidget(hs, 1, 0, 1, 1)

        self.tool_bar = tb = ToolBar(self)
        tb.setObjectName('tool_bar'), tb.setIconSize(QSize(32, 32))
        self.addToolBar(Qt.LeftToolBarArea, tb)

        self.tool_bar2 = tb2 = QToolBar(self)
        tb2.setObjectName('tool_bar2')
        self.addToolBar(Qt.TopToolBarArea, tb2)
        self.tool_bar.setContextMenuPolicy(Qt.DefaultContextMenu)
        self.tool_bar2.setContextMenuPolicy(Qt.PreventContextMenu)

        self.pos = DoubleSpinBox()
        self.pos.setDecimals(1)
        self.pos.setSuffix('/' + _('Unknown') + '     ')
        self.pos.setMinimum(1.)
        self.tool_bar2.addWidget(self.pos)
        self.tool_bar2.addSeparator()
        self.reference = Reference()
        self.tool_bar2.addWidget(self.reference)
        self.tool_bar2.addSeparator()
        self.search = SearchBox2(self)
        self.search.setMinimumContentsLength(20)
        self.search.initialize('viewer_search_history')
        self.search.setToolTip(_('Search for text in book'))
        self.search.setMinimumWidth(200)
        self.tool_bar2.addWidget(self.search)

        self.toc_dock = d = QDockWidget(_('Table of Contents'), self)
        d.setContextMenuPolicy(Qt.CustomContextMenu)
        self.toc_container = w = QWidget(self)
        w.l = QVBoxLayout(w)
        self.toc = TOCView(w)
        self.toc_search = TOCSearch(self.toc, parent=w)
        w.l.addWidget(self.toc), w.l.addWidget(
            self.toc_search), w.l.setContentsMargins(0, 0, 0, 0)
        d.setObjectName('toc-dock')
        d.setWidget(w)
        d.close()  # starts out hidden
        self.addDockWidget(Qt.LeftDockWidgetArea, d)
        d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)

        self.bookmarks_dock = d = QDockWidget(_('Bookmarks'), self)
        d.setContextMenuPolicy(Qt.CustomContextMenu)
        self.bookmarks = BookmarkManager(self)
        d.setObjectName('bookmarks-dock')
        d.setWidget(self.bookmarks)
        d.close()  # starts out hidden
        self.addDockWidget(Qt.RightDockWidgetArea, d)
        d.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)

        self.footnotes_dock = d = QDockWidget(_('Footnotes'), self)
        d.visibilityChanged.connect(self.footnote_visibility_changed)
        d.setContextMenuPolicy(Qt.CustomContextMenu)
        self.footnotes_view = FootnotesView(self)
        self.footnotes_view.follow_link.connect(self.view.follow_footnote_link)
        self.footnotes_view.close_view.connect(d.close)
        self.view.footnotes.set_footnotes_view(self.footnotes_view)
        d.setObjectName('footnotes-dock')
        d.setWidget(self.footnotes_view)
        d.close()  # starts out hidden
        self.addDockWidget(Qt.BottomDockWidgetArea, d)
        d.setAllowedAreas(Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea
                          | Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)

        self.create_actions()

        self.metadata = Metadata(self.centralwidget)
        self.history = History(self.action_back, self.action_forward)

        self.full_screen_label = QLabel(
            '''
                <center>
                <h1>%s</h1>
                <h3>%s</h3>
                <h3>%s</h3>
                <h3>%s</h3>
                </center>
                ''' %
            (_('Full screen mode'), _('Right click to show controls'),
             _('Tap in the left or right page margin to turn pages'),
             _('Press Esc to quit')), self.centralWidget())
        self.full_screen_label.setVisible(False)
        self.full_screen_label.final_height = 200
        self.full_screen_label.setFocusPolicy(Qt.NoFocus)
        self.full_screen_label.setStyleSheet('''
        QLabel {
            text-align: center;
            background-color: white;
            color: black;
            border-width: 1px;
            border-style: solid;
            border-radius: 20px;
        }
        ''')
        self.clock_label = QLabel('99:99', self.centralWidget())
        self.clock_label.setVisible(False)
        self.clock_label.setFocusPolicy(Qt.NoFocus)
        self.info_label_style = '''
            QLabel {
                text-align: center;
                border-width: 1px;
                border-style: solid;
                border-radius: 8px;
                background-color: %s;
                color: %s;
                font-family: monospace;
                font-size: larger;
                padding: 5px;
        }'''
        self.pos_label = QLabel('2000/4000', self.centralWidget())
        self.pos_label.setVisible(False)
        self.pos_label.setFocusPolicy(Qt.NoFocus)

        self.resize(653, 746)
Example #2
0
    def __init__(self, parent, prefs=None):
        QWidget.__init__(self, parent)
        self.prefs = prefs or gprefs
        self.setLayout(QVBoxLayout())

        self.la = la = QLabel(
            '<b>' + _('Select a destination for the Table of Contents entry'))
        self.layout().addWidget(la)
        self.splitter = sp = QSplitter(self)
        self.layout().addWidget(sp)
        self.layout().setStretch(1, 10)
        sp.setOpaqueResize(False)
        sp.setChildrenCollapsible(False)

        self.dest_list = dl = QListWidget(self)
        dl.setMinimumWidth(250)
        dl.currentItemChanged.connect(self.current_changed)
        sp.addWidget(dl)

        w = self.w = QWidget(self)
        l = w.l = QGridLayout()
        w.setLayout(l)
        self.view = WebView(self)
        self.view.elem_clicked.connect(self.elem_clicked)
        l.addWidget(self.view, 0, 0, 1, 3)
        sp.addWidget(w)

        self.search_text = s = QLineEdit(self)
        s.setPlaceholderText(_('Search for text...'))
        l.addWidget(s, 1, 0)
        self.ns_button = b = QPushButton(QIcon(I('arrow-down.png')),
                                         _('Find &next'), self)
        b.clicked.connect(self.find_next)
        l.addWidget(b, 1, 1)
        self.ps_button = b = QPushButton(QIcon(I('arrow-up.png')),
                                         _('Find &previous'), self)
        l.addWidget(b, 1, 2)
        b.clicked.connect(self.find_previous)

        self.f = f = QFrame()
        f.setFrameShape(f.StyledPanel)
        f.setMinimumWidth(250)
        l = f.l = QVBoxLayout()
        f.setLayout(l)
        sp.addWidget(f)

        f.la = la = QLabel('<p>' + _(
            'Here you can choose a destination for the Table of Contents\' entry'
            ' to point to. First choose a file from the book in the left-most panel. The'
            ' file will open in the central panel.<p>'
            'Then choose a location inside the file. To do so, simply click on'
            ' the place in the central panel that you want to use as the'
            ' destination. As you move the mouse around the central panel, a'
            ' thick green line appears, indicating the precise location'
            ' that will be selected when you click.'))
        la.setStyleSheet('QLabel { margin-bottom: 20px }')
        la.setWordWrap(True)
        l.addWidget(la)

        f.la2 = la = QLabel('<b>' + _('&Name of the ToC entry:'))
        l.addWidget(la)
        self.name = QLineEdit(self)
        la.setBuddy(self.name)
        l.addWidget(self.name)

        self.base_msg = '<b>' + _('Currently selected destination:') + '</b>'
        self.dest_label = la = QLabel(self.base_msg)
        la.setWordWrap(True)
        la.setStyleSheet('QLabel { margin-top: 20px }')
        l.addWidget(la)

        l.addStretch()

        state = self.prefs.get('toc_edit_splitter_state', None)
        if state is not None:
            sp.restoreState(state)
Example #3
0
    def __init__(self, plugin):
        DefaultConfigWidget.__init__(self, plugin)
        c = plugin_prefs[STORE_NAME]

        other_group_box = QGroupBox('Other options', self)
        self.l.addWidget(other_group_box, self.l.rowCount(), 0, 1, 2)
        other_group_box_layout = QGridLayout()
        other_group_box.setLayout(other_group_box_layout)

        # SRU Token
        sru_token_label = QLabel('SRU Token (recommended):', self)
        sru_token_label.setToolTip(
            'To access the API of the DNB a personal SRU access token is required.\n'
            'The token is for free.\n\n'
            'To get a token, create an account at https://portal.dnb.de/myAccount/register.htm \n'
            'After that write an email to [email protected] and ask them to enable \n'
            'SRU token generation for your account.')
        other_group_box_layout.addWidget(sru_token_label, 0, 0, 1, 1)

        self.sru_token_line = QtGui.QLineEdit(self)
        self.sru_token_line.setText(
            c.get(KEY_SRUTOKEN, DEFAULT_STORE_VALUES[KEY_SRUTOKEN]))
        other_group_box_layout.addWidget(self.sru_token_line, 0, 1, 1, 1)

        # Guess Series
        guess_series_label = QLabel(
            'Guess Series and Series Index from Title:', self)
        guess_series_label.setToolTip(
            'DNB only rarely provides correct data about a book\'s series.\n'
            'This plugin can try to extract series and series_index from the book title.\n'
            'Be careful, this overrides DNB\'s series metadata does not work perfectly!'
        )
        other_group_box_layout.addWidget(guess_series_label, 1, 0, 1, 1)

        self.guess_series_checkbox = QtGui.QCheckBox(self)
        self.guess_series_checkbox.setChecked(
            c.get(KEY_GUESS_SERIES, DEFAULT_STORE_VALUES[KEY_GUESS_SERIES]))
        other_group_box_layout.addWidget(self.guess_series_checkbox, 1, 1, 1,
                                         1)

        # Append Edition to Title
        append_edition_to_title_label = QLabel('Append Edition to Title:',
                                               self)
        append_edition_to_title_label.setToolTip(
            'For some books DNB has information about the edition.\n'
            'This plugin can fetch this information and append it to the book\'s title,\n'
            'e.g. "Mord am Tegernsee : Ein Bayern-Krimi : 2. Aufl.".\n'
            'Of course this only works reliable if you search for a book with a known unique identifier such as dnb-idn or ISBN.'
        )
        other_group_box_layout.addWidget(append_edition_to_title_label, 2, 0,
                                         1, 1)

        self.append_edition_to_title_checkbox = QtGui.QCheckBox(self)
        self.append_edition_to_title_checkbox.setChecked(
            c.get(KEY_APPEND_EDITION_TO_TITLE,
                  DEFAULT_STORE_VALUES[KEY_APPEND_EDITION_TO_TITLE]))
        other_group_box_layout.addWidget(self.append_edition_to_title_checkbox,
                                         2, 1, 1, 1)

        # Fetch Subjects
        fetch_subjects_label = QLabel('Fetch Subjects:', self)
        fetch_subjects_label.setToolTip(
            'DNB provides several types of subjects:\n'
            ' - Standardized subjects according to the GND\n'
            ' - Subjects delivered by the publisher\n'
            'You can choose which ones to fetch.')
        other_group_box_layout.addWidget(fetch_subjects_label, 3, 0, 1, 1)

        self.fetch_subjects_radios_group = QtGui.QButtonGroup(other_group_box)
        titles = [
            'only GND subjects',
            'GND subjects if available, otherwise non-GND subjects',
            'GND and non-GND subjects',
            'non-GND subjects if available, otherwise GND subjects',
            'only non-GND subjects', 'none'
        ]
        self.fetch_subjects_radios = [
            QtGui.QRadioButton(title) for title in titles
        ]
        for i, radio in enumerate(self.fetch_subjects_radios):
            if i == c.get(KEY_FETCH_SUBJECTS,
                          DEFAULT_STORE_VALUES[KEY_FETCH_SUBJECTS]):
                radio.setChecked(True)
            self.fetch_subjects_radios_group.addButton(radio, i)
            other_group_box_layout.addWidget(radio, 3 + i, 1, 1, 1)
Example #4
0
    def __init__(self, window, plugin, keystore, device_id):
        title = _("{} Settings").format(plugin.device)
        super(SettingsDialog, self).__init__(window, title)
        self.setMaximumWidth(540)

        devmgr = plugin.device_manager()
        config = devmgr.config
        handler = keystore.handler
        thread = keystore.thread
        hs_rows, hs_cols = (64, 128)

        def invoke_client(method, *args, **kw_args):
            unpair_after = kw_args.pop('unpair_after', False)

            def task():
                client = devmgr.client_by_id(device_id)
                if not client:
                    raise RuntimeError("Device not connected")
                if method:
                    getattr(client, method)(*args, **kw_args)
                if unpair_after:
                    devmgr.unpair_id(device_id)
                return client.features

            thread.add(task, on_success=update)

        def update(features):
            self.features = features
            set_label_enabled()
            bl_hash = bh2u(features.bootloader_hash)
            bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]])
            noyes = [_("No"), _("Yes")]
            endis = [_("Enable Passphrases"), _("Disable Passphrases")]
            disen = [_("Disabled"), _("Enabled")]
            setchange = [_("Set a PIN"), _("Change PIN")]

            version = "%d.%d.%d" % (features.major_version,
                                    features.minor_version,
                                    features.patch_version)
            coins = ", ".join(coin.coin_name for coin in features.coins)

            device_label.setText(features.label)
            pin_set_label.setText(noyes[features.pin_protection])
            passphrases_label.setText(disen[features.passphrase_protection])
            bl_hash_label.setText(bl_hash)
            label_edit.setText(features.label)
            device_id_label.setText(features.device_id)
            initialized_label.setText(noyes[features.initialized])
            version_label.setText(version)
            coins_label.setText(coins)
            clear_pin_button.setVisible(features.pin_protection)
            clear_pin_warning.setVisible(features.pin_protection)
            pin_button.setText(setchange[features.pin_protection])
            pin_msg.setVisible(not features.pin_protection)
            passphrase_button.setText(endis[features.passphrase_protection])
            language_label.setText(features.language)

        def set_label_enabled():
            label_apply.setEnabled(label_edit.text() != self.features.label)

        def rename():
            invoke_client('change_label', label_edit.text())

        def toggle_passphrase():
            title = _("Confirm Toggle Passphrase Protection")
            currently_enabled = self.features.passphrase_protection
            if currently_enabled:
                msg = _("After disabling passphrases, you can only pair this "
                        "Electrum wallet if it had an empty passphrase.  "
                        "If its passphrase was not empty, you will need to "
                        "create a new wallet with the install wizard.  You "
                        "can use this wallet again at any time by re-enabling "
                        "passphrases and entering its passphrase.")
            else:
                msg = _("Your current Electrum wallet can only be used with "
                        "an empty passphrase.  You must create a separate "
                        "wallet with the install wizard for other passphrases "
                        "as each one generates a new set of addresses.")
            msg += "\n\n" + _("Are you sure you want to proceed?")
            if not self.question(msg, title=title):
                return
            invoke_client('toggle_passphrase', unpair_after=currently_enabled)

        def change_homescreen():
            from PIL import Image  # FIXME
            dialog = QFileDialog(self, _("Choose Homescreen"))
            filename, __ = dialog.getOpenFileName()
            if filename:
                im = Image.open(str(filename))
                if im.size != (hs_cols, hs_rows):
                    raise Exception('Image must be 64 x 128 pixels')
                im = im.convert('1')
                pix = im.load()
                img = ''
                for j in range(hs_rows):
                    for i in range(hs_cols):
                        img += '1' if pix[i, j] else '0'
                img = ''.join(chr(int(img[i:i + 8], 2))
                              for i in range(0, len(img), 8))
                invoke_client('change_homescreen', img)

        def clear_homescreen():
            invoke_client('change_homescreen', '\x00')

        def set_pin():
            invoke_client('set_pin', remove=False)

        def clear_pin():
            invoke_client('set_pin', remove=True)

        def wipe_device():
            wallet = window.wallet
            if wallet and sum(wallet.get_balance()):
                title = _("Confirm Device Wipe")
                msg = _("Are you SURE you want to wipe the device?\n"
                        "Your wallet still has viacoins in it!")
                if not self.question(msg, title=title,
                                     icon=QMessageBox.Critical):
                    return
            invoke_client('wipe_device', unpair_after=True)

        def slider_moved():
            mins = timeout_slider.sliderPosition()
            timeout_minutes.setText(_("%2d minutes") % mins)

        def slider_released():
            config.set_session_timeout(timeout_slider.sliderPosition() * 60)

        # Information tab
        info_tab = QWidget()
        info_layout = QVBoxLayout(info_tab)
        info_glayout = QGridLayout()
        info_glayout.setColumnStretch(2, 1)
        device_label = QLabel()
        pin_set_label = QLabel()
        passphrases_label = QLabel()
        version_label = QLabel()
        device_id_label = QLabel()
        bl_hash_label = QLabel()
        bl_hash_label.setWordWrap(True)
        coins_label = QLabel()
        coins_label.setWordWrap(True)
        language_label = QLabel()
        initialized_label = QLabel()
        rows = [
            (_("Device Label"), device_label),
            (_("PIN set"), pin_set_label),
            (_("Passphrases"), passphrases_label),
            (_("Firmware Version"), version_label),
            (_("Device ID"), device_id_label),
            (_("Bootloader Hash"), bl_hash_label),
            (_("Supported Coins"), coins_label),
            (_("Language"), language_label),
            (_("Initialized"), initialized_label),
        ]
        for row_num, (label, widget) in enumerate(rows):
            info_glayout.addWidget(QLabel(label), row_num, 0)
            info_glayout.addWidget(widget, row_num, 1)
        info_layout.addLayout(info_glayout)

        # Settings tab
        settings_tab = QWidget()
        settings_layout = QVBoxLayout(settings_tab)
        settings_glayout = QGridLayout()

        # Settings tab - Label
        label_msg = QLabel(_("Name this {}.  If you have multiple devices "
                             "their labels help distinguish them.")
                           .format(plugin.device))
        label_msg.setWordWrap(True)
        label_label = QLabel(_("Device Label"))
        label_edit = QLineEdit()
        label_edit.setMinimumWidth(150)
        label_edit.setMaxLength(plugin.MAX_LABEL_LEN)
        label_apply = QPushButton(_("Apply"))
        label_apply.clicked.connect(rename)
        label_edit.textChanged.connect(set_label_enabled)
        settings_glayout.addWidget(label_label, 0, 0)
        settings_glayout.addWidget(label_edit, 0, 1, 1, 2)
        settings_glayout.addWidget(label_apply, 0, 3)
        settings_glayout.addWidget(label_msg, 1, 1, 1, -1)

        # Settings tab - PIN
        pin_label = QLabel(_("PIN Protection"))
        pin_button = QPushButton()
        pin_button.clicked.connect(set_pin)
        settings_glayout.addWidget(pin_label, 2, 0)
        settings_glayout.addWidget(pin_button, 2, 1)
        pin_msg = QLabel(_("PIN protection is strongly recommended.  "
                           "A PIN is your only protection against someone "
                           "stealing your viacoins if they obtain physical "
                           "access to your %s.") % plugin.device)
                           "stealing your viacoins if they obtain physical "
                           "access to your {}.").format(plugin.device))
Example #5
0
    def do_layout(self):
        if len(self.db.custom_column_label_map) == 0:
            self.central_widget.tabBar().setVisible(False)
        self.central_widget.clear()
        self.tabs = []
        self.labels = []
        self.tabs.append(QWidget(self))
        self.central_widget.addTab(self.tabs[0], _("&Basic metadata"))
        self.tabs[0].l = l = QVBoxLayout()
        self.tabs[0].tl = tl = QGridLayout()
        self.tabs[0].setLayout(l)
        w = getattr(self, 'custom_metadata_widgets_parent', None)
        if w is not None:
            self.tabs.append(w)
            self.central_widget.addTab(w, _('&Custom metadata'))
        l.addLayout(tl)
        l.addItem(QSpacerItem(10, 15, QSizePolicy.Expanding,
                              QSizePolicy.Fixed))

        sto = QWidget.setTabOrder
        sto(self.button_box, self.fetch_metadata_button)
        sto(self.fetch_metadata_button, self.config_metadata_button)
        sto(self.config_metadata_button, self.title)

        def create_row(row, one, two, three, col=1, icon='forward.png'):
            ql = BuddyLabel(one)
            tl.addWidget(ql, row, col + 0, 1, 1)
            self.labels.append(ql)
            tl.addWidget(one, row, col + 1, 1, 1)
            if two is not None:
                tl.addWidget(two, row, col + 2, 1, 1)
                two.setIcon(QIcon(I(icon)))
            ql = BuddyLabel(three)
            tl.addWidget(ql, row, col + 3, 1, 1)
            self.labels.append(ql)
            tl.addWidget(three, row, col + 4, 1, 1)
            sto(one, two)
            sto(two, three)

        tl.addWidget(self.swap_title_author_button, 0, 0, 1, 1)
        tl.addWidget(self.manage_authors_button, 1, 0, 1, 1)

        create_row(0, self.title, self.deduce_title_sort_button,
                   self.title_sort)
        sto(self.title_sort, self.authors)
        create_row(1, self.authors, self.deduce_author_sort_button,
                   self.author_sort)
        sto(self.author_sort, self.series)
        create_row(2,
                   self.series,
                   self.clear_series_button,
                   self.series_index,
                   icon='trash.png')
        sto(self.series_index, self.swap_title_author_button)
        sto(self.swap_title_author_button, self.manage_authors_button)

        tl.addWidget(self.formats_manager, 0, 6, 3, 1)

        self.splitter = Splitter(Qt.Horizontal, self)
        self.splitter.addWidget(self.cover)
        self.splitter.frame_resized.connect(self.cover.frame_resized)
        l.addWidget(self.splitter)
        self.tabs[0].gb = gb = QGroupBox(_('Change cover'), self)
        gb.l = l = QGridLayout()
        gb.setLayout(l)
        sto(self.manage_authors_button, self.cover.buttons[0])
        for i, b in enumerate(self.cover.buttons[:3]):
            l.addWidget(b, 0, i, 1, 1)
            sto(b, self.cover.buttons[i + 1])
        gb.hl = QHBoxLayout()
        for b in self.cover.buttons[3:]:
            gb.hl.addWidget(b)
        sto(self.cover.buttons[-2], self.cover.buttons[-1])
        l.addLayout(gb.hl, 1, 0, 1, 3)
        self.tabs[0].middle = w = QWidget(self)
        w.l = l = QGridLayout()
        w.setLayout(w.l)
        self.splitter.addWidget(w)

        def create_row2(row, widget, button=None, front_button=None):
            row += 1
            ql = BuddyLabel(widget)
            if front_button:
                ltl = QHBoxLayout()
                ltl.addWidget(front_button)
                ltl.addWidget(ql)
                l.addLayout(ltl, row, 0, 1, 1)
            else:
                l.addWidget(ql, row, 0, 1, 1)
            l.addWidget(widget, row, 1, 1, 2 if button is None else 1)
            if button is not None:
                l.addWidget(button, row, 2, 1, 1)
            if button is not None:
                sto(widget, button)

        l.addWidget(gb, 0, 0, 1, 3)
        self.tabs[0].spc_one = QSpacerItem(10, 10, QSizePolicy.Expanding,
                                           QSizePolicy.Expanding)
        l.addItem(self.tabs[0].spc_one, 1, 0, 1, 3)
        sto(self.cover.buttons[-1], self.rating)
        create_row2(1, self.rating, self.clear_ratings_button)
        sto(self.rating, self.clear_ratings_button)
        sto(self.clear_ratings_button, self.tags_editor_button)
        sto(self.tags_editor_button, self.tags)
        create_row2(2,
                    self.tags,
                    self.clear_tags_button,
                    front_button=self.tags_editor_button)
        sto(self.clear_tags_button, self.paste_isbn_button)
        sto(self.paste_isbn_button, self.identifiers)
        create_row2(3,
                    self.identifiers,
                    self.clear_identifiers_button,
                    front_button=self.paste_isbn_button)
        sto(self.clear_identifiers_button, self.timestamp)
        create_row2(4, self.timestamp, self.timestamp.clear_button)
        sto(self.timestamp.clear_button, self.pubdate)
        create_row2(5, self.pubdate, self.pubdate.clear_button)
        sto(self.pubdate.clear_button, self.publisher)
        create_row2(6, self.publisher)
        sto(self.publisher, self.languages)
        create_row2(7, self.languages)
        self.tabs[0].spc_two = QSpacerItem(10, 10, QSizePolicy.Expanding,
                                           QSizePolicy.Expanding)
        l.addItem(self.tabs[0].spc_two, 9, 0, 1, 3)
        l.addWidget(self.fetch_metadata_button, 10, 0, 1, 2)
        l.addWidget(self.config_metadata_button, 10, 2, 1, 1)

        self.tabs[0].gb2 = gb = QGroupBox(_('Co&mments'), self)
        gb.l = l = QVBoxLayout()
        gb.setLayout(l)
        l.addWidget(self.comments)
        self.splitter.addWidget(gb)

        self.set_custom_metadata_tab_order()
Example #6
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.l = gl = QGridLayout(self)
        self.changed = False

        self.bars = b = QComboBox(self)
        b.addItem(_('Choose which toolbar you want to customize'))
        ft = _('Tools for %s editors')
        for name, text in (
            (
                'global_book_toolbar',
                _('Book wide actions'),
            ),
            (
                'global_tools_toolbar',
                _('Book wide tools'),
            ),
            (
                'global_plugins_toolbar',
                _('Book wide tools from third party plugins'),
            ),
            ('editor_common_toolbar', ft % _('all')),
            (
                'editor_html_toolbar',
                ft % 'HTML',
            ),
            (
                'editor_css_toolbar',
                ft % 'CSS',
            ),
            (
                'editor_xml_toolbar',
                ft % 'XML',
            ),
            (
                'editor_format_toolbar',
                _('Text formatting actions'),
            ),
        ):
            b.addItem(text, name)
        self.la = la = QLabel(_('&Toolbar to customize:'))
        la.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        la.setBuddy(b)
        gl.addWidget(la), gl.addWidget(b, 0, 1)
        self.sl = l = QGridLayout()
        gl.addLayout(l, 1, 0, 1, -1)

        self.gb1 = gb1 = QGroupBox(_('A&vailable actions'), self)
        self.gb2 = gb2 = QGroupBox(_('&Current actions'), self)
        gb1.setFlat(True), gb2.setFlat(True)
        gb1.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        gb2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        l.addWidget(gb1, 0, 0, -1, 1), l.addWidget(gb2, 0, 2, -1, 1)
        self.available, self.current = ToolbarList(self), ToolbarList(self)
        self.ub = b = QToolButton(self)
        connect_lambda(b.clicked, self, lambda self: self.move(up=True))
        b.setToolTip(_('Move selected action up')), b.setIcon(
            QIcon(I('arrow-up.png')))
        self.db = b = QToolButton(self)
        connect_lambda(b.clicked, self, lambda self: self.move(up=False))
        b.setToolTip(_('Move selected action down')), b.setIcon(
            QIcon(I('arrow-down.png')))
        self.gl1 = gl1 = QVBoxLayout()
        gl1.addWidget(self.available), gb1.setLayout(gl1)
        self.gl2 = gl2 = QGridLayout()
        gl2.addWidget(self.current, 0, 0, -1, 1)
        gl2.addWidget(self.ub, 0, 1), gl2.addWidget(self.db, 2, 1)
        gb2.setLayout(gl2)
        self.lb = b = QToolButton(self)
        b.setToolTip(_('Add selected actions to the toolbar')), b.setIcon(
            QIcon(I('forward.png')))
        l.addWidget(b, 1, 1), b.clicked.connect(self.add_action)
        self.rb = b = QToolButton(self)
        b.setToolTip(_('Remove selected actions from the toolbar')), b.setIcon(
            QIcon(I('back.png')))
        l.addWidget(b, 3, 1), b.clicked.connect(self.remove_action)
        self.si = QSpacerItem(20,
                              10,
                              hPolicy=QSizePolicy.Preferred,
                              vPolicy=QSizePolicy.Expanding)
        l.setRowStretch(0, 10), l.setRowStretch(2, 10), l.setRowStretch(4, 10)
        l.addItem(self.si, 4, 1)

        self.read_settings()
        self.toggle_visibility(False)
        self.bars.currentIndexChanged.connect(self.bar_changed)

        self.toolbar_icon_size = ics = QSpinBox(self)
        ics.setMinimum(16), ics.setMaximum(128), ics.setSuffix(
            ' px'), ics.setValue(tprefs['toolbar_icon_size'])
        ics.setToolTip('<p>' + _('Adjust the size of icons on all toolbars'))
        self.h = h = QHBoxLayout()
        gl.addLayout(h, gl.rowCount(), 0, 1, -1)
        self.toolbar_icon_size_label = la = QLabel(_('Toolbar &icon size:'))
        la.setBuddy(ics)
        h.addWidget(la), h.addWidget(ics), h.addStretch(10)
Example #7
0
    def __init__(self, db, book_id_map, parent=None):
        from calibre.ebooks.oeb.polish.main import HELP
        QDialog.__init__(self, parent)
        self.db, self.book_id_map = weakref.ref(db), book_id_map
        self.setWindowIcon(QIcon(I('polish.png')))
        title = _('Polish book')
        if len(book_id_map) > 1:
            title = _('Polish %d books')%len(book_id_map)
        self.setWindowTitle(title)

        self.help_text = {
            'polish': _('<h3>About Polishing books</h3>%s')%HELP['about'].format(
                _('''<p>If you have both EPUB and ORIGINAL_EPUB in your book,
                  then polishing will run on ORIGINAL_EPUB (the same for other
                  ORIGINAL_* formats).  So if you
                  want Polishing to not run on the ORIGINAL_* format, delete the
                  ORIGINAL_* format before running it.</p>''')
            ),

            'embed':_('<h3>Embed referenced fonts</h3>%s')%HELP['embed'],
            'subset':_('<h3>Subsetting fonts</h3>%s')%HELP['subset'],

            'smarten_punctuation':
            _('<h3>Smarten punctuation</h3>%s')%HELP['smarten_punctuation'],

            'metadata':_('<h3>Updating metadata</h3>'
                         '<p>This will update all metadata <i>except</i> the cover in the'
                         ' e-book files to match the current metadata in the'
                         ' calibre library.</p>'
                         ' <p>Note that most e-book'
                         ' formats are not capable of supporting all the'
                         ' metadata in calibre.</p><p>There is a separate option to'
                         ' update the cover.</p>'),
            'do_cover': _('<h3>Update cover</h3><p>Update the covers in the e-book files to match the'
                        ' current cover in the calibre library.</p>'
                        '<p>If the e-book file does not have'
                        ' an identifiable cover, a new cover is inserted.</p>'
                        ),
            'jacket':_('<h3>Book jacket</h3>%s')%HELP['jacket'],
            'remove_jacket':_('<h3>Remove book jacket</h3>%s')%HELP['remove_jacket'],
            'remove_unused_css':_('<h3>Remove unused CSS rules</h3>%s')%HELP['remove_unused_css'],
            'compress_images': _('<h3>Losslessly compress images</h3>%s') % HELP['compress_images'],
            'add_soft_hyphens': _('<h3>Add soft-hyphens</h3>%s') % HELP['add_soft_hyphens'],
            'remove_soft_hyphens': _('<h3>Remove soft-hyphens</h3>%s') % HELP['remove_soft_hyphens'],
            'upgrade_book': _('<h3>Upgrade book internals</h3>%s') % HELP['upgrade_book'],
        }

        self.l = l = QGridLayout()
        self.setLayout(l)

        self.la = la = QLabel('<b>'+_('Select actions to perform:'))
        l.addWidget(la, 0, 0, 1, 2)

        count = 0
        self.all_actions = OrderedDict([
            ('embed', _('&Embed all referenced fonts')),
            ('subset', _('&Subset all embedded fonts')),
            ('smarten_punctuation', _('Smarten &punctuation')),
            ('metadata', _('Update &metadata in the book files')),
            ('do_cover', _('Update the &cover in the book files')),
            ('jacket', _('Add/replace metadata as a "book &jacket" page')),
            ('remove_jacket', _('&Remove a previously inserted book jacket')),
            ('remove_unused_css', _('Remove &unused CSS rules from the book')),
            ('compress_images', _('Losslessly &compress images')),
            ('add_soft_hyphens', _('Add s&oft hyphens')),
            ('remove_soft_hyphens', _('Remove soft hyphens')),
            ('upgrade_book', _('&Upgrade book internals')),
        ])
        prefs = gprefs.get('polishing_settings', {})
        for name, text in iteritems(self.all_actions):
            count += 1
            x = QCheckBox(text, self)
            x.setChecked(prefs.get(name, False))
            x.setObjectName(name)
            connect_lambda(x.stateChanged, self, lambda self, state: self.option_toggled(self.sender().objectName(), state))
            l.addWidget(x, count, 0, 1, 1)
            setattr(self, 'opt_'+name, x)
            la = QLabel(' <a href="#%s">%s</a>'%(name, _('About')))
            setattr(self, 'label_'+name, x)
            la.linkActivated.connect(self.help_link_activated)
            l.addWidget(la, count, 1, 1, 1)

        count += 1
        l.addItem(QSpacerItem(10, 10, vPolicy=QSizePolicy.Policy.Expanding), count, 1, 1, 2)

        la = self.help_label = QLabel('')
        self.help_link_activated('#polish')
        la.setWordWrap(True)
        la.setTextFormat(Qt.TextFormat.RichText)
        la.setFrameShape(QFrame.Shape.StyledPanel)
        la.setAlignment(Qt.AlignmentFlag.AlignLeft|Qt.AlignmentFlag.AlignTop)
        la.setLineWidth(2)
        la.setStyleSheet('QLabel { margin-left: 75px }')
        l.addWidget(la, 0, 2, count+1, 1)
        l.setColumnStretch(2, 1)

        self.show_reports = sr = QCheckBox(_('Show &report'), self)
        sr.setChecked(gprefs.get('polish_show_reports', True))
        sr.setToolTip(textwrap.fill(_('Show a report of all the actions performed'
                        ' after polishing is completed')))
        l.addWidget(sr, count+1, 0, 1, 1)
        self.bb = bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok|QDialogButtonBox.StandardButton.Cancel)
        bb.accepted.connect(self.accept)
        bb.rejected.connect(self.reject)
        self.save_button = sb = bb.addButton(_('&Save settings'), QDialogButtonBox.ButtonRole.ActionRole)
        sb.clicked.connect(self.save_settings)
        self.load_button = lb = bb.addButton(_('&Load settings'), QDialogButtonBox.ButtonRole.ActionRole)
        self.load_menu = QMenu(lb)
        lb.setMenu(self.load_menu)
        self.all_button = b = bb.addButton(_('Select &all'), QDialogButtonBox.ButtonRole.ActionRole)
        connect_lambda(b.clicked, self, lambda self: self.select_all(True))
        self.none_button = b = bb.addButton(_('Select &none'), QDialogButtonBox.ButtonRole.ActionRole)
        connect_lambda(b.clicked, self, lambda self: self.select_all(False))
        l.addWidget(bb, count+1, 1, 1, -1)
        self.setup_load_button()

        self.resize(QSize(950, 600))
Example #8
0
    def __init__(self, parent, prefs):
        QFrame.__init__(self, parent)
        self.prefs = prefs
        self.setFrameShape(QFrame.StyledPanel)
        self.setMinimumWidth(250)
        self.stack = s = QStackedWidget(self)
        self.l = l = QVBoxLayout()
        self.setLayout(l)
        l.addWidget(s)
        self.root_pane = rp = QWidget(self)
        self.item_pane = ip = QWidget(self)
        self.current_item = None
        s.addWidget(rp)
        s.addWidget(ip)

        self.l1 = la = QLabel('<p>' + _(
            'You can edit existing entries in the Table of Contents by clicking them'
            ' in the panel to the left.'
        ) + '<p>' + _(
            'Entries with a green tick next to them point to a location that has '
            'been verified to exist. Entries with a red dot are broken and may need'
            ' to be fixed.'))
        la.setStyleSheet('QLabel { margin-bottom: 20px }')
        la.setWordWrap(True)
        l = rp.l = QVBoxLayout()
        rp.setLayout(l)
        l.addWidget(la)
        self.add_new_to_root_button = b = QPushButton(_('Create a &new entry'))
        b.clicked.connect(self.add_new_to_root)
        l.addWidget(b)
        l.addStretch()

        self.cfmhb = b = QPushButton(_('Generate ToC from &major headings'))
        b.clicked.connect(self.create_from_major_headings)
        b.setToolTip(
            textwrap.fill(
                _('Generate a Table of Contents from the major headings in the book.'
                  ' This will work if the book identifies its headings using HTML'
                  ' heading tags. Uses the <h1>, <h2> and <h3> tags.')))
        l.addWidget(b)
        self.cfmab = b = QPushButton(_('Generate ToC from &all headings'))
        b.clicked.connect(self.create_from_all_headings)
        b.setToolTip(
            textwrap.fill(
                _('Generate a Table of Contents from all the headings in the book.'
                  ' This will work if the book identifies its headings using HTML'
                  ' heading tags. Uses the <h1-6> tags.')))
        l.addWidget(b)

        self.lb = b = QPushButton(_('Generate ToC from &links'))
        b.clicked.connect(self.create_from_links)
        b.setToolTip(
            textwrap.fill(
                _('Generate a Table of Contents from all the links in the book.'
                  ' Links that point to destinations that do not exist in the book are'
                  ' ignored. Also multiple links with the same destination or the same'
                  ' text are ignored.')))
        l.addWidget(b)

        self.cfb = b = QPushButton(_('Generate ToC from &files'))
        b.clicked.connect(self.create_from_files)
        b.setToolTip(
            textwrap.fill(
                _('Generate a Table of Contents from individual files in the book.'
                  ' Each entry in the ToC will point to the start of the file, the'
                  ' text of the entry will be the "first line" of text from the file.'
                  )))
        l.addWidget(b)

        self.xpb = b = QPushButton(_('Generate ToC from &XPath'))
        b.clicked.connect(self.create_from_user_xpath)
        b.setToolTip(
            textwrap.fill(
                _('Generate a Table of Contents from arbitrary XPath expressions.'
                  )))
        l.addWidget(b)

        self.fal = b = QPushButton(_('&Flatten the ToC'))
        b.clicked.connect(self.flatten_toc)
        b.setToolTip(
            textwrap.fill(
                _('Flatten the Table of Contents, putting all entries at the top level'
                  )))
        l.addWidget(b)

        l.addStretch()
        self.w1 = la = QLabel(
            _('<b>WARNING:</b> calibre only supports the '
              'creation of linear ToCs in AZW3 files. In a '
              'linear ToC every entry must point to a '
              'location after the previous entry. If you '
              'create a non-linear ToC it will be '
              'automatically re-arranged inside the AZW3 file.'))
        la.setWordWrap(True)
        l.addWidget(la)

        l = ip.l = QGridLayout()
        ip.setLayout(l)
        la = ip.heading = QLabel('')
        l.addWidget(la, 0, 0, 1, 2)
        la.setWordWrap(True)
        la = ip.la = QLabel(
            _('You can move this entry around the Table of Contents by drag '
              'and drop or using the up and down buttons to the left'))
        la.setWordWrap(True)
        l.addWidget(la, 1, 0, 1, 2)

        # Item status
        ip.hl1 = hl = QFrame()
        hl.setFrameShape(hl.HLine)
        l.addWidget(hl, l.rowCount(), 0, 1, 2)
        self.icon_label = QLabel()
        self.status_label = QLabel()
        self.status_label.setWordWrap(True)
        l.addWidget(self.icon_label, l.rowCount(), 0)
        l.addWidget(self.status_label, l.rowCount() - 1, 1)
        ip.hl2 = hl = QFrame()
        hl.setFrameShape(hl.HLine)
        l.addWidget(hl, l.rowCount(), 0, 1, 2)

        # Edit/remove item
        rs = l.rowCount()
        ip.b1 = b = QPushButton(QIcon(I('edit_input.png')),
                                _('Change the &location this entry points to'),
                                self)
        b.clicked.connect(self.edit_item)
        l.addWidget(b, l.rowCount() + 1, 0, 1, 2)
        ip.b2 = b = QPushButton(QIcon(I('trash.png')), _('&Remove this entry'),
                                self)
        l.addWidget(b, l.rowCount(), 0, 1, 2)
        b.clicked.connect(self.delete_item)
        ip.hl3 = hl = QFrame()
        hl.setFrameShape(hl.HLine)
        l.addWidget(hl, l.rowCount(), 0, 1, 2)
        l.setRowMinimumHeight(rs, 20)

        # Add new item
        rs = l.rowCount()
        ip.b3 = b = QPushButton(QIcon(I('plus.png')),
                                _('New entry &inside this entry'))
        connect_lambda(b.clicked, self, lambda self: self.add_new('inside'))
        l.addWidget(b, l.rowCount() + 1, 0, 1, 2)
        ip.b4 = b = QPushButton(QIcon(I('plus.png')),
                                _('New entry &above this entry'))
        connect_lambda(b.clicked, self, lambda self: self.add_new('before'))
        l.addWidget(b, l.rowCount(), 0, 1, 2)
        ip.b5 = b = QPushButton(QIcon(I('plus.png')),
                                _('New entry &below this entry'))
        connect_lambda(b.clicked, self, lambda self: self.add_new('after'))
        l.addWidget(b, l.rowCount(), 0, 1, 2)
        # Flatten entry
        ip.b3 = b = QPushButton(QIcon(I('heuristics.png')),
                                _('&Flatten this entry'))
        b.clicked.connect(self.flatten_item)
        b.setToolTip(
            _('All children of this entry are brought to the same '
              'level as this entry.'))
        l.addWidget(b, l.rowCount() + 1, 0, 1, 2)

        ip.hl4 = hl = QFrame()
        hl.setFrameShape(hl.HLine)
        l.addWidget(hl, l.rowCount(), 0, 1, 2)
        l.setRowMinimumHeight(rs, 20)

        # Return to welcome
        rs = l.rowCount()
        ip.b4 = b = QPushButton(QIcon(I('back.png')),
                                _('&Return to welcome screen'))
        b.clicked.connect(self.go_to_root)
        b.setToolTip(_('Go back to the top level view'))
        l.addWidget(b, l.rowCount() + 1, 0, 1, 2)

        l.setRowMinimumHeight(rs, 20)

        l.addWidget(QLabel(), l.rowCount(), 0, 1, 2)
        l.setColumnStretch(1, 10)
        l.setRowStretch(l.rowCount() - 1, 10)
        self.w2 = la = QLabel(self.w1.text())
        self.w2.setWordWrap(True)
        l.addWidget(la, l.rowCount(), 0, 1, 2)
Example #9
0
    def __init__(self, parent, prefs):
        QWidget.__init__(self, parent)
        self.toc_title = None
        self.prefs = prefs
        l = self.l = QGridLayout()
        self.setLayout(l)
        self.tocw = t = TreeWidget(self)
        self.tocw.edit_item.connect(self.edit_item)
        l.addWidget(t, 0, 0, 7, 3)
        self.up_button = b = QToolButton(self)
        b.setIcon(QIcon(I('arrow-up.png')))
        b.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
        l.addWidget(b, 0, 3)
        b.setToolTip(_('Move current entry up [Ctrl+Up]'))
        b.clicked.connect(self.move_up)

        self.left_button = b = QToolButton(self)
        b.setIcon(QIcon(I('back.png')))
        b.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
        l.addWidget(b, 2, 3)
        b.setToolTip(_('Unindent the current entry [Ctrl+Left]'))
        b.clicked.connect(self.tocw.move_left)

        self.del_button = b = QToolButton(self)
        b.setIcon(QIcon(I('trash.png')))
        b.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
        l.addWidget(b, 3, 3)
        b.setToolTip(_('Remove all selected entries'))
        b.clicked.connect(self.del_items)

        self.right_button = b = QToolButton(self)
        b.setIcon(QIcon(I('forward.png')))
        b.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
        l.addWidget(b, 4, 3)
        b.setToolTip(_('Indent the current entry [Ctrl+Right]'))
        b.clicked.connect(self.tocw.move_right)

        self.down_button = b = QToolButton(self)
        b.setIcon(QIcon(I('arrow-down.png')))
        b.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
        l.addWidget(b, 6, 3)
        b.setToolTip(_('Move current entry down [Ctrl+Down]'))
        b.clicked.connect(self.move_down)
        self.expand_all_button = b = QPushButton(_('&Expand all'))
        col = 7
        l.addWidget(b, col, 0)
        b.clicked.connect(self.tocw.expandAll)
        self.collapse_all_button = b = QPushButton(_('&Collapse all'))
        b.clicked.connect(self.tocw.collapseAll)
        l.addWidget(b, col, 1)
        self.default_msg = _('Double click on an entry to change the text')
        self.hl = hl = QLabel(self.default_msg)
        hl.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        l.addWidget(hl, col, 2, 1, -1)
        self.item_view = i = ItemView(self, self.prefs)
        self.item_view.delete_item.connect(self.delete_current_item)
        i.add_new_item.connect(self.add_new_item)
        i.create_from_xpath.connect(self.create_from_xpath)
        i.create_from_links.connect(self.create_from_links)
        i.create_from_files.connect(self.create_from_files)
        i.flatten_item.connect(self.flatten_item)
        i.flatten_toc.connect(self.flatten_toc)
        i.go_to_root.connect(self.go_to_root)
        l.addWidget(i, 0, 4, col, 1)

        l.setColumnStretch(2, 10)
Example #10
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.l = l = QGridLayout(self)
        self.setLayout(l)

        self.enabled = c = QCheckBox(self)
        l.addWidget(c, l.rowCount(), 0, 1, 2)
        c.setVisible(False)
        c.stateChanged.connect(self.changed)

        self.l1 = l1 = QLabel('')
        l1.setWordWrap(True)
        l.addWidget(l1, l.rowCount(), 0, 1, 2)

        self.add_button = QPushButton(QIcon(I('plus.png')), _('Add rule'),
                                      self)
        self.remove_button = QPushButton(QIcon(I('minus.png')),
                                         _('Remove rule(s)'), self)
        self.add_button.clicked.connect(self.add_rule)
        self.remove_button.clicked.connect(self.remove_rule)
        l.addWidget(self.add_button, l.rowCount(), 0)
        l.addWidget(self.remove_button, l.rowCount() - 1, 1)

        self.g = g = QGridLayout()
        self.rules_view = QListView(self)
        self.rules_view.doubleClicked.connect(self.edit_rule)
        self.rules_view.setSelectionMode(self.rules_view.ExtendedSelection)
        self.rules_view.setAlternatingRowColors(True)
        self.rtfd = RichTextDelegate(parent=self.rules_view, max_width=400)
        self.rules_view.setItemDelegate(self.rtfd)
        g.addWidget(self.rules_view, 0, 0, 2, 1)

        self.up_button = b = QToolButton(self)
        b.setIcon(QIcon(I('arrow-up.png')))
        b.setToolTip(_('Move the selected rule up'))
        b.clicked.connect(self.move_up)
        g.addWidget(b, 0, 1, 1, 1, Qt.AlignTop)
        self.down_button = b = QToolButton(self)
        b.setIcon(QIcon(I('arrow-down.png')))
        b.setToolTip(_('Move the selected rule down'))
        b.clicked.connect(self.move_down)
        g.addWidget(b, 1, 1, 1, 1, Qt.AlignBottom)

        l.addLayout(g, l.rowCount(), 0, 1, 2)
        l.setRowStretch(l.rowCount() - 1, 10)

        self.add_advanced_button = b = QPushButton(QIcon(I('plus.png')),
                                                   _('Add advanced rule'),
                                                   self)
        b.clicked.connect(self.add_advanced)
        self.hb = hb = QHBoxLayout()
        l.addLayout(hb, l.rowCount(), 0, 1, 2)
        hb.addWidget(b)
        hb.addStretch(10)
        self.export_button = b = QPushButton(_('E&xport'), self)
        b.clicked.connect(self.export_rules)
        b.setToolTip(_('Export these rules to a file'))
        hb.addWidget(b)
        self.import_button = b = QPushButton(_('&Import'), self)
        b.setToolTip(_('Import rules from a file'))
        b.clicked.connect(self.import_rules)
        hb.addWidget(b)
Example #11
0
    def setup_ui(self):
        self.vl = vl = QVBoxLayout(self)
        self.stack = l = QStackedLayout()
        self.pi = pi = ProgressIndicator(self, 256)
        vl.addLayout(l), vl.addWidget(self.bb)
        self.restore_defs_button = b = self.bb.addButton(
            _('Restore &default icons'), self.bb.ActionRole)
        b.clicked.connect(self.restore_defaults)
        b.setIcon(QIcon(I('view-refresh.png')))
        self.c = c = QWidget(self)
        self.c.v = v = QVBoxLayout(self.c)
        v.addStretch(), v.addWidget(pi, 0, Qt.AlignCenter)
        self.wait_msg = m = QLabel(self)
        v.addWidget(m, 0, Qt.AlignCenter), v.addStretch()
        m.setStyleSheet('QLabel { font-size: 40px; font-weight: bold }')
        self.start_spinner()

        l.addWidget(c)
        self.w = w = QWidget(self)
        l.addWidget(w)
        w.l = l = QGridLayout(w)

        def add_row(x, y=None):
            if isinstance(x, type('')):
                x = QLabel(x)
            row = l.rowCount()
            if y is None:
                if isinstance(x, QLabel):
                    x.setWordWrap(True)
                l.addWidget(x, row, 0, 1, 2)
            else:
                if isinstance(x, QLabel):
                    x.setBuddy(y)
                l.addWidget(x, row, 0), l.addWidget(y, row, 1)

        add_row(
            _('Choose an icon theme below. You will need to restart'
              ' calibre to see the new icons.'))
        add_row(
            _('Current icon theme:') + '\xa0<b>' +
            (self.current_theme or 'None'))
        self.sort_by = sb = QComboBox(self)
        add_row(_('&Sort by:'), sb)
        sb.addItems([
            _('Number of icons'),
            _('Popularity'),
            _('Name'),
        ])
        sb.setEditable(False), sb.setCurrentIndex(
            gprefs.get('choose_icon_theme_sort_by', 1))
        sb.currentIndexChanged[int].connect(self.re_sort)
        sb.currentIndexChanged[int].connect(
            lambda: gprefs.set('choose_icon_theme_sort_by', sb.currentIndex()))
        self.theme_list = tl = QListWidget(self)
        tl.setVerticalScrollMode(tl.ScrollPerPixel)
        self.delegate = Delegate(tl)
        tl.setItemDelegate(self.delegate)
        tl.itemDoubleClicked.connect(self.accept)
        add_row(tl)

        t = Thread(name='GetIconThemes', target=self.get_themes)
        t.daemon = True
        t.start()
Example #12
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.l = l = QGridLayout(self)
        l.setContentsMargins(0, 0, 0, 0)
        self.setLayout(l)

        self.fl = fl = QLabel(_('&Find:'))
        fl.setAlignment(Qt.AlignRight | Qt.AlignCenter)
        self.find_text = ft = HistoryBox(self, _('Clear search history'))
        ft.save_search.connect(self.save_search)
        ft.show_saved_searches.connect(self.show_saved_searches)
        ft.initialize('tweak_book_find_edit')
        ft.lineEdit().returnPressed.connect(
            lambda: self.search_triggered.emit('find'))
        fl.setBuddy(ft)
        l.addWidget(fl, 0, 0)
        l.addWidget(ft, 0, 1)

        self.rl = rl = QLabel(_('&Replace:'))
        rl.setAlignment(Qt.AlignRight | Qt.AlignCenter)
        self.replace_text = rt = HistoryBox(self, _('Clear replace history'))
        rt.save_search.connect(self.save_search)
        rt.show_saved_searches.connect(self.show_saved_searches)
        rt.initialize('tweak_book_replace_edit')
        rl.setBuddy(rt)
        l.addWidget(rl, 1, 0)
        l.addWidget(rt, 1, 1)
        l.setColumnStretch(1, 10)

        self.fb = fb = PushButton(_('&Find'), 'find', self)
        self.rfb = rfb = PushButton(_('Replace a&nd Find'), 'replace-find',
                                    self)
        self.rb = rb = PushButton(_('&Replace'), 'replace', self)
        self.rab = rab = PushButton(_('Replace &all'), 'replace-all', self)
        l.addWidget(fb, 0, 2)
        l.addWidget(rfb, 0, 3)
        l.addWidget(rb, 1, 2)
        l.addWidget(rab, 1, 3)

        self.ml = ml = QLabel(_('&Mode:'))
        self.ol = ol = QHBoxLayout()
        ml.setAlignment(Qt.AlignRight | Qt.AlignCenter)
        l.addWidget(ml, 2, 0)
        l.addLayout(ol, 2, 1, 1, 3)
        self.mode_box = mb = ModeBox(self)
        mb.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        ml.setBuddy(mb)
        ol.addWidget(mb)

        self.where_box = wb = WhereBox(self)
        wb.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
        ol.addWidget(wb)

        self.direction_box = db = DirectionBox(self)
        db.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        ol.addWidget(db)

        self.cs = cs = QCheckBox(_('&Case sensitive'))
        cs.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        ol.addWidget(cs)

        self.wr = wr = QCheckBox(_('&Wrap'))
        wr.setToolTip('<p>' + _(
            'When searching reaches the end, wrap around to the beginning and continue the search'
        ))
        wr.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        ol.addWidget(wr)

        self.da = da = QCheckBox(_('&Dot all'))
        da.setToolTip('<p>' + _(
            "Make the '.' special character match any character at all, including a newline"
        ))
        da.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        ol.addWidget(da)

        self.mode_box.currentIndexChanged[int].connect(self.da.setVisible)

        ol.addStretch(10)
Example #13
0
    def setupUi(self):
        self.setObjectName("Dialog")
        self.resize(1024, 700)
        self.setWindowIcon(QIcon(I('convert.png')))
        self.gridLayout = QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.input_label = QLabel(self)
        self.input_label.setObjectName("input_label")
        self.horizontalLayout.addWidget(self.input_label)
        self.input_formats = QComboBox(self)
        self.input_formats.setSizeAdjustPolicy(
            QComboBox.AdjustToMinimumContentsLengthWithIcon)
        self.input_formats.setMinimumContentsLength(5)
        self.input_formats.setObjectName("input_formats")
        self.horizontalLayout.addWidget(self.input_formats)
        self.opt_individual_saved_settings = QCheckBox(self)
        self.opt_individual_saved_settings.setObjectName(
            "opt_individual_saved_settings")
        self.horizontalLayout.addWidget(self.opt_individual_saved_settings)
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        self.label_2 = QLabel(self)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout.addWidget(self.label_2)
        self.output_formats = QComboBox(self)
        self.output_formats.setSizeAdjustPolicy(
            QComboBox.AdjustToMinimumContentsLengthWithIcon)
        self.output_formats.setMinimumContentsLength(5)
        self.output_formats.setObjectName("output_formats")
        self.horizontalLayout.addWidget(self.output_formats)
        self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 2)
        self.groups = QListView(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.groups.sizePolicy().hasHeightForWidth())
        self.groups.setSizePolicy(sizePolicy)
        self.groups.setTabKeyNavigation(True)
        self.groups.setIconSize(QSize(48, 48))
        self.groups.setWordWrap(True)
        self.groups.setObjectName("groups")
        self.gridLayout.addWidget(self.groups, 1, 0, 3, 1)
        self.scrollArea = QScrollArea(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(4)
        sizePolicy.setVerticalStretch(10)
        sizePolicy.setHeightForWidth(
            self.scrollArea.sizePolicy().hasHeightForWidth())
        self.scrollArea.setSizePolicy(sizePolicy)
        self.scrollArea.setFrameShape(QFrame.NoFrame)
        self.scrollArea.setLineWidth(0)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        self.page = QWidget()
        self.page.setObjectName("page")
        self.gridLayout.addWidget(self.scrollArea, 1, 1, 1, 1)
        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok
                                          | QDialogButtonBox.RestoreDefaults)
        self.buttonBox.setObjectName("buttonBox")
        self.gridLayout.addWidget(self.buttonBox, 3, 1, 1, 1)
        self.help = QTextEdit(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.help.sizePolicy().hasHeightForWidth())
        self.help.setSizePolicy(sizePolicy)
        self.help.setMaximumHeight(80)
        self.help.setObjectName("help")
        self.gridLayout.addWidget(self.help, 2, 1, 1, 1)
        self.input_label.setBuddy(self.input_formats)
        self.label_2.setBuddy(self.output_formats)
        self.input_label.setText(_("&Input format:"))
        self.opt_individual_saved_settings.setText(
            _("Use &saved conversion settings for individual books"))
        self.label_2.setText(_("&Output format:"))

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
Example #14
0
    def __init__(self, parent, view, row, link_delegate):
        QDialog.__init__(self, parent)
        self.normal_brush = QBrush(Qt.white)
        self.marked_brush = QBrush(Qt.lightGray)
        self.marked = None
        self.gui = parent
        self.splitter = QSplitter(self)
        self._l = l = QVBoxLayout(self)
        self.setLayout(l)
        l.addWidget(self.splitter)

        self.cover = CoverView(self)
        self.cover.resizeEvent = self.cover_view_resized
        self.cover.cover_changed.connect(self.cover_changed)
        self.cover_pixmap = None
        self.cover.sizeHint = self.details_size_hint
        self.splitter.addWidget(self.cover)

        self.details = Details(parent.book_details.book_info, self)
        self.details.page().setLinkDelegationPolicy(
            self.details.page().DelegateAllLinks)
        self.details.linkClicked.connect(self.link_clicked)
        s = self.details.page().settings()
        s.setAttribute(s.JavascriptEnabled, False)
        self.css = css()
        self.link_delegate = link_delegate
        self.details.setAttribute(Qt.WA_OpaquePaintEvent, False)
        palette = self.details.palette()
        self.details.setAcceptDrops(False)
        palette.setBrush(QPalette.Base, Qt.transparent)
        self.details.page().setPalette(palette)

        self.c = QWidget(self)
        self.c.l = l2 = QGridLayout(self.c)
        self.c.setLayout(l2)
        l2.addWidget(self.details, 0, 0, 1, -1)
        self.splitter.addWidget(self.c)

        self.fit_cover = QCheckBox(_('Fit &cover within view'), self)
        self.fit_cover.setChecked(
            gprefs.get('book_info_dialog_fit_cover', True))
        l2.addWidget(self.fit_cover, l2.rowCount(), 0, 1, -1)
        self.previous_button = QPushButton(QIcon(I('previous.png')),
                                           _('&Previous'), self)
        self.previous_button.clicked.connect(self.previous)
        l2.addWidget(self.previous_button, l2.rowCount(), 0)
        self.next_button = QPushButton(QIcon(I('next.png')), _('&Next'), self)
        self.next_button.clicked.connect(self.__next__)
        l2.addWidget(self.next_button, l2.rowCount() - 1, 1)

        self.view = view
        self.current_row = None
        self.refresh(row)
        self.view.model().new_bookdisplay_data.connect(self.slave)
        self.fit_cover.stateChanged.connect(self.toggle_cover_fit)
        self.ns = QShortcut(QKeySequence('Alt+Right'), self)
        self.ns.activated.connect(self.__next__)
        self.ps = QShortcut(QKeySequence('Alt+Left'), self)
        self.ps.activated.connect(self.previous)
        self.next_button.setToolTip(
            _('Next [%s]') %
            str(self.ns.key().toString(QKeySequence.NativeText)))
        self.previous_button.setToolTip(
            _('Previous [%s]') %
            str(self.ps.key().toString(QKeySequence.NativeText)))

        geom = QCoreApplication.instance().desktop().availableGeometry(self)
        screen_height = geom.height() - 100
        screen_width = geom.width() - 100
        self.resize(max(int(screen_width / 2), 700), screen_height)
        saved_layout = gprefs.get('book_info_dialog_layout', None)
        if saved_layout is not None:
            try:
                self.restoreGeometry(saved_layout[0])
                self.splitter.restoreState(saved_layout[1])
            except Exception:
                pass
Example #15
0
    def __init__(self,
                 field_metadata,
                 parent=None,
                 revert_tooltip=None,
                 datetime_fmt='MMMM yyyy',
                 blank_as_equal=True,
                 fields=('title', 'authors', 'series', 'tags', 'rating',
                         'publisher', 'pubdate', 'identifiers', 'languages',
                         'comments', 'cover'),
                 db=None):
        QWidget.__init__(self, parent)
        self.l = l = QGridLayout()
        l.setContentsMargins(0, 0, 0, 0)
        self.setLayout(l)
        revert_tooltip = revert_tooltip or _('Revert %s')
        self.current_mi = None
        self.changed_font = QFont(QApplication.font())
        self.changed_font.setBold(True)
        self.changed_font.setItalic(True)
        self.blank_as_equal = blank_as_equal

        self.widgets = OrderedDict()
        row = 0

        for field in fields:
            m = field_metadata[field]
            dt = m['datatype']
            extra = None
            if 'series' in {field, dt}:
                cls = SeriesEdit
            elif field == 'identifiers':
                cls = IdentifiersEdit
            elif field == 'languages':
                cls = LanguagesEdit
            elif 'comments' in {field, dt}:
                cls = CommentsEdit
            elif 'rating' in {field, dt}:
                cls = RatingsEdit
            elif dt == 'datetime':
                extra = datetime_fmt
                cls = DateEdit
            elif field == 'cover':
                cls = CoverView
            elif dt in {'text', 'enum'}:
                cls = LineEdit
            else:
                continue
            neww = cls(field, True, self, m, extra)
            neww.changed.connect(partial(self.changed, field))
            if isinstance(neww, EditWithComplete):
                try:
                    neww.update_items_cache(db.new_api.all_field_names(field))
                except ValueError:
                    pass  # A one-one field like title
            if isinstance(neww, SeriesEdit):
                neww.set_db(db.new_api)
            oldw = cls(field, False, self, m, extra)
            newl = QLabel('&%s:' % m['name'])
            newl.setBuddy(neww)
            button = RightClickButton(self)
            button.setIcon(QIcon(I('back.png')))
            button.clicked.connect(partial(self.revert, field))
            button.setToolTip(revert_tooltip % m['name'])
            if field == 'identifiers':
                button.m = m = QMenu(button)
                button.setMenu(m)
                button.setPopupMode(QToolButton.DelayedPopup)
                m.addAction(button.toolTip()).triggered.connect(button.click)
                m.actions()[0].setIcon(button.icon())
                m.addAction(_('Merge identifiers')).triggered.connect(
                    self.merge_identifiers)
                m.actions()[1].setIcon(QIcon(I('merge.png')))
            elif field == 'tags':
                button.m = m = QMenu(button)
                button.setMenu(m)
                button.setPopupMode(QToolButton.DelayedPopup)
                m.addAction(button.toolTip()).triggered.connect(button.click)
                m.actions()[0].setIcon(button.icon())
                m.addAction(_('Merge tags')).triggered.connect(self.merge_tags)
                m.actions()[1].setIcon(QIcon(I('merge.png')))

            self.widgets[field] = Widgets(neww, oldw, newl, button)
            for i, w in enumerate((newl, neww, button, oldw)):
                c = i if i < 2 else i + 1
                if w is oldw:
                    c += 1
                l.addWidget(w, row, c)
            row += 1

        self.sep = f = QFrame(self)
        f.setFrameShape(f.VLine)
        l.addWidget(f, 0, 2, row, 1)
        self.sep2 = f = QFrame(self)
        f.setFrameShape(f.VLine)
        l.addWidget(f, 0, 4, row, 1)
        if 'comments' in self.widgets and not gprefs.get(
                'diff_widget_show_comments_controls', True):
            self.widgets['comments'].new.hide_toolbars()
Example #16
0
    def __init__(self, gui, icon, do_user_config):
        QDialog.__init__(self, gui)
        self.icon = icon
        self.gui = gui
        self.do_user_config = do_user_config

        self.setAttribute(Qt.WA_DeleteOnClose)

        self.setWindowTitle(_('Prince PDF'))
        self.setWindowIcon(icon)

        self.l = QGridLayout()
        self.setLayout(self.l)

        self.image = QLabel()
        self.image.setPixmap(icon.pixmap(120, 120))
        self.l.addWidget(self.image, 1, 1, 4, 1, Qt.AlignVCenter)

        self.convert_to_PDF_button = QPushButton(_('Convert to &PDF'), self)
        self.convert_to_PDF_button.clicked.connect(self.convert_to_PDF)
        self.convert_to_PDF_button.setDefault(True)
        self.convert_to_PDF_button.setToolTip(
            _('<qt>Start the conversion process</qt>'))
        self.l.addWidget(self.convert_to_PDF_button, 1, 2, Qt.AlignVCenter)

        self.view_log = QPushButton(_('&View log'), self)
        self.view_log.clicked.connect(self.show_log)
        self.view_log.setToolTip(
            _('<qt>Display the log from the last Prince run</qt>'))
        self.l.addWidget(self.view_log, 2, 2, Qt.AlignVCenter)
        self.view_log.hide()

        self.conf_button = QPushButton(_('Con&figure'), self)
        self.conf_button.clicked.connect(self.config)
        self.conf_button.setToolTip(_('<qt>Configure this plugin</qt>'))
        self.l.addWidget(self.conf_button, 4, 2, Qt.AlignVCenter)

        self.info = QLabel()
        self.l.addWidget(self.info, 5, 1, 1, -1)

        self.suggestion = QLabel()
        self.suggestion.setAlignment(Qt.AlignCenter)
        self.l.addWidget(self.suggestion, 6, 1, 1, -1)

        self.l.setColumnStretch(1, 1)
        self.l.setColumnStretch(2, 10)
        self.l.setRowStretch(1, 1)
        self.l.setRowStretch(2, 1)
        self.l.setRowStretch(3, 10)
        self.l.setRowStretch(4, 1)
        self.l.setRowStretch(5, 1)
        self.l.setRowStretch(6, 1)
        self.l.setRowMinimumHeight(1, 1)
        self.l.setRowMinimumHeight(2, 1)
        self.l.setRowMinimumHeight(3, 1)
        self.l.setRowMinimumHeight(4, 1)
        self.l.setRowMinimumHeight(5, 1)
        self.l.setRowMinimumHeight(6, 1)

        self.buttons = QDialogButtonBox(QDialogButtonBox.Close
                                        | QDialogButtonBox.Help)
        self.l.addWidget(self.buttons, 7, 1, 1, -1)
        self.buttons.rejected.connect(self.reject)
        self.buttons.helpRequested.connect(self.about)

        self.adjustSize()

        # Update the info now and every time the selection or the data changes
        self.gui.library_view.model().dataChanged.connect(self.update_info)
        self.gui.library_view.selectionModel().selectionChanged.connect(
            self.update_info)
        self.update_info()
Example #17
0
    def __init__(self, parent, view, row, link_delegate):
        QDialog.__init__(self, parent)
        self.normal_brush = QBrush(Qt.white)
        self.marked_brush = QBrush(Qt.lightGray)
        self.marked = None
        self.gui = parent
        self.splitter = QSplitter(self)
        self._l = l = QVBoxLayout(self)
        self.setLayout(l)
        l.addWidget(self.splitter)

        self.cover = Cover(self, show_size=gprefs['bd_overlay_cover_size'])
        self.cover.resizeEvent = self.cover_view_resized
        self.cover.cover_changed.connect(self.cover_changed)
        self.cover.open_with_requested.connect(self.open_with)
        self.cover.choose_open_with_requested.connect(self.choose_open_with)
        self.cover_pixmap = None
        self.cover.sizeHint = self.details_size_hint
        self.splitter.addWidget(self.cover)

        self.details = Details(parent.book_details.book_info, self)
        self.details.anchor_clicked.connect(self.on_link_clicked)
        self.link_delegate = link_delegate
        self.details.setAttribute(Qt.WA_OpaquePaintEvent, False)
        palette = self.details.palette()
        self.details.setAcceptDrops(False)
        palette.setBrush(QPalette.Base, Qt.transparent)
        self.details.setPalette(palette)

        self.c = QWidget(self)
        self.c.l = l2 = QGridLayout(self.c)
        l2.setContentsMargins(0, 0, 0, 0)
        self.c.setLayout(l2)
        l2.addWidget(self.details, 0, 0, 1, -1)
        self.splitter.addWidget(self.c)

        self.fit_cover = QCheckBox(_('Fit &cover within view'), self)
        self.fit_cover.setChecked(
            gprefs.get('book_info_dialog_fit_cover', True))
        self.hl = hl = QHBoxLayout()
        hl.setContentsMargins(0, 0, 0, 0)
        l2.addLayout(hl, l2.rowCount(), 0, 1, -1)
        hl.addWidget(self.fit_cover), hl.addStretch()
        self.clabel = QLabel(
            '<div style="text-align: right"><a href="calibre:conf" title="{}" style="text-decoration: none">{}</a>'
            .format(_('Configure this view'), _('Configure')))
        self.clabel.linkActivated.connect(self.configure)
        hl.addWidget(self.clabel)
        self.previous_button = QPushButton(QIcon(I('previous.png')),
                                           _('&Previous'), self)
        self.previous_button.clicked.connect(self.previous)
        l2.addWidget(self.previous_button, l2.rowCount(), 0)
        self.next_button = QPushButton(QIcon(I('next.png')), _('&Next'), self)
        self.next_button.clicked.connect(self.next)
        l2.addWidget(self.next_button, l2.rowCount() - 1, 1)

        self.view = view
        self.path_to_book = None
        self.current_row = None
        self.refresh(row)
        self.view.model().new_bookdisplay_data.connect(self.slave)
        self.fit_cover.stateChanged.connect(self.toggle_cover_fit)
        self.ns = QShortcut(QKeySequence('Alt+Right'), self)
        self.ns.activated.connect(self.next)
        self.ps = QShortcut(QKeySequence('Alt+Left'), self)
        self.ps.activated.connect(self.previous)
        self.next_button.setToolTip(
            _('Next [%s]') %
            unicode_type(self.ns.key().toString(QKeySequence.NativeText)))
        self.previous_button.setToolTip(
            _('Previous [%s]') %
            unicode_type(self.ps.key().toString(QKeySequence.NativeText)))

        geom = QCoreApplication.instance().desktop().availableGeometry(self)
        screen_height = geom.height() - 100
        screen_width = geom.width() - 100
        self.resize(max(int(screen_width / 2), 700), screen_height)
        saved_layout = gprefs.get('book_info_dialog_layout', None)
        if saved_layout is not None:
            try:
                QApplication.instance().safe_restore_geometry(
                    self, saved_layout[0])
                self.splitter.restoreState(saved_layout[1])
            except Exception:
                pass
        from calibre.gui2.ui import get_gui
        ema = get_gui().iactions['Edit Metadata'].menuless_qaction
        a = self.ema = QAction('edit metadata', self)
        a.setShortcut(ema.shortcut())
        self.addAction(a)
        a.triggered.connect(self.edit_metadata)
Example #18
0
    def __init__(self, recipe_model, parent=None):
        QDialog.__init__(self, parent)
        self.commit_on_change = True
        self.previous_urn = None

        self.setWindowIcon(QIcon(I('scheduler.png')))
        self.l = l = QGridLayout(self)

        # Left panel
        self.h = h = QHBoxLayout()
        l.addLayout(h, 0, 0, 1, 1)
        self.search = s = SearchBox2(self)
        self.search.initialize('scheduler_search_history')
        self.search.setMinimumContentsLength(15)
        self.go_button = b = QToolButton(self)
        b.setText(_("Go"))
        b.clicked.connect(self.search.do_search)
        h.addWidget(s), h.addWidget(b)
        self.recipes = RecipesView(self)
        l.addWidget(self.recipes, 1, 0, 2, 1)
        self.recipe_model = recipe_model
        self.recipe_model.do_refresh()
        self.recipes.setModel(self.recipe_model)
        self.recipes.setFocus(Qt.FocusReason.OtherFocusReason)
        self.setWindowTitle(
            _("Schedule news download [{} sources]").format(
                self.recipe_model.showing_count))
        self.search.search.connect(self.recipe_model.search)
        self.recipe_model.searched.connect(
            self.search.search_done, type=Qt.ConnectionType.QueuedConnection)
        self.recipe_model.searched.connect(self.search_done)

        # Right Panel
        self.scroll_area_contents = sac = QWidget(self)
        self.l.addWidget(sac, 0, 1, 2, 1)
        sac.v = v = QVBoxLayout(sac)
        v.setContentsMargins(0, 0, 0, 0)
        self.detail_box = QTabWidget(self)
        self.detail_box.setVisible(False)
        self.detail_box.setCurrentIndex(0)
        v.addWidget(self.detail_box)
        v.addItem(
            QSpacerItem(20, 40, QSizePolicy.Policy.Minimum,
                        QSizePolicy.Policy.Expanding))

        # First Tab (scheduling)
        self.tab = QWidget()
        self.detail_box.addTab(self.tab, _("&Schedule"))
        self.tab.v = vt = QVBoxLayout(self.tab)
        vt.setContentsMargins(0, 0, 0, 0)
        self.blurb = la = QLabel('blurb')
        la.setWordWrap(True), la.setOpenExternalLinks(True)
        vt.addWidget(la)
        self.frame = f = QFrame(self.tab)
        vt.addWidget(f)
        f.setFrameShape(f.StyledPanel)
        f.setFrameShadow(f.Raised)
        f.v = vf = QVBoxLayout(f)
        self.schedule = s = QCheckBox(_("&Schedule for download:"), f)
        self.schedule.stateChanged[int].connect(self.toggle_schedule_info)
        vf.addWidget(s)
        f.h = h = QHBoxLayout()
        vf.addLayout(h)
        self.days_of_week = QRadioButton(_("&Days of  week"), f)
        self.days_of_month = QRadioButton(_("Da&ys of month"), f)
        self.every_x_days = QRadioButton(_("Every &x days"), f)
        self.days_of_week.setChecked(True)
        h.addWidget(self.days_of_week), h.addWidget(
            self.days_of_month), h.addWidget(self.every_x_days)
        self.schedule_stack = ss = QStackedWidget(f)
        self.schedule_widgets = []
        for key in reversed(self.SCHEDULE_TYPES):
            self.schedule_widgets.insert(0, self.SCHEDULE_TYPES[key](self))
            self.schedule_stack.insertWidget(0, self.schedule_widgets[0])
        vf.addWidget(ss)
        self.last_downloaded = la = QLabel(f)
        la.setWordWrap(True)
        vf.addWidget(la)
        self.account = acc = QGroupBox(self.tab)
        acc.setTitle(_("&Account"))
        vt.addWidget(acc)
        acc.g = g = QGridLayout(acc)
        acc.unla = la = QLabel(_("&Username:"******"&Password:"******"&Show password"), self.account)
        spw.stateChanged[int].connect(self.set_pw_echo_mode)
        g.addWidget(spw, 2, 0, 1, 2)
        self.rla = la = QLabel(
            _("For the scheduling to work, you must leave calibre running."))
        vt.addWidget(la)
        for b, c in iteritems(self.SCHEDULE_TYPES):
            b = getattr(self, b)
            b.toggled.connect(self.schedule_type_selected)
            b.setToolTip(textwrap.dedent(c.HELP))

        # Second tab (advanced settings)
        self.tab2 = t2 = QWidget()
        self.detail_box.addTab(self.tab2, _("&Advanced"))
        self.tab2.g = g = QGridLayout(t2)
        g.setContentsMargins(0, 0, 0, 0)
        self.add_title_tag = tt = QCheckBox(_("Add &title as tag"), t2)
        g.addWidget(tt, 0, 0, 1, 2)
        t2.la = la = QLabel(_("&Extra tags:"))
        self.custom_tags = ct = QLineEdit(self)
        la.setBuddy(ct)
        g.addWidget(la), g.addWidget(ct, 1, 1)
        t2.la2 = la = QLabel(_("&Keep at most:"))
        la.setToolTip(
            _("Maximum number of copies (issues) of this recipe to keep.  Set to 0 to keep all (disable)."
              ))
        self.keep_issues = ki = QSpinBox(t2)
        tt.toggled['bool'].connect(self.keep_issues.setEnabled)
        ki.setMaximum(100000), la.setBuddy(ki)
        ki.setToolTip(
            _("<p>When set, this option will cause calibre to keep, at most, the specified number of issues"
              " of this periodical. Every time a new issue is downloaded, the oldest one is deleted, if the"
              " total is larger than this number.\n<p>Note that this feature only works if you have the"
              " option to add the title as tag checked, above.\n<p>Also, the setting for deleting periodicals"
              " older than a number of days, below, takes priority over this setting."
              ))
        ki.setSpecialValueText(_("all issues")), ki.setSuffix(_(" issues"))
        g.addWidget(la), g.addWidget(ki, 2, 1)
        si = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum,
                         QSizePolicy.Policy.Expanding)
        g.addItem(si, 3, 1, 1, 1)

        # Bottom area
        self.hb = h = QHBoxLayout()
        self.l.addLayout(h, 2, 1, 1, 1)
        self.labt = la = QLabel(_("Delete downloaded &news older than:"))
        self.old_news = on = QSpinBox(self)
        on.setToolTip(
            _("<p>Delete downloaded news older than the specified number of days. Set to zero to disable.\n"
              "<p>You can also control the maximum number of issues of a specific periodical that are kept"
              " by clicking the Advanced tab for that periodical above."))
        on.setSpecialValueText(_("never delete")), on.setSuffix(_(" days"))
        on.setMaximum(1000), la.setBuddy(on)
        on.setValue(gconf['oldest_news'])
        h.addWidget(la), h.addWidget(on)
        self.download_all_button = b = QPushButton(
            QIcon(I('news.png')), _("Download &all scheduled"), self)
        b.setToolTip(_("Download all scheduled news sources at once"))
        b.clicked.connect(self.download_all_clicked)
        self.l.addWidget(b, 3, 0, 1, 1)
        self.bb = bb = QDialogButtonBox(
            QDialogButtonBox.StandardButton.Ok
            | QDialogButtonBox.StandardButton.Cancel, self)
        bb.accepted.connect(self.accept), bb.rejected.connect(self.reject)
        self.download_button = b = bb.addButton(
            _('&Download now'), QDialogButtonBox.ButtonRole.ActionRole)
        b.setIcon(QIcon(I('arrow-down.png'))), b.setVisible(False)
        b.clicked.connect(self.download_clicked)
        self.l.addWidget(bb, 3, 1, 1, 1)

        geom = gprefs.get('scheduler_dialog_geometry')
        if geom is not None:
            QApplication.instance().safe_restore_geometry(self, geom)
Example #19
0
    def __init__(self, gui, initial_panel=None):
        QDialog.__init__(self, gui)
        self.l = l = QGridLayout(self)
        self.setLayout(l)
        self.setWindowTitle(_('Preferences for Edit book'))
        self.setWindowIcon(QIcon(I('config.png')))

        self.stacks = QStackedWidget(self)
        l.addWidget(self.stacks, 0, 1, 1, 1)

        self.categories_list = cl = QListWidget(self)
        cl.currentRowChanged.connect(self.stacks.setCurrentIndex)
        cl.clearPropertyFlags()
        cl.setViewMode(cl.IconMode)
        cl.setFlow(cl.TopToBottom)
        cl.setMovement(cl.Static)
        cl.setWrapping(False)
        cl.setSpacing(15)
        if get_lang()[:2] not in ('zh', 'ja'):
            cl.setWordWrap(True)
        l.addWidget(cl, 0, 0, 1, 1)

        self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok
                                        | QDialogButtonBox.Cancel)
        bb.accepted.connect(self.accept)
        bb.rejected.connect(self.reject)
        self.rdb = b = bb.addButton(_('Restore all &defaults'), bb.ResetRole)
        b.setToolTip(_('Restore defaults for all preferences'))
        b.clicked.connect(self.restore_all_defaults)
        self.rcdb = b = bb.addButton(_('Restore &current defaults'),
                                     bb.ResetRole)
        b.setToolTip(_('Restore defaults for currently displayed preferences'))
        b.clicked.connect(self.restore_current_defaults)
        self.rconfs = b = bb.addButton(_('Restore c&onfirmations'),
                                       bb.ResetRole)
        b.setToolTip(_('Restore all disabled confirmation prompts'))
        b.clicked.connect(self.restore_confirmations)

        l.addWidget(bb, 1, 0, 1, 2)

        self.resize(800, 600)
        geom = tprefs.get('preferences_geom', None)
        if geom is not None:
            self.restoreGeometry(geom)

        self.keyboard_panel = ShortcutConfig(self)
        self.keyboard_panel.initialize(gui.keyboard)
        self.editor_panel = EditorSettings(self)
        self.integration_panel = IntegrationSettings(self)
        self.main_window_panel = MainWindowSettings(self)
        self.preview_panel = PreviewSettings(self)
        self.toolbars_panel = ToolbarSettings(self)

        for name, icon, panel in [
            (_('Main window'), 'page.png', 'main_window'),
            (_('Editor settings'), 'modified.png', 'editor'),
            (_('Preview settings'), 'viewer.png', 'preview'),
            (_('Keyboard shortcuts'), 'keyboard-prefs.png', 'keyboard'),
            (_('Toolbars'), 'wizard.png', 'toolbars'),
            (_('Integration with calibre'), 'lt.png', 'integration'),
        ]:
            i = QListWidgetItem(QIcon(I(icon)), name, cl)
            cl.addItem(i)
            self.stacks.addWidget(getattr(self, panel + '_panel'))

        cl.setCurrentRow(0)
        cl.item(0).setSelected(True)
        w, h = cl.sizeHintForColumn(0), 0
        for i in range(cl.count()):
            h = cl.sizeHintForRow(i)
            cl.item(i).setSizeHint(QSize(w, h))

        cl.setMaximumWidth(cl.sizeHintForColumn(0) + 35)
        cl.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
Example #20
0
 def __init__(self, parent=None):
     QWidget.__init__(self, parent)
     self.l = QGridLayout()
     self.setLayout(self.l)
     self.setToolTip(textwrap.dedent(self.HELP))
Example #21
0
        timeout_msg.setWordWrap(True)
        timeout_slider.setSliderPosition(config.get_session_timeout() // 60)
        slider_moved()
        timeout_slider.valueChanged.connect(slider_moved)
        timeout_slider.sliderReleased.connect(slider_released)
        settings_glayout.addWidget(timeout_label, 6, 0)
        settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3)
        settings_glayout.addWidget(timeout_minutes, 6, 4)
        settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1)
        settings_layout.addLayout(settings_glayout)
        settings_layout.addStretch(1)

        # Advanced tab
        advanced_tab = QWidget()
        advanced_layout = QVBoxLayout(advanced_tab)
        advanced_glayout = QGridLayout()

        # Advanced tab - clear PIN
        clear_pin_button = QPushButton(_("Disable PIN"))
        clear_pin_button.clicked.connect(clear_pin)
        clear_pin_warning = QLabel(
            _("If you disable your PIN, anyone with physical access to your "
              "{} device can spend your viacoins.").format(plugin.device))
        clear_pin_warning.setWordWrap(True)
        clear_pin_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(clear_pin_button, 0, 2)
        advanced_glayout.addWidget(clear_pin_warning, 1, 0, 1, 5)

        # Advanced tab - toggle passphrase protection
        passphrase_button = QPushButton()
        passphrase_button.clicked.connect(toggle_passphrase)
Example #22
0
    def setup_ui(self):
        self.setWindowIcon(QIcon(I('diff.png')))
        self.stacks = st = QStackedLayout(self)
        self.busy = BusyWidget(self)
        self.w = QWidget(self)
        st.addWidget(self.busy), st.addWidget(self.w)

        self.setLayout(st)
        self.l = l = QGridLayout()
        self.w.setLayout(l)

        self.view = v = DiffView(self,
                                 show_open_in_editor=self.show_open_in_editor)
        l.addWidget(v, l.rowCount(), 0, 1, -1)

        r = l.rowCount()
        self.bp = b = QToolButton(self)
        b.setIcon(QIcon(I('back.png')))
        b.clicked.connect(partial(self.view.next_change, -1))
        b.setToolTip(_('Go to previous change') + ' [p]')
        b.setText(_('&Previous change')), b.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)
        l.addWidget(b, r, 0)

        self.bn = b = QToolButton(self)
        b.setIcon(QIcon(I('forward.png')))
        b.clicked.connect(partial(self.view.next_change, 1))
        b.setToolTip(_('Go to next change') + ' [n]')
        b.setText(_('&Next change')), b.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)
        l.addWidget(b, r, 1)

        self.search = s = HistoryLineEdit2(self)
        s.initialize('diff_search_history')
        l.addWidget(s, r, 2)
        s.setPlaceholderText(_('Search for text'))
        s.returnPressed.connect(partial(self.do_search, False))
        self.sbn = b = QToolButton(self)
        b.setIcon(QIcon(I('arrow-down.png')))
        b.clicked.connect(partial(self.do_search, False))
        b.setToolTip(_('Find next match'))
        b.setText(_('Next &match')), b.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)
        l.addWidget(b, r, 3)
        self.sbp = b = QToolButton(self)
        b.setIcon(QIcon(I('arrow-up.png')))
        b.clicked.connect(partial(self.do_search, True))
        b.setToolTip(_('Find previous match'))
        b.setText(_('P&revious match')), b.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)
        l.addWidget(b, r, 4)
        self.lb = b = QRadioButton(_('Left panel'), self)
        b.setToolTip(_('Perform search in the left panel'))
        l.addWidget(b, r, 5)
        self.rb = b = QRadioButton(_('Right panel'), self)
        b.setToolTip(_('Perform search in the right panel'))
        l.addWidget(b, r, 6)
        b.setChecked(True)
        self.pb = b = QToolButton(self)
        b.setIcon(QIcon(I('config.png')))
        b.setText(_('&Options')), b.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)
        b.setToolTip(_('Change how the differences are displayed'))
        b.setPopupMode(b.InstantPopup)
        m = QMenu(b)
        b.setMenu(m)
        cm = self.cm = QMenu(_('Lines of context around each change'))
        for i in (3, 5, 10, 50):
            cm.addAction(
                _('Show %d lines of context') % i,
                partial(self.change_context, i))
        cm.addAction(_('Show all text'), partial(self.change_context, None))
        self.beautify_action = m.addAction('', self.toggle_beautify)
        self.set_beautify_action_text()
        m.addMenu(cm)
        l.addWidget(b, r, 7)

        self.hl = QHBoxLayout()
        l.addLayout(self.hl, l.rowCount(), 0, 1, -1)
        self.names = QLabel('')
        self.hl.addWidget(self.names, r)

        self.bb.setStandardButtons(self.bb.Close)
        if self.revert_button_msg is not None:
            self.rvb = b = self.bb.addButton(self.revert_button_msg,
                                             self.bb.ActionRole)
            b.setIcon(QIcon(I('edit-undo.png'))), b.setAutoDefault(False)
            b.clicked.connect(self.revert_requested)
            b.clicked.connect(self.reject)
        self.bb.button(self.bb.Close).setDefault(True)
        self.hl.addWidget(self.bb, r)

        self.view.setFocus(Qt.OtherFocusReason)
Example #23
0
    def do_layout(self):
        self.central_widget.clear()
        self.labels = []
        sto = QWidget.setTabOrder

        self.central_widget.tabBar().setVisible(False)
        tab0 = QWidget(self)
        self.central_widget.addTab(tab0, _("&Metadata"))
        l = QGridLayout()
        tab0.setLayout(l)

        # Basic metadata in col 0
        tl = QGridLayout()
        gb = QGroupBox(_('Basic metadata'), tab0)
        l.addWidget(gb, 0, 0, 1, 1)
        gb.setLayout(tl)

        self.button_box_layout.insertWidget(1, self.fetch_metadata_button)
        self.button_box_layout.insertWidget(2, self.config_metadata_button)
        sto(self.button_box, self.fetch_metadata_button)
        sto(self.fetch_metadata_button, self.config_metadata_button)
        sto(self.config_metadata_button, self.title)

        def create_row(row, widget, tab_to, button=None, icon=None, span=1):
            ql = BuddyLabel(widget)
            tl.addWidget(ql, row, 1, 1, 1)
            tl.addWidget(widget, row, 2, 1, 1)
            if button is not None:
                tl.addWidget(button, row, 3, span, 1)
                if icon is not None:
                    button.setIcon(QIcon(I(icon)))
            if tab_to is not None:
                if button is not None:
                    sto(widget, button)
                    sto(button, tab_to)
                else:
                    sto(widget, tab_to)

        tl.addWidget(self.swap_title_author_button, 0, 0, 2, 1)
        tl.addWidget(self.manage_authors_button, 2, 0, 2, 1)
        tl.addWidget(self.paste_isbn_button, 12, 0, 1, 1)
        tl.addWidget(self.tags_editor_button, 6, 0, 1, 1)

        create_row(0,
                   self.title,
                   self.title_sort,
                   button=self.deduce_title_sort_button,
                   span=2,
                   icon='auto_author_sort.png')
        create_row(1, self.title_sort, self.authors)
        create_row(2,
                   self.authors,
                   self.author_sort,
                   button=self.deduce_author_sort_button,
                   span=2,
                   icon='auto_author_sort.png')
        create_row(3, self.author_sort, self.series)
        create_row(4,
                   self.series,
                   self.series_index,
                   button=self.clear_series_button,
                   icon='trash.png')
        create_row(5, self.series_index, self.tags)
        create_row(6, self.tags, self.rating, button=self.clear_tags_button)
        create_row(7,
                   self.rating,
                   self.pubdate,
                   button=self.clear_ratings_button)
        create_row(8,
                   self.pubdate,
                   self.publisher,
                   button=self.pubdate.clear_button,
                   icon='trash.png')
        create_row(9, self.publisher, self.languages)
        create_row(10, self.languages, self.timestamp)
        create_row(11,
                   self.timestamp,
                   self.identifiers,
                   button=self.timestamp.clear_button,
                   icon='trash.png')
        create_row(12,
                   self.identifiers,
                   self.comments,
                   button=self.clear_identifiers_button,
                   icon='trash.png')
        sto(self.clear_identifiers_button, self.swap_title_author_button)
        sto(self.swap_title_author_button, self.manage_authors_button)
        sto(self.manage_authors_button, self.tags_editor_button)
        sto(self.tags_editor_button, self.paste_isbn_button)
        tl.addItem(QSpacerItem(1, 1, QSizePolicy.Fixed, QSizePolicy.Expanding),
                   13, 1, 1, 1)

        # Custom metadata in col 1
        w = getattr(self, 'custom_metadata_widgets_parent', None)
        if w is not None:
            gb = QGroupBox(_('Custom metadata'), tab0)
            gbl = QVBoxLayout()
            gb.setLayout(gbl)
            sr = QScrollArea(gb)
            sr.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            sr.setWidgetResizable(True)
            sr.setFrameStyle(QFrame.NoFrame)
            sr.setWidget(w)
            gbl.addWidget(sr)
            l.addWidget(gb, 0, 1, 1, 1)
            sp = QSizePolicy()
            sp.setVerticalStretch(10)
            sp.setHorizontalPolicy(QSizePolicy.Minimum)
            sp.setVerticalPolicy(QSizePolicy.Expanding)
            gb.setSizePolicy(sp)
            self.set_custom_metadata_tab_order()

        # comments span col 0 & 1
        w = QGroupBox(_('Comments'), tab0)
        sp = QSizePolicy()
        sp.setVerticalStretch(10)
        sp.setHorizontalPolicy(QSizePolicy.Expanding)
        sp.setVerticalPolicy(QSizePolicy.Expanding)
        w.setSizePolicy(sp)
        lb = QHBoxLayout()
        w.setLayout(lb)
        lb.addWidget(self.comments)
        l.addWidget(w, 1, 0, 1, 2)

        # Cover & formats in col 3
        gb = QGroupBox(_('Cover'), tab0)
        lb = QGridLayout()
        gb.setLayout(lb)
        lb.addWidget(self.cover, 0, 0, 1, 3, alignment=Qt.AlignCenter)
        sto(self.manage_authors_button, self.cover.buttons[0])
        for i, b in enumerate(self.cover.buttons[:3]):
            lb.addWidget(b, 1, i, 1, 1)
            sto(b, self.cover.buttons[i + 1])
        hl = QHBoxLayout()
        for b in self.cover.buttons[3:]:
            hl.addWidget(b)
        sto(self.cover.buttons[-2], self.cover.buttons[-1])
        lb.addLayout(hl, 2, 0, 1, 3)
        l.addWidget(gb, 0, 2, 1, 1)
        l.addWidget(self.formats_manager, 1, 2, 1, 1)
        sto(self.cover.buttons[-1], self.formats_manager)

        self.formats_manager.formats.setMaximumWidth(10000)
        self.formats_manager.formats.setIconSize(QSize(32, 32))
Example #24
0
    def __init__(self, window, plugin, keystore, device_id):
        title = _("{} Settings").format(plugin.device)
        super(SettingsDialog, self).__init__(window, title)
        self.setMaximumWidth(540)

        devmgr = plugin.device_manager()
        config = devmgr.config
        handler = keystore.handler
        thread = keystore.thread
        hs_rows, hs_cols = (64, 128)

        def invoke_client(method, *args, **kw_args):
            unpair_after = kw_args.pop('unpair_after', False)

            def task():
                client = devmgr.client_by_id(device_id)
                if not client:
                    raise RuntimeError("Device not connected")
                if method:
                    getattr(client, method)(*args, **kw_args)
                if unpair_after:
                    devmgr.unpair_id(device_id)
                return client.features

            thread.add(task, on_success=update)

        def update(features):
            self.features = features
            set_label_enabled()
            if features.bootloader_hash:
                bl_hash = bh2u(features.bootloader_hash)
                bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]])
            else:
                bl_hash = "N/A"
            noyes = [_("No"), _("Yes")]
            endis = [_("Enable Passphrases"), _("Disable Passphrases")]
            disen = [_("Disabled"), _("Enabled")]
            setchange = [_("Set a PIN"), _("Change PIN")]

            version = "%d.%d.%d" % (features.major_version,
                                    features.minor_version,
                                    features.patch_version)

            device_label.setText(features.label)
            pin_set_label.setText(noyes[features.pin_protection])
            passphrases_label.setText(disen[features.passphrase_protection])
            bl_hash_label.setText(bl_hash)
            label_edit.setText(features.label)
            device_id_label.setText(features.device_id)
            initialized_label.setText(noyes[features.initialized])
            version_label.setText(version)
            clear_pin_button.setVisible(features.pin_protection)
            clear_pin_warning.setVisible(features.pin_protection)
            pin_button.setText(setchange[features.pin_protection])
            pin_msg.setVisible(not features.pin_protection)
            passphrase_button.setText(endis[features.passphrase_protection])
            language_label.setText(features.language)

        def set_label_enabled():
            label_apply.setEnabled(label_edit.text() != self.features.label)

        def rename():
            invoke_client('change_label', label_edit.text())

        def toggle_passphrase():
            title = _("Confirm Toggle Passphrase Protection")
            currently_enabled = self.features.passphrase_protection
            if currently_enabled:
                msg = _("After disabling passphrases, you can only pair this "
                        "Electrum wallet if it had an empty passphrase.  "
                        "If its passphrase was not empty, you will need to "
                        "create a new wallet with the install wizard.  You "
                        "can use this wallet again at any time by re-enabling "
                        "passphrases and entering its passphrase.")
            else:
                msg = _("Your current Electrum wallet can only be used with "
                        "an empty passphrase.  You must create a separate "
                        "wallet with the install wizard for other passphrases "
                        "as each one generates a new set of addresses.")
            msg += "\n\n" + _("Are you sure you want to proceed?")
            if not self.question(msg, title=title):
                return
            invoke_client('toggle_passphrase', unpair_after=currently_enabled)

        def change_homescreen():
            dialog = QFileDialog(self, _("Choose Homescreen"))
            filename, __ = dialog.getOpenFileName()
            if not filename:
                return  # user cancelled

            if filename.endswith('.toif'):
                img = open(filename, 'rb').read()
                if img[:8] != b'TOIf\x90\x00\x90\x00':
                    handler.show_error('File is not a TOIF file with size of 144x144')
                    return
            else:
                from PIL import Image # FIXME
                im = Image.open(filename)
                if im.size != (128, 64):
                    handler.show_error('Image must be 128 x 64 pixels')
                    return
                im = im.convert('1')
                pix = im.load()
                img = bytearray(1024)
                for j in range(64):
                    for i in range(128):
                        if pix[i, j]:
                            o = (i + j * 128)
                            img[o // 8] |= (1 << (7 - o % 8))
                img = bytes(img)
            invoke_client('change_homescreen', img)

        def clear_homescreen():
            invoke_client('change_homescreen', b'\x00')

        def set_pin():
            invoke_client('set_pin', remove=False)

        def clear_pin():
            invoke_client('set_pin', remove=True)

        def wipe_device():
            wallet = window.wallet
            if wallet and sum(wallet.get_balance()):
                title = _("Confirm Device Wipe")
                msg = _("Are you SURE you want to wipe the device?\n"
                        "Your wallet still has bitcoins in it!")
                if not self.question(msg, title=title,
                                     icon=QMessageBox.Critical):
                    return
            invoke_client('wipe_device', unpair_after=True)

        def slider_moved():
            mins = timeout_slider.sliderPosition()
            timeout_minutes.setText(_("%2d minutes") % mins)

        def slider_released():
            config.set_session_timeout(timeout_slider.sliderPosition() * 60)

        # Information tab
        info_tab = QWidget()
        info_layout = QVBoxLayout(info_tab)
        info_glayout = QGridLayout()
        info_glayout.setColumnStretch(2, 1)
        device_label = QLabel()
        pin_set_label = QLabel()
        passphrases_label = QLabel()
        version_label = QLabel()
        device_id_label = QLabel()
        bl_hash_label = QLabel()
        bl_hash_label.setWordWrap(True)
        language_label = QLabel()
        initialized_label = QLabel()
        rows = [
            (_("Device Label"), device_label),
            (_("PIN set"), pin_set_label),
            (_("Passphrases"), passphrases_label),
            (_("Firmware Version"), version_label),
            (_("Device ID"), device_id_label),
            (_("Bootloader Hash"), bl_hash_label),
            (_("Language"), language_label),
            (_("Initialized"), initialized_label),
        ]
        for row_num, (label, widget) in enumerate(rows):
            info_glayout.addWidget(QLabel(label), row_num, 0)
            info_glayout.addWidget(widget, row_num, 1)
        info_layout.addLayout(info_glayout)

        # Settings tab
        settings_tab = QWidget()
        settings_layout = QVBoxLayout(settings_tab)
        settings_glayout = QGridLayout()

        # Settings tab - Label
        label_msg = QLabel(_("Name this {}.  If you have multiple devices "
                             "their labels help distinguish them.")
                           .format(plugin.device))
        label_msg.setWordWrap(True)
        label_label = QLabel(_("Device Label"))
        label_edit = QLineEdit()
        label_edit.setMinimumWidth(150)
        label_edit.setMaxLength(plugin.MAX_LABEL_LEN)
        label_apply = QPushButton(_("Apply"))
        label_apply.clicked.connect(rename)
        label_edit.textChanged.connect(set_label_enabled)
        settings_glayout.addWidget(label_label, 0, 0)
        settings_glayout.addWidget(label_edit, 0, 1, 1, 2)
        settings_glayout.addWidget(label_apply, 0, 3)
        settings_glayout.addWidget(label_msg, 1, 1, 1, -1)

        # Settings tab - PIN
        pin_label = QLabel(_("PIN Protection"))
        pin_button = QPushButton()
        pin_button.clicked.connect(set_pin)
        settings_glayout.addWidget(pin_label, 2, 0)
        settings_glayout.addWidget(pin_button, 2, 1)
        pin_msg = QLabel(_("PIN protection is strongly recommended.  "
                           "A PIN is your only protection against someone "
                           "stealing your bitcoins if they obtain physical "
                           "access to your {}.").format(plugin.device))
        pin_msg.setWordWrap(True)
        pin_msg.setStyleSheet("color: red")
        settings_glayout.addWidget(pin_msg, 3, 1, 1, -1)

        # Settings tab - Homescreen
        homescreen_label = QLabel(_("Homescreen"))
        homescreen_change_button = QPushButton(_("Change..."))
        homescreen_clear_button = QPushButton(_("Reset"))
        homescreen_change_button.clicked.connect(change_homescreen)
        try:
            import PIL
        except ImportError:
            homescreen_change_button.setDisabled(True)
            homescreen_change_button.setToolTip(
                _("Required package 'PIL' is not available - Please install it or use the Trezor website instead.")
            )
        homescreen_clear_button.clicked.connect(clear_homescreen)
        homescreen_msg = QLabel(_("You can set the homescreen on your "
                                  "device to personalize it.  You must "
                                  "choose a {} x {} monochrome black and "
                                  "white image.").format(hs_rows, hs_cols))
        homescreen_msg.setWordWrap(True)
        settings_glayout.addWidget(homescreen_label, 4, 0)
        settings_glayout.addWidget(homescreen_change_button, 4, 1)
        settings_glayout.addWidget(homescreen_clear_button, 4, 2)
        settings_glayout.addWidget(homescreen_msg, 5, 1, 1, -1)

        # Settings tab - Session Timeout
        timeout_label = QLabel(_("Session Timeout"))
        timeout_minutes = QLabel()
        timeout_slider = QSlider(Qt.Horizontal)
        timeout_slider.setRange(1, 60)
        timeout_slider.setSingleStep(1)
        timeout_slider.setTickInterval(5)
        timeout_slider.setTickPosition(QSlider.TicksBelow)
        timeout_slider.setTracking(True)
        timeout_msg = QLabel(
            _("Clear the session after the specified period "
              "of inactivity.  Once a session has timed out, "
              "your PIN and passphrase (if enabled) must be "
              "re-entered to use the device."))
        timeout_msg.setWordWrap(True)
        timeout_slider.setSliderPosition(config.get_session_timeout() // 60)
        slider_moved()
        timeout_slider.valueChanged.connect(slider_moved)
        timeout_slider.sliderReleased.connect(slider_released)
        settings_glayout.addWidget(timeout_label, 6, 0)
        settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3)
        settings_glayout.addWidget(timeout_minutes, 6, 4)
        settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1)
        settings_layout.addLayout(settings_glayout)
        settings_layout.addStretch(1)

        # Advanced tab
        advanced_tab = QWidget()
        advanced_layout = QVBoxLayout(advanced_tab)
        advanced_glayout = QGridLayout()

        # Advanced tab - clear PIN
        clear_pin_button = QPushButton(_("Disable PIN"))
        clear_pin_button.clicked.connect(clear_pin)
        clear_pin_warning = QLabel(
            _("If you disable your PIN, anyone with physical access to your "
              "{} device can spend your bitcoins.").format(plugin.device))
        clear_pin_warning.setWordWrap(True)
        clear_pin_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(clear_pin_button, 0, 2)
        advanced_glayout.addWidget(clear_pin_warning, 1, 0, 1, 5)

        # Advanced tab - toggle passphrase protection
        passphrase_button = QPushButton()
        passphrase_button.clicked.connect(toggle_passphrase)
        passphrase_msg = WWLabel(PASSPHRASE_HELP)
        passphrase_warning = WWLabel(PASSPHRASE_NOT_PIN)
        passphrase_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(passphrase_button, 3, 2)
        advanced_glayout.addWidget(passphrase_msg, 4, 0, 1, 5)
        advanced_glayout.addWidget(passphrase_warning, 5, 0, 1, 5)

        # Advanced tab - wipe device
        wipe_device_button = QPushButton(_("Wipe Device"))
        wipe_device_button.clicked.connect(wipe_device)
        wipe_device_msg = QLabel(
            _("Wipe the device, removing all data from it.  The firmware "
              "is left unchanged."))
        wipe_device_msg.setWordWrap(True)
        wipe_device_warning = QLabel(
            _("Only wipe a device if you have the recovery seed written down "
              "and the device wallet(s) are empty, otherwise the bitcoins "
              "will be lost forever."))
        wipe_device_warning.setWordWrap(True)
        wipe_device_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(wipe_device_button, 6, 2)
        advanced_glayout.addWidget(wipe_device_msg, 7, 0, 1, 5)
        advanced_glayout.addWidget(wipe_device_warning, 8, 0, 1, 5)
        advanced_layout.addLayout(advanced_glayout)
        advanced_layout.addStretch(1)

        tabs = QTabWidget(self)
        tabs.addTab(info_tab, _("Information"))
        tabs.addTab(settings_tab, _("Settings"))
        tabs.addTab(advanced_tab, _("Advanced"))
        dialog_vbox = QVBoxLayout(self)
        dialog_vbox.addWidget(tabs)
        dialog_vbox.addLayout(Buttons(CloseButton(self)))

        # Update information
        invoke_client(None)
Example #25
0
    def do_layout(self):
        self.central_widget.clear()
        self.tabs = []
        self.labels = []
        sto = QWidget.setTabOrder

        self.on_drag_enter.connect(self.handle_drag_enter)
        self.tabs.append(DragTrackingWidget(self, self.on_drag_enter))
        self.central_widget.addTab(self.tabs[0], _("&Metadata"))
        self.tabs[0].l = QGridLayout()
        self.tabs[0].setLayout(self.tabs[0].l)

        self.tabs.append(QWidget(self))
        self.central_widget.addTab(self.tabs[1], _("&Cover and formats"))
        self.tabs[1].l = QGridLayout()
        self.tabs[1].setLayout(self.tabs[1].l)

        # accept drop events so we can automatically switch to the second tab to
        # drop covers and formats
        self.tabs[0].setAcceptDrops(True)

        # Tab 0
        tab0 = self.tabs[0]

        tl = QGridLayout()
        gb = QGroupBox(_('&Basic metadata'), self.tabs[0])
        self.tabs[0].l.addWidget(gb, 0, 0, 1, 1)
        gb.setLayout(tl)

        self.button_box_layout.insertWidget(1, self.fetch_metadata_button)
        self.button_box_layout.insertWidget(2, self.config_metadata_button)
        sto(self.button_box, self.fetch_metadata_button)
        sto(self.fetch_metadata_button, self.config_metadata_button)
        sto(self.config_metadata_button, self.title)

        def create_row(row, widget, tab_to, button=None, icon=None, span=1):
            ql = BuddyLabel(widget)
            tl.addWidget(ql, row, 1, 1, 1)
            tl.addWidget(widget, row, 2, 1, 1)
            if button is not None:
                tl.addWidget(button, row, 3, span, 1)
                if icon is not None:
                    button.setIcon(QIcon(I(icon)))
            if tab_to is not None:
                if button is not None:
                    sto(widget, button)
                    sto(button, tab_to)
                else:
                    sto(widget, tab_to)

        tl.addWidget(self.swap_title_author_button, 0, 0, 2, 1)
        tl.addWidget(self.manage_authors_button, 2, 0, 1, 1)
        tl.addWidget(self.paste_isbn_button, 12, 0, 1, 1)
        tl.addWidget(self.tags_editor_button, 6, 0, 1, 1)

        create_row(0,
                   self.title,
                   self.title_sort,
                   button=self.deduce_title_sort_button,
                   span=2,
                   icon='auto_author_sort.png')
        create_row(1, self.title_sort, self.authors)
        create_row(2,
                   self.authors,
                   self.author_sort,
                   button=self.deduce_author_sort_button,
                   span=2,
                   icon='auto_author_sort.png')
        create_row(3, self.author_sort, self.series)
        create_row(4,
                   self.series,
                   self.series_index,
                   button=self.clear_series_button,
                   icon='trash.png')
        create_row(5, self.series_index, self.tags)
        create_row(6, self.tags, self.rating, button=self.clear_tags_button)
        create_row(7,
                   self.rating,
                   self.pubdate,
                   button=self.clear_ratings_button)
        create_row(8,
                   self.pubdate,
                   self.publisher,
                   button=self.pubdate.clear_button,
                   icon='trash.png')
        create_row(9, self.publisher, self.languages)
        create_row(10, self.languages, self.timestamp)
        create_row(11,
                   self.timestamp,
                   self.identifiers,
                   button=self.timestamp.clear_button,
                   icon='trash.png')
        create_row(12,
                   self.identifiers,
                   self.comments,
                   button=self.clear_identifiers_button,
                   icon='trash.png')
        sto(self.clear_identifiers_button, self.swap_title_author_button)
        sto(self.swap_title_author_button, self.manage_authors_button)
        sto(self.manage_authors_button, self.tags_editor_button)
        sto(self.tags_editor_button, self.paste_isbn_button)
        tl.addItem(QSpacerItem(1, 1, QSizePolicy.Fixed, QSizePolicy.Expanding),
                   13, 1, 1, 1)

        w = getattr(self, 'custom_metadata_widgets_parent', None)
        if w is not None:
            gb = QGroupBox(_('C&ustom metadata'), tab0)
            gbl = QVBoxLayout()
            gb.setLayout(gbl)
            sr = QScrollArea(tab0)
            sr.setWidgetResizable(True)
            sr.setFrameStyle(QFrame.NoFrame)
            sr.setWidget(w)
            gbl.addWidget(sr)
            self.tabs[0].l.addWidget(gb, 0, 1, 1, 1)
            sto(self.identifiers, gb)

        w = QGroupBox(_('&Comments'), tab0)
        sp = QSizePolicy()
        sp.setVerticalStretch(10)
        sp.setHorizontalPolicy(QSizePolicy.Expanding)
        sp.setVerticalPolicy(QSizePolicy.Expanding)
        w.setSizePolicy(sp)
        l = QHBoxLayout()
        w.setLayout(l)
        l.addWidget(self.comments)
        tab0.l.addWidget(w, 1, 0, 1, 2)

        # Tab 1
        tab1 = self.tabs[1]

        wsp = QWidget(tab1)
        wgl = QVBoxLayout()
        wsp.setLayout(wgl)

        # right-hand side of splitter
        gb = QGroupBox(_('Change cover'), tab1)
        l = QGridLayout()
        gb.setLayout(l)
        for i, b in enumerate(self.cover.buttons[:3]):
            l.addWidget(b, 0, i, 1, 1)
            sto(b, self.cover.buttons[i + 1])
        hl = QHBoxLayout()
        for b in self.cover.buttons[3:]:
            hl.addWidget(b)
        sto(self.cover.buttons[-2], self.cover.buttons[-1])
        l.addLayout(hl, 1, 0, 1, 3)
        wgl.addWidget(gb)
        wgl.addItem(
            QSpacerItem(10, 10, QSizePolicy.Expanding, QSizePolicy.Expanding))
        wgl.addItem(
            QSpacerItem(10, 10, QSizePolicy.Expanding, QSizePolicy.Expanding))
        wgl.addWidget(self.formats_manager)

        self.splitter = QSplitter(Qt.Horizontal, tab1)
        tab1.l.addWidget(self.splitter)
        self.splitter.addWidget(self.cover)
        self.splitter.addWidget(wsp)

        self.formats_manager.formats.setMaximumWidth(10000)
        self.formats_manager.formats.setIconSize(QSize(64, 64))
Example #26
0
    def setup_ui(self):
        self.l = l = QGridLayout(self)
        self.setLayout(l)

        self.la1 = la = QLabel(_('&Existing images in the book'))
        la.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        l.addWidget(la, 0, 0, 1, 2)
        if self.for_browsing:
            la.setVisible(False)

        self.view = v = QListView(self)
        v.setViewMode(v.IconMode)
        v.setFlow(v.LeftToRight)
        v.setSpacing(4)
        v.setResizeMode(v.Adjust)
        v.setUniformItemSizes(True)
        pi = plugins['progress_indicator'][0]
        if hasattr(pi, 'set_no_activate_on_click'):
            pi.set_no_activate_on_click(v)
        v.activated.connect(self.activated)
        v.doubleClicked.connect(self.activated)
        self.d = ImageDelegate(v)
        v.setItemDelegate(self.d)
        self.model = Images(self.view)
        self.fm = fm = QSortFilterProxyModel(self.view)
        self.fm.setDynamicSortFilter(self.for_browsing)
        fm.setSourceModel(self.model)
        fm.setFilterCaseSensitivity(False)
        v.setModel(fm)
        l.addWidget(v, 1, 0, 1, 2)
        v.pressed.connect(self.pressed)
        la.setBuddy(v)

        self.filter = f = QLineEdit(self)
        f.setPlaceholderText(_('Search for image by file name'))
        l.addWidget(f, 2, 0)
        self.cb = b = QToolButton(self)
        b.setIcon(QIcon(I('clear_left.png')))
        b.clicked.connect(f.clear)
        l.addWidget(b, 2, 1)
        f.textChanged.connect(self.filter_changed)

        if self.for_browsing:
            self.bb.clear()
            self.bb.addButton(self.bb.Close)
            b = self.refresh_button = self.bb.addButton(
                _('&Refresh'), self.bb.ActionRole)
            b.clicked.connect(self.refresh)
            b.setIcon(QIcon(I('view-refresh.png')))
            b.setToolTip(_('Refresh the displayed images'))
            self.setAttribute(Qt.WA_DeleteOnClose, False)
        else:
            b = self.import_button = self.bb.addButton(_('&Import image'),
                                                       self.bb.ActionRole)
            b.clicked.connect(self.import_image)
            b.setIcon(QIcon(I('view-image.png')))
            b.setToolTip(_('Import an image from elsewhere in your computer'))
            b = self.paste_button = self.bb.addButton(_('&Paste image'),
                                                      self.bb.ActionRole)
            b.clicked.connect(self.paste_image)
            b.setIcon(QIcon(I('edit-paste.png')))
            b.setToolTip(_('Paste an image from the clipboard'))
            self.fullpage = f = QCheckBox(_('Full page image'), self)
            f.setToolTip(
                _('Insert the image so that it takes up an entire page when viewed in a reader'
                  ))
            f.setChecked(tprefs['insert_full_screen_image'])
            self.preserve_aspect_ratio = a = QCheckBox(
                _('Preserve aspect ratio'))
            a.setToolTip(
                _('Preserve the aspect ratio of the inserted image when rendering it full paged'
                  ))
            a.setChecked(tprefs['preserve_aspect_ratio_when_inserting_image'])
            f.toggled.connect(
                lambda: (tprefs.set('insert_full_screen_image', f.isChecked()),
                         a.setVisible(f.isChecked())))
            a.toggled.connect(lambda: tprefs.set(
                'preserve_aspect_ratio_when_inserting_image', a.isChecked()))
            a.setVisible(f.isChecked())
            h = QHBoxLayout()
            l.addLayout(h, 3, 0, 1, -1)
            h.addWidget(f), h.addStretch(10), h.addWidget(a)
        l.addWidget(self.bb, 4, 0, 1, 2)
Example #27
0
    def setup_ui(self):
        self.l = l = QGridLayout(self)
        self.setLayout(l)

        self.bb.setStandardButtons(self.bb.Close)
        self.rearrange_button = b = self.bb.addButton(_('Re-arrange favorites'), self.bb.ActionRole)
        b.setCheckable(True)
        b.setChecked(False)
        b.setVisible(False)
        b.setDefault(True)

        self.splitter = s = QSplitter(self)
        s.setFocusPolicy(Qt.FocusPolicy.NoFocus)
        s.setChildrenCollapsible(False)

        self.search = h = HistoryLineEdit2(self)
        h.setToolTip(textwrap.fill(_(
            'Search for Unicode characters by using the English names or nicknames.'
            ' You can also search directly using a character code. For example, the following'
            ' searches will all yield the no-break space character: U+A0, nbsp, no-break')))
        h.initialize('charmap_search')
        h.setPlaceholderText(_('Search by name, nickname or character code'))
        self.search_button = b = QPushButton(_('&Search'))
        b.setFocusPolicy(Qt.FocusPolicy.NoFocus)
        h.returnPressed.connect(self.do_search)
        b.clicked.connect(self.do_search)
        self.clear_button = cb = QToolButton(self)
        cb.setIcon(QIcon(I('clear_left.png')))
        cb.setFocusPolicy(Qt.FocusPolicy.NoFocus)
        cb.setText(_('Clear search'))
        cb.clicked.connect(self.clear_search)
        l.addWidget(h), l.addWidget(b, 0, 1), l.addWidget(cb, 0, 2)

        self.category_view = CategoryView(self)
        self.category_view.setFocusPolicy(Qt.FocusPolicy.NoFocus)
        l.addWidget(s, 1, 0, 1, 3)
        self.char_view = CharView(self)
        self.char_view.setFocusPolicy(Qt.FocusPolicy.NoFocus)
        self.rearrange_button.toggled[bool].connect(self.set_allow_drag_and_drop)
        self.category_view.category_selected.connect(self.show_chars)
        self.char_view.show_name.connect(self.show_char_info)
        self.char_view.char_selected.connect(self.char_selected)
        s.addWidget(self.category_view), s.addWidget(self.char_view)

        self.char_info = la = QLabel('\xa0')
        la.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
        l.addWidget(la, 2, 0, 1, 3)

        self.rearrange_msg = la = QLabel(_(
            'Drag and drop characters to re-arrange them. Click the "Re-arrange" button again when you are done.'))
        la.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
        la.setVisible(False)
        l.addWidget(la, 3, 0, 1, 3)
        self.h = h = QHBoxLayout()
        h.setContentsMargins(0, 0, 0, 0)
        self.match_any = mm = QCheckBox(_('Match any word'))
        mm.setToolTip(_('When searching return characters whose names match any of the specified words'))
        mm.setChecked(tprefs.get('char_select_match_any', True))
        connect_lambda(mm.stateChanged, self, lambda self: tprefs.set('char_select_match_any', self.match_any.isChecked()))
        h.addWidget(mm), h.addStretch(), h.addWidget(self.bb)
        l.addLayout(h, 4, 0, 1, 3)
        self.char_view.setFocus(Qt.FocusReason.OtherFocusReason)
Example #28
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.l = l = QGridLayout(self)

        def add_row(*args):
            r = l.rowCount()
            if len(args) == 1:
                l.addWidget(args[0], r, 0, 1, 2)
            else:
                la = QLabel(args[0])
                l.addWidget(la, r, 0,
                            Qt.AlignmentFlag.AlignRight), l.addWidget(
                                args[1], r, 1)
                la.setBuddy(args[1])

        self.heading = la = QLabel('<h2>\xa0')
        add_row(la)
        self.helpl = la = QLabel(
            _('For help with snippets, see the <a href="%s">User Manual</a>') %
            localize_user_manual_link(
                'https://manual.calibre-ebook.com/snippets.html'))
        la.setOpenExternalLinks(True)
        add_row(la)

        self.name = n = QLineEdit(self)
        n.setPlaceholderText(_('The name of this snippet'))
        add_row(_('&Name:'), n)

        self.trig = t = QLineEdit(self)
        t.setPlaceholderText(_('The text used to trigger this snippet'))
        add_row(_('Tri&gger:'), t)

        self.template = t = QPlainTextEdit(self)
        la.setBuddy(t)
        add_row(_('&Template:'), t)

        self.types = t = QListWidget(self)
        t.setFlow(QListView.Flow.LeftToRight)
        t.setWrapping(True), t.setResizeMode(
            QListView.ResizeMode.Adjust), t.setSpacing(5)
        fm = t.fontMetrics()
        t.setMaximumHeight(2 * (fm.ascent() + fm.descent()) + 25)
        add_row(_('&File types:'), t)
        t.setToolTip(_('Which file types this snippet should be active in'))

        self.frame = f = QFrame(self)
        f.setFrameShape(f.HLine)
        add_row(f)
        self.test = d = SnippetTextEdit('', self)
        d.snippet_manager.snip_func = self.snip_func
        d.setToolTip(_('You can test your snippet here'))
        d.setMaximumHeight(t.maximumHeight() + 15)
        add_row(_('T&est:'), d)

        i = QListWidgetItem(_('All'), t)
        i.setData(Qt.ItemDataRole.UserRole, '*')
        i.setCheckState(Qt.CheckState.Checked)
        i.setFlags(i.flags() | Qt.ItemFlag.ItemIsUserCheckable)
        for ftype in sorted(all_text_syntaxes):
            i = QListWidgetItem(ftype, t)
            i.setData(Qt.ItemDataRole.UserRole, ftype)
            i.setCheckState(Qt.CheckState.Checked)
            i.setFlags(i.flags() | Qt.ItemFlag.ItemIsUserCheckable)

        self.creating_snippet = False
Example #29
0
    def __init__(self, fm, pref_name, parent=None):
        QDialog.__init__(self, parent)
        self.fm = fm

        if pref_name == 'column_color_rules':
            self.rule_kind = 'color'
            rule_text = _('column coloring')
        elif pref_name == 'column_icon_rules':
            self.rule_kind = 'icon'
            rule_text = _('column icon')
        elif pref_name == 'cover_grid_icon_rules':
            self.rule_kind = 'emblem'
            rule_text = _('Cover grid emblem')

        self.setWindowIcon(QIcon(I('format-fill-color.png')))
        self.setWindowTitle(_('Create/edit a {0} rule').format(rule_text))

        self.l = l = QGridLayout(self)
        self.setLayout(l)

        self.l1 = l1 = QLabel(
            _('Create a {0} rule by'
              ' filling in the boxes below').format(rule_text))
        l.addWidget(l1, 0, 0, 1, 8)

        self.f1 = QFrame(self)
        self.f1.setFrameShape(QFrame.HLine)
        l.addWidget(self.f1, 1, 0, 1, 8)

        self.l2 = l2 = QLabel(
            _('Add the emblem:') if self.rule_kind ==
            'emblem' else _('Set the'))
        l.addWidget(l2, 2, 0)

        if self.rule_kind == 'color':
            l.addWidget(QLabel(_('color')))
        elif self.rule_kind == 'icon':
            self.kind_box = QComboBox(self)
            for tt, t in icon_rule_kinds:
                self.kind_box.addItem(tt, t)
            l.addWidget(self.kind_box, 2, 1)
            self.kind_box.setToolTip(
                textwrap.fill(
                    _('If you choose composed icons and multiple rules match, then all the'
                      ' matching icons will be combined, otherwise the icon from the'
                      ' first rule to match will be used.')))
        else:
            pass

        self.l3 = l3 = QLabel(_('of the column:'))
        l.addWidget(l3, 2, 2)

        self.column_box = QComboBox(self)
        l.addWidget(self.column_box, 2, 3)

        self.l4 = l4 = QLabel(_('to'))
        l.addWidget(l4, 2, 4)
        if self.rule_kind == 'emblem':
            l3.setVisible(False), self.column_box.setVisible(
                False), l4.setVisible(False)

        def create_filename_box():
            self.filename_box = f = QComboBox()
            self.filenamebox_view = v = QListView()
            v.setIconSize(QSize(32, 32))
            self.filename_box.setView(v)
            self.orig_filenamebox_view = f.view()
            f.setMinimumContentsLength(20), f.setSizeAdjustPolicy(
                f.AdjustToMinimumContentsLengthWithIcon)
            self.populate_icon_filenames()

        if self.rule_kind == 'color':
            self.color_box = ColorButton(parent=self)
            self.color_label = QLabel('Sample text Sample text')
            self.color_label.setTextFormat(Qt.RichText)
            l.addWidget(self.color_box, 2, 5)
            l.addWidget(self.color_label, 2, 6)
            l.addItem(QSpacerItem(10, 10, QSizePolicy.Expanding), 2, 7)
        elif self.rule_kind == 'emblem':
            create_filename_box()
            self.update_filename_box()
            self.filename_button = QPushButton(QIcon(I('document_open.png')),
                                               _('&Add new image'))
            l.addWidget(self.filename_box)
            l.addWidget(self.filename_button, 2, 6)
            l.addWidget(QLabel(_('(Images should be square-ish)')), 2, 7)
            l.setColumnStretch(7, 10)
        else:
            create_filename_box()

            vb = QVBoxLayout()
            self.multiple_icon_cb = QCheckBox(_('Choose more than one icon'))
            vb.addWidget(self.multiple_icon_cb)
            self.update_filename_box()
            self.multiple_icon_cb.clicked.connect(self.multiple_box_clicked)
            vb.addWidget(self.filename_box)
            l.addLayout(vb, 2, 5)

            self.filename_button = QPushButton(QIcon(I('document_open.png')),
                                               _('&Add icon'))
            l.addWidget(self.filename_button, 2, 6)
            l.addWidget(QLabel(_('Icons should be square or landscape')), 2, 7)
            l.setColumnStretch(7, 10)

        self.l5 = l5 = QLabel(
            _('Only if the following conditions are all satisfied:'))
        l.addWidget(l5, 3, 0, 1, 7)

        self.scroll_area = sa = QScrollArea(self)
        sa.setMinimumHeight(300)
        sa.setMinimumWidth(950)
        sa.setWidgetResizable(True)
        l.addWidget(sa, 4, 0, 1, 8)

        self.add_button = b = QPushButton(QIcon(I('plus.png')),
                                          _('Add another condition'))
        l.addWidget(b, 5, 0, 1, 8)
        b.clicked.connect(self.add_blank_condition)

        self.l6 = l6 = QLabel(
            _('You can disable a condition by'
              ' blanking all of its boxes'))
        l.addWidget(l6, 6, 0, 1, 8)

        self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok
                                        | QDialogButtonBox.Cancel)
        bb.accepted.connect(self.accept)
        bb.rejected.connect(self.reject)
        l.addWidget(bb, 7, 0, 1, 8)
        if self.rule_kind != 'color':
            self.remove_button = b = bb.addButton(_('Remove image'),
                                                  bb.ActionRole)
            b.setIcon(QIcon(I('minus.png')))
            b.setMenu(QMenu())
            self.update_remove_button()

        self.conditions_widget = QWidget(self)
        sa.setWidget(self.conditions_widget)
        self.conditions_widget.setLayout(QVBoxLayout())
        self.conditions_widget.layout().setAlignment(Qt.AlignTop)
        self.conditions = []

        if self.rule_kind == 'color':
            for b in (self.column_box, ):
                b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon)
                b.setMinimumContentsLength(15)

        for key in sorted(displayable_columns(fm),
                          key=lambda (k): sort_key(fm[k]['name'])
                          if k != color_row_key else 0):
            if key == color_row_key and self.rule_kind != 'color':
                continue
            name = all_columns_string if key == color_row_key else fm[key][
                'name']
            if name:
                self.column_box.addItem(name, key)
        self.column_box.setCurrentIndex(0)

        if self.rule_kind == 'color':
            self.color_box.color = '#000'
            self.update_color_label()
            self.color_box.color_changed.connect(self.update_color_label)
        else:
            self.rule_icon_files = []
            self.filename_button.clicked.connect(self.filename_button_clicked)

        self.resize(self.sizeHint())
Example #30
0
    def __init__(self, device, parent=None, highlight_ignored_folders=False):
        QTabWidget.__init__(self, parent)
        self._device = weakref.ref(device)

        cd = msg = None
        if device.current_friendly_name is not None:
            if device.current_serial_num is None:
                msg = '<p>' + (_('The <b>%s</b> device has no serial number, '
                    'it cannot be configured')%device.current_friendly_name)
            else:
                cd = 'device-'+device.current_serial_num
        else:
            msg = '<p>' + _('<b>No MTP device connected.</b><p>'
                ' You can only configure the MTP device plugin when a device'
                ' is connected.')

        self.current_device_key = cd

        if msg:
            msg += '<p>' + _('If you want to un-ignore a previously'
                ' ignored MTP device, use the "Ignored devices" tab.')
            l = QLabel(msg)
            l.setWordWrap(True)
            l.setStyleSheet('QLabel { margin-left: 2em }')
            l.setMinimumWidth(500)
            l.setMinimumHeight(400)
            self.insertTab(0, l, _('Cannot configure'))
        else:
            self.base = QWidget(self)
            self.insertTab(0, self.base, _('Configure %s')%self.device.current_friendly_name)
            l = self.base.l = QGridLayout(self.base)
            self.base.setLayout(l)

            self.rules = r = FormatRules(self.device, self.get_pref('rules'))
            self.formats = FormatsConfig(set(BOOK_EXTENSIONS),
                    self.get_pref('format_map'))
            self.send_to = SendToConfig(self.get_pref('send_to'), self.device)
            self.template = TemplateConfig(self.get_pref('send_template'))
            self.base.la = la = QLabel(_(
                'Choose the formats to send to the %s')%self.device.current_friendly_name)
            la.setWordWrap(True)
            self.base.b = b = QPushButton(QIcon(I('list_remove.png')),
                _('&Ignore the %s in calibre')%device.current_friendly_name,
                self.base)
            b.clicked.connect(self.ignore_device)
            self.config_ign_folders_button = cif = QPushButton(
                QIcon(I('tb_folder.png')), _('Change scanned &folders'))
            cif.setStyleSheet(
                    'QPushButton { font-weight: bold; }')
            if highlight_ignored_folders:
                cif.setIconSize(QSize(64, 64))
            self.show_debug_button = bd = QPushButton(QIcon(I('debug.png')),
                    _('Show device information'))
            bd.clicked.connect(self.show_debug_info)
            cif.clicked.connect(self.change_ignored_folders)

            l.addWidget(b, 0, 0, 1, 2)
            l.addWidget(la, 1, 0, 1, 1)
            l.addWidget(self.formats, 2, 0, 5, 1)
            l.addWidget(cif, 2, 1, 1, 1)
            l.addWidget(self.template, 3, 1, 1, 1)
            l.addWidget(self.send_to, 4, 1, 1, 1)
            l.addWidget(self.show_debug_button, 5, 1, 1, 1)
            l.setRowStretch(6, 10)
            l.addWidget(r, 7, 0, 1, 2)
            l.setRowStretch(7, 100)

        self.igntab = IgnoredDevices(self.device.prefs['history'],
                self.device.prefs['blacklist'])
        self.addTab(self.igntab, _('Ignored devices'))
        self.current_ignored_folders = self.get_pref('ignored_folders')
        self.initial_ignored_folders = self.current_ignored_folders

        self.setCurrentIndex(1 if msg else 0)