Exemplo n.º 1
0
    def show_context_menu(self, point):
        item = self.currentItem()

        def key(k):
            sc = str(QKeySequence(k | Qt.KeyboardModifier.ControlModifier).toString(QKeySequence.SequenceFormat.NativeText))
            return ' [%s]'%sc

        if item is not None:
            m = QMenu(self)
            m.addAction(QIcon(I('edit_input.png')), _('Change the location this entry points to'), self.edit_item)
            m.addAction(QIcon(I('modified.png')), _('Bulk rename all selected items'), self.bulk_rename)
            m.addAction(QIcon(I('trash.png')), _('Remove all selected items'), self.del_items)
            m.addSeparator()
            ci = str(item.data(0, Qt.ItemDataRole.DisplayRole) or '')
            p = item.parent() or self.invisibleRootItem()
            idx = p.indexOfChild(item)
            if idx > 0:
                m.addAction(QIcon(I('arrow-up.png')), (_('Move "%s" up')%ci)+key(Qt.Key.Key_Up), self.move_up)
            if idx + 1 < p.childCount():
                m.addAction(QIcon(I('arrow-down.png')), (_('Move "%s" down')%ci)+key(Qt.Key.Key_Down), self.move_down)
            if item.parent() is not None:
                m.addAction(QIcon(I('back.png')), (_('Unindent "%s"')%ci)+key(Qt.Key.Key_Left), self.move_left)
            if idx > 0:
                m.addAction(QIcon(I('forward.png')), (_('Indent "%s"')%ci)+key(Qt.Key.Key_Right), self.move_right)

            m.addSeparator()
            case_menu = QMenu(_('Change case'), m)
            case_menu.addAction(_('Upper case'), self.upper_case)
            case_menu.addAction(_('Lower case'), self.lower_case)
            case_menu.addAction(_('Swap case'), self.swap_case)
            case_menu.addAction(_('Title case'), self.title_case)
            case_menu.addAction(_('Capitalize'), self.capitalize)
            m.addMenu(case_menu)

            m.exec(QCursor.pos())
Exemplo n.º 2
0
 def contextMenuEvent(self, ev):
     cm = QMenu(self)
     paste = cm.addAction(QIcon.ic('edit-paste.png'), _('Paste cover'))
     copy = cm.addAction(QIcon.ic('edit-copy.png'), _('Copy cover'))
     save = cm.addAction(QIcon.ic('save.png'), _('Save cover to disk'))
     remove = cm.addAction(QIcon.ic('trash.png'), _('Remove cover'))
     gc = cm.addAction(QIcon.ic('default_cover.png'), _('Generate cover from metadata'))
     cm.addSeparator()
     if self.pixmap is not self.default_pixmap and self.data.get('id'):
         book_id = self.data['id']
         cm.tc = QMenu(_('Trim cover'))
         cm.tc.addAction(QIcon.ic('trim.png'), _('Automatically trim borders'), self.trim_cover)
         cm.tc.addAction(_('Trim borders manually'), self.manual_trim_cover)
         cm.tc.addSeparator()
         cm.tc.addAction(QIcon.ic('edit-undo.png'), _('Undo last trim'), self.undo_last_trim).setEnabled(self.last_trim_id == book_id)
         cm.addMenu(cm.tc)
         cm.addSeparator()
     if not QApplication.instance().clipboard().mimeData().hasImage():
         paste.setEnabled(False)
     copy.triggered.connect(self.copy_to_clipboard)
     paste.triggered.connect(self.paste_from_clipboard)
     remove.triggered.connect(self.remove_cover)
     gc.triggered.connect(self.generate_cover)
     save.triggered.connect(self.save_cover)
     create_open_cover_with_menu(self, cm)
     cm.si = m = create_search_internet_menu(self.search_internet.emit)
     cm.addMenu(m)
     cm.exec(ev.globalPos())
Exemplo n.º 3
0
def details_context_menu_event(view,
                               ev,
                               book_info,
                               add_popup_action=False,
                               edit_metadata=None):
    url = view.anchorAt(ev.pos())
    menu = QMenu(view)
    copy_menu = menu.addMenu(QIcon(I('edit-copy.png')), _('Copy'))
    copy_menu.addAction(QIcon(I('edit-copy.png')), _('All book details'),
                        partial(copy_all, view))
    if view.textCursor().hasSelection():
        copy_menu.addAction(QIcon(I('edit-copy.png')), _('Selected text'),
                            view.copy)
    copy_menu.addSeparator()
    copy_links_added = False
    search_internet_added = False
    search_menu = QMenu(_('Search'), menu)
    search_menu.setIcon(QIcon(I('search.png')))
    if url and url.startswith('action:'):
        data = json_loads(from_hex_bytes(url.split(':', 1)[1]))
        search_internet_added = add_item_specific_entries(
            menu, data, book_info, copy_menu, search_menu)
        create_copy_links(copy_menu, data)
        copy_links_added = True
    elif url and not url.startswith('#'):
        ac = book_info.copy_link_action
        ac.current_url = url
        ac.setText(_('Copy link location'))
        menu.addAction(ac)
    if not copy_links_added:
        create_copy_links(copy_menu)

    if not search_internet_added and hasattr(book_info, 'search_internet'):
        sim = create_search_internet_menu(book_info.search_internet)
        if search_menu.isEmpty():
            search_menu = sim
        else:
            search_menu.addSeparator()
            for ac in sim.actions():
                search_menu.addAction(ac)
                ac.setText(_('Search {0} for this book').format(ac.text()))
    if not search_menu.isEmpty():
        menu.addMenu(search_menu)
    for ac in tuple(menu.actions()):
        if not ac.isEnabled():
            menu.removeAction(ac)
    menu.addSeparator()
    if add_popup_action:
        ac = menu.addAction(_('Open the Book details window'))
        ac.triggered.connect(book_info.show_book_info)
    else:
        from calibre.gui2.ui import get_gui
        ema = get_gui().iactions['Edit Metadata'].menuless_qaction
        menu.addAction(
            _('Open the Edit metadata window') + '\t' +
            ema.shortcut().toString(QKeySequence.SequenceFormat.NativeText),
            edit_metadata)
    if len(menu.actions()) > 0:
        menu.exec_(ev.globalPos())
Exemplo n.º 4
0
 def contextMenuEvent(self, ev):
     m = QMenu(self)
     m.addAction(QIcon.ic('sort.png'), _('Sort tabs alphabetically'),
                 self.sort_alphabetically)
     hidden = self.current_db.new_api.pref('virt_libs_hidden')
     if hidden:
         s = m._s = m.addMenu(_('Restore hidden tabs'))
         for x in hidden:
             s.addAction(x, partial(self.restore, x))
     m.addAction(_('Hide Virtual library tabs'), self.disable_bar)
     if gprefs['vl_tabs_closable']:
         m.addAction(QIcon.ic('drm-locked.png'),
                     _('Lock Virtual library tabs'), self.lock_tab)
     else:
         m.addAction(QIcon.ic('drm-unlocked.png'),
                     _('Unlock Virtual library tabs'), self.unlock_tab)
     i = self.tabAt(ev.pos())
     if i > -1:
         vl = str(self.tabData(i) or '')
         if vl:
             vln = vl.replace('&', '&&')
             m.addSeparator()
             m.addAction(QIcon.ic('edit_input.png'),
                         _('Edit "%s"') % vln,
                         partial(self.gui.do_create_edit, name=vl))
             m.addAction(QIcon.ic('trash.png'),
                         _('Delete "%s"') % vln,
                         partial(self.gui.remove_vl_triggered, name=vl))
     m.exec(ev.globalPos())
Exemplo n.º 5
0
 def contextMenuEvent(self, ev):
     cm = QMenu(self)
     paste = cm.addAction(_('Paste cover'))
     copy = cm.addAction(_('Copy cover'))
     save = cm.addAction(_('Save cover to disk'))
     remove = cm.addAction(_('Remove cover'))
     gc = cm.addAction(_('Generate cover from metadata'))
     cm.addSeparator()
     if not QApplication.instance().clipboard().mimeData().hasImage():
         paste.setEnabled(False)
     copy.triggered.connect(self.copy_to_clipboard)
     paste.triggered.connect(self.paste_from_clipboard)
     remove.triggered.connect(self.remove_cover)
     gc.triggered.connect(self.generate_cover)
     save.triggered.connect(self.save_cover)
     create_open_cover_with_menu(self, cm)
     cm.si = m = create_search_internet_menu(self.search_internet.emit)
     cm.addMenu(m)
     cm.exec_(ev.globalPos())
Exemplo n.º 6
0
    def show_context_menu(self, pos):
        m = QMenu(self)
        a = m.addAction
        c = self.editor.cursorForPosition(pos)
        origc = QTextCursor(c)
        current_cursor = self.editor.textCursor()
        r = origr = self.editor.syntax_range_for_cursor(c)
        if (
                r is None or not r.format.property(SPELL_PROPERTY)
        ) and c.positionInBlock() > 0 and not current_cursor.hasSelection():
            c.setPosition(c.position() - 1)
            r = self.editor.syntax_range_for_cursor(c)

        if r is not None and r.format.property(SPELL_PROPERTY):
            word = self.editor.text_for_range(c.block(), r)
            locale = self.editor.spellcheck_locale_for_cursor(c)
            orig_pos = c.position()
            c.setPosition(orig_pos - utf16_length(word))
            found = False
            self.editor.setTextCursor(c)
            if self.editor.find_spell_word([word],
                                           locale.langcode,
                                           center_on_cursor=False):
                found = True
                fc = self.editor.textCursor()
                if fc.position() < c.position():
                    self.editor.find_spell_word([word],
                                                locale.langcode,
                                                center_on_cursor=False)
            spell_cursor = self.editor.textCursor()
            if current_cursor.hasSelection():
                # Restore the current cursor so that any selection is preserved
                # for the change case actions
                self.editor.setTextCursor(current_cursor)
            if found:
                suggestions = dictionaries.suggestions(word, locale)[:7]
                if suggestions:
                    for suggestion in suggestions:
                        ac = m.addAction(
                            suggestion,
                            partial(self.editor.simple_replace,
                                    suggestion,
                                    cursor=spell_cursor))
                        f = ac.font()
                        f.setBold(True), ac.setFont(f)
                    m.addSeparator()
                m.addAction(actions['spell-next'])
                m.addAction(_('Ignore this word'),
                            partial(self._nuke_word, None, word, locale))
                dics = dictionaries.active_user_dictionaries
                if len(dics) > 0:
                    if len(dics) == 1:
                        m.addAction(
                            _('Add this word to the dictionary: {0}').format(
                                dics[0].name),
                            partial(self._nuke_word, dics[0].name, word,
                                    locale))
                    else:
                        ac = m.addAction(_('Add this word to the dictionary'))
                        dmenu = QMenu(m)
                        ac.setMenu(dmenu)
                        for dic in dics:
                            dmenu.addAction(
                                dic.name,
                                partial(self._nuke_word, dic.name, word,
                                        locale))
                m.addSeparator()

        if origr is not None and origr.format.property(LINK_PROPERTY):
            href = self.editor.text_for_range(origc.block(), origr)
            m.addAction(
                _('Open %s') % href, partial(self.link_clicked.emit, href))

        if origr is not None and (origr.format.property(TAG_NAME_PROPERTY)
                                  or origr.format.property(CSS_PROPERTY)):
            word = self.editor.text_for_range(origc.block(), origr)
            item_type = 'tag_name' if origr.format.property(
                TAG_NAME_PROPERTY) else 'css_property'
            url = help_url(word,
                           item_type,
                           self.editor.highlighter.doc_name,
                           extra_data=current_container().opf_version)
            if url is not None:
                m.addAction(
                    _('Show help for: %s') % word, partial(open_url, url))

        for x in ('undo', 'redo'):
            ac = actions['editor-%s' % x]
            if ac.isEnabled():
                a(ac)
        m.addSeparator()
        for x in ('cut', 'copy', 'paste'):
            ac = actions['editor-' + x]
            if ac.isEnabled():
                a(ac)
        m.addSeparator()
        m.addAction(_('&Select all'), self.editor.select_all)
        if self.selected_text or self.has_marked_text:
            update_mark_text_action(self)
            m.addAction(actions['mark-selected-text'])
        if self.syntax != 'css' and actions['editor-cut'].isEnabled():
            cm = QMenu(_('Change &case'), m)
            for ac in 'upper lower swap title capitalize'.split():
                cm.addAction(actions['transform-case-' + ac])
            m.addMenu(cm)
        if self.syntax == 'html':
            m.addAction(actions['multisplit'])
        m.exec_(self.editor.viewport().mapToGlobal(pos))
Exemplo n.º 7
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')))
        connect_lambda(b.clicked, self, lambda self: self.view.next_change(-1))
        b.setToolTip(_('Go to previous change') + ' [p]')
        b.setText(_('&Previous change')), b.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
        l.addWidget(b, r, 0)

        self.bn = b = QToolButton(self)
        b.setIcon(QIcon(I('forward.png')))
        connect_lambda(b.clicked, self, lambda self: self.view.next_change(1))
        b.setToolTip(_('Go to next change') + ' [n]')
        b.setText(_('&Next change')), b.setToolButtonStyle(Qt.ToolButtonStyle.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'))
        connect_lambda(s.returnPressed, self, lambda self: self.do_search(False))
        self.sbn = b = QToolButton(self)
        b.setIcon(QIcon(I('arrow-down.png')))
        connect_lambda(b.clicked, self, lambda self: self.do_search(False))
        b.setToolTip(_('Find next match'))
        b.setText(_('Next &match')), b.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
        l.addWidget(b, r, 3)
        self.sbp = b = QToolButton(self)
        b.setIcon(QIcon(I('arrow-up.png')))
        connect_lambda(b.clicked, self, lambda self: self.do_search(True))
        b.setToolTip(_('Find previous match'))
        b.setText(_('P&revious match')), b.setToolButtonStyle(Qt.ToolButtonStyle.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.ToolButtonStyle.ToolButtonTextBesideIcon)
        b.setToolTip(_('Change how the differences are displayed'))
        b.setPopupMode(QToolButton.ToolButtonPopupMode.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, stretch=100)
        if self.show_open_in_editor:
            self.edit_msg = QLabel(_('Double click right side to edit'))
            self.edit_msg.setToolTip(textwrap.fill(_(
                'Double click on any change in the right panel to edit that location in the editor')))
            self.hl.addWidget(self.edit_msg)

        self.bb.setStandardButtons(QDialogButtonBox.StandardButton.Close)
        if self.revert_button_msg is not None:
            self.rvb = b = self.bb.addButton(self.revert_button_msg, QDialogButtonBox.ButtonRole.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(QDialogButtonBox.StandardButton.Close).setDefault(True)
        self.hl.addWidget(self.bb)

        self.view.setFocus(Qt.FocusReason.OtherFocusReason)
Exemplo n.º 8
0
class LocationManager(QObject):  # {{{

    locations_changed = pyqtSignal()
    unmount_device = pyqtSignal()
    location_selected = pyqtSignal(object)
    configure_device = pyqtSignal()
    update_device_metadata = pyqtSignal()

    def __init__(self, parent=None):
        QObject.__init__(self, parent)
        self.free = [-1, -1, -1]
        self.count = 0
        self.location_actions = QActionGroup(self)
        self.location_actions.setExclusive(True)
        self.current_location = 'library'
        self._mem = []
        self.tooltips = {}

        self.all_actions = []

        def ac(name, text, icon, tooltip):
            icon = QIcon(I(icon))
            ac = self.location_actions.addAction(icon, text)
            setattr(self, 'location_' + name, ac)
            ac.setAutoRepeat(False)
            ac.setCheckable(True)
            receiver = partial(self._location_selected, name)
            ac.triggered.connect(receiver)
            self.tooltips[name] = tooltip

            m = QMenu(parent)
            self._mem.append(m)
            a = m.addAction(icon, tooltip)
            a.triggered.connect(receiver)
            if name != 'library':
                self._mem.append(a)
                a = m.addAction(QIcon(I('eject.png')), _('Eject this device'))
                a.triggered.connect(self._eject_requested)
                self._mem.append(a)
                a = m.addAction(QIcon(I('config.png')),
                                _('Configure this device'))
                a.triggered.connect(self._configure_requested)
                self._mem.append(a)
                a = m.addAction(QIcon(I('sync.png')),
                                _('Update cached metadata on device'))
                a.triggered.connect(
                    lambda x: self.update_device_metadata.emit())
                self._mem.append(a)

            else:
                ac.setToolTip(tooltip)
            ac.setMenu(m)
            ac.calibre_name = name

            self.all_actions.append(ac)
            return ac

        self.library_action = ac('library', _('Library'), 'lt.png',
                                 _('Show books in calibre library'))
        ac('main', _('Device'), 'reader.png',
           _('Show books in the main memory of the device'))
        ac('carda', _('Card A'), 'sd.png', _('Show books in storage card A'))
        ac('cardb', _('Card B'), 'sd.png', _('Show books in storage card B'))

    def set_switch_actions(self, quick_actions, rename_actions, delete_actions,
                           switch_actions, choose_action):
        self.switch_menu = self.library_action.menu()
        if self.switch_menu:
            self.switch_menu.addSeparator()
        else:
            self.switch_menu = QMenu()

        self.switch_menu.addAction(choose_action)
        self.cs_menus = []
        for t, acs in [(_('Quick switch'), quick_actions),
                       (_('Rename library'), rename_actions),
                       (_('Delete library'), delete_actions)]:
            if acs:
                self.cs_menus.append(QMenu(t))
                for ac in acs:
                    self.cs_menus[-1].addAction(ac)
                self.switch_menu.addMenu(self.cs_menus[-1])
        self.switch_menu.addSeparator()
        for ac in switch_actions:
            self.switch_menu.addAction(ac)

        if self.switch_menu != self.library_action.menu():
            self.library_action.setMenu(self.switch_menu)

    def _location_selected(self, location, *args):
        if location != self.current_location and hasattr(
                self, 'location_' + location):
            self.current_location = location
            self.location_selected.emit(location)
            getattr(self, 'location_' + location).setChecked(True)

    def _eject_requested(self, *args):
        self.unmount_device.emit()

    def _configure_requested(self):
        self.configure_device.emit()

    def update_devices(self, cp=(None, None), fs=[-1, -1, -1], icon=None):
        if icon is None:
            icon = I('reader.png')
        self.location_main.setIcon(QIcon(icon))
        had_device = self.has_device
        if cp is None:
            cp = (None, None)
        if isinstance(cp, (bytes, unicode_type)):
            cp = (cp, None)
        if len(fs) < 3:
            fs = list(fs) + [0]
        self.free[0] = fs[0]
        self.free[1] = fs[1]
        self.free[2] = fs[2]
        cpa, cpb = cp
        self.free[1] = fs[1] if fs[1] is not None and cpa is not None else -1
        self.free[2] = fs[2] if fs[2] is not None and cpb is not None else -1
        self.update_tooltips()
        if self.has_device != had_device:
            self.location_library.setChecked(True)
            self.locations_changed.emit()
            if not self.has_device:
                self.location_library.trigger()

    def update_tooltips(self):
        for i, loc in enumerate(('main', 'carda', 'cardb')):
            t = self.tooltips[loc]
            if self.free[i] > -1:
                t += '\n\n%s ' % human_readable(self.free[i]) + _('available')
            ac = getattr(self, 'location_' + loc)
            ac.setToolTip(t)
            ac.setWhatsThis(t)
            ac.setStatusTip(t)

    @property
    def has_device(self):
        return max(self.free) > -1

    @property
    def available_actions(self):
        ans = [self.location_library]
        for i, loc in enumerate(('main', 'carda', 'cardb')):
            if self.free[i] > -1:
                ans.append(getattr(self, 'location_' + loc))
        return ans