def init_saved_seach_box_mixin(self): self.saved_search.changed.connect(self.saved_searches_changed) ac = self.search.findChild(QAction, QT_HIDDEN_CLEAR_ACTION) if ac is not None: ac.triggered.connect(self.saved_search.clear) self.save_search_button.clicked.connect( self.saved_search.save_search_button_clicked) self.copy_search_button.clicked.connect( self.saved_search.copy_search_button_clicked) # self.saved_searches_changed() self.saved_search.initialize(self.search, colorize=True, help_text=_('Saved searches')) self.saved_search.tool_tip_text=_('Choose saved search or enter name for new saved search') self.saved_search.setToolTip(self.saved_search.tool_tip_text) self.saved_search.setStatusTip(self.saved_search.tool_tip_text) for x in ('copy', 'save'): b = getattr(self, x+'_search_button') b.setStatusTip(b.toolTip()) self.save_search_button.setToolTip('<p>' + _("Save current search under the name shown in the box. " "Press and hold for a pop-up options menu.") + '</p>') self.save_search_button.setMenu(QMenu(self.save_search_button)) self.save_search_button.menu().addAction( QIcon(I('plus.png')), _('Create Saved search'), self.saved_search.save_search_button_clicked) self.save_search_button.menu().addAction( QIcon(I('trash.png')), _('Delete Saved search'), self.saved_search.delete_current_search) self.save_search_button.menu().addAction( QIcon(I('search.png')), _('Manage Saved searches'), partial(self.do_saved_search_edit, None)) self.add_saved_search_button.setMenu(QMenu(self.add_saved_search_button)) self.add_saved_search_button.menu().aboutToShow.connect(self.populate_add_saved_search_menu)
def init_search_restriction_mixin(self): self.checked = QIcon(I('ok.png')) self.empty = QIcon(I('blank.png')) self.current_search_action = QAction(self.empty, _('*current search'), self) self.current_search_action.triggered.connect(partial(self.apply_virtual_library, library='*')) self.addAction(self.current_search_action) self.keyboard.register_shortcut( 'vl-from-current-search', _('Virtual library from current search'), description=_( 'Create a temporary Virtual library from the current search'), group=pgettext('search restriction group name', 'Miscellaneous'), default_keys=('Ctrl+*',), action=self.current_search_action) self.search_based_vl_name = None self.search_based_vl = None self.virtual_library_menu = QMenu(self.virtual_library) self.virtual_library.setMenu(self.virtual_library_menu) self.virtual_library_menu.aboutToShow.connect(self.virtual_library_menu_about_to_show) self.clear_vl.clicked.connect(lambda x: (self.apply_virtual_library(), self.clear_additional_restriction())) self.virtual_library_tooltip = \ _('Use a "Virtual library" to show only a subset of the books present in this library') self.virtual_library.setToolTip(self.virtual_library_tooltip) self.search_restriction = ComboBoxWithHelp(self) self.search_restriction.setVisible(False) self.clear_vl.setText(_("(all books)")) self.ar_menu = QMenu(_('Additional restriction'), self.virtual_library_menu) self.edit_menu = QMenu(_('Edit Virtual library'), self.virtual_library_menu) self.rm_menu = QMenu(_('Remove Virtual library'), self.virtual_library_menu) self.search_restriction_list_built = False
def __init__(self, parent=None): QMenu.__init__(self, parent) self.ip_text = '' mitem = self.addAction(QIcon(I('devices/folder.png')), _('Connect to folder')) mitem.setEnabled(True) connect_lambda(mitem.triggered, self, lambda self: self.connect_to_folder.emit()) self.connect_to_folder_action = mitem self.addSeparator() self.toggle_server_action = \ self.addAction(QIcon(I('network-server.png')), _('Start Content server')) connect_lambda(self.toggle_server_action.triggered, self, lambda self: self.toggle_server.emit()) self.control_smartdevice_action = \ self.addAction(QIcon(I('dot_red.png')), self.DEVICE_MSGS[0]) connect_lambda(self.control_smartdevice_action.triggered, self, lambda self: self.control_smartdevice.emit()) self.addSeparator() self.email_actions = [] if hasattr(parent, 'keyboard'): r = parent.keyboard.register_shortcut prefix = 'Share/Connect Menu ' gr = ConnectShareAction.action_spec[0] for attr in ('folder', ): ac = getattr(self, 'connect_to_%s_action'%attr) r(prefix + attr, str(ac.text()), action=ac, group=gr) r(prefix+' content server', _('Start/stop Content server'), action=self.toggle_server_action, group=gr)
def build_menu(self, action): m = action.menu() ac = MenuAction(action, self) if m is None: m = QMenu() m.addAction(action) ac.setMenu(m) return ac
def show_item_context_menu(self, point): item = self.items.currentItem() self.context_menu = QMenu(self) self.context_menu.addAction(self.search_icon, _('Find item in the Tag browser'), partial(self.item_doubleclicked, item)) self.context_menu.addAction(self.search_icon, _('Find item in the library'), partial(self.do_search, follow_library_view=False)) self.context_menu.popup(self.items.mapToGlobal(point)) self.context_menu = QMenu(self)
def build_context_menu(self): cm = QMenu(self) paste = cm.addAction(QIcon.ic('edit-paste.png'), _('Paste cover')) copy = cm.addAction(QIcon.ic('edit-copy.png'), _('Copy cover')) if not QApplication.instance().clipboard().mimeData().hasImage(): paste.setEnabled(False) copy.triggered.connect(self.copy_to_clipboard) paste.triggered.connect(self.paste_from_clipboard) return cm
def genesis(self): self.search_icon = QIcon.ic('search.png') self.qaction.triggered.connect(self.toggle_selected) self.menu = m = self.qaction.menu() m.aboutToShow.connect(self.about_to_show_menu) ma = partial(self.create_menu_action, m) self.show_marked_action = a = ma('mark_with_text', _('Mark books with text label'), icon='marked.png') a.triggered.connect(partial(self.mark_with_text, book_ids=None)) global mark_books_with_text mark_books_with_text = self.mark_with_text self.show_marked_action = a = ma('show-marked', _('Show marked books'), icon='search.png', shortcut='Shift+Ctrl+M') a.triggered.connect(self.show_marked) self.show_marked_with_text = QMenu( _('Show marked books with text label')) self.show_marked_with_text.setIcon(self.search_icon) m.addMenu(self.show_marked_with_text) self.clear_selected_marked_action = a = ma( 'clear-marks-on-selected', _('Clear marks for selected books'), icon='clear_left.png') a.triggered.connect(self.clear_marks_on_selected_books) self.clear_marked_action = a = ma('clear-all-marked', _('Clear all marked books'), icon='clear_left.png') a.triggered.connect(self.clear_all_marked) m.addSeparator() self.mark_author_action = a = ma( 'mark-author', _('Mark all books by selected author(s)'), icon='plus.png') connect_lambda(a.triggered, self, lambda self: self.mark_field('authors', True)) self.mark_series_action = a = ma( 'mark-series', _('Mark all books in the selected series'), icon='plus.png') connect_lambda(a.triggered, self, lambda self: self.mark_field('series', True)) m.addSeparator() self.unmark_author_action = a = ma( 'unmark-author', _('Clear all books by selected author(s)'), icon='minus.png') connect_lambda(a.triggered, self, lambda self: self.mark_field('authors', False)) self.unmark_series_action = a = ma( 'unmark-series', _('Clear all books in the selected series'), icon='minus.png') connect_lambda(a.triggered, self, lambda self: self.mark_field('series', False))
def publish_new_menu(self): menu = self.notifier.contextMenu() if menu is None: menu = QMenu() if len(menu.actions()) == 0: menu.addAction(self.notifier.icon(), _('Show/hide %s') % self.title, self.notifier.emit_activated) # The menu must have at least one entry, namely the show/hide entry. # This is necessary as Canonical in their infinite wisdom decided to # force all tray icons to show their popup menus when clicked. self.dbus_menu.publish_new_menu(menu)
def clone_one_menu(m): m.aboutToShow.emit() ans = QMenu(m.parent()) for ac in m.actions(): cac = clone_action(ac, ans) ans.addAction(cac) m = ac.menu() if m is not None: cac.setMenu(clone_menu(m)) return ans
def about_to_show(self): if sip.isdeleted(self.clone): return cm = self.clone.menu() if cm is None: return before = list(QMenu.actions(cm)) cm.aboutToShow.emit() after = list(QMenu.actions(cm)) if before != after: self.clone_menu()
def create_application_menubar(cls): if not cls.__actions: mb = QMenuBar(None) menu = QMenu() for action in cls.get_menubar_actions(): menu.addAction(action) cls.__actions.append(action) mb.addMenu(menu) cls.___menu_bar = mb cls.___menu = menu return cls.__actions
def add_format_entries(menu, data, book_info, copy_menu, search_menu): from calibre.ebooks.oeb.polish.main import SUPPORTED from calibre.gui2.ui import get_gui book_id = int(data['book_id']) fmt = data['fmt'] init_find_in_tag_browser(search_menu, book_info.find_in_tag_browser_action, 'formats', fmt) init_find_in_grouped_search(search_menu, 'formats', fmt, book_info) db = get_gui().current_db.new_api ofmt = fmt.upper() if fmt.startswith('ORIGINAL_') else 'ORIGINAL_' + fmt nfmt = ofmt[len('ORIGINAL_'):] fmts = {x.upper() for x in db.formats(book_id)} for a, t in [ ('remove', _('Delete the %s format')), ('save', _('Save the %s format to disk')), ('restore', _('Restore the %s format')), ('compare', ''), ('set_cover', _('Set the book cover from the %s file')), ]: if a == 'restore' and not fmt.startswith('ORIGINAL_'): continue if a == 'compare': if ofmt not in fmts or nfmt not in SUPPORTED: continue t = _('Compare to the %s format') % (fmt[9:] if fmt.startswith('ORIGINAL_') else ofmt) else: t = t % fmt ac = getattr(book_info, '%s_format_action'%a) ac.current_fmt = (book_id, fmt) ac.setText(t) menu.addAction(ac) if not fmt.upper().startswith('ORIGINAL_'): from calibre.gui2.open_with import edit_programs, populate_menu m = QMenu(_('Open %s with...') % fmt.upper()) def connect_action(ac, entry): connect_lambda(ac.triggered, book_info, lambda book_info: book_info.open_with(book_id, fmt, entry)) populate_menu(m, connect_action, fmt) if len(m.actions()) == 0: menu.addAction(_('Open %s with...') % fmt.upper(), partial(book_info.choose_open_with, book_id, fmt)) else: m.addSeparator() m.addAction(_('Add other application for %s files...') % fmt.upper(), partial(book_info.choose_open_with, book_id, fmt)) m.addAction(_('Edit Open with applications...'), partial(edit_programs, fmt, book_info)) menu.addMenu(m) menu.ow = m if fmt.upper() in SUPPORTED: menu.addSeparator() menu.addAction(_('Edit %s format') % fmt.upper(), partial(book_info.edit_fmt, book_id, fmt)) path = data['path'] if path: if data.get('fname'): path = os.path.join(path, data['fname'] + '.' + data['fmt'].lower()) ac = book_info.copy_link_action ac.current_url = path ac.setText(_('Path to file')) copy_menu.addAction(ac)
def __init__(self, location_manager, parent): QObject.__init__(self, parent) self.gui = parent self.location_manager = location_manager self.added_actions = [] self.last_actions = [] self.donate_action = QAction(_('Donate'), self) self.donate_menu = QMenu() self.donate_menu.addAction(self.gui.donate_action) self.donate_action.setMenu(self.donate_menu) self.refresh_timer = t = QTimer(self) t.setInterval(200), t.setSingleShot(True), t.timeout.connect(self.refresh_bar)
def show_context_menu(self, point): idx = self.tweaks_view.currentIndex() if not idx.isValid(): return True tweak = self.tweaks.data(idx, Qt.ItemDataRole.UserRole) self.context_menu = QMenu(self) self.context_menu.addAction( self.copy_icon, _('Copy to clipboard'), partial(self.copy_item_to_clipboard, val="%s (%s: %s)" % (tweak.name, _('ID'), tweak.var_names[0]))) self.context_menu.popup(self.mapToGlobal(point)) return True
def contextMenuEvent(self, event): index = self.indexAt(event.pos()) if not index.isValid(): return plugin = self.model().get_plugin(index) menu = QMenu(self) ca = menu.addAction(_('Configure...'), partial(self.configure_plugin, plugin)) if not plugin.is_customizable(): ca.setEnabled(False) menu.exec(event.globalPos())
def contextMenuEvent(self, ev): m = QMenu(self) m.addAction(_('Set to undefined') + '\t' + QKeySequence(Qt.Key.Key_Space).toString(QKeySequence.SequenceFormat.NativeText), self.clear_to_undefined) m.addSeparator() populate_standard_spinbox_context_menu(self, m) m.popup(ev.globalPos())
def test(): setup_for_cli_run() app = QApplication([]) bus = dbus.SessionBus() dbus_name = BusName('com.calibre-ebook.TestDBusMenu', bus=bus, do_not_queue=True) m = QMenu() ac = m.addAction(QIcon(I('window-close.png')), 'Quit', app.quit) ac.setShortcut(QKeySequence('Ctrl+Q')) menu = DBusMenu('/Menu', bus=bus) menu.publish_new_menu(m) app.exec_() del dbus_name
def __init__(self, location_manager, parent): QObject.__init__(self, parent) self.menu_bar = QMenuBar(parent) self.menu_bar.is_native_menubar = False parent.setMenuBar(self.menu_bar) self.gui = parent self.location_manager = location_manager self.added_actions = [] self.donate_action = QAction(_('Donate'), self) self.donate_menu = QMenu() self.donate_menu.addAction(self.gui.donate_action) self.donate_action.setMenu(self.donate_menu)
def show_context_menu(self, point): idx = self.currentIndex() if idx and idx.isValid() and not idx.data(Qt.ItemDataRole.UserRole): m = QMenu(self) m.addAction(QIcon(I('view.png')), _('View this cover at full size'), self.show_cover) m.addAction(QIcon(I('edit-copy.png')), _('Copy this cover to clipboard'), self.copy_cover) m.exec_(QCursor.pos())
def context_menu_requested(self, widget, ev): if isinstance(widget, Heading): start = widget else: found = False for w in reversed(self.widgets): if w is widget: found = True elif found and isinstance(w, Heading): start = w break else: return found = False lines = [] for w in self.widgets: if found and isinstance(w, Heading): break if w is start: found = True if found: lines += w.lines_for_copy if not lines: return block = '\n'.join(lines).replace('\xa0', ' ') heading = lines[0] m = QMenu(self) m.addAction(QIcon(I('edit-copy.png')), _('Copy') + ' ' + heading.replace('\xa0', ' '), lambda : QApplication.instance().clipboard().setText(block)) all_lines = [] for w in self.widgets: all_lines += w.lines_for_copy all_text = '\n'.join(all_lines).replace('\xa0', ' ') m.addAction(QIcon(I('edit-copy.png')), _('Copy everything'), lambda : QApplication.instance().clipboard().setText(all_text)) m.exec(ev.globalPos())
def __init__(self, location_manager, parent): QObject.__init__(self, parent) f = factory(app_id='com.calibre-ebook.gui') self.menu_bar = f.create_window_menubar(parent) self.is_native_menubar = self.menu_bar.is_native_menubar self.gui = parent self.location_manager = location_manager self.added_actions = [] self.donate_action = QAction(_('Donate'), self) self.donate_menu = QMenu() self.donate_menu.addAction(self.gui.donate_action) self.donate_action.setMenu(self.donate_menu)
def init_find_in_grouped_search(menu, field, value, book_info): from calibre.gui2.ui import get_gui db = get_gui().current_db fm = db.field_metadata field_name = fm.get(field, {}).get('name', None) if field_name is None: # I don't think this can ever happen, but ... return gsts = db.prefs.get('grouped_search_terms', {}) gsts_to_show = [] for v in gsts: fk = fm.search_term_to_field_key(v) if field in fk: gsts_to_show.append(v) if gsts_to_show: m = QMenu((_('Search calibre for %s') + '...')%escape_for_menu(value), menu) m.setIcon(QIcon(I('search.png'))) menu.addMenu(m) m.addAction(QIcon(get_icon_path(field, '')), _('in category %s')%escape_for_menu(field_name), lambda g=field: book_info.search_requested( '{}:"={}"'.format(g, value.replace('"', r'\"')), '')) for gst in gsts_to_show: icon_path = get_icon_path(gst, '@') m.addAction(QIcon(icon_path), _('in grouped search %s')%gst, lambda g=gst: book_info.search_requested( '{}:"={}"'.format(g, value.replace('"', r'\"')), '')) else: menu.addAction(QIcon(I('search.png')), _('Search calibre for {val} in category {name}').format( val=escape_for_menu(value), name=escape_for_menu(field_name)), lambda g=field: book_info.search_requested( '{}:"={}"'.format(g, value.replace('"', r'\"')), ''))
def show_context_menu(self, pos): menu = QMenu(self) menu.addAction(QIcon.ic('plus.png'), _('Expand all'), self.plugin_view.expandAll) menu.addAction(QIcon.ic('minus.png'), _('Collapse all'), self.plugin_view.collapseAll) menu.exec(self.plugin_view.mapToGlobal(pos))
def create_change_case_menu(self, menu): case_menu = QMenu(_('Change case'), menu) action_upper_case = case_menu.addAction(_('Upper case')) action_lower_case = case_menu.addAction(_('Lower case')) action_swap_case = case_menu.addAction(_('Swap case')) action_title_case = case_menu.addAction(_('Title case')) action_capitalize = case_menu.addAction(_('Capitalize')) action_upper_case.triggered.connect(self.upper_case) action_lower_case.triggered.connect(self.lower_case) action_swap_case.triggered.connect(self.swap_case) action_title_case.triggered.connect(self.title_case) action_capitalize.triggered.connect(self.capitalize) menu.addMenu(case_menu) return case_menu
def build_menu(self, ac): ans = CloneAction(ac, self.native_menubar, is_top_level=True) if ans.menu() is None: m = QMenu() m.addAction(CloneAction(ac, self.native_menubar)) ans.setMenu(m) # Qt (as of 5.3.0) does not update global menubar entries # correctly, so we have to rebuild the global menubar. # Without this the Choose Library action shows the text # 'Untitled' and the Location Manager items do not work. ans.text_changed.connect(self.refresh_timer.start) ans.visibility_changed.connect(self.refresh_timer.start) self.native_menubar.addAction(ans) self.added_actions.append(ans) return ans
def show_context_menu(self, point): index = self.books_table.indexAt(point) row = index.row() column = index.column() item = self.books_table.item(index.row(), 0) if item is None: return False book_id = int(item.data(Qt.ItemDataRole.UserRole)) book_displayed = self.book_displayed_in_library_view(book_id) m = self.context_menu = QMenu(self) a = m.addAction(self.select_book_icon, _('Select this book in the library'), partial(self.select_book, book_id)) a.setEnabled(book_displayed) m.addAction(self.search_icon, _('Find item in the library'), partial(self.do_search, follow_library_view=False)) a = m.addAction( self.edit_metadata_icon, _('Edit metadata'), partial(self.edit_metadata, book_id, follow_library_view=False)) a.setEnabled(book_displayed) a = m.addAction(self.quickview_icon, _('Quickview this cell'), partial(self.quickview_item, row, column)) a.setEnabled( self.is_category(self.column_order[column]) and book_displayed and not self.lock_qv.isChecked()) m.addSeparator() m.addAction(self.view_icon, _('Open book in the E-book viewer'), partial(self.view_plugin._view_calibre_books, [book_id])) self.context_menu.popup(self.books_table.mapToGlobal(point)) return True
def add_action(name, bar): if name is None: bar.addSeparator() return try: ac = actions[name] except KeyError: if DEBUG: prints('Unknown editor tool: %r' % name) return bar.addAction(ac) if name == 'insert-tag': w = bar.widgetForAction(ac) if hasattr(w, 'setPopupMode'): # For some unknown reason this button is occassionally a # QPushButton instead of a QToolButton w.setPopupMode( QToolButton.ToolButtonPopupMode.MenuButtonPopup) w.setMenu(self.insert_tag_menu) w.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) w.customContextMenuRequested.connect(w.showMenu) self._build_insert_tag_button_menu() elif name == 'change-paragraph': m = ac.m = QMenu() ac.setMenu(m) ch = bar.widgetForAction(ac) if hasattr(ch, 'setPopupMode'): # For some unknown reason this button is occassionally a # QPushButton instead of a QToolButton ch.setPopupMode( QToolButton.ToolButtonPopupMode.InstantPopup) for name in tuple('h%d' % d for d in range(1, 7)) + ('p', ): m.addAction(actions['rename-block-tag-%s' % name])
def clone_changed(self): otext = self.text() self.setText(self.clone.text()) if otext != self.text: self.text_changed.emit() ov = self.isVisible() self.setVisible(self.clone.isVisible()) if ov != self.isVisible(): self.visibility_changed.emit() self.setEnabled(self.clone.isEnabled()) self.setCheckable(self.clone.isCheckable()) self.setChecked(self.clone.isChecked()) self.setIcon(self.clone.icon()) if self.clone_shortcuts: sc = self.clone.shortcut() if sc and not sc.isEmpty(): self.setText(self.text() + '\t' + sc.toString(QKeySequence.SequenceFormat.NativeText)) if self.clone.menu() is None: if not self.is_top_level: self.setMenu(None) else: m = QMenu(self.text(), self.parent()) m.aboutToShow.connect(self.about_to_show) self.setMenu(m) self.clone_menu()
def __init__(self, parent, prefs): QDialog.__init__(self, parent) self.prefs = prefs self.setWindowTitle(_('Create ToC from XPath')) self.l = l = QVBoxLayout() self.setLayout(l) self.la = la = QLabel(_( 'Specify a series of XPath expressions for the different levels of' ' the Table of Contents. You can use the wizard buttons to help' ' you create XPath expressions.')) la.setWordWrap(True) l.addWidget(la) self.widgets = [] for i in range(5): la = _('Level %s ToC:')%('&%d'%(i+1)) xp = XPathEdit(self) xp.set_msg(la) self.widgets.append(xp) l.addWidget(xp) self.bb = bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok|QDialogButtonBox.StandardButton.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) self.ssb = b = bb.addButton(_('&Save settings'), QDialogButtonBox.ButtonRole.ActionRole) b.clicked.connect(self.save_settings) self.load_button = b = bb.addButton(_('&Load settings'), QDialogButtonBox.ButtonRole.ActionRole) self.load_menu = QMenu(b) b.setMenu(self.load_menu) self.setup_load_button() self.remove_duplicates_cb = QCheckBox(_('Do not add duplicate entries at the same level')) self.remove_duplicates_cb.setChecked(self.prefs.get('xpath_toc_remove_duplicates', True)) l.addWidget(self.remove_duplicates_cb) l.addStretch() l.addWidget(bb) self.resize(self.sizeHint() + QSize(50, 75))
def __init__(self, parent=None): self.loaded_ruleset = None QWidget.__init__(self, parent) self.PREFS_OBJECT = JSONConfig('style-transform-rules') l = QVBoxLayout(self) self.rules_widget = w = Rules(self) w.changed.connect(self.changed.emit) l.addWidget(w) self.h = h = QHBoxLayout() l.addLayout(h) self.export_button = b = QPushButton(_('E&xport'), self) b.setToolTip(_('Export these rules to a file')) b.clicked.connect(self.export_rules) h.addWidget(b) self.import_button = b = QPushButton(_('&Import'), self) b.setToolTip(_('Import previously exported rules')) b.clicked.connect(self.import_rules) h.addWidget(b) self.test_button = b = QPushButton(_('&Test rules'), self) b.clicked.connect(self.test_rules) h.addWidget(b) h.addStretch(10) self.save_button = b = QPushButton(_('&Save'), self) b.setToolTip(_('Save this ruleset for later re-use')) b.clicked.connect(self.save_ruleset) h.addWidget(b) self.export_button = b = QPushButton(_('&Load'), self) self.load_menu = QMenu(self) b.setMenu(self.load_menu) b.setToolTip(_('Load a previously saved ruleset')) b.clicked.connect(self.load_ruleset) h.addWidget(b) self.build_load_menu()