mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Add keyboard shorcuts to find the next highlighted match
This commit is contained in:
parent
215ad8c245
commit
b2ad17d7ff
@ -705,13 +705,17 @@ class ActionTweakEpub(InterfaceActionBase):
|
||||
name = 'Tweak ePub'
|
||||
actual_plugin = 'calibre.gui2.actions.tweak_epub:TweakEpubAction'
|
||||
|
||||
class ActionNextMatch(InterfaceActionBase):
|
||||
name = 'Next Match'
|
||||
actual_plugin = 'calibre.gui2.actions.next_match:NextMatchAction'
|
||||
|
||||
plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog,
|
||||
ActionConvert, ActionDelete, ActionEditMetadata, ActionView,
|
||||
ActionFetchNews, ActionSaveToDisk, ActionShowBookDetails,
|
||||
ActionRestart, ActionOpenFolder, ActionConnectShare,
|
||||
ActionSendToDevice, ActionHelp, ActionPreferences, ActionSimilarBooks,
|
||||
ActionAddToLibrary, ActionEditCollections, ActionChooseLibrary,
|
||||
ActionCopyToLibrary, ActionTweakEpub]
|
||||
ActionCopyToLibrary, ActionTweakEpub, ActionNextMatch]
|
||||
|
||||
# }}}
|
||||
|
||||
|
@ -111,7 +111,10 @@ class InterfaceAction(QObject):
|
||||
action.setWhatsThis(text)
|
||||
action.setAutoRepeat(False)
|
||||
if shortcut:
|
||||
action.setShortcut(shortcut)
|
||||
if isinstance(shortcut, list):
|
||||
action.setShortcuts(shortcut)
|
||||
else:
|
||||
action.setShortcut(shortcut)
|
||||
setattr(self, attr, action)
|
||||
return action
|
||||
|
||||
@ -170,6 +173,14 @@ class InterfaceAction(QObject):
|
||||
'''
|
||||
pass
|
||||
|
||||
def gui_layout_complete(self):
|
||||
'''
|
||||
Called once per action when the layout of the main GUI is
|
||||
completed. If your action needs to make changes to the layout, they
|
||||
should be done here, rather than in :meth:`initialization_complete`.
|
||||
'''
|
||||
pass
|
||||
|
||||
def initialization_complete(self):
|
||||
'''
|
||||
Called once per action when the initialization of the main GUI is
|
||||
|
56
src/calibre/gui2/actions/next_match.py
Normal file
56
src/calibre/gui2/actions/next_match.py
Normal file
@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
from calibre.gui2.actions import InterfaceAction
|
||||
|
||||
class NextMatchAction(InterfaceAction):
|
||||
name = 'Move to next highlighted book'
|
||||
action_spec = (_('Move to next match'), 'arrow-down.png',
|
||||
_('Move to next highlighted match'), [_('N'), _('F3')])
|
||||
dont_add_to = frozenset(['toolbar-device', 'context-menu-device'])
|
||||
action_type = 'current'
|
||||
|
||||
def genesis(self):
|
||||
'''
|
||||
Setup this plugin. Only called once during initialization. self.gui is
|
||||
available. The action secified by :attr:`action_spec` is available as
|
||||
``self.qaction``.
|
||||
'''
|
||||
self.can_move = None
|
||||
self.qaction.triggered.connect(self.move_forward)
|
||||
self.create_action(spec=(_('Move to previous item'), 'arrow-up.png',
|
||||
_('Move to previous highlighted item'), [_('Shift+N'),
|
||||
_('Shift+F3')]), attr='p_action')
|
||||
self.gui.addAction(self.p_action)
|
||||
self.p_action.triggered.connect(self.move_backward)
|
||||
|
||||
def gui_layout_complete(self):
|
||||
self.gui.search_highlight_only.setVisible(True)
|
||||
|
||||
def location_selected(self, loc):
|
||||
self.can_move = loc == 'library'
|
||||
try:
|
||||
self.gui.search_highlight_only.setVisible(self.can_move)
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
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)
|
||||
|
||||
if self.can_move:
|
||||
self.gui.current_view().move_highlighted_row(forward=True)
|
||||
|
||||
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)
|
||||
|
||||
if self.can_move:
|
||||
self.gui.current_view().move_highlighted_row(forward=False)
|
@ -196,9 +196,11 @@ class SearchBar(QWidget): # {{{
|
||||
|
||||
x = parent.search_highlight_only = QCheckBox()
|
||||
x.setText(_('&Highlight'))
|
||||
x.setToolTip(_('Highlight matched books in the book list, instead '
|
||||
'of restricting the book list to the matches.'))
|
||||
x.setToolTip('<p>'+_('When searching, highlight matched books, instead '
|
||||
'of restricting the book list to the matches.<p> You can use the '
|
||||
'N or F3 keys to go to the next match.'))
|
||||
l.addWidget(x)
|
||||
x.setVisible(False)
|
||||
|
||||
x = parent.saved_search = SavedSearchBox(self)
|
||||
x.setMaximumSize(QSize(150, 16777215))
|
||||
|
@ -93,8 +93,9 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
self.bool_no_icon = QIcon(I('list_remove.png'))
|
||||
self.bool_blank_icon = QIcon(I('blank.png'))
|
||||
self.device_connected = False
|
||||
self.rows_matching = set()
|
||||
self.lowest_row_matching = None
|
||||
self.rows_to_highlight = []
|
||||
self.rows_to_highlight_set = set()
|
||||
self.current_highlighted_row = None
|
||||
self.highlight_only = False
|
||||
self.read_config()
|
||||
|
||||
@ -130,6 +131,9 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
self.book_on_device = func
|
||||
|
||||
def set_database(self, db):
|
||||
self.rows_to_highlight = []
|
||||
self.rows_to_highlight_set = set()
|
||||
self.current_highlighted_row = None
|
||||
self.db = db
|
||||
self.custom_columns = self.db.field_metadata.custom_field_metadata()
|
||||
self.column_map = list(self.orig_headers.keys()) + \
|
||||
@ -237,21 +241,43 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
if self.last_search:
|
||||
self.research()
|
||||
|
||||
def get_current_highlighted_row(self):
|
||||
if len(self.rows_to_highlight) == 0 or self.current_highlighted_row is None:
|
||||
return None
|
||||
try:
|
||||
return self.rows_to_highlight[self.current_highlighted_row]
|
||||
except:
|
||||
return None
|
||||
|
||||
def get_next_highlighted_row(self, forward):
|
||||
if len(self.rows_to_highlight) == 0 or self.current_highlighted_row is None:
|
||||
return None
|
||||
self.current_highlighted_row += 1 if forward else -1
|
||||
if self.current_highlighted_row < 0:
|
||||
self.current_highlighted_row = len(self.rows_to_highlight) - 1;
|
||||
elif self.current_highlighted_row >= len(self.rows_to_highlight):
|
||||
self.current_highlighted_row = 0
|
||||
return self.get_current_highlighted_row()
|
||||
|
||||
def search(self, text, reset=True):
|
||||
try:
|
||||
if self.highlight_only:
|
||||
self.db.search('')
|
||||
if not text:
|
||||
self.rows_matching = set()
|
||||
self.lowest_row_matching = None
|
||||
self.rows_to_highlight = []
|
||||
self.rows_to_highlight_set = set()
|
||||
self.current_highlighted_row = None
|
||||
else:
|
||||
self.rows_matching = self.db.search(text, return_matches=True)
|
||||
if self.rows_matching:
|
||||
self.lowest_row_matching = self.db.row(self.rows_matching[0])
|
||||
self.rows_matching = set(self.rows_matching)
|
||||
self.rows_to_highlight = self.db.search(text, return_matches=True)
|
||||
self.rows_to_highlight_set = set(self.rows_to_highlight)
|
||||
if self.rows_to_highlight:
|
||||
self.current_highlighted_row = 0
|
||||
else:
|
||||
self.current_highlighted_row = None
|
||||
else:
|
||||
self.rows_matching = set()
|
||||
self.lowest_row_matching = None
|
||||
self.rows_to_highlight = []
|
||||
self.rows_to_highlight_set = set()
|
||||
self.current_highlighted_row = None
|
||||
self.db.search(text)
|
||||
except ParseException as e:
|
||||
self.searched.emit(e.msg)
|
||||
@ -674,7 +700,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
if role in (Qt.DisplayRole, Qt.EditRole):
|
||||
return self.column_to_dc_map[col](index.row())
|
||||
elif role == Qt.BackgroundColorRole:
|
||||
if self.id(index) in self.rows_matching:
|
||||
if self.id(index) in self.rows_to_highlight_set:
|
||||
return QColor('lightgreen')
|
||||
elif role == Qt.DecorationRole:
|
||||
if self.column_to_dc_decorator_map[col] is not None:
|
||||
|
@ -680,10 +680,16 @@ class BooksView(QTableView): # {{{
|
||||
def set_editable(self, editable, supports_backloading):
|
||||
self._model.set_editable(editable)
|
||||
|
||||
def move_highlighted_row(self, forward):
|
||||
id_to_select = self._model.get_next_highlighted_row(forward)
|
||||
if id_to_select is not None:
|
||||
self.select_rows([id_to_select], using_ids=True)
|
||||
|
||||
def search_proxy(self, txt):
|
||||
self._model.search(txt)
|
||||
if self._model.lowest_row_matching is not None:
|
||||
self.select_rows([self._model.lowest_row_matching], using_ids=False)
|
||||
id_to_select = self._model.get_current_highlighted_row()
|
||||
if id_to_select is not None:
|
||||
self.select_rows([id_to_select], using_ids=True)
|
||||
self.setFocus(Qt.OtherFocusReason)
|
||||
|
||||
def connect_to_search_box(self, sb, search_done):
|
||||
|
@ -256,6 +256,14 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
||||
self.height())
|
||||
self.resize(self.width(), self._calculated_available_height)
|
||||
|
||||
for ac in self.iactions.values():
|
||||
try:
|
||||
ac.gui_layout_complete()
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
if ac.plugin_path is None:
|
||||
raise
|
||||
|
||||
if config['autolaunch_server']:
|
||||
self.start_content_server()
|
||||
|
@ -478,6 +478,10 @@ Calibre has several keyboard shortcuts to save you time and mouse movement. Thes
|
||||
- Focus the search bar
|
||||
* - :kbd:`Shift+Ctrl+F`
|
||||
- Open the advanced search dialog
|
||||
* - :kbd:`N or F3`
|
||||
- Find the next book that matches the current search (only works if the highlight checkbox next to the search bar is checked)
|
||||
* - :kbd:`Shift+N or Shift+F3`
|
||||
- Find the next book that matches the current search (only works if the highlight checkbox next to the search bar is checked)
|
||||
* - :kbd:`Ctrl+D`
|
||||
- Download metadata and shortcuts
|
||||
* - :kbd:`Ctrl+R`
|
||||
|
Loading…
x
Reference in New Issue
Block a user