diff --git a/src/calibre/gui2/search_restriction_mixin.py b/src/calibre/gui2/search_restriction_mixin.py index 54274a104d..cad8ba9f00 100644 --- a/src/calibre/gui2/search_restriction_mixin.py +++ b/src/calibre/gui2/search_restriction_mixin.py @@ -6,15 +6,18 @@ Created on 10 Jun 2010 from functools import partial -from PyQt4.Qt import (Qt, QMenu, QPoint, QIcon, QDialog, QGridLayout, QLabel, - QLineEdit, QDialogButtonBox, QEvent, QToolTip) +from PyQt4.Qt import ( + Qt, QMenu, QPoint, QIcon, QDialog, QGridLayout, QLabel, QLineEdit, + QDialogButtonBox, QSize) + from calibre.gui2 import error_dialog, question_dialog from calibre.gui2.widgets import ComboBoxWithHelp from calibre.utils.icu import sort_key from calibre.utils.pyparsing import ParseException from calibre.utils.search_query_parser import saved_searches -class CreateVirtualLibrary(QDialog): +class CreateVirtualLibrary(QDialog): # {{{ + def __init__(self, gui, existing_names): QDialog.__init__(self, None, Qt.WindowSystemMenuHint | Qt.WindowTitleHint) @@ -22,22 +25,49 @@ class CreateVirtualLibrary(QDialog): self.existing_names = existing_names self.setWindowTitle(_('Create virtual library')) + self.setWindowIcon(QIcon(I('lt.png'))) + gl = QGridLayout() self.setLayout(gl) - gl.addWidget(QLabel(_('Virtual library name')), 0, 0) + self.la1 = la1 = QLabel(_('Virtual library &name:')) + gl.addWidget(la1, 0, 0) self.vl_name = QLineEdit() - self.vl_name.setMinimumWidth(400) + la1.setBuddy(self.vl_name) gl.addWidget(self.vl_name, 0, 1) - gl.addWidget(QLabel(_('Search expression')), 1, 0) + + self.la2 = la2 = QLabel(_('&Search expression:')) + gl.addWidget(la2, 1, 0) self.vl_text = QLineEdit() + la2.setBuddy(self.vl_text) gl.addWidget(self.vl_text, 1, 1) self.vl_text.setText(self.build_full_search_string()) - bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) - bb.accepted.connect(self.accepted) - bb.rejected.connect(self.rejected) - gl.addWidget(bb, 2, 0, 1, 0) - search_templates = [ + self.hl = hl = QLabel(_(''' +

Virtual Libraries

+ +

Using virtual libraries you can restrict calibre to only show + you books that match a search. When a virtual library is in effect, calibre + behaves as though the library contains only the matched books. The Tag Browser + display only the tags/authors/series/etc. that belong to the matched books and any searches + you do will only search within the books in the virtual library. This + is a good way to partition your large library into smaller and easier to work with subsets.

+ +

For example you can use a Virtual Library to only show you books with the Tag "Unread" + or only books by "My Favorite Author" or only books in a particular series.

+ ''')) + hl.setWordWrap(True) + hl.setFrameStyle(hl.StyledPanel) + gl.addWidget(hl, 0, 3, 3, 1) + + bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + bb.accepted.connect(self.accept) + bb.rejected.connect(self.reject) + gl.addWidget(bb, 3, 0, 1, 0) + + self.resize(self.sizeHint()+QSize(150, 25)) + + def build_full_search_string(self): + search_templates = ( '', '{cl}', '{cr}', @@ -46,11 +76,10 @@ class CreateVirtualLibrary(QDialog): '(({cl}) and ({sb}))', '(({cr}) and ({sb}))', '(({cl}) and ({cr}) and ({sb}))' - ] + ) - def build_full_search_string(self): sb = self.gui.search.current_text - db = self.gui.library_view.model().db + db = self.gui.current_db cr = db.data.get_search_restriction() cl = db.data.get_base_restriction() dex = 0 @@ -60,10 +89,10 @@ class CreateVirtualLibrary(QDialog): dex += 2 if cl: dex += 1 - template = self.search_templates[dex] + template = search_templates[dex] return template.format(cl=cl, cr=cr, sb=sb) - def accepted(self): + def accept(self): n = unicode(self.vl_name.text()) if not n: error_dialog(self.gui, _('No name'), @@ -94,42 +123,17 @@ class CreateVirtualLibrary(QDialog): det_msg=e.msg, show=True) return - if not recs: - if question_dialog(self.gui, _('Search found no books'), - _('The search found no books, so the virtual library ' - 'will be empty. Do you really want to use that search?'), - default_yes=False) == self.Rejected: + if not recs and not question_dialog( + self.gui, _('Search found no books'), + _('The search found no books, so the virtual library ' + 'will be empty. Do you really want to use that search?'), + default_yes=False): return self.library_name = n self.library_search = v - self.accept() - - def rejected(self): - self.reject() - -class VirtLibMenu(QMenu): - - def __init__(self): - QMenu.__init__(self) - self.show_tt_for = [] - - def event(self, e): - QMenu.event(self, e) - if e.type() == QEvent.ToolTip: - a = self.activeAction() - if a and a in self.show_tt_for: - tt = a.toolTip() - if tt: - QToolTip.showText(e.globalPos(), tt) - return True - - def clear(self): - self.show_tt_for = [] - QMenu.clear(self) - - def show_tooltip_for_action(self, a): - self.show_tt_for.append(a) + QDialog.accept(self) +# }}} class SearchRestrictionMixin(object): @@ -139,7 +143,7 @@ class SearchRestrictionMixin(object): self.checked = QIcon(I('ok.png')) self.empty = QIcon() - self.virtual_library_menu = VirtLibMenu() + self.virtual_library_menu = QMenu() self.virtual_library.clicked.connect(self.virtual_library_clicked) @@ -161,8 +165,7 @@ class SearchRestrictionMixin(object): db = self.library_view.model().db virt_libs = db.prefs.get('virtual_libraries', {}) cd = CreateVirtualLibrary(self, virt_libs.keys()) - ret = cd.exec_() - if ret == cd.Accepted: + if cd.exec_() == cd.Accepted: self.add_virtual_library(db, cd.library_name, cd.library_search) self.apply_virtual_library(cd.library_name) @@ -180,9 +183,8 @@ class SearchRestrictionMixin(object): a = m.addAction(_('Create Virtual Library')) a.triggered.connect(self.do_create) a.setToolTip(_('Create a new virtual library from the results of a search')) - m.show_tooltip_for_action(a) - self.rm_menu = a = VirtLibMenu() + self.rm_menu = a = QMenu() a.setTitle(_('Remove Virtual Library')) a.aboutToShow.connect(self.build_virtual_library_list) m.addMenu(a) @@ -212,7 +214,6 @@ class SearchRestrictionMixin(object): a = m.addAction(self.checked if vl == current_lib else self.empty, vl) a.setToolTip(virt_libs[vl]) a.triggered.connect(partial(self.apply_virtual_library, library=vl)) - m.show_tooltip_for_action(a) p = QPoint(0, self.virtual_library.height()) self.virtual_library_menu.popup(self.virtual_library.mapToGlobal(p)) @@ -238,7 +239,6 @@ class SearchRestrictionMixin(object): def add_action(name, search): a = m.addAction(name) a.setToolTip(search) - m.show_tooltip_for_action(a) a.triggered.connect(partial(self.remove_vl_triggered, name=name)) for n in sorted(virt_libs.keys(), key=sort_key): @@ -368,3 +368,14 @@ class SearchRestrictionMixin(object): self.search_count.setStyleSheet( 'QLabel { background-color: transparent; }') self.search_count.setText(t) + +if __name__ == '__main__': + from calibre.gui2 import Application + from calibre.gui2.preferences import init_gui + app = Application([]) + app + gui = init_gui() + d = CreateVirtualLibrary(gui, []) + d.exec_() + +