From 6cf0d07f1b3977531679b905f98ee62b5fecf470 Mon Sep 17 00:00:00 2001 From: Dmitri Bogomolov <4glitch@gmail.com> Date: Tue, 19 Feb 2019 19:04:10 +0200 Subject: [PATCH] Inbox messagelist in MV style, isolated on Messages tab (hope). --- src/bitmessageqt/__init__.py | 81 ++++++++--------------- src/bitmessageqt/main.ui | 37 ++++------- src/bitmessageqt/messagelist.py | 113 ++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 81 deletions(-) create mode 100644 src/bitmessageqt/messagelist.py diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 4fed7e18..e6b4243d 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -372,7 +372,7 @@ class MainWindow(Window): self.treeWidgetChans.keyPressEvent = self.treeWidgetKeyPressEvent # Key press in messagelist - self.tableWidgetInbox.keyPressEvent = self.tableWidgetKeyPressEvent + self.messagelistInbox.keyPressEvent = self.tableWidgetKeyPressEvent self.tableWidgetInboxSubscriptions.keyPressEvent = self.tableWidgetKeyPressEvent self.tableWidgetInboxChans.keyPressEvent = self.tableWidgetKeyPressEvent @@ -535,29 +535,6 @@ class MainWindow(Window): ) def updateUnreadStatus(self, widget, row, msgid, unread=True): - """ - Switch unread for item of msgid and related items in - other STableWidgets "All Accounts" and "Chans" - """ - related = [self.tableWidgetInbox, self.tableWidgetInboxChans] - try: - related.remove(widget) - related = related.pop() - except ValueError: - rrow = None - related = [] - else: - # maybe use instead: - # rrow = related.row(msgid), msgid should be QTableWidgetItem - # related = related.findItems(msgid, QtCore.Qt.MatchExactly), - # returns an empty list - for rrow in xrange(related.rowCount()): - if msgid == str(related.item(rrow, 3).data( - QtCore.Qt.UserRole).toPyObject()): - break - else: - rrow = None - status = widget.item(row, 0).unread if status == unread: font = QtGui.QFont() @@ -565,15 +542,7 @@ class MainWindow(Window): widget.item(row, 3).setFont(font) for col in (0, 1, 2): widget.item(row, col).setUnread(not status) - - try: - related.item(rrow, 3).setFont(font) - except (TypeError, AttributeError): - pass - else: - for col in (0, 1, 2): - related.item(rrow, col).setUnread(not status) - + def propagateUnreadCount(self, address = None, folder = "inbox", widget = None, type = 1): widgets = [self.treeWidgetYourIdentities, self.treeWidgetSubscriptions, self.treeWidgetChans] queryReturn = sqlQuery("SELECT toaddress, folder, COUNT(msgid) AS cnt FROM inbox WHERE read = 0 GROUP BY toaddress, folder") @@ -1348,7 +1317,8 @@ class MainWindow(Window): def updateSentItemStatusByAckdata(self, ackdata, textToDisplay): if type(ackdata) is str: ackdata = QtCore.QByteArray(ackdata) - for sent in [self.tableWidgetInbox, self.tableWidgetInboxSubscriptions, self.tableWidgetInboxChans]: + for sent in ( + self.tableWidgetInboxSubscriptions, self.tableWidgetInboxChans): treeWidget = self.widgetConvert(sent) if self.getCurrentFolder(treeWidget) != "sent": continue @@ -1372,10 +1342,10 @@ class MainWindow(Window): sent.item(i, 3).setText(textToDisplay) def removeInboxRowByMsgid(self, msgid): # msgid and inventoryHash are the same thing - for inbox in ([ - self.tableWidgetInbox, + for inbox in ( self.tableWidgetInboxSubscriptions, - self.tableWidgetInboxChans]): + self.tableWidgetInboxChans + ): for i in range(inbox.rowCount()): if msgid == str(inbox.item(i, 3).data(QtCore.Qt.UserRole).toPyObject()): self.updateStatusBar( @@ -1391,8 +1361,7 @@ class MainWindow(Window): "MainWindow", "New version of PyBitmessage is available: %1. Download it" " from https://github.com/Bitmessage/PyBitmessage/releases/latest" - ).arg(self.notifiedNewVersion) - ) + ).arg(self.notifiedNewVersion)) def displayAlert(self, title, text, exitAfterUserClicksOk): self.updateStatusBar(text) @@ -1401,17 +1370,17 @@ class MainWindow(Window): os._exit(0) def rerenderMessagelistFromLabels(self): - for messagelist in (self.tableWidgetInbox, self.tableWidgetInboxChans, self.tableWidgetInboxSubscriptions): + for messagelist in (self.tableWidgetInboxChans, self.tableWidgetInboxSubscriptions): for i in range(messagelist.rowCount()): messagelist.item(i, 1).setLabel() def rerenderMessagelistToLabels(self): - for messagelist in (self.tableWidgetInbox, self.tableWidgetInboxChans, self.tableWidgetInboxSubscriptions): + for messagelist in (self.tableWidgetInboxChans, self.tableWidgetInboxSubscriptions): for i in range(messagelist.rowCount()): messagelist.item(i, 0).setLabel() def rerenderAddressBook(self): - def addRow (address, label, type): + def addRow(address, label, type): self.tableWidgetAddressBook.insertRow(0) newItem = Ui_AddressBookWidgetItemLabel(address, unicode(label, 'utf-8'), type) self.tableWidgetAddressBook.setItem(0, 0, newItem) @@ -2876,20 +2845,18 @@ class MainWindow(Window): self.treeWidgetSubscriptions.mapToGlobal(point)) def widgetConvert(self, widget): - if widget == self.tableWidgetInbox: - return self.treeWidgetYourIdentities - elif widget == self.tableWidgetInboxSubscriptions: + # if widget == self.tableWidgetInbox: + # return self.treeWidgetYourIdentities + if widget == self.tableWidgetInboxSubscriptions: return self.treeWidgetSubscriptions elif widget == self.tableWidgetInboxChans: return self.treeWidgetChans elif widget == self.treeWidgetYourIdentities: - return self.tableWidgetInbox + return self.messagelistInbox elif widget == self.treeWidgetSubscriptions: return self.tableWidgetInboxSubscriptions elif widget == self.treeWidgetChans: return self.tableWidgetInboxChans - else: - return None def getCurrentTreeWidget(self): currentIndex = self.tabWidget.currentIndex() @@ -2917,17 +2884,15 @@ class MainWindow(Window): def getCurrentMessagelist(self): currentIndex = self.tabWidget.currentIndex(); - messagelistList = [ - self.tableWidgetInbox, - False, + messagelistList = ( self.tableWidgetInboxSubscriptions, self.tableWidgetInboxChans, - ] - if currentIndex >= 0 and currentIndex < len(messagelistList): - return messagelistList[currentIndex] + ) + if currentIndex >= 2 and currentIndex - 2 < len(messagelistList): + return messagelistList[currentIndex - 2] else: return False - + def getAccountMessagelist(self, account): try: if account.type == AccountMixin.CHAN: @@ -3494,6 +3459,12 @@ class MainWindow(Window): messageTextedit.setTextColor(QtGui.QColor()) messageTextedit.setContent(message) + def messagelistSelect(self, msg): + messageTextedit = self.getCurrentMessageTextedit() + if not messageTextedit: + return + messageTextedit.setContent(msg) + def tableWidgetAddressBookItemChanged(self, item): if item.type == AccountMixin.CHAN: self.rerenderComboBoxSendFrom() diff --git a/src/bitmessageqt/main.ui b/src/bitmessageqt/main.ui index 01516539..62657030 100644 --- a/src/bitmessageqt/main.ui +++ b/src/bitmessageqt/main.ui @@ -178,7 +178,7 @@ - + Qt::CustomContextMenu @@ -224,26 +224,6 @@ 26 - - - To - - - - - From - - - - - Subject - - - - - Received - - @@ -1604,6 +1584,11 @@ p, li { white-space: pre-wrap; } QTableWidget
bitmessageqt.settingsmixin
+ + InboxMessagelist + QTableView +
bitmessageqt.messagelist
+
SSplitter QSplitter @@ -1617,7 +1602,7 @@ p, li { white-space: pre-wrap; } - tableWidgetInbox + messagelistInbox textEditInboxMessage comboBoxSendFrom lineEditTo @@ -1919,7 +1904,7 @@ p, li { white-space: pre-wrap; } - tableWidgetInbox + messagelistInbox customContextMenuRequested(QPoint) MainWindow on_context_menuInbox() @@ -2783,10 +2768,10 @@ p, li { white-space: pre-wrap; } - tableWidgetInbox - itemSelectionChanged() + messagelistInbox + messageSelected(QString) MainWindow - tableWidgetInboxItemClicked + messagelistSelect 20 diff --git a/src/bitmessageqt/messagelist.py b/src/bitmessageqt/messagelist.py new file mode 100644 index 00000000..e5d95491 --- /dev/null +++ b/src/bitmessageqt/messagelist.py @@ -0,0 +1,113 @@ +from PyQt4 import QtCore, QtGui + +from debug import logger +from helper_sql import sqlQuery, sqlExecute +from tr import _translate + + +class InboxFilter(dict): + def __init__(self, *args, **kwargs): + self.fields = kwargs.pop('fields') + super(InboxFilter, self).__init__(*args, **kwargs) + + def __str__(self): + terms = ' AND '.join([ + '%s = %r' % (key, val) + for key, val in self.iteritems() + if key in self.fields + ]) + + return 'WHERE %s' % terms if terms else '' + + +class InboxTableItem(QtCore.QAbstractItemModel): + pass + + +class InboxTableModel(QtCore.QAbstractTableModel): + fields = ( + 'msgid', 'toaddress', 'fromaddress', 'subject', 'received', 'read') + header = ( + {'field': 'fromaddress', + 'label': _translate("MainWindow", "From")}, + {'field': 'subject', + 'label': _translate("MainWindow", "Subject")}, + {'field': 'received', + 'label': _translate("MainWindow", "Received")} + ) + attributes = ('msgid', 'read') + table = 'inbox' + + def __init__(self, parent=None): + super(InboxTableModel, self).__init__() + self.filter = InboxFilter(fields=self.fields) + self.fields = ','.join(self.fields) + 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(): + return 0 + return self.column_count + + def rowCount(self, parent=QtCore.QModelIndex()): + if parent.isValid(): + return 0 + return sqlQuery('%s %s' % (self.query, self.filter) % 'COUNT(*)')[0][0] + + def data(self, index, role=QtCore.Qt.DisplayRole): + if role == QtCore.Qt.FontRole: + font = QtGui.QFont() + font.setBold( + not sqlQuery( + '%s %s %s' % (self.query, self.filter, self.sort) % 'read' + )[index.row()][0] + ) + return font + if not index.isValid() or role not in ( + QtCore.Qt.DisplayRole, QtCore.Qt.ToolTipRole + ): + return QtCore.QVariant() + + try: + column = self.header[index.column()]['field'] + except IndexError: + # virtual columns: 3 - msgid, 4 - read + column = self.attributes[index.column() - len(self.header)] + + return sqlQuery( + '%s %s %s' % (self.query, self.filter, self.sort) % column + )[index.row()][0] + + def headerData(self, column, orientation, role=QtCore.Qt.DisplayRole): + if orientation == QtCore.Qt.Vertical: + return + if role == QtCore.Qt.DisplayRole: + return self.header[column]['label'] + + def setRead(self, row, read=True): + msgid = self.data(self.createIndex(row, 3)) + sqlExecute('UPDATE inbox SET read = ? WHERE msgid = ?', read, msgid) + + def getMessage(self, row): + msgid = self.data(self.createIndex(row, 3)) + logger.debug('Selected msgid: %r' % msgid) + return sqlQuery( + 'SELECT message FROM inbox WHERE msgid = ?', msgid + )[0][0] + + +class InboxMessagelist(QtGui.QTableView): + def __init__(self, parent=None): + super(InboxMessagelist, self).__init__(parent) + self.setModel(InboxTableModel()) + + def currentChanged(self, cur_id, prev_id): + row = cur_id.row() + if row == prev_id.row(): + return + self.model().setRead(row) + msg = self.model().getMessage(row) + self.emit(QtCore.SIGNAL("messageSelected(QString)"), msg)