diff --git a/src/calibre/gui2/actions/next_match.py b/src/calibre/gui2/actions/next_match.py index 79de6a2d9b..b88aa0dd59 100644 --- a/src/calibre/gui2/actions/next_match.py +++ b/src/calibre/gui2/actions/next_match.py @@ -29,12 +29,12 @@ class NextMatchAction(InterfaceAction): self.p_action.triggered.connect(self.move_backward) def gui_layout_complete(self): - self.gui.search_highlight_only.setVisible(True) + self.gui.search_options_button.setVisible(True) def location_selected(self, loc): self.can_move = loc == 'library' try: - self.gui.search_highlight_only.setVisible(self.can_move) + self.gui.search_options_button.setVisible(self.can_move) except: import traceback traceback.print_exc() @@ -42,7 +42,7 @@ class NextMatchAction(InterfaceAction): def move_forward(self): if self.can_move is None: self.can_move = self.gui.current_view() is self.gui.library_view - self.gui.search_highlight_only.setVisible(self.can_move) + self.gui.search_options_button.setVisible(self.can_move) if self.can_move: self.gui.current_view().move_highlighted_row(forward=True) @@ -50,7 +50,7 @@ class NextMatchAction(InterfaceAction): def move_backward(self): if self.can_move is None: self.can_move = self.gui.current_view() is self.gui.library_view - self.gui.search_highlight_only.setVisible(self.can_move) + self.gui.search_options_button.setVisible(self.can_move) if self.can_move: self.gui.current_view().move_highlighted_row(forward=False) diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index d3d51066a1..9ef8a546eb 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -7,8 +7,8 @@ __docformat__ = 'restructuredtext en' from functools import partial -from PyQt4.Qt import QIcon, Qt, QWidget, QToolBar, QSize, \ - pyqtSignal, QToolButton, QMenu, QCheckBox, \ +from PyQt4.Qt import QIcon, Qt, QWidget, QToolBar, QSize, QDialogButtonBox, \ + pyqtSignal, QToolButton, QMenu, QCheckBox, QDialog, QGridLayout, \ QObject, QVBoxLayout, QSizePolicy, QLabel, QHBoxLayout, QActionGroup @@ -17,7 +17,9 @@ from calibre.gui2.search_box import SearchBox2, SavedSearchBox from calibre.gui2.throbber import ThrobbingButton from calibre.gui2 import gprefs from calibre.gui2.widgets import ComboBoxWithHelp +from calibre.gui2.complete import MultiCompleteLineEdit from calibre import human_readable +from calibre.utils.config import prefs class LocationManager(QObject): # {{{ @@ -149,6 +151,8 @@ class SearchBar(QWidget): # {{{ def __init__(self, parent): QWidget.__init__(self, parent) + self.parent = parent + self._layout = l = QHBoxLayout() self.setLayout(self._layout) self._layout.setContentsMargins(0,5,0,0) @@ -156,9 +160,10 @@ class SearchBar(QWidget): # {{{ x = ComboBoxWithHelp(self) x.setMaximumSize(QSize(150, 16777215)) x.setObjectName("search_restriction") - x.setToolTip(_("Books display will be restricted to those matching the selected saved search")) - l.addWidget(x) + x.setToolTip(_('Books display will be restricted to those matching the ' + 'selected saved search')) parent.search_restriction = x + l.addWidget(x) x = QLabel(self) x.setObjectName("search_count") @@ -175,7 +180,8 @@ class SearchBar(QWidget): # {{{ x = parent.search = SearchBox2(self) x.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) x.setObjectName("search") - x.setToolTip(_("

Search the list of books by title, author, publisher, tags, comments, etc.

Words separated by spaces are ANDed")) + x.setToolTip(_("

Search the list of books by title, author, publisher, " + "tags, comments, etc.

Words separated by spaces are ANDed")) l.addWidget(x) self.search_button = QToolButton() @@ -194,23 +200,13 @@ class SearchBar(QWidget): # {{{ l.addWidget(x) x.setToolTip(_("Reset Quick Search")) - x = parent.search_highlight_only = QCheckBox() - x.setText(_('&Highlight')) - x.setToolTip('

'+_('When searching, highlight matched books, instead ' - 'of restricting the book list to the matches.

You can use the ' - 'N or F3 keys to go to the next match.')) + x = parent.search_options_button = QToolButton(self) + x.setIcon(QIcon(I('config.png'))) + x.setObjectName("search_option_button") l.addWidget(x) + x.setToolTip(_("Change search highlighting and field limit options")) x.setVisible(False) - x = parent.search_limit_to = QCheckBox() - x.setText(_('&Limit')) - x.setToolTip('

'+_('When searching for text without using lookup ' - 'prefixes, as for example someword instead of title:someword, ' - 'limit the columns searched to those named in the option ' - 'Preferences -> Look and Feel -> Limit non-prefixed searches to columns.')) - x.setVisible(False) - l.addWidget(x) - x = parent.saved_search = SavedSearchBox(self) x.setMaximumSize(QSize(150, 16777215)) x.setMinimumContentsLength(15) @@ -236,6 +232,80 @@ class SearchBar(QWidget): # {{{ x.setToolTip(_("Delete current saved search")) +class SearchOptions(QDialog): + + def __init__(self, parent, limit_to_fields, limit_field_list, + limit_cbox, highlight_cbox): + QDialog.__init__(self, parent=parent) +# self.search_limit_possible_fields = [] +# self.search_limit_cbox_value = False +# self.search_highlight_cbox_value = False +# self.search_limit_list = '' +# self = self.search_popup = QDialog(self.parent) + self.setWindowTitle(_('Search options')) + l = QGridLayout() + self.setLayout(l) + + x = QLabel(_(' '), parent=self) + x.setBuddy(parent.search_restriction) + l.addWidget(x, 1, 0, 1, 1) + + x = self.search_highlight_only = QCheckBox(self) + x.setToolTip('

'+_('When searching, highlight matched books, instead ' + 'of restricting the book list to the matches.

You can use the ' + 'N or F3 keys to go to the next match.')) + x.setChecked(highlight_cbox) + l.addWidget(x, 2, 1, 1, 1) + x = QLabel(_('Check this box if you want to see all books with search ' + 'results &highlighted'), parent=self) + x.setBuddy(self.search_highlight_only) + l.addWidget(x, 2, 0, 1, 1) + + x = self.search_limit_checkbox = QCheckBox(self) + x.setToolTip('

'+_('When searching for text without using lookup ' + 'prefixes, as for example someword instead of title:someword, ' + 'limit the columns searched to those named in the option ' + 'Preferences -> Look and Feel -> Limit non-prefixed searches to columns.')) + x.setChecked(limit_cbox) + l.addWidget(x, 3, 1, 1, 1) + x = QLabel(_('Check this box if you want non-prefixed searches to be ' + '&limited to certain fields/lookup names'), parent=self) + x.setBuddy(self.search_limit_checkbox) + l.addWidget(x, 3, 0, 1, 1) + + x = self.search_box_limit_to = MultiCompleteLineEdit(parent=self) + x.setToolTip(_('Choose columns to be searched when not using prefixes, ' + 'as for example when searching for someword instead of ' + 'title:someword. Enter a list of search/lookup names ' + 'separated by commas. You must check the Limit box ' + 'above for this option to take effect.')) + x.setMinimumWidth(200) + x.set_separator(',') + x.update_items_cache(limit_field_list) + x.setText(limit_to_fields) + l.addWidget(x, 4, 1, 1, 1) + x = QLabel(_('Enter the list of fields that non-prefixed searches ' + 'are &limited to'), parent=self) + x.setBuddy(self.search_box_limit_to) + l.addWidget(x, 4, 0, 1, 1) + + buttons = QDialogButtonBox() + buttons.addButton(QDialogButtonBox.Ok) + buttons.addButton(QDialogButtonBox.Cancel) + l.addWidget(buttons, 5, 0, 1, 1) + buttons.accepted.connect(self.search_options_accepted) + buttons.rejected.connect(self.search_options_rejected) + + def search_options_accepted(self): + QDialog.accept(self) + + def search_options_rejected(self): + QDialog.reject(self) + + def values(self): + return (unicode(self.search_box_limit_to.text()), + bool(self.search_limit_checkbox.checkState()), + bool(self.search_highlight_only.checkState())) # }}} diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py index 2f8a747c39..48668d3376 100644 --- a/src/calibre/gui2/library/models.py +++ b/src/calibre/gui2/library/models.py @@ -238,8 +238,6 @@ class BooksModel(QAbstractTableModel): # {{{ def set_highlight_only(self, toWhat): self.highlight_only = toWhat - if self.last_search: - self.research() def get_current_highlighted_id(self): if len(self.ids_to_highlight) == 0 or self.current_highlighted_idx is None: diff --git a/src/calibre/gui2/preferences/look_feel.py b/src/calibre/gui2/preferences/look_feel.py index 86d450567c..37ed90cc61 100644 --- a/src/calibre/gui2/preferences/look_feel.py +++ b/src/calibre/gui2/preferences/look_feel.py @@ -62,11 +62,6 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): r('tags_browser_partition_method', gprefs, choices=choices) r('tags_browser_collapse_at', gprefs) - r('search_box_limit_to', prefs) - self.opt_search_box_limit_to.set_separator(',') - self.opt_search_box_limit_to.update_items_cache( - self.gui.library_view.model().db.field_metadata.get_search_terms()) - self.current_font = None self.change_font_button.clicked.connect(self.change_font) @@ -124,7 +119,6 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): gui.search.search_as_you_type(config['search_as_you_type']) self.update_font_display() gui.tags_view.reread_collapse_parameters() - gui.search_limit_to.setEnabled(bool(prefs['search_box_limit_to'])) if __name__ == '__main__': app = QApplication([]) diff --git a/src/calibre/gui2/preferences/look_feel.ui b/src/calibre/gui2/preferences/look_feel.ui index 4bd514101b..2c9c2cc089 100644 --- a/src/calibre/gui2/preferences/look_feel.ui +++ b/src/calibre/gui2/preferences/look_feel.ui @@ -200,26 +200,6 @@ up into sub-categories. If the partition method is set to disable, this value is - - - - Limit non-&prefixed searches to columns: - - - opt_search_box_limit_to - - - - - - - Choose columns to be searched when not using prefixes, as for -example when searching for someword instead of title:someword. -Enter a list of search/lookup names separated by commas. You -must check the 'Limit' box on the GUI for this option to take effect. - - - diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py index 1c94038125..827b549afb 100644 --- a/src/calibre/gui2/search_box.py +++ b/src/calibre/gui2/search_box.py @@ -376,15 +376,10 @@ class SearchBoxMixin(object): # {{{ unicode(self.search.toolTip()))) self.advanced_search_button.setStatusTip(self.advanced_search_button.toolTip()) self.clear_button.setStatusTip(self.clear_button.toolTip()) - self.search_highlight_only.stateChanged.connect(self.highlight_only_changed) - self.search_highlight_only.setChecked( - dynamic.get('search_highlight_only', False)) - self.search_limit_to.stateChanged.connect(self.search_limit_to_changed) - self.search_limit_to.setVisible(True) - chk = dynamic.get('use_search_box_limit', False) - self.search_limit_to.setChecked(chk) - prefs['use_search_box_limit'] = chk - self.search_limit_to.setEnabled(bool(prefs['search_box_limit_to'])) + + self.search_options_button.clicked.connect(self.search_options_button_clicked) + prefs['use_search_box_limit'] = dynamic.get('use_search_box_limit', False) + highlight_cbox=dynamic.get('search_highlight_only', False) def focus_search_box(self, *args): self.search.setFocus(Qt.OtherFocusReason) @@ -408,6 +403,40 @@ class SearchBoxMixin(object): # {{{ self.search.do_search() self.focus_to_library() + def search_options_button_clicked(self): + fm = self.library_view.model().db.field_metadata + ll = fm.get_search_terms() + ll = [l for l in ll if not l.startswith('@') and l not in fm.search_items] + print ll + + from calibre.gui2.layout import SearchOptions + options_box = SearchOptions(self, + limit_to_fields=prefs['search_box_limit_to'], + limit_field_list=ll, + limit_cbox=dynamic.get('use_search_box_limit', False), + highlight_cbox=dynamic.get('search_highlight_only', False)) + r = options_box.exec_() + if r: + limit_list, limit_cb, highlight_cb = options_box.values() + print limit_list, limit_cb, highlight_cb + prefs['search_box_limit_to'] = limit_list + dynamic.set('use_search_box_limit', limit_cb) + prefs['use_search_box_limit'] = limit_cb + dynamic.set('search_highlight_only', highlight_cb) + self.current_view().model().set_highlight_only(highlight_cb) + self.search.do_search() + +# self.search_highlight_only.stateChanged.connect(self.highlight_only_changed) +# self.search_highlight_only.setChecked( +# dynamic.get('search_highlight_only', False)) +# self.search_limit_checkbox.stateChanged.connect(self.search_limit_checkbox_changed) +# self.search_limit_checkbox.setVisible(True) +# chk = dynamic.get('use_search_box_limit', False) +# self.search_limit_checkbox.setChecked(chk) +# prefs['use_search_box_limit'] = chk +# self.search_limit_checkbox.setEnabled(bool(prefs['search_box_limit_to'])) + + def focus_to_library(self): self.current_view().setFocus(Qt.OtherFocusReason) @@ -416,7 +445,8 @@ class SearchBoxMixin(object): # {{{ self.current_view().model().set_highlight_only(toWhat) self.focus_to_library() - def search_limit_to_changed(self, toWhat): + def search_limit_checkbox_changed(self, toWhat): + toWhat = bool(toWhat) dynamic.set('use_search_box_limit', toWhat) prefs['use_search_box_limit'] = toWhat self.search.do_search() diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 70d0d387a5..907dd577b8 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -482,10 +482,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ for action in self.iactions.values(): action.location_selected(location) if location == 'library': - self.search_limit_to.setVisible(True) self.search_restriction.setEnabled(True) else: - self.search_limit_to.setVisible(False) self.search_restriction.setEnabled(False) # Reset the view in case something changed while it was invisible self.current_view().reset() diff --git a/src/calibre/utils/config.py b/src/calibre/utils/config.py index 976864ebd3..0ccc949260 100644 --- a/src/calibre/utils/config.py +++ b/src/calibre/utils/config.py @@ -729,7 +729,7 @@ def _prefs(): c.add_opt('manage_device_metadata', default='manual', help=_('How and when calibre updates metadata on the device.')) - c.add_opt('search_box_limit_to', default='', + c.add_opt('search_box_limit_to', default='title, authors, series', help=_('Comma-separated list of fields to search when no prefix')) c.add_opt('use_search_box_limit', default=False, help=_('Set to true to apply the search box limit'))