diff --git a/src/bitmessageqt/messagelist.py b/src/bitmessageqt/messagelist.py index e5d95491..05217b4c 100644 --- a/src/bitmessageqt/messagelist.py +++ b/src/bitmessageqt/messagelist.py @@ -1,8 +1,13 @@ +from collections import OrderedDict + from PyQt4 import QtCore, QtGui +import l10n +from bmconfigparser import BMConfigParser from debug import logger from helper_sql import sqlQuery, sqlExecute from tr import _translate +from utils import avatarize class InboxFilter(dict): @@ -20,23 +25,71 @@ class InboxFilter(dict): return 'WHERE %s' % terms if terms else '' -class InboxTableItem(QtCore.QAbstractItemModel): - pass +class CacheDict(OrderedDict): + def __init__(self, *args, **kwargs): + self._maxlen = kwargs.pop('maxlen') + super(CacheDict, self).__init__(*args, **kwargs) + self._check_len() + + def __setitem__(self, key, value): + super(CacheDict, self).__setitem__(key, value) + self._check_len() + + def _check_len(self): + if self._maxlen: + while len(self) > self._maxlen: + # TODO: use Counter + self.popitem(last=False) + + +class TimestampFormatter(object): + def __call__(self, value, role=QtCore.Qt.DisplayRole): + if role == QtCore.Qt.DisplayRole: + return l10n.formatTimestamp(value) + + +class AccountFormatter(object): + def __init__(self): + self.addrs = CacheDict(maxlen=100) + + def __call__(self, addr, role=QtCore.Qt.DisplayRole): + account = self.addrs.get(addr, {}) + if not account: + self.addrs[addr] = account + + label = account.get('label') + if label is None: + account['label'] = label = ( + BMConfigParser().safeGet(addr, 'label') or + '' + ) + + if role == QtCore.Qt.DisplayRole: + return label or addr + elif role == QtCore.Qt.ToolTipRole: + return '%s (%s)' % (label, addr) if label else addr + elif role == QtCore.Qt.DecorationRole: + icon = account.get('icon') + if not icon: + account['icon'] = icon = avatarize(addr) + return icon class InboxTableModel(QtCore.QAbstractTableModel): + table = 'inbox' fields = ( 'msgid', 'toaddress', 'fromaddress', 'subject', 'received', 'read') header = ( {'field': 'fromaddress', - 'label': _translate("MainWindow", "From")}, + 'label': _translate("MainWindow", "From"), + 'formatter': AccountFormatter()}, {'field': 'subject', 'label': _translate("MainWindow", "Subject")}, {'field': 'received', - 'label': _translate("MainWindow", "Received")} + 'label': _translate("MainWindow", "Received"), + 'formatter': TimestampFormatter()} ) attributes = ('msgid', 'read') - table = 'inbox' def __init__(self, parent=None): super(InboxTableModel, self).__init__() @@ -45,7 +98,6 @@ class InboxTableModel(QtCore.QAbstractTableModel): self.query = 'SELECT %%s FROM %s ' % self.table self.sort = ' ORDER BY received DESC' self.column_count = len(self.header) - self.item = InboxTableItem() def columnCount(self, parent=QtCore.QModelIndex()): if parent.isValid(): @@ -67,7 +119,8 @@ class InboxTableModel(QtCore.QAbstractTableModel): ) return font if not index.isValid() or role not in ( - QtCore.Qt.DisplayRole, QtCore.Qt.ToolTipRole + QtCore.Qt.DisplayRole, QtCore.Qt.ToolTipRole, + QtCore.Qt.DecorationRole ): return QtCore.QVariant() @@ -77,10 +130,17 @@ class InboxTableModel(QtCore.QAbstractTableModel): # virtual columns: 3 - msgid, 4 - read column = self.attributes[index.column() - len(self.header)] - return sqlQuery( + result = sqlQuery( '%s %s %s' % (self.query, self.filter, self.sort) % column )[index.row()][0] + try: + result = self.header[index.column()].get('formatter')(result, role) + except (IndexError, TypeError): + pass + + return result + def headerData(self, column, orientation, role=QtCore.Qt.DisplayRole): if orientation == QtCore.Qt.Vertical: return