diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index 8fc3cc55de..c2cacee2ee 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -834,6 +834,16 @@ class ActionQuickview(InterfaceActionBase): actual_plugin = 'calibre.gui2.actions.show_quickview:ShowQuickviewAction' description = _('Show a list of related books quickly') +class ActionQuickviewFocusTo(InterfaceActionBase): + name = 'Focus To Quickview' + actual_plugin = 'calibre.gui2.actions.show_quickview:FocusToQuickviewAction' + description = _('Move the focus to the Quickview pane/window') + +class ActionQuickviewFocusFrom(InterfaceActionBase): + name = 'Focus From Quickview' + actual_plugin = 'calibre.gui2.actions.show_quickview:FocusFromQuickviewAction' + description = _('Move the focus to the library pane') + class ActionTemplateTester(InterfaceActionBase): name = 'Template Tester' actual_plugin = 'calibre.gui2.actions.show_template_tester:ShowTemplateTesterAction' @@ -974,7 +984,8 @@ plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, ActionAddToLibrary, ActionEditCollections, ActionMatchBooks, ActionChooseLibrary, ActionCopyToLibrary, ActionTweakEpub, ActionUnpackBook, ActionNextMatch, ActionStore, ActionPluginUpdater, ActionPickRandom, ActionEditToC, ActionSortBy, - ActionMarkBooks, ActionEmbed, ActionTemplateTester] + ActionMarkBooks, ActionEmbed, ActionTemplateTester, ActionQuickviewFocusTo, + ActionQuickviewFocusFrom] # }}} diff --git a/src/calibre/gui2/actions/show_quickview.py b/src/calibre/gui2/actions/show_quickview.py index e6d693bb22..d02485a570 100644 --- a/src/calibre/gui2/actions/show_quickview.py +++ b/src/calibre/gui2/actions/show_quickview.py @@ -1,5 +1,6 @@ #!/usr/bin/env python2 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from calibre.utils.fonts.sfnt.glyf import ARGS_ARE_XY_VALUES __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' @@ -10,10 +11,40 @@ from calibre.gui2.actions import InterfaceAction from calibre.gui2.dialogs.quickview import Quickview from calibre.gui2 import error_dialog +class FocusToQuickviewAction(InterfaceAction): + + name = 'Focus To Quickview' + action_spec = (_('Focus To Quickview'), 'search.png', None, ('Shift+Q')) + dont_add_to = frozenset(['context-menu-device']) + action_type = 'current' + + def genesis(self): + self.qaction.triggered.connect(self.focus_quickview) + + def focus_quickview(self, *args): + from calibre.customize.ui import find_plugin + qv = find_plugin('Show Quickview') + if qv: + qv.actual_plugin_.focus_quickview() + + +class FocusFromQuickviewAction(InterfaceAction): + + name = 'Focus From Quickview' + action_spec = (_('Focus From Quickview'), 'search.png', None, ('Ctrl+Q')) + dont_add_to = frozenset(['context-menu-device']) + action_type = 'current' + + def genesis(self): + self.qaction.triggered.connect(self.focus_quickview) + + def focus_quickview(self, *args): + self.gui.library_view.setFocus() + class ShowQuickviewAction(InterfaceAction): - name = 'Show quickview' - action_spec = (_('Show quickview'), 'search.png', None, _('Q')) + name = 'Show Quickview' + action_spec = (_('Show Quickview'), 'search.png', None, (_('Q'))) dont_add_to = frozenset(['context-menu-device']) action_type = 'current' @@ -25,9 +56,9 @@ class ShowQuickviewAction(InterfaceAction): def show_quickview(self, *args): if self.current_instance: if not self.current_instance.is_closed: - self.current_instance.set_focus() - return + self.current_instance.reject() self.current_instance = None + return if self.gui.current_view() is not self.gui.library_view: error_dialog(self.gui, _('No quickview available'), _('Quickview is not available for books ' @@ -36,8 +67,15 @@ class ShowQuickviewAction(InterfaceAction): index = self.gui.library_view.currentIndex() if index.isValid(): self.current_instance = Quickview(self.gui, index) + self.current_instance.reopen_quickview.connect(self.reopen_quickview) self.current_instance.show() + def reopen_quickview(self): + if self.current_instance and not self.current_instance.is_closed: + self.current_instance.reject() + self.current_instance = None + self.show_quickview() + def change_quickview_column(self, idx): self.show_quickview() if self.current_instance: @@ -48,3 +86,8 @@ class ShowQuickviewAction(InterfaceAction): def library_changed(self, db): if self.current_instance and not self.current_instance.is_closed: self.current_instance.reject() + + def focus_quickview(self): + if not (self.current_instance and not self.current_instance.is_closed): + self.show_quickview() + self.current_instance.set_focus() \ No newline at end of file diff --git a/src/calibre/gui2/dialogs/quickview.py b/src/calibre/gui2/dialogs/quickview.py index c795db7c88..3e8023a16d 100644 --- a/src/calibre/gui2/dialogs/quickview.py +++ b/src/calibre/gui2/dialogs/quickview.py @@ -42,7 +42,15 @@ class TableItem(QTableWidgetItem): return self.sort_idx < other.sort_idx return 0 -class KeyPressFilter(QObject): +IN_WIDGET_ITEMS = 0 +IN_WIDGET_BOOKS = 1 +IN_WIDGET_LOCK = 2 +IN_WIDGET_DOCK = 3 +IN_WIDGET_SEARCH = 4 +IN_WIDGET_CLOSE = 5 +IN_WIDGET_LAST = 5 + +class BooksKeyPressFilter(QObject): return_pressed_signal = pyqtSignal() @@ -50,12 +58,30 @@ class KeyPressFilter(QObject): if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Return: self.return_pressed_signal.emit() return True; - else: - return QObject.eventFilter(self, obj, event); + return False + +class WidgetTabFilter(QObject): + + def __init__(self, attachToClass, which_widget, tab_signal): + QObject.__init__(self, attachToClass) + self.tab_signal = tab_signal + self.which_widget = which_widget + + def eventFilter(self, obj, event): + if event.type() == QEvent.KeyPress: + if event.key() == Qt.Key_Tab: + self.tab_signal.emit(self.which_widget, True) + return True + if event.key() == Qt.Key_Backtab: + self.tab_signal.emit(self.which_widget, False) + return True + return False class Quickview(QDialog, Ui_Quickview): - change_quickview_column = pyqtSignal(object) + change_quickview_column = pyqtSignal(object) + reopen_quickview = pyqtSignal() + tab_pressed_signal = pyqtSignal(object, object) def __init__(self, gui, row): self.is_pane = gprefs.get('quickview_is_pane', False) @@ -107,10 +133,18 @@ class Quickview(QDialog, Ui_Quickview): self.items.setSelectionMode(QAbstractItemView.SingleSelection) self.items.currentTextChanged.connect(self.item_selected) + self.tab_pressed_signal.connect(self.tab_pressed) # Set up the books table columns - return_filter = KeyPressFilter(self.books_table) + return_filter = BooksKeyPressFilter(self.books_table) return_filter.return_pressed_signal.connect(self.return_pressed) self.books_table.installEventFilter(return_filter) + + self.close_button = self.buttonBox.button(QDialogButtonBox.Close) + self.tab_order_widgets = [self.items, self.books_table, self.lock_qv, + self.dock_button, self.search_button, self.close_button] + for idx,widget in enumerate(self.tab_order_widgets): + widget.installEventFilter(WidgetTabFilter(widget, idx, self.tab_pressed_signal)) + self.books_table.setSelectionBehavior(QAbstractItemView.SelectRows) self.books_table.setSelectionMode(QAbstractItemView.SingleSelection) self.books_table.setColumnCount(3) @@ -142,26 +176,39 @@ class Quickview(QDialog, Ui_Quickview): self.search_button.clicked.connect(self.do_search) self.view.model().new_bookdisplay_data.connect(self.book_was_changed) - close_button = self.buttonBox.button(QDialogButtonBox.Close) - close_button.setDefault(False) - if self.is_pane: - close_button.setText(_('&Close')) - - self.books_table.horizontalHeader().sectionResized.connect(self.section_resized) + self.close_button.setDefault(False) if self.is_pane: + self.dock_button.setText(_('Undock')) + self.lock_qv.setText(_('Lock Quickview contents')) + self.search_button.setText(_('Search')) self.gui.quickview_splitter.add_quickview_dialog(self) self.set_focus() + else: + self.lock_qv.setText(_('&Dock')) + self.close_button.setText(_('&Close')) - self.show_as_pane.setChecked(self.is_pane) - self.show_as_pane.stateChanged.connect(self.show_as_pane_changed) + self.books_table.horizontalHeader().sectionResized.connect(self.section_resized) + self.dock_button.clicked.connect(self.show_as_pane_changed) + + def tab_pressed(self, inWidget, isForward): + if isForward: + inWidget += 1 + if inWidget > IN_WIDGET_LAST: + inWidget = 0 + else: + inWidget -= 1 + if inWidget < 0: + inWidget = IN_WIDGET_LAST + self.tab_order_widgets[inWidget].setFocus(Qt.TabFocusReason) def show(self): QDialog.show(self) if self.is_pane: self.gui.quickview_splitter.show_quickview_widget() - def show_as_pane_changed(self, new_state): - gprefs['quickview_is_pane'] = self.show_as_pane.isChecked() + def show_as_pane_changed(self): + gprefs['quickview_is_pane'] = not gprefs.get('quickview_is_pane', False) + self.reopen_quickview.emit() # search button def do_search(self): diff --git a/src/calibre/gui2/dialogs/quickview.ui b/src/calibre/gui2/dialogs/quickview.ui index 627b840d00..d8403e6a5f 100644 --- a/src/calibre/gui2/dialogs/quickview.ui +++ b/src/calibre/gui2/dialogs/quickview.ui @@ -87,15 +87,18 @@ - + - Sho&w as pane + &Dock <p>If checked, the next time Quickview is opened it will be shown as a pane under the library view. If unchecked it will be shown as a separate window.</p> + + false +