Indicate marked books in the main book list as well

Books marked with the Temp Marker plugin will now have an icon next to
their row number to indicate they have been marked in the main book
list.
This commit is contained in:
Kovid Goyal 2013-10-04 18:01:08 +05:30
parent 9a9daa7908
commit 49686b7093
4 changed files with 37 additions and 4 deletions

View File

@ -77,6 +77,7 @@ class View(object):
def __init__(self, cache):
self.cache = cache
self.marked_ids = {}
self.marked_listeners = {}
self.search_restriction_book_count = 0
self.search_restriction = self.base_restriction = ''
self.search_restriction_name = self.base_restriction_name = ''
@ -127,6 +128,9 @@ class View(object):
self.full_map_is_sorted = True
self.sort_history = [('id', True)]
def add_marked_listener(self, func):
self.marked_listeners[id(func)] = weakref.ref(func)
def add_to_sort_history(self, items):
self.sort_history = uniq((list(items) + list(self.sort_history)),
operator.itemgetter(0))[:tweaks['maximum_resort_levels']]
@ -370,7 +374,13 @@ class View(object):
id_dict.itervalues())))
# This invalidates all searches in the cache even though the cache may
# be shared by multiple views. This is not ideal, but...
self.cache.clear_search_caches(old_marked_ids | set(self.marked_ids))
cmids = set(self.marked_ids)
self.cache.clear_search_caches(old_marked_ids | cmids)
if old_marked_ids != cmids:
for funcref in self.marked_listeners.itervalues():
func = funcref()
if func is not None:
func(old_marked_ids, cmids)
def refresh(self, field=None, ascending=True, clear_caches=True, do_search=True):
self._map = tuple(sorted(self.cache.all_book_ids()))

View File

@ -422,7 +422,7 @@ class CoverDelegate(QStyledItemDelegate):
try:
p = self.marked_emblem
except AttributeError:
p = self.marked_emblem = QPixmap(I('rating.png')).scaled(48, 48, transformMode=Qt.SmoothTransformation)
p = self.marked_emblem = m.marked_icon.pixmap(48, 48)
drect = QRect(orect)
drect.setLeft(drect.left() + right_adjust)
drect.setRight(drect.left() + p.width())

View File

@ -111,7 +111,7 @@ class ColumnIcon(object): # {{{
d = os.path.join(config_dir, 'cc_icons', icon)
if (os.path.exists(d)):
bm = QPixmap(d)
bm = bm.scaled(128, 128, aspectRatioMode= Qt.KeepAspectRatio,
bm = bm.scaled(128, 128, aspectRatioMode=Qt.KeepAspectRatio,
transformMode=Qt.SmoothTransformation)
icon_bitmaps.append(bm)
total_width += bm.width()
@ -193,6 +193,8 @@ class BooksModel(QAbstractTableModel): # {{{
self.bool_yes_icon = QIcon(I('ok.png'))
self.bool_no_icon = QIcon(I('list_remove.png'))
self.bool_blank_icon = QIcon(I('blank.png'))
self.marked_icon = QIcon(I('rating.png'))
self.row_decoration = NONE
self.device_connected = False
self.ids_to_highlight = []
self.ids_to_highlight_set = set()
@ -921,6 +923,8 @@ class BooksModel(QAbstractTableModel): # {{{
if role == Qt.DisplayRole: # orientation is vertical
return QVariant(section+1)
if role == Qt.DecorationRole:
return self.marked_icon if self.db.data.get_marked(self.db.data.index_to_id(section)) else self.row_decoration
return NONE
def flags(self, index):

View File

@ -22,7 +22,7 @@ from calibre.gui2.library.delegates import (RatingDelegate, PubDateDelegate,
from calibre.gui2.library.models import BooksModel, DeviceBooksModel
from calibre.gui2.library.alternate_views import AlternateViews, setup_dnd_interface
from calibre.utils.config import tweaks, prefs
from calibre.gui2 import error_dialog, gprefs
from calibre.gui2 import error_dialog, gprefs, FunctionDispatcher
from calibre.gui2.library import DEFAULT_SORT
from calibre.constants import filesystem_encoding
from calibre import force_unicode
@ -63,6 +63,11 @@ class HeaderView(QHeaderView): # {{{
opt.state |= QStyle.State_MouseOver
sm = self.selectionModel()
if opt.orientation == Qt.Vertical:
try:
opt.icon = model.headerData(logical_index, opt.orientation, Qt.DecorationRole)
opt.iconAlignment = Qt.AlignVCenter
except TypeError:
pass
if sm.isRowSelected(logical_index, QModelIndex()):
opt.state |= QStyle.State_Sunken
@ -214,6 +219,7 @@ class BooksView(QTableView): # {{{
self.setSortingEnabled(True)
self.selectionModel().currentRowChanged.connect(self._model.current_changed)
self.preserve_state = partial(PreserveViewState, self)
self.marked_changed_listener = FunctionDispatcher(self.marked_changed)
# {{{ Column Header setup
self.can_add_columns = True
@ -229,6 +235,7 @@ class BooksView(QTableView): # {{{
self.column_header.customContextMenuRequested.connect(self.show_column_header_context_menu)
self.column_header.sectionResized.connect(self.column_resized, Qt.QueuedConnection)
self.row_header = HeaderView(Qt.Vertical, self)
self.row_header.setResizeMode(self.row_header.Fixed)
self.setVerticalHeader(self.row_header)
# }}}
@ -682,7 +689,19 @@ class BooksView(QTableView): # {{{
self.publisher_delegate.set_auto_complete_function(db.all_publishers)
self.alternate_views.set_database(db, stage=1)
def marked_changed(self, old_marked, current_marked):
if bool(old_marked) == bool(current_marked):
changed = old_marked | current_marked
sections = tuple(map(self.model().db.data.id_to_index, changed))
self.row_header.headerDataChanged(Qt.Vertical, min(sections), max(sections))
else:
# Marked items have either appeared or all been removed
self.model().row_decoration = self.model().bool_blank_icon if current_marked else None
self.row_header.headerDataChanged(Qt.Vertical, 0, self.row_header.count()-1)
self.row_header.geometriesChanged.emit()
def database_changed(self, db):
db.data.add_marked_listener(self.marked_changed_listener)
for i in range(self.model().columnCount(None)):
if self.itemDelegateForColumn(i) in (self.rating_delegate,
self.timestamp_delegate, self.pubdate_delegate,