|
|
|
@ -4,6 +4,7 @@ PyQt based UI for bitmessage, the main module
|
|
|
|
|
|
|
|
|
|
import hashlib
|
|
|
|
|
import locale
|
|
|
|
|
import logging
|
|
|
|
|
import os
|
|
|
|
|
import random
|
|
|
|
|
import string
|
|
|
|
@ -15,52 +16,52 @@ import time
|
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
|
from sqlite3 import register_adapter
|
|
|
|
|
|
|
|
|
|
from PyQt4 import QtCore, QtGui
|
|
|
|
|
from PyQt4.QtNetwork import QLocalSocket, QLocalServer
|
|
|
|
|
from qtpy import QtCore, QtGui, QtWidgets, QtNetwork
|
|
|
|
|
|
|
|
|
|
# This is needed for tray icon
|
|
|
|
|
import bitmessage_icons_rc # noqa:F401 pylint: disable=unused-import
|
|
|
|
|
import dialogs
|
|
|
|
|
import helper_addressbook
|
|
|
|
|
import helper_search
|
|
|
|
|
import helper_sent
|
|
|
|
|
import l10n
|
|
|
|
|
import namecoin
|
|
|
|
|
import paths
|
|
|
|
|
import queues
|
|
|
|
|
import settingsmixin
|
|
|
|
|
import shared
|
|
|
|
|
import shutdown
|
|
|
|
|
import sound
|
|
|
|
|
import state
|
|
|
|
|
from debug import logger
|
|
|
|
|
from tr import _translate
|
|
|
|
|
import support
|
|
|
|
|
from account import (
|
|
|
|
|
getSortedAccounts, getSortedSubscriptions, accountClass, BMAccount,
|
|
|
|
|
GatewayAccount, MailchuckAccount, AccountColor)
|
|
|
|
|
from addresses import decodeAddress, addBMIfNotPresent
|
|
|
|
|
from bitmessageui import Ui_MainWindow
|
|
|
|
|
from bmconfigparser import BMConfigParser
|
|
|
|
|
import namecoin
|
|
|
|
|
from messageview import MessageView
|
|
|
|
|
from migrationwizard import Ui_MigrationWizard
|
|
|
|
|
from foldertree import (
|
|
|
|
|
AccountMixin, Ui_FolderWidget, Ui_AddressWidget, Ui_SubscriptionWidget,
|
|
|
|
|
MessageList_AddressWidget, MessageList_SubjectWidget,
|
|
|
|
|
Ui_AddressBookWidgetItemLabel, Ui_AddressBookWidgetItemAddress,
|
|
|
|
|
MessageList_TimeWidget)
|
|
|
|
|
import settingsmixin
|
|
|
|
|
import support
|
|
|
|
|
from helper_sql import sqlQuery, sqlExecute, sqlExecuteChunked, sqlStoredProcedure
|
|
|
|
|
import helper_addressbook
|
|
|
|
|
import helper_search
|
|
|
|
|
import l10n
|
|
|
|
|
from utils import str_broadcast_subscribers, avatarize
|
|
|
|
|
from account import (
|
|
|
|
|
getSortedAccounts, getSortedSubscriptions, accountClass, BMAccount,
|
|
|
|
|
GatewayAccount, MailchuckAccount, AccountColor)
|
|
|
|
|
import dialogs
|
|
|
|
|
from helper_sql import (
|
|
|
|
|
sqlQuery, sqlExecute, sqlExecuteChunked, sqlStoredProcedure)
|
|
|
|
|
from messageview import MessageView
|
|
|
|
|
from network.stats import pendingDownload, pendingUpload
|
|
|
|
|
from uisignaler import UISignaler
|
|
|
|
|
import paths
|
|
|
|
|
from proofofwork import getPowType
|
|
|
|
|
import queues
|
|
|
|
|
import shutdown
|
|
|
|
|
from statusbar import BMStatusBar
|
|
|
|
|
import sound
|
|
|
|
|
# This is needed for tray icon
|
|
|
|
|
import bitmessage_icons_rc # noqa:F401 pylint: disable=unused-import
|
|
|
|
|
import helper_sent
|
|
|
|
|
from tr import _translate
|
|
|
|
|
from uisignaler import UISignaler
|
|
|
|
|
from utils import str_broadcast_subscribers, avatarize
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from plugins.plugin import get_plugin, get_plugins
|
|
|
|
|
except ImportError:
|
|
|
|
|
get_plugins = False
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger('default')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: rewrite
|
|
|
|
|
def powQueueSize():
|
|
|
|
@ -99,12 +100,12 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
newlocale = l10n.getTranslationLanguage()
|
|
|
|
|
try:
|
|
|
|
|
if not self.qmytranslator.isEmpty():
|
|
|
|
|
QtGui.QApplication.removeTranslator(self.qmytranslator)
|
|
|
|
|
QtWidgets.QApplication.removeTranslator(self.qmytranslator)
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
try:
|
|
|
|
|
if not self.qsystranslator.isEmpty():
|
|
|
|
|
QtGui.QApplication.removeTranslator(self.qsystranslator)
|
|
|
|
|
QtWidgets.QApplication.removeTranslator(self.qsystranslator)
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
@ -112,7 +113,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
translationpath = os.path.join(
|
|
|
|
|
paths.codePath(), 'translations', 'bitmessage_' + newlocale)
|
|
|
|
|
self.qmytranslator.load(translationpath)
|
|
|
|
|
QtGui.QApplication.installTranslator(self.qmytranslator)
|
|
|
|
|
QtWidgets.QApplication.installTranslator(self.qmytranslator)
|
|
|
|
|
|
|
|
|
|
self.qsystranslator = QtCore.QTranslator()
|
|
|
|
|
if paths.frozen:
|
|
|
|
@ -123,7 +124,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
str(QtCore.QLibraryInfo.location(
|
|
|
|
|
QtCore.QLibraryInfo.TranslationsPath)), 'qt_' + newlocale)
|
|
|
|
|
self.qsystranslator.load(translationpath)
|
|
|
|
|
QtGui.QApplication.installTranslator(self.qsystranslator)
|
|
|
|
|
QtWidgets.QApplication.installTranslator(self.qsystranslator)
|
|
|
|
|
|
|
|
|
|
lang = locale.normalize(l10n.getTranslationLanguage())
|
|
|
|
|
langs = [
|
|
|
|
@ -146,49 +147,35 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
logger.error("Failed to set locale to %s", lang, exc_info=True)
|
|
|
|
|
|
|
|
|
|
def init_file_menu(self):
|
|
|
|
|
QtCore.QObject.connect(self.ui.actionExit, QtCore.SIGNAL(
|
|
|
|
|
"triggered()"), self.quit)
|
|
|
|
|
QtCore.QObject.connect(self.ui.actionNetworkSwitch, QtCore.SIGNAL(
|
|
|
|
|
"triggered()"), self.network_switch)
|
|
|
|
|
QtCore.QObject.connect(self.ui.actionManageKeys, QtCore.SIGNAL(
|
|
|
|
|
"triggered()"), self.click_actionManageKeys)
|
|
|
|
|
QtCore.QObject.connect(self.ui.actionDeleteAllTrashedMessages,
|
|
|
|
|
QtCore.SIGNAL(
|
|
|
|
|
"triggered()"),
|
|
|
|
|
self.click_actionDeleteAllTrashedMessages)
|
|
|
|
|
QtCore.QObject.connect(self.ui.actionRegenerateDeterministicAddresses,
|
|
|
|
|
QtCore.SIGNAL(
|
|
|
|
|
"triggered()"),
|
|
|
|
|
self.click_actionRegenerateDeterministicAddresses)
|
|
|
|
|
QtCore.QObject.connect(self.ui.pushButtonAddChan, QtCore.SIGNAL(
|
|
|
|
|
"clicked()"),
|
|
|
|
|
self.click_actionJoinChan) # also used for creating chans.
|
|
|
|
|
QtCore.QObject.connect(self.ui.pushButtonNewAddress, QtCore.SIGNAL(
|
|
|
|
|
"clicked()"), self.click_NewAddressDialog)
|
|
|
|
|
QtCore.QObject.connect(self.ui.pushButtonAddAddressBook, QtCore.SIGNAL(
|
|
|
|
|
"clicked()"), self.click_pushButtonAddAddressBook)
|
|
|
|
|
QtCore.QObject.connect(self.ui.pushButtonAddSubscription, QtCore.SIGNAL(
|
|
|
|
|
"clicked()"), self.click_pushButtonAddSubscription)
|
|
|
|
|
QtCore.QObject.connect(self.ui.pushButtonTTL, QtCore.SIGNAL(
|
|
|
|
|
"clicked()"), self.click_pushButtonTTL)
|
|
|
|
|
QtCore.QObject.connect(self.ui.pushButtonClear, QtCore.SIGNAL(
|
|
|
|
|
"clicked()"), self.click_pushButtonClear)
|
|
|
|
|
QtCore.QObject.connect(self.ui.pushButtonSend, QtCore.SIGNAL(
|
|
|
|
|
"clicked()"), self.click_pushButtonSend)
|
|
|
|
|
QtCore.QObject.connect(self.ui.pushButtonFetchNamecoinID, QtCore.SIGNAL(
|
|
|
|
|
"clicked()"), self.click_pushButtonFetchNamecoinID)
|
|
|
|
|
QtCore.QObject.connect(self.ui.actionSettings, QtCore.SIGNAL(
|
|
|
|
|
"triggered()"), self.click_actionSettings)
|
|
|
|
|
QtCore.QObject.connect(self.ui.actionAbout, QtCore.SIGNAL(
|
|
|
|
|
"triggered()"), self.click_actionAbout)
|
|
|
|
|
QtCore.QObject.connect(self.ui.actionSupport, QtCore.SIGNAL(
|
|
|
|
|
"triggered()"), self.click_actionSupport)
|
|
|
|
|
QtCore.QObject.connect(self.ui.actionHelp, QtCore.SIGNAL(
|
|
|
|
|
"triggered()"), self.click_actionHelp)
|
|
|
|
|
self.ui.actionExit.triggered.connect(self.quit)
|
|
|
|
|
self.ui.actionNetworkSwitch.triggered.connect(self.network_switch)
|
|
|
|
|
self.ui.actionManageKeys.triggered.connect(self.click_actionManageKeys)
|
|
|
|
|
self.ui.actionDeleteAllTrashedMessages.triggered.connect(
|
|
|
|
|
self.click_actionDeleteAllTrashedMessages)
|
|
|
|
|
self.ui.actionRegenerateDeterministicAddresses.triggered.connect(
|
|
|
|
|
self.click_actionRegenerateDeterministicAddresses)
|
|
|
|
|
self.ui.actionSettings.triggered.connect(self.click_actionSettings)
|
|
|
|
|
self.ui.actionAbout.triggered.connect(self.click_actionAbout)
|
|
|
|
|
self.ui.actionSupport.triggered.connect(self.click_actionSupport)
|
|
|
|
|
self.ui.actionHelp.triggered.connect(self.click_actionHelp)
|
|
|
|
|
|
|
|
|
|
# also used for creating chans.
|
|
|
|
|
self.ui.pushButtonAddChan.clicked.connect(self.click_actionJoinChan)
|
|
|
|
|
self.ui.pushButtonNewAddress.clicked.connect(
|
|
|
|
|
self.click_NewAddressDialog)
|
|
|
|
|
self.ui.pushButtonAddAddressBook.clicked.connect(
|
|
|
|
|
self.click_pushButtonAddAddressBook)
|
|
|
|
|
self.ui.pushButtonAddSubscription.clicked.connect(
|
|
|
|
|
self.click_pushButtonAddSubscription)
|
|
|
|
|
self.ui.pushButtonTTL.clicked.connect(self.click_pushButtonTTL)
|
|
|
|
|
self.ui.pushButtonClear.clicked.connect(self.click_pushButtonClear)
|
|
|
|
|
self.ui.pushButtonSend.clicked.connect(self.click_pushButtonSend)
|
|
|
|
|
self.ui.pushButtonFetchNamecoinID.clicked.connect(
|
|
|
|
|
self.click_pushButtonFetchNamecoinID)
|
|
|
|
|
|
|
|
|
|
def init_inbox_popup_menu(self, connectSignal=True):
|
|
|
|
|
# Popup menu for the Inbox tab
|
|
|
|
|
self.ui.inboxContextMenuToolbar = QtGui.QToolBar()
|
|
|
|
|
self.ui.inboxContextMenuToolbar = QtWidgets.QToolBar()
|
|
|
|
|
# Actions
|
|
|
|
|
self.actionReply = self.ui.inboxContextMenuToolbar.addAction(_translate(
|
|
|
|
|
"MainWindow", "Reply to sender"), self.on_action_InboxReply)
|
|
|
|
@ -224,25 +211,22 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
self.ui.tableWidgetInbox.setContextMenuPolicy(
|
|
|
|
|
QtCore.Qt.CustomContextMenu)
|
|
|
|
|
if connectSignal:
|
|
|
|
|
self.connect(self.ui.tableWidgetInbox, QtCore.SIGNAL(
|
|
|
|
|
'customContextMenuRequested(const QPoint&)'),
|
|
|
|
|
self.ui.tableWidgetInbox.customContextMenuRequested.connect(
|
|
|
|
|
self.on_context_menuInbox)
|
|
|
|
|
self.ui.tableWidgetInboxSubscriptions.setContextMenuPolicy(
|
|
|
|
|
QtCore.Qt.CustomContextMenu)
|
|
|
|
|
if connectSignal:
|
|
|
|
|
self.connect(self.ui.tableWidgetInboxSubscriptions, QtCore.SIGNAL(
|
|
|
|
|
'customContextMenuRequested(const QPoint&)'),
|
|
|
|
|
self.ui.tableWidgetInboxSubscriptions.customContextMenuRequested.connect(
|
|
|
|
|
self.on_context_menuInbox)
|
|
|
|
|
self.ui.tableWidgetInboxChans.setContextMenuPolicy(
|
|
|
|
|
QtCore.Qt.CustomContextMenu)
|
|
|
|
|
if connectSignal:
|
|
|
|
|
self.connect(self.ui.tableWidgetInboxChans, QtCore.SIGNAL(
|
|
|
|
|
'customContextMenuRequested(const QPoint&)'),
|
|
|
|
|
self.ui.tableWidgetInboxChans.customContextMenuRequested.connect(
|
|
|
|
|
self.on_context_menuInbox)
|
|
|
|
|
|
|
|
|
|
def init_identities_popup_menu(self, connectSignal=True):
|
|
|
|
|
# Popup menu for the Your Identities tab
|
|
|
|
|
self.ui.addressContextMenuToolbarYourIdentities = QtGui.QToolBar()
|
|
|
|
|
self.ui.addressContextMenuToolbarYourIdentities = QtWidgets.QToolBar()
|
|
|
|
|
# Actions
|
|
|
|
|
self.actionNewYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction(_translate(
|
|
|
|
|
"MainWindow", "New"), self.on_action_YourIdentitiesNew)
|
|
|
|
@ -276,8 +260,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
self.ui.treeWidgetYourIdentities.setContextMenuPolicy(
|
|
|
|
|
QtCore.Qt.CustomContextMenu)
|
|
|
|
|
if connectSignal:
|
|
|
|
|
self.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL(
|
|
|
|
|
'customContextMenuRequested(const QPoint&)'),
|
|
|
|
|
self.ui.treeWidgetYourIdentities.customContextMenuRequested.connect(
|
|
|
|
|
self.on_context_menuYourIdentities)
|
|
|
|
|
|
|
|
|
|
# load all gui.menu plugins with prefix 'address'
|
|
|
|
@ -326,13 +309,12 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
self.ui.treeWidgetChans.setContextMenuPolicy(
|
|
|
|
|
QtCore.Qt.CustomContextMenu)
|
|
|
|
|
if connectSignal:
|
|
|
|
|
self.connect(self.ui.treeWidgetChans, QtCore.SIGNAL(
|
|
|
|
|
'customContextMenuRequested(const QPoint&)'),
|
|
|
|
|
self.ui.treeWidgetChans.customContextMenuRequested.connect(
|
|
|
|
|
self.on_context_menuChan)
|
|
|
|
|
|
|
|
|
|
def init_addressbook_popup_menu(self, connectSignal=True):
|
|
|
|
|
# Popup menu for the Address Book page
|
|
|
|
|
self.ui.addressBookContextMenuToolbar = QtGui.QToolBar()
|
|
|
|
|
self.ui.addressBookContextMenuToolbar = QtWidgets.QToolBar()
|
|
|
|
|
# Actions
|
|
|
|
|
self.actionAddressBookSend = self.ui.addressBookContextMenuToolbar.addAction(
|
|
|
|
|
_translate(
|
|
|
|
@ -363,8 +345,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
self.ui.tableWidgetAddressBook.setContextMenuPolicy(
|
|
|
|
|
QtCore.Qt.CustomContextMenu)
|
|
|
|
|
if connectSignal:
|
|
|
|
|
self.connect(self.ui.tableWidgetAddressBook, QtCore.SIGNAL(
|
|
|
|
|
'customContextMenuRequested(const QPoint&)'),
|
|
|
|
|
self.ui.tableWidgetAddressBook.customContextMenuRequested.connect(
|
|
|
|
|
self.on_context_menuAddressBook)
|
|
|
|
|
|
|
|
|
|
def init_subscriptions_popup_menu(self, connectSignal=True):
|
|
|
|
@ -392,8 +373,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
self.ui.treeWidgetSubscriptions.setContextMenuPolicy(
|
|
|
|
|
QtCore.Qt.CustomContextMenu)
|
|
|
|
|
if connectSignal:
|
|
|
|
|
self.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL(
|
|
|
|
|
'customContextMenuRequested(const QPoint&)'),
|
|
|
|
|
self.ui.treeWidgetSubscriptions.customContextMenuRequested.connect(
|
|
|
|
|
self.on_context_menuSubscriptions)
|
|
|
|
|
|
|
|
|
|
def init_sent_popup_menu(self, connectSignal=True):
|
|
|
|
@ -411,7 +391,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
self.actionSentReply = self.ui.sentContextMenuToolbar.addAction(
|
|
|
|
|
_translate("MainWindow", "Send update"),
|
|
|
|
|
self.on_action_SentReply)
|
|
|
|
|
# self.popMenuSent = QtGui.QMenu( self )
|
|
|
|
|
# self.popMenuSent = QtWidgets.QMenu( self )
|
|
|
|
|
# self.popMenuSent.addAction( self.actionSentClipboard )
|
|
|
|
|
# self.popMenuSent.addAction( self.actionTrashSentMessage )
|
|
|
|
|
|
|
|
|
@ -435,7 +415,6 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
if treeWidget.isSortingEnabled():
|
|
|
|
|
treeWidget.setSortingEnabled(False)
|
|
|
|
|
|
|
|
|
|
widgets = {}
|
|
|
|
|
i = 0
|
|
|
|
|
while i < treeWidget.topLevelItemCount():
|
|
|
|
|
widget = treeWidget.topLevelItem(i)
|
|
|
|
@ -453,7 +432,8 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
while j < widget.childCount():
|
|
|
|
|
subwidget = widget.child(j)
|
|
|
|
|
try:
|
|
|
|
|
subwidget.setUnreadCount(db[toAddress][subwidget.folderName]['count'])
|
|
|
|
|
subwidget.setUnreadCount(
|
|
|
|
|
db[toAddress][subwidget.folderName]['count'])
|
|
|
|
|
unread += db[toAddress][subwidget.folderName]['count']
|
|
|
|
|
db[toAddress].pop(subwidget.folderName, None)
|
|
|
|
|
except:
|
|
|
|
@ -467,7 +447,8 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
j = 0
|
|
|
|
|
for f, c in db[toAddress].iteritems():
|
|
|
|
|
try:
|
|
|
|
|
subwidget = Ui_FolderWidget(widget, j, toAddress, f, c['count'])
|
|
|
|
|
subwidget = Ui_FolderWidget(
|
|
|
|
|
widget, j, toAddress, f, c['count'])
|
|
|
|
|
except KeyError:
|
|
|
|
|
subwidget = Ui_FolderWidget(widget, j, toAddress, f, 0)
|
|
|
|
|
j += 1
|
|
|
|
@ -477,15 +458,21 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
|
|
|
|
|
i = 0
|
|
|
|
|
for toAddress in db:
|
|
|
|
|
widget = Ui_SubscriptionWidget(treeWidget, i, toAddress, db[toAddress]["inbox"]['count'], db[toAddress]["inbox"]['label'], db[toAddress]["inbox"]['enabled'])
|
|
|
|
|
widget = Ui_SubscriptionWidget(
|
|
|
|
|
treeWidget, i, toAddress, db[toAddress]["inbox"]['count'],
|
|
|
|
|
db[toAddress]["inbox"]['label'],
|
|
|
|
|
db[toAddress]["inbox"]['enabled'])
|
|
|
|
|
j = 0
|
|
|
|
|
unread = 0
|
|
|
|
|
for folder in folders:
|
|
|
|
|
try:
|
|
|
|
|
subwidget = Ui_FolderWidget(widget, j, toAddress, folder, db[toAddress][folder]['count'])
|
|
|
|
|
subwidget = Ui_FolderWidget(
|
|
|
|
|
widget, j, toAddress, folder,
|
|
|
|
|
db[toAddress][folder]['count'])
|
|
|
|
|
unread += db[toAddress][folder]['count']
|
|
|
|
|
except KeyError:
|
|
|
|
|
subwidget = Ui_FolderWidget(widget, j, toAddress, folder, 0)
|
|
|
|
|
subwidget = Ui_FolderWidget(
|
|
|
|
|
widget, j, toAddress, folder, 0)
|
|
|
|
|
j += 1
|
|
|
|
|
widget.setUnreadCount(unread)
|
|
|
|
|
i += 1
|
|
|
|
@ -518,8 +505,8 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
toAddress, 'enabled')
|
|
|
|
|
isChan = BMConfigParser().safeGetBoolean(
|
|
|
|
|
toAddress, 'chan')
|
|
|
|
|
isMaillinglist = BMConfigParser().safeGetBoolean(
|
|
|
|
|
toAddress, 'mailinglist')
|
|
|
|
|
# isMaillinglist = BMConfigParser().safeGetBoolean(
|
|
|
|
|
# toAddress, 'mailinglist')
|
|
|
|
|
|
|
|
|
|
if treeWidget == self.ui.treeWidgetYourIdentities:
|
|
|
|
|
if isChan:
|
|
|
|
@ -553,7 +540,6 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
if treeWidget.isSortingEnabled():
|
|
|
|
|
treeWidget.setSortingEnabled(False)
|
|
|
|
|
|
|
|
|
|
widgets = {}
|
|
|
|
|
i = 0
|
|
|
|
|
while i < treeWidget.topLevelItemCount():
|
|
|
|
|
widget = treeWidget.topLevelItem(i)
|
|
|
|
@ -614,7 +600,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
treeWidget.setSortingEnabled(True)
|
|
|
|
|
|
|
|
|
|
def __init__(self, parent=None):
|
|
|
|
|
QtGui.QWidget.__init__(self, parent)
|
|
|
|
|
super(MyForm, self).__init__(parent)
|
|
|
|
|
self.ui = Ui_MainWindow()
|
|
|
|
|
self.ui.setupUi(self)
|
|
|
|
|
|
|
|
|
@ -632,11 +618,13 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
addressInKeysFile)
|
|
|
|
|
if addressVersionNumber == 1:
|
|
|
|
|
displayMsg = _translate(
|
|
|
|
|
"MainWindow", "One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. "
|
|
|
|
|
+ "May we delete it now?").arg(addressInKeysFile)
|
|
|
|
|
reply = QtGui.QMessageBox.question(
|
|
|
|
|
self, 'Message', displayMsg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
|
|
|
|
|
if reply == QtGui.QMessageBox.Yes:
|
|
|
|
|
"MainWindow",
|
|
|
|
|
"One of your addresses, {0}, is an old version 1"
|
|
|
|
|
" address. Version 1 addresses are no longer supported."
|
|
|
|
|
" May we delete it now?").format(addressInKeysFile)
|
|
|
|
|
reply = QtWidgets.QMessageBox.question(
|
|
|
|
|
self, 'Message', displayMsg, QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
|
|
|
|
|
if reply == QtWidgets.QMessageBox.Yes:
|
|
|
|
|
BMConfigParser().remove_section(addressInKeysFile)
|
|
|
|
|
BMConfigParser().save()
|
|
|
|
|
|
|
|
|
@ -680,107 +668,97 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
self.rerenderSubscriptions()
|
|
|
|
|
|
|
|
|
|
# Initialize the inbox search
|
|
|
|
|
QtCore.QObject.connect(self.ui.inboxSearchLineEdit, QtCore.SIGNAL(
|
|
|
|
|
"returnPressed()"), self.inboxSearchLineEditReturnPressed)
|
|
|
|
|
QtCore.QObject.connect(self.ui.inboxSearchLineEditSubscriptions, QtCore.SIGNAL(
|
|
|
|
|
"returnPressed()"), self.inboxSearchLineEditReturnPressed)
|
|
|
|
|
QtCore.QObject.connect(self.ui.inboxSearchLineEditChans, QtCore.SIGNAL(
|
|
|
|
|
"returnPressed()"), self.inboxSearchLineEditReturnPressed)
|
|
|
|
|
QtCore.QObject.connect(self.ui.inboxSearchLineEdit, QtCore.SIGNAL(
|
|
|
|
|
"textChanged(QString)"), self.inboxSearchLineEditUpdated)
|
|
|
|
|
QtCore.QObject.connect(self.ui.inboxSearchLineEditSubscriptions, QtCore.SIGNAL(
|
|
|
|
|
"textChanged(QString)"), self.inboxSearchLineEditUpdated)
|
|
|
|
|
QtCore.QObject.connect(self.ui.inboxSearchLineEditChans, QtCore.SIGNAL(
|
|
|
|
|
"textChanged(QString)"), self.inboxSearchLineEditUpdated)
|
|
|
|
|
for line_edit in (
|
|
|
|
|
self.ui.inboxSearchLineEdit,
|
|
|
|
|
self.ui.inboxSearchLineEditSubscriptions,
|
|
|
|
|
self.ui.inboxSearchLineEditChans,
|
|
|
|
|
):
|
|
|
|
|
line_edit.returnPressed.connect(
|
|
|
|
|
self.inboxSearchLineEditReturnPressed)
|
|
|
|
|
line_edit.textChanged.connect(
|
|
|
|
|
self.inboxSearchLineEditUpdated)
|
|
|
|
|
|
|
|
|
|
# Initialize addressbook
|
|
|
|
|
QtCore.QObject.connect(self.ui.tableWidgetAddressBook, QtCore.SIGNAL(
|
|
|
|
|
"itemChanged(QTableWidgetItem *)"), self.tableWidgetAddressBookItemChanged)
|
|
|
|
|
self.ui.tableWidgetAddressBook.itemChanged.connect(
|
|
|
|
|
self.tableWidgetAddressBookItemChanged)
|
|
|
|
|
|
|
|
|
|
# This is necessary for the completer to work if multiple recipients
|
|
|
|
|
QtCore.QObject.connect(self.ui.lineEditTo, QtCore.SIGNAL(
|
|
|
|
|
"cursorPositionChanged(int, int)"), self.ui.lineEditTo.completer().onCursorPositionChanged)
|
|
|
|
|
self.ui.lineEditTo.cursorPositionChanged.connect(
|
|
|
|
|
self.ui.lineEditTo.completer().onCursorPositionChanged)
|
|
|
|
|
|
|
|
|
|
# show messages from message list
|
|
|
|
|
QtCore.QObject.connect(self.ui.tableWidgetInbox, QtCore.SIGNAL(
|
|
|
|
|
"itemSelectionChanged ()"), self.tableWidgetInboxItemClicked)
|
|
|
|
|
QtCore.QObject.connect(self.ui.tableWidgetInboxSubscriptions, QtCore.SIGNAL(
|
|
|
|
|
"itemSelectionChanged ()"), self.tableWidgetInboxItemClicked)
|
|
|
|
|
QtCore.QObject.connect(self.ui.tableWidgetInboxChans, QtCore.SIGNAL(
|
|
|
|
|
"itemSelectionChanged ()"), self.tableWidgetInboxItemClicked)
|
|
|
|
|
for table_widget in (
|
|
|
|
|
self.ui.tableWidgetInbox,
|
|
|
|
|
self.ui.tableWidgetInboxSubscriptions,
|
|
|
|
|
self.ui.tableWidgetInboxChans
|
|
|
|
|
):
|
|
|
|
|
table_widget.itemSelectionChanged.connect(
|
|
|
|
|
self.tableWidgetInboxItemClicked)
|
|
|
|
|
|
|
|
|
|
# tree address lists
|
|
|
|
|
QtCore.QObject.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL(
|
|
|
|
|
"itemSelectionChanged ()"), self.treeWidgetItemClicked)
|
|
|
|
|
QtCore.QObject.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL(
|
|
|
|
|
"itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged)
|
|
|
|
|
QtCore.QObject.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL(
|
|
|
|
|
"itemSelectionChanged ()"), self.treeWidgetItemClicked)
|
|
|
|
|
QtCore.QObject.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL(
|
|
|
|
|
"itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged)
|
|
|
|
|
QtCore.QObject.connect(self.ui.treeWidgetChans, QtCore.SIGNAL(
|
|
|
|
|
"itemSelectionChanged ()"), self.treeWidgetItemClicked)
|
|
|
|
|
QtCore.QObject.connect(self.ui.treeWidgetChans, QtCore.SIGNAL(
|
|
|
|
|
"itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged)
|
|
|
|
|
QtCore.QObject.connect(
|
|
|
|
|
self.ui.tabWidget, QtCore.SIGNAL("currentChanged(int)"),
|
|
|
|
|
self.tabWidgetCurrentChanged
|
|
|
|
|
)
|
|
|
|
|
for tree_widget in (
|
|
|
|
|
self.ui.treeWidgetYourIdentities,
|
|
|
|
|
self.ui.treeWidgetSubscriptions,
|
|
|
|
|
self.ui.treeWidgetChans
|
|
|
|
|
):
|
|
|
|
|
tree_widget.itemSelectionChanged.connect(
|
|
|
|
|
self.treeWidgetItemClicked)
|
|
|
|
|
tree_widget.itemChanged.connect(self.treeWidgetItemChanged)
|
|
|
|
|
|
|
|
|
|
self.ui.tabWidget.currentChanged.connect(self.tabWidgetCurrentChanged)
|
|
|
|
|
|
|
|
|
|
# Put the colored icon on the status bar
|
|
|
|
|
# self.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/yellowicon.png"))
|
|
|
|
|
self.setStatusBar(BMStatusBar())
|
|
|
|
|
self.statusbar = self.statusBar()
|
|
|
|
|
|
|
|
|
|
self.pushButtonStatusIcon = QtGui.QPushButton(self)
|
|
|
|
|
self.pushButtonStatusIcon = QtWidgets.QPushButton(self)
|
|
|
|
|
self.pushButtonStatusIcon.setText('')
|
|
|
|
|
self.pushButtonStatusIcon.setIcon(
|
|
|
|
|
QtGui.QIcon(':/newPrefix/images/redicon.png'))
|
|
|
|
|
self.pushButtonStatusIcon.setFlat(True)
|
|
|
|
|
self.statusbar.insertPermanentWidget(0, self.pushButtonStatusIcon)
|
|
|
|
|
QtCore.QObject.connect(self.pushButtonStatusIcon, QtCore.SIGNAL(
|
|
|
|
|
"clicked()"), self.click_pushButtonStatusIcon)
|
|
|
|
|
self.pushButtonStatusIcon.clicked.connect(
|
|
|
|
|
self.click_pushButtonStatusIcon)
|
|
|
|
|
|
|
|
|
|
self.unreadCount = 0
|
|
|
|
|
|
|
|
|
|
# Set the icon sizes for the identicons
|
|
|
|
|
identicon_size = 3*7
|
|
|
|
|
self.ui.tableWidgetInbox.setIconSize(QtCore.QSize(identicon_size, identicon_size))
|
|
|
|
|
self.ui.treeWidgetChans.setIconSize(QtCore.QSize(identicon_size, identicon_size))
|
|
|
|
|
self.ui.treeWidgetYourIdentities.setIconSize(QtCore.QSize(identicon_size, identicon_size))
|
|
|
|
|
self.ui.treeWidgetSubscriptions.setIconSize(QtCore.QSize(identicon_size, identicon_size))
|
|
|
|
|
self.ui.tableWidgetAddressBook.setIconSize(QtCore.QSize(identicon_size, identicon_size))
|
|
|
|
|
|
|
|
|
|
identicon_size = 3 * 7
|
|
|
|
|
for widget in (
|
|
|
|
|
self.ui.tableWidgetInbox, self.ui.treeWidgetChans,
|
|
|
|
|
self.ui.treeWidgetYourIdentities, self.ui.treeWidgetSubscriptions,
|
|
|
|
|
self.ui.tableWidgetAddressBook
|
|
|
|
|
):
|
|
|
|
|
widget.setIconSize(QtCore.QSize(identicon_size, identicon_size))
|
|
|
|
|
|
|
|
|
|
self.UISignalThread = UISignaler.get()
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"updateSentItemStatusByToAddress(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByToAddress)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByAckdata)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewInboxMessage)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewSentMessage)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"setStatusIcon(PyQt_PyObject)"), self.setStatusIcon)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"changedInboxUnread(PyQt_PyObject)"), self.changedInboxUnread)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"rerenderMessagelistFromLabels()"), self.rerenderMessagelistFromLabels)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"rerenderMessgelistToLabels()"), self.rerenderMessagelistToLabels)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"rerenderAddressBook()"), self.rerenderAddressBook)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"rerenderSubscriptions()"), self.rerenderSubscriptions)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"removeInboxRowByMsgid(PyQt_PyObject)"), self.removeInboxRowByMsgid)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"newVersionAvailable(PyQt_PyObject)"), self.newVersionAvailable)
|
|
|
|
|
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
|
|
|
|
"displayAlert(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayAlert)
|
|
|
|
|
self.UISignalThread.writeNewAddressToTable.connect(
|
|
|
|
|
self.writeNewAddressToTable)
|
|
|
|
|
self.UISignalThread.updateStatusBar.connect(self.updateStatusBar)
|
|
|
|
|
self.UISignalThread.updateSentItemStatusByToAddress.connect(
|
|
|
|
|
self.updateSentItemStatusByToAddress)
|
|
|
|
|
self.UISignalThread.updateSentItemStatusByAckdata.connect(
|
|
|
|
|
self.updateSentItemStatusByAckdata)
|
|
|
|
|
self.UISignalThread.displayNewInboxMessage.connect(
|
|
|
|
|
self.displayNewInboxMessage)
|
|
|
|
|
self.UISignalThread.displayNewSentMessage.connect(
|
|
|
|
|
self.displayNewSentMessage)
|
|
|
|
|
self.UISignalThread.setStatusIcon.connect(self.setStatusIcon)
|
|
|
|
|
self.UISignalThread.changedInboxUnread.connect(self.changedInboxUnread)
|
|
|
|
|
self.UISignalThread.rerenderMessagelistFromLabels.connect(
|
|
|
|
|
self.rerenderMessagelistFromLabels)
|
|
|
|
|
self.UISignalThread.rerenderMessagelistToLabels.connect(
|
|
|
|
|
self.rerenderMessagelistToLabels)
|
|
|
|
|
self.UISignalThread.rerenderAddressBook.connect(
|
|
|
|
|
self.rerenderAddressBook)
|
|
|
|
|
self.UISignalThread.rerenderSubscriptions.connect(
|
|
|
|
|
self.rerenderSubscriptions)
|
|
|
|
|
self.UISignalThread.removeInboxRowByMsgid.connect(
|
|
|
|
|
self.removeInboxRowByMsgid)
|
|
|
|
|
self.UISignalThread.newVersionAvailable.connect(
|
|
|
|
|
self.newVersionAvailable)
|
|
|
|
|
self.UISignalThread.displayAlert.connect(self.displayAlert)
|
|
|
|
|
self.UISignalThread.start()
|
|
|
|
|
|
|
|
|
|
# Key press in tree view
|
|
|
|
@ -809,16 +787,15 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
|
|
|
|
|
# Put the TTL slider in the correct spot
|
|
|
|
|
TTL = BMConfigParser().getint('bitmessagesettings', 'ttl')
|
|
|
|
|
if TTL < 3600: # an hour
|
|
|
|
|
if TTL < 3600: # an hour
|
|
|
|
|
TTL = 3600
|
|
|
|
|
elif TTL > 28*24*60*60: # 28 days
|
|
|
|
|
TTL = 28*24*60*60
|
|
|
|
|
self.ui.horizontalSliderTTL.setSliderPosition((TTL - 3600) ** (1/3.199))
|
|
|
|
|
elif TTL > 28 * 24 * 60 * 60: # 28 days
|
|
|
|
|
TTL = 28 * 24 * 60 * 60
|
|
|
|
|
self.ui.horizontalSliderTTL.setSliderPosition(
|
|
|
|
|
(TTL - 3600) ** (1 / 3.199))
|
|
|
|
|
self.updateHumanFriendlyTTLDescription(TTL)
|
|
|
|
|
|
|
|
|
|
QtCore.QObject.connect(self.ui.horizontalSliderTTL, QtCore.SIGNAL(
|
|
|
|
|
"valueChanged(int)"), self.updateTTL)
|
|
|
|
|
|
|
|
|
|
self.ui.horizontalSliderTTL.valueChanged.connect(self.updateTTL)
|
|
|
|
|
self.initSettings()
|
|
|
|
|
self.resetNamecoinConnection()
|
|
|
|
|
self.sqlInit()
|
|
|
|
@ -873,21 +850,25 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
BMConfigParser().save()
|
|
|
|
|
|
|
|
|
|
def updateHumanFriendlyTTLDescription(self, TTL):
|
|
|
|
|
numberOfHours = int(round(TTL / (60*60)))
|
|
|
|
|
numberOfHours = int(round(TTL / (60 * 60)))
|
|
|
|
|
font = QtGui.QFont()
|
|
|
|
|
stylesheet = ""
|
|
|
|
|
|
|
|
|
|
if numberOfHours < 48:
|
|
|
|
|
self.ui.labelHumanFriendlyTTLDescription.setText(
|
|
|
|
|
_translate("MainWindow", "%n hour(s)", None, QtCore.QCoreApplication.CodecForTr, numberOfHours) +
|
|
|
|
|
", " +
|
|
|
|
|
_translate("MainWindow", "not recommended for chans", None, QtCore.QCoreApplication.CodecForTr)
|
|
|
|
|
)
|
|
|
|
|
_translate(
|
|
|
|
|
"MainWindow", "%n hour(s)", None, numberOfHours
|
|
|
|
|
) + ",\n" +
|
|
|
|
|
_translate("MainWindow", "not recommended for chans")
|
|
|
|
|
)
|
|
|
|
|
stylesheet = "QLabel { color : red; }"
|
|
|
|
|
font.setBold(True)
|
|
|
|
|
else:
|
|
|
|
|
numberOfDays = int(round(TTL / (24*60*60)))
|
|
|
|
|
self.ui.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%n day(s)", None, QtCore.QCoreApplication.CodecForTr, numberOfDays))
|
|
|
|
|
numberOfDays = int(round(TTL / (24 * 60 * 60)))
|
|
|
|
|
self.ui.labelHumanFriendlyTTLDescription.setText(
|
|
|
|
|
_translate(
|
|
|
|
|
"MainWindow", "%n day(s)", None, numberOfDays)
|
|
|
|
|
)
|
|
|
|
|
font.setBold(False)
|
|
|
|
|
self.ui.labelHumanFriendlyTTLDescription.setStyleSheet(stylesheet)
|
|
|
|
|
self.ui.labelHumanFriendlyTTLDescription.setFont(font)
|
|
|
|
@ -1115,20 +1096,19 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
elif status == 'msgsent':
|
|
|
|
|
statusText = _translate(
|
|
|
|
|
"MainWindow",
|
|
|
|
|
"Message sent. Waiting for acknowledgement. Sent at %1"
|
|
|
|
|
).arg(l10n.formatTimestamp(lastactiontime))
|
|
|
|
|
"Message sent. Waiting for acknowledgement. Sent at {0}"
|
|
|
|
|
).format(l10n.formatTimestamp(lastactiontime))
|
|
|
|
|
elif status == 'msgsentnoackexpected':
|
|
|
|
|
statusText = _translate(
|
|
|
|
|
"MainWindow", "Message sent. Sent at %1"
|
|
|
|
|
).arg(l10n.formatTimestamp(lastactiontime))
|
|
|
|
|
"MainWindow", "Message sent. Sent at {0}"
|
|
|
|
|
).format(l10n.formatTimestamp(lastactiontime))
|
|
|
|
|
elif status == 'doingmsgpow':
|
|
|
|
|
statusText = _translate(
|
|
|
|
|
"MainWindow", "Doing work necessary to send message.")
|
|
|
|
|
elif status == 'ackreceived':
|
|
|
|
|
statusText = _translate(
|
|
|
|
|
"MainWindow",
|
|
|
|
|
"Acknowledgement of the message received %1"
|
|
|
|
|
).arg(l10n.formatTimestamp(lastactiontime))
|
|
|
|
|
"MainWindow", "Acknowledgement of the message received {0}"
|
|
|
|
|
).format(l10n.formatTimestamp(lastactiontime))
|
|
|
|
|
elif status == 'broadcastqueued':
|
|
|
|
|
statusText = _translate(
|
|
|
|
|
"MainWindow", "Broadcast queued.")
|
|
|
|
@ -1136,36 +1116,34 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
statusText = _translate(
|
|
|
|
|
"MainWindow", "Doing work necessary to send broadcast.")
|
|
|
|
|
elif status == 'broadcastsent':
|
|
|
|
|
statusText = _translate("MainWindow", "Broadcast on %1").arg(
|
|
|
|
|
l10n.formatTimestamp(lastactiontime))
|
|
|
|
|
statusText = _translate("MainWindow", "Broadcast on {0}").format(
|
|
|
|
|
l10n.formatTimestamp(lastactiontime)
|
|
|
|
|
)
|
|
|
|
|
elif status == 'toodifficult':
|
|
|
|
|
statusText = _translate(
|
|
|
|
|
"MainWindow",
|
|
|
|
|
"Problem: The work demanded by the recipient is more"
|
|
|
|
|
" difficult than you are willing to do. %1"
|
|
|
|
|
).arg(l10n.formatTimestamp(lastactiontime))
|
|
|
|
|
" difficult than you are willing to do. {0}"
|
|
|
|
|
).format(l10n.formatTimestamp(lastactiontime))
|
|
|
|
|
elif status == 'badkey':
|
|
|
|
|
statusText = _translate(
|
|
|
|
|
"MainWindow",
|
|
|
|
|
"Problem: The recipient\'s encryption key is no good."
|
|
|
|
|
" Could not encrypt message. %1"
|
|
|
|
|
).arg(l10n.formatTimestamp(lastactiontime))
|
|
|
|
|
" Could not encrypt message. {0}"
|
|
|
|
|
).format(l10n.formatTimestamp(lastactiontime))
|
|
|
|
|
elif status == 'forcepow':
|
|
|
|
|
statusText = _translate(
|
|
|
|
|
"MainWindow",
|
|
|
|
|
"Forced difficulty override. Send should start soon.")
|
|
|
|
|
else:
|
|
|
|
|
statusText = _translate(
|
|
|
|
|
"MainWindow", "Unknown status: %1 %2").arg(status).arg(
|
|
|
|
|
l10n.formatTimestamp(lastactiontime))
|
|
|
|
|
"MainWindow", "Unknown status: {0} {1}"
|
|
|
|
|
).format(status, l10n.formatTimestamp(lastactiontime))
|
|
|
|
|
|
|
|
|
|
items = [
|
|
|
|
|
MessageList_AddressWidget(
|
|
|
|
|
toAddress, unicode(acct.toLabel, 'utf-8')),
|
|
|
|
|
MessageList_AddressWidget(
|
|
|
|
|
fromAddress, unicode(acct.fromLabel, 'utf-8')),
|
|
|
|
|
MessageList_SubjectWidget(
|
|
|
|
|
str(subject), unicode(acct.subject, 'utf-8', 'replace')),
|
|
|
|
|
MessageList_AddressWidget(toAddress, acct.toLabel),
|
|
|
|
|
MessageList_AddressWidget(fromAddress, acct.fromLabel),
|
|
|
|
|
MessageList_SubjectWidget(subject, acct.subject),
|
|
|
|
|
MessageList_TimeWidget(
|
|
|
|
|
statusText, False, lastactiontime, ackdata)]
|
|
|
|
|
self.addMessageListItem(tableWidget, items)
|
|
|
|
@ -1185,13 +1163,9 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
acct.parseMessage(toAddress, fromAddress, subject, "")
|
|
|
|
|
|
|
|
|
|
items = [
|
|
|
|
|
MessageList_AddressWidget(
|
|
|
|
|
toAddress, unicode(acct.toLabel, 'utf-8'), not read),
|
|
|
|
|
MessageList_AddressWidget(
|
|
|
|
|
fromAddress, unicode(acct.fromLabel, 'utf-8'), not read),
|
|
|
|
|
MessageList_SubjectWidget(
|
|
|
|
|
str(subject), unicode(acct.subject, 'utf-8', 'replace'),
|
|
|
|
|
not read),
|
|
|
|
|
MessageList_AddressWidget(toAddress, acct.toLabel, not read),
|
|
|
|
|
MessageList_AddressWidget(fromAddress, acct.fromLabel, not read),
|
|
|
|
|
MessageList_SubjectWidget(subject, acct.subject, not read),
|
|
|
|
|
MessageList_TimeWidget(
|
|
|
|
|
l10n.formatTimestamp(received), not read, received, msgid)
|
|
|
|
|
]
|
|
|
|
@ -1260,7 +1234,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
for row in queryreturn:
|
|
|
|
|
toAddress, fromAddress, subject, _, msgid, received, read = row
|
|
|
|
|
self.addMessageListItemInbox(
|
|
|
|
|
tableWidget, toAddress, fromAddress, subject,
|
|
|
|
|
tableWidget, toAddress, fromAddress, unicode(subject, 'utf-8'),
|
|
|
|
|
msgid, received, read)
|
|
|
|
|
|
|
|
|
|
tableWidget.horizontalHeader().setSortIndicator(
|
|
|
|
@ -1274,23 +1248,21 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
# create application indicator
|
|
|
|
|
def appIndicatorInit(self, app):
|
|
|
|
|
self.initTrayIcon("can-icon-24px-red.png", app)
|
|
|
|
|
traySignal = "activated(QSystemTrayIcon::ActivationReason)"
|
|
|
|
|
QtCore.QObject.connect(self.tray, QtCore.SIGNAL(
|
|
|
|
|
traySignal), self.__icon_activated)
|
|
|
|
|
self.tray.activated.connect(self.__icon_activated)
|
|
|
|
|
|
|
|
|
|
m = QtGui.QMenu()
|
|
|
|
|
m = QtWidgets.QMenu()
|
|
|
|
|
|
|
|
|
|
self.actionStatus = QtGui.QAction(_translate(
|
|
|
|
|
self.actionStatus = QtWidgets.QAction(_translate(
|
|
|
|
|
"MainWindow", "Not Connected"), m, checkable=False)
|
|
|
|
|
m.addAction(self.actionStatus)
|
|
|
|
|
|
|
|
|
|
# separator
|
|
|
|
|
actionSeparator = QtGui.QAction('', m, checkable=False)
|
|
|
|
|
actionSeparator = QtWidgets.QAction('', m, checkable=False)
|
|
|
|
|
actionSeparator.setSeparator(True)
|
|
|
|
|
m.addAction(actionSeparator)
|
|
|
|
|
|
|
|
|
|
# show bitmessage
|
|
|
|
|
self.actionShow = QtGui.QAction(_translate(
|
|
|
|
|
self.actionShow = QtWidgets.QAction(_translate(
|
|
|
|
|
"MainWindow", "Show Bitmessage"), m, checkable=True)
|
|
|
|
|
self.actionShow.setChecked(not BMConfigParser().getboolean(
|
|
|
|
|
'bitmessagesettings', 'startintray'))
|
|
|
|
@ -1299,7 +1271,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
m.addAction(self.actionShow)
|
|
|
|
|
|
|
|
|
|
# quiet mode
|
|
|
|
|
self.actionQuiet = QtGui.QAction(_translate(
|
|
|
|
|
self.actionQuiet = QtWidgets.QAction(_translate(
|
|
|
|
|
"MainWindow", "Quiet Mode"), m, checkable=True)
|
|
|
|
|
self.actionQuiet.setChecked(not BMConfigParser().getboolean(
|
|
|
|
|
'bitmessagesettings', 'showtraynotifications'))
|
|
|
|
@ -1307,25 +1279,25 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
m.addAction(self.actionQuiet)
|
|
|
|
|
|
|
|
|
|
# Send
|
|
|
|
|
actionSend = QtGui.QAction(_translate(
|
|
|
|
|
actionSend = QtWidgets.QAction(_translate(
|
|
|
|
|
"MainWindow", "Send"), m, checkable=False)
|
|
|
|
|
actionSend.triggered.connect(self.appIndicatorSend)
|
|
|
|
|
m.addAction(actionSend)
|
|
|
|
|
|
|
|
|
|
# Subscribe
|
|
|
|
|
actionSubscribe = QtGui.QAction(_translate(
|
|
|
|
|
actionSubscribe = QtWidgets.QAction(_translate(
|
|
|
|
|
"MainWindow", "Subscribe"), m, checkable=False)
|
|
|
|
|
actionSubscribe.triggered.connect(self.appIndicatorSubscribe)
|
|
|
|
|
m.addAction(actionSubscribe)
|
|
|
|
|
|
|
|
|
|
# Channels
|
|
|
|
|
actionSubscribe = QtGui.QAction(_translate(
|
|
|
|
|
actionSubscribe = QtWidgets.QAction(_translate(
|
|
|
|
|
"MainWindow", "Channel"), m, checkable=False)
|
|
|
|
|
actionSubscribe.triggered.connect(self.appIndicatorChannel)
|
|
|
|
|
m.addAction(actionSubscribe)
|
|
|
|
|
|
|
|
|
|
# separator
|
|
|
|
|
actionSeparator = QtGui.QAction('', m, checkable=False)
|
|
|
|
|
actionSeparator = QtWidgets.QAction('', m, checkable=False)
|
|
|
|
|
actionSeparator.setSeparator(True)
|
|
|
|
|
m.addAction(actionSeparator)
|
|
|
|
|
|
|
|
|
@ -1442,11 +1414,10 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
def notifierInit(self):
|
|
|
|
|
def _simple_notify(
|
|
|
|
|
title, subtitle, category, label=None, icon=None):
|
|
|
|
|
self.tray.showMessage(title, subtitle, 1, 2000)
|
|
|
|
|
self.tray.showMessage(
|
|
|
|
|
title, subtitle, self.tray.NoIcon, msecs=2000)
|
|
|
|
|
|
|
|
|
|
self._notifier = _simple_notify
|
|
|
|
|
# does nothing if isAvailable returns false
|
|
|
|
|
self._player = QtGui.QSound.play
|
|
|
|
|
|
|
|
|
|
if not get_plugins:
|
|
|
|
|
return
|
|
|
|
@ -1459,7 +1430,10 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
|
|
|
|
|
self._theme_player = get_plugin('notification.sound', 'theme')
|
|
|
|
|
|
|
|
|
|
if not QtGui.QSound.isAvailable():
|
|
|
|
|
try:
|
|
|
|
|
from qtpy import QtMultimedia
|
|
|
|
|
self._player = QtMultimedia.QSound.play
|
|
|
|
|
except ImportError:
|
|
|
|
|
_plugin = get_plugin(
|
|
|
|
|
'notification.sound', 'file', fallback='file.fallback')
|
|
|
|
|
if _plugin:
|
|
|
|
@ -1483,7 +1457,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
if event.key() == QtCore.Qt.Key_Delete:
|
|
|
|
|
self.on_action_AddressBookDelete()
|
|
|
|
|
else:
|
|
|
|
|
return QtGui.QTableWidget.keyPressEvent(
|
|
|
|
|
return QtWidgets.QTableWidget.keyPressEvent(
|
|
|
|
|
self.ui.tableWidgetAddressBook, event)
|
|
|
|
|
|
|
|
|
|
# inbox / sent
|
|
|
|
@ -1498,14 +1472,14 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
"""This method handles keypress events for all widgets on MyForm"""
|
|
|
|
|
messagelist = self.getCurrentMessagelist()
|
|
|
|
|
if event.key() == QtCore.Qt.Key_Delete:
|
|
|
|
|
if isinstance(focus, (MessageView, QtGui.QTableWidget)):
|
|
|
|
|
if isinstance(focus, (MessageView, QtWidgets.QTableWidget)):
|
|
|
|
|
folder = self.getCurrentFolder()
|
|
|
|
|
if folder == "sent":
|
|
|
|
|
self.on_action_SentTrash()
|
|
|
|
|
else:
|
|
|
|
|
self.on_action_InboxTrash()
|
|
|
|
|
event.ignore()
|
|
|
|
|
elif QtGui.QApplication.queryKeyboardModifiers() == QtCore.Qt.NoModifier:
|
|
|
|
|
elif QtWidgets.QApplication.queryKeyboardModifiers() == QtCore.Qt.NoModifier:
|
|
|
|
|
if event.key() == QtCore.Qt.Key_N:
|
|
|
|
|
currentRow = messagelist.currentRow()
|
|
|
|
|
if currentRow < messagelist.rowCount() - 1:
|
|
|
|
@ -1544,38 +1518,77 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
return
|
|
|
|
|
if isinstance(focus, MessageView):
|
|
|
|
|
return MessageView.keyPressEvent(focus, event)
|
|
|
|
|
if isinstance(focus, QtGui.QTableWidget):
|
|
|
|
|
return QtGui.QTableWidget.keyPressEvent(focus, event)
|
|
|
|
|
if isinstance(focus, QtGui.QTreeWidget):
|
|
|
|
|
return QtGui.QTreeWidget.keyPressEvent(focus, event)
|
|
|
|
|
elif isinstance(focus, QtWidgets.QTableWidget):
|
|
|
|
|
return QtWidgets.QTableWidget.keyPressEvent(focus, event)
|
|
|
|
|
elif isinstance(focus, QtWidgets.QTreeWidget):
|
|
|
|
|
return QtWidgets.QTreeWidget.keyPressEvent(focus, event)
|
|
|
|
|
|
|
|
|
|
# menu button 'manage keys'
|
|
|
|
|
def click_actionManageKeys(self):
|
|
|
|
|
if 'darwin' in sys.platform or 'linux' in sys.platform:
|
|
|
|
|
if state.appdata == '':
|
|
|
|
|
# reply = QtGui.QMessageBox.information(self, 'keys.dat?','You
|
|
|
|
|
# reply = QtWidgets.QMessageBox.information(self, 'keys.dat?','You
|
|
|
|
|
# may manage your keys by editing the keys.dat file stored in
|
|
|
|
|
# the same directory as this program. It is important that you
|
|
|
|
|
# back up this file.', QMessageBox.Ok)
|
|
|
|
|
reply = QtGui.QMessageBox.information(self, 'keys.dat?', _translate(
|
|
|
|
|
"MainWindow", "You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file."), QtGui.QMessageBox.Ok)
|
|
|
|
|
reply = QtWidgets.QMessageBox.information(
|
|
|
|
|
self, 'keys.dat?', _translate(
|
|
|
|
|
"MainWindow",
|
|
|
|
|
"You may manage your keys by editing the keys.dat"
|
|
|
|
|
" file stored in the same directory as this"
|
|
|
|
|
" program. It is important that you back up this"
|
|
|
|
|
" file."), QtWidgets.QMessageBox.Ok)
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
QtGui.QMessageBox.information(self, 'keys.dat?', _translate(
|
|
|
|
|
"MainWindow", "You may manage your keys by editing the keys.dat file stored in\n %1 \nIt is important that you back up this file.").arg(state.appdata), QtGui.QMessageBox.Ok)
|
|
|
|
|
QtWidgets.QMessageBox.information(
|
|
|
|
|
self, 'keys.dat?',
|
|
|
|
|
_translate(
|
|
|
|
|
"MainWindow",
|
|
|
|
|
"You may manage your keys by editing the keys.dat"
|
|
|
|
|
" file stored in\n {0} \nIt is important that you"
|
|
|
|
|
" back up this file."
|
|
|
|
|
).format(state.appdata),
|
|
|
|
|
QtWidgets.QMessageBox.Ok
|
|
|
|
|
)
|
|
|
|
|
elif sys.platform == 'win32' or sys.platform == 'win64':
|
|
|
|
|
if state.appdata == '':
|
|
|
|
|
reply = QtGui.QMessageBox.question(self, _translate("MainWindow", "Open keys.dat?"), _translate(
|
|
|
|
|
"MainWindow", "You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.)"), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
|
|
|
|
|
reply = QtWidgets.QMessageBox.question(
|
|
|
|
|
self, _translate("MainWindow", "Open keys.dat?"),
|
|
|
|
|
_translate(
|
|
|
|
|
"MainWindow",
|
|
|
|
|
"You may manage your keys by editing the keys.dat"
|
|
|
|
|
" file stored in the same directory as this"
|
|
|
|
|
" program. It is important that you back up this"
|
|
|
|
|
" file. Would you like to open the file now?"
|
|
|
|
|
" (Be sure to close Bitmessage before making any"
|
|
|
|
|
" changes.)"
|
|
|
|
|
), QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
|
|
|
|
|
else:
|
|
|
|
|
reply = QtGui.QMessageBox.question(self, _translate("MainWindow", "Open keys.dat?"), _translate(
|
|
|
|
|
"MainWindow", "You may manage your keys by editing the keys.dat file stored in\n %1 \nIt is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.)").arg(state.appdata), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
|
|
|
|
|
if reply == QtGui.QMessageBox.Yes:
|
|
|
|
|
reply = QtWidgets.QMessageBox.question(
|
|
|
|
|
self,
|
|
|
|
|
_translate("MainWindow", "Open keys.dat?"),
|
|
|
|
|
_translate(
|
|
|
|
|
"MainWindow",
|
|
|
|
|
"You may manage your keys by editing the keys.dat"
|
|
|
|
|
" file stored in\n {0} \nIt is important that you"
|
|
|
|
|
" back up this file. Would you like to open the"
|
|
|
|
|
" file now? (Be sure to close Bitmessage before"
|
|
|
|
|
" making any changes.)"
|
|
|
|
|
).format(state.appdata),
|
|
|
|
|
QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No
|
|
|
|
|
)
|
|
|
|
|
if reply == QtWidgets.QMessageBox.Yes:
|
|
|
|
|
openKeysFile()
|
|
|
|
|
|
|
|
|
|
# menu button 'delete all treshed messages'
|
|
|
|
|
def click_actionDeleteAllTrashedMessages(self):
|
|
|
|
|
if QtGui.QMessageBox.question(self, _translate("MainWindow", "Delete trash?"), _translate("MainWindow", "Are you sure you want to delete all trashed messages?"), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) == QtGui.QMessageBox.No:
|
|
|
|
|
if QtWidgets.QMessageBox.question(
|
|
|
|
|
self, _translate("MainWindow", "Delete trash?"),
|
|
|
|
|
_translate(
|
|
|
|
|
"MainWindow",
|
|
|
|
|
"Are you sure you want to delete all trashed messages?"
|
|
|
|
|
), QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No
|
|
|
|
|
) == QtWidgets.QMessageBox.No:
|
|
|
|
|
return
|
|
|
|
|
sqlStoredProcedure('deleteandvacuume')
|
|
|
|
|
self.rerenderTabTreeMessages()
|
|
|
|
@ -1593,7 +1606,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
dialog = dialogs.RegenerateAddressesDialog(self)
|
|
|
|
|
if dialog.exec_():
|
|
|
|
|
if dialog.lineEditPassphrase.text() == "":
|
|
|
|
|
QtGui.QMessageBox.about(
|
|
|
|
|
QtWidgets.QMessageBox.about(
|
|
|
|
|
self, _translate("MainWindow", "bad passphrase"),
|
|
|
|
|
_translate(
|
|
|
|
|
"MainWindow",
|
|
|
|
@ -1606,7 +1619,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
addressVersionNumber = int(
|
|
|
|
|
dialog.lineEditAddressVersionNumber.text())
|
|
|
|
|
except:
|
|
|
|
|
QtGui.QMessageBox.about(
|
|
|
|
|
QtWidgets.QMessageBox.about(
|
|
|
|
|
self,
|
|
|
|
|
_translate("MainWindow", "Bad address version number"),
|
|
|
|
|
_translate(
|
|
|
|
@ -1616,7 +1629,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
))
|
|
|
|
|
return
|
|
|
|
|
if addressVersionNumber < 3 or addressVersionNumber > 4:
|
|
|
|
|
QtGui.QMessageBox.about(
|
|
|
|
|
QtWidgets.QMessageBox.about(
|
|
|
|
|
self,
|
|
|
|
|
_translate("MainWindow", "Bad address version number"),
|
|
|
|
|
_translate(
|
|
|
|
@ -1629,7 +1642,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
addressVersionNumber, streamNumberForAddress,
|
|
|
|
|
"regenerated deterministic address",
|
|
|
|
|
dialog.spinBoxNumberOfAddressesToMake.value(),
|
|
|
|
|
dialog.lineEditPassphrase.text().toUtf8(),
|
|
|
|
|
dialog.lineEditPassphrase.text().encode('utf-8'),
|
|
|
|
|
dialog.checkBoxEighteenByteRipe.isChecked()
|
|
|
|
|
))
|
|
|
|
|
self.ui.tabWidget.setCurrentIndex(
|
|
|
|
@ -1653,13 +1666,6 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
else:
|
|
|
|
|
self._firstrun = False
|
|
|
|
|
|
|
|
|
|
def showMigrationWizard(self, level):
|
|
|
|
|
self.migrationWizardInstance = Ui_MigrationWizard(["a"])
|
|
|
|
|
if self.migrationWizardInstance.exec_():
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def changeEvent(self, event):
|
|
|
|
|
if event.type() == QtCore.QEvent.LanguageChange:
|
|
|
|
|
self.ui.retranslateUi(self)
|
|
|
|
@ -1680,7 +1686,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def __icon_activated(self, reason):
|
|
|
|
|
if reason == QtGui.QSystemTrayIcon.Trigger:
|
|
|
|
|
if reason == QtWidgets.QSystemTrayIcon.Trigger:
|
|
|
|
|
self.actionShow.setChecked(not self.actionShow.isChecked())
|
|
|
|
|
self.appIndicatorShowOrHideWindow()
|
|
|
|
|
|
|
|
|
@ -1753,7 +1759,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
|
|
|
|
|
def initTrayIcon(self, iconFileName, app):
|
|
|
|
|
self.currentTrayIconFileName = iconFileName
|
|
|
|
|
self.tray = QtGui.QSystemTrayIcon(
|
|
|
|
|
self.tray = QtWidgets.QSystemTrayIcon(
|
|
|
|
|
self.calcTrayIcon(iconFileName, self.findInboxUnreadCount()), app)
|
|
|
|
|
|
|
|
|
|
def setTrayIconFile(self, iconFileName):
|
|
|
|
@ -1785,8 +1791,7 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
# draw text
|
|
|
|
|
painter = QtGui.QPainter()
|
|
|
|
|
painter.begin(pixmap)
|
|
|
|
|
painter.setPen(
|
|
|
|
|
QtGui.QPen(QtGui.QColor(255, 0, 0), QtCore.Qt.SolidPattern))
|
|
|
|
|
painter.setPen(QtGui.QPen(QtGui.QColor(255, 0, 0)))
|
|
|
|
|
painter.setFont(font)
|
|
|
|
|
painter.drawText(24-rect.right()-marginX, -rect.top()+marginY, txt)
|
|
|
|
|
painter.end()
|
|
|
|
@ -1833,8 +1838,11 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
if toAddress == rowAddress:
|
|
|
|
|
sent.item(i, 3).setToolTip(textToDisplay)
|
|
|
|
|
try:
|
|
|
|
|
newlinePosition = textToDisplay.indexOf('\n')
|
|
|
|
|
except: # If someone misses adding a "_translate" to a string before passing it to this function, this function won't receive a qstring which will cause an exception.
|
|
|
|
|
newlinePosition = textToDisplay.find('\n')
|
|
|
|
|
# If someone misses adding a "_translate" to a string
|
|
|
|
|
# before passing it to this function
|
|
|
|
|
# ? why textToDisplay isn't unicode
|
|
|
|
|
except AttributeError:
|
|
|
|
|
newlinePosition = 0
|
|
|
|
|
if newlinePosition > 1:
|
|
|
|
|
sent.item(i, 3).setText(
|
|
|
|
@ -1843,8 +1851,6 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
sent.item(i, 3).setText(textToDisplay)
|
|
|
|
|
|
|
|
|
|
def updateSentItemStatusByAckdata(self, ackdata, textToDisplay):
|
|
|
|
|
if type(ackdata) is str:
|
|
|
|
|
ackdata = QtCore.QByteArray(ackdata)
|
|
|
|
|
for sent in (
|
|
|
|
|
self.ui.tableWidgetInbox,
|
|
|
|
|
self.ui.tableWidgetInboxSubscriptions,
|
|
|
|
@ -1854,21 +1860,22 @@ class MyForm(settingsmixin.SMainWindow):
|
|
|
|
|
if self.getCurrentFolder(treeWidget) != "sent":
|
|
|
|
|
continue
|
|
|
|
|
for i in range(sent.rowCount()):
|
|
|
|
|
toAddress = sent.item(i, 0).data(QtCore.Qt.UserRole)
|
|
|