mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Another attempt at enhancement #1415714. The user has the choice of putting quickview in its own window (original implementation) or as a splitter panel containing library view and the quickview panes.
This commit is contained in:
parent
9e7d1a6ed4
commit
f26495354f
@ -25,6 +25,7 @@ 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 = None
|
||||
if self.gui.current_view() is not self.gui.library_view:
|
||||
@ -34,8 +35,7 @@ class ShowQuickviewAction(InterfaceAction):
|
||||
return
|
||||
index = self.gui.library_view.currentIndex()
|
||||
if index.isValid():
|
||||
self.current_instance = \
|
||||
Quickview(self.gui, self.gui.library_view, index)
|
||||
self.current_instance = Quickview(self.gui, index)
|
||||
self.current_instance.show()
|
||||
|
||||
def change_quickview_column(self, idx):
|
||||
|
@ -5,8 +5,8 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
|
||||
from PyQt5.Qt import (Qt, QDialog, QAbstractItemView, QTableWidgetItem,
|
||||
QListWidgetItem, QByteArray, QCoreApplication,
|
||||
QApplication, pyqtSignal, QDialogButtonBox)
|
||||
QListWidgetItem, QCoreApplication, QEvent, QObject,
|
||||
QApplication, pyqtSignal, QDialogButtonBox, QByteArray)
|
||||
|
||||
from calibre.customize.ui import find_plugin
|
||||
from calibre.gui2 import gprefs
|
||||
@ -42,33 +42,52 @@ class TableItem(QTableWidgetItem):
|
||||
return self.sort_idx < other.sort_idx
|
||||
return 0
|
||||
|
||||
class KeyPressFilter(QObject):
|
||||
|
||||
return_pressed_signal = pyqtSignal()
|
||||
|
||||
def eventFilter(self, obj, event):
|
||||
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);
|
||||
|
||||
class Quickview(QDialog, Ui_Quickview):
|
||||
|
||||
change_quickview_column = pyqtSignal(object)
|
||||
|
||||
def __init__(self, gui, view, row):
|
||||
QDialog.__init__(self, gui, flags=Qt.Window)
|
||||
def __init__(self, gui, row):
|
||||
self.is_pane = gprefs.get('quickview_is_pane', False)
|
||||
|
||||
if not self.is_pane:
|
||||
QDialog.__init__(self, gui, flags=Qt.Window)
|
||||
else:
|
||||
QDialog.__init__(self, gui)
|
||||
Ui_Quickview.__init__(self)
|
||||
self.setupUi(self)
|
||||
self.isClosed = False
|
||||
|
||||
|
||||
self.books_table_column_widths = None
|
||||
try:
|
||||
self.books_table_column_widths = \
|
||||
gprefs.get('quickview_dialog_books_table_widths', None)
|
||||
geom = gprefs.get('quickview_dialog_geometry', bytearray(''))
|
||||
self.restoreGeometry(QByteArray(geom))
|
||||
if not self.is_pane:
|
||||
geom = gprefs.get('quickview_dialog_geometry', bytearray(''))
|
||||
self.restoreGeometry(QByteArray(geom))
|
||||
except:
|
||||
pass
|
||||
|
||||
# Remove the help button from the window title bar
|
||||
icon = self.windowIcon()
|
||||
self.setWindowFlags(self.windowFlags()&(~Qt.WindowContextHelpButtonHint))
|
||||
self.setWindowFlags(self.windowFlags()|Qt.WindowStaysOnTopHint)
|
||||
self.setWindowIcon(icon)
|
||||
if not self.is_pane:
|
||||
# Remove the help button from the window title bar
|
||||
icon = self.windowIcon()
|
||||
self.setWindowFlags(self.windowFlags()&(~Qt.WindowContextHelpButtonHint))
|
||||
self.setWindowFlags(self.windowFlags()|Qt.WindowStaysOnTopHint)
|
||||
self.setWindowIcon(icon)
|
||||
|
||||
self.db = view.model().db
|
||||
self.view = view
|
||||
self.view = gui.library_view
|
||||
self.db = self.view.model().db
|
||||
self.gui = gui
|
||||
self.is_closed = False
|
||||
self.current_book_id = None
|
||||
@ -89,6 +108,9 @@ class Quickview(QDialog, Ui_Quickview):
|
||||
self.items.currentTextChanged.connect(self.item_selected)
|
||||
|
||||
# Set up the books table columns
|
||||
return_filter = KeyPressFilter(self.books_table)
|
||||
return_filter.return_pressed_signal.connect(self.return_pressed)
|
||||
self.books_table.installEventFilter(return_filter)
|
||||
self.books_table.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
self.books_table.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
self.books_table.setColumnCount(3)
|
||||
@ -118,10 +140,28 @@ class Quickview(QDialog, Ui_Quickview):
|
||||
self.change_quickview_column.connect(self.slave)
|
||||
QCoreApplication.instance().aboutToQuit.connect(self.save_state)
|
||||
self.search_button.clicked.connect(self.do_search)
|
||||
view.model().new_bookdisplay_data.connect(self.book_was_changed)
|
||||
self.view.model().new_bookdisplay_data.connect(self.book_was_changed)
|
||||
|
||||
close_button = self.buttonBox.button(QDialogButtonBox.Close)
|
||||
close_button.setAutoDefault(False)
|
||||
close_button.setDefault(False)
|
||||
if self.is_pane:
|
||||
close_button.setText(_('&Close'))
|
||||
|
||||
self.books_table.horizontalHeader().sectionResized.connect(self.section_resized)
|
||||
if self.is_pane:
|
||||
self.gui.quickview_splitter.add_quickview_dialog(self)
|
||||
self.set_focus()
|
||||
|
||||
self.show_as_pane.setChecked(self.is_pane)
|
||||
self.show_as_pane.stateChanged.connect(self.show_as_pane_changed)
|
||||
|
||||
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()
|
||||
|
||||
# search button
|
||||
def do_search(self):
|
||||
@ -261,6 +301,11 @@ class Quickview(QDialog, Ui_Quickview):
|
||||
# correct until the first paint.
|
||||
def resizeEvent(self, *args):
|
||||
QDialog.resizeEvent(self, *args)
|
||||
|
||||
# Do this if we are resizing for the first time to reset state.
|
||||
if self.is_pane and self.height() == 0:
|
||||
self.gui.quickview_splitter.set_sizes()
|
||||
|
||||
if self.books_table_column_widths is not None:
|
||||
for c,w in enumerate(self.books_table_column_widths):
|
||||
self.books_table.setColumnWidth(c, w)
|
||||
@ -274,9 +319,15 @@ class Quickview(QDialog, Ui_Quickview):
|
||||
self.books_table.setColumnWidth(c, w)
|
||||
self.save_state()
|
||||
|
||||
def return_pressed(self):
|
||||
self.select_book(self.books_table.currentRow())
|
||||
|
||||
def book_doubleclicked(self, row, column):
|
||||
if self.no_valid_items:
|
||||
return
|
||||
self.select_book(row)
|
||||
|
||||
def select_book(self, row):
|
||||
book_id = int(self.books_table.item(row, self.title_column).data(Qt.UserRole))
|
||||
self.view.select_rows([book_id])
|
||||
modifiers = int(QApplication.keyboardModifiers())
|
||||
@ -285,6 +336,9 @@ class Quickview(QDialog, Ui_Quickview):
|
||||
if em is not None:
|
||||
em.actual_plugin_.edit_metadata(None)
|
||||
|
||||
def set_focus(self):
|
||||
self.books_table.setFocus(Qt.ActiveWindowFocusReason)
|
||||
|
||||
# called when a book is clicked on the library view
|
||||
def slave(self, current):
|
||||
if self.is_closed:
|
||||
@ -292,6 +346,9 @@ class Quickview(QDialog, Ui_Quickview):
|
||||
self.refresh(current)
|
||||
self.view.activateWindow()
|
||||
|
||||
def section_resized(self, logicalIndex, oldSize, newSize):
|
||||
self.save_state()
|
||||
|
||||
def save_state(self):
|
||||
if self.is_closed:
|
||||
return
|
||||
@ -299,7 +356,8 @@ class Quickview(QDialog, Ui_Quickview):
|
||||
for c in range(0, self.books_table.columnCount()):
|
||||
self.books_table_column_widths.append(self.books_table.columnWidth(c))
|
||||
gprefs['quickview_dialog_books_table_widths'] = self.books_table_column_widths
|
||||
gprefs['quickview_dialog_geometry'] = bytearray(self.saveGeometry())
|
||||
if not self.is_pane:
|
||||
gprefs['quickview_dialog_geometry'] = bytearray(self.saveGeometry())
|
||||
|
||||
def _close(self):
|
||||
self.save_state()
|
||||
@ -307,12 +365,10 @@ class Quickview(QDialog, Ui_Quickview):
|
||||
self.db = self.view = self.gui = None
|
||||
self.is_closed = True
|
||||
|
||||
# called by the window system
|
||||
def closeEvent(self, *args):
|
||||
self._close()
|
||||
QDialog.closeEvent(self, *args)
|
||||
|
||||
# called by the close button
|
||||
def reject(self):
|
||||
if self.is_pane:
|
||||
self.gui.quickview_splitter.hide_quickview_widget()
|
||||
self.gui.library_view.setFocus(Qt.ActiveWindowFocusReason)
|
||||
self._close()
|
||||
QDialog.reject(self)
|
||||
|
@ -11,7 +11,7 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
@ -68,8 +68,33 @@
|
||||
<string>&Lock Quickview contents</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Select to prevent Quickview from changing content when the
|
||||
selection on the library view is changed</string>
|
||||
<string><p>Select to prevent Quickview from changing content when the
|
||||
selection on the library view is changed</p></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="show_as_pane">
|
||||
<property name="text">
|
||||
<string>Sho&w as pane</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><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></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -8,7 +8,8 @@ __docformat__ = 'restructuredtext en'
|
||||
import functools
|
||||
|
||||
from PyQt5.Qt import (Qt, QApplication, QStackedWidget, QMenu, QTimer,
|
||||
QSize, QSizePolicy, QStatusBar, QLabel, QFont, QAction, QTabBar)
|
||||
QSize, QSizePolicy, QStatusBar, QLabel, QFont, QAction, QTabBar,
|
||||
QVBoxLayout, QWidget, QSplitter)
|
||||
|
||||
from calibre.utils.config import prefs
|
||||
from calibre.utils.icu import sort_key
|
||||
@ -99,6 +100,37 @@ class LibraryViewMixin(object): # {{{
|
||||
|
||||
# }}}
|
||||
|
||||
class QuickviewSplitter(QSplitter): # {{{
|
||||
|
||||
def __init__(self, parent=None, orientation=Qt.Vertical, qv_widget=None):
|
||||
QSplitter.__init__(self, parent=parent, orientation=orientation)
|
||||
self.splitterMoved.connect(self.splitter_moved)
|
||||
self.setChildrenCollapsible(False)
|
||||
self.qv_widget = qv_widget
|
||||
|
||||
def splitter_moved(self):
|
||||
gprefs['quickview_dialog_heights'] = self.sizes()
|
||||
|
||||
def resizeEvent(self, *args):
|
||||
QSplitter.resizeEvent(self, *args)
|
||||
if self.sizes()[1] != 0:
|
||||
gprefs['quickview_dialog_heights'] = self.sizes()
|
||||
|
||||
def set_sizes(self):
|
||||
sizes = gprefs.get('quickview_dialog_heights', [])
|
||||
if len(sizes) == 2:
|
||||
self.setSizes(sizes)
|
||||
|
||||
def add_quickview_dialog(self, qv_dialog):
|
||||
self.qv_widget.layout().addWidget(qv_dialog)
|
||||
|
||||
def show_quickview_widget(self):
|
||||
self.qv_widget.show()
|
||||
|
||||
def hide_quickview_widget(self):
|
||||
self.qv_widget.hide()
|
||||
# }}}
|
||||
|
||||
class LibraryWidget(Splitter): # {{{
|
||||
|
||||
def __init__(self, parent):
|
||||
@ -113,6 +145,10 @@ class LibraryWidget(Splitter): # {{{
|
||||
connect_button=not config['separate_cover_flow'],
|
||||
side_index=idx, initial_side_size=size, initial_show=False,
|
||||
shortcut='Shift+Alt+B')
|
||||
|
||||
quickview_widget = QWidget()
|
||||
parent.quickview_splitter = QuickviewSplitter(
|
||||
parent=self, orientation=Qt.Vertical, qv_widget=quickview_widget)
|
||||
parent.library_view = BooksView(parent)
|
||||
parent.library_view.setObjectName('library_view')
|
||||
stack = QStackedWidget(self)
|
||||
@ -121,7 +157,13 @@ class LibraryWidget(Splitter): # {{{
|
||||
parent.grid_view = GridView(parent)
|
||||
parent.grid_view.setObjectName('grid_view')
|
||||
av.add_view('grid', parent.grid_view)
|
||||
self.addWidget(stack)
|
||||
parent.quickview_splitter.addWidget(stack)
|
||||
|
||||
quickview_widget.setLayout(QVBoxLayout())
|
||||
parent.quickview_splitter.addWidget(quickview_widget)
|
||||
parent.quickview_splitter.hide_quickview_widget()
|
||||
|
||||
self.addWidget(parent.quickview_splitter)
|
||||
# }}}
|
||||
|
||||
class Stack(QStackedWidget): # {{{
|
||||
|
Loading…
x
Reference in New Issue
Block a user