This commit is contained in:
Kovid Goyal 2017-07-03 17:19:12 +05:30
commit 5d967e3ba6
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
11 changed files with 385 additions and 84 deletions

View File

@ -471,6 +471,7 @@ class DB(object):
('uuid', False), ('comments', True), ('id', False), ('pubdate', False), ('uuid', False), ('comments', True), ('id', False), ('pubdate', False),
('last_modified', False), ('size', False), ('languages', False), ('last_modified', False), ('size', False), ('languages', False),
] ]
defs['qv_display_fields'] = [('title', True), ('authors', True), ('series', True)]
defs['virtual_libraries'] = {} defs['virtual_libraries'] = {}
defs['virtual_lib_on_startup'] = defs['cs_virtual_lib_on_startup'] = '' defs['virtual_lib_on_startup'] = defs['cs_virtual_lib_on_startup'] = ''
defs['virt_libs_hidden'] = defs['virt_libs_order'] = () defs['virt_libs_hidden'] = defs['virt_libs_order'] = ()

View File

@ -152,6 +152,10 @@ def create_defs():
defs['hidpi'] = 'auto' defs['hidpi'] = 'auto'
defs['tag_browser_item_padding'] = 0.5 defs['tag_browser_item_padding'] = 0.5
defs['paste_isbn_prefixes'] = ['isbn', 'url', 'amazon', 'google'] defs['paste_isbn_prefixes'] = ['isbn', 'url', 'amazon', 'google']
defs['qv_respects_vls'] = True
defs['qv_dclick_changes_column'] = True
defs['qv_retkey_changes_column'] = True
defs['qv_show_on_startup'] = False
create_defs() create_defs()

View File

@ -24,6 +24,7 @@ from calibre.utils.icu import sort_key
from calibre.db.errors import NoSuchFormat from calibre.db.errors import NoSuchFormat
from calibre.library.comments import merge_comments from calibre.library.comments import merge_comments
from calibre.ebooks.metadata.sources.prefs import msprefs from calibre.ebooks.metadata.sources.prefs import msprefs
from calibre.customize.ui import find_plugin
class EditMetadataAction(InterfaceAction): class EditMetadataAction(InterfaceAction):
@ -347,6 +348,9 @@ class EditMetadataAction(InterfaceAction):
self.gui.refresh_cover_browser() self.gui.refresh_cover_browser()
m.current_changed(current, previous or current) m.current_changed(current, previous or current)
self.gui.tags_view.recount_with_position_based_index() self.gui.tags_view.recount_with_position_based_index()
qv = find_plugin('Show Quickview')
if qv is not None:
qv.actual_plugin_.refill_quickview()
def do_edit_metadata(self, row_list, current_row, editing_multiple): def do_edit_metadata(self, row_list, current_row, editing_multiple):
from calibre.gui2.metadata.single import edit_metadata from calibre.gui2.metadata.single import edit_metadata

View File

@ -56,7 +56,6 @@ class ShowQuickviewAction(InterfaceAction):
'on the device.')).exec_() 'on the device.')).exec_()
return return
index = self.gui.library_view.currentIndex() index = self.gui.library_view.currentIndex()
if index.isValid():
self.current_instance = Quickview(self.gui, index) self.current_instance = Quickview(self.gui, index)
self.current_instance.reopen_quickview.connect(self.reopen_quickview) self.current_instance.reopen_quickview.connect(self.reopen_quickview)
self.set_search_shortcut() self.set_search_shortcut()
@ -73,6 +72,10 @@ class ShowQuickviewAction(InterfaceAction):
self.current_instance = None self.current_instance = None
self.show_quickview() self.show_quickview()
def refill_quickview(self):
if self.current_instance and not self.current_instance.is_closed:
self.current_instance.refill()
def change_quickview_column(self, idx): def change_quickview_column(self, idx):
self.show_quickview() self.show_quickview()
if self.current_instance: if self.current_instance:

View File

@ -108,6 +108,10 @@ class Quickview(QDialog, Ui_Quickview):
Ui_Quickview.__init__(self) Ui_Quickview.__init__(self)
self.setupUi(self) self.setupUi(self)
self.isClosed = False self.isClosed = False
self.current_book = None
if self.is_pane:
self.main_grid_layout.setContentsMargins(0, 0, 0, 0)
self.books_table_column_widths = None self.books_table_column_widths = None
try: try:
@ -130,19 +134,13 @@ class Quickview(QDialog, Ui_Quickview):
self.db = self.view.model().db self.db = self.view.model().db
self.gui = gui self.gui = gui
self.is_closed = False self.is_closed = False
self.current_book_id = None self.current_book_id = None # the db id of the book used to fill the lh pane
self.current_key = None self.current_column = None # current logical column in books list
self.current_key = None # current lookup key in books list
self.last_search = None self.last_search = None
self.current_column = None
self.current_item = None
self.no_valid_items = False self.no_valid_items = False
column_positions = self.view.get_state()['column_positions'] self.fm = self.db.field_metadata
column_order = ['title', 'authors', 'series']
column_order.sort(key=lambda col: column_positions[col])
self.title_column = column_order.index('title')
self.author_column = column_order.index('authors')
self.series_column = column_order.index('series')
self.items.setSelectionMode(QAbstractItemView.SingleSelection) self.items.setSelectionMode(QAbstractItemView.SingleSelection)
self.items.currentTextChanged.connect(self.item_selected) self.items.currentTextChanged.connect(self.item_selected)
@ -153,7 +151,6 @@ class Quickview(QDialog, Ui_Quickview):
self.items.installEventFilter(focus_filter) self.items.installEventFilter(focus_filter)
self.tab_pressed_signal.connect(self.tab_pressed) self.tab_pressed_signal.connect(self.tab_pressed)
# Set up the books table columns
return_filter = BooksTableFilter(self.books_table) return_filter = BooksTableFilter(self.books_table)
return_filter.return_pressed_signal.connect(self.return_pressed) return_filter.return_pressed_signal.connect(self.return_pressed)
self.books_table.installEventFilter(return_filter) self.books_table.installEventFilter(return_filter)
@ -172,19 +169,16 @@ class Quickview(QDialog, Ui_Quickview):
self.books_table.setSelectionBehavior(QAbstractItemView.SelectRows) self.books_table.setSelectionBehavior(QAbstractItemView.SelectRows)
self.books_table.setSelectionMode(QAbstractItemView.SingleSelection) self.books_table.setSelectionMode(QAbstractItemView.SingleSelection)
self.books_table.setProperty('highlight_current_item', 150) self.books_table.setProperty('highlight_current_item', 150)
self.books_table.setColumnCount(3)
t = QTableWidgetItem(_('Title')) # Set up the books table columns
self.books_table.setHorizontalHeaderItem(self.title_column, t) self.add_columns_to_widget()
t = QTableWidgetItem(_('Authors'))
self.books_table.setHorizontalHeaderItem(self.author_column, t)
t = QTableWidgetItem(ngettext("Series", 'Series', 1))
self.books_table.setHorizontalHeaderItem(self.series_column, t)
self.books_table_header_height = self.books_table.height() self.books_table_header_height = self.books_table.height()
self.books_table.cellDoubleClicked.connect(self.book_doubleclicked) self.books_table.cellDoubleClicked.connect(self.book_doubleclicked)
self.books_table.currentCellChanged.connect(self.books_table_cell_changed) self.books_table.currentCellChanged.connect(self.books_table_cell_changed)
self.books_table.cellClicked.connect(self.books_table_set_search_string) self.books_table.cellClicked.connect(self.books_table_set_search_string)
self.books_table.cellActivated.connect(self.books_table_set_search_string) self.books_table.cellActivated.connect(self.books_table_set_search_string)
self.books_table.sortByColumn(self.title_column, Qt.AscendingOrder) self.books_table.sortByColumn(0, Qt.AscendingOrder)
# get the standard table row height. Do this here because calling # get the standard table row height. Do this here because calling
# resizeRowsToContents can word wrap long cell contents, creating # resizeRowsToContents can word wrap long cell contents, creating
@ -225,6 +219,25 @@ class Quickview(QDialog, Ui_Quickview):
self.books_table.horizontalHeader().sectionResized.connect(self.section_resized) self.books_table.horizontalHeader().sectionResized.connect(self.section_resized)
self.dock_button.clicked.connect(self.show_as_pane_changed) self.dock_button.clicked.connect(self.show_as_pane_changed)
def add_columns_to_widget(self):
'''
Get the list of columns from the preferences. Clear the current table
and add the current column set
'''
self.column_order = [x[0] for x in get_qv_field_list(self.fm) if x[1]]
self.books_table.clear()
self.books_table.setColumnCount(len(self.column_order))
for idx,col in enumerate(self.column_order):
t = QTableWidgetItem(self.fm[col]['name'])
self.books_table.setHorizontalHeaderItem(idx, t)
def refill(self):
'''
Refill the table in case the book data changes
'''
self.add_columns_to_widget()
self._refresh(self.current_book_id, self.current_key)
def set_search_text(self, txt): def set_search_text(self, txt):
if txt: if txt:
self.search_button.setEnabled(True) self.search_button.setEnabled(True)
@ -248,22 +261,39 @@ class Quickview(QDialog, Ui_Quickview):
self.books_table_set_search_string(cur_row, cur_col) self.books_table_set_search_string(cur_row, cur_col)
def books_table_set_search_string(self, current_row, current_col): def books_table_set_search_string(self, current_row, current_col):
current = self.books_table.currentItem() '''
Given the contents of a cell, compute a search string that will find
that book and any others with identical contents in the cell.
'''
current = self.books_table.item(current_row, current_col)
if current is None: if current is None:
return return
if current.column() == 0: book_id = current.data(Qt.UserRole)
if current is None:
return
col = self.column_order[current.column()]
if col == 'title':
self.set_search_text('title:="' + current.text().replace('"', '\\"') + '"') self.set_search_text('title:="' + current.text().replace('"', '\\"') + '"')
elif current.column() == 1: elif col == 'authors':
authors = [] authors = []
for aut in [t.strip() for t in current.text().split('&')]: for aut in [t.strip() for t in current.text().split('&')]:
authors.append('authors:="' + aut.replace('"', '\\"') + '"') authors.append('authors:="' + aut.replace('"', '\\"') + '"')
self.set_search_text(' and '.join(authors)) self.set_search_text(' and '.join(authors))
else: elif self.fm[col]['datatype'] == 'series':
t = current.text().rpartition('[')[0].strip() mi = self.db.get_metadata(book_id, index_is_id=True, get_user_categories=False)
t = mi.get(col)
if t: if t:
self.set_search_text('series:="' + t.replace('"', '\\"') + '"') self.set_search_text(col+ ':="' + t + '"')
else: else:
self.set_search_text(None) self.set_search_text(None)
else:
if self.fm[col]['is_multiple']:
items = [(col + ':"=' + v.strip() + '"') for v in
current.text().split(self.fm[col]['is_multiple']['ui_to_list'])]
self.set_search_text(' and '.join(items))
else:
self.set_search_text(col + ':"=' + current.text() + '"')
def tab_pressed(self, in_widget, isForward): def tab_pressed(self, in_widget, isForward):
if isForward: if isForward:
@ -292,10 +322,13 @@ class Quickview(QDialog, Ui_Quickview):
if self.last_search is not None: if self.last_search is not None:
self.gui.search.set_search_string(self.last_search) self.gui.search.set_search_string(self.last_search)
# Called when book information is changed in the library view. Make that
# book current. This means that prev and next in edit metadata will move
# the current book.
def book_was_changed(self, mi): def book_was_changed(self, mi):
'''
Called when book information is changed in the library view. Make that
book info current. This means that prev and next in edit metadata will move
the current book and change quickview
'''
if self.is_closed or self.current_column is None: if self.is_closed or self.current_column is None:
return return
# There is an ordering problem when libraries are changed. The library # There is an ordering problem when libraries are changed. The library
@ -305,7 +338,7 @@ class Quickview(QDialog, Ui_Quickview):
# operation if we get an exception. The "close" will come # operation if we get an exception. The "close" will come
# eventually. # eventually.
try: try:
self.refresh(self.view.model().index(self.db.row(mi.id), self.current_column)) self._refresh(mi.get('id'), self.current_key)
except: except:
pass pass
@ -316,21 +349,29 @@ class Quickview(QDialog, Ui_Quickview):
self.fill_in_books_box(unicode(txt)) self.fill_in_books_box(unicode(txt))
self.set_search_text(self.current_key + ':"=' + txt.replace('"', '\\"') + '"') self.set_search_text(self.current_key + ':"=' + txt.replace('"', '\\"') + '"')
# Given a cell in the library view, display the information
def refresh(self, idx): def refresh(self, idx):
'''
Given a cell in the library view, display the information. This method
converts the index into the lookup ken
'''
if self.lock_qv.isChecked(): if self.lock_qv.isChecked():
return return
bv_row = idx.row() bv_row = idx.row()
self.current_column = idx.column() self.current_column = idx.column()
key = self.view.model().column_map[self.current_column] key = self.view.column_map[self.current_column]
book_id = self.view.model().id(bv_row) book_id = self.view.model().id(bv_row)
if self.current_book_id == book_id and self.current_key == key: if self.current_book_id == book_id and self.current_key == key:
return return
self._refresh(book_id, key)
def _refresh(self, book_id, key):
'''
Actually fill in the left-hand pane from the information in the
selected column of the selected book
'''
# Only show items for categories # Only show items for categories
if not self.db.field_metadata[key]['is_category']: if key is None or not self.fm[key]['is_category']:
if self.current_key is None: if self.current_key is None:
self.indicate_no_items() self.indicate_no_items()
return return
@ -338,7 +379,7 @@ class Quickview(QDialog, Ui_Quickview):
label_text = _('&Item: {0} ({1})') label_text = _('&Item: {0} ({1})')
if self.is_pane: if self.is_pane:
label_text = label_text.replace('&', '') label_text = label_text.replace('&', '')
self.items_label.setText(label_text.format(self.db.field_metadata[key]['name'], key)) self.items_label.setText(label_text.format(self.fm[key]['name'], key))
self.items.blockSignals(True) self.items.blockSignals(True)
self.items.clear() self.items.clear()
@ -349,7 +390,10 @@ class Quickview(QDialog, Ui_Quickview):
if vals: if vals:
self.no_valid_items = False self.no_valid_items = False
if self.db.field_metadata[key]['datatype'] == 'rating': if self.fm[key]['datatype'] == 'rating':
if self.fm[key]['display'].get('allow_half_stars', False):
vals = unicode(vals/2.0)
else:
vals = unicode(vals/2) vals = unicode(vals/2)
if not isinstance(vals, list): if not isinstance(vals, list):
vals = [vals] vals = [vals]
@ -377,15 +421,20 @@ class Quickview(QDialog, Ui_Quickview):
'to see the information for that book')) 'to see the information for that book'))
def fill_in_books_box(self, selected_item): def fill_in_books_box(self, selected_item):
self.current_item = selected_item '''
Given the selected row in the left-hand box, fill in the grid with
the books that contain that data.
'''
# Do a bit of fix-up on the items so that the search works. # Do a bit of fix-up on the items so that the search works.
if selected_item.startswith('.'): if selected_item.startswith('.'):
sv = '.' + selected_item sv = '.' + selected_item
else: else:
sv = selected_item sv = selected_item
sv = self.current_key + ':"=' + sv.replace('"', r'\"') + '"' sv = self.current_key + ':"=' + sv.replace('"', r'\"') + '"'
books = self.db.search(sv, return_matches=True, if gprefs['qv_respects_vls']:
sort_results=False) books = self.db.search(sv, return_matches=True, sort_results=False)
else:
books = self.db.new_api.search(sv)
self.books_table.setRowCount(len(books)) self.books_table.setRowCount(len(books))
label_text = _('&Books with selected item "{0}": {1}') label_text = _('&Books with selected item "{0}": {1}')
@ -395,28 +444,39 @@ class Quickview(QDialog, Ui_Quickview):
select_item = None select_item = None
self.books_table.setSortingEnabled(False) self.books_table.setSortingEnabled(False)
self.books_table.blockSignals(True)
tt = ('<p>' + tt = ('<p>' +
_('Double-click on a book to change the selection in the library view. ' _('Double-click on a book to change the selection in the library view or '
'Shift- or control-double-click to edit the metadata of a book') + '</p>') 'change the column shown in the left-hand pane. '
'Shift- or control-double-click to edit the metadata of a book, '
'which also changes the selected book.'
) + '</p>')
for row, b in enumerate(books): for row, b in enumerate(books):
mi = self.db.get_metadata(b, index_is_id=True, get_user_categories=False) mi = self.db.get_metadata(b, index_is_id=True, get_user_categories=False)
for col in self.column_order:
if col == 'title':
a = TableItem(mi.title, mi.title_sort) a = TableItem(mi.title, mi.title_sort)
a.setData(Qt.UserRole, b)
a.setToolTip(tt)
self.books_table.setItem(row, self.title_column, a)
if b == self.current_book_id: if b == self.current_book_id:
select_item = a select_item = a
elif col == 'authors':
a = TableItem(' & '.join(mi.authors), mi.author_sort) a = TableItem(' & '.join(mi.authors), mi.author_sort)
a.setToolTip(tt) elif col == 'series':
self.books_table.setItem(row, self.author_column, a)
series = mi.format_field('series')[1] series = mi.format_field('series')[1]
if series is None: if series is None:
series = '' series = ''
a = TableItem(series, mi.series, mi.series_index) a = TableItem(series, mi.series, mi.series_index)
elif self.fm[col]['datatype'] == 'series':
v = mi.format_field(col)[1]
a = TableItem(v, mi.get(col), mi.get(col+'_index'))
else:
v = mi.format_field(col)[1]
a = TableItem(v, v)
a.setData(Qt.UserRole, b)
a.setToolTip(tt) a.setToolTip(tt)
self.books_table.setItem(row, self.series_column, a) self.books_table.setItem(row, self.key_to_table_widget_column(col), a)
self.books_table.setRowHeight(row, self.books_table_row_height) self.books_table.setRowHeight(row, self.books_table_row_height)
self.books_table.blockSignals(False)
self.books_table.setSortingEnabled(True) self.books_table.setSortingEnabled(True)
if select_item is not None: if select_item is not None:
self.books_table.setCurrentItem(select_item) self.books_table.setCurrentItem(select_item)
@ -445,22 +505,43 @@ class Quickview(QDialog, Ui_Quickview):
self.books_table.setColumnWidth(c, w) self.books_table.setColumnWidth(c, w)
self.save_state() self.save_state()
def key_to_table_widget_column(self, key):
return self.column_order.index(key)
def return_pressed(self): def return_pressed(self):
self.select_book(self.books_table.currentRow()) row = self.books_table.currentRow()
if gprefs['qv_retkey_changes_column']:
self.select_book(row, self.books_table.currentColumn())
else:
self.select_book(row, self.key_to_table_widget_column(self.current_key))
def book_doubleclicked(self, row, column): def book_doubleclicked(self, row, column):
if self.no_valid_items: if self.no_valid_items:
return return
self.select_book(row) if gprefs['qv_dclick_changes_column']:
self.select_book(row, column)
else:
self.select_book(row, self.key_to_table_widget_column(self.current_key))
def select_book(self, row): def select_book(self, row, column):
book_id = int(self.books_table.item(row, self.title_column).data(Qt.UserRole)) '''
self.view.select_rows([book_id]) row and column both refer the qv table. In particular, column is not
the logical column in the book list.
'''
item = self.books_table.item(row, column)
if item is None:
return
book_id = int(self.books_table.item(row, column).data(Qt.UserRole))
key = self.column_order[column]
modifiers = int(QApplication.keyboardModifiers()) modifiers = int(QApplication.keyboardModifiers())
if modifiers in (Qt.CTRL, Qt.SHIFT): if modifiers in (Qt.CTRL, Qt.SHIFT):
self.view.select_rows([book_id])
em = find_plugin('Edit Metadata') em = find_plugin('Edit Metadata')
if em is not None: if em is not None:
em.actual_plugin_.edit_metadata(None) em.actual_plugin_.edit_metadata(None)
else:
self.view.select_cell(self.db.data.id_to_index(book_id),
self.view.column_map.index(key))
def set_focus(self): def set_focus(self):
self.items.setFocus(Qt.ActiveWindowFocusReason) self.items.setFocus(Qt.ActiveWindowFocusReason)
@ -498,3 +579,20 @@ class Quickview(QDialog, Ui_Quickview):
self.gui.library_view.setFocus(Qt.ActiveWindowFocusReason) self.gui.library_view.setFocus(Qt.ActiveWindowFocusReason)
self._close() self._close()
QDialog.reject(self) QDialog.reject(self)
def get_qv_field_list(fm, use_defaults=False):
from calibre.gui2.ui import get_gui
db = get_gui().current_db
if use_defaults:
src = db.prefs.defaults
else:
src = db.prefs
fieldlist = list(src['qv_display_fields'])
names = frozenset([x[0] for x in fieldlist])
for field in fm.displayable_field_keys():
if (field != 'comments'
and fm[field]['datatype'] != 'comments'
and field not in names):
fieldlist.append((field, False))
available = frozenset(fm.displayable_field_keys())
return [(f, d) for f, d in fieldlist if f in available]

View File

@ -19,7 +19,7 @@
<property name="windowTitle"> <property name="windowTitle">
<string>Quickview</string> <string>Quickview</string>
</property> </property>
<layout class="QGridLayout"> <layout class="QGridLayout" name="main_grid_layout">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="items_label"> <widget class="QLabel" name="items_label">
<property name="buddy"> <property name="buddy">
@ -62,6 +62,19 @@
</item> </item>
<item row="3" column="0" colspan="2"> <item row="3" column="0" colspan="2">
<layout class="QHBoxLayout"> <layout class="QHBoxLayout">
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QCheckBox" name="lock_qv"> <widget class="QCheckBox" name="lock_qv">
<property name="text"> <property name="text">
@ -80,7 +93,7 @@
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>0</width> <width>20</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
@ -145,6 +158,19 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>

View File

@ -164,7 +164,9 @@ class LibraryWidget(Splitter): # {{{
av.add_view('grid', parent.grid_view) av.add_view('grid', parent.grid_view)
parent.quickview_splitter.addWidget(stack) parent.quickview_splitter.addWidget(stack)
quickview_widget.setLayout(QVBoxLayout()) l = QVBoxLayout()
l.setContentsMargins(0, 0, 0, 0)
quickview_widget.setLayout(l)
parent.quickview_splitter.addWidget(quickview_widget) parent.quickview_splitter.addWidget(quickview_widget)
parent.quickview_splitter.hide_quickview_widget() parent.quickview_splitter.hide_quickview_widget()

View File

@ -921,6 +921,15 @@ class BooksView(QTableView): # {{{
sm = self.selectionModel() sm = self.selectionModel()
sm.select(index, sm.ClearAndSelect|sm.Rows) sm.select(index, sm.ClearAndSelect|sm.Rows)
def select_cell(self, row_number=0, logical_column=0):
if row_number > -1 and row_number < self.model().rowCount(QModelIndex()):
index = self.model().index(row_number, logical_column)
self.setCurrentIndex(index)
sm = self.selectionModel()
sm.select(index, sm.ClearAndSelect|sm.Rows)
sm.select(index, sm.Current)
self.clicked.emit(index)
def row_at_top(self): def row_at_top(self):
pos = 0 pos = 0
while pos < 100: while pos < 100:

View File

@ -32,9 +32,11 @@ from calibre.utils.localization import (available_translations,
from calibre.utils.config import prefs from calibre.utils.config import prefs
from calibre.utils.icu import sort_key from calibre.utils.icu import sort_key
from calibre.gui2.book_details import get_field_list from calibre.gui2.book_details import get_field_list
from calibre.gui2.dialogs.quickview import get_qv_field_list
from calibre.gui2.preferences.coloring import EditRules from calibre.gui2.preferences.coloring import EditRules
from calibre.gui2.library.alternate_views import auto_height, CM_TO_INCH from calibre.gui2.library.alternate_views import auto_height, CM_TO_INCH
from calibre.gui2.widgets2 import Dialog from calibre.gui2.widgets2 import Dialog
from calibre.customize.ui import find_plugin
class BusyCursor(object): class BusyCursor(object):
@ -209,7 +211,6 @@ class IdLinksEditor(Dialog):
self.table.removeRow(r) self.table.removeRow(r)
# }}} # }}}
class DisplayedFields(QAbstractListModel): # {{{ class DisplayedFields(QAbstractListModel): # {{{
def __init__(self, db, parent=None): def __init__(self, db, parent=None):
@ -285,6 +286,25 @@ class DisplayedFields(QAbstractListModel): # {{{
# }}} # }}}
class QVDisplayedFields(DisplayedFields): # {{{
def __init__(self, db, parent=None):
DisplayedFields.__init__(self, db, parent)
def initialize(self, use_defaults=False):
self.beginResetModel()
self.fields = [[x[0], x[1]] for x in
get_qv_field_list(self.db.field_metadata, use_defaults=use_defaults)]
self.endResetModel()
self.changed = True
def commit(self):
if self.changed:
self.db.new_api.set_pref('qv_display_fields', self.fields)
# }}}
class Background(QWidget): # {{{ class Background(QWidget): # {{{
def __init__(self, parent): def __init__(self, parent):
@ -363,6 +383,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
r('tag_browser_show_counts', gprefs) r('tag_browser_show_counts', gprefs)
r('tag_browser_item_padding', gprefs) r('tag_browser_item_padding', gprefs)
r('qv_respects_vls', gprefs)
r('qv_dclick_changes_column', gprefs)
r('qv_retkey_changes_column', gprefs)
r('qv_show_on_startup', gprefs)
r('cover_flow_queue_length', config, restart_required=True) r('cover_flow_queue_length', config, restart_required=True)
r('cover_browser_reflections', gprefs) r('cover_browser_reflections', gprefs)
r('cover_browser_title_template', db.prefs) r('cover_browser_title_template', db.prefs)
@ -443,8 +469,19 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.field_display_order) self.field_display_order)
self.display_model.dataChanged.connect(self.changed_signal) self.display_model.dataChanged.connect(self.changed_signal)
self.field_display_order.setModel(self.display_model) self.field_display_order.setModel(self.display_model)
self.df_up_button.clicked.connect(self.move_df_up) self.df_up_button.clicked.connect(partial(self.move_field_up,
self.df_down_button.clicked.connect(self.move_df_down) self.field_display_order, self.display_model))
self.df_down_button.clicked.connect(partial(self.move_field_down,
self.field_display_order, self.display_model))
self.qv_display_model = QVDisplayedFields(self.gui.current_db,
self.qv_display_order)
self.qv_display_model.dataChanged.connect(self.changed_signal)
self.qv_display_order.setModel(self.qv_display_model)
self.qv_up_button.clicked.connect(partial(self.move_field_up,
self.qv_display_order, self.qv_display_model))
self.qv_down_button.clicked.connect(partial(self.move_field_down,
self.qv_display_order, self.qv_display_model))
self.edit_rules = EditRules(self.tabWidget) self.edit_rules = EditRules(self.tabWidget)
self.edit_rules.changed.connect(self.changed_signal) self.edit_rules.changed.connect(self.changed_signal)
@ -553,6 +590,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.current_font = self.initial_font = font self.current_font = self.initial_font = font
self.update_font_display() self.update_font_display()
self.display_model.initialize() self.display_model.initialize()
self.qv_display_model.initialize()
db = self.gui.current_db db = self.gui.current_db
try: try:
idx = self.gui.library_view.currentIndex().row() idx = self.gui.library_view.currentIndex().row()
@ -606,6 +644,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.changed_signal.emit() self.changed_signal.emit()
self.update_font_display() self.update_font_display()
self.display_model.restore_defaults() self.display_model.restore_defaults()
self.qv_display_model.restore_defaults();
self.edit_rules.clear() self.edit_rules.clear()
self.icon_rules.clear() self.icon_rules.clear()
self.grid_rules.clear() self.grid_rules.clear()
@ -654,23 +693,23 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.font_display.setText(name + self.font_display.setText(name +
' [%dpt]'%fi.pointSize()) ' [%dpt]'%fi.pointSize())
def move_df_up(self): def move_field_up(self, widget, model):
idx = self.field_display_order.currentIndex() idx = widget.currentIndex()
if idx.isValid(): if idx.isValid():
idx = self.display_model.move(idx, -1) idx = model.move(idx, -1)
if idx is not None: if idx is not None:
sm = self.field_display_order.selectionModel() sm = widget.selectionModel()
sm.select(idx, sm.ClearAndSelect) sm.select(idx, sm.ClearAndSelect)
self.field_display_order.setCurrentIndex(idx) widget.setCurrentIndex(idx)
def move_df_down(self): def move_field_down(self, widget, model):
idx = self.field_display_order.currentIndex() idx = widget.currentIndex()
if idx.isValid(): if idx.isValid():
idx = self.display_model.move(idx, 1) idx = model.move(idx, 1)
if idx is not None: if idx is not None:
sm = self.field_display_order.selectionModel() sm = widget.selectionModel()
sm.select(idx, sm.ClearAndSelect) sm.select(idx, sm.ClearAndSelect)
self.field_display_order.setCurrentIndex(idx) widget.setCurrentIndex(idx)
def change_font(self, *args): def change_font(self, *args):
fd = QFontDialog(self.build_font_obj(), self) fd = QFontDialog(self.build_font_obj(), self)
@ -693,6 +732,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
QApplication.setFont(self.font_display.font()) QApplication.setFont(self.font_display.font())
rr = True rr = True
self.display_model.commit() self.display_model.commit()
self.qv_display_model.commit()
self.edit_rules.commit(self.gui.current_db.prefs) self.edit_rules.commit(self.gui.current_db.prefs)
self.icon_rules.commit(self.gui.current_db.prefs) self.icon_rules.commit(self.gui.current_db.prefs)
self.grid_rules.commit(self.gui.current_db.prefs) self.grid_rules.commit(self.gui.current_db.prefs)
@ -720,6 +760,9 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
getattr(gui, view + '_view').set_row_header_visibility() getattr(gui, view + '_view').set_row_header_visibility()
gui.library_view.refresh_row_sizing() gui.library_view.refresh_row_sizing()
gui.grid_view.refresh_settings() gui.grid_view.refresh_settings()
qv = find_plugin('Show Quickview')
if qv is not None:
qv.actual_plugin_.refill_quickview()
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -1131,6 +1131,112 @@ them to all have the same width and height</string>
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="quickview_tab">
<attribute name="icon">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/search.png</normaloff>:/images/search.png</iconset>
</attribute>
<attribute name="title">
<string>&amp;Quickview</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_122">
<item row="1" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_122">
<item row="1" column="0">
<widget class="QCheckBox" name="opt_qv_respects_vls">
<property name="text">
<string>&amp;Apply virtual libraries in Quickview pane</string>
</property>
<property name="toolTip">
<string>Check this box to make Quickview show books only in the
current virtual library. If unchecked, Quickview ignores virtual libraries.</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="opt_qv_show_on_startup">
<property name="text">
<string>&amp;Show Quickview on startup</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="opt_qv_retkey_changes_column">
<property name="toolTip">
<string>Pressing return in a cell changes both the book and the
column being examined (the left-hand pane)</string>
</property>
<property name="text">
<string>&amp;Pressing 'return' changes examined column</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="opt_qv_dclick_changes_column">
<property name="toolTip">
<string>Double-clicking in a cell changes both the book and the
column being examined (the left-hand pane)</string>
</property>
<property name="text">
<string>&amp;Doubleclick changes examined column</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0" rowspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Select displayed columns</string>
</property>
<layout class="QGridLayout" name="gridLayout_32">
<item row="0" column="1">
<widget class="QToolButton" name="qv_up_button">
<property name="toolTip">
<string>Move up</string>
</property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/arrow-up.png</normaloff>:/images/arrow-up.png</iconset>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QToolButton" name="qv_down_button">
<property name="toolTip">
<string>Move down</string>
</property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/arrow-down.png</normaloff>:/images/arrow-down.png</iconset>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="3">
<widget class="QListView" name="qv_display_order">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>

View File

@ -26,7 +26,7 @@ from calibre.constants import (
from calibre.utils.config import prefs, dynamic from calibre.utils.config import prefs, dynamic
from calibre.utils.ipc.pool import Pool from calibre.utils.ipc.pool import Pool
from calibre.db.legacy import LibraryDatabase from calibre.db.legacy import LibraryDatabase
from calibre.customize.ui import interface_actions, available_store_plugins from calibre.customize.ui import interface_actions, available_store_plugins, find_plugin
from calibre.gui2 import (error_dialog, GetMetadata, open_url, from calibre.gui2 import (error_dialog, GetMetadata, open_url,
gprefs, max_available_height, config, info_dialog, Dispatcher, gprefs, max_available_height, config, info_dialog, Dispatcher,
question_dialog, warning_dialog) question_dialog, warning_dialog)
@ -428,6 +428,11 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
self.auto_adder = AutoAdder(gprefs['auto_add_path'], self) self.auto_adder = AutoAdder(gprefs['auto_add_path'], self)
self.save_layout_state() self.save_layout_state()
if gprefs['qv_show_on_startup']:
qv = find_plugin('Show Quickview')
if qv is not None:
qv.actual_plugin_.show_quickview()
# Collect cycles now # Collect cycles now
gc.collect() gc.collect()