Show the number of currently selected books in the status bar at the bottom of the book list

This commit is contained in:
Kovid Goyal 2013-05-19 14:25:09 +05:30
parent 70340d8b7c
commit 2c12c1aa3d
3 changed files with 77 additions and 21 deletions

View File

@ -161,18 +161,18 @@ class StatusBar(QStatusBar): # {{{
def __init__(self, parent=None):
QStatusBar.__init__(self, parent)
self.default_message = __appname__ + ' ' + _('version') + ' ' + \
self.get_version() + ' ' + _('created by Kovid Goyal')
self.device_string = ''
self.update_label = UpdateLabel('')
self.total = self.current = self.selected = 0
self.addPermanentWidget(self.update_label)
self.update_label.setVisible(False)
self._font = QFont()
self._font.setBold(True)
self.setFont(self._font)
self.defmsg = QLabel(self.default_message)
self.defmsg = QLabel('')
self.defmsg.setFont(self._font)
self.addWidget(self.defmsg)
self.set_label()
def initialize(self, systray=None):
self.systray = systray
@ -180,18 +180,42 @@ class StatusBar(QStatusBar): # {{{
def device_connected(self, devname):
self.device_string = _('Connected ') + devname
self.defmsg.setText(self.default_message + ' ..::.. ' +
self.device_string)
self.set_label()
def update_state(self, total, current, selected):
self.total, self.current, self.selected = total, current, selected
self.set_label()
def set_label(self):
try:
self._set_label()
except:
import traceback
traceback.print_exc()
def _set_label(self):
msg = '%s %s %s' % (__appname__, _('version'), get_version())
if self.device_string:
msg += ' ..::.. ' + self.device_string
else:
msg += _(' %(created)s %(name)s') % dict(created=_('created by'), name='Kovid Goyal')
if self.total != self.current:
base = _('%(num)d of %(total)d books') % dict(num=self.current, total=self.total)
else:
base = _('%d books') % self.total
if self.selected > 0:
base = _('%(num)s, %(sel)d selected') % dict(num=base, sel=self.selected)
self.defmsg.setText('%s [%s]' % (msg, base))
self.clearMessage()
def device_disconnected(self):
self.device_string = ''
self.set_label()
self.defmsg.setText(self.default_message)
self.clearMessage()
def get_version(self):
return get_version()
def show_message(self, msg, timeout=0):
self.showMessage(msg, timeout)
if self.notifier is not None and not config['disable_tray_notification']:
@ -312,9 +336,15 @@ class LayoutMixin(object): # {{{
def read_layout_settings(self):
# View states are restored automatically when set_database is called
for x in ('cb', 'tb', 'bd'):
getattr(self, x+'_splitter').restore_state()
def update_status_bar(self, *args):
v = self.current_view()
selected = len(v.selectionModel().selectedRows())
total, current = v.model().counts()
self.status_bar.update_state(total, current, selected)
# }}}

View File

@ -6,7 +6,7 @@ __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import functools, re, os, traceback, errno, time
from collections import defaultdict
from collections import defaultdict, namedtuple
from PyQt4.Qt import (QAbstractTableModel, Qt, pyqtSignal, QIcon, QImage,
QModelIndex, QVariant, QDateTime, QColor, QPixmap)
@ -29,6 +29,8 @@ from calibre.gui2.library import DEFAULT_SORT
from calibre.utils.localization import calibre_langcode_to_name
from calibre.library.coloring import color_row_key
Counts = namedtuple('Counts', 'total current')
def human_readable(size, precision=1):
""" Convert a size in bytes into megabytes """
return ('%.'+str(precision)+'f') % ((size/(1024.*1024.)),)
@ -46,7 +48,7 @@ def default_image():
_default_image = QImage(I('default_cover.png'))
return _default_image
class ColumnColor(object):
class ColumnColor(object): # {{{
def __init__(self, formatter, colors):
self.mi = None
@ -70,9 +72,9 @@ class ColumnColor(object):
return color
except:
pass
# }}}
class ColumnIcon(object):
class ColumnIcon(object): # {{{
def __init__(self, formatter):
self.mi = None
@ -108,6 +110,7 @@ class ColumnIcon(object):
return icon_bitmap
except:
pass
# }}}
class BooksModel(QAbstractTableModel): # {{{
@ -281,6 +284,13 @@ class BooksModel(QAbstractTableModel): # {{{
self._clear_caches()
self.count_changed_signal.emit(self.db.count())
def counts(self):
if self.db.data.search_restriction_applied():
total = self.db.data.get_search_restriction_book_count()
else:
total = self.db.count()
return Counts(total, self.count())
def row_indices(self, index):
''' Return list indices of all cells in index.row()'''
return [self.index(index.row(), c) for c in range(self.columnCount(None))]
@ -1195,6 +1205,12 @@ class DeviceBooksModel(BooksModel): # {{{
self.editable = ['title', 'authors', 'collections']
self.book_in_library = None
def counts(self):
return Counts(len(self.db), len(self.map))
def count_changed(self, *args):
self.count_changed_signal.emit(len(self.db))
def mark_for_deletion(self, job, rows, rows_are_ids=False):
db_indices = rows if rows_are_ids else self.indices(rows)
db_items = [self.db[i] for i in db_indices if -1 < i < len(self.db)]
@ -1234,11 +1250,13 @@ class DeviceBooksModel(BooksModel): # {{{
if not succeeded:
indices = self.row_indices(self.index(row, 0))
self.dataChanged.emit(indices[0], indices[-1])
self.count_changed()
def paths_deleted(self, paths):
self.map = list(range(0, len(self.db)))
self.resort(False)
self.research(True)
self.count_changed()
def is_row_marked_for_deletion(self, row):
try:
@ -1301,6 +1319,7 @@ class DeviceBooksModel(BooksModel): # {{{
self.last_search = text
if self.last_search:
self.searched.emit(True)
self.count_changed()
def research(self, reset=True):
self.search(self.last_search, reset)
@ -1370,6 +1389,7 @@ class DeviceBooksModel(BooksModel): # {{{
self.map = list(range(0, len(db)))
self.research(reset=False)
self.resort()
self.count_changed()
def cover(self, row):
item = self.db[self.map[row]]

View File

@ -325,6 +325,11 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
if self.library_view.model().rowCount(None) < 3:
self.library_view.resizeColumnsToContents()
for view in ('library', 'memory', 'card_a', 'card_b'):
v = getattr(self, '%s_view' % view)
v.selectionModel().selectionChanged.connect(self.update_status_bar)
v.model().count_changed_signal.connect(self.update_status_bar)
self.library_view.model().count_changed()
self.bars_manager.database_changed(self.library_view.model().db)
self.library_view.model().database_changed.connect(self.bars_manager.database_changed,
@ -661,6 +666,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
# Reset the view in case something changed while it was invisible
self.current_view().reset()
self.set_number_of_books_shown()
self.update_status_bar()
def job_exception(self, job, dialog_title=_('Conversion Error')):
if not hasattr(self, '_modeless_dialogs'):