diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index d0f986209c..176d5e3901 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -705,13 +705,17 @@ class ActionTweakEpub(InterfaceActionBase): name = 'Tweak ePub' actual_plugin = 'calibre.gui2.actions.tweak_epub:TweakEpubAction' +class ActionMoveSelection(InterfaceActionBase): + name = 'Edit Metadata' + actual_plugin = 'calibre.gui2.actions.move_selection:MoveSelectionAction' + 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, ActionMoveSelection] # }}} diff --git a/src/calibre/gui2/actions/move_selection.py b/src/calibre/gui2/actions/move_selection.py new file mode 100644 index 0000000000..e49803fcd6 --- /dev/null +++ b/src/calibre/gui2/actions/move_selection.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from calibre.gui2.actions import InterfaceAction + +class MoveSelectionAction(InterfaceAction): + name = 'Move selection in library' + action_spec = (_('Move to next item'), 'arrow-down.png', + _('Move to next highlighted item'), 'n') + 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'), 'F3'), attr='p_action') + self.gui.addAction(self.p_action) + self.p_action.triggered.connect(self.move_backward) + + def location_selected(self, loc): + self.can_move = loc == 'library' + + def move_forward(self): + if self.can_move is None: + self.can_move = self.gui.current_view() is self.gui.library_view + 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 + if self.can_move: + self.gui.current_view().move_highlighted_row(forward=False) \ No newline at end of file diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py index 38a4b28744..670a2d823e 100644 --- a/src/calibre/gui2/library/models.py +++ b/src/calibre/gui2/library/models.py @@ -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) @@ -673,7 +699,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: diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py index ea2e03fdad..e5cc259244 100644 --- a/src/calibre/gui2/library/views.py +++ b/src/calibre/gui2/library/views.py @@ -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):