Compare commits

...

23 Commits

Author SHA1 Message Date
b811f8fe5e
qidenticon: no xrange 2021-03-05 16:22:54 +02:00
1a203dd2a2
Sorted imports in __init__ and removed import from debug 2021-03-03 18:28:49 +02:00
68d24a1969
Fix tray icon changing upon notification 2021-03-03 18:28:49 +02:00
b5e93edae1
winbuild.sh script: additional packages 2021-03-03 18:28:49 +02:00
4ac97393c2
Changes for PyInstaller to build with qtpy and PyQt4 2021-03-03 18:28:49 +02:00
f12022614c
Removed unused resources in ui-files 2021-03-03 18:28:49 +02:00
6817d8d030
Don't close BitmessageQtApplication.server in __del__() 2021-03-03 18:28:49 +02:00
cf36bc4551
Suppressed pylint relative-import and pycodestyle E402 in depends 2021-03-03 18:28:48 +02:00
61f9b2eaf7
Explicitly set wordWrap property to false in STableWidgets
on tabs "Send", "Blacklist" and "Network Status":
in qt5 it's probably true by default.
2021-03-03 18:28:48 +02:00
973ef47549
PyQt5 based qtpy fallback 2021-03-03 18:28:48 +02:00
f4eae01886
Handled pylint warnings in bitmessageqt, qidenticon, depends,
resolved pylint redefined-variable-type warnings,
marked autogenerated modules for skipping by pylint and flake8
2021-03-03 18:28:48 +02:00
a38e5c63e1
Changed check_pyqt() to work with qtpy
(closes #897, closes #1418)
2021-03-03 18:28:48 +02:00
da940d9895
QWheelEvent.orientation() is obsolete, used angleDelta() instead 2021-03-03 18:28:48 +02:00
c1b3154728
fromAddress - str, subject - unicode
(for simple encoding like for extended)
2021-03-03 18:28:48 +02:00
a8c7edef89
QComboBox.findData() compatible with pyside 2021-03-03 18:28:48 +02:00
6c134d0a08
No more arg() call on result of _translate() 2021-03-03 18:28:47 +02:00
64bd64eea2
Better formatting of connections table header 2021-03-03 18:28:47 +02:00
f3b54cea75
Module support rewrite:
- added Qt API string into support request
  - finished flake8 formatting
2021-03-03 18:28:47 +02:00
39a1d69b5d
Changes for pyside:
customwidgets in ui-files and QtGui.QPen instantiation
2021-03-03 18:28:47 +02:00
51b5e64f34
Initial support for PyQt5 (main window shown) using QtPy package.
QtPy is a compatibility layer which allows to use the code written for
PyQt5 with any python Qt binding: PyQt4, PyQt5, pyside or pyside2.

Main differences in PyQt5:

  - all widget classes are now in QtWidgets package, not QtGui;
  - QString obsoleted by unicode (sip API 2);
  - changed the way of signals connection.

Closes: #1191
2021-03-03 18:28:47 +02:00
d7c9eac8e7
Prepare newchandialog module for using qtpy 2021-03-03 18:28:47 +02:00
abc4b5ebfc
Prepare qidenticon module for using qtpy 2021-03-03 18:28:47 +02:00
5a5f57eddf
tr compatible with all Qt APIs 2021-03-03 18:28:46 +02:00
45 changed files with 1934 additions and 1801 deletions

View File

@ -9,7 +9,7 @@ addons:
packages: packages:
- build-essential - build-essential
- libcap-dev - libcap-dev
- python-qt4 - python-pyqt5
- tor - tor
- xvfb - xvfb
install: install:

View File

@ -72,6 +72,8 @@ function install_python(){
wine python -m pip install pytools==2020.2 wine python -m pip install pytools==2020.2
echo "Upgrading pip" echo "Upgrading pip"
wine python -m pip install --upgrade pip wine python -m pip install --upgrade pip
# install pypiwin32 for win32com
wine python -m pip install pypiwin32
} }
function install_pyqt(){ function install_pyqt(){
@ -82,6 +84,8 @@ function install_pyqt(){
echo "Installing PyQt-${PYQT_VERSION} 32b" echo "Installing PyQt-${PYQT_VERSION} 32b"
wine PyQt${PYQT_VERSION}-x32.exe /S /WX wine PyQt${PYQT_VERSION}-x32.exe /S /WX
fi fi
# and qtpy
wine python -m pip install qtpy
} }
function install_openssl(){ function install_openssl(){

View File

@ -32,9 +32,14 @@ a = Analysis(
'bitmessageqt.languagebox', 'pyopencl', 'numpy', 'win32com', 'bitmessageqt.languagebox', 'pyopencl', 'numpy', 'win32com',
'setuptools.msvc', '_cffi_backend' 'setuptools.msvc', '_cffi_backend'
], ],
hookspath=None, hookspath=None, # this feature has undocumented syntax
runtime_hooks=None, # https://github.com/pyinstaller/pyinstaller/wiki/Recipe-PyQt4-API-Version
excludes=['bsddb', 'bz2', 'tcl', 'tk', 'Tkinter'] runtime_hooks=['pyinstaller_rthook_pyqt4.py'],
excludes=[
'bsddb', 'bz2',
'PyQt4.QtOpenGL', 'PyQt4.QtOpenGL', 'PyQt4.QtSql',
'PyQt4.QtSvg', 'PyQt4.QtTest', 'PyQt4.QtWebKit', 'PyQt4.QtXml',
'tcl', 'tk', 'Tkinter', 'win32ui']
) )
os.rename( os.rename(
@ -77,9 +82,8 @@ a.datas += addTranslations()
excluded_binaries = [ excluded_binaries = [
'QtOpenGL4.dll', 'QtOpenGL4.dll', 'QtSql4.dll', 'QtSvg4.dll', 'QtTest4.dll',
'QtSvg4.dll', 'QtWebKit4.dll', 'QtXml4.dll'
'QtXml4.dll',
] ]
a.binaries = TOC([x for x in a.binaries if x[0] not in excluded_binaries]) a.binaries = TOC([x for x in a.binaries if x[0] not in excluded_binaries])

View File

@ -4,6 +4,7 @@ PyQt based UI for bitmessage, the main module
import hashlib import hashlib
import locale import locale
import logging
import os import os
import random import random
import string import string
@ -15,52 +16,52 @@ import time
from datetime import datetime, timedelta from datetime import datetime, timedelta
from sqlite3 import register_adapter from sqlite3 import register_adapter
from PyQt4 import QtCore, QtGui from qtpy import QtCore, QtGui, QtWidgets, QtNetwork
from PyQt4.QtNetwork import QLocalSocket, QLocalServer
# 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 shared
import shutdown
import sound
import state import state
from debug import logger import support
from tr import _translate from account import (
getSortedAccounts, getSortedSubscriptions, accountClass, BMAccount,
GatewayAccount, MailchuckAccount, AccountColor)
from addresses import decodeAddress, addBMIfNotPresent from addresses import decodeAddress, addBMIfNotPresent
from bitmessageui import Ui_MainWindow from bitmessageui import Ui_MainWindow
from bmconfigparser import BMConfigParser from bmconfigparser import BMConfigParser
import namecoin
from messageview import MessageView
from migrationwizard import Ui_MigrationWizard
from foldertree import ( from foldertree import (
AccountMixin, Ui_FolderWidget, Ui_AddressWidget, Ui_SubscriptionWidget, AccountMixin, Ui_FolderWidget, Ui_AddressWidget, Ui_SubscriptionWidget,
MessageList_AddressWidget, MessageList_SubjectWidget, MessageList_AddressWidget, MessageList_SubjectWidget,
Ui_AddressBookWidgetItemLabel, Ui_AddressBookWidgetItemAddress, Ui_AddressBookWidgetItemLabel, Ui_AddressBookWidgetItemAddress,
MessageList_TimeWidget) MessageList_TimeWidget)
import settingsmixin from helper_sql import (
import support sqlQuery, sqlExecute, sqlExecuteChunked, sqlStoredProcedure)
from helper_sql import sqlQuery, sqlExecute, sqlExecuteChunked, sqlStoredProcedure from messageview import MessageView
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 network.stats import pendingDownload, pendingUpload from network.stats import pendingDownload, pendingUpload
from uisignaler import UISignaler
import paths
from proofofwork import getPowType from proofofwork import getPowType
import queues
import shutdown
from statusbar import BMStatusBar from statusbar import BMStatusBar
import sound from tr import _translate
# This is needed for tray icon from uisignaler import UISignaler
import bitmessage_icons_rc # noqa:F401 pylint: disable=unused-import from utils import str_broadcast_subscribers, avatarize
import helper_sent
try: try:
from plugins.plugin import get_plugin, get_plugins from plugins.plugin import get_plugin, get_plugins
except ImportError: except ImportError:
get_plugins = False get_plugins = False
logger = logging.getLogger('default')
# TODO: rewrite # TODO: rewrite
def powQueueSize(): def powQueueSize():
@ -99,12 +100,12 @@ class MyForm(settingsmixin.SMainWindow):
newlocale = l10n.getTranslationLanguage() newlocale = l10n.getTranslationLanguage()
try: try:
if not self.qmytranslator.isEmpty(): if not self.qmytranslator.isEmpty():
QtGui.QApplication.removeTranslator(self.qmytranslator) QtWidgets.QApplication.removeTranslator(self.qmytranslator)
except: except:
pass pass
try: try:
if not self.qsystranslator.isEmpty(): if not self.qsystranslator.isEmpty():
QtGui.QApplication.removeTranslator(self.qsystranslator) QtWidgets.QApplication.removeTranslator(self.qsystranslator)
except: except:
pass pass
@ -112,7 +113,7 @@ class MyForm(settingsmixin.SMainWindow):
translationpath = os.path.join( translationpath = os.path.join(
paths.codePath(), 'translations', 'bitmessage_' + newlocale) paths.codePath(), 'translations', 'bitmessage_' + newlocale)
self.qmytranslator.load(translationpath) self.qmytranslator.load(translationpath)
QtGui.QApplication.installTranslator(self.qmytranslator) QtWidgets.QApplication.installTranslator(self.qmytranslator)
self.qsystranslator = QtCore.QTranslator() self.qsystranslator = QtCore.QTranslator()
if paths.frozen: if paths.frozen:
@ -123,7 +124,7 @@ class MyForm(settingsmixin.SMainWindow):
str(QtCore.QLibraryInfo.location( str(QtCore.QLibraryInfo.location(
QtCore.QLibraryInfo.TranslationsPath)), 'qt_' + newlocale) QtCore.QLibraryInfo.TranslationsPath)), 'qt_' + newlocale)
self.qsystranslator.load(translationpath) self.qsystranslator.load(translationpath)
QtGui.QApplication.installTranslator(self.qsystranslator) QtWidgets.QApplication.installTranslator(self.qsystranslator)
lang = locale.normalize(l10n.getTranslationLanguage()) lang = locale.normalize(l10n.getTranslationLanguage())
langs = [ langs = [
@ -146,49 +147,35 @@ class MyForm(settingsmixin.SMainWindow):
logger.error("Failed to set locale to %s", lang, exc_info=True) logger.error("Failed to set locale to %s", lang, exc_info=True)
def init_file_menu(self): def init_file_menu(self):
QtCore.QObject.connect(self.ui.actionExit, QtCore.SIGNAL( self.ui.actionExit.triggered.connect(self.quit)
"triggered()"), self.quit) self.ui.actionNetworkSwitch.triggered.connect(self.network_switch)
QtCore.QObject.connect(self.ui.actionNetworkSwitch, QtCore.SIGNAL( self.ui.actionManageKeys.triggered.connect(self.click_actionManageKeys)
"triggered()"), self.network_switch) self.ui.actionDeleteAllTrashedMessages.triggered.connect(
QtCore.QObject.connect(self.ui.actionManageKeys, QtCore.SIGNAL( self.click_actionDeleteAllTrashedMessages)
"triggered()"), self.click_actionManageKeys) self.ui.actionRegenerateDeterministicAddresses.triggered.connect(
QtCore.QObject.connect(self.ui.actionDeleteAllTrashedMessages, self.click_actionRegenerateDeterministicAddresses)
QtCore.SIGNAL( self.ui.actionSettings.triggered.connect(self.click_actionSettings)
"triggered()"), self.ui.actionAbout.triggered.connect(self.click_actionAbout)
self.click_actionDeleteAllTrashedMessages) self.ui.actionSupport.triggered.connect(self.click_actionSupport)
QtCore.QObject.connect(self.ui.actionRegenerateDeterministicAddresses, self.ui.actionHelp.triggered.connect(self.click_actionHelp)
QtCore.SIGNAL(
"triggered()"), # also used for creating chans.
self.click_actionRegenerateDeterministicAddresses) self.ui.pushButtonAddChan.clicked.connect(self.click_actionJoinChan)
QtCore.QObject.connect(self.ui.pushButtonAddChan, QtCore.SIGNAL( self.ui.pushButtonNewAddress.clicked.connect(
"clicked()"), self.click_NewAddressDialog)
self.click_actionJoinChan) # also used for creating chans. self.ui.pushButtonAddAddressBook.clicked.connect(
QtCore.QObject.connect(self.ui.pushButtonNewAddress, QtCore.SIGNAL( self.click_pushButtonAddAddressBook)
"clicked()"), self.click_NewAddressDialog) self.ui.pushButtonAddSubscription.clicked.connect(
QtCore.QObject.connect(self.ui.pushButtonAddAddressBook, QtCore.SIGNAL( self.click_pushButtonAddSubscription)
"clicked()"), self.click_pushButtonAddAddressBook) self.ui.pushButtonTTL.clicked.connect(self.click_pushButtonTTL)
QtCore.QObject.connect(self.ui.pushButtonAddSubscription, QtCore.SIGNAL( self.ui.pushButtonClear.clicked.connect(self.click_pushButtonClear)
"clicked()"), self.click_pushButtonAddSubscription) self.ui.pushButtonSend.clicked.connect(self.click_pushButtonSend)
QtCore.QObject.connect(self.ui.pushButtonTTL, QtCore.SIGNAL( self.ui.pushButtonFetchNamecoinID.clicked.connect(
"clicked()"), self.click_pushButtonTTL) self.click_pushButtonFetchNamecoinID)
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)
def init_inbox_popup_menu(self, connectSignal=True): def init_inbox_popup_menu(self, connectSignal=True):
# Popup menu for the Inbox tab # Popup menu for the Inbox tab
self.ui.inboxContextMenuToolbar = QtGui.QToolBar() self.ui.inboxContextMenuToolbar = QtWidgets.QToolBar()
# Actions # Actions
self.actionReply = self.ui.inboxContextMenuToolbar.addAction(_translate( self.actionReply = self.ui.inboxContextMenuToolbar.addAction(_translate(
"MainWindow", "Reply to sender"), self.on_action_InboxReply) "MainWindow", "Reply to sender"), self.on_action_InboxReply)
@ -224,25 +211,22 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.tableWidgetInbox.setContextMenuPolicy( self.ui.tableWidgetInbox.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu) QtCore.Qt.CustomContextMenu)
if connectSignal: if connectSignal:
self.connect(self.ui.tableWidgetInbox, QtCore.SIGNAL( self.ui.tableWidgetInbox.customContextMenuRequested.connect(
'customContextMenuRequested(const QPoint&)'),
self.on_context_menuInbox) self.on_context_menuInbox)
self.ui.tableWidgetInboxSubscriptions.setContextMenuPolicy( self.ui.tableWidgetInboxSubscriptions.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu) QtCore.Qt.CustomContextMenu)
if connectSignal: if connectSignal:
self.connect(self.ui.tableWidgetInboxSubscriptions, QtCore.SIGNAL( self.ui.tableWidgetInboxSubscriptions.customContextMenuRequested.connect(
'customContextMenuRequested(const QPoint&)'),
self.on_context_menuInbox) self.on_context_menuInbox)
self.ui.tableWidgetInboxChans.setContextMenuPolicy( self.ui.tableWidgetInboxChans.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu) QtCore.Qt.CustomContextMenu)
if connectSignal: if connectSignal:
self.connect(self.ui.tableWidgetInboxChans, QtCore.SIGNAL( self.ui.tableWidgetInboxChans.customContextMenuRequested.connect(
'customContextMenuRequested(const QPoint&)'),
self.on_context_menuInbox) self.on_context_menuInbox)
def init_identities_popup_menu(self, connectSignal=True): def init_identities_popup_menu(self, connectSignal=True):
# Popup menu for the Your Identities tab # Popup menu for the Your Identities tab
self.ui.addressContextMenuToolbarYourIdentities = QtGui.QToolBar() self.ui.addressContextMenuToolbarYourIdentities = QtWidgets.QToolBar()
# Actions # Actions
self.actionNewYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction(_translate( self.actionNewYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction(_translate(
"MainWindow", "New"), self.on_action_YourIdentitiesNew) "MainWindow", "New"), self.on_action_YourIdentitiesNew)
@ -276,8 +260,7 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.treeWidgetYourIdentities.setContextMenuPolicy( self.ui.treeWidgetYourIdentities.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu) QtCore.Qt.CustomContextMenu)
if connectSignal: if connectSignal:
self.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL( self.ui.treeWidgetYourIdentities.customContextMenuRequested.connect(
'customContextMenuRequested(const QPoint&)'),
self.on_context_menuYourIdentities) self.on_context_menuYourIdentities)
# load all gui.menu plugins with prefix 'address' # load all gui.menu plugins with prefix 'address'
@ -326,13 +309,12 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.treeWidgetChans.setContextMenuPolicy( self.ui.treeWidgetChans.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu) QtCore.Qt.CustomContextMenu)
if connectSignal: if connectSignal:
self.connect(self.ui.treeWidgetChans, QtCore.SIGNAL( self.ui.treeWidgetChans.customContextMenuRequested.connect(
'customContextMenuRequested(const QPoint&)'),
self.on_context_menuChan) self.on_context_menuChan)
def init_addressbook_popup_menu(self, connectSignal=True): def init_addressbook_popup_menu(self, connectSignal=True):
# Popup menu for the Address Book page # Popup menu for the Address Book page
self.ui.addressBookContextMenuToolbar = QtGui.QToolBar() self.ui.addressBookContextMenuToolbar = QtWidgets.QToolBar()
# Actions # Actions
self.actionAddressBookSend = self.ui.addressBookContextMenuToolbar.addAction( self.actionAddressBookSend = self.ui.addressBookContextMenuToolbar.addAction(
_translate( _translate(
@ -363,8 +345,7 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.tableWidgetAddressBook.setContextMenuPolicy( self.ui.tableWidgetAddressBook.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu) QtCore.Qt.CustomContextMenu)
if connectSignal: if connectSignal:
self.connect(self.ui.tableWidgetAddressBook, QtCore.SIGNAL( self.ui.tableWidgetAddressBook.customContextMenuRequested.connect(
'customContextMenuRequested(const QPoint&)'),
self.on_context_menuAddressBook) self.on_context_menuAddressBook)
def init_subscriptions_popup_menu(self, connectSignal=True): def init_subscriptions_popup_menu(self, connectSignal=True):
@ -392,8 +373,7 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.treeWidgetSubscriptions.setContextMenuPolicy( self.ui.treeWidgetSubscriptions.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu) QtCore.Qt.CustomContextMenu)
if connectSignal: if connectSignal:
self.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL( self.ui.treeWidgetSubscriptions.customContextMenuRequested.connect(
'customContextMenuRequested(const QPoint&)'),
self.on_context_menuSubscriptions) self.on_context_menuSubscriptions)
def init_sent_popup_menu(self, connectSignal=True): def init_sent_popup_menu(self, connectSignal=True):
@ -411,7 +391,7 @@ class MyForm(settingsmixin.SMainWindow):
self.actionSentReply = self.ui.sentContextMenuToolbar.addAction( self.actionSentReply = self.ui.sentContextMenuToolbar.addAction(
_translate("MainWindow", "Send update"), _translate("MainWindow", "Send update"),
self.on_action_SentReply) self.on_action_SentReply)
# self.popMenuSent = QtGui.QMenu( self ) # self.popMenuSent = QtWidgets.QMenu( self )
# self.popMenuSent.addAction( self.actionSentClipboard ) # self.popMenuSent.addAction( self.actionSentClipboard )
# self.popMenuSent.addAction( self.actionTrashSentMessage ) # self.popMenuSent.addAction( self.actionTrashSentMessage )
@ -435,7 +415,6 @@ class MyForm(settingsmixin.SMainWindow):
if treeWidget.isSortingEnabled(): if treeWidget.isSortingEnabled():
treeWidget.setSortingEnabled(False) treeWidget.setSortingEnabled(False)
widgets = {}
i = 0 i = 0
while i < treeWidget.topLevelItemCount(): while i < treeWidget.topLevelItemCount():
widget = treeWidget.topLevelItem(i) widget = treeWidget.topLevelItem(i)
@ -453,7 +432,8 @@ class MyForm(settingsmixin.SMainWindow):
while j < widget.childCount(): while j < widget.childCount():
subwidget = widget.child(j) subwidget = widget.child(j)
try: try:
subwidget.setUnreadCount(db[toAddress][subwidget.folderName]['count']) subwidget.setUnreadCount(
db[toAddress][subwidget.folderName]['count'])
unread += db[toAddress][subwidget.folderName]['count'] unread += db[toAddress][subwidget.folderName]['count']
db[toAddress].pop(subwidget.folderName, None) db[toAddress].pop(subwidget.folderName, None)
except: except:
@ -467,7 +447,8 @@ class MyForm(settingsmixin.SMainWindow):
j = 0 j = 0
for f, c in db[toAddress].iteritems(): for f, c in db[toAddress].iteritems():
try: try:
subwidget = Ui_FolderWidget(widget, j, toAddress, f, c['count']) subwidget = Ui_FolderWidget(
widget, j, toAddress, f, c['count'])
except KeyError: except KeyError:
subwidget = Ui_FolderWidget(widget, j, toAddress, f, 0) subwidget = Ui_FolderWidget(widget, j, toAddress, f, 0)
j += 1 j += 1
@ -477,15 +458,21 @@ class MyForm(settingsmixin.SMainWindow):
i = 0 i = 0
for toAddress in db: 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 j = 0
unread = 0 unread = 0
for folder in folders: for folder in folders:
try: 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'] unread += db[toAddress][folder]['count']
except KeyError: except KeyError:
subwidget = Ui_FolderWidget(widget, j, toAddress, folder, 0) subwidget = Ui_FolderWidget(
widget, j, toAddress, folder, 0)
j += 1 j += 1
widget.setUnreadCount(unread) widget.setUnreadCount(unread)
i += 1 i += 1
@ -518,8 +505,8 @@ class MyForm(settingsmixin.SMainWindow):
toAddress, 'enabled') toAddress, 'enabled')
isChan = BMConfigParser().safeGetBoolean( isChan = BMConfigParser().safeGetBoolean(
toAddress, 'chan') toAddress, 'chan')
isMaillinglist = BMConfigParser().safeGetBoolean( # isMaillinglist = BMConfigParser().safeGetBoolean(
toAddress, 'mailinglist') # toAddress, 'mailinglist')
if treeWidget == self.ui.treeWidgetYourIdentities: if treeWidget == self.ui.treeWidgetYourIdentities:
if isChan: if isChan:
@ -553,7 +540,6 @@ class MyForm(settingsmixin.SMainWindow):
if treeWidget.isSortingEnabled(): if treeWidget.isSortingEnabled():
treeWidget.setSortingEnabled(False) treeWidget.setSortingEnabled(False)
widgets = {}
i = 0 i = 0
while i < treeWidget.topLevelItemCount(): while i < treeWidget.topLevelItemCount():
widget = treeWidget.topLevelItem(i) widget = treeWidget.topLevelItem(i)
@ -614,7 +600,7 @@ class MyForm(settingsmixin.SMainWindow):
treeWidget.setSortingEnabled(True) treeWidget.setSortingEnabled(True)
def __init__(self, parent=None): def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent) super(MyForm, self).__init__(parent)
self.ui = Ui_MainWindow() self.ui = Ui_MainWindow()
self.ui.setupUi(self) self.ui.setupUi(self)
@ -632,11 +618,13 @@ class MyForm(settingsmixin.SMainWindow):
addressInKeysFile) addressInKeysFile)
if addressVersionNumber == 1: if addressVersionNumber == 1:
displayMsg = _translate( displayMsg = _translate(
"MainWindow", "One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. " "MainWindow",
+ "May we delete it now?").arg(addressInKeysFile) "One of your addresses, {0}, is an old version 1"
reply = QtGui.QMessageBox.question( " address. Version 1 addresses are no longer supported."
self, 'Message', displayMsg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) " May we delete it now?").format(addressInKeysFile)
if reply == QtGui.QMessageBox.Yes: reply = QtWidgets.QMessageBox.question(
self, 'Message', displayMsg, QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.Yes:
BMConfigParser().remove_section(addressInKeysFile) BMConfigParser().remove_section(addressInKeysFile)
BMConfigParser().save() BMConfigParser().save()
@ -680,107 +668,97 @@ class MyForm(settingsmixin.SMainWindow):
self.rerenderSubscriptions() self.rerenderSubscriptions()
# Initialize the inbox search # Initialize the inbox search
QtCore.QObject.connect(self.ui.inboxSearchLineEdit, QtCore.SIGNAL( for line_edit in (
"returnPressed()"), self.inboxSearchLineEditReturnPressed) self.ui.inboxSearchLineEdit,
QtCore.QObject.connect(self.ui.inboxSearchLineEditSubscriptions, QtCore.SIGNAL( self.ui.inboxSearchLineEditSubscriptions,
"returnPressed()"), self.inboxSearchLineEditReturnPressed) self.ui.inboxSearchLineEditChans,
QtCore.QObject.connect(self.ui.inboxSearchLineEditChans, QtCore.SIGNAL( ):
"returnPressed()"), self.inboxSearchLineEditReturnPressed) line_edit.returnPressed.connect(
QtCore.QObject.connect(self.ui.inboxSearchLineEdit, QtCore.SIGNAL( self.inboxSearchLineEditReturnPressed)
"textChanged(QString)"), self.inboxSearchLineEditUpdated) line_edit.textChanged.connect(
QtCore.QObject.connect(self.ui.inboxSearchLineEditSubscriptions, QtCore.SIGNAL( self.inboxSearchLineEditUpdated)
"textChanged(QString)"), self.inboxSearchLineEditUpdated)
QtCore.QObject.connect(self.ui.inboxSearchLineEditChans, QtCore.SIGNAL(
"textChanged(QString)"), self.inboxSearchLineEditUpdated)
# Initialize addressbook # Initialize addressbook
QtCore.QObject.connect(self.ui.tableWidgetAddressBook, QtCore.SIGNAL( self.ui.tableWidgetAddressBook.itemChanged.connect(
"itemChanged(QTableWidgetItem *)"), self.tableWidgetAddressBookItemChanged) self.tableWidgetAddressBookItemChanged)
# This is necessary for the completer to work if multiple recipients # This is necessary for the completer to work if multiple recipients
QtCore.QObject.connect(self.ui.lineEditTo, QtCore.SIGNAL( self.ui.lineEditTo.cursorPositionChanged.connect(
"cursorPositionChanged(int, int)"), self.ui.lineEditTo.completer().onCursorPositionChanged) self.ui.lineEditTo.completer().onCursorPositionChanged)
# show messages from message list # show messages from message list
QtCore.QObject.connect(self.ui.tableWidgetInbox, QtCore.SIGNAL( for table_widget in (
"itemSelectionChanged ()"), self.tableWidgetInboxItemClicked) self.ui.tableWidgetInbox,
QtCore.QObject.connect(self.ui.tableWidgetInboxSubscriptions, QtCore.SIGNAL( self.ui.tableWidgetInboxSubscriptions,
"itemSelectionChanged ()"), self.tableWidgetInboxItemClicked) self.ui.tableWidgetInboxChans
QtCore.QObject.connect(self.ui.tableWidgetInboxChans, QtCore.SIGNAL( ):
"itemSelectionChanged ()"), self.tableWidgetInboxItemClicked) table_widget.itemSelectionChanged.connect(
self.tableWidgetInboxItemClicked)
# tree address lists # tree address lists
QtCore.QObject.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL( for tree_widget in (
"itemSelectionChanged ()"), self.treeWidgetItemClicked) self.ui.treeWidgetYourIdentities,
QtCore.QObject.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL( self.ui.treeWidgetSubscriptions,
"itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged) self.ui.treeWidgetChans
QtCore.QObject.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL( ):
"itemSelectionChanged ()"), self.treeWidgetItemClicked) tree_widget.itemSelectionChanged.connect(
QtCore.QObject.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL( self.treeWidgetItemClicked)
"itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged) tree_widget.itemChanged.connect(self.treeWidgetItemChanged)
QtCore.QObject.connect(self.ui.treeWidgetChans, QtCore.SIGNAL(
"itemSelectionChanged ()"), self.treeWidgetItemClicked) self.ui.tabWidget.currentChanged.connect(self.tabWidgetCurrentChanged)
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
)
# Put the colored icon on the status bar # Put the colored icon on the status bar
# self.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/yellowicon.png")) # self.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/yellowicon.png"))
self.setStatusBar(BMStatusBar()) self.setStatusBar(BMStatusBar())
self.statusbar = self.statusBar() self.statusbar = self.statusBar()
self.pushButtonStatusIcon = QtGui.QPushButton(self) self.pushButtonStatusIcon = QtWidgets.QPushButton(self)
self.pushButtonStatusIcon.setText('') self.pushButtonStatusIcon.setText('')
self.pushButtonStatusIcon.setIcon( self.pushButtonStatusIcon.setIcon(
QtGui.QIcon(':/newPrefix/images/redicon.png')) QtGui.QIcon(':/newPrefix/images/redicon.png'))
self.pushButtonStatusIcon.setFlat(True) self.pushButtonStatusIcon.setFlat(True)
self.statusbar.insertPermanentWidget(0, self.pushButtonStatusIcon) self.statusbar.insertPermanentWidget(0, self.pushButtonStatusIcon)
QtCore.QObject.connect(self.pushButtonStatusIcon, QtCore.SIGNAL( self.pushButtonStatusIcon.clicked.connect(
"clicked()"), self.click_pushButtonStatusIcon) self.click_pushButtonStatusIcon)
self.unreadCount = 0 self.unreadCount = 0
# Set the icon sizes for the identicons # Set the icon sizes for the identicons
identicon_size = 3*7 identicon_size = 3 * 7
self.ui.tableWidgetInbox.setIconSize(QtCore.QSize(identicon_size, identicon_size)) for widget in (
self.ui.treeWidgetChans.setIconSize(QtCore.QSize(identicon_size, identicon_size)) self.ui.tableWidgetInbox, self.ui.treeWidgetChans,
self.ui.treeWidgetYourIdentities.setIconSize(QtCore.QSize(identicon_size, identicon_size)) self.ui.treeWidgetYourIdentities, self.ui.treeWidgetSubscriptions,
self.ui.treeWidgetSubscriptions.setIconSize(QtCore.QSize(identicon_size, identicon_size)) self.ui.tableWidgetAddressBook
self.ui.tableWidgetAddressBook.setIconSize(QtCore.QSize(identicon_size, identicon_size)) ):
widget.setIconSize(QtCore.QSize(identicon_size, identicon_size))
self.UISignalThread = UISignaler.get() self.UISignalThread = UISignaler.get()
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.UISignalThread.writeNewAddressToTable.connect(
"writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable) self.writeNewAddressToTable)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.UISignalThread.updateStatusBar.connect(self.updateStatusBar)
"updateStatusBar(PyQt_PyObject)"), self.updateStatusBar) self.UISignalThread.updateSentItemStatusByToAddress.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.updateSentItemStatusByToAddress)
"updateSentItemStatusByToAddress(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByToAddress) self.UISignalThread.updateSentItemStatusByAckdata.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.updateSentItemStatusByAckdata)
"updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByAckdata) self.UISignalThread.displayNewInboxMessage.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.displayNewInboxMessage)
"displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewInboxMessage) self.UISignalThread.displayNewSentMessage.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.displayNewSentMessage)
"displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewSentMessage) self.UISignalThread.setStatusIcon.connect(self.setStatusIcon)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.UISignalThread.changedInboxUnread.connect(self.changedInboxUnread)
"setStatusIcon(PyQt_PyObject)"), self.setStatusIcon) self.UISignalThread.rerenderMessagelistFromLabels.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.rerenderMessagelistFromLabels)
"changedInboxUnread(PyQt_PyObject)"), self.changedInboxUnread) self.UISignalThread.rerenderMessagelistToLabels.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.rerenderMessagelistToLabels)
"rerenderMessagelistFromLabels()"), self.rerenderMessagelistFromLabels) self.UISignalThread.rerenderAddressBook.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.rerenderAddressBook)
"rerenderMessgelistToLabels()"), self.rerenderMessagelistToLabels) self.UISignalThread.rerenderSubscriptions.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.rerenderSubscriptions)
"rerenderAddressBook()"), self.rerenderAddressBook) self.UISignalThread.removeInboxRowByMsgid.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.removeInboxRowByMsgid)
"rerenderSubscriptions()"), self.rerenderSubscriptions) self.UISignalThread.newVersionAvailable.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.newVersionAvailable)
"removeInboxRowByMsgid(PyQt_PyObject)"), self.removeInboxRowByMsgid) self.UISignalThread.displayAlert.connect(self.displayAlert)
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.start() self.UISignalThread.start()
# Key press in tree view # Key press in tree view
@ -809,16 +787,15 @@ class MyForm(settingsmixin.SMainWindow):
# Put the TTL slider in the correct spot # Put the TTL slider in the correct spot
TTL = BMConfigParser().getint('bitmessagesettings', 'ttl') TTL = BMConfigParser().getint('bitmessagesettings', 'ttl')
if TTL < 3600: # an hour if TTL < 3600: # an hour
TTL = 3600 TTL = 3600
elif TTL > 28*24*60*60: # 28 days elif TTL > 28 * 24 * 60 * 60: # 28 days
TTL = 28*24*60*60 TTL = 28 * 24 * 60 * 60
self.ui.horizontalSliderTTL.setSliderPosition((TTL - 3600) ** (1/3.199)) self.ui.horizontalSliderTTL.setSliderPosition(
(TTL - 3600) ** (1 / 3.199))
self.updateHumanFriendlyTTLDescription(TTL) 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.initSettings()
self.resetNamecoinConnection() self.resetNamecoinConnection()
self.sqlInit() self.sqlInit()
@ -873,21 +850,25 @@ class MyForm(settingsmixin.SMainWindow):
BMConfigParser().save() BMConfigParser().save()
def updateHumanFriendlyTTLDescription(self, TTL): def updateHumanFriendlyTTLDescription(self, TTL):
numberOfHours = int(round(TTL / (60*60))) numberOfHours = int(round(TTL / (60 * 60)))
font = QtGui.QFont() font = QtGui.QFont()
stylesheet = "" stylesheet = ""
if numberOfHours < 48: if numberOfHours < 48:
self.ui.labelHumanFriendlyTTLDescription.setText( self.ui.labelHumanFriendlyTTLDescription.setText(
_translate("MainWindow", "%n hour(s)", None, QtCore.QCoreApplication.CodecForTr, numberOfHours) + _translate(
", " + "MainWindow", "%n hour(s)", None, numberOfHours
_translate("MainWindow", "not recommended for chans", None, QtCore.QCoreApplication.CodecForTr) ) + ",\n" +
) _translate("MainWindow", "not recommended for chans")
)
stylesheet = "QLabel { color : red; }" stylesheet = "QLabel { color : red; }"
font.setBold(True) font.setBold(True)
else: else:
numberOfDays = int(round(TTL / (24*60*60))) numberOfDays = int(round(TTL / (24 * 60 * 60)))
self.ui.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%n day(s)", None, QtCore.QCoreApplication.CodecForTr, numberOfDays)) self.ui.labelHumanFriendlyTTLDescription.setText(
_translate(
"MainWindow", "%n day(s)", None, numberOfDays)
)
font.setBold(False) font.setBold(False)
self.ui.labelHumanFriendlyTTLDescription.setStyleSheet(stylesheet) self.ui.labelHumanFriendlyTTLDescription.setStyleSheet(stylesheet)
self.ui.labelHumanFriendlyTTLDescription.setFont(font) self.ui.labelHumanFriendlyTTLDescription.setFont(font)
@ -1115,20 +1096,19 @@ class MyForm(settingsmixin.SMainWindow):
elif status == 'msgsent': elif status == 'msgsent':
statusText = _translate( statusText = _translate(
"MainWindow", "MainWindow",
"Message sent. Waiting for acknowledgement. Sent at %1" "Message sent. Waiting for acknowledgement. Sent at {0}"
).arg(l10n.formatTimestamp(lastactiontime)) ).format(l10n.formatTimestamp(lastactiontime))
elif status == 'msgsentnoackexpected': elif status == 'msgsentnoackexpected':
statusText = _translate( statusText = _translate(
"MainWindow", "Message sent. Sent at %1" "MainWindow", "Message sent. Sent at {0}"
).arg(l10n.formatTimestamp(lastactiontime)) ).format(l10n.formatTimestamp(lastactiontime))
elif status == 'doingmsgpow': elif status == 'doingmsgpow':
statusText = _translate( statusText = _translate(
"MainWindow", "Doing work necessary to send message.") "MainWindow", "Doing work necessary to send message.")
elif status == 'ackreceived': elif status == 'ackreceived':
statusText = _translate( statusText = _translate(
"MainWindow", "MainWindow", "Acknowledgement of the message received {0}"
"Acknowledgement of the message received %1" ).format(l10n.formatTimestamp(lastactiontime))
).arg(l10n.formatTimestamp(lastactiontime))
elif status == 'broadcastqueued': elif status == 'broadcastqueued':
statusText = _translate( statusText = _translate(
"MainWindow", "Broadcast queued.") "MainWindow", "Broadcast queued.")
@ -1136,36 +1116,34 @@ class MyForm(settingsmixin.SMainWindow):
statusText = _translate( statusText = _translate(
"MainWindow", "Doing work necessary to send broadcast.") "MainWindow", "Doing work necessary to send broadcast.")
elif status == 'broadcastsent': elif status == 'broadcastsent':
statusText = _translate("MainWindow", "Broadcast on %1").arg( statusText = _translate("MainWindow", "Broadcast on {0}").format(
l10n.formatTimestamp(lastactiontime)) l10n.formatTimestamp(lastactiontime)
)
elif status == 'toodifficult': elif status == 'toodifficult':
statusText = _translate( statusText = _translate(
"MainWindow", "MainWindow",
"Problem: The work demanded by the recipient is more" "Problem: The work demanded by the recipient is more"
" difficult than you are willing to do. %1" " difficult than you are willing to do. {0}"
).arg(l10n.formatTimestamp(lastactiontime)) ).format(l10n.formatTimestamp(lastactiontime))
elif status == 'badkey': elif status == 'badkey':
statusText = _translate( statusText = _translate(
"MainWindow", "MainWindow",
"Problem: The recipient\'s encryption key is no good." "Problem: The recipient\'s encryption key is no good."
" Could not encrypt message. %1" " Could not encrypt message. {0}"
).arg(l10n.formatTimestamp(lastactiontime)) ).format(l10n.formatTimestamp(lastactiontime))
elif status == 'forcepow': elif status == 'forcepow':
statusText = _translate( statusText = _translate(
"MainWindow", "MainWindow",
"Forced difficulty override. Send should start soon.") "Forced difficulty override. Send should start soon.")
else: else:
statusText = _translate( statusText = _translate(
"MainWindow", "Unknown status: %1 %2").arg(status).arg( "MainWindow", "Unknown status: {0} {1}"
l10n.formatTimestamp(lastactiontime)) ).format(status, l10n.formatTimestamp(lastactiontime))
items = [ items = [
MessageList_AddressWidget( MessageList_AddressWidget(toAddress, acct.toLabel),
toAddress, unicode(acct.toLabel, 'utf-8')), MessageList_AddressWidget(fromAddress, acct.fromLabel),
MessageList_AddressWidget( MessageList_SubjectWidget(subject, acct.subject),
fromAddress, unicode(acct.fromLabel, 'utf-8')),
MessageList_SubjectWidget(
str(subject), unicode(acct.subject, 'utf-8', 'replace')),
MessageList_TimeWidget( MessageList_TimeWidget(
statusText, False, lastactiontime, ackdata)] statusText, False, lastactiontime, ackdata)]
self.addMessageListItem(tableWidget, items) self.addMessageListItem(tableWidget, items)
@ -1185,13 +1163,9 @@ class MyForm(settingsmixin.SMainWindow):
acct.parseMessage(toAddress, fromAddress, subject, "") acct.parseMessage(toAddress, fromAddress, subject, "")
items = [ items = [
MessageList_AddressWidget( MessageList_AddressWidget(toAddress, acct.toLabel, not read),
toAddress, unicode(acct.toLabel, 'utf-8'), not read), MessageList_AddressWidget(fromAddress, acct.fromLabel, not read),
MessageList_AddressWidget( MessageList_SubjectWidget(subject, acct.subject, not read),
fromAddress, unicode(acct.fromLabel, 'utf-8'), not read),
MessageList_SubjectWidget(
str(subject), unicode(acct.subject, 'utf-8', 'replace'),
not read),
MessageList_TimeWidget( MessageList_TimeWidget(
l10n.formatTimestamp(received), not read, received, msgid) l10n.formatTimestamp(received), not read, received, msgid)
] ]
@ -1260,7 +1234,7 @@ class MyForm(settingsmixin.SMainWindow):
for row in queryreturn: for row in queryreturn:
toAddress, fromAddress, subject, _, msgid, received, read = row toAddress, fromAddress, subject, _, msgid, received, read = row
self.addMessageListItemInbox( self.addMessageListItemInbox(
tableWidget, toAddress, fromAddress, subject, tableWidget, toAddress, fromAddress, unicode(subject, 'utf-8'),
msgid, received, read) msgid, received, read)
tableWidget.horizontalHeader().setSortIndicator( tableWidget.horizontalHeader().setSortIndicator(
@ -1274,23 +1248,21 @@ class MyForm(settingsmixin.SMainWindow):
# create application indicator # create application indicator
def appIndicatorInit(self, app): def appIndicatorInit(self, app):
self.initTrayIcon("can-icon-24px-red.png", app) self.initTrayIcon("can-icon-24px-red.png", app)
traySignal = "activated(QSystemTrayIcon::ActivationReason)" self.tray.activated.connect(self.__icon_activated)
QtCore.QObject.connect(self.tray, QtCore.SIGNAL(
traySignal), 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) "MainWindow", "Not Connected"), m, checkable=False)
m.addAction(self.actionStatus) m.addAction(self.actionStatus)
# separator # separator
actionSeparator = QtGui.QAction('', m, checkable=False) actionSeparator = QtWidgets.QAction('', m, checkable=False)
actionSeparator.setSeparator(True) actionSeparator.setSeparator(True)
m.addAction(actionSeparator) m.addAction(actionSeparator)
# show bitmessage # show bitmessage
self.actionShow = QtGui.QAction(_translate( self.actionShow = QtWidgets.QAction(_translate(
"MainWindow", "Show Bitmessage"), m, checkable=True) "MainWindow", "Show Bitmessage"), m, checkable=True)
self.actionShow.setChecked(not BMConfigParser().getboolean( self.actionShow.setChecked(not BMConfigParser().getboolean(
'bitmessagesettings', 'startintray')) 'bitmessagesettings', 'startintray'))
@ -1299,7 +1271,7 @@ class MyForm(settingsmixin.SMainWindow):
m.addAction(self.actionShow) m.addAction(self.actionShow)
# quiet mode # quiet mode
self.actionQuiet = QtGui.QAction(_translate( self.actionQuiet = QtWidgets.QAction(_translate(
"MainWindow", "Quiet Mode"), m, checkable=True) "MainWindow", "Quiet Mode"), m, checkable=True)
self.actionQuiet.setChecked(not BMConfigParser().getboolean( self.actionQuiet.setChecked(not BMConfigParser().getboolean(
'bitmessagesettings', 'showtraynotifications')) 'bitmessagesettings', 'showtraynotifications'))
@ -1307,25 +1279,25 @@ class MyForm(settingsmixin.SMainWindow):
m.addAction(self.actionQuiet) m.addAction(self.actionQuiet)
# Send # Send
actionSend = QtGui.QAction(_translate( actionSend = QtWidgets.QAction(_translate(
"MainWindow", "Send"), m, checkable=False) "MainWindow", "Send"), m, checkable=False)
actionSend.triggered.connect(self.appIndicatorSend) actionSend.triggered.connect(self.appIndicatorSend)
m.addAction(actionSend) m.addAction(actionSend)
# Subscribe # Subscribe
actionSubscribe = QtGui.QAction(_translate( actionSubscribe = QtWidgets.QAction(_translate(
"MainWindow", "Subscribe"), m, checkable=False) "MainWindow", "Subscribe"), m, checkable=False)
actionSubscribe.triggered.connect(self.appIndicatorSubscribe) actionSubscribe.triggered.connect(self.appIndicatorSubscribe)
m.addAction(actionSubscribe) m.addAction(actionSubscribe)
# Channels # Channels
actionSubscribe = QtGui.QAction(_translate( actionSubscribe = QtWidgets.QAction(_translate(
"MainWindow", "Channel"), m, checkable=False) "MainWindow", "Channel"), m, checkable=False)
actionSubscribe.triggered.connect(self.appIndicatorChannel) actionSubscribe.triggered.connect(self.appIndicatorChannel)
m.addAction(actionSubscribe) m.addAction(actionSubscribe)
# separator # separator
actionSeparator = QtGui.QAction('', m, checkable=False) actionSeparator = QtWidgets.QAction('', m, checkable=False)
actionSeparator.setSeparator(True) actionSeparator.setSeparator(True)
m.addAction(actionSeparator) m.addAction(actionSeparator)
@ -1442,11 +1414,10 @@ class MyForm(settingsmixin.SMainWindow):
def notifierInit(self): def notifierInit(self):
def _simple_notify( def _simple_notify(
title, subtitle, category, label=None, icon=None): 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 self._notifier = _simple_notify
# does nothing if isAvailable returns false
self._player = QtGui.QSound.play
if not get_plugins: if not get_plugins:
return return
@ -1459,7 +1430,10 @@ class MyForm(settingsmixin.SMainWindow):
self._theme_player = get_plugin('notification.sound', 'theme') 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( _plugin = get_plugin(
'notification.sound', 'file', fallback='file.fallback') 'notification.sound', 'file', fallback='file.fallback')
if _plugin: if _plugin:
@ -1483,7 +1457,7 @@ class MyForm(settingsmixin.SMainWindow):
if event.key() == QtCore.Qt.Key_Delete: if event.key() == QtCore.Qt.Key_Delete:
self.on_action_AddressBookDelete() self.on_action_AddressBookDelete()
else: else:
return QtGui.QTableWidget.keyPressEvent( return QtWidgets.QTableWidget.keyPressEvent(
self.ui.tableWidgetAddressBook, event) self.ui.tableWidgetAddressBook, event)
# inbox / sent # inbox / sent
@ -1498,14 +1472,14 @@ class MyForm(settingsmixin.SMainWindow):
"""This method handles keypress events for all widgets on MyForm""" """This method handles keypress events for all widgets on MyForm"""
messagelist = self.getCurrentMessagelist() messagelist = self.getCurrentMessagelist()
if event.key() == QtCore.Qt.Key_Delete: if event.key() == QtCore.Qt.Key_Delete:
if isinstance(focus, (MessageView, QtGui.QTableWidget)): if isinstance(focus, (MessageView, QtWidgets.QTableWidget)):
folder = self.getCurrentFolder() folder = self.getCurrentFolder()
if folder == "sent": if folder == "sent":
self.on_action_SentTrash() self.on_action_SentTrash()
else: else:
self.on_action_InboxTrash() self.on_action_InboxTrash()
event.ignore() event.ignore()
elif QtGui.QApplication.queryKeyboardModifiers() == QtCore.Qt.NoModifier: elif QtWidgets.QApplication.queryKeyboardModifiers() == QtCore.Qt.NoModifier:
if event.key() == QtCore.Qt.Key_N: if event.key() == QtCore.Qt.Key_N:
currentRow = messagelist.currentRow() currentRow = messagelist.currentRow()
if currentRow < messagelist.rowCount() - 1: if currentRow < messagelist.rowCount() - 1:
@ -1544,38 +1518,77 @@ class MyForm(settingsmixin.SMainWindow):
return return
if isinstance(focus, MessageView): if isinstance(focus, MessageView):
return MessageView.keyPressEvent(focus, event) return MessageView.keyPressEvent(focus, event)
if isinstance(focus, QtGui.QTableWidget): elif isinstance(focus, QtWidgets.QTableWidget):
return QtGui.QTableWidget.keyPressEvent(focus, event) return QtWidgets.QTableWidget.keyPressEvent(focus, event)
if isinstance(focus, QtGui.QTreeWidget): elif isinstance(focus, QtWidgets.QTreeWidget):
return QtGui.QTreeWidget.keyPressEvent(focus, event) return QtWidgets.QTreeWidget.keyPressEvent(focus, event)
# menu button 'manage keys' # menu button 'manage keys'
def click_actionManageKeys(self): def click_actionManageKeys(self):
if 'darwin' in sys.platform or 'linux' in sys.platform: if 'darwin' in sys.platform or 'linux' in sys.platform:
if state.appdata == '': 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 # may manage your keys by editing the keys.dat file stored in
# the same directory as this program. It is important that you # the same directory as this program. It is important that you
# back up this file.', QMessageBox.Ok) # back up this file.', QMessageBox.Ok)
reply = QtGui.QMessageBox.information(self, 'keys.dat?', _translate( reply = QtWidgets.QMessageBox.information(
"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) 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: else:
QtGui.QMessageBox.information(self, 'keys.dat?', _translate( QtWidgets.QMessageBox.information(
"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) 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': elif sys.platform == 'win32' or sys.platform == 'win64':
if state.appdata == '': if state.appdata == '':
reply = QtGui.QMessageBox.question(self, _translate("MainWindow", "Open keys.dat?"), _translate( reply = QtWidgets.QMessageBox.question(
"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) 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: else:
reply = QtGui.QMessageBox.question(self, _translate("MainWindow", "Open keys.dat?"), _translate( reply = QtWidgets.QMessageBox.question(
"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) self,
if reply == QtGui.QMessageBox.Yes: _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() openKeysFile()
# menu button 'delete all treshed messages' # menu button 'delete all treshed messages'
def click_actionDeleteAllTrashedMessages(self): 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 return
sqlStoredProcedure('deleteandvacuume') sqlStoredProcedure('deleteandvacuume')
self.rerenderTabTreeMessages() self.rerenderTabTreeMessages()
@ -1593,7 +1606,7 @@ class MyForm(settingsmixin.SMainWindow):
dialog = dialogs.RegenerateAddressesDialog(self) dialog = dialogs.RegenerateAddressesDialog(self)
if dialog.exec_(): if dialog.exec_():
if dialog.lineEditPassphrase.text() == "": if dialog.lineEditPassphrase.text() == "":
QtGui.QMessageBox.about( QtWidgets.QMessageBox.about(
self, _translate("MainWindow", "bad passphrase"), self, _translate("MainWindow", "bad passphrase"),
_translate( _translate(
"MainWindow", "MainWindow",
@ -1606,7 +1619,7 @@ class MyForm(settingsmixin.SMainWindow):
addressVersionNumber = int( addressVersionNumber = int(
dialog.lineEditAddressVersionNumber.text()) dialog.lineEditAddressVersionNumber.text())
except: except:
QtGui.QMessageBox.about( QtWidgets.QMessageBox.about(
self, self,
_translate("MainWindow", "Bad address version number"), _translate("MainWindow", "Bad address version number"),
_translate( _translate(
@ -1616,7 +1629,7 @@ class MyForm(settingsmixin.SMainWindow):
)) ))
return return
if addressVersionNumber < 3 or addressVersionNumber > 4: if addressVersionNumber < 3 or addressVersionNumber > 4:
QtGui.QMessageBox.about( QtWidgets.QMessageBox.about(
self, self,
_translate("MainWindow", "Bad address version number"), _translate("MainWindow", "Bad address version number"),
_translate( _translate(
@ -1629,7 +1642,7 @@ class MyForm(settingsmixin.SMainWindow):
addressVersionNumber, streamNumberForAddress, addressVersionNumber, streamNumberForAddress,
"regenerated deterministic address", "regenerated deterministic address",
dialog.spinBoxNumberOfAddressesToMake.value(), dialog.spinBoxNumberOfAddressesToMake.value(),
dialog.lineEditPassphrase.text().toUtf8(), dialog.lineEditPassphrase.text().encode('utf-8'),
dialog.checkBoxEighteenByteRipe.isChecked() dialog.checkBoxEighteenByteRipe.isChecked()
)) ))
self.ui.tabWidget.setCurrentIndex( self.ui.tabWidget.setCurrentIndex(
@ -1653,13 +1666,6 @@ class MyForm(settingsmixin.SMainWindow):
else: else:
self._firstrun = False self._firstrun = False
def showMigrationWizard(self, level):
self.migrationWizardInstance = Ui_MigrationWizard(["a"])
if self.migrationWizardInstance.exec_():
pass
else:
pass
def changeEvent(self, event): def changeEvent(self, event):
if event.type() == QtCore.QEvent.LanguageChange: if event.type() == QtCore.QEvent.LanguageChange:
self.ui.retranslateUi(self) self.ui.retranslateUi(self)
@ -1680,7 +1686,7 @@ class MyForm(settingsmixin.SMainWindow):
pass pass
def __icon_activated(self, reason): def __icon_activated(self, reason):
if reason == QtGui.QSystemTrayIcon.Trigger: if reason == QtWidgets.QSystemTrayIcon.Trigger:
self.actionShow.setChecked(not self.actionShow.isChecked()) self.actionShow.setChecked(not self.actionShow.isChecked())
self.appIndicatorShowOrHideWindow() self.appIndicatorShowOrHideWindow()
@ -1753,7 +1759,7 @@ class MyForm(settingsmixin.SMainWindow):
def initTrayIcon(self, iconFileName, app): def initTrayIcon(self, iconFileName, app):
self.currentTrayIconFileName = iconFileName self.currentTrayIconFileName = iconFileName
self.tray = QtGui.QSystemTrayIcon( self.tray = QtWidgets.QSystemTrayIcon(
self.calcTrayIcon(iconFileName, self.findInboxUnreadCount()), app) self.calcTrayIcon(iconFileName, self.findInboxUnreadCount()), app)
def setTrayIconFile(self, iconFileName): def setTrayIconFile(self, iconFileName):
@ -1785,8 +1791,7 @@ class MyForm(settingsmixin.SMainWindow):
# draw text # draw text
painter = QtGui.QPainter() painter = QtGui.QPainter()
painter.begin(pixmap) painter.begin(pixmap)
painter.setPen( painter.setPen(QtGui.QPen(QtGui.QColor(255, 0, 0)))
QtGui.QPen(QtGui.QColor(255, 0, 0), QtCore.Qt.SolidPattern))
painter.setFont(font) painter.setFont(font)
painter.drawText(24-rect.right()-marginX, -rect.top()+marginY, txt) painter.drawText(24-rect.right()-marginX, -rect.top()+marginY, txt)
painter.end() painter.end()
@ -1833,8 +1838,11 @@ class MyForm(settingsmixin.SMainWindow):
if toAddress == rowAddress: if toAddress == rowAddress:
sent.item(i, 3).setToolTip(textToDisplay) sent.item(i, 3).setToolTip(textToDisplay)
try: try:
newlinePosition = textToDisplay.indexOf('\n') newlinePosition = textToDisplay.find('\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. # If someone misses adding a "_translate" to a string
# before passing it to this function
# ? why textToDisplay isn't unicode
except AttributeError:
newlinePosition = 0 newlinePosition = 0
if newlinePosition > 1: if newlinePosition > 1:
sent.item(i, 3).setText( sent.item(i, 3).setText(
@ -1843,8 +1851,6 @@ class MyForm(settingsmixin.SMainWindow):
sent.item(i, 3).setText(textToDisplay) sent.item(i, 3).setText(textToDisplay)
def updateSentItemStatusByAckdata(self, ackdata, textToDisplay): def updateSentItemStatusByAckdata(self, ackdata, textToDisplay):
if type(ackdata) is str:
ackdata = QtCore.QByteArray(ackdata)
for sent in ( for sent in (
self.ui.tableWidgetInbox, self.ui.tableWidgetInbox,
self.ui.tableWidgetInboxSubscriptions, self.ui.tableWidgetInboxSubscriptions,
@ -1854,21 +1860,22 @@ class MyForm(settingsmixin.SMainWindow):
if self.getCurrentFolder(treeWidget) != "sent": if self.getCurrentFolder(treeWidget) != "sent":
continue continue
for i in range(sent.rowCount()): for i in range(sent.rowCount()):
toAddress = sent.item(i, 0).data(QtCore.Qt.UserRole) # toAddress = sent.item(i, 0).data(QtCore.Qt.UserRole)
tableAckdata = sent.item(i, 3).data() # decodeAddress(toAddress)
status, addressVersionNumber, streamNumber, ripe = decodeAddress(
toAddress) if sent.item(i, 3).data() == ackdata:
if ackdata == tableAckdata:
sent.item(i, 3).setToolTip(textToDisplay) sent.item(i, 3).setToolTip(textToDisplay)
try: try:
newlinePosition = textToDisplay.indexOf('\n') newlinePosition = textToDisplay.find('\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. # If someone misses adding a "_translate" to a string
# before passing it to this function
# ? why textToDisplay isn't unicode
except AttributeError:
newlinePosition = 0 newlinePosition = 0
if newlinePosition > 1: if newlinePosition > 1:
sent.item(i, 3).setText( textToDisplay = textToDisplay[:newlinePosition]
textToDisplay[:newlinePosition])
else: sent.item(i, 3).setText(textToDisplay)
sent.item(i, 3).setText(textToDisplay)
def removeInboxRowByMsgid(self, msgid): def removeInboxRowByMsgid(self, msgid):
# msgid and inventoryHash are the same thing # msgid and inventoryHash are the same thing
@ -1896,33 +1903,42 @@ class MyForm(settingsmixin.SMainWindow):
self.notifiedNewVersion = ".".join(str(n) for n in version) self.notifiedNewVersion = ".".join(str(n) for n in version)
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"New version of PyBitmessage is available: %1. Download it" "New version of PyBitmessage is available: {0}. Download it"
" from https://github.com/Bitmessage/PyBitmessage/releases/latest" " from https://github.com/Bitmessage/PyBitmessage/releases/latest"
).arg(self.notifiedNewVersion) ).format(self.notifiedNewVersion)
) )
def displayAlert(self, title, text, exitAfterUserClicksOk): def displayAlert(self, title, text, exitAfterUserClicksOk):
self.updateStatusBar(text) self.updateStatusBar(text)
QtGui.QMessageBox.critical(self, title, text, QtGui.QMessageBox.Ok) QtWidgets.QMessageBox.critical(
self, title, text, QtWidgets.QMessageBox.Ok)
if exitAfterUserClicksOk: if exitAfterUserClicksOk:
os._exit(0) os._exit(0)
def rerenderMessagelistFromLabels(self): def rerenderMessagelistFromLabels(self):
for messagelist in (self.ui.tableWidgetInbox, self.ui.tableWidgetInboxChans, self.ui.tableWidgetInboxSubscriptions): for messagelist in (
self.ui.tableWidgetInbox,
self.ui.tableWidgetInboxChans,
self.ui.tableWidgetInboxSubscriptions
):
for i in range(messagelist.rowCount()): for i in range(messagelist.rowCount()):
messagelist.item(i, 1).setLabel() messagelist.item(i, 1).setLabel()
def rerenderMessagelistToLabels(self): def rerenderMessagelistToLabels(self):
for messagelist in (self.ui.tableWidgetInbox, self.ui.tableWidgetInboxChans, self.ui.tableWidgetInboxSubscriptions): for messagelist in (
self.ui.tableWidgetInbox,
self.ui.tableWidgetInboxChans,
self.ui.tableWidgetInboxSubscriptions
):
for i in range(messagelist.rowCount()): for i in range(messagelist.rowCount()):
messagelist.item(i, 0).setLabel() messagelist.item(i, 0).setLabel()
def rerenderAddressBook(self): def rerenderAddressBook(self):
def addRow (address, label, type): def addRow(address, label, type):
self.ui.tableWidgetAddressBook.insertRow(0) self.ui.tableWidgetAddressBook.insertRow(0)
newItem = Ui_AddressBookWidgetItemLabel(address, unicode(label, 'utf-8'), type) newItem = Ui_AddressBookWidgetItemLabel(address, label, type)
self.ui.tableWidgetAddressBook.setItem(0, 0, newItem) self.ui.tableWidgetAddressBook.setItem(0, 0, newItem)
newItem = Ui_AddressBookWidgetItemAddress(address, unicode(label, 'utf-8'), type) newItem = Ui_AddressBookWidgetItemAddress(address, label, type)
self.ui.tableWidgetAddressBook.setItem(0, 1, newItem) self.ui.tableWidgetAddressBook.setItem(0, 1, newItem)
oldRows = {} oldRows = {}
@ -1940,18 +1956,21 @@ class MyForm(settingsmixin.SMainWindow):
queryreturn = sqlQuery('SELECT label, address FROM subscriptions WHERE enabled = 1') queryreturn = sqlQuery('SELECT label, address FROM subscriptions WHERE enabled = 1')
for row in queryreturn: for row in queryreturn:
label, address = row label, address = row
newRows[address] = [label, AccountMixin.SUBSCRIPTION] newRows[address] = [unicode(label, 'utf-8'), AccountMixin.SUBSCRIPTION]
# chans # chans
addresses = getSortedAccounts() addresses = getSortedAccounts()
for address in addresses: for address in addresses:
account = accountClass(address) account = accountClass(address)
if (account.type == AccountMixin.CHAN and BMConfigParser().safeGetBoolean(address, 'enabled')): if (
account.type == AccountMixin.CHAN
and BMConfigParser().safeGetBoolean(address, 'enabled')
):
newRows[address] = [account.getLabel(), AccountMixin.CHAN] newRows[address] = [account.getLabel(), AccountMixin.CHAN]
# normal accounts # normal accounts
queryreturn = sqlQuery('SELECT * FROM addressbook') queryreturn = sqlQuery('SELECT * FROM addressbook')
for row in queryreturn: for row in queryreturn:
label, address = row label, address = row
newRows[address] = [label, AccountMixin.NORMAL] newRows[address] = [unicode(label, 'utf-8'), AccountMixin.NORMAL]
completerList = [] completerList = []
for address in sorted( for address in sorted(
@ -1964,7 +1983,7 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.tableWidgetAddressBook.removeRow(oldRows[address][2]) self.ui.tableWidgetAddressBook.removeRow(oldRows[address][2])
for address in newRows: for address in newRows:
addRow(address, newRows[address][0], newRows[address][1]) addRow(address, newRows[address][0], newRows[address][1])
completerList.append(unicode(newRows[address][0], encoding="UTF-8") + " <" + address + ">") completerList.append(newRows[address][0] + " <" + address + ">")
# sort # sort
self.ui.tableWidgetAddressBook.sortByColumn( self.ui.tableWidgetAddressBook.sortByColumn(
@ -1976,11 +1995,17 @@ class MyForm(settingsmixin.SMainWindow):
self.rerenderTabTreeSubscriptions() self.rerenderTabTreeSubscriptions()
def click_pushButtonTTL(self): def click_pushButtonTTL(self):
QtGui.QMessageBox.information(self, 'Time To Live', _translate( QtWidgets.QMessageBox.information(
"MainWindow", """The TTL, or Time-To-Live is the length of time that the network will hold the message. self, 'Time To Live', _translate(
The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it "MainWindow",
will resend the message automatically. The longer the Time-To-Live, the "The TTL, or Time-To-Live is the length of time that"
more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate."""), QtGui.QMessageBox.Ok) " the network will hold the message. The recipient must"
" get it during this time. If your Bitmessage client does"
" not hear an acknowledgement, it will resend the message"
" automatically. The longer the Time-To-Live, the more"
" work your computer must do to send the message. A"
" Time-To-Live of four or five days is often appropriate."
), QtWidgets.QMessageBox.Ok)
def click_pushButtonClear(self): def click_pushButtonClear(self):
self.ui.lineEditSubject.setText("") self.ui.lineEditSubject.setText("")
@ -1989,7 +2014,10 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.comboBoxSendFrom.setCurrentIndex(0) self.ui.comboBoxSendFrom.setCurrentIndex(0)
def click_pushButtonSend(self): def click_pushButtonSend(self):
encoding = 3 if QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ShiftModifier else 2 # pylint: disable=too-many-locals
encoding = (
3 if QtWidgets.QApplication.queryKeyboardModifiers()
& QtCore.Qt.ShiftModifier else 2)
self.statusbar.clearMessage() self.statusbar.clearMessage()
@ -1997,38 +2025,36 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.tabWidgetSend.indexOf(self.ui.sendDirect): self.ui.tabWidgetSend.indexOf(self.ui.sendDirect):
# message to specific people # message to specific people
sendMessageToPeople = True sendMessageToPeople = True
fromAddress = str(self.ui.comboBoxSendFrom.itemData( fromAddress = self.ui.comboBoxSendFrom.itemData(
self.ui.comboBoxSendFrom.currentIndex(), self.ui.comboBoxSendFrom.currentIndex(),
QtCore.Qt.UserRole).toString()) QtCore.Qt.UserRole)
toAddresses = str(self.ui.lineEditTo.text().toUtf8()) toAddresses = self.ui.lineEditTo.text()
subject = str(self.ui.lineEditSubject.text().toUtf8()) subject = self.ui.lineEditSubject.text()
message = str( message = self.ui.textEditMessage.document().toPlainText()
self.ui.textEditMessage.document().toPlainText().toUtf8())
else: else:
# broadcast message # broadcast message
sendMessageToPeople = False sendMessageToPeople = False
fromAddress = str(self.ui.comboBoxSendFromBroadcast.itemData( fromAddress = self.ui.comboBoxSendFromBroadcast.itemData(
self.ui.comboBoxSendFromBroadcast.currentIndex(), self.ui.comboBoxSendFromBroadcast.currentIndex(),
QtCore.Qt.UserRole).toString()) QtCore.Qt.UserRole)
subject = str(self.ui.lineEditSubjectBroadcast.text().toUtf8()) subject = self.ui.lineEditSubjectBroadcast.text()
message = str( message = \
self.ui.textEditMessageBroadcast.document().toPlainText().toUtf8()) self.ui.textEditMessageBroadcast.document().toPlainText()
"""
The whole network message must fit in 2^18 bytes. # The whole network message must fit in 2^18 bytes.
Let's assume 500 bytes of overhead. If someone wants to get that # Let's assume 500 bytes of overhead. If someone wants to get that
too an exact number you are welcome to but I think that it would # too an exact number you are welcome to but I think that it would
be a better use of time to support message continuation so that # be a better use of time to support message continuation so that
users can send messages of any length. # users can send messages of any length.
""" if len(message) > 2 ** 18 - 500:
if len(message) > (2 ** 18 - 500): QtWidgets.QMessageBox.about(
QtGui.QMessageBox.about(
self, _translate("MainWindow", "Message too long"), self, _translate("MainWindow", "Message too long"),
_translate( _translate(
"MainWindow", "MainWindow",
"The message that you are trying to send is too long" "The message that you are trying to send is too long"
" by %1 bytes. (The maximum is 261644 bytes). Please" " by {0} bytes. (The maximum is 261644 bytes). Please"
" cut it down before sending." " cut it down before sending."
).arg(len(message) - (2 ** 18 - 500))) ).format(len(message) - (2 ** 18 - 500)))
return return
acct = accountClass(fromAddress) acct = accountClass(fromAddress)
@ -2049,18 +2075,32 @@ class MyForm(settingsmixin.SMainWindow):
# email address # email address
if toAddress.find("@") >= 0: if toAddress.find("@") >= 0:
if isinstance(acct, GatewayAccount): if isinstance(acct, GatewayAccount):
acct.createMessage(toAddress, fromAddress, subject, message) acct.createMessage(
toAddress, fromAddress, subject, message)
subject = acct.subject subject = acct.subject
toAddress = acct.toAddress toAddress = acct.toAddress
else: else:
if QtGui.QMessageBox.question(self, "Sending an email?", _translate("MainWindow", if QtWidgets.QMessageBox.question(
"You are trying to send an email instead of a bitmessage. This requires registering with a gateway. Attempt to register?"), self, "Sending an email?",
QtGui.QMessageBox.Yes|QtGui.QMessageBox.No) != QtGui.QMessageBox.Yes: _translate(
"MainWindow",
"You are trying to send an email"
" instead of a bitmessage. This"
" requires registering with a"
" gateway. Attempt to register?"
), QtWidgets.QMessageBox.Yes
| QtWidgets.QMessageBox.No
) != QtWidgets.QMessageBox.Yes:
continue continue
email = acct.getLabel() email = acct.getLabel()
if email[-14:] != "@mailchuck.com": #attempt register # attempt register
if email[-14:] != "@mailchuck.com":
# 12 character random email address # 12 character random email address
email = ''.join(random.SystemRandom().choice(string.ascii_lowercase) for _ in range(12)) + "@mailchuck.com" email = u''.join(
random.SystemRandom().choice(
string.ascii_lowercase
) for _ in range(12)
) + "@mailchuck.com"
acct = MailchuckAccount(fromAddress) acct = MailchuckAccount(fromAddress)
acct.register(email) acct.register(email)
BMConfigParser().set(fromAddress, 'label', email) BMConfigParser().set(fromAddress, 'label', email)
@ -2070,75 +2110,79 @@ class MyForm(settingsmixin.SMainWindow):
"MainWindow", "MainWindow",
"Error: Your account wasn't registered at" "Error: Your account wasn't registered at"
" an email gateway. Sending registration" " an email gateway. Sending registration"
" now as %1, please wait for the registration" " now as {0}, please wait for the registration"
" to be processed before retrying sending." " to be processed before retrying sending."
).arg(email) ).format(email))
)
return return
status, addressVersionNumber, streamNumber = decodeAddress(toAddress)[:3] status, addressVersionNumber, streamNumber = \
decodeAddress(toAddress)[:3]
if status != 'success': if status != 'success':
try: try:
toAddress = unicode(toAddress, 'utf-8', 'ignore') toAddress_value = unicode(
toAddress, 'utf-8', 'ignore')
except: except:
pass logger.warning(
logger.error('Error: Could not decode recipient address ' + toAddress + ':' + status) "Failed unicode(toAddress ):", exc_info=True)
logger.error(
'Error: Could not decode recipient address %s: %s',
toAddress_value, status)
if status == 'missingbm': if status == 'missingbm':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Error: Bitmessage addresses start with" "Error: Bitmessage addresses start with"
" BM- Please check the recipient address %1" " BM- Please check the recipient address {0}"
).arg(toAddress)) ).format(toAddress_value))
elif status == 'checksumfailed': elif status == 'checksumfailed':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Error: The recipient address %1 is not" "Error: The recipient address {0} is not"
" typed or copied correctly. Please check it." " typed or copied correctly. Please check it."
).arg(toAddress)) ).format(toAddress_value))
elif status == 'invalidcharacters': elif status == 'invalidcharacters':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Error: The recipient address %1 contains" "Error: The recipient address {0} contains"
" invalid characters. Please check it." " invalid characters. Please check it."
).arg(toAddress)) ).format(toAddress_value))
elif status == 'versiontoohigh': elif status == 'versiontoohigh':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Error: The version of the recipient address" "Error: The version of the recipient address"
" %1 is too high. Either you need to upgrade" " {0} is too high. Either you need to upgrade"
" your Bitmessage software or your" " your Bitmessage software or your"
" acquaintance is being clever." " acquaintance is being clever."
).arg(toAddress)) ).format(toAddress_value))
elif status == 'ripetooshort': elif status == 'ripetooshort':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Error: Some data encoded in the recipient" "Error: Some data encoded in the recipient"
" address %1 is too short. There might be" " address {0} is too short. There might be"
" something wrong with the software of" " something wrong with the software of"
" your acquaintance." " your acquaintance."
).arg(toAddress)) ).format(toAddress_value))
elif status == 'ripetoolong': elif status == 'ripetoolong':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Error: Some data encoded in the recipient" "Error: Some data encoded in the recipient"
" address %1 is too long. There might be" " address {0} is too long. There might be"
" something wrong with the software of" " something wrong with the software of"
" your acquaintance." " your acquaintance."
).arg(toAddress)) ).format(toAddress_value))
elif status == 'varintmalformed': elif status == 'varintmalformed':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Error: Some data encoded in the recipient" "Error: Some data encoded in the recipient"
" address %1 is malformed. There might be" " address {0} is malformed. There might be"
" something wrong with the software of" " something wrong with the software of"
" your acquaintance." " your acquaintance."
).arg(toAddress)) ).format(toAddress_value))
else: else:
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Error: Something is wrong with the" "Error: Something is wrong with the"
" recipient address %1." " recipient address {0}."
).arg(toAddress)) ).format(toAddress_value))
elif fromAddress == '': elif fromAddress == '':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
@ -2150,12 +2194,31 @@ class MyForm(settingsmixin.SMainWindow):
toAddress = addBMIfNotPresent(toAddress) toAddress = addBMIfNotPresent(toAddress)
if addressVersionNumber > 4 or addressVersionNumber <= 1: if addressVersionNumber > 4 or addressVersionNumber <= 1:
QtGui.QMessageBox.about(self, _translate("MainWindow", "Address version number"), _translate( QtWidgets.QMessageBox.about(
"MainWindow", "Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version.").arg(toAddress).arg(str(addressVersionNumber))) self,
_translate(
"MainWindow", "Address version number"),
_translate(
"MainWindow",
"Concerning the address {0}, Bitmessage"
" cannot understand address version"
" numbers of {1}. Perhaps upgrade"
" Bitmessage to the latest version."
).format(toAddress, addressVersionNumber)
)
continue continue
if streamNumber > 1 or streamNumber == 0: if streamNumber > 1 or streamNumber == 0:
QtGui.QMessageBox.about(self, _translate("MainWindow", "Stream number"), _translate( QtWidgets.QMessageBox.about(
"MainWindow", "Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version.").arg(toAddress).arg(str(streamNumber))) self,
_translate("MainWindow", "Stream number"),
_translate(
"MainWindow",
"Concerning the address {0}, Bitmessage"
" cannot handle stream numbers of {1}."
" Perhaps upgrade Bitmessage to the"
" latest version."
).format(toAddress, streamNumber)
)
continue continue
self.statusbar.clearMessage() self.statusbar.clearMessage()
if state.statusIconColor == 'red': if state.statusIconColor == 'red':
@ -2240,11 +2303,11 @@ class MyForm(settingsmixin.SMainWindow):
)) ))
def click_pushButtonFetchNamecoinID(self): def click_pushButtonFetchNamecoinID(self):
identities = str(self.ui.lineEditTo.text().toUtf8()).split(";") identities = self.ui.lineEditTo.text().split(";")
err, addr = self.namecoin.query(identities[-1].strip()) err, addr = self.namecoin.query(identities[-1].strip())
if err is not None: if err is not None:
self.updateStatusBar( self.updateStatusBar(
_translate("MainWindow", "Error: %1").arg(err)) _translate("MainWindow", "Error: {0}").format(err))
else: else:
identities[-1] = addr identities[-1] = addr
self.ui.lineEditTo.setText("; ".join(identities)) self.ui.lineEditTo.setText("; ".join(identities))
@ -2274,8 +2337,8 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.comboBoxSendFrom.addItem(avatarize(addressInKeysFile), label, addressInKeysFile) self.ui.comboBoxSendFrom.addItem(avatarize(addressInKeysFile), label, addressInKeysFile)
# self.ui.comboBoxSendFrom.model().sort(1, Qt.AscendingOrder) # self.ui.comboBoxSendFrom.model().sort(1, Qt.AscendingOrder)
for i in range(self.ui.comboBoxSendFrom.count()): for i in range(self.ui.comboBoxSendFrom.count()):
address = str(self.ui.comboBoxSendFrom.itemData( address = self.ui.comboBoxSendFrom.itemData(
i, QtCore.Qt.UserRole).toString()) i, QtCore.Qt.UserRole)
self.ui.comboBoxSendFrom.setItemData( self.ui.comboBoxSendFrom.setItemData(
i, AccountColor(address).accountColor(), i, AccountColor(address).accountColor(),
QtCore.Qt.ForegroundRole) QtCore.Qt.ForegroundRole)
@ -2297,13 +2360,13 @@ class MyForm(settingsmixin.SMainWindow):
label = addressInKeysFile label = addressInKeysFile
self.ui.comboBoxSendFromBroadcast.addItem(avatarize(addressInKeysFile), label, addressInKeysFile) self.ui.comboBoxSendFromBroadcast.addItem(avatarize(addressInKeysFile), label, addressInKeysFile)
for i in range(self.ui.comboBoxSendFromBroadcast.count()): for i in range(self.ui.comboBoxSendFromBroadcast.count()):
address = str(self.ui.comboBoxSendFromBroadcast.itemData( address = self.ui.comboBoxSendFromBroadcast.itemData(
i, QtCore.Qt.UserRole).toString()) i, QtCore.Qt.UserRole)
self.ui.comboBoxSendFromBroadcast.setItemData( self.ui.comboBoxSendFromBroadcast.setItemData(
i, AccountColor(address).accountColor(), i, AccountColor(address).accountColor(),
QtCore.Qt.ForegroundRole) QtCore.Qt.ForegroundRole)
self.ui.comboBoxSendFromBroadcast.insertItem(0, '', '') self.ui.comboBoxSendFromBroadcast.insertItem(0, '', '')
if(self.ui.comboBoxSendFromBroadcast.count() == 2): if self.ui.comboBoxSendFromBroadcast.count() == 2:
self.ui.comboBoxSendFromBroadcast.setCurrentIndex(1) self.ui.comboBoxSendFromBroadcast.setCurrentIndex(1)
else: else:
self.ui.comboBoxSendFromBroadcast.setCurrentIndex(0) self.ui.comboBoxSendFromBroadcast.setCurrentIndex(0)
@ -2377,6 +2440,8 @@ class MyForm(settingsmixin.SMainWindow):
tableWidget = self.widgetConvert(treeWidget) tableWidget = self.widgetConvert(treeWidget)
current_account = self.getCurrentAccount(treeWidget) current_account = self.getCurrentAccount(treeWidget)
current_folder = self.getCurrentFolder(treeWidget) current_folder = self.getCurrentFolder(treeWidget)
# inventoryHash surprisingly is of type unicode
# inventoryHash = inventoryHash.encode('utf-8')
# pylint: disable=too-many-boolean-expressions # pylint: disable=too-many-boolean-expressions
if ((tableWidget == inbox if ((tableWidget == inbox
and current_account == acct.address and current_account == acct.address
@ -2397,15 +2462,14 @@ class MyForm(settingsmixin.SMainWindow):
'bitmessagesettings', 'showtraynotifications'): 'bitmessagesettings', 'showtraynotifications'):
self.notifierShow( self.notifierShow(
_translate("MainWindow", "New Message"), _translate("MainWindow", "New Message"),
_translate("MainWindow", "From %1").arg( _translate("MainWindow", "From {0}").format(acct.fromLabel),
unicode(acct.fromLabel, 'utf-8')),
sound.SOUND_UNKNOWN sound.SOUND_UNKNOWN
) )
if self.getCurrentAccount() is not None and ( if self.getCurrentAccount() is not None and (
(self.getCurrentFolder(treeWidget) != "inbox" (self.getCurrentFolder(treeWidget) != "inbox"
and self.getCurrentFolder(treeWidget) is not None) and self.getCurrentFolder(treeWidget) is not None)
or self.getCurrentAccount(treeWidget) != acct.address): or self.getCurrentAccount(treeWidget) != acct.address):
# Ubuntu should notify of new message irrespective of # Ubuntu should notify of new message irespective of
# whether it's in current message list or not # whether it's in current message list or not
self.indicatorUpdate(True, to_label=acct.toLabel) self.indicatorUpdate(True, to_label=acct.toLabel)
@ -2424,7 +2488,7 @@ class MyForm(settingsmixin.SMainWindow):
dialog.exec_() dialog.exec_()
try: try:
address, label = dialog.data address, label = dialog.data
except AttributeError: except (AttributeError, TypeError):
return return
# First we must check to see if the address is already in the # First we must check to see if the address is already in the
@ -2469,7 +2533,7 @@ class MyForm(settingsmixin.SMainWindow):
dialog.exec_() dialog.exec_()
try: try:
address, label = dialog.data address, label = dialog.data
except AttributeError: except (AttributeError, TypeError):
return return
# We must check to see if the address is already in the # We must check to see if the address is already in the
@ -2528,15 +2592,14 @@ class MyForm(settingsmixin.SMainWindow):
dialog = dialogs.EmailGatewayDialog(self, config=BMConfigParser()) dialog = dialogs.EmailGatewayDialog(self, config=BMConfigParser())
# For Modal dialogs # For Modal dialogs
dialog.exec_() dialog.exec_()
try: acct = dialog.data
acct = dialog.data if not acct:
except AttributeError:
return return
# Only settings remain here # Only settings remain here
acct.settings() acct.settings()
for i in range(self.ui.comboBoxSendFrom.count()): for i in range(self.ui.comboBoxSendFrom.count()):
if str(self.ui.comboBoxSendFrom.itemData(i).toPyObject()) \ if str(self.ui.comboBoxSendFrom.itemData(i)) \
== acct.fromAddress: == acct.fromAddress:
self.ui.comboBoxSendFrom.setCurrentIndex(i) self.ui.comboBoxSendFrom.setCurrentIndex(i)
break break
@ -2555,13 +2618,13 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.textEditMessage.setFocus() self.ui.textEditMessage.setFocus()
def on_action_MarkAllRead(self): def on_action_MarkAllRead(self):
if QtGui.QMessageBox.question( if QtWidgets.QMessageBox.question(
self, "Marking all messages as read?", self, "Marking all messages as read?",
_translate( _translate(
"MainWindow", "MainWindow",
"Are you sure you would like to mark all messages read?" "Are you sure you would like to mark all messages read?"
), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No ), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
) != QtGui.QMessageBox.Yes: ) != QtWidgets.QMessageBox.Yes:
return return
tableWidget = self.getCurrentMessagelist() tableWidget = self.getCurrentMessagelist()
@ -2572,7 +2635,7 @@ class MyForm(settingsmixin.SMainWindow):
msgids = [] msgids = []
for i in range(0, idCount): for i in range(0, idCount):
msgids.append(tableWidget.item(i, 3).data()) msgids.append(tableWidget.item(i, 3).data())
for col in xrange(tableWidget.columnCount()): for col in range(tableWidget.columnCount()):
tableWidget.item(i, col).setUnread(False) tableWidget.item(i, col).setUnread(False)
markread = sqlExecuteChunked( markread = sqlExecuteChunked(
@ -2589,7 +2652,7 @@ class MyForm(settingsmixin.SMainWindow):
def network_switch(self): def network_switch(self):
dontconnect_option = not BMConfigParser().safeGetBoolean( dontconnect_option = not BMConfigParser().safeGetBoolean(
'bitmessagesettings', 'dontconnect') 'bitmessagesettings', 'dontconnect')
reply = QtGui.QMessageBox.question( reply = QtWidgets.QMessageBox.question(
self, _translate("MainWindow", "Disconnecting") self, _translate("MainWindow", "Disconnecting")
if dontconnect_option else _translate("MainWindow", "Connecting"), if dontconnect_option else _translate("MainWindow", "Connecting"),
_translate( _translate(
@ -2598,9 +2661,9 @@ class MyForm(settingsmixin.SMainWindow):
) if dontconnect_option else _translate( ) if dontconnect_option else _translate(
"MainWindow", "MainWindow",
"Bitmessage will now start connecting to network. Are you sure?" "Bitmessage will now start connecting to network. Are you sure?"
), QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel, ), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel,
QtGui.QMessageBox.Cancel) QtWidgets.QMessageBox.Cancel)
if reply != QtGui.QMessageBox.Yes: if reply != QtWidgets.QMessageBox.Yes:
return return
BMConfigParser().set( BMConfigParser().set(
'bitmessagesettings', 'dontconnect', str(dontconnect_option)) 'bitmessagesettings', 'dontconnect', str(dontconnect_option))
@ -2626,68 +2689,67 @@ class MyForm(settingsmixin.SMainWindow):
waitForSync = False waitForSync = False
# C PoW currently doesn't support interrupting and OpenCL is untested # C PoW currently doesn't support interrupting and OpenCL is untested
if getPowType() == "python" and (powQueueSize() > 0 or pendingUpload() > 0): if getPowType() == "python" and (
reply = QtGui.QMessageBox.question( powQueueSize() > 0 or pendingUpload() > 0):
reply = QtWidgets.QMessageBox.question(
self, _translate("MainWindow", "Proof of work pending"), self, _translate("MainWindow", "Proof of work pending"),
_translate( _translate(
"MainWindow", "MainWindow",
"%n object(s) pending proof of work", None, "%n object(s) pending proof of work", None, powQueueSize()
QtCore.QCoreApplication.CodecForTr, powQueueSize() ) + ", "
) + ", " + + _translate(
_translate(
"MainWindow", "MainWindow",
"%n object(s) waiting to be distributed", None, "%n object(s) waiting to be distributed",
QtCore.QCoreApplication.CodecForTr, pendingUpload() None, pendingUpload()
) + "\n\n" + ) + "\n\n"
_translate( + _translate("MainWindow", "Wait until these tasks finish?"),
"MainWindow", "Wait until these tasks finish?"), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtWidgets.QMessageBox.Cancel, QtWidgets.QMessageBox.Cancel
| QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel) )
if reply == QtGui.QMessageBox.No: if reply == QtWidgets.QMessageBox.No:
waitForPow = False waitForPow = False
elif reply == QtGui.QMessageBox.Cancel: elif reply == QtWidgets.QMessageBox.Cancel:
return return
if pendingDownload() > 0: if pendingDownload() > 0:
reply = QtGui.QMessageBox.question( reply = QtWidgets.QMessageBox.question(
self, _translate("MainWindow", "Synchronisation pending"), self, _translate("MainWindow", "Synchronisation pending"),
_translate( _translate(
"MainWindow", "MainWindow",
"Bitmessage hasn't synchronised with the network," "Bitmessage hasn't synchronised with the network,"
" %n object(s) to be downloaded. If you quit now," " %n object(s) to be downloaded. If you quit now,"
" it may cause delivery delays. Wait until the" " it may cause delivery delays. Wait until the"
" synchronisation finishes?", None, " synchronisation finishes?",
QtCore.QCoreApplication.CodecForTr, pendingDownload() None, pendingDownload()
), ), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtWidgets.QMessageBox.Cancel, QtWidgets.QMessageBox.Cancel)
| QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel) if reply == QtWidgets.QMessageBox.Yes:
if reply == QtGui.QMessageBox.Yes:
self.wait = waitForSync = True self.wait = waitForSync = True
elif reply == QtGui.QMessageBox.Cancel: elif reply == QtWidgets.QMessageBox.Cancel:
return return
if state.statusIconColor == 'red' and not BMConfigParser().safeGetBoolean( if state.statusIconColor == 'red' \
and not BMConfigParser().safeGetBoolean(
'bitmessagesettings', 'dontconnect'): 'bitmessagesettings', 'dontconnect'):
reply = QtGui.QMessageBox.question( reply = QtWidgets.QMessageBox.question(
self, _translate("MainWindow", "Not connected"), self, _translate("MainWindow", "Not connected"),
_translate( _translate(
"MainWindow", "MainWindow",
"Bitmessage isn't connected to the network. If you" "Bitmessage isn't connected to the network. If you"
" quit now, it may cause delivery delays. Wait until" " quit now, it may cause delivery delays. Wait until"
" connected and the synchronisation finishes?" " connected and the synchronisation finishes?"
), ), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtWidgets.QMessageBox.Cancel, QtWidgets.QMessageBox.Cancel)
| QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel) if reply == QtWidgets.QMessageBox.Yes:
if reply == QtGui.QMessageBox.Yes:
waitForConnection = True waitForConnection = True
self.wait = waitForSync = True self.wait = waitForSync = True
elif reply == QtGui.QMessageBox.Cancel: elif reply == QtWidgets.QMessageBox.Cancel:
return return
self.quitAccepted = True self.quitAccepted = True
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "Shutting down PyBitmessage... %1%").arg(0)) "MainWindow", "Shutting down PyBitmessage... {0}%").format(0))
if waitForConnection: if waitForConnection:
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
@ -2721,16 +2783,18 @@ class MyForm(settingsmixin.SMainWindow):
maxWorkerQueue = curWorkerQueue maxWorkerQueue = curWorkerQueue
if curWorkerQueue > 0: if curWorkerQueue > 0:
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "Waiting for PoW to finish... %1%" "MainWindow", "Waiting for PoW to finish... {0}%"
).arg(50 * (maxWorkerQueue - curWorkerQueue) / ).format(
maxWorkerQueue)) 50 * (maxWorkerQueue - curWorkerQueue) / maxWorkerQueue
))
time.sleep(0.5) time.sleep(0.5)
QtCore.QCoreApplication.processEvents( QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000 QtCore.QEventLoop.AllEvents, 1000
) )
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "Shutting down Pybitmessage... %1%").arg(50)) "MainWindow", "Shutting down Pybitmessage... {0}%"
).format(50))
QtCore.QCoreApplication.processEvents( QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000 QtCore.QEventLoop.AllEvents, 1000
@ -2744,29 +2808,27 @@ class MyForm(settingsmixin.SMainWindow):
# check if upload (of objects created locally) pending # check if upload (of objects created locally) pending
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "Waiting for objects to be sent... %1%").arg(50)) "MainWindow", "Waiting for objects to be sent... {0}%"
).format(50))
maxPendingUpload = max(1, pendingUpload()) maxPendingUpload = max(1, pendingUpload())
while pendingUpload() > 1: while pendingUpload() > 1:
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Waiting for objects to be sent... %1%" "Waiting for objects to be sent... {0}%"
).arg(int(50 + 20 * (pendingUpload() / maxPendingUpload)))) ).format(int(50 + 20 * pendingUpload() / maxPendingUpload)))
time.sleep(0.5) time.sleep(0.5)
QtCore.QCoreApplication.processEvents( QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000 QtCore.QEventLoop.AllEvents, 1000
) )
QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000
)
QtCore.QCoreApplication.processEvents( QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000 QtCore.QEventLoop.AllEvents, 1000
) )
# save state and geometry self and all widgets # save state and geometry self and all widgets
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "Saving settings... %1%").arg(70)) "MainWindow", "Saving settings... {0}%").format(70))
QtCore.QCoreApplication.processEvents( QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000 QtCore.QEventLoop.AllEvents, 1000
) )
@ -2779,18 +2841,18 @@ class MyForm(settingsmixin.SMainWindow):
obj.saveSettings() obj.saveSettings()
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "Shutting down core... %1%").arg(80)) "MainWindow", "Shutting down core... {0}%").format(80))
QtCore.QCoreApplication.processEvents( QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000 QtCore.QEventLoop.AllEvents, 1000
) )
shutdown.doCleanShutdown() shutdown.doCleanShutdown()
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "Stopping notifications... %1%").arg(90)) "MainWindow", "Stopping notifications... {0}%").format(90))
self.tray.hide() self.tray.hide()
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "Shutdown imminent... %1%").arg(100)) "MainWindow", "Shutdown imminent... {0}%").format(100))
logger.info("Shutdown complete") logger.info("Shutdown complete")
self.close() self.close()
@ -2825,17 +2887,25 @@ class MyForm(settingsmixin.SMainWindow):
totalLines = len(lines) totalLines = len(lines)
for i in xrange(totalLines): for i in xrange(totalLines):
if 'Message ostensibly from ' in lines[i]: if 'Message ostensibly from ' in lines[i]:
lines[i] = '<p style="font-size: 12px; color: grey;">%s</span></p>' % ( lines[i] = (
lines[i]) '<p style="font-size: 12px; color: grey;">%s</span></p>' %
elif lines[i] == '------------------------------------------------------': lines[i]
)
elif (
lines[i] ==
'------------------------------------------------------'
):
lines[i] = '<hr>' lines[i] = '<hr>'
elif lines[i] == '' and (i+1) < totalLines and \ elif (
lines[i+1] != '------------------------------------------------------': lines[i] == '' and (i + 1) < totalLines and
lines[i + 1] !=
'------------------------------------------------------'
):
lines[i] = '<br><br>' lines[i] = '<br><br>'
content = ' '.join(lines) # To keep the whitespace between lines content = ' '.join(lines) # To keep the whitespace between lines
content = shared.fixPotentiallyInvalidUTF8Data(content) content = shared.fixPotentiallyInvalidUTF8Data(content)
content = unicode(content, 'utf-8)') content = unicode(content, 'utf-8')
textEdit.setHtml(QtCore.QString(content)) textEdit.setHtml(content)
def on_action_InboxMarkUnread(self): def on_action_InboxMarkUnread(self):
tableWidget = self.getCurrentMessagelist() tableWidget = self.getCurrentMessagelist()
@ -2861,18 +2931,15 @@ class MyForm(settingsmixin.SMainWindow):
) )
self.propagateUnreadCount() self.propagateUnreadCount()
# tableWidget.selectRow(currentRow + 1)
# This doesn't de-select the last message if you try to mark it
# unread, but that doesn't interfere. Might not be necessary.
# We could also select upwards, but then our problem would be
# with the topmost message.
# tableWidget.clearSelection() manages to mark the message
# as read again.
# Format predefined text on message reply. # Format predefined text on message reply.
def quoted_text(self, message): def quoted_text(self, message):
if not BMConfigParser().safeGetBoolean('bitmessagesettings', 'replybelow'): if not BMConfigParser().safeGetBoolean(
return '\n\n------------------------------------------------------\n' + message 'bitmessagesettings', 'replybelow'):
return (
'\n\n------------------------------------------------------\n' +
message
)
quoteWrapper = textwrap.TextWrapper( quoteWrapper = textwrap.TextWrapper(
replace_whitespace=False, initial_indent='> ', replace_whitespace=False, initial_indent='> ',
@ -2902,7 +2969,7 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.comboBoxSendFrom, self.ui.comboBoxSendFromBroadcast self.ui.comboBoxSendFrom, self.ui.comboBoxSendFromBroadcast
): ):
for i in range(box.count()): for i in range(box.count()):
if str(box.itemData(i).toPyObject()) == address: if str(box.itemData(i)) == address:
box.setCurrentIndex(i) box.setCurrentIndex(i)
break break
else: else:
@ -2946,7 +3013,8 @@ class MyForm(settingsmixin.SMainWindow):
acct.parseMessage( acct.parseMessage(
toAddressAtCurrentInboxRow, fromAddressAtCurrentInboxRow, toAddressAtCurrentInboxRow, fromAddressAtCurrentInboxRow,
tableWidget.item(currentInboxRow, 2).subject, tableWidget.item(currentInboxRow, 2).subject,
messageAtCurrentInboxRow) messageAtCurrentInboxRow
)
widget = { widget = {
'subject': self.ui.lineEditSubject, 'subject': self.ui.lineEditSubject,
'from': self.ui.comboBoxSendFrom, 'from': self.ui.comboBoxSendFrom,
@ -2959,23 +3027,26 @@ class MyForm(settingsmixin.SMainWindow):
) )
# toAddressAtCurrentInboxRow = fromAddressAtCurrentInboxRow # toAddressAtCurrentInboxRow = fromAddressAtCurrentInboxRow
elif not BMConfigParser().has_section(toAddressAtCurrentInboxRow): elif not BMConfigParser().has_section(toAddressAtCurrentInboxRow):
QtGui.QMessageBox.information( QtWidgets.QMessageBox.information(
self, _translate("MainWindow", "Address is gone"), self,
_translate("MainWindow", "Address is gone"),
_translate( _translate(
"MainWindow", "MainWindow",
"Bitmessage cannot find your address %1. Perhaps you" "Bitmessage cannot find your address {0}. Perhaps you"
" removed it?" " removed it?"
).arg(toAddressAtCurrentInboxRow), QtGui.QMessageBox.Ok) ).format(toAddressAtCurrentInboxRow),
QtWidgets.QMessageBox.Ok)
elif not BMConfigParser().getboolean( elif not BMConfigParser().getboolean(
toAddressAtCurrentInboxRow, 'enabled'): toAddressAtCurrentInboxRow, 'enabled'):
QtGui.QMessageBox.information( QtWidgets.QMessageBox.information(
self, _translate("MainWindow", "Address disabled"), self,
_translate("MainWindow", "Address disabled"),
_translate( _translate(
"MainWindow", "MainWindow",
"Error: The address from which you are trying to send" "Error: The address from which you are trying to send"
" is disabled. You\'ll have to enable it on the" " is disabled. You\'ll have to enable it on the \'Your"
" \'Your Identities\' tab before using it." " Identities\' tab before using it."
), QtGui.QMessageBox.Ok) ), QtWidgets.QMessageBox.Ok)
else: else:
self.setBroadcastEnablementDependingOnWhetherThisIsAMailingListAddress(toAddressAtCurrentInboxRow) self.setBroadcastEnablementDependingOnWhetherThisIsAMailingListAddress(toAddressAtCurrentInboxRow)
broadcast_tab_index = self.ui.tabWidgetSend.indexOf( broadcast_tab_index = self.ui.tabWidgetSend.indexOf(
@ -3053,8 +3124,9 @@ class MyForm(settingsmixin.SMainWindow):
recipientAddress = tableWidget.item( recipientAddress = tableWidget.item(
currentInboxRow, 0).data(QtCore.Qt.UserRole) currentInboxRow, 0).data(QtCore.Qt.UserRole)
# Let's make sure that it isn't already in the address book # Let's make sure that it isn't already in the address book
queryreturn = sqlQuery('''select * from blacklist where address=?''', queryreturn = sqlQuery(
addressAtCurrentInboxRow) 'SELECT * FROM blacklist WHERE address=?',
addressAtCurrentInboxRow)
if queryreturn == []: if queryreturn == []:
label = "\"" + tableWidget.item(currentInboxRow, 2).subject + "\" in " + BMConfigParser().get(recipientAddress, "label") label = "\"" + tableWidget.item(currentInboxRow, 2).subject + "\" in " + BMConfigParser().get(recipientAddress, "label")
sqlExecute('''INSERT INTO blacklist VALUES (?,?, ?)''', sqlExecute('''INSERT INTO blacklist VALUES (?,?, ?)''',
@ -3102,8 +3174,8 @@ class MyForm(settingsmixin.SMainWindow):
return return
currentRow = 0 currentRow = 0
folder = self.getCurrentFolder() folder = self.getCurrentFolder()
shifted = QtGui.QApplication.queryKeyboardModifiers() \ shifted = (QtWidgets.QApplication.queryKeyboardModifiers() &
& QtCore.Qt.ShiftModifier QtCore.Qt.ShiftModifier)
tableWidget.setUpdatesEnabled(False) tableWidget.setUpdatesEnabled(False)
inventoryHashesToTrash = set() inventoryHashesToTrash = set()
# ranges in reversed order # ranges in reversed order
@ -3120,8 +3192,8 @@ class MyForm(settingsmixin.SMainWindow):
idCount = len(inventoryHashesToTrash) idCount = len(inventoryHashesToTrash)
sqlExecuteChunked( sqlExecuteChunked(
("DELETE FROM inbox" if folder == "trash" or shifted else ("DELETE FROM inbox" if folder == "trash" or shifted else
"UPDATE inbox SET folder='trash', read=1") + "UPDATE inbox SET folder='trash', read=1")
" WHERE msgid IN ({0})", idCount, *inventoryHashesToTrash) + " WHERE msgid IN ({0})", idCount, *inventoryHashesToTrash)
tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1) tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1)
tableWidget.setUpdatesEnabled(True) tableWidget.setUpdatesEnabled(True)
self.propagateUnreadCount(folder) self.propagateUnreadCount(folder)
@ -3169,14 +3241,17 @@ class MyForm(settingsmixin.SMainWindow):
# Retrieve the message data out of the SQL database # Retrieve the message data out of the SQL database
msgid = tableWidget.item(currentInboxRow, 3).data() msgid = tableWidget.item(currentInboxRow, 3).data()
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select message from inbox where msgid=?''', msgid) 'SELECT message FROM inbox WHERE msgid=?', msgid)
if queryreturn != []: if queryreturn != []:
for row in queryreturn: for row in queryreturn:
message, = row message, = row
defaultFilename = "".join(x for x in subjectAtCurrentInboxRow if x.isalnum()) + '.txt' defaultFilename = "".join(
filename = QtGui.QFileDialog.getSaveFileName(self, _translate("MainWindow","Save As..."), defaultFilename, "Text files (*.txt);;All files (*.*)") x for x in subjectAtCurrentInboxRow if x.isalnum()) + '.txt'
if filename == '': filename = QtWidgets.QFileDialog.getSaveFileName(
self, _translate("MainWindow", "Save As..."), defaultFilename,
"Text files (*.txt);;All files (*.*)")[0]
if not filename:
return return
try: try:
f = open(filename, 'w') f = open(filename, 'w')
@ -3188,11 +3263,13 @@ class MyForm(settingsmixin.SMainWindow):
# Send item on the Sent tab to trash # Send item on the Sent tab to trash
def on_action_SentTrash(self): def on_action_SentTrash(self):
currentRow = 0
tableWidget = self.getCurrentMessagelist() tableWidget = self.getCurrentMessagelist()
if not tableWidget: if not tableWidget:
return return
folder = self.getCurrentFolder() folder = self.getCurrentFolder()
shifted = QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ShiftModifier shifted = (QtWidgets.QApplication.queryKeyboardModifiers() &
QtCore.Qt.ShiftModifier)
while tableWidget.selectedIndexes() != []: while tableWidget.selectedIndexes() != []:
currentRow = tableWidget.selectedIndexes()[0].row() currentRow = tableWidget.selectedIndexes()[0].row()
ackdataToTrash = tableWidget.item(currentRow, 3).data() ackdataToTrash = tableWidget.item(currentRow, 3).data()
@ -3220,15 +3297,18 @@ class MyForm(settingsmixin.SMainWindow):
queryreturn = sqlQuery('''select ackdata FROM sent WHERE status='forcepow' ''') queryreturn = sqlQuery('''select ackdata FROM sent WHERE status='forcepow' ''')
for row in queryreturn: for row in queryreturn:
ackdata, = row ackdata, = row
queues.UISignalQueue.put(('updateSentItemStatusByAckdata', ( queues.UISignalQueue.put((
ackdata, 'Overriding maximum-difficulty setting. Work queued.'))) 'updateSentItemStatusByAckdata',
(ackdata, 'Overriding maximum-difficulty setting.'
' Work queued.')
))
queues.workerQueue.put(('sendmessage', '')) queues.workerQueue.put(('sendmessage', ''))
def on_action_SentClipboard(self): def on_action_SentClipboard(self):
currentRow = self.ui.tableWidgetInbox.currentRow() currentRow = self.ui.tableWidgetInbox.currentRow()
addressAtCurrentRow = self.ui.tableWidgetInbox.item( addressAtCurrentRow = self.ui.tableWidgetInbox.item(
currentRow, 0).data(QtCore.Qt.UserRole) currentRow, 0).data(QtCore.Qt.UserRole)
clipboard = QtGui.QApplication.clipboard() clipboard = QtWidgets.QApplication.clipboard()
clipboard.setText(str(addressAtCurrentRow)) clipboard.setText(str(addressAtCurrentRow))
# Group of functions for the Address Book dialog box # Group of functions for the Address Book dialog box
@ -3253,7 +3333,7 @@ class MyForm(settingsmixin.SMainWindow):
addresses_string = item.address addresses_string = item.address
else: else:
addresses_string += ', ' + item.address addresses_string += ', ' + item.address
clipboard = QtGui.QApplication.clipboard() clipboard = QtWidgets.QApplication.clipboard()
clipboard.setText(addresses_string) clipboard.setText(addresses_string)
def on_action_AddressBookSend(self): def on_action_AddressBookSend(self):
@ -3263,8 +3343,7 @@ class MyForm(settingsmixin.SMainWindow):
return self.updateStatusBar(_translate( return self.updateStatusBar(_translate(
"MainWindow", "No addresses selected.")) "MainWindow", "No addresses selected."))
addresses_string = unicode( addresses_string = self.ui.lineEditTo.text()
self.ui.lineEditTo.text().toUtf8(), 'utf-8')
for item in selected_items: for item in selected_items:
address_string = item.accountString() address_string = item.accountString()
if not addresses_string: if not addresses_string:
@ -3295,7 +3374,7 @@ class MyForm(settingsmixin.SMainWindow):
) )
def on_context_menuAddressBook(self, point): def on_context_menuAddressBook(self, point):
self.popMenuAddressBook = QtGui.QMenu(self) self.popMenuAddressBook = QtWidgets.QMenu(self)
self.popMenuAddressBook.addAction(self.actionAddressBookSend) self.popMenuAddressBook.addAction(self.actionAddressBookSend)
self.popMenuAddressBook.addAction(self.actionAddressBookClipboard) self.popMenuAddressBook.addAction(self.actionAddressBookClipboard)
self.popMenuAddressBook.addAction(self.actionAddressBookSubscribe) self.popMenuAddressBook.addAction(self.actionAddressBookSubscribe)
@ -3325,7 +3404,7 @@ class MyForm(settingsmixin.SMainWindow):
self.click_pushButtonAddSubscription() self.click_pushButtonAddSubscription()
def on_action_SubscriptionsDelete(self): def on_action_SubscriptionsDelete(self):
if QtGui.QMessageBox.question( if QtWidgets.QMessageBox.question(
self, "Delete subscription?", self, "Delete subscription?",
_translate( _translate(
"MainWindow", "MainWindow",
@ -3336,8 +3415,8 @@ class MyForm(settingsmixin.SMainWindow):
" messages, but you can still view messages you" " messages, but you can still view messages you"
" already received.\n\nAre you sure you want to" " already received.\n\nAre you sure you want to"
" delete the subscription?" " delete the subscription?"
), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No ), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
) != QtGui.QMessageBox.Yes: ) != QtWidgets.QMessageBox.Yes:
return return
address = self.getCurrentAccount() address = self.getCurrentAccount()
sqlExecute('''DELETE FROM subscriptions WHERE address=?''', sqlExecute('''DELETE FROM subscriptions WHERE address=?''',
@ -3349,7 +3428,7 @@ class MyForm(settingsmixin.SMainWindow):
def on_action_SubscriptionsClipboard(self): def on_action_SubscriptionsClipboard(self):
address = self.getCurrentAccount() address = self.getCurrentAccount()
clipboard = QtGui.QApplication.clipboard() clipboard = QtWidgets.QApplication.clipboard()
clipboard.setText(str(address)) clipboard.setText(str(address))
def on_action_SubscriptionsEnable(self): def on_action_SubscriptionsEnable(self):
@ -3374,7 +3453,7 @@ class MyForm(settingsmixin.SMainWindow):
def on_context_menuSubscriptions(self, point): def on_context_menuSubscriptions(self, point):
currentItem = self.getCurrentItem() currentItem = self.getCurrentItem()
self.popMenuSubscriptions = QtGui.QMenu(self) self.popMenuSubscriptions = QtWidgets.QMenu(self)
if isinstance(currentItem, Ui_AddressWidget): if isinstance(currentItem, Ui_AddressWidget):
self.popMenuSubscriptions.addAction(self.actionsubscriptionsNew) self.popMenuSubscriptions.addAction(self.actionsubscriptionsNew)
self.popMenuSubscriptions.addAction(self.actionsubscriptionsDelete) self.popMenuSubscriptions.addAction(self.actionsubscriptionsDelete)
@ -3414,8 +3493,6 @@ class MyForm(settingsmixin.SMainWindow):
return self.ui.tableWidgetInboxSubscriptions return self.ui.tableWidgetInboxSubscriptions
elif widget == self.ui.treeWidgetChans: elif widget == self.ui.treeWidgetChans:
return self.ui.tableWidgetInboxChans return self.ui.tableWidgetInboxChans
else:
return None
def getCurrentTreeWidget(self): def getCurrentTreeWidget(self):
currentIndex = self.ui.tabWidget.currentIndex() currentIndex = self.ui.tabWidget.currentIndex()
@ -3504,7 +3581,7 @@ class MyForm(settingsmixin.SMainWindow):
if currentIndex >= 0 and currentIndex < len(messagelistList): if currentIndex >= 0 and currentIndex < len(messagelistList):
return ( return (
messagelistList[currentIndex] if retObj messagelistList[currentIndex] if retObj
else messagelistList[currentIndex].text().toUtf8().data()) else messagelistList[currentIndex].text())
def getCurrentSearchOption(self, currentIndex=None): def getCurrentSearchOption(self, currentIndex=None):
if currentIndex is None: if currentIndex is None:
@ -3560,7 +3637,7 @@ class MyForm(settingsmixin.SMainWindow):
if account.type == AccountMixin.NORMAL: if account.type == AccountMixin.NORMAL:
return # maybe in the future return # maybe in the future
elif account.type == AccountMixin.CHAN: elif account.type == AccountMixin.CHAN:
if QtGui.QMessageBox.question( if QtWidgets.QMessageBox.question(
self, "Delete channel?", self, "Delete channel?",
_translate( _translate(
"MainWindow", "MainWindow",
@ -3571,8 +3648,8 @@ class MyForm(settingsmixin.SMainWindow):
" messages, but you can still view messages you" " messages, but you can still view messages you"
" already received.\n\nAre you sure you want to" " already received.\n\nAre you sure you want to"
" delete the channel?" " delete the channel?"
), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No ), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
) == QtGui.QMessageBox.Yes: ) == QtWidgets.QMessageBox.Yes:
BMConfigParser().remove_section(str(account.address)) BMConfigParser().remove_section(str(account.address))
else: else:
return return
@ -3613,7 +3690,7 @@ class MyForm(settingsmixin.SMainWindow):
def on_action_Clipboard(self): def on_action_Clipboard(self):
address = self.getCurrentAccount() address = self.getCurrentAccount()
clipboard = QtGui.QApplication.clipboard() clipboard = QtWidgets.QApplication.clipboard()
clipboard.setText(str(address)) clipboard.setText(str(address))
def on_action_ClipboardMessagelist(self): def on_action_ClipboardMessagelist(self):
@ -3631,14 +3708,15 @@ class MyForm(settingsmixin.SMainWindow):
myAddress = tableWidget.item(currentRow, 0).data(QtCore.Qt.UserRole) myAddress = tableWidget.item(currentRow, 0).data(QtCore.Qt.UserRole)
otherAddress = tableWidget.item(currentRow, 1).data(QtCore.Qt.UserRole) otherAddress = tableWidget.item(currentRow, 1).data(QtCore.Qt.UserRole)
account = accountClass(myAddress) account = accountClass(myAddress)
if isinstance(account, GatewayAccount) and otherAddress == account.relayAddress and ( if isinstance(account, GatewayAccount) \
(currentColumn in [0, 2] and self.getCurrentFolder() == "sent") or and otherAddress == account.relayAddress and (
(currentColumn in [1, 2] and self.getCurrentFolder() != "sent")): (currentColumn in (0, 2) and currentFolder == "sent") or
text = str(tableWidget.item(currentRow, currentColumn).label) (currentColumn in (1, 2) and currentFolder != "sent")):
text = tableWidget.item(currentRow, currentColumn).label
else: else:
text = tableWidget.item(currentRow, currentColumn).data(QtCore.Qt.UserRole) text = tableWidget.item(currentRow, currentColumn).data(QtCore.Qt.UserRole)
# text = unicode(str(text), 'utf-8', 'ignore')
clipboard = QtGui.QApplication.clipboard() clipboard = QtWidgets.QApplication.clipboard()
clipboard.setText(text) clipboard.setText(text)
# set avatar functions # set avatar functions
@ -3663,10 +3741,7 @@ class MyForm(settingsmixin.SMainWindow):
if not os.path.exists(state.appdata + 'avatars/'): if not os.path.exists(state.appdata + 'avatars/'):
os.makedirs(state.appdata + 'avatars/') os.makedirs(state.appdata + 'avatars/')
hash = hashlib.md5(addBMIfNotPresent(addressAtCurrentRow)).hexdigest() hash = hashlib.md5(addBMIfNotPresent(addressAtCurrentRow)).hexdigest()
extensions = [ # http://pyqt.sourceforge.net/Docs/PyQt4/qimagereader.html#supportedImageFormats
'PNG', 'GIF', 'JPG', 'JPEG', 'SVG', 'BMP', 'MNG', 'PBM',
'PGM', 'PPM', 'TIFF', 'XBM', 'XPM', 'TGA']
names = { names = {
'BMP': 'Windows Bitmap', 'BMP': 'Windows Bitmap',
'GIF': 'Graphic Interchange Format', 'GIF': 'Graphic Interchange Format',
@ -3681,11 +3756,12 @@ class MyForm(settingsmixin.SMainWindow):
'XBM': 'X11 Bitmap', 'XBM': 'X11 Bitmap',
'XPM': 'X11 Pixmap', 'XPM': 'X11 Pixmap',
'SVG': 'Scalable Vector Graphics', 'SVG': 'Scalable Vector Graphics',
'TGA': 'Targa Image Format'} 'TGA': 'Targa Image Format'
}
filters = [] filters = []
all_images_filter = [] all_images_filter = []
current_files = [] current_files = []
for ext in extensions: for ext in names:
filters += [names[ext] + ' (*.' + ext.lower() + ')'] filters += [names[ext] + ' (*.' + ext.lower() + ')']
all_images_filter += ['*.' + ext.lower()] all_images_filter += ['*.' + ext.lower()]
upper = state.appdata + 'avatars/' + hash + '.' + ext.upper() upper = state.appdata + 'avatars/' + hash + '.' + ext.upper()
@ -3696,10 +3772,9 @@ class MyForm(settingsmixin.SMainWindow):
current_files += [upper] current_files += [upper]
filters[0:0] = ['Image files (' + ' '.join(all_images_filter) + ')'] filters[0:0] = ['Image files (' + ' '.join(all_images_filter) + ')']
filters[1:1] = ['All files (*.*)'] filters[1:1] = ['All files (*.*)']
sourcefile = QtGui.QFileDialog.getOpenFileName( sourcefile = QtWidgets.QFileDialog.getOpenFileName(
self, _translate("MainWindow", "Set avatar..."), self, _translate("MainWindow", "Set avatar..."),
filter=';;'.join(filters) filter=';;'.join(filters))[0]
)
# determine the correct filename (note that avatars don't use the suffix) # determine the correct filename (note that avatars don't use the suffix)
destination = state.appdata + 'avatars/' + hash + '.' + sourcefile.split('.')[-1] destination = state.appdata + 'avatars/' + hash + '.' + sourcefile.split('.')[-1]
exists = QtCore.QFile.exists(destination) exists = QtCore.QFile.exists(destination)
@ -3708,11 +3783,11 @@ class MyForm(settingsmixin.SMainWindow):
if exists | (len(current_files) > 0): if exists | (len(current_files) > 0):
displayMsg = _translate( displayMsg = _translate(
"MainWindow", "Do you really want to remove this avatar?") "MainWindow", "Do you really want to remove this avatar?")
overwrite = QtGui.QMessageBox.question( overwrite = QtWidgets.QMessageBox.question(
self, 'Message', displayMsg, self, 'Message', displayMsg,
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
else: else:
overwrite = QtGui.QMessageBox.No overwrite = QtWidgets.QMessageBox.No
else: else:
# ask whether to overwrite old avatar # ask whether to overwrite old avatar
if exists | (len(current_files) > 0): if exists | (len(current_files) > 0):
@ -3720,15 +3795,15 @@ class MyForm(settingsmixin.SMainWindow):
"MainWindow", "MainWindow",
"You have already set an avatar for this address." "You have already set an avatar for this address."
" Do you really want to overwrite it?") " Do you really want to overwrite it?")
overwrite = QtGui.QMessageBox.question( overwrite = QtWidgets.QMessageBox.question(
self, 'Message', displayMsg, self, 'Message', displayMsg,
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
else: else:
overwrite = QtGui.QMessageBox.No overwrite = QtWidgets.QMessageBox.No
# copy the image file to the appdata folder # copy the image file to the appdata folder
if (not exists) | (overwrite == QtGui.QMessageBox.Yes): if (not exists) | (overwrite == QtWidgets.QMessageBox.Yes):
if overwrite == QtGui.QMessageBox.Yes: if overwrite == QtWidgets.QMessageBox.Yes:
for file in current_files: for file in current_files:
QtCore.QFile.remove(file) QtCore.QFile.remove(file)
QtCore.QFile.remove(destination) QtCore.QFile.remove(destination)
@ -3760,10 +3835,10 @@ class MyForm(settingsmixin.SMainWindow):
"MainWindow", "Sound files (%s)" % "MainWindow", "Sound files (%s)" %
' '.join(['*%s%s' % (os.extsep, ext) for ext in sound.extensions]) ' '.join(['*%s%s' % (os.extsep, ext) for ext in sound.extensions])
))] ))]
sourcefile = unicode(QtGui.QFileDialog.getOpenFileName( sourcefile = QtWidgets.QFileDialog.getOpenFileName(
self, _translate("MainWindow", "Set notification sound..."), self, _translate("MainWindow", "Set notification sound..."),
filter=';;'.join(filters) filter=';;'.join(filters)
)) )[0]
if not sourcefile: if not sourcefile:
return return
@ -3778,15 +3853,15 @@ class MyForm(settingsmixin.SMainWindow):
pattern = destfile.lower() pattern = destfile.lower()
for item in os.listdir(destdir): for item in os.listdir(destdir):
if item.lower() == pattern: if item.lower() == pattern:
overwrite = QtGui.QMessageBox.question( overwrite = QtWidgets.QMessageBox.question(
self, _translate("MainWindow", "Message"), self, _translate("MainWindow", "Message"),
_translate( _translate(
"MainWindow", "MainWindow",
"You have already set a notification sound" "You have already set a notification sound"
" for this address book entry." " for this address book entry."
" Do you really want to overwrite it?"), " Do you really want to overwrite it?"),
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No
) == QtGui.QMessageBox.Yes ) == QtWidgets.QMessageBox.Yes
if overwrite: if overwrite:
QtCore.QFile.remove(os.path.join(destdir, item)) QtCore.QFile.remove(os.path.join(destdir, item))
break break
@ -3797,18 +3872,23 @@ class MyForm(settingsmixin.SMainWindow):
def on_context_menuYourIdentities(self, point): def on_context_menuYourIdentities(self, point):
currentItem = self.getCurrentItem() currentItem = self.getCurrentItem()
self.popMenuYourIdentities = QtGui.QMenu(self) self.popMenuYourIdentities = QtWidgets.QMenu(self)
if isinstance(currentItem, Ui_AddressWidget): if isinstance(currentItem, Ui_AddressWidget):
self.popMenuYourIdentities.addAction(self.actionNewYourIdentities) self.popMenuYourIdentities.addAction(self.actionNewYourIdentities)
self.popMenuYourIdentities.addSeparator() self.popMenuYourIdentities.addSeparator()
self.popMenuYourIdentities.addAction(self.actionClipboardYourIdentities) self.popMenuYourIdentities.addAction(
self.actionClipboardYourIdentities)
self.popMenuYourIdentities.addSeparator() self.popMenuYourIdentities.addSeparator()
if currentItem.isEnabled: if currentItem.isEnabled:
self.popMenuYourIdentities.addAction(self.actionDisableYourIdentities) self.popMenuYourIdentities.addAction(
self.actionDisableYourIdentities)
else: else:
self.popMenuYourIdentities.addAction(self.actionEnableYourIdentities) self.popMenuYourIdentities.addAction(
self.popMenuYourIdentities.addAction(self.actionSetAvatarYourIdentities) self.actionEnableYourIdentities)
self.popMenuYourIdentities.addAction(self.actionSpecialAddressBehaviorYourIdentities) self.popMenuYourIdentities.addAction(
self.actionSetAvatarYourIdentities)
self.popMenuYourIdentities.addAction(
self.actionSpecialAddressBehaviorYourIdentities)
self.popMenuYourIdentities.addAction(self.actionEmailGateway) self.popMenuYourIdentities.addAction(self.actionEmailGateway)
self.popMenuYourIdentities.addSeparator() self.popMenuYourIdentities.addSeparator()
if currentItem.type != AccountMixin.ALL: if currentItem.type != AccountMixin.ALL:
@ -3827,7 +3907,7 @@ class MyForm(settingsmixin.SMainWindow):
# TODO make one popMenu # TODO make one popMenu
def on_context_menuChan(self, point): def on_context_menuChan(self, point):
currentItem = self.getCurrentItem() currentItem = self.getCurrentItem()
self.popMenu = QtGui.QMenu(self) self.popMenu = QtWidgets.QMenu(self)
if isinstance(currentItem, Ui_AddressWidget): if isinstance(currentItem, Ui_AddressWidget):
self.popMenu.addAction(self.actionNew) self.popMenu.addAction(self.actionNew)
self.popMenu.addAction(self.actionDelete) self.popMenu.addAction(self.actionDelete)
@ -3863,7 +3943,7 @@ class MyForm(settingsmixin.SMainWindow):
self.on_context_menuSent(point) self.on_context_menuSent(point)
return return
self.popMenuInbox = QtGui.QMenu(self) self.popMenuInbox = QtWidgets.QMenu(self)
self.popMenuInbox.addAction(self.actionForceHtml) self.popMenuInbox.addAction(self.actionForceHtml)
self.popMenuInbox.addAction(self.actionMarkUnread) self.popMenuInbox.addAction(self.actionMarkUnread)
self.popMenuInbox.addSeparator() self.popMenuInbox.addSeparator()
@ -3898,7 +3978,7 @@ class MyForm(settingsmixin.SMainWindow):
def on_context_menuSent(self, point): def on_context_menuSent(self, point):
currentRow = self.ui.tableWidgetInbox.currentRow() currentRow = self.ui.tableWidgetInbox.currentRow()
self.popMenuSent = QtGui.QMenu(self) self.popMenuSent = QtWidgets.QMenu(self)
self.popMenuSent.addAction(self.actionSentClipboard) self.popMenuSent.addAction(self.actionSentClipboard)
self._contact_selected = self.ui.tableWidgetInbox.item(currentRow, 0) self._contact_selected = self.ui.tableWidgetInbox.item(currentRow, 0)
# preloaded gui.menu plugins with prefix 'address' # preloaded gui.menu plugins with prefix 'address'
@ -3922,7 +4002,7 @@ class MyForm(settingsmixin.SMainWindow):
def inboxSearchLineEditUpdated(self, text): def inboxSearchLineEditUpdated(self, text):
# dynamic search for too short text is slow # dynamic search for too short text is slow
text = text.toUtf8() text = text.encode('utf-8')
if 0 < len(text) < 3: if 0 < len(text) < 3:
return return
messagelist = self.getCurrentMessagelist() messagelist = self.getCurrentMessagelist()
@ -3935,9 +4015,9 @@ class MyForm(settingsmixin.SMainWindow):
def inboxSearchLineEditReturnPressed(self): def inboxSearchLineEditReturnPressed(self):
logger.debug("Search return pressed") logger.debug("Search return pressed")
searchLine = self.getCurrentSearchLine() searchLine = self.getCurrentSearchLine().encode('utf-8')
messagelist = self.getCurrentMessagelist() messagelist = self.getCurrentMessagelist()
if messagelist and len(str(searchLine)) < 3: if messagelist and len(searchLine) < 3:
searchOption = self.getCurrentSearchOption() searchOption = self.getCurrentSearchOption()
account = self.getCurrentAccount() account = self.getCurrentAccount()
folder = self.getCurrentFolder() folder = self.getCurrentFolder()
@ -3977,7 +4057,7 @@ class MyForm(settingsmixin.SMainWindow):
if item.type == AccountMixin.ALL: if item.type == AccountMixin.ALL:
return return
newLabel = unicode(item.text(0), 'utf-8', 'ignore') newLabel = item.text(0)
oldLabel = item.defaultLabel() oldLabel = item.defaultLabel()
# unchanged, do not do anything either # unchanged, do not do anything either
@ -3996,7 +4076,9 @@ class MyForm(settingsmixin.SMainWindow):
self.rerenderMessagelistFromLabels() self.rerenderMessagelistFromLabels()
if item.type != AccountMixin.SUBSCRIPTION: if item.type != AccountMixin.SUBSCRIPTION:
self.rerenderMessagelistToLabels() self.rerenderMessagelistToLabels()
if item.type in (AccountMixin.NORMAL, AccountMixin.CHAN, AccountMixin.SUBSCRIPTION): if item.type in (
AccountMixin.NORMAL, AccountMixin.CHAN, AccountMixin.SUBSCRIPTION
):
self.rerenderAddressBook() self.rerenderAddressBook()
self.recurDepth -= 1 self.recurDepth -= 1
@ -4016,10 +4098,12 @@ class MyForm(settingsmixin.SMainWindow):
) )
try: try:
message = queryreturn[-1][0] message = unicode(queryreturn[-1][0], 'utf-8')
except NameError: except NameError:
message = "" message = u""
except IndexError: except IndexError:
# _translate() often returns unicode, no redefinition here!
# pylint: disable=redefined-variable-type
message = _translate( message = _translate(
"MainWindow", "MainWindow",
"Error occurred: could not load message from disk." "Error occurred: could not load message from disk."
@ -4114,7 +4198,7 @@ app = None
myapp = None myapp = None
class BitmessageQtApplication(QtGui.QApplication): class BitmessageQtApplication(QtWidgets.QApplication):
""" """
Listener to allow our Qt form to get focus when another instance of the Listener to allow our Qt form to get focus when another instance of the
application is open. application is open.
@ -4137,15 +4221,15 @@ class BitmessageQtApplication(QtGui.QApplication):
self.server = None self.server = None
self.is_running = False self.is_running = False
socket = QLocalSocket() socket = QtNetwork.QLocalSocket()
socket.connectToServer(id) socket.connectToServer(id)
self.is_running = socket.waitForConnected() self.is_running = socket.waitForConnected()
# Cleanup past crashed servers # Cleanup past crashed servers
if not self.is_running: if not self.is_running:
if socket.error() == QLocalSocket.ConnectionRefusedError: if socket.error() == QtNetwork.QLocalSocket.ConnectionRefusedError:
socket.disconnectFromServer() socket.disconnectFromServer()
QLocalServer.removeServer(id) QtNetwork.QLocalServer.removeServer(id)
socket.abort() socket.abort()
@ -4156,16 +4240,12 @@ class BitmessageQtApplication(QtGui.QApplication):
else: else:
# Nope, create a local server with this id and assign on_new_connection # Nope, create a local server with this id and assign on_new_connection
# for whenever a second instance tries to run focus the application. # for whenever a second instance tries to run focus the application.
self.server = QLocalServer() self.server = QtNetwork.QLocalServer()
self.server.listen(id) self.server.listen(id)
self.server.newConnection.connect(self.on_new_connection) self.server.newConnection.connect(self.on_new_connection)
self.setStyleSheet("QStatusBar::item { border: 0px solid black }") self.setStyleSheet("QStatusBar::item { border: 0px solid black }")
def __del__(self):
if self.server:
self.server.close()
def on_new_connection(self): def on_new_connection(self):
if myapp: if myapp:
myapp.appIndicatorShow() myapp.appIndicatorShow()
@ -4188,12 +4268,6 @@ def run():
if myapp._firstrun: if myapp._firstrun:
myapp.showConnectDialog() # ask the user if we may connect myapp.showConnectDialog() # ask the user if we may connect
# try:
# if BMConfigParser().get('bitmessagesettings', 'mailchuck') < 1:
# myapp.showMigrationWizard(BMConfigParser().get('bitmessagesettings', 'mailchuck'))
# except:
# myapp.showMigrationWizard(0)
# only show after wizards and connect dialogs have completed # only show after wizards and connect dialogs have completed
if not BMConfigParser().getboolean('bitmessagesettings', 'startintray'): if not BMConfigParser().getboolean('bitmessagesettings', 'startintray'):
myapp.show() myapp.show()

View File

@ -1,46 +1,31 @@
# pylint: disable=too-many-instance-attributes,attribute-defined-outside-init
""" """
account.py
==========
Account related functions. Account related functions.
""" """
from __future__ import absolute_import
import inspect import inspect
import re import re
import sys import sys
import time import time
from PyQt4 import QtGui
import queues import queues
from addresses import decodeAddress from addresses import decodeAddress
from bmconfigparser import BMConfigParser from bmconfigparser import BMConfigParser
from helper_ackPayload import genAckPayload from helper_ackPayload import genAckPayload
from helper_sql import sqlQuery, sqlExecute from helper_sql import sqlQuery, sqlExecute
from .foldertree import AccountMixin from foldertree import AccountMixin
from .utils import str_broadcast_subscribers from utils import str_broadcast_subscribers
from tr import _translate
def getSortedAccounts(): def getSortedAccounts():
"""Get a sorted list of configSections""" """Get a sorted list of address config sections"""
configSections = BMConfigParser().addresses() configSections = BMConfigParser().addresses()
configSections.sort( configSections.sort(
cmp=lambda x, y: cmp( cmp=lambda x, y: cmp(
unicode( unicode(BMConfigParser().get(x, 'label'), 'utf-8').lower(),
BMConfigParser().get( unicode(BMConfigParser().get(y, 'label'), 'utf-8').lower())
x, )
'label'),
'utf-8').lower(),
unicode(
BMConfigParser().get(
y,
'label'),
'utf-8').lower()))
return configSections return configSections
@ -94,7 +79,8 @@ def accountClass(address):
return subscription return subscription
try: try:
gateway = BMConfigParser().get(address, "gateway") gateway = BMConfigParser().get(address, "gateway")
for _, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass): for _, cls in inspect.getmembers(
sys.modules[__name__], inspect.isclass):
if issubclass(cls, GatewayAccount) and cls.gatewayName == gateway: if issubclass(cls, GatewayAccount) and cls.gatewayName == gateway:
return cls(address) return cls(address)
# general gateway # general gateway
@ -105,7 +91,7 @@ def accountClass(address):
return BMAccount(address) return BMAccount(address)
class AccountColor(AccountMixin): # pylint: disable=too-few-public-methods class AccountColor(AccountMixin):
"""Set the type of account""" """Set the type of account"""
def __init__(self, address, address_type=None): def __init__(self, address, address_type=None):
@ -127,12 +113,35 @@ class AccountColor(AccountMixin): # pylint: disable=too-few-public-methods
self.type = address_type self.type = address_type
class BMAccount(object): class NoAccount(object):
"""Encapsulate a Bitmessage account""" """Minimal account like object (All accounts)"""
# pylint: disable=too-many-instance-attributes
def __init__(self, address=None): def __init__(self, address=None):
self.address = address self.address = address
self.type = AccountMixin.NORMAL self.type = AccountMixin.NORMAL
self.toAddress = self.fromAddress = ''
self.subject = self.message = ''
self.fromLabel = self.toLabel = ''
def getLabel(self, address=None):
"""Get a label for this bitmessage account"""
return address or self.address
def parseMessage(self, toAddress, fromAddress, subject, message):
"""Set metadata and address labels on self"""
self.toAddress = toAddress
self.fromAddress = fromAddress
self.subject = subject
self.message = message
self.fromLabel = self.getLabel(fromAddress)
self.toLabel = self.getLabel(toAddress)
class BMAccount(NoAccount):
"""Encapsulate a Bitmessage account"""
def __init__(self, address=None):
super(BMAccount, self).__init__(address)
if BMConfigParser().has_section(address): if BMConfigParser().has_section(address):
if BMConfigParser().safeGetBoolean(self.address, 'chan'): if BMConfigParser().safeGetBoolean(self.address, 'chan'):
self.type = AccountMixin.CHAN self.type = AccountMixin.CHAN
@ -148,8 +157,7 @@ class BMAccount(object):
def getLabel(self, address=None): def getLabel(self, address=None):
"""Get a label for this bitmessage account""" """Get a label for this bitmessage account"""
if address is None: address = super(BMAccount, self).getLabel(address)
address = self.address
label = BMConfigParser().safeGet(address, 'label', address) label = BMConfigParser().safeGet(address, 'label', address)
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select label from addressbook where address=?''', address) '''select label from addressbook where address=?''', address)
@ -162,33 +170,7 @@ class BMAccount(object):
if queryreturn != []: if queryreturn != []:
for row in queryreturn: for row in queryreturn:
label, = row label, = row
return label return unicode(label, 'utf-8')
def parseMessage(self, toAddress, fromAddress, subject, message):
"""Set metadata and address labels on self"""
self.toAddress = toAddress
self.fromAddress = fromAddress
if isinstance(subject, unicode):
self.subject = str(subject)
else:
self.subject = subject
self.message = message
self.fromLabel = self.getLabel(fromAddress)
self.toLabel = self.getLabel(toAddress)
class NoAccount(BMAccount):
"""Override the __init__ method on a BMAccount"""
def __init__(self, address=None): # pylint: disable=super-init-not-called
self.address = address
self.type = AccountMixin.NORMAL
def getLabel(self, address=None):
if address is None:
address = self.address
return address
class SubscriptionAccount(BMAccount): class SubscriptionAccount(BMAccount):
@ -208,15 +190,11 @@ class GatewayAccount(BMAccount):
ALL_OK = 0 ALL_OK = 0
REGISTRATION_DENIED = 1 REGISTRATION_DENIED = 1
def __init__(self, address):
super(GatewayAccount, self).__init__(address)
def send(self): def send(self):
"""Override the send method for gateway accounts""" """The send method for gateway accounts"""
streamNumber, ripe = decodeAddress(self.toAddress)[2:]
# pylint: disable=unused-variable stealthLevel = BMConfigParser().safeGetInt(
status, addressVersionNumber, streamNumber, ripe = decodeAddress(self.toAddress) 'bitmessagesettings', 'ackstealthlevel')
stealthLevel = BMConfigParser().safeGetInt('bitmessagesettings', 'ackstealthlevel')
ackdata = genAckPayload(streamNumber, stealthLevel) ackdata = genAckPayload(streamNumber, stealthLevel)
sqlExecute( sqlExecute(
'''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''',
@ -289,10 +267,9 @@ class MailchuckAccount(GatewayAccount):
def settings(self): def settings(self):
"""settings specific to a MailchuckAccount""" """settings specific to a MailchuckAccount"""
self.toAddress = self.registrationAddress self.toAddress = self.registrationAddress
self.subject = "config" self.subject = "config"
self.message = QtGui.QApplication.translate( self.message = _translate(
"Mailchuck", "Mailchuck",
"""# You can use this to configure your email gateway account """# You can use this to configure your email gateway account
# Uncomment the setting you want to use # Uncomment the setting you want to use
@ -338,8 +315,9 @@ class MailchuckAccount(GatewayAccount):
def parseMessage(self, toAddress, fromAddress, subject, message): def parseMessage(self, toAddress, fromAddress, subject, message):
"""parseMessage specific to a MailchuckAccount""" """parseMessage specific to a MailchuckAccount"""
super(MailchuckAccount, self).parseMessage(
super(MailchuckAccount, self).parseMessage(toAddress, fromAddress, subject, message) toAddress, fromAddress, subject, message
)
if fromAddress == self.relayAddress: if fromAddress == self.relayAddress:
matches = self.regExpIncoming.search(subject) matches = self.regExpIncoming.search(subject)
if matches is not None: if matches is not None:
@ -360,6 +338,7 @@ class MailchuckAccount(GatewayAccount):
self.toLabel = matches.group(1) self.toLabel = matches.group(1)
self.toAddress = matches.group(1) self.toAddress = matches.group(1)
self.feedback = self.ALL_OK self.feedback = self.ALL_OK
if fromAddress == self.registrationAddress and self.subject == "Registration Request Denied": if fromAddress == self.registrationAddress \
and self.subject == "Registration Request Denied":
self.feedback = self.REGISTRATION_DENIED self.feedback = self.REGISTRATION_DENIED
return self.feedback return self.feedback

View File

@ -1,39 +1,39 @@
""" """
Dialogs that work with BM address. Dialogs that work with BM address.
""" """
# pylint: disable=attribute-defined-outside-init,too-few-public-methods,relative-import # pylint: disable=too-few-public-methods
# https://github.com/PyCQA/pylint/issues/471
import hashlib import hashlib
from PyQt4 import QtCore, QtGui from qtpy import QtGui, QtWidgets
import queues import queues
import widgets import widgets
from account import AccountMixin, GatewayAccount, MailchuckAccount, accountClass, getSortedAccounts from account import (
from addresses import addBMIfNotPresent, decodeAddress, encodeVarint GatewayAccount, MailchuckAccount, AccountMixin, accountClass,
getSortedAccounts
)
from addresses import decodeAddress, encodeVarint, addBMIfNotPresent
from inventory import Inventory from inventory import Inventory
from tr import _translate from tr import _translate
class AddressCheckMixin(object): class AddressCheckMixin(object):
"""Base address validation class for QT UI""" """Base address validation class for Qt UI"""
def __init__(self): def _setup(self):
self.valid = False self.valid = False
QtCore.QObject.connect( # pylint: disable=no-member self.lineEditAddress.textChanged.connect(self.addressChanged)
self.lineEditAddress,
QtCore.SIGNAL("textChanged(QString)"),
self.addressChanged)
def _onSuccess(self, addressVersion, streamNumber, ripe): def _onSuccess(self, addressVersion, streamNumber, ripe):
pass pass
def addressChanged(self, QString): def addressChanged(self, address):
""" """
Address validation callback, performs validation and gives feedback Address validation callback, performs validation and gives feedback
""" """
status, addressVersion, streamNumber, ripe = decodeAddress( status, addressVersion, streamNumber, ripe = decodeAddress(address)
str(QString))
self.valid = status == 'success' self.valid = status == 'success'
if self.valid: if self.valid:
self.labelAddressCheck.setText( self.labelAddressCheck.setText(
@ -78,19 +78,27 @@ class AddressCheckMixin(object):
)) ))
class AddressDataDialog(QtGui.QDialog, AddressCheckMixin): class AddressDataDialog(QtWidgets.QDialog, AddressCheckMixin):
"""QDialog with Bitmessage address validation""" """
Base class for a dialog getting BM-address data.
Corresponding ui-file should define two fields:
lineEditAddress - for the address
lineEditLabel - for it's label
After address validation the values of that fields are put into
the data field of the dialog.
"""
def __init__(self, parent): def __init__(self, parent):
super(AddressDataDialog, self).__init__(parent) super(AddressDataDialog, self).__init__(parent)
self.parent = parent self.parent = parent
self.data = None
def accept(self): def accept(self):
"""Callback for QDIalog accepting value""" """Callback for QDialog accepting value"""
if self.valid: if self.valid:
self.data = ( self.data = (
addBMIfNotPresent(str(self.lineEditAddress.text())), addBMIfNotPresent(str(self.lineEditAddress.text())),
str(self.lineEditLabel.text().toUtf8()) self.lineEditLabel.text().encode('utf-8')
) )
else: else:
queues.UISignalQueue.put(('updateStatusBar', _translate( queues.UISignalQueue.put(('updateStatusBar', _translate(
@ -106,12 +114,12 @@ class AddAddressDialog(AddressDataDialog):
def __init__(self, parent=None, address=None): def __init__(self, parent=None, address=None):
super(AddAddressDialog, self).__init__(parent) super(AddAddressDialog, self).__init__(parent)
widgets.load('addaddressdialog.ui', self) widgets.load('addaddressdialog.ui', self)
AddressCheckMixin.__init__(self) self._setup()
if address: if address:
self.lineEditAddress.setText(address) self.lineEditAddress.setText(address)
class NewAddressDialog(QtGui.QDialog): class NewAddressDialog(QtWidgets.QDialog):
"""QDialog for generating a new address""" """QDialog for generating a new address"""
def __init__(self, parent=None): def __init__(self, parent=None):
@ -124,7 +132,7 @@ class NewAddressDialog(QtGui.QDialog):
self.radioButtonExisting.click() self.radioButtonExisting.click()
self.comboBoxExisting.addItem(address) self.comboBoxExisting.addItem(address)
self.groupBoxDeterministic.setHidden(True) self.groupBoxDeterministic.setHidden(True)
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) QtWidgets.QWidget.resize(self, QtWidgets.QWidget.sizeHint(self))
self.show() self.show()
def accept(self): def accept(self):
@ -141,13 +149,13 @@ class NewAddressDialog(QtGui.QDialog):
self.comboBoxExisting.currentText())[2] self.comboBoxExisting.currentText())[2]
queues.addressGeneratorQueue.put(( queues.addressGeneratorQueue.put((
'createRandomAddress', 4, streamNumberForAddress, 'createRandomAddress', 4, streamNumberForAddress,
str(self.newaddresslabel.text().toUtf8()), 1, "", self.newaddresslabel.text().encode('utf-8'), 1, "",
self.checkBoxEighteenByteRipe.isChecked() self.checkBoxEighteenByteRipe.isChecked()
)) ))
else: else:
if self.lineEditPassphrase.text() != \ if self.lineEditPassphrase.text() != \
self.lineEditPassphraseAgain.text(): self.lineEditPassphraseAgain.text():
QtGui.QMessageBox.about( QtWidgets.QMessageBox.about(
self, _translate("MainWindow", "Passphrase mismatch"), self, _translate("MainWindow", "Passphrase mismatch"),
_translate( _translate(
"MainWindow", "MainWindow",
@ -155,7 +163,7 @@ class NewAddressDialog(QtGui.QDialog):
" match. Try again.") " match. Try again.")
) )
elif self.lineEditPassphrase.text() == "": elif self.lineEditPassphrase.text() == "":
QtGui.QMessageBox.about( QtWidgets.QMessageBox.about(
self, _translate("MainWindow", "Choose a passphrase"), self, _translate("MainWindow", "Choose a passphrase"),
_translate( _translate(
"MainWindow", "You really do need a passphrase.") "MainWindow", "You really do need a passphrase.")
@ -168,7 +176,7 @@ class NewAddressDialog(QtGui.QDialog):
'createDeterministicAddresses', 4, streamNumberForAddress, 'createDeterministicAddresses', 4, streamNumberForAddress,
"unused deterministic address", "unused deterministic address",
self.spinBoxNumberOfAddressesToMake.value(), self.spinBoxNumberOfAddressesToMake.value(),
self.lineEditPassphrase.text().toUtf8(), self.lineEditPassphrase.text().encode('utf-8'),
self.checkBoxEighteenByteRipe.isChecked() self.checkBoxEighteenByteRipe.isChecked()
)) ))
@ -179,7 +187,8 @@ class NewSubscriptionDialog(AddressDataDialog):
def __init__(self, parent=None): def __init__(self, parent=None):
super(NewSubscriptionDialog, self).__init__(parent) super(NewSubscriptionDialog, self).__init__(parent)
widgets.load('newsubscriptiondialog.ui', self) widgets.load('newsubscriptiondialog.ui', self)
AddressCheckMixin.__init__(self) self.recent = []
self._setup()
def _onSuccess(self, addressVersion, streamNumber, ripe): def _onSuccess(self, addressVersion, streamNumber, ripe):
if addressVersion <= 3: if addressVersion <= 3:
@ -210,22 +219,21 @@ class NewSubscriptionDialog(AddressDataDialog):
_translate( _translate(
"MainWindow", "MainWindow",
"Display the %n recent broadcast(s) from this address.", "Display the %n recent broadcast(s) from this address.",
None, None, count
QtCore.QCoreApplication.CodecForTr,
count
)) ))
class RegenerateAddressesDialog(QtGui.QDialog): class RegenerateAddressesDialog(QtWidgets.QDialog):
"""QDialog for regenerating deterministic addresses""" """QDialog for regenerating deterministic addresses"""
def __init__(self, parent=None): def __init__(self, parent=None):
super(RegenerateAddressesDialog, self).__init__(parent) super(RegenerateAddressesDialog, self).__init__(parent)
widgets.load('regenerateaddresses.ui', self) widgets.load('regenerateaddresses.ui', self)
self.groupBox.setTitle('') self.groupBox.setTitle('')
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) QtWidgets.QWidget.resize(self, QtWidgets.QWidget.sizeHint(self))
class SpecialAddressBehaviorDialog(QtGui.QDialog): class SpecialAddressBehaviorDialog(QtWidgets.QDialog):
""" """
QDialog for special address behaviour (e.g. mailing list functionality) QDialog for special address behaviour (e.g. mailing list functionality)
""" """
@ -256,12 +264,12 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog):
self.radioButtonBehaviorMailingList.click() self.radioButtonBehaviorMailingList.click()
else: else:
self.radioButtonBehaveNormalAddress.click() self.radioButtonBehaveNormalAddress.click()
mailingListName = config.safeGet(self.address, 'mailinglistname', '') mailingListName = config.safeGet(
self.address, 'mailinglistname', '')
self.lineEditMailingListName.setText( self.lineEditMailingListName.setText(
unicode(mailingListName, 'utf-8') mailingListName.decode('utf-8'))
)
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) QtWidgets.QWidget.resize(self, QtWidgets.QWidget.sizeHint(self))
self.show() self.show()
def accept(self): def accept(self):
@ -274,14 +282,15 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog):
# Set the color to either black or grey # Set the color to either black or grey
if self.config.getboolean(self.address, 'enabled'): if self.config.getboolean(self.address, 'enabled'):
self.parent.setCurrentItemColor( self.parent.setCurrentItemColor(
QtGui.QApplication.palette().text().color() QtWidgets.QApplication.palette().text().color()
) )
else: else:
self.parent.setCurrentItemColor(QtGui.QColor(128, 128, 128)) self.parent.setCurrentItemColor(QtGui.QColor(128, 128, 128))
else: else:
self.config.set(str(self.address), 'mailinglist', 'true') self.config.set(str(self.address), 'mailinglist', 'true')
self.config.set(str(self.address), 'mailinglistname', str( self.config.set(
self.lineEditMailingListName.text().toUtf8())) str(self.address), 'mailinglistname',
self.lineEditMailingListName.text().encode('utf-8'))
self.parent.setCurrentItemColor( self.parent.setCurrentItemColor(
QtGui.QColor(137, 4, 177)) # magenta QtGui.QColor(137, 4, 177)) # magenta
self.parent.rerenderComboBoxSendFrom() self.parent.rerenderComboBoxSendFrom()
@ -290,13 +299,15 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog):
self.parent.rerenderMessagelistToLabels() self.parent.rerenderMessagelistToLabels()
class EmailGatewayDialog(QtGui.QDialog): class EmailGatewayDialog(QtWidgets.QDialog):
"""QDialog for email gateway control""" """QDialog for email gateway control"""
def __init__(self, parent, config=None, account=None): def __init__(self, parent, config=None, account=None):
super(EmailGatewayDialog, self).__init__(parent) super(EmailGatewayDialog, self).__init__(parent)
widgets.load('emailgateway.ui', self) widgets.load('emailgateway.ui', self)
self.parent = parent self.parent = parent
self.config = config self.config = config
self.data = None
if account: if account:
self.acct = account self.acct = account
self.setWindowTitle(_translate( self.setWindowTitle(_translate(
@ -329,7 +340,7 @@ class EmailGatewayDialog(QtGui.QDialog):
else: else:
self.acct = MailchuckAccount(address) self.acct = MailchuckAccount(address)
self.lineEditEmail.setFocus() self.lineEditEmail.setFocus()
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) QtWidgets.QWidget.resize(self, QtWidgets.QWidget.sizeHint(self))
def accept(self): def accept(self):
"""Accept callback""" """Accept callback"""
@ -343,7 +354,7 @@ class EmailGatewayDialog(QtGui.QDialog):
if self.radioButtonRegister.isChecked() \ if self.radioButtonRegister.isChecked() \
or self.radioButtonRegister.isHidden(): or self.radioButtonRegister.isHidden():
email = str(self.lineEditEmail.text().toUtf8()) email = self.lineEditEmail.text().encode('utf-8')
self.acct.register(email) self.acct.register(email)
self.config.set(self.acct.fromAddress, 'label', email) self.config.set(self.acct.fromAddress, 'label', email)
self.config.set(self.acct.fromAddress, 'gateway', 'mailchuck') self.config.set(self.acct.fromAddress, 'gateway', 'mailchuck')

View File

@ -1,14 +1,16 @@
""" """
Address validator module. The validator for address and passphrase QLineEdits
used in `.dialogs.NewChanDialog`.
""" """
# pylint: disable=too-many-branches,too-many-arguments # pylint: disable=too-many-arguments
from PyQt4 import QtGui
from Queue import Empty from Queue import Empty
from qtpy import QtGui
from account import getSortedAccounts from account import getSortedAccounts
from addresses import decodeAddress, addBMIfNotPresent from addresses import decodeAddress, addBMIfNotPresent
from queues import apiAddressGeneratorReturnQueue, addressGeneratorQueue from queues import addressGeneratorQueue, apiAddressGeneratorReturnQueue
from tr import _translate from tr import _translate
from utils import str_chan from utils import str_chan
@ -16,22 +18,18 @@ from utils import str_chan
class AddressPassPhraseValidatorMixin(object): class AddressPassPhraseValidatorMixin(object):
"""Bitmessage address or passphrase validator class for Qt UI""" """Bitmessage address or passphrase validator class for Qt UI"""
def setParams( def setParams(
self, self, passPhraseObject=None, addressObject=None,
passPhraseObject=None, feedBackObject=None, button=None, addressMandatory=True
addressObject=None,
feedBackObject=None,
buttonBox=None,
addressMandatory=True,
): ):
"""Initialisation""" """Initialization"""
self.addressObject = addressObject self.addressObject = addressObject
self.passPhraseObject = passPhraseObject self.passPhraseObject = passPhraseObject
self.feedBackObject = feedBackObject self.feedBackObject = feedBackObject
self.buttonBox = buttonBox
self.addressMandatory = addressMandatory self.addressMandatory = addressMandatory
self.isValid = False self.isValid = False
# save default text # save default text
self.okButtonLabel = self.buttonBox.button(QtGui.QDialogButtonBox.Ok).text() self.okButton = button
self.okButtonLabel = button.text()
def setError(self, string): def setError(self, string):
"""Indicate that the validation is pending or failed""" """Indicate that the validation is pending or failed"""
@ -42,13 +40,13 @@ class AddressPassPhraseValidatorMixin(object):
self.feedBackObject.setStyleSheet("QLabel { color : red; }") self.feedBackObject.setStyleSheet("QLabel { color : red; }")
self.feedBackObject.setText(string) self.feedBackObject.setText(string)
self.isValid = False self.isValid = False
if self.buttonBox: if self.okButton:
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(False) self.okButton.setEnabled(False)
if string is not None and self.feedBackObject is not None: if string is not None and self.feedBackObject is not None:
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setText( self.okButton.setText(
_translate("AddressValidator", "Invalid")) _translate("AddressValidator", "Invalid"))
else: else:
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setText( self.okButton.setText(
_translate("AddressValidator", "Validating...")) _translate("AddressValidator", "Validating..."))
def setOK(self, string): def setOK(self, string):
@ -60,9 +58,9 @@ class AddressPassPhraseValidatorMixin(object):
self.feedBackObject.setStyleSheet("QLabel { }") self.feedBackObject.setStyleSheet("QLabel { }")
self.feedBackObject.setText(string) self.feedBackObject.setText(string)
self.isValid = True self.isValid = True
if self.buttonBox: if self.okButton:
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True) self.okButton.setEnabled(True)
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setText(self.okButtonLabel) self.okButton.setText(self.okButtonLabel)
def checkQueue(self): def checkQueue(self):
"""Validator queue loop""" """Validator queue loop"""
@ -75,7 +73,8 @@ class AddressPassPhraseValidatorMixin(object):
while True: while True:
try: try:
addressGeneratorReturnValue = apiAddressGeneratorReturnQueue.get(False) addressGeneratorReturnValue = \
apiAddressGeneratorReturnQueue.get(False)
except Empty: except Empty:
if gotOne: if gotOne:
break break
@ -85,96 +84,120 @@ class AddressPassPhraseValidatorMixin(object):
gotOne = True gotOne = True
if not addressGeneratorReturnValue: if not addressGeneratorReturnValue:
self.setError(_translate("AddressValidator", "Address already present as one of your identities.")) self.setError(_translate(
return (QtGui.QValidator.Intermediate, 0) "AddressValidator",
if addressGeneratorReturnValue[0] == 'chan name does not match address': "Address already present as one of your identities."
self.setError( ))
_translate( return
"AddressValidator", if addressGeneratorReturnValue[0] == \
"Although the Bitmessage address you " 'chan name does not match address':
"entered was valid, it doesn't match the chan name.")) self.setError(_translate(
return (QtGui.QValidator.Intermediate, 0) "AddressValidator",
self.setOK(_translate("MainWindow", "Passphrase and address appear to be valid.")) "Although the Bitmessage address you entered was valid,"
" it doesn\'t match the chan name."
))
return
self.setOK(_translate(
"MainWindow", "Passphrase and address appear to be valid."))
def returnValid(self): def returnValid(self):
"""Return the value of whether the validation was successful""" """Return the value of whether the validation was successful"""
if self.isValid: return QtGui.QValidator.Acceptable if self.isValid \
return QtGui.QValidator.Acceptable else QtGui.QValidator.Intermediate
return QtGui.QValidator.Intermediate
def validate(self, s, pos): def validate(self, s, pos):
"""Top level validator method""" """Top level validator method"""
if self.addressObject is None: try:
address = self.addressObject.text().encode('utf-8')
except AttributeError:
address = None address = None
else: try:
address = str(self.addressObject.text().toUtf8()) passPhrase = self.passPhraseObject.text().encode('utf-8')
if address == "": except AttributeError:
address = None
if self.passPhraseObject is None:
passPhrase = "" passPhrase = ""
else:
passPhrase = str(self.passPhraseObject.text().toUtf8())
if passPhrase == "":
passPhrase = None
# no chan name # no chan name
if passPhrase is None: if not passPhrase:
self.setError(_translate("AddressValidator", "Chan name/passphrase needed. You didn't enter a chan name.")) self.setError(_translate(
return (QtGui.QValidator.Intermediate, pos) "AddressValidator",
"Chan name/passphrase needed. You didn't enter a chan name."
))
return (QtGui.QValidator.Intermediate, s, pos)
if self.addressMandatory or address is not None: if self.addressMandatory or address:
# check if address already exists: # check if address already exists:
if address in getSortedAccounts(): if address in getSortedAccounts():
self.setError(_translate("AddressValidator", "Address already present as one of your identities.")) self.setError(_translate(
return (QtGui.QValidator.Intermediate, pos) "AddressValidator",
"Address already present as one of your identities."
))
return (QtGui.QValidator.Intermediate, s, pos)
status = decodeAddress(address)[0]
# version too high # version too high
if decodeAddress(address)[0] == 'versiontoohigh': if status == 'versiontoohigh':
self.setError( self.setError(_translate(
_translate( "AddressValidator",
"AddressValidator", "Address too new. Although that Bitmessage address"
"Address too new. Although that Bitmessage" " might be valid, its version number is too new"
" address might be valid, its version number" " for us to handle. Perhaps you need to upgrade"
" is too new for us to handle. Perhaps you need" " Bitmessage."
" to upgrade Bitmessage.")) ))
return (QtGui.QValidator.Intermediate, pos) return (QtGui.QValidator.Intermediate, s, pos)
# invalid # invalid
if decodeAddress(address)[0] != 'success': if status != 'success':
self.setError(_translate("AddressValidator", "The Bitmessage address is not valid.")) self.setError(_translate(
return (QtGui.QValidator.Intermediate, pos) "AddressValidator",
"The Bitmessage address is not valid."
))
return (QtGui.QValidator.Intermediate, s, pos)
# this just disables the OK button without changing the feedback text # this just disables the OK button without changing the feedback text
# but only if triggered by textEdited, not by clicking the Ok button # but only if triggered by textEdited, not by clicking the Ok button
if not self.buttonBox.button(QtGui.QDialogButtonBox.Ok).hasFocus(): if not self.okButton.hasFocus():
self.setError(None) self.setError(None)
# check through generator # check through generator
if address is None: if not address:
addressGeneratorQueue.put(('createChan', 4, 1, str_chan + ' ' + str(passPhrase), passPhrase, False)) addressGeneratorQueue.put((
'createChan', 4, 1,
str_chan + ' ' + passPhrase, passPhrase, False
))
else: else:
addressGeneratorQueue.put( addressGeneratorQueue.put((
('joinChan', addBMIfNotPresent(address), 'joinChan', addBMIfNotPresent(address),
"{} {}".format(str_chan, passPhrase), passPhrase, False)) "{} {}".format(str_chan, passPhrase), passPhrase, False
))
if self.buttonBox.button(QtGui.QDialogButtonBox.Ok).hasFocus(): if self.okButton.hasFocus():
return (self.returnValid(), pos) return (self.returnValid(), s, pos)
return (QtGui.QValidator.Intermediate, pos) else:
return (QtGui.QValidator.Intermediate, s, pos)
def checkData(self): def checkData(self):
"""Validator Qt signal interface""" """Validator Qt signal interface"""
return self.validate("", 0) return self.validate(u"", 0)
class AddressValidator(QtGui.QValidator, AddressPassPhraseValidatorMixin): class AddressValidator(QtGui.QValidator, AddressPassPhraseValidatorMixin):
"""AddressValidator class for Qt UI""" """AddressValidator class for Qt UI"""
def __init__(self, parent=None, passPhraseObject=None, feedBackObject=None, buttonBox=None, addressMandatory=True): def __init__(
self, parent=None, passPhraseObject=None, feedBackObject=None,
button=None, addressMandatory=True
):
super(AddressValidator, self).__init__(parent) super(AddressValidator, self).__init__(parent)
self.setParams(passPhraseObject, parent, feedBackObject, buttonBox, addressMandatory) self.setParams(
passPhraseObject, parent, feedBackObject, button,
addressMandatory)
class PassPhraseValidator(QtGui.QValidator, AddressPassPhraseValidatorMixin): class PassPhraseValidator(QtGui.QValidator, AddressPassPhraseValidatorMixin):
"""PassPhraseValidator class for Qt UI""" """PassPhraseValidator class for Qt UI"""
def __init__(self, parent=None, addressObject=None, feedBackObject=None, buttonBox=None, addressMandatory=False): def __init__(
self, parent=None, addressObject=None, feedBackObject=None,
button=None, addressMandatory=False
):
super(PassPhraseValidator, self).__init__(parent) super(PassPhraseValidator, self).__init__(parent)
self.setParams(parent, addressObject, feedBackObject, buttonBox, addressMandatory) self.setParams(
parent, addressObject, feedBackObject, button,
addressMandatory)

View File

@ -7,7 +7,7 @@
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore from qtpy import QtCore
qt_resource_data = "\ qt_resource_data = "\
\x00\x00\x03\x66\ \x00\x00\x03\x66\
@ -1666,10 +1666,15 @@ qt_resource_struct = "\
\x00\x00\x01\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x34\xdf\ \x00\x00\x01\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x34\xdf\
" "
def qInitResources(): def qInitResources():
QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) QtCore.qRegisterResourceData(
0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
def qCleanupResources(): def qCleanupResources():
QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) QtCore.qUnregisterResourceData(
0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
qInitResources() qInitResources()

View File

@ -1,13 +1,8 @@
# -*- coding: utf-8 -*- # pylint: skip-file
# flake8: noqa
# Form implementation generated from reading ui file 'bitmessageui.ui' from qtpy import QtCore, QtGui, QtWidgets
# from tr import _translate
# Created: Mon Mar 23 22:18:07 2015
# by: PyQt4 UI code generator 4.10.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
from bmconfigparser import BMConfigParser from bmconfigparser import BMConfigParser
from foldertree import AddressBookCompleter from foldertree import AddressBookCompleter
from messageview import MessageView from messageview import MessageView
@ -16,40 +11,23 @@ import settingsmixin
from networkstatus import NetworkStatus from networkstatus import NetworkStatus
from blacklist import Blacklist from blacklist import Blacklist
try: import bitmessage_icons_rc
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig, encoding = QtCore.QCoreApplication.CodecForTr, n = None):
if n is None:
return QtGui.QApplication.translate(context, text, disambig, _encoding)
else:
return QtGui.QApplication.translate(context, text, disambig, _encoding, n)
except AttributeError:
def _translate(context, text, disambig, encoding = QtCore.QCoreApplication.CodecForTr, n = None):
if n is None:
return QtGui.QApplication.translate(context, text, disambig)
else:
return QtGui.QApplication.translate(context, text, disambig, QtCore.QCoreApplication.CodecForTr, n)
class Ui_MainWindow(object): class Ui_MainWindow(object):
def setupUi(self, MainWindow): def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow")) MainWindow.setObjectName("MainWindow")
MainWindow.resize(885, 580) MainWindow.resize(885, 580)
icon = QtGui.QIcon() icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/can-icon-24px.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon.addPixmap(QtGui.QPixmap(":/newPrefix/images/can-icon-24px.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MainWindow.setWindowIcon(icon) MainWindow.setWindowIcon(icon)
MainWindow.setTabShape(QtGui.QTabWidget.Rounded) MainWindow.setTabShape(QtWidgets.QTabWidget.Rounded)
self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget")) self.centralwidget.setObjectName("centralwidget")
self.gridLayout_10 = QtGui.QGridLayout(self.centralwidget) self.gridLayout_10 = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout_10.setObjectName(_fromUtf8("gridLayout_10")) self.gridLayout_10.setObjectName("gridLayout_10")
self.tabWidget = QtGui.QTabWidget(self.centralwidget) self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth())
@ -59,27 +37,27 @@ class Ui_MainWindow(object):
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setPointSize(9)
self.tabWidget.setFont(font) self.tabWidget.setFont(font)
self.tabWidget.setTabPosition(QtGui.QTabWidget.North) self.tabWidget.setTabPosition(QtWidgets.QTabWidget.North)
self.tabWidget.setTabShape(QtGui.QTabWidget.Rounded) self.tabWidget.setTabShape(QtWidgets.QTabWidget.Rounded)
self.tabWidget.setObjectName(_fromUtf8("tabWidget")) self.tabWidget.setObjectName("tabWidget")
self.inbox = QtGui.QWidget() self.inbox = QtWidgets.QWidget()
self.inbox.setObjectName(_fromUtf8("inbox")) self.inbox.setObjectName("inbox")
self.gridLayout = QtGui.QGridLayout(self.inbox) self.gridLayout = QtWidgets.QGridLayout(self.inbox)
self.gridLayout.setObjectName(_fromUtf8("gridLayout")) self.gridLayout.setObjectName("gridLayout")
self.horizontalSplitter_3 = settingsmixin.SSplitter() self.horizontalSplitter_3 = settingsmixin.SSplitter()
self.horizontalSplitter_3.setObjectName(_fromUtf8("horizontalSplitter_3")) self.horizontalSplitter_3.setObjectName("horizontalSplitter_3")
self.verticalSplitter_12 = settingsmixin.SSplitter() self.verticalSplitter_12 = settingsmixin.SSplitter()
self.verticalSplitter_12.setObjectName(_fromUtf8("verticalSplitter_12")) self.verticalSplitter_12.setObjectName("verticalSplitter_12")
self.verticalSplitter_12.setOrientation(QtCore.Qt.Vertical) self.verticalSplitter_12.setOrientation(QtCore.Qt.Vertical)
self.treeWidgetYourIdentities = settingsmixin.STreeWidget(self.inbox) self.treeWidgetYourIdentities = settingsmixin.STreeWidget(self.inbox)
self.treeWidgetYourIdentities.setObjectName(_fromUtf8("treeWidgetYourIdentities")) self.treeWidgetYourIdentities.setObjectName("treeWidgetYourIdentities")
self.treeWidgetYourIdentities.resize(200, self.treeWidgetYourIdentities.height()) self.treeWidgetYourIdentities.resize(200, self.treeWidgetYourIdentities.height())
icon1 = QtGui.QIcon() icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/identities.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off) icon1.addPixmap(QtGui.QPixmap(":/newPrefix/images/identities.png"), QtGui.QIcon.Selected, QtGui.QIcon.Off)
self.treeWidgetYourIdentities.headerItem().setIcon(0, icon1) self.treeWidgetYourIdentities.headerItem().setIcon(0, icon1)
self.verticalSplitter_12.addWidget(self.treeWidgetYourIdentities) self.verticalSplitter_12.addWidget(self.treeWidgetYourIdentities)
self.pushButtonNewAddress = QtGui.QPushButton(self.inbox) self.pushButtonNewAddress = QtWidgets.QPushButton(self.inbox)
self.pushButtonNewAddress.setObjectName(_fromUtf8("pushButtonNewAddress")) self.pushButtonNewAddress.setObjectName("pushButtonNewAddress")
self.pushButtonNewAddress.resize(200, self.pushButtonNewAddress.height()) self.pushButtonNewAddress.resize(200, self.pushButtonNewAddress.height())
self.verticalSplitter_12.addWidget(self.pushButtonNewAddress) self.verticalSplitter_12.addWidget(self.pushButtonNewAddress)
self.verticalSplitter_12.setStretchFactor(0, 1) self.verticalSplitter_12.setStretchFactor(0, 1)
@ -89,21 +67,21 @@ class Ui_MainWindow(object):
self.verticalSplitter_12.handle(1).setEnabled(False) self.verticalSplitter_12.handle(1).setEnabled(False)
self.horizontalSplitter_3.addWidget(self.verticalSplitter_12) self.horizontalSplitter_3.addWidget(self.verticalSplitter_12)
self.verticalSplitter_7 = settingsmixin.SSplitter() self.verticalSplitter_7 = settingsmixin.SSplitter()
self.verticalSplitter_7.setObjectName(_fromUtf8("verticalSplitter_7")) self.verticalSplitter_7.setObjectName("verticalSplitter_7")
self.verticalSplitter_7.setOrientation(QtCore.Qt.Vertical) self.verticalSplitter_7.setOrientation(QtCore.Qt.Vertical)
self.horizontalSplitterSearch = QtGui.QSplitter() self.horizontalSplitterSearch = QtWidgets.QSplitter()
self.horizontalSplitterSearch.setObjectName(_fromUtf8("horizontalSplitterSearch")) self.horizontalSplitterSearch.setObjectName("horizontalSplitterSearch")
self.inboxSearchLineEdit = QtGui.QLineEdit(self.inbox) self.inboxSearchLineEdit = QtWidgets.QLineEdit(self.inbox)
self.inboxSearchLineEdit.setObjectName(_fromUtf8("inboxSearchLineEdit")) self.inboxSearchLineEdit.setObjectName("inboxSearchLineEdit")
self.horizontalSplitterSearch.addWidget(self.inboxSearchLineEdit) self.horizontalSplitterSearch.addWidget(self.inboxSearchLineEdit)
self.inboxSearchOption = QtGui.QComboBox(self.inbox) self.inboxSearchOption = QtWidgets.QComboBox(self.inbox)
self.inboxSearchOption.setObjectName(_fromUtf8("inboxSearchOption")) self.inboxSearchOption.setObjectName("inboxSearchOption")
self.inboxSearchOption.addItem(_fromUtf8("")) self.inboxSearchOption.addItem("")
self.inboxSearchOption.addItem(_fromUtf8("")) self.inboxSearchOption.addItem("")
self.inboxSearchOption.addItem(_fromUtf8("")) self.inboxSearchOption.addItem("")
self.inboxSearchOption.addItem(_fromUtf8("")) self.inboxSearchOption.addItem("")
self.inboxSearchOption.addItem(_fromUtf8("")) self.inboxSearchOption.addItem("")
self.inboxSearchOption.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) self.inboxSearchOption.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)
self.inboxSearchOption.setCurrentIndex(3) self.inboxSearchOption.setCurrentIndex(3)
self.horizontalSplitterSearch.addWidget(self.inboxSearchOption) self.horizontalSplitterSearch.addWidget(self.inboxSearchOption)
self.horizontalSplitterSearch.handle(1).setEnabled(False) self.horizontalSplitterSearch.handle(1).setEnabled(False)
@ -111,21 +89,21 @@ class Ui_MainWindow(object):
self.horizontalSplitterSearch.setStretchFactor(1, 0) self.horizontalSplitterSearch.setStretchFactor(1, 0)
self.verticalSplitter_7.addWidget(self.horizontalSplitterSearch) self.verticalSplitter_7.addWidget(self.horizontalSplitterSearch)
self.tableWidgetInbox = settingsmixin.STableWidget(self.inbox) self.tableWidgetInbox = settingsmixin.STableWidget(self.inbox)
self.tableWidgetInbox.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) self.tableWidgetInbox.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.tableWidgetInbox.setAlternatingRowColors(True) self.tableWidgetInbox.setAlternatingRowColors(True)
self.tableWidgetInbox.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.tableWidgetInbox.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.tableWidgetInbox.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.tableWidgetInbox.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.tableWidgetInbox.setWordWrap(False) self.tableWidgetInbox.setWordWrap(False)
self.tableWidgetInbox.setObjectName(_fromUtf8("tableWidgetInbox")) self.tableWidgetInbox.setObjectName("tableWidgetInbox")
self.tableWidgetInbox.setColumnCount(4) self.tableWidgetInbox.setColumnCount(4)
self.tableWidgetInbox.setRowCount(0) self.tableWidgetInbox.setRowCount(0)
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidgetInbox.setHorizontalHeaderItem(0, item) self.tableWidgetInbox.setHorizontalHeaderItem(0, item)
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidgetInbox.setHorizontalHeaderItem(1, item) self.tableWidgetInbox.setHorizontalHeaderItem(1, item)
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidgetInbox.setHorizontalHeaderItem(2, item) self.tableWidgetInbox.setHorizontalHeaderItem(2, item)
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidgetInbox.setHorizontalHeaderItem(3, item) self.tableWidgetInbox.setHorizontalHeaderItem(3, item)
self.tableWidgetInbox.horizontalHeader().setCascadingSectionResizes(True) self.tableWidgetInbox.horizontalHeader().setCascadingSectionResizes(True)
self.tableWidgetInbox.horizontalHeader().setDefaultSectionSize(200) self.tableWidgetInbox.horizontalHeader().setDefaultSectionSize(200)
@ -139,7 +117,7 @@ class Ui_MainWindow(object):
self.textEditInboxMessage = MessageView(self.inbox) self.textEditInboxMessage = MessageView(self.inbox)
self.textEditInboxMessage.setBaseSize(QtCore.QSize(0, 500)) self.textEditInboxMessage.setBaseSize(QtCore.QSize(0, 500))
self.textEditInboxMessage.setReadOnly(True) self.textEditInboxMessage.setReadOnly(True)
self.textEditInboxMessage.setObjectName(_fromUtf8("textEditInboxMessage")) self.textEditInboxMessage.setObjectName("textEditInboxMessage")
self.verticalSplitter_7.addWidget(self.textEditInboxMessage) self.verticalSplitter_7.addWidget(self.textEditInboxMessage)
self.verticalSplitter_7.setStretchFactor(0, 0) self.verticalSplitter_7.setStretchFactor(0, 0)
self.verticalSplitter_7.setStretchFactor(1, 1) self.verticalSplitter_7.setStretchFactor(1, 1)
@ -155,50 +133,51 @@ class Ui_MainWindow(object):
self.horizontalSplitter_3.setCollapsible(1, False) self.horizontalSplitter_3.setCollapsible(1, False)
self.gridLayout.addWidget(self.horizontalSplitter_3) self.gridLayout.addWidget(self.horizontalSplitter_3)
icon2 = QtGui.QIcon() icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/inbox.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon2.addPixmap(QtGui.QPixmap(":/newPrefix/images/inbox.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.tabWidget.addTab(self.inbox, icon2, _fromUtf8("")) self.tabWidget.addTab(self.inbox, icon2, "")
self.send = QtGui.QWidget() self.send = QtWidgets.QWidget()
self.send.setObjectName(_fromUtf8("send")) self.send.setObjectName("send")
self.gridLayout_7 = QtGui.QGridLayout(self.send) self.gridLayout_7 = QtWidgets.QGridLayout(self.send)
self.gridLayout_7.setObjectName(_fromUtf8("gridLayout_7")) self.gridLayout_7.setObjectName("gridLayout_7")
self.horizontalSplitter = settingsmixin.SSplitter() self.horizontalSplitter = settingsmixin.SSplitter()
self.horizontalSplitter.setObjectName(_fromUtf8("horizontalSplitter")) self.horizontalSplitter.setObjectName("horizontalSplitter")
self.verticalSplitter_2 = settingsmixin.SSplitter() self.verticalSplitter_2 = settingsmixin.SSplitter()
self.verticalSplitter_2.setObjectName(_fromUtf8("verticalSplitter_2")) self.verticalSplitter_2.setObjectName("verticalSplitter_2")
self.verticalSplitter_2.setOrientation(QtCore.Qt.Vertical) self.verticalSplitter_2.setOrientation(QtCore.Qt.Vertical)
self.tableWidgetAddressBook = settingsmixin.STableWidget(self.send) self.tableWidgetAddressBook = settingsmixin.STableWidget(self.send)
self.tableWidgetAddressBook.setAlternatingRowColors(True) self.tableWidgetAddressBook.setAlternatingRowColors(True)
self.tableWidgetAddressBook.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.tableWidgetAddressBook.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.tableWidgetAddressBook.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.tableWidgetAddressBook.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.tableWidgetAddressBook.setObjectName(_fromUtf8("tableWidgetAddressBook")) self.tableWidgetAddressBook.setObjectName("tableWidgetAddressBook")
self.tableWidgetAddressBook.setColumnCount(2) self.tableWidgetAddressBook.setColumnCount(2)
self.tableWidgetAddressBook.setRowCount(0) self.tableWidgetAddressBook.setRowCount(0)
self.tableWidgetAddressBook.resize(200, self.tableWidgetAddressBook.height()) self.tableWidgetAddressBook.resize(200, self.tableWidgetAddressBook.height())
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
icon3 = QtGui.QIcon() icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/addressbook.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off) icon3.addPixmap(QtGui.QPixmap(":/newPrefix/images/addressbook.png"), QtGui.QIcon.Selected, QtGui.QIcon.Off)
item.setIcon(icon3) item.setIcon(icon3)
self.tableWidgetAddressBook.setHorizontalHeaderItem(0, item) self.tableWidgetAddressBook.setHorizontalHeaderItem(0, item)
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidgetAddressBook.setHorizontalHeaderItem(1, item) self.tableWidgetAddressBook.setHorizontalHeaderItem(1, item)
self.tableWidgetAddressBook.horizontalHeader().setCascadingSectionResizes(True) self.tableWidgetAddressBook.horizontalHeader().setCascadingSectionResizes(True)
self.tableWidgetAddressBook.horizontalHeader().setDefaultSectionSize(200) self.tableWidgetAddressBook.horizontalHeader().setDefaultSectionSize(200)
self.tableWidgetAddressBook.horizontalHeader().setHighlightSections(False) self.tableWidgetAddressBook.horizontalHeader().setHighlightSections(False)
self.tableWidgetAddressBook.horizontalHeader().setStretchLastSection(True) self.tableWidgetAddressBook.horizontalHeader().setStretchLastSection(True)
self.tableWidgetAddressBook.verticalHeader().setVisible(False) self.tableWidgetAddressBook.verticalHeader().setVisible(False)
self.tableWidgetAddressBook.setWordWrap(False)
self.verticalSplitter_2.addWidget(self.tableWidgetAddressBook) self.verticalSplitter_2.addWidget(self.tableWidgetAddressBook)
self.addressBookCompleter = AddressBookCompleter() self.addressBookCompleter = AddressBookCompleter()
self.addressBookCompleter.setCompletionMode(QtGui.QCompleter.PopupCompletion) self.addressBookCompleter.setCompletionMode(QtWidgets.QCompleter.PopupCompletion)
self.addressBookCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.addressBookCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.addressBookCompleterModel = QtGui.QStringListModel() self.addressBookCompleterModel = QtCore.QStringListModel()
self.addressBookCompleter.setModel(self.addressBookCompleterModel) self.addressBookCompleter.setModel(self.addressBookCompleterModel)
self.pushButtonAddAddressBook = QtGui.QPushButton(self.send) self.pushButtonAddAddressBook = QtWidgets.QPushButton(self.send)
self.pushButtonAddAddressBook.setObjectName(_fromUtf8("pushButtonAddAddressBook")) self.pushButtonAddAddressBook.setObjectName("pushButtonAddAddressBook")
self.pushButtonAddAddressBook.resize(200, self.pushButtonAddAddressBook.height()) self.pushButtonAddAddressBook.resize(200, self.pushButtonAddAddressBook.height())
self.verticalSplitter_2.addWidget(self.pushButtonAddAddressBook) self.verticalSplitter_2.addWidget(self.pushButtonAddAddressBook)
self.pushButtonFetchNamecoinID = QtGui.QPushButton(self.send) self.pushButtonFetchNamecoinID = QtWidgets.QPushButton(self.send)
self.pushButtonFetchNamecoinID.resize(200, self.pushButtonFetchNamecoinID.height()) self.pushButtonFetchNamecoinID.resize(200, self.pushButtonFetchNamecoinID.height())
self.pushButtonFetchNamecoinID.setObjectName(_fromUtf8("pushButtonFetchNamecoinID")) self.pushButtonFetchNamecoinID.setObjectName("pushButtonFetchNamecoinID")
self.verticalSplitter_2.addWidget(self.pushButtonFetchNamecoinID) self.verticalSplitter_2.addWidget(self.pushButtonFetchNamecoinID)
self.verticalSplitter_2.setStretchFactor(0, 1) self.verticalSplitter_2.setStretchFactor(0, 1)
self.verticalSplitter_2.setStretchFactor(1, 0) self.verticalSplitter_2.setStretchFactor(1, 0)
@ -210,45 +189,45 @@ class Ui_MainWindow(object):
self.verticalSplitter_2.handle(2).setEnabled(False) self.verticalSplitter_2.handle(2).setEnabled(False)
self.horizontalSplitter.addWidget(self.verticalSplitter_2) self.horizontalSplitter.addWidget(self.verticalSplitter_2)
self.verticalSplitter = settingsmixin.SSplitter() self.verticalSplitter = settingsmixin.SSplitter()
self.verticalSplitter.setObjectName(_fromUtf8("verticalSplitter")) self.verticalSplitter.setObjectName("verticalSplitter")
self.verticalSplitter.setOrientation(QtCore.Qt.Vertical) self.verticalSplitter.setOrientation(QtCore.Qt.Vertical)
self.tabWidgetSend = QtGui.QTabWidget(self.send) self.tabWidgetSend = QtWidgets.QTabWidget(self.send)
self.tabWidgetSend.setObjectName(_fromUtf8("tabWidgetSend")) self.tabWidgetSend.setObjectName("tabWidgetSend")
self.sendDirect = QtGui.QWidget() self.sendDirect = QtWidgets.QWidget()
self.sendDirect.setObjectName(_fromUtf8("sendDirect")) self.sendDirect.setObjectName("sendDirect")
self.gridLayout_8 = QtGui.QGridLayout(self.sendDirect) self.gridLayout_8 = QtWidgets.QGridLayout(self.sendDirect)
self.gridLayout_8.setObjectName(_fromUtf8("gridLayout_8")) self.gridLayout_8.setObjectName("gridLayout_8")
self.verticalSplitter_5 = settingsmixin.SSplitter() self.verticalSplitter_5 = settingsmixin.SSplitter()
self.verticalSplitter_5.setObjectName(_fromUtf8("verticalSplitter_5")) self.verticalSplitter_5.setObjectName("verticalSplitter_5")
self.verticalSplitter_5.setOrientation(QtCore.Qt.Vertical) self.verticalSplitter_5.setOrientation(QtCore.Qt.Vertical)
self.gridLayout_2 = QtGui.QGridLayout() self.gridLayout_2 = QtWidgets.QGridLayout()
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) self.gridLayout_2.setObjectName("gridLayout_2")
self.label_3 = QtGui.QLabel(self.sendDirect) self.label_3 = QtWidgets.QLabel(self.sendDirect)
self.label_3.setObjectName(_fromUtf8("label_3")) self.label_3.setObjectName("label_3")
self.gridLayout_2.addWidget(self.label_3, 2, 0, 1, 1) self.gridLayout_2.addWidget(self.label_3, 2, 0, 1, 1)
self.label_2 = QtGui.QLabel(self.sendDirect) self.label_2 = QtWidgets.QLabel(self.sendDirect)
self.label_2.setObjectName(_fromUtf8("label_2")) self.label_2.setObjectName("label_2")
self.gridLayout_2.addWidget(self.label_2, 0, 0, 1, 1) self.gridLayout_2.addWidget(self.label_2, 0, 0, 1, 1)
self.lineEditSubject = QtGui.QLineEdit(self.sendDirect) self.lineEditSubject = QtWidgets.QLineEdit(self.sendDirect)
self.lineEditSubject.setText(_fromUtf8("")) self.lineEditSubject.setText("")
self.lineEditSubject.setObjectName(_fromUtf8("lineEditSubject")) self.lineEditSubject.setObjectName("lineEditSubject")
self.gridLayout_2.addWidget(self.lineEditSubject, 2, 1, 1, 1) self.gridLayout_2.addWidget(self.lineEditSubject, 2, 1, 1, 1)
self.label = QtGui.QLabel(self.sendDirect) self.label = QtWidgets.QLabel(self.sendDirect)
self.label.setObjectName(_fromUtf8("label")) self.label.setObjectName("label")
self.gridLayout_2.addWidget(self.label, 1, 0, 1, 1) self.gridLayout_2.addWidget(self.label, 1, 0, 1, 1)
self.comboBoxSendFrom = QtGui.QComboBox(self.sendDirect) self.comboBoxSendFrom = QtWidgets.QComboBox(self.sendDirect)
self.comboBoxSendFrom.setMinimumSize(QtCore.QSize(300, 0)) self.comboBoxSendFrom.setMinimumSize(QtCore.QSize(300, 0))
self.comboBoxSendFrom.setObjectName(_fromUtf8("comboBoxSendFrom")) self.comboBoxSendFrom.setObjectName("comboBoxSendFrom")
self.gridLayout_2.addWidget(self.comboBoxSendFrom, 0, 1, 1, 1) self.gridLayout_2.addWidget(self.comboBoxSendFrom, 0, 1, 1, 1)
self.lineEditTo = QtGui.QLineEdit(self.sendDirect) self.lineEditTo = QtWidgets.QLineEdit(self.sendDirect)
self.lineEditTo.setObjectName(_fromUtf8("lineEditTo")) self.lineEditTo.setObjectName("lineEditTo")
self.gridLayout_2.addWidget(self.lineEditTo, 1, 1, 1, 1) self.gridLayout_2.addWidget(self.lineEditTo, 1, 1, 1, 1)
self.lineEditTo.setCompleter(self.addressBookCompleter) self.lineEditTo.setCompleter(self.addressBookCompleter)
self.gridLayout_2_Widget = QtGui.QWidget() self.gridLayout_2_Widget = QtWidgets.QWidget()
self.gridLayout_2_Widget.setLayout(self.gridLayout_2) self.gridLayout_2_Widget.setLayout(self.gridLayout_2)
self.verticalSplitter_5.addWidget(self.gridLayout_2_Widget) self.verticalSplitter_5.addWidget(self.gridLayout_2_Widget)
self.textEditMessage = MessageCompose(self.sendDirect) self.textEditMessage = MessageCompose(self.sendDirect)
self.textEditMessage.setObjectName(_fromUtf8("textEditMessage")) self.textEditMessage.setObjectName("textEditMessage")
self.verticalSplitter_5.addWidget(self.textEditMessage) self.verticalSplitter_5.addWidget(self.textEditMessage)
self.verticalSplitter_5.setStretchFactor(0, 0) self.verticalSplitter_5.setStretchFactor(0, 0)
self.verticalSplitter_5.setStretchFactor(1, 1) self.verticalSplitter_5.setStretchFactor(1, 1)
@ -256,35 +235,35 @@ class Ui_MainWindow(object):
self.verticalSplitter_5.setCollapsible(1, False) self.verticalSplitter_5.setCollapsible(1, False)
self.verticalSplitter_5.handle(1).setEnabled(False) self.verticalSplitter_5.handle(1).setEnabled(False)
self.gridLayout_8.addWidget(self.verticalSplitter_5, 0, 0, 1, 1) self.gridLayout_8.addWidget(self.verticalSplitter_5, 0, 0, 1, 1)
self.tabWidgetSend.addTab(self.sendDirect, _fromUtf8("")) self.tabWidgetSend.addTab(self.sendDirect, "")
self.sendBroadcast = QtGui.QWidget() self.sendBroadcast = QtWidgets.QWidget()
self.sendBroadcast.setObjectName(_fromUtf8("sendBroadcast")) self.sendBroadcast.setObjectName("sendBroadcast")
self.gridLayout_9 = QtGui.QGridLayout(self.sendBroadcast) self.gridLayout_9 = QtWidgets.QGridLayout(self.sendBroadcast)
self.gridLayout_9.setObjectName(_fromUtf8("gridLayout_9")) self.gridLayout_9.setObjectName("gridLayout_9")
self.verticalSplitter_6 = settingsmixin.SSplitter() self.verticalSplitter_6 = settingsmixin.SSplitter()
self.verticalSplitter_6.setObjectName(_fromUtf8("verticalSplitter_6")) self.verticalSplitter_6.setObjectName("verticalSplitter_6")
self.verticalSplitter_6.setOrientation(QtCore.Qt.Vertical) self.verticalSplitter_6.setOrientation(QtCore.Qt.Vertical)
self.gridLayout_5 = QtGui.QGridLayout() self.gridLayout_5 = QtWidgets.QGridLayout()
self.gridLayout_5.setObjectName(_fromUtf8("gridLayout_5")) self.gridLayout_5.setObjectName("gridLayout_5")
self.label_8 = QtGui.QLabel(self.sendBroadcast) self.label_8 = QtWidgets.QLabel(self.sendBroadcast)
self.label_8.setObjectName(_fromUtf8("label_8")) self.label_8.setObjectName("label_8")
self.gridLayout_5.addWidget(self.label_8, 0, 0, 1, 1) self.gridLayout_5.addWidget(self.label_8, 0, 0, 1, 1)
self.lineEditSubjectBroadcast = QtGui.QLineEdit(self.sendBroadcast) self.lineEditSubjectBroadcast = QtWidgets.QLineEdit(self.sendBroadcast)
self.lineEditSubjectBroadcast.setText(_fromUtf8("")) self.lineEditSubjectBroadcast.setText("")
self.lineEditSubjectBroadcast.setObjectName(_fromUtf8("lineEditSubjectBroadcast")) self.lineEditSubjectBroadcast.setObjectName("lineEditSubjectBroadcast")
self.gridLayout_5.addWidget(self.lineEditSubjectBroadcast, 1, 1, 1, 1) self.gridLayout_5.addWidget(self.lineEditSubjectBroadcast, 1, 1, 1, 1)
self.label_7 = QtGui.QLabel(self.sendBroadcast) self.label_7 = QtWidgets.QLabel(self.sendBroadcast)
self.label_7.setObjectName(_fromUtf8("label_7")) self.label_7.setObjectName("label_7")
self.gridLayout_5.addWidget(self.label_7, 1, 0, 1, 1) self.gridLayout_5.addWidget(self.label_7, 1, 0, 1, 1)
self.comboBoxSendFromBroadcast = QtGui.QComboBox(self.sendBroadcast) self.comboBoxSendFromBroadcast = QtWidgets.QComboBox(self.sendBroadcast)
self.comboBoxSendFromBroadcast.setMinimumSize(QtCore.QSize(300, 0)) self.comboBoxSendFromBroadcast.setMinimumSize(QtCore.QSize(300, 0))
self.comboBoxSendFromBroadcast.setObjectName(_fromUtf8("comboBoxSendFromBroadcast")) self.comboBoxSendFromBroadcast.setObjectName("comboBoxSendFromBroadcast")
self.gridLayout_5.addWidget(self.comboBoxSendFromBroadcast, 0, 1, 1, 1) self.gridLayout_5.addWidget(self.comboBoxSendFromBroadcast, 0, 1, 1, 1)
self.gridLayout_5_Widget = QtGui.QWidget() self.gridLayout_5_Widget = QtWidgets.QWidget()
self.gridLayout_5_Widget.setLayout(self.gridLayout_5) self.gridLayout_5_Widget.setLayout(self.gridLayout_5)
self.verticalSplitter_6.addWidget(self.gridLayout_5_Widget) self.verticalSplitter_6.addWidget(self.gridLayout_5_Widget)
self.textEditMessageBroadcast = MessageCompose(self.sendBroadcast) self.textEditMessageBroadcast = MessageCompose(self.sendBroadcast)
self.textEditMessageBroadcast.setObjectName(_fromUtf8("textEditMessageBroadcast")) self.textEditMessageBroadcast.setObjectName("textEditMessageBroadcast")
self.verticalSplitter_6.addWidget(self.textEditMessageBroadcast) self.verticalSplitter_6.addWidget(self.textEditMessageBroadcast)
self.verticalSplitter_6.setStretchFactor(0, 0) self.verticalSplitter_6.setStretchFactor(0, 0)
self.verticalSplitter_6.setStretchFactor(1, 1) self.verticalSplitter_6.setStretchFactor(1, 1)
@ -292,15 +271,15 @@ class Ui_MainWindow(object):
self.verticalSplitter_6.setCollapsible(1, False) self.verticalSplitter_6.setCollapsible(1, False)
self.verticalSplitter_6.handle(1).setEnabled(False) self.verticalSplitter_6.handle(1).setEnabled(False)
self.gridLayout_9.addWidget(self.verticalSplitter_6, 0, 0, 1, 1) self.gridLayout_9.addWidget(self.verticalSplitter_6, 0, 0, 1, 1)
self.tabWidgetSend.addTab(self.sendBroadcast, _fromUtf8("")) self.tabWidgetSend.addTab(self.sendBroadcast, "")
self.verticalSplitter.addWidget(self.tabWidgetSend) self.verticalSplitter.addWidget(self.tabWidgetSend)
self.tTLContainer = QtGui.QWidget() self.tTLContainer = QtWidgets.QWidget()
self.tTLContainer.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed) self.tTLContainer.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
self.horizontalLayout_5 = QtGui.QHBoxLayout() self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
self.tTLContainer.setLayout(self.horizontalLayout_5) self.tTLContainer.setLayout(self.horizontalLayout_5)
self.horizontalLayout_5.setObjectName(_fromUtf8("horizontalLayout_5")) self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.pushButtonTTL = QtGui.QPushButton(self.send) self.pushButtonTTL = QtWidgets.QPushButton(self.send)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButtonTTL.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.pushButtonTTL.sizePolicy().hasHeightForWidth())
@ -320,29 +299,29 @@ class Ui_MainWindow(object):
font.setUnderline(True) font.setUnderline(True)
self.pushButtonTTL.setFont(font) self.pushButtonTTL.setFont(font)
self.pushButtonTTL.setFlat(True) self.pushButtonTTL.setFlat(True)
self.pushButtonTTL.setObjectName(_fromUtf8("pushButtonTTL")) self.pushButtonTTL.setObjectName("pushButtonTTL")
self.horizontalLayout_5.addWidget(self.pushButtonTTL, 0, QtCore.Qt.AlignRight) self.horizontalLayout_5.addWidget(self.pushButtonTTL, 0, QtCore.Qt.AlignRight)
self.horizontalSliderTTL = QtGui.QSlider(self.send) self.horizontalSliderTTL = QtWidgets.QSlider(self.send)
self.horizontalSliderTTL.setMinimumSize(QtCore.QSize(70, 0)) self.horizontalSliderTTL.setMinimumSize(QtCore.QSize(70, 0))
self.horizontalSliderTTL.setOrientation(QtCore.Qt.Horizontal) self.horizontalSliderTTL.setOrientation(QtCore.Qt.Horizontal)
self.horizontalSliderTTL.setInvertedAppearance(False) self.horizontalSliderTTL.setInvertedAppearance(False)
self.horizontalSliderTTL.setInvertedControls(False) self.horizontalSliderTTL.setInvertedControls(False)
self.horizontalSliderTTL.setObjectName(_fromUtf8("horizontalSliderTTL")) self.horizontalSliderTTL.setObjectName("horizontalSliderTTL")
self.horizontalLayout_5.addWidget(self.horizontalSliderTTL, 0, QtCore.Qt.AlignLeft) self.horizontalLayout_5.addWidget(self.horizontalSliderTTL, 0, QtCore.Qt.AlignLeft)
self.labelHumanFriendlyTTLDescription = QtGui.QLabel(self.send) self.labelHumanFriendlyTTLDescription = QtWidgets.QLabel(self.send)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.labelHumanFriendlyTTLDescription.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.labelHumanFriendlyTTLDescription.sizePolicy().hasHeightForWidth())
self.labelHumanFriendlyTTLDescription.setSizePolicy(sizePolicy) self.labelHumanFriendlyTTLDescription.setSizePolicy(sizePolicy)
self.labelHumanFriendlyTTLDescription.setMinimumSize(QtCore.QSize(45, 0)) self.labelHumanFriendlyTTLDescription.setMinimumSize(QtCore.QSize(45, 0))
self.labelHumanFriendlyTTLDescription.setObjectName(_fromUtf8("labelHumanFriendlyTTLDescription")) self.labelHumanFriendlyTTLDescription.setObjectName("labelHumanFriendlyTTLDescription")
self.horizontalLayout_5.addWidget(self.labelHumanFriendlyTTLDescription, 1, QtCore.Qt.AlignLeft) self.horizontalLayout_5.addWidget(self.labelHumanFriendlyTTLDescription, 1, QtCore.Qt.AlignLeft)
self.pushButtonClear = QtGui.QPushButton(self.send) self.pushButtonClear = QtWidgets.QPushButton(self.send)
self.pushButtonClear.setObjectName(_fromUtf8("pushButtonClear")) self.pushButtonClear.setObjectName("pushButtonClear")
self.horizontalLayout_5.addWidget(self.pushButtonClear, 0, QtCore.Qt.AlignRight) self.horizontalLayout_5.addWidget(self.pushButtonClear, 0, QtCore.Qt.AlignRight)
self.pushButtonSend = QtGui.QPushButton(self.send) self.pushButtonSend = QtWidgets.QPushButton(self.send)
self.pushButtonSend.setObjectName(_fromUtf8("pushButtonSend")) self.pushButtonSend.setObjectName("pushButtonSend")
self.horizontalLayout_5.addWidget(self.pushButtonSend, 0, QtCore.Qt.AlignRight) self.horizontalLayout_5.addWidget(self.pushButtonSend, 0, QtCore.Qt.AlignRight)
self.horizontalSliderTTL.setMaximumSize(QtCore.QSize(105, self.pushButtonSend.height())) self.horizontalSliderTTL.setMaximumSize(QtCore.QSize(105, self.pushButtonSend.height()))
self.verticalSplitter.addWidget(self.tTLContainer) self.verticalSplitter.addWidget(self.tTLContainer)
@ -359,29 +338,29 @@ class Ui_MainWindow(object):
self.horizontalSplitter.setCollapsible(1, False) self.horizontalSplitter.setCollapsible(1, False)
self.gridLayout_7.addWidget(self.horizontalSplitter, 0, 0, 1, 1) self.gridLayout_7.addWidget(self.horizontalSplitter, 0, 0, 1, 1)
icon4 = QtGui.QIcon() icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/send.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon4.addPixmap(QtGui.QPixmap(":/newPrefix/images/send.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.tabWidget.addTab(self.send, icon4, _fromUtf8("")) self.tabWidget.addTab(self.send, icon4, "")
self.subscriptions = QtGui.QWidget() self.subscriptions = QtWidgets.QWidget()
self.subscriptions.setObjectName(_fromUtf8("subscriptions")) self.subscriptions.setObjectName("subscriptions")
self.gridLayout_3 = QtGui.QGridLayout(self.subscriptions) self.gridLayout_3 = QtWidgets.QGridLayout(self.subscriptions)
self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3")) self.gridLayout_3.setObjectName("gridLayout_3")
self.horizontalSplitter_4 = settingsmixin.SSplitter() self.horizontalSplitter_4 = settingsmixin.SSplitter()
self.horizontalSplitter_4.setObjectName(_fromUtf8("horizontalSplitter_4")) self.horizontalSplitter_4.setObjectName("horizontalSplitter_4")
self.verticalSplitter_3 = settingsmixin.SSplitter() self.verticalSplitter_3 = settingsmixin.SSplitter()
self.verticalSplitter_3.setObjectName(_fromUtf8("verticalSplitter_3")) self.verticalSplitter_3.setObjectName("verticalSplitter_3")
self.verticalSplitter_3.setOrientation(QtCore.Qt.Vertical) self.verticalSplitter_3.setOrientation(QtCore.Qt.Vertical)
self.treeWidgetSubscriptions = settingsmixin.STreeWidget(self.subscriptions) self.treeWidgetSubscriptions = settingsmixin.STreeWidget(self.subscriptions)
self.treeWidgetSubscriptions.setAlternatingRowColors(True) self.treeWidgetSubscriptions.setAlternatingRowColors(True)
self.treeWidgetSubscriptions.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) self.treeWidgetSubscriptions.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
self.treeWidgetSubscriptions.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.treeWidgetSubscriptions.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.treeWidgetSubscriptions.setObjectName(_fromUtf8("treeWidgetSubscriptions")) self.treeWidgetSubscriptions.setObjectName("treeWidgetSubscriptions")
self.treeWidgetSubscriptions.resize(200, self.treeWidgetSubscriptions.height()) self.treeWidgetSubscriptions.resize(200, self.treeWidgetSubscriptions.height())
icon5 = QtGui.QIcon() icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/subscriptions.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off) icon5.addPixmap(QtGui.QPixmap(":/newPrefix/images/subscriptions.png"), QtGui.QIcon.Selected, QtGui.QIcon.Off)
self.treeWidgetSubscriptions.headerItem().setIcon(0, icon5) self.treeWidgetSubscriptions.headerItem().setIcon(0, icon5)
self.verticalSplitter_3.addWidget(self.treeWidgetSubscriptions) self.verticalSplitter_3.addWidget(self.treeWidgetSubscriptions)
self.pushButtonAddSubscription = QtGui.QPushButton(self.subscriptions) self.pushButtonAddSubscription = QtWidgets.QPushButton(self.subscriptions)
self.pushButtonAddSubscription.setObjectName(_fromUtf8("pushButtonAddSubscription")) self.pushButtonAddSubscription.setObjectName("pushButtonAddSubscription")
self.pushButtonAddSubscription.resize(200, self.pushButtonAddSubscription.height()) self.pushButtonAddSubscription.resize(200, self.pushButtonAddSubscription.height())
self.verticalSplitter_3.addWidget(self.pushButtonAddSubscription) self.verticalSplitter_3.addWidget(self.pushButtonAddSubscription)
self.verticalSplitter_3.setStretchFactor(0, 1) self.verticalSplitter_3.setStretchFactor(0, 1)
@ -391,20 +370,20 @@ class Ui_MainWindow(object):
self.verticalSplitter_3.handle(1).setEnabled(False) self.verticalSplitter_3.handle(1).setEnabled(False)
self.horizontalSplitter_4.addWidget(self.verticalSplitter_3) self.horizontalSplitter_4.addWidget(self.verticalSplitter_3)
self.verticalSplitter_4 = settingsmixin.SSplitter() self.verticalSplitter_4 = settingsmixin.SSplitter()
self.verticalSplitter_4.setObjectName(_fromUtf8("verticalSplitter_4")) self.verticalSplitter_4.setObjectName("verticalSplitter_4")
self.verticalSplitter_4.setOrientation(QtCore.Qt.Vertical) self.verticalSplitter_4.setOrientation(QtCore.Qt.Vertical)
self.horizontalSplitter_2 = QtGui.QSplitter() self.horizontalSplitter_2 = QtWidgets.QSplitter()
self.horizontalSplitter_2.setObjectName(_fromUtf8("horizontalSplitter_2")) self.horizontalSplitter_2.setObjectName("horizontalSplitter_2")
self.inboxSearchLineEditSubscriptions = QtGui.QLineEdit(self.subscriptions) self.inboxSearchLineEditSubscriptions = QtWidgets.QLineEdit(self.subscriptions)
self.inboxSearchLineEditSubscriptions.setObjectName(_fromUtf8("inboxSearchLineEditSubscriptions")) self.inboxSearchLineEditSubscriptions.setObjectName("inboxSearchLineEditSubscriptions")
self.horizontalSplitter_2.addWidget(self.inboxSearchLineEditSubscriptions) self.horizontalSplitter_2.addWidget(self.inboxSearchLineEditSubscriptions)
self.inboxSearchOptionSubscriptions = QtGui.QComboBox(self.subscriptions) self.inboxSearchOptionSubscriptions = QtWidgets.QComboBox(self.subscriptions)
self.inboxSearchOptionSubscriptions.setObjectName(_fromUtf8("inboxSearchOptionSubscriptions")) self.inboxSearchOptionSubscriptions.setObjectName("inboxSearchOptionSubscriptions")
self.inboxSearchOptionSubscriptions.addItem(_fromUtf8("")) self.inboxSearchOptionSubscriptions.addItem("")
self.inboxSearchOptionSubscriptions.addItem(_fromUtf8("")) self.inboxSearchOptionSubscriptions.addItem("")
self.inboxSearchOptionSubscriptions.addItem(_fromUtf8("")) self.inboxSearchOptionSubscriptions.addItem("")
self.inboxSearchOptionSubscriptions.addItem(_fromUtf8("")) self.inboxSearchOptionSubscriptions.addItem("")
self.inboxSearchOptionSubscriptions.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) self.inboxSearchOptionSubscriptions.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)
self.inboxSearchOptionSubscriptions.setCurrentIndex(2) self.inboxSearchOptionSubscriptions.setCurrentIndex(2)
self.horizontalSplitter_2.addWidget(self.inboxSearchOptionSubscriptions) self.horizontalSplitter_2.addWidget(self.inboxSearchOptionSubscriptions)
self.horizontalSplitter_2.handle(1).setEnabled(False) self.horizontalSplitter_2.handle(1).setEnabled(False)
@ -412,21 +391,21 @@ class Ui_MainWindow(object):
self.horizontalSplitter_2.setStretchFactor(1, 0) self.horizontalSplitter_2.setStretchFactor(1, 0)
self.verticalSplitter_4.addWidget(self.horizontalSplitter_2) self.verticalSplitter_4.addWidget(self.horizontalSplitter_2)
self.tableWidgetInboxSubscriptions = settingsmixin.STableWidget(self.subscriptions) self.tableWidgetInboxSubscriptions = settingsmixin.STableWidget(self.subscriptions)
self.tableWidgetInboxSubscriptions.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) self.tableWidgetInboxSubscriptions.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.tableWidgetInboxSubscriptions.setAlternatingRowColors(True) self.tableWidgetInboxSubscriptions.setAlternatingRowColors(True)
self.tableWidgetInboxSubscriptions.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.tableWidgetInboxSubscriptions.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.tableWidgetInboxSubscriptions.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.tableWidgetInboxSubscriptions.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.tableWidgetInboxSubscriptions.setWordWrap(False) self.tableWidgetInboxSubscriptions.setWordWrap(False)
self.tableWidgetInboxSubscriptions.setObjectName(_fromUtf8("tableWidgetInboxSubscriptions")) self.tableWidgetInboxSubscriptions.setObjectName("tableWidgetInboxSubscriptions")
self.tableWidgetInboxSubscriptions.setColumnCount(4) self.tableWidgetInboxSubscriptions.setColumnCount(4)
self.tableWidgetInboxSubscriptions.setRowCount(0) self.tableWidgetInboxSubscriptions.setRowCount(0)
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(0, item) self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(0, item)
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(1, item) self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(1, item)
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(2, item) self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(2, item)
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(3, item) self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(3, item)
self.tableWidgetInboxSubscriptions.horizontalHeader().setCascadingSectionResizes(True) self.tableWidgetInboxSubscriptions.horizontalHeader().setCascadingSectionResizes(True)
self.tableWidgetInboxSubscriptions.horizontalHeader().setDefaultSectionSize(200) self.tableWidgetInboxSubscriptions.horizontalHeader().setDefaultSectionSize(200)
@ -440,7 +419,7 @@ class Ui_MainWindow(object):
self.textEditInboxMessageSubscriptions = MessageView(self.subscriptions) self.textEditInboxMessageSubscriptions = MessageView(self.subscriptions)
self.textEditInboxMessageSubscriptions.setBaseSize(QtCore.QSize(0, 500)) self.textEditInboxMessageSubscriptions.setBaseSize(QtCore.QSize(0, 500))
self.textEditInboxMessageSubscriptions.setReadOnly(True) self.textEditInboxMessageSubscriptions.setReadOnly(True)
self.textEditInboxMessageSubscriptions.setObjectName(_fromUtf8("textEditInboxMessageSubscriptions")) self.textEditInboxMessageSubscriptions.setObjectName("textEditInboxMessageSubscriptions")
self.verticalSplitter_4.addWidget(self.textEditInboxMessageSubscriptions) self.verticalSplitter_4.addWidget(self.textEditInboxMessageSubscriptions)
self.verticalSplitter_4.setStretchFactor(0, 0) self.verticalSplitter_4.setStretchFactor(0, 0)
self.verticalSplitter_4.setStretchFactor(1, 1) self.verticalSplitter_4.setStretchFactor(1, 1)
@ -456,31 +435,31 @@ class Ui_MainWindow(object):
self.horizontalSplitter_4.setCollapsible(1, False) self.horizontalSplitter_4.setCollapsible(1, False)
self.gridLayout_3.addWidget(self.horizontalSplitter_4, 0, 0, 1, 1) self.gridLayout_3.addWidget(self.horizontalSplitter_4, 0, 0, 1, 1)
icon6 = QtGui.QIcon() icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/subscriptions.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon6.addPixmap(QtGui.QPixmap(":/newPrefix/images/subscriptions.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.tabWidget.addTab(self.subscriptions, icon6, _fromUtf8("")) self.tabWidget.addTab(self.subscriptions, icon6, "")
self.chans = QtGui.QWidget() self.chans = QtWidgets.QWidget()
self.chans.setObjectName(_fromUtf8("chans")) self.chans.setObjectName("chans")
self.gridLayout_4 = QtGui.QGridLayout(self.chans) self.gridLayout_4 = QtWidgets.QGridLayout(self.chans)
self.gridLayout_4.setObjectName(_fromUtf8("gridLayout_4")) self.gridLayout_4.setObjectName("gridLayout_4")
self.horizontalSplitter_7 = settingsmixin.SSplitter() self.horizontalSplitter_7 = settingsmixin.SSplitter()
self.horizontalSplitter_7.setObjectName(_fromUtf8("horizontalSplitter_7")) self.horizontalSplitter_7.setObjectName("horizontalSplitter_7")
self.verticalSplitter_17 = settingsmixin.SSplitter() self.verticalSplitter_17 = settingsmixin.SSplitter()
self.verticalSplitter_17.setObjectName(_fromUtf8("verticalSplitter_17")) self.verticalSplitter_17.setObjectName("verticalSplitter_17")
self.verticalSplitter_17.setOrientation(QtCore.Qt.Vertical) self.verticalSplitter_17.setOrientation(QtCore.Qt.Vertical)
self.treeWidgetChans = settingsmixin.STreeWidget(self.chans) self.treeWidgetChans = settingsmixin.STreeWidget(self.chans)
self.treeWidgetChans.setFrameShadow(QtGui.QFrame.Sunken) self.treeWidgetChans.setFrameShadow(QtWidgets.QFrame.Sunken)
self.treeWidgetChans.setLineWidth(1) self.treeWidgetChans.setLineWidth(1)
self.treeWidgetChans.setAlternatingRowColors(True) self.treeWidgetChans.setAlternatingRowColors(True)
self.treeWidgetChans.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) self.treeWidgetChans.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
self.treeWidgetChans.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.treeWidgetChans.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.treeWidgetChans.setObjectName(_fromUtf8("treeWidgetChans")) self.treeWidgetChans.setObjectName("treeWidgetChans")
self.treeWidgetChans.resize(200, self.treeWidgetChans.height()) self.treeWidgetChans.resize(200, self.treeWidgetChans.height())
icon7 = QtGui.QIcon() icon7 = QtGui.QIcon()
icon7.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/can-icon-16px.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off) icon7.addPixmap(QtGui.QPixmap(":/newPrefix/images/can-icon-16px.png"), QtGui.QIcon.Selected, QtGui.QIcon.Off)
self.treeWidgetChans.headerItem().setIcon(0, icon7) self.treeWidgetChans.headerItem().setIcon(0, icon7)
self.verticalSplitter_17.addWidget(self.treeWidgetChans) self.verticalSplitter_17.addWidget(self.treeWidgetChans)
self.pushButtonAddChan = QtGui.QPushButton(self.chans) self.pushButtonAddChan = QtWidgets.QPushButton(self.chans)
self.pushButtonAddChan.setObjectName(_fromUtf8("pushButtonAddChan")) self.pushButtonAddChan.setObjectName("pushButtonAddChan")
self.pushButtonAddChan.resize(200, self.pushButtonAddChan.height()) self.pushButtonAddChan.resize(200, self.pushButtonAddChan.height())
self.verticalSplitter_17.addWidget(self.pushButtonAddChan) self.verticalSplitter_17.addWidget(self.pushButtonAddChan)
self.verticalSplitter_17.setStretchFactor(0, 1) self.verticalSplitter_17.setStretchFactor(0, 1)
@ -490,21 +469,21 @@ class Ui_MainWindow(object):
self.verticalSplitter_17.handle(1).setEnabled(False) self.verticalSplitter_17.handle(1).setEnabled(False)
self.horizontalSplitter_7.addWidget(self.verticalSplitter_17) self.horizontalSplitter_7.addWidget(self.verticalSplitter_17)
self.verticalSplitter_8 = settingsmixin.SSplitter() self.verticalSplitter_8 = settingsmixin.SSplitter()
self.verticalSplitter_8.setObjectName(_fromUtf8("verticalSplitter_8")) self.verticalSplitter_8.setObjectName("verticalSplitter_8")
self.verticalSplitter_8.setOrientation(QtCore.Qt.Vertical) self.verticalSplitter_8.setOrientation(QtCore.Qt.Vertical)
self.horizontalSplitter_6 = QtGui.QSplitter() self.horizontalSplitter_6 = QtWidgets.QSplitter()
self.horizontalSplitter_6.setObjectName(_fromUtf8("horizontalSplitter_6")) self.horizontalSplitter_6.setObjectName("horizontalSplitter_6")
self.inboxSearchLineEditChans = QtGui.QLineEdit(self.chans) self.inboxSearchLineEditChans = QtWidgets.QLineEdit(self.chans)
self.inboxSearchLineEditChans.setObjectName(_fromUtf8("inboxSearchLineEditChans")) self.inboxSearchLineEditChans.setObjectName("inboxSearchLineEditChans")
self.horizontalSplitter_6.addWidget(self.inboxSearchLineEditChans) self.horizontalSplitter_6.addWidget(self.inboxSearchLineEditChans)
self.inboxSearchOptionChans = QtGui.QComboBox(self.chans) self.inboxSearchOptionChans = QtWidgets.QComboBox(self.chans)
self.inboxSearchOptionChans.setObjectName(_fromUtf8("inboxSearchOptionChans")) self.inboxSearchOptionChans.setObjectName("inboxSearchOptionChans")
self.inboxSearchOptionChans.addItem(_fromUtf8("")) self.inboxSearchOptionChans.addItem("")
self.inboxSearchOptionChans.addItem(_fromUtf8("")) self.inboxSearchOptionChans.addItem("")
self.inboxSearchOptionChans.addItem(_fromUtf8("")) self.inboxSearchOptionChans.addItem("")
self.inboxSearchOptionChans.addItem(_fromUtf8("")) self.inboxSearchOptionChans.addItem("")
self.inboxSearchOptionChans.addItem(_fromUtf8("")) self.inboxSearchOptionChans.addItem("")
self.inboxSearchOptionChans.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) self.inboxSearchOptionChans.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)
self.inboxSearchOptionChans.setCurrentIndex(3) self.inboxSearchOptionChans.setCurrentIndex(3)
self.horizontalSplitter_6.addWidget(self.inboxSearchOptionChans) self.horizontalSplitter_6.addWidget(self.inboxSearchOptionChans)
self.horizontalSplitter_6.handle(1).setEnabled(False) self.horizontalSplitter_6.handle(1).setEnabled(False)
@ -512,21 +491,21 @@ class Ui_MainWindow(object):
self.horizontalSplitter_6.setStretchFactor(1, 0) self.horizontalSplitter_6.setStretchFactor(1, 0)
self.verticalSplitter_8.addWidget(self.horizontalSplitter_6) self.verticalSplitter_8.addWidget(self.horizontalSplitter_6)
self.tableWidgetInboxChans = settingsmixin.STableWidget(self.chans) self.tableWidgetInboxChans = settingsmixin.STableWidget(self.chans)
self.tableWidgetInboxChans.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) self.tableWidgetInboxChans.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.tableWidgetInboxChans.setAlternatingRowColors(True) self.tableWidgetInboxChans.setAlternatingRowColors(True)
self.tableWidgetInboxChans.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.tableWidgetInboxChans.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.tableWidgetInboxChans.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.tableWidgetInboxChans.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.tableWidgetInboxChans.setWordWrap(False) self.tableWidgetInboxChans.setWordWrap(False)
self.tableWidgetInboxChans.setObjectName(_fromUtf8("tableWidgetInboxChans")) self.tableWidgetInboxChans.setObjectName("tableWidgetInboxChans")
self.tableWidgetInboxChans.setColumnCount(4) self.tableWidgetInboxChans.setColumnCount(4)
self.tableWidgetInboxChans.setRowCount(0) self.tableWidgetInboxChans.setRowCount(0)
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidgetInboxChans.setHorizontalHeaderItem(0, item) self.tableWidgetInboxChans.setHorizontalHeaderItem(0, item)
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidgetInboxChans.setHorizontalHeaderItem(1, item) self.tableWidgetInboxChans.setHorizontalHeaderItem(1, item)
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidgetInboxChans.setHorizontalHeaderItem(2, item) self.tableWidgetInboxChans.setHorizontalHeaderItem(2, item)
item = QtGui.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidgetInboxChans.setHorizontalHeaderItem(3, item) self.tableWidgetInboxChans.setHorizontalHeaderItem(3, item)
self.tableWidgetInboxChans.horizontalHeader().setCascadingSectionResizes(True) self.tableWidgetInboxChans.horizontalHeader().setCascadingSectionResizes(True)
self.tableWidgetInboxChans.horizontalHeader().setDefaultSectionSize(200) self.tableWidgetInboxChans.horizontalHeader().setDefaultSectionSize(200)
@ -540,7 +519,7 @@ class Ui_MainWindow(object):
self.textEditInboxMessageChans = MessageView(self.chans) self.textEditInboxMessageChans = MessageView(self.chans)
self.textEditInboxMessageChans.setBaseSize(QtCore.QSize(0, 500)) self.textEditInboxMessageChans.setBaseSize(QtCore.QSize(0, 500))
self.textEditInboxMessageChans.setReadOnly(True) self.textEditInboxMessageChans.setReadOnly(True)
self.textEditInboxMessageChans.setObjectName(_fromUtf8("textEditInboxMessageChans")) self.textEditInboxMessageChans.setObjectName("textEditInboxMessageChans")
self.verticalSplitter_8.addWidget(self.textEditInboxMessageChans) self.verticalSplitter_8.addWidget(self.textEditInboxMessageChans)
self.verticalSplitter_8.setStretchFactor(0, 0) self.verticalSplitter_8.setStretchFactor(0, 0)
self.verticalSplitter_8.setStretchFactor(1, 1) self.verticalSplitter_8.setStretchFactor(1, 1)
@ -556,8 +535,8 @@ class Ui_MainWindow(object):
self.horizontalSplitter_7.setCollapsible(1, False) self.horizontalSplitter_7.setCollapsible(1, False)
self.gridLayout_4.addWidget(self.horizontalSplitter_7, 0, 0, 1, 1) self.gridLayout_4.addWidget(self.horizontalSplitter_7, 0, 0, 1, 1)
icon8 = QtGui.QIcon() icon8 = QtGui.QIcon()
icon8.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/can-icon-16px.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon8.addPixmap(QtGui.QPixmap(":/newPrefix/images/can-icon-16px.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.tabWidget.addTab(self.chans, icon8, _fromUtf8("")) self.tabWidget.addTab(self.chans, icon8, "")
self.blackwhitelist = Blacklist() self.blackwhitelist = Blacklist()
self.tabWidget.addTab(self.blackwhitelist, QtGui.QIcon(":/newPrefix/images/blacklist.png"), "") self.tabWidget.addTab(self.blackwhitelist, QtGui.QIcon(":/newPrefix/images/blacklist.png"), "")
# Initialize the Blacklist or Whitelist # Initialize the Blacklist or Whitelist
@ -569,62 +548,62 @@ class Ui_MainWindow(object):
self.tabWidget.addTab(self.networkstatus, QtGui.QIcon(":/newPrefix/images/networkstatus.png"), "") self.tabWidget.addTab(self.networkstatus, QtGui.QIcon(":/newPrefix/images/networkstatus.png"), "")
self.gridLayout_10.addWidget(self.tabWidget, 0, 0, 1, 1) self.gridLayout_10.addWidget(self.tabWidget, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget) MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow) self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 885, 27)) self.menubar.setGeometry(QtCore.QRect(0, 0, 885, 27))
self.menubar.setObjectName(_fromUtf8("menubar")) self.menubar.setObjectName("menubar")
self.menuFile = QtGui.QMenu(self.menubar) self.menuFile = QtWidgets.QMenu(self.menubar)
self.menuFile.setObjectName(_fromUtf8("menuFile")) self.menuFile.setObjectName("menuFile")
self.menuSettings = QtGui.QMenu(self.menubar) self.menuSettings = QtWidgets.QMenu(self.menubar)
self.menuSettings.setObjectName(_fromUtf8("menuSettings")) self.menuSettings.setObjectName("menuSettings")
self.menuHelp = QtGui.QMenu(self.menubar) self.menuHelp = QtWidgets.QMenu(self.menubar)
self.menuHelp.setObjectName(_fromUtf8("menuHelp")) self.menuHelp.setObjectName("menuHelp")
MainWindow.setMenuBar(self.menubar) MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow) self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setMaximumSize(QtCore.QSize(16777215, 22)) self.statusbar.setMaximumSize(QtCore.QSize(16777215, 22))
self.statusbar.setObjectName(_fromUtf8("statusbar")) self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar) MainWindow.setStatusBar(self.statusbar)
self.actionImport_keys = QtGui.QAction(MainWindow) self.actionImport_keys = QtWidgets.QAction(MainWindow)
self.actionImport_keys.setObjectName(_fromUtf8("actionImport_keys")) self.actionImport_keys.setObjectName("actionImport_keys")
self.actionManageKeys = QtGui.QAction(MainWindow) self.actionManageKeys = QtWidgets.QAction(MainWindow)
self.actionManageKeys.setCheckable(False) self.actionManageKeys.setCheckable(False)
self.actionManageKeys.setEnabled(True) self.actionManageKeys.setEnabled(True)
icon = QtGui.QIcon.fromTheme(_fromUtf8("dialog-password")) icon = QtGui.QIcon.fromTheme("dialog-password")
self.actionManageKeys.setIcon(icon) self.actionManageKeys.setIcon(icon)
self.actionManageKeys.setObjectName(_fromUtf8("actionManageKeys")) self.actionManageKeys.setObjectName("actionManageKeys")
self.actionNetworkSwitch = QtGui.QAction(MainWindow) self.actionNetworkSwitch = QtWidgets.QAction(MainWindow)
self.actionNetworkSwitch.setObjectName(_fromUtf8("actionNetworkSwitch")) self.actionNetworkSwitch.setObjectName("actionNetworkSwitch")
self.actionExit = QtGui.QAction(MainWindow) self.actionExit = QtWidgets.QAction(MainWindow)
icon = QtGui.QIcon.fromTheme(_fromUtf8("application-exit")) icon = QtGui.QIcon.fromTheme("application-exit")
self.actionExit.setIcon(icon) self.actionExit.setIcon(icon)
self.actionExit.setObjectName(_fromUtf8("actionExit")) self.actionExit.setObjectName("actionExit")
self.actionHelp = QtGui.QAction(MainWindow) self.actionHelp = QtWidgets.QAction(MainWindow)
icon = QtGui.QIcon.fromTheme(_fromUtf8("help-contents")) icon = QtGui.QIcon.fromTheme("help-contents")
self.actionHelp.setIcon(icon) self.actionHelp.setIcon(icon)
self.actionHelp.setObjectName(_fromUtf8("actionHelp")) self.actionHelp.setObjectName("actionHelp")
self.actionSupport = QtGui.QAction(MainWindow) self.actionSupport = QtWidgets.QAction(MainWindow)
icon = QtGui.QIcon.fromTheme(_fromUtf8("help-support")) icon = QtGui.QIcon.fromTheme("help-support")
self.actionSupport.setIcon(icon) self.actionSupport.setIcon(icon)
self.actionSupport.setObjectName(_fromUtf8("actionSupport")) self.actionSupport.setObjectName("actionSupport")
self.actionAbout = QtGui.QAction(MainWindow) self.actionAbout = QtWidgets.QAction(MainWindow)
icon = QtGui.QIcon.fromTheme(_fromUtf8("help-about")) icon = QtGui.QIcon.fromTheme("help-about")
self.actionAbout.setIcon(icon) self.actionAbout.setIcon(icon)
self.actionAbout.setObjectName(_fromUtf8("actionAbout")) self.actionAbout.setObjectName("actionAbout")
self.actionSettings = QtGui.QAction(MainWindow) self.actionSettings = QtWidgets.QAction(MainWindow)
icon = QtGui.QIcon.fromTheme(_fromUtf8("document-properties")) icon = QtGui.QIcon.fromTheme("document-properties")
self.actionSettings.setIcon(icon) self.actionSettings.setIcon(icon)
self.actionSettings.setObjectName(_fromUtf8("actionSettings")) self.actionSettings.setObjectName("actionSettings")
self.actionRegenerateDeterministicAddresses = QtGui.QAction(MainWindow) self.actionRegenerateDeterministicAddresses = QtWidgets.QAction(MainWindow)
icon = QtGui.QIcon.fromTheme(_fromUtf8("view-refresh")) icon = QtGui.QIcon.fromTheme("view-refresh")
self.actionRegenerateDeterministicAddresses.setIcon(icon) self.actionRegenerateDeterministicAddresses.setIcon(icon)
self.actionRegenerateDeterministicAddresses.setObjectName(_fromUtf8("actionRegenerateDeterministicAddresses")) self.actionRegenerateDeterministicAddresses.setObjectName("actionRegenerateDeterministicAddresses")
self.actionDeleteAllTrashedMessages = QtGui.QAction(MainWindow) self.actionDeleteAllTrashedMessages = QtWidgets.QAction(MainWindow)
icon = QtGui.QIcon.fromTheme(_fromUtf8("user-trash")) icon = QtGui.QIcon.fromTheme("user-trash")
self.actionDeleteAllTrashedMessages.setIcon(icon) self.actionDeleteAllTrashedMessages.setIcon(icon)
self.actionDeleteAllTrashedMessages.setObjectName(_fromUtf8("actionDeleteAllTrashedMessages")) self.actionDeleteAllTrashedMessages.setObjectName("actionDeleteAllTrashedMessages")
self.actionJoinChan = QtGui.QAction(MainWindow) self.actionJoinChan = QtWidgets.QAction(MainWindow)
icon = QtGui.QIcon.fromTheme(_fromUtf8("contact-new")) icon = QtGui.QIcon.fromTheme("contact-new")
self.actionJoinChan.setIcon(icon) self.actionJoinChan.setIcon(icon)
self.actionJoinChan.setObjectName(_fromUtf8("actionJoinChan")) self.actionJoinChan.setObjectName("actionJoinChan")
self.menuFile.addAction(self.actionManageKeys) self.menuFile.addAction(self.actionManageKeys)
self.menuFile.addAction(self.actionDeleteAllTrashedMessages) self.menuFile.addAction(self.actionDeleteAllTrashedMessages)
self.menuFile.addAction(self.actionRegenerateDeterministicAddresses) self.menuFile.addAction(self.actionRegenerateDeterministicAddresses)
@ -655,11 +634,11 @@ class Ui_MainWindow(object):
# Popup menu actions container for the Sent page # Popup menu actions container for the Sent page
# pylint: disable=attribute-defined-outside-init # pylint: disable=attribute-defined-outside-init
self.sentContextMenuToolbar = QtGui.QToolBar() self.sentContextMenuToolbar = QtWidgets.QToolBar()
# Popup menu actions container for chans tree # Popup menu actions container for chans tree
self.addressContextMenuToolbar = QtGui.QToolBar() self.addressContextMenuToolbar = QtWidgets.QToolBar()
# Popup menu actions container for subscriptions tree # Popup menu actions container for subscriptions tree
self.subscriptionsContextMenuToolbar = QtGui.QToolBar() self.subscriptionsContextMenuToolbar = QtWidgets.QToolBar()
def updateNetworkSwitchMenuLabel(self, dontconnect=None): def updateNetworkSwitchMenuLabel(self, dontconnect=None):
if dontconnect is None: if dontconnect is None:
@ -713,7 +692,7 @@ class Ui_MainWindow(object):
hours = int(BMConfigParser().getint('bitmessagesettings', 'ttl')/60/60) hours = int(BMConfigParser().getint('bitmessagesettings', 'ttl')/60/60)
except: except:
pass pass
self.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%n hour(s)", None, QtCore.QCoreApplication.CodecForTr, hours)) self.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%n hour(s)", None, hours))
self.pushButtonClear.setText(_translate("MainWindow", "Clear", None)) self.pushButtonClear.setText(_translate("MainWindow", "Clear", None))
self.pushButtonSend.setText(_translate("MainWindow", "Send", None)) self.pushButtonSend.setText(_translate("MainWindow", "Send", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.send), _translate("MainWindow", "Send", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.send), _translate("MainWindow", "Send", None))
@ -774,15 +753,12 @@ class Ui_MainWindow(object):
self.updateNetworkSwitchMenuLabel() self.updateNetworkSwitchMenuLabel()
import bitmessage_icons_rc
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
app = QtGui.QApplication(sys.argv) app = QtWidgets.QApplication(sys.argv)
MainWindow = settingsmixin.SMainWindow() MainWindow = settingsmixin.SMainWindow()
ui = Ui_MainWindow() ui = Ui_MainWindow()
ui.setupUi(MainWindow) ui.setupUi(MainWindow)
MainWindow.show() MainWindow.show()
sys.exit(app.exec_()) sys.exit(app.exec_())

View File

@ -1,4 +1,4 @@
from PyQt4 import QtCore, QtGui from qtpy import QtCore, QtGui, QtWidgets
import widgets import widgets
from addresses import addBMIfNotPresent from addresses import addBMIfNotPresent
@ -12,31 +12,31 @@ from uisignaler import UISignaler
from utils import avatarize from utils import avatarize
class Blacklist(QtGui.QWidget, RetranslateMixin): class Blacklist(QtWidgets.QWidget, RetranslateMixin):
def __init__(self, parent=None): def __init__(self, parent=None):
super(Blacklist, self).__init__(parent) super(Blacklist, self).__init__(parent)
widgets.load('blacklist.ui', self) widgets.load('blacklist.ui', self)
QtCore.QObject.connect(self.radioButtonBlacklist, QtCore.SIGNAL( self.radioButtonBlacklist.clicked.connect(
"clicked()"), self.click_radioButtonBlacklist) self.click_radioButtonBlacklist)
QtCore.QObject.connect(self.radioButtonWhitelist, QtCore.SIGNAL( self.radioButtonWhitelist.clicked.connect(
"clicked()"), self.click_radioButtonWhitelist) self.click_radioButtonWhitelist)
QtCore.QObject.connect(self.pushButtonAddBlacklist, QtCore.SIGNAL( self.pushButtonAddBlacklist.clicked.connect(
"clicked()"), self.click_pushButtonAddBlacklist) self.click_pushButtonAddBlacklist)
self.init_blacklist_popup_menu() self.init_blacklist_popup_menu()
# Initialize blacklist self.tableWidgetBlacklist.itemChanged.connect(
QtCore.QObject.connect(self.tableWidgetBlacklist, QtCore.SIGNAL( self.tableWidgetBlacklistItemChanged)
"itemChanged(QTableWidgetItem *)"), self.tableWidgetBlacklistItemChanged)
# Set the icon sizes for the identicons # Set the icon sizes for the identicons
identicon_size = 3*7 identicon_size = 3 * 7
self.tableWidgetBlacklist.setIconSize(QtCore.QSize(identicon_size, identicon_size)) self.tableWidgetBlacklist.setIconSize(
QtCore.QSize(identicon_size, identicon_size))
self.UISignalThread = UISignaler.get() self.UISignalThread = UISignaler.get()
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.UISignalThread.rerenderBlackWhiteList.connect(
"rerenderBlackWhiteList()"), self.rerenderBlackWhiteList) self.rerenderBlackWhiteList)
def click_radioButtonBlacklist(self): def click_radioButtonBlacklist(self):
if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'white': if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'white':
@ -69,20 +69,20 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
sql = '''select * from blacklist where address=?''' sql = '''select * from blacklist where address=?'''
else: else:
sql = '''select * from whitelist where address=?''' sql = '''select * from whitelist where address=?'''
queryreturn = sqlQuery(sql,*t) queryreturn = sqlQuery(sql, *t)
if queryreturn == []: if queryreturn == []:
self.tableWidgetBlacklist.setSortingEnabled(False) self.tableWidgetBlacklist.setSortingEnabled(False)
self.tableWidgetBlacklist.insertRow(0) self.tableWidgetBlacklist.insertRow(0)
newItem = QtGui.QTableWidgetItem(unicode( newItem = QtGui.QTableWidgetItem(
self.NewBlacklistDialogInstance.lineEditLabel.text().toUtf8(), 'utf-8')) self.NewBlacklistDialogInstance.lineEditLabel.text())
newItem.setIcon(avatarize(address)) newItem.setIcon(avatarize(address))
self.tableWidgetBlacklist.setItem(0, 0, newItem) self.tableWidgetBlacklist.setItem(0, 0, newItem)
newItem = QtGui.QTableWidgetItem(address) newItem = QtWidgets.QTableWidgetItem(address)
newItem.setFlags( newItem.setFlags(
QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.tableWidgetBlacklist.setItem(0, 1, newItem) self.tableWidgetBlacklist.setItem(0, 1, newItem)
self.tableWidgetBlacklist.setSortingEnabled(True) self.tableWidgetBlacklist.setSortingEnabled(True)
t = (str(self.NewBlacklistDialogInstance.lineEditLabel.text().toUtf8()), address, True) t = (self.NewBlacklistDialogInstance.lineEditLabel.text(), address, True)
if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black': if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black':
sql = '''INSERT INTO blacklist VALUES (?,?,?)''' sql = '''INSERT INTO blacklist VALUES (?,?,?)'''
else: else:
@ -108,17 +108,17 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
def tableWidgetBlacklistItemChanged(self, item): def tableWidgetBlacklistItemChanged(self, item):
if item.column() == 0: if item.column() == 0:
addressitem = self.tableWidgetBlacklist.item(item.row(), 1) addressitem = self.tableWidgetBlacklist.item(item.row(), 1)
if isinstance(addressitem, QtGui.QTableWidgetItem): if isinstance(addressitem, QtWidgets.QTableWidgetItem):
if self.radioButtonBlacklist.isChecked(): if self.radioButtonBlacklist.isChecked():
sqlExecute('''UPDATE blacklist SET label=? WHERE address=?''', sqlExecute('''UPDATE blacklist SET label=? WHERE address=?''',
str(item.text()), str(addressitem.text())) item.text(), str(addressitem.text()))
else: else:
sqlExecute('''UPDATE whitelist SET label=? WHERE address=?''', sqlExecute('''UPDATE whitelist SET label=? WHERE address=?''',
str(item.text()), str(addressitem.text())) item.text(), str(addressitem.text()))
def init_blacklist_popup_menu(self, connectSignal=True): def init_blacklist_popup_menu(self, connectSignal=True):
# Popup menu for the Blacklist page # Popup menu for the Blacklist page
self.blacklistContextMenuToolbar = QtGui.QToolBar() self.blacklistContextMenuToolbar = QtWidgets.QToolBar()
# Actions # Actions
self.actionBlacklistNew = self.blacklistContextMenuToolbar.addAction( self.actionBlacklistNew = self.blacklistContextMenuToolbar.addAction(
_translate( _translate(
@ -143,10 +143,9 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
self.tableWidgetBlacklist.setContextMenuPolicy( self.tableWidgetBlacklist.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu) QtCore.Qt.CustomContextMenu)
if connectSignal: if connectSignal:
self.connect(self.tableWidgetBlacklist, QtCore.SIGNAL( self.tableWidgetBlacklist.customContextMenuRequested.connect(
'customContextMenuRequested(const QPoint&)'), self.on_context_menuBlacklist)
self.on_context_menuBlacklist) self.popMenuBlacklist = QtWidgets.QMenu(self)
self.popMenuBlacklist = QtGui.QMenu(self)
# self.popMenuBlacklist.addAction( self.actionBlacklistNew ) # self.popMenuBlacklist.addAction( self.actionBlacklistNew )
self.popMenuBlacklist.addAction(self.actionBlacklistDelete) self.popMenuBlacklist.addAction(self.actionBlacklistDelete)
self.popMenuBlacklist.addSeparator() self.popMenuBlacklist.addSeparator()
@ -172,16 +171,16 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
for row in queryreturn: for row in queryreturn:
label, address, enabled = row label, address, enabled = row
self.tableWidgetBlacklist.insertRow(0) self.tableWidgetBlacklist.insertRow(0)
newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8')) newItem = QtWidgets.QTableWidgetItem(label)
if not enabled: if not enabled:
newItem.setTextColor(QtGui.QColor(128, 128, 128)) newItem.setForeground(QtGui.QColor(128, 128, 128))
newItem.setIcon(avatarize(address)) newItem.setIcon(avatarize(address))
self.tableWidgetBlacklist.setItem(0, 0, newItem) self.tableWidgetBlacklist.setItem(0, 0, newItem)
newItem = QtGui.QTableWidgetItem(address) newItem = QtWidgets.QTableWidgetItem(address)
newItem.setFlags( newItem.setFlags(
QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
if not enabled: if not enabled:
newItem.setTextColor(QtGui.QColor(128, 128, 128)) newItem.setForeground(QtGui.QColor(128, 128, 128))
self.tableWidgetBlacklist.setItem(0, 1, newItem) self.tableWidgetBlacklist.setItem(0, 1, newItem)
self.tableWidgetBlacklist.setSortingEnabled(True) self.tableWidgetBlacklist.setSortingEnabled(True)
@ -192,7 +191,7 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
def on_action_BlacklistDelete(self): def on_action_BlacklistDelete(self):
currentRow = self.tableWidgetBlacklist.currentRow() currentRow = self.tableWidgetBlacklist.currentRow()
labelAtCurrentRow = self.tableWidgetBlacklist.item( labelAtCurrentRow = self.tableWidgetBlacklist.item(
currentRow, 0).text().toUtf8() currentRow, 0).text()
addressAtCurrentRow = self.tableWidgetBlacklist.item( addressAtCurrentRow = self.tableWidgetBlacklist.item(
currentRow, 1).text() currentRow, 1).text()
if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black': if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black':
@ -209,7 +208,7 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
currentRow = self.tableWidgetBlacklist.currentRow() currentRow = self.tableWidgetBlacklist.currentRow()
addressAtCurrentRow = self.tableWidgetBlacklist.item( addressAtCurrentRow = self.tableWidgetBlacklist.item(
currentRow, 1).text() currentRow, 1).text()
clipboard = QtGui.QApplication.clipboard() clipboard = QtWidgets.QApplication.clipboard()
clipboard.setText(str(addressAtCurrentRow)) clipboard.setText(str(addressAtCurrentRow))
def on_context_menuBlacklist(self, point): def on_context_menuBlacklist(self, point):
@ -220,11 +219,12 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
currentRow = self.tableWidgetBlacklist.currentRow() currentRow = self.tableWidgetBlacklist.currentRow()
addressAtCurrentRow = self.tableWidgetBlacklist.item( addressAtCurrentRow = self.tableWidgetBlacklist.item(
currentRow, 1).text() currentRow, 1).text()
self.tableWidgetBlacklist.item( self.tableWidgetBlacklist.item(currentRow, 0).setForeground(
currentRow, 0).setTextColor(QtGui.QApplication.palette().text().color()) QtWidgets.QApplication.palette().text().color())
self.tableWidgetBlacklist.item( self.tableWidgetBlacklist.item(currentRow, 1).setForeground(
currentRow, 1).setTextColor(QtGui.QApplication.palette().text().color()) QtWidgets.QApplication.palette().text().color())
if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black': if BMConfigParser().get(
'bitmessagesettings', 'blackwhitelist') == 'black':
sqlExecute( sqlExecute(
'''UPDATE blacklist SET enabled=1 WHERE address=?''', '''UPDATE blacklist SET enabled=1 WHERE address=?''',
str(addressAtCurrentRow)) str(addressAtCurrentRow))
@ -237,11 +237,12 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
currentRow = self.tableWidgetBlacklist.currentRow() currentRow = self.tableWidgetBlacklist.currentRow()
addressAtCurrentRow = self.tableWidgetBlacklist.item( addressAtCurrentRow = self.tableWidgetBlacklist.item(
currentRow, 1).text() currentRow, 1).text()
self.tableWidgetBlacklist.item( self.tableWidgetBlacklist.item(currentRow, 0).setForeground(
currentRow, 0).setTextColor(QtGui.QColor(128, 128, 128)) QtGui.QColor(128, 128, 128))
self.tableWidgetBlacklist.item( self.tableWidgetBlacklist.item(currentRow, 1).setForeground(
currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128)) QtGui.QColor(128, 128, 128))
if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black': if BMConfigParser().get(
'bitmessagesettings', 'blackwhitelist') == 'black':
sqlExecute( sqlExecute(
'''UPDATE blacklist SET enabled=0 WHERE address=?''', str(addressAtCurrentRow)) '''UPDATE blacklist SET enabled=0 WHERE address=?''', str(addressAtCurrentRow))
else: else:

View File

@ -62,6 +62,9 @@
<property name="sortingEnabled"> <property name="sortingEnabled">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="wordWrap">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes"> <attribute name="horizontalHeaderCascadingSectionResizes">
<bool>true</bool> <bool>true</bool>
</attribute> </attribute>
@ -98,11 +101,8 @@
<customwidget> <customwidget>
<class>STableWidget</class> <class>STableWidget</class>
<extends>QTableWidget</extends> <extends>QTableWidget</extends>
<header>bitmessageqt/settingsmixin.h</header> <header>bitmessageqt.settingsmixin</header>
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources>
<include location="bitmessage_icons.qrc"/>
</resources>
<connections/> <connections/>
</ui> </ui>

View File

@ -1,8 +1,9 @@
""" """
Custom dialog classes All dialogs are available in this module.
""" """
# pylint: disable=too-few-public-methods # pylint: disable=too-few-public-methods
from PyQt4 import QtGui
from qtpy import QtWidgets
import paths import paths
import widgets import widgets
@ -16,7 +17,6 @@ from settings import SettingsDialog
from tr import _translate from tr import _translate
from version import softwareVersion from version import softwareVersion
__all__ = [ __all__ = [
"NewChanDialog", "AddAddressDialog", "NewAddressDialog", "NewChanDialog", "AddAddressDialog", "NewAddressDialog",
"NewSubscriptionDialog", "RegenerateAddressesDialog", "NewSubscriptionDialog", "RegenerateAddressesDialog",
@ -25,8 +25,8 @@ __all__ = [
] ]
class AboutDialog(QtGui.QDialog): class AboutDialog(QtWidgets.QDialog):
"""The `About` dialog""" """The "About" dialog"""
def __init__(self, parent=None): def __init__(self, parent=None):
super(AboutDialog, self).__init__(parent) super(AboutDialog, self).__init__(parent)
widgets.load('about.ui', self) widgets.load('about.ui', self)
@ -50,11 +50,11 @@ class AboutDialog(QtGui.QDialog):
except AttributeError: except AttributeError:
pass pass
self.setFixedSize(QtGui.QWidget.sizeHint(self)) self.setFixedSize(QtWidgets.QWidget.sizeHint(self))
class IconGlossaryDialog(QtGui.QDialog): class IconGlossaryDialog(QtWidgets.QDialog):
"""The `Icon Glossary` dialog, explaining the status icon colors""" """The "Icon Glossary" dialog, explaining the status icon colors"""
def __init__(self, parent=None, config=None): def __init__(self, parent=None, config=None):
super(IconGlossaryDialog, self).__init__(parent) super(IconGlossaryDialog, self).__init__(parent)
widgets.load('iconglossary.ui', self) widgets.load('iconglossary.ui', self)
@ -64,22 +64,23 @@ class IconGlossaryDialog(QtGui.QDialog):
self.labelPortNumber.setText(_translate( self.labelPortNumber.setText(_translate(
"iconGlossaryDialog", "iconGlossaryDialog",
"You are using TCP port %1. (This can be changed in the settings)." "You are using TCP port {0}."
).arg(config.getint('bitmessagesettings', 'port'))) " (This can be changed in the settings)."
self.setFixedSize(QtGui.QWidget.sizeHint(self)) ).format(config.getint('bitmessagesettings', 'port')))
self.setFixedSize(QtWidgets.QWidget.sizeHint(self))
class HelpDialog(QtGui.QDialog): class HelpDialog(QtWidgets.QDialog):
"""The `Help` dialog""" """The "Help" dialog"""
def __init__(self, parent=None): def __init__(self, parent=None):
super(HelpDialog, self).__init__(parent) super(HelpDialog, self).__init__(parent)
widgets.load('help.ui', self) widgets.load('help.ui', self)
self.setFixedSize(QtGui.QWidget.sizeHint(self)) self.setFixedSize(QtWidgets.QWidget.sizeHint(self))
class ConnectDialog(QtGui.QDialog): class ConnectDialog(QtWidgets.QDialog):
"""The `Connect` dialog""" """The "Connect" dialog"""
def __init__(self, parent=None): def __init__(self, parent=None):
super(ConnectDialog, self).__init__(parent) super(ConnectDialog, self).__init__(parent)
widgets.load('connect.ui', self) widgets.load('connect.ui', self)
self.setFixedSize(QtGui.QWidget.sizeHint(self)) self.setFixedSize(QtWidgets.QWidget.sizeHint(self))

View File

@ -1,12 +1,12 @@
""" """
Folder tree and messagelist widgets definitions. Folder tree and messagelist widgets definitions.
""" """
# pylint: disable=too-many-arguments,bad-super-call # pylint: disable=too-many-arguments
# pylint: disable=attribute-defined-outside-init # pylint: disable=attribute-defined-outside-init
from cgi import escape from cgi import escape
from PyQt4 import QtCore, QtGui from qtpy import QtCore, QtGui, QtWidgets
from bmconfigparser import BMConfigParser from bmconfigparser import BMConfigParser
from helper_sql import sqlExecute, sqlQuery from helper_sql import sqlExecute, sqlQuery
@ -38,15 +38,16 @@ class AccountMixin(object):
return QtGui.QColor(128, 128, 128) return QtGui.QColor(128, 128, 128)
elif self.type == self.CHAN: elif self.type == self.CHAN:
return QtGui.QColor(216, 119, 0) return QtGui.QColor(216, 119, 0)
elif self.type in [self.MAILINGLIST, self.SUBSCRIPTION]: elif self.type in (self.MAILINGLIST, self.SUBSCRIPTION):
return QtGui.QColor(137, 4, 177) return QtGui.QColor(137, 4, 177)
return QtGui.QApplication.palette().text().color()
return QtWidgets.QApplication.palette().text().color()
def folderColor(self): def folderColor(self):
"""QT UI color for a folder""" """QT UI color for a folder"""
if not self.parent().isEnabled: if not self.parent().isEnabled:
return QtGui.QColor(128, 128, 128) return QtGui.QColor(128, 128, 128)
return QtGui.QApplication.palette().text().color() return QtWidgets.QApplication.palette().text().color()
def accountBrush(self): def accountBrush(self):
"""Account brush (for QT UI)""" """Account brush (for QT UI)"""
@ -83,7 +84,7 @@ class AccountMixin(object):
except AttributeError: except AttributeError:
pass pass
self.unreadCount = int(cnt) self.unreadCount = int(cnt)
if isinstance(self, QtGui.QTreeWidgetItem): if isinstance(self, QtWidgets.QTreeWidgetItem):
self.emitDataChanged() self.emitDataChanged()
def setEnabled(self, enabled): def setEnabled(self, enabled):
@ -97,7 +98,7 @@ class AccountMixin(object):
for i in range(self.childCount()): for i in range(self.childCount()):
if isinstance(self.child(i), Ui_FolderWidget): if isinstance(self.child(i), Ui_FolderWidget):
self.child(i).setEnabled(enabled) self.child(i).setEnabled(enabled)
if isinstance(self, QtGui.QTreeWidgetItem): if isinstance(self, QtWidgets.QTreeWidgetItem):
self.emitDataChanged() self.emitDataChanged()
def setType(self): def setType(self):
@ -111,7 +112,9 @@ class AccountMixin(object):
elif BMConfigParser().safeGetBoolean(self.address, 'mailinglist'): elif BMConfigParser().safeGetBoolean(self.address, 'mailinglist'):
self.type = self.MAILINGLIST self.type = self.MAILINGLIST
elif sqlQuery( elif sqlQuery(
'''select label from subscriptions where address=?''', self.address): 'SELECT label FROM subscriptions WHERE address=?',
self.address
):
self.type = AccountMixin.SUBSCRIPTION self.type = AccountMixin.SUBSCRIPTION
else: else:
self.type = self.NORMAL self.type = self.NORMAL
@ -128,27 +131,30 @@ class AccountMixin(object):
BMConfigParser().get(self.address, 'label'), 'utf-8') BMConfigParser().get(self.address, 'label'), 'utf-8')
except Exception: except Exception:
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select label from addressbook where address=?''', self.address) 'SELECT label FROM addressbook WHERE address=?',
self.address
)
elif self.type == AccountMixin.SUBSCRIPTION: elif self.type == AccountMixin.SUBSCRIPTION:
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select label from subscriptions where address=?''', self.address) 'SELECT label FROM subscriptions WHERE address=?',
self.address
)
if queryreturn is not None: if queryreturn is not None:
if queryreturn != []: if queryreturn != []:
for row in queryreturn: for row in queryreturn:
retval, = row retval, = row
retval = unicode(retval, 'utf-8') retval = unicode(retval, 'utf-8')
elif self.address is None or self.type == AccountMixin.ALL: elif self.address is None or self.type == AccountMixin.ALL:
return unicode( return _translate("MainWindow", "All accounts")
str(_translate("MainWindow", "All accounts")), 'utf-8')
return retval or unicode(self.address, 'utf-8') return retval or unicode(self.address, 'utf-8')
class BMTreeWidgetItem(QtGui.QTreeWidgetItem, AccountMixin): class BMTreeWidgetItem(QtWidgets.QTreeWidgetItem, AccountMixin):
"""A common abstract class for Tree widget item""" """A common abstract class for Tree widget item"""
def __init__(self, parent, pos, address, unreadCount): def __init__(self, parent, pos, address, unreadCount):
super(QtGui.QTreeWidgetItem, self).__init__() super(QtWidgets.QTreeWidgetItem, self).__init__()
self.setAddress(address) self.setAddress(address)
self.setUnreadCount(unreadCount) self.setUnreadCount(unreadCount)
self._setup(parent, pos) self._setup(parent, pos)
@ -157,7 +163,7 @@ class BMTreeWidgetItem(QtGui.QTreeWidgetItem, AccountMixin):
return " (" + str(self.unreadCount) + ")" if unreadCount else "" return " (" + str(self.unreadCount) + ")" if unreadCount else ""
def data(self, column, role): def data(self, column, role):
"""Override internal QT method for returning object data""" """Override internal Qt method for returning object data"""
if column == 0: if column == 0:
if role == QtCore.Qt.DisplayRole: if role == QtCore.Qt.DisplayRole:
return self._getLabel() + self._getAddressBracket( return self._getLabel() + self._getAddressBracket(
@ -190,11 +196,11 @@ class Ui_FolderWidget(BMTreeWidgetItem):
return _translate("MainWindow", self.folderName) return _translate("MainWindow", self.folderName)
def setFolderName(self, fname): def setFolderName(self, fname):
"""Set folder name (for QT UI)""" """Set folder name (for Qt UI)"""
self.folderName = str(fname) self.folderName = str(fname)
def data(self, column, role): def data(self, column, role):
"""Override internal QT method for returning object data""" """Override internal Qt method for returning object data"""
if column == 0 and role == QtCore.Qt.ForegroundRole: if column == 0 and role == QtCore.Qt.ForegroundRole:
return self.folderBrush() return self.folderBrush()
return super(Ui_FolderWidget, self).data(column, role) return super(Ui_FolderWidget, self).data(column, role)
@ -216,12 +222,14 @@ class Ui_FolderWidget(BMTreeWidgetItem):
return self.folderName < other.folderName return self.folderName < other.folderName
return x >= y if reverse else x < y return x >= y if reverse else x < y
return super(QtGui.QTreeWidgetItem, self).__lt__(other) return super(QtWidgets.QTreeWidgetItem, self).__lt__(other)
class Ui_AddressWidget(BMTreeWidgetItem, SettingsMixin): class Ui_AddressWidget(BMTreeWidgetItem, SettingsMixin):
"""Item in the account/folder tree representing an account""" """Item in the account/folder tree representing an account"""
def __init__(self, parent, pos=0, address=None, unreadCount=0, enabled=True): def __init__(
self, parent, pos=0, address=None, unreadCount=0, enabled=True
):
super(Ui_AddressWidget, self).__init__( super(Ui_AddressWidget, self).__init__(
parent, pos, address, unreadCount) parent, pos, address, unreadCount)
self.setEnabled(enabled) self.setEnabled(enabled)
@ -232,8 +240,7 @@ class Ui_AddressWidget(BMTreeWidgetItem, SettingsMixin):
def _getLabel(self): def _getLabel(self):
if self.address is None: if self.address is None:
return unicode(_translate( return _translate("MainWindow", "All accounts")
"MainWindow", "All accounts").toUtf8(), 'utf-8', 'ignore')
else: else:
try: try:
return unicode( return unicode(
@ -260,15 +267,14 @@ class Ui_AddressWidget(BMTreeWidgetItem, SettingsMixin):
return super(Ui_AddressWidget, self).data(column, role) return super(Ui_AddressWidget, self).data(column, role)
def setData(self, column, role, value): def setData(self, column, role, value):
"""Save account label (if you edit in the the UI, this will be triggered and will save it to keys.dat)""" """
Save account label (if you edit in the the UI, this will be
triggered and will save it to keys.dat)
"""
if role == QtCore.Qt.EditRole \ if role == QtCore.Qt.EditRole \
and self.type != AccountMixin.SUBSCRIPTION: and self.type != AccountMixin.SUBSCRIPTION:
BMConfigParser().set( BMConfigParser().set(
str(self.address), 'label', str(self.address), 'label', value.encode('utf-8'))
str(value.toString().toUtf8())
if isinstance(value, QtCore.QVariant)
else value.encode('utf-8')
)
BMConfigParser().save() BMConfigParser().save()
return super(Ui_AddressWidget, self).setData(column, role, value) return super(Ui_AddressWidget, self).setData(column, role, value)
@ -295,19 +301,23 @@ class Ui_AddressWidget(BMTreeWidgetItem, SettingsMixin):
if self._getSortRank() < other._getSortRank() else reverse if self._getSortRank() < other._getSortRank() else reverse
) )
return super(QtGui.QTreeWidgetItem, self).__lt__(other) return super(Ui_AddressWidget, self).__lt__(other)
class Ui_SubscriptionWidget(Ui_AddressWidget): class Ui_SubscriptionWidget(Ui_AddressWidget):
"""Special treating of subscription addresses""" """Special treating of subscription addresses"""
# pylint: disable=unused-argument # pylint: disable=unused-argument
def __init__(self, parent, pos=0, address="", unreadCount=0, label="", enabled=True): def __init__(
self, parent, pos=0, address="", unreadCount=0, label="",
enabled=True
):
super(Ui_SubscriptionWidget, self).__init__( super(Ui_SubscriptionWidget, self).__init__(
parent, pos, address, unreadCount, enabled) parent, pos, address, unreadCount, enabled)
def _getLabel(self): def _getLabel(self):
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select label from subscriptions where address=?''', self.address) 'SELECT label FROM subscriptions WHERE address=?',
self.address)
if queryreturn != []: if queryreturn != []:
for row in queryreturn: for row in queryreturn:
retval, = row retval, = row
@ -322,22 +332,17 @@ class Ui_SubscriptionWidget(Ui_AddressWidget):
def setData(self, column, role, value): def setData(self, column, role, value):
"""Save subscription label to database""" """Save subscription label to database"""
if role == QtCore.Qt.EditRole: if role == QtCore.Qt.EditRole:
if isinstance(value, QtCore.QVariant):
label = str(
value.toString().toUtf8()).decode('utf-8', 'ignore')
else:
label = unicode(value, 'utf-8', 'ignore')
sqlExecute( sqlExecute(
'''UPDATE subscriptions SET label=? WHERE address=?''', 'UPDATE subscriptions SET label=? WHERE address=?',
label, self.address) value, self.address)
return super(Ui_SubscriptionWidget, self).setData(column, role, value) return super(Ui_SubscriptionWidget, self).setData(column, role, value)
class BMTableWidgetItem(QtGui.QTableWidgetItem, SettingsMixin): class BMTableWidgetItem(QtWidgets.QTableWidgetItem, SettingsMixin):
"""A common abstract class for Table widget item""" """A common abstract class for Table widget item"""
def __init__(self, label=None, unread=False): def __init__(self, label=None, unread=False):
super(QtGui.QTableWidgetItem, self).__init__() super(QtWidgets.QTableWidgetItem, self).__init__()
self.setLabel(label) self.setLabel(label)
self.setUnread(unread) self.setUnread(unread)
self._setup() self._setup()
@ -412,10 +417,12 @@ class MessageList_AddressWidget(BMAddressWidget):
'utf-8', 'ignore') 'utf-8', 'ignore')
except: except:
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select label from addressbook where address=?''', self.address) 'SELECT label FROM addressbook WHERE address=?',
self.address)
elif self.type == AccountMixin.SUBSCRIPTION: elif self.type == AccountMixin.SUBSCRIPTION:
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select label from subscriptions where address=?''', self.address) 'SELECT label FROM subscriptions WHERE address=?',
self.address)
if queryreturn: if queryreturn:
for row in queryreturn: for row in queryreturn:
newLabel = unicode(row[0], 'utf-8', 'ignore') newLabel = unicode(row[0], 'utf-8', 'ignore')
@ -438,7 +445,7 @@ class MessageList_AddressWidget(BMAddressWidget):
def __lt__(self, other): def __lt__(self, other):
if isinstance(other, MessageList_AddressWidget): if isinstance(other, MessageList_AddressWidget):
return self.label.lower() < other.label.lower() return self.label.lower() < other.label.lower()
return super(QtGui.QTableWidgetItem, self).__lt__(other) return super(MessageList_AddressWidget, self).__lt__(other)
class MessageList_SubjectWidget(BMTableWidgetItem): class MessageList_SubjectWidget(BMTableWidgetItem):
@ -456,14 +463,14 @@ class MessageList_SubjectWidget(BMTableWidgetItem):
if role == QtCore.Qt.UserRole: if role == QtCore.Qt.UserRole:
return self.subject return self.subject
if role == QtCore.Qt.ToolTipRole: if role == QtCore.Qt.ToolTipRole:
return escape(unicode(self.subject, 'utf-8')) return escape(self.subject)
return super(MessageList_SubjectWidget, self).data(role) return super(MessageList_SubjectWidget, self).data(role)
# label (or address) alphabetically, disabled at the end # label (or address) alphabetically, disabled at the end
def __lt__(self, other): def __lt__(self, other):
if isinstance(other, MessageList_SubjectWidget): if isinstance(other, MessageList_SubjectWidget):
return self.label.lower() < other.label.lower() return self.label.lower() < other.label.lower()
return super(QtGui.QTableWidgetItem, self).__lt__(other) return super(MessageList_SubjectWidget, self).__lt__(other)
# In order for the time columns on the Inbox and Sent tabs to be sorted # In order for the time columns on the Inbox and Sent tabs to be sorted
@ -491,15 +498,14 @@ class MessageList_TimeWidget(BMTableWidgetItem):
""" """
data = super(MessageList_TimeWidget, self).data(role) data = super(MessageList_TimeWidget, self).data(role)
if role == TimestampRole: if role == TimestampRole:
return int(data.toPyObject()) return int(data)
if role == QtCore.Qt.UserRole: if role == QtCore.Qt.UserRole:
return str(data.toPyObject()) return str(data)
return data return data
class Ui_AddressBookWidgetItem(BMAddressWidget): class Ui_AddressBookWidgetItem(BMAddressWidget):
"""Addressbook item""" """Addressbook item"""
# pylint: disable=unused-argument
def __init__(self, label=None, acc_type=AccountMixin.NORMAL): def __init__(self, label=None, acc_type=AccountMixin.NORMAL):
self.type = acc_type self.type = acc_type
super(Ui_AddressBookWidgetItem, self).__init__(label=label) super(Ui_AddressBookWidgetItem, self).__init__(label=label)
@ -513,10 +519,7 @@ class Ui_AddressBookWidgetItem(BMAddressWidget):
def setData(self, role, value): def setData(self, role, value):
"""Set data""" """Set data"""
if role == QtCore.Qt.EditRole: if role == QtCore.Qt.EditRole:
self.label = str( self.label = value.encode('utf-8')
value.toString().toUtf8()
if isinstance(value, QtCore.QVariant) else value
)
if self.type in ( if self.type in (
AccountMixin.NORMAL, AccountMixin.NORMAL,
AccountMixin.MAILINGLIST, AccountMixin.CHAN): AccountMixin.MAILINGLIST, AccountMixin.CHAN):
@ -525,22 +528,29 @@ class Ui_AddressBookWidgetItem(BMAddressWidget):
BMConfigParser().set(self.address, 'label', self.label) BMConfigParser().set(self.address, 'label', self.label)
BMConfigParser().save() BMConfigParser().save()
except: except:
sqlExecute('''UPDATE addressbook set label=? WHERE address=?''', self.label, self.address) sqlExecute(
'UPDATE addressbook SET label=? WHERE address=?',
self.label, self.address
)
elif self.type == AccountMixin.SUBSCRIPTION: elif self.type == AccountMixin.SUBSCRIPTION:
sqlExecute('''UPDATE subscriptions set label=? WHERE address=?''', self.label, self.address) sqlExecute(
'UPDATE subscriptions SET label=? WHERE address=?',
self.label, self.address)
else: else:
pass pass
return super(Ui_AddressBookWidgetItem, self).setData(role, value) return super(Ui_AddressBookWidgetItem, self).setData(role, value)
def __lt__(self, other): def __lt__(self, other):
if isinstance(other, Ui_AddressBookWidgetItem): if not isinstance(other, Ui_AddressBookWidgetItem):
reverse = QtCore.Qt.DescendingOrder == \ return super(Ui_AddressBookWidgetItem, self).__lt__(other)
self.tableWidget().horizontalHeader().sortIndicatorOrder()
if self.type == other.type: reverse = QtCore.Qt.DescendingOrder == \
return self.label.lower() < other.label.lower() self.tableWidget().horizontalHeader().sortIndicatorOrder()
return not reverse if self.type < other.type else reverse
return super(QtGui.QTableWidgetItem, self).__lt__(other) if self.type == other.type:
return self.label.lower() < other.label.lower()
return not reverse if self.type < other.type else reverse
class Ui_AddressBookWidgetItemLabel(Ui_AddressBookWidgetItem): class Ui_AddressBookWidgetItemLabel(Ui_AddressBookWidgetItem):
@ -570,28 +580,26 @@ class Ui_AddressBookWidgetItemAddress(Ui_AddressBookWidgetItem):
return super(Ui_AddressBookWidgetItemAddress, self).data(role) return super(Ui_AddressBookWidgetItemAddress, self).data(role)
class AddressBookCompleter(QtGui.QCompleter): class AddressBookCompleter(QtWidgets.QCompleter):
"""Addressbook completer""" """Addressbook completer"""
def __init__(self): def __init__(self):
super(AddressBookCompleter, self).__init__() super(AddressBookCompleter, self).__init__()
self.cursorPos = -1 self.cursorPos = -1
def onCursorPositionChanged(self, oldPos, newPos): # pylint: disable=unused-argument def onCursorPositionChanged(self, oldPos, newPos):
"""Callback for cursor position change""" """Callback for cursor position change"""
# pylint: disable=unused-argument
if oldPos != self.cursorPos: if oldPos != self.cursorPos:
self.cursorPos = -1 self.cursorPos = -1
def splitPath(self, path): def splitPath(self, path):
"""Split on semicolon""" """Split on semicolon"""
text = unicode(path.toUtf8(), 'utf-8') return [path[:self.widget().cursorPosition()].split(';')[-1].strip()]
return [text[:self.widget().cursorPosition()].split(';')[-1].strip()]
def pathFromIndex(self, index): def pathFromIndex(self, index):
"""Perform autocompletion (reimplemented QCompleter method)""" """Perform autocompletion (reimplemented QCompleter method)"""
autoString = unicode( autoString = index.data(QtCore.Qt.EditRole).toString()
index.data(QtCore.Qt.EditRole).toString().toUtf8(), 'utf-8') text = self.widget().text()
text = unicode(self.widget().text().toUtf8(), 'utf-8')
# If cursor position was saved, restore it, else save it # If cursor position was saved, restore it, else save it
if self.cursorPos != -1: if self.cursorPos != -1:
@ -620,7 +628,6 @@ class AddressBookCompleter(QtGui.QCompleter):
# Get string value from before auto finished string is selected # Get string value from before auto finished string is selected
# pre = text[prevDelimiterIndex + 1:curIndex - 1] # pre = text[prevDelimiterIndex + 1:curIndex - 1]
# Get part of string that occurs AFTER cursor # Get part of string that occurs AFTER cursor
part2 = text[nextDelimiterIndex:] part2 = text[nextDelimiterIndex:]

View File

@ -1,48 +1,56 @@
"""Language Box Module for Locale Settings""" """LanguageBox widget is for selecting UI language"""
# pylint: disable=too-few-public-methods,bad-continuation
import glob import glob
import os import os
from PyQt4 import QtCore, QtGui from qtpy import QtCore, QtWidgets
import paths import paths
from bmconfigparser import BMConfigParser from bmconfigparser import BMConfigParser
from tr import _translate
class LanguageBox(QtGui.QComboBox): # pylint: disable=too-few-public-methods
"""LanguageBox class for Qt UI""" class LanguageBox(QtWidgets.QComboBox):
"""A subclass of `QtWidgets.QComboBox` for selecting language"""
languageName = { languageName = {
"system": "System Settings", "eo": "Esperanto", "system": "System Settings",
"eo": "Esperanto",
"en_pirate": "Pirate English" "en_pirate": "Pirate English"
} }
def __init__(self, parent=None): def __init__(self, parent=None):
super(QtGui.QComboBox, self).__init__(parent) super(LanguageBox, self).__init__(parent)
self.populate() self.populate()
def populate(self): def populate(self):
"""Populates drop down list with all available languages.""" """Populates drop down list with all available languages."""
self.clear() self.clear()
localesPath = os.path.join(paths.codePath(), 'translations') localesPath = os.path.join(paths.codePath(), 'translations')
self.addItem(QtGui.QApplication.translate( self.addItem(
"settingsDialog", "System Settings", "system"), "system") _translate("settingsDialog", "System Settings", "system"),
"system"
)
self.setCurrentIndex(0) self.setCurrentIndex(0)
self.setInsertPolicy(QtGui.QComboBox.InsertAlphabetically) self.setInsertPolicy(QtWidgets.QComboBox.InsertAlphabetically)
for translationFile in sorted( for translationFile in sorted(
glob.glob(os.path.join(localesPath, "bitmessage_*.qm")) glob.glob(os.path.join(localesPath, "bitmessage_*.qm"))
): ):
localeShort = \ localeShort = \
os.path.split(translationFile)[1].split("_", 1)[1][:-3] os.path.split(translationFile)[1].split("_", 1)[1][:-3]
locale = QtCore.QLocale(localeShort)
if localeShort in LanguageBox.languageName: if localeShort in LanguageBox.languageName:
self.addItem( self.addItem(
LanguageBox.languageName[localeShort], localeShort) LanguageBox.languageName[localeShort], localeShort)
elif locale.nativeLanguageName() == "":
self.addItem(localeShort, localeShort)
else: else:
locale = QtCore.QLocale(localeShort) locale = QtCore.QLocale(localeShort)
self.addItem( self.addItem(
locale.nativeLanguageName() or localeShort, localeShort) locale.nativeLanguageName() or localeShort, localeShort)
configuredLocale = BMConfigParser().safeGet( configuredLocale = BMConfigParser().safeGet(
'bitmessagesettings', 'userlocale', "system") 'bitmessagesettings', 'userlocale', 'system')
for i in range(self.count()): for i in range(self.count()):
if self.itemData(i) == configuredLocale: if self.itemData(i) == configuredLocale:
self.setCurrentIndex(i) self.setCurrentIndex(i)

View File

@ -1,33 +1,34 @@
""" """The MessageCompose class definition"""
Message editor with a wheel zoom functionality
"""
# pylint: disable=bad-continuation
from PyQt4 import QtCore, QtGui from qtpy import QtCore, QtWidgets
from tr import _translate
class MessageCompose(QtGui.QTextEdit): class MessageCompose(QtWidgets.QTextEdit):
"""Editor class with wheel zoom functionality""" """Editor class with wheel zoom functionality"""
def __init__(self, parent=0): def __init__(self, parent=None):
super(MessageCompose, self).__init__(parent) super(MessageCompose, self).__init__(parent)
# we'll deal with this later when we have a new message format
self.setAcceptRichText(False) self.setAcceptRichText(False)
self.defaultFontPointSize = self.currentFont().pointSize() self.defaultFontPointSize = self.currentFont().pointSize()
def wheelEvent(self, event): def wheelEvent(self, event):
"""Mouse wheel scroll event handler""" """Mouse wheel scroll event handler"""
if ( if (
QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ControlModifier (QtWidgets.QApplication.queryKeyboardModifiers()
) == QtCore.Qt.ControlModifier and event.orientation() == QtCore.Qt.Vertical: & QtCore.Qt.ControlModifier) == QtCore.Qt.ControlModifier
and event.angleDelta().y() != 0
):
if event.delta() > 0: if event.delta() > 0:
self.zoomIn(1) self.zoomIn(1)
else: else:
self.zoomOut(1) self.zoomOut(1)
zoom = self.currentFont().pointSize() * 100 / self.defaultFontPointSize QtWidgets.QApplication.activeWindow().statusbar.showMessage(
QtGui.QApplication.activeWindow().statusBar().showMessage( _translate("MainWindow", "Zoom level {0}%").format(
QtGui.QApplication.translate("MainWindow", "Zoom level %1%").arg( # zoom percentage
str(zoom) self.currentFont().pointSize() * 100
) / self.defaultFontPointSize
) ))
else: else:
# in QTextEdit, super does not zoom, only scroll # in QTextEdit, super does not zoom, only scroll
super(MessageCompose, self).wheelEvent(event) super(MessageCompose, self).wheelEvent(event)

View File

@ -1,22 +1,21 @@
""" """
Custom message viewer with support for switching between HTML and plain Custom message viewer with support for switching between HTML and plain
text rendering, HTML sanitization, lazy rendering (as you scroll down), text rendering, HTML sanitization, lazy rendering (as you scroll down),
zoom and URL click warning popup zoom and URL click warning popup.
""" """
from PyQt4 import QtCore, QtGui from qtpy import QtCore, QtGui, QtWidgets
from safehtmlparser import SafeHTMLParser from safehtmlparser import SafeHTMLParser
from tr import _translate from tr import _translate
class MessageView(QtGui.QTextBrowser): class MessageView(QtWidgets.QTextBrowser):
"""Message content viewer class, can switch between plaintext and HTML""" """Message content viewer class, can switch between plaintext and HTML"""
MODE_PLAIN = 0 MODE_PLAIN = 0
MODE_HTML = 1 MODE_HTML = 1
def __init__(self, parent=0): def __init__(self, parent=None):
super(MessageView, self).__init__(parent) super(MessageView, self).__init__(parent)
self.mode = MessageView.MODE_PLAIN self.mode = MessageView.MODE_PLAIN
self.html = None self.html = None
@ -38,8 +37,11 @@ class MessageView(QtGui.QTextBrowser):
def mousePressEvent(self, event): def mousePressEvent(self, event):
"""Mouse press button event handler""" """Mouse press button event handler"""
if event.button() == QtCore.Qt.LeftButton and self.html and self.html.has_html and self.cursorForPosition( if (
event.pos()).block().blockNumber() == 0: event.button() == QtCore.Qt.LeftButton
and self.html and self.html.has_html
and self.cursorForPosition(event.pos()).block().blockNumber() == 0
):
if self.mode == MessageView.MODE_PLAIN: if self.mode == MessageView.MODE_PLAIN:
self.showHTML() self.showHTML()
else: else:
@ -52,23 +54,23 @@ class MessageView(QtGui.QTextBrowser):
# super will actually automatically take care of zooming # super will actually automatically take care of zooming
super(MessageView, self).wheelEvent(event) super(MessageView, self).wheelEvent(event)
if ( if (
QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ControlModifier (QtWidgets.QApplication.queryKeyboardModifiers()
) == QtCore.Qt.ControlModifier and event.orientation() == QtCore.Qt.Vertical: & QtCore.Qt.ControlModifier) == QtCore.Qt.ControlModifier
and event.angleDelta().y() != 0
):
zoom = self.currentFont().pointSize() * 100 / self.defaultFontPointSize zoom = self.currentFont().pointSize() * 100 / self.defaultFontPointSize
QtGui.QApplication.activeWindow().statusBar().showMessage(_translate( QtWidgets.QApplication.activeWindow().statusbar.showMessage(
"MainWindow", "Zoom level %1%").arg(str(zoom))) _translate("MainWindow", "Zoom level {0}%").format(zoom))
def setWrappingWidth(self, width=None): def setWrappingWidth(self, width=None):
"""Set word-wrapping width""" """Set word-wrapping width"""
self.setLineWrapMode(QtGui.QTextEdit.FixedPixelWidth) self.setLineWrapMode(QtWidgets.QTextEdit.FixedPixelWidth)
if width is None: self.setLineWrapColumnOrWidth(width or self.width())
width = self.width()
self.setLineWrapColumnOrWidth(width)
def confirmURL(self, link): def confirmURL(self, link):
"""Show a dialog requesting URL opening confirmation""" """Show a dialog requesting URL opening confirmation"""
if link.scheme() == "mailto": if link.scheme() == "mailto":
window = QtGui.QApplication.activeWindow() window = QtWidgets.QApplication.activeWindow()
window.ui.lineEditTo.setText(link.path()) window.ui.lineEditTo.setText(link.path())
if link.hasQueryItem("subject"): if link.hasQueryItem("subject"):
window.ui.lineEditSubject.setText( window.ui.lineEditSubject.setText(
@ -83,39 +85,40 @@ class MessageView(QtGui.QTextBrowser):
) )
window.ui.textEditMessage.setFocus() window.ui.textEditMessage.setFocus()
return return
reply = QtGui.QMessageBox.warning( reply = QtWidgets.QMessageBox.warning(
self, self, _translate("MessageView", "Follow external link"),
QtGui.QApplication.translate( _translate(
"MessageView", "MessageView",
"Follow external link"), "The link \"{0}\" will open in a browser. It may be"
QtGui.QApplication.translate( " a security risk, it could de-anonymise you or download"
"MessageView", " malicious data. Are you sure?"
"The link \"%1\" will open in a browser. It may be a security risk, it could de-anonymise you" ).format(link.toString()),
" or download malicious data. Are you sure?").arg(unicode(link.toString())), QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
QtGui.QMessageBox.Yes, if reply == QtWidgets.QMessageBox.Yes:
QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
QtGui.QDesktopServices.openUrl(link) QtGui.QDesktopServices.openUrl(link)
def loadResource(self, restype, name): def loadResource(self, restype, name):
""" """
Callback for loading referenced objects, such as an image. For security reasons at the moment doesn't do Callback for loading referenced objects, such as an image.
anything) For security reasons at the moment doesn't do anything
""" """
pass pass
def lazyRender(self): def lazyRender(self):
""" """
Partially render a message. This is to avoid UI freezing when loading huge messages. It continues loading as Partially render a message. This is to avoid UI freezing when
you scroll down. loading huge messages. It continues loading as you scroll down.
""" """
if self.rendering: if self.rendering:
return return
self.rendering = True self.rendering = True
position = self.verticalScrollBar().value() position = self.verticalScrollBar().value()
cursor = QtGui.QTextCursor(self.document()) cursor = QtGui.QTextCursor(self.document())
while self.outpos < len(self.out) and self.verticalScrollBar().value( while (
) >= self.document().size().height() - 2 * self.size().height(): self.outpos < len(self.out)
and self.verticalScrollBar().value()
>= self.document().size().height() - 2 * self.size().height()
):
startpos = self.outpos startpos = self.outpos
self.outpos += 10240 self.outpos += 10240
# find next end of tag # find next end of tag
@ -123,8 +126,9 @@ class MessageView(QtGui.QTextBrowser):
pos = self.out.find(">", self.outpos) pos = self.out.find(">", self.outpos)
if pos > self.outpos: if pos > self.outpos:
self.outpos = pos + 1 self.outpos = pos + 1
cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.MoveAnchor) cursor.movePosition(
cursor.insertHtml(QtCore.QString(self.out[startpos:self.outpos])) QtGui.QTextCursor.End, QtGui.QTextCursor.MoveAnchor)
cursor.insertHtml(self.out[startpos:self.outpos])
self.verticalScrollBar().setValue(position) self.verticalScrollBar().setValue(position)
self.rendering = False self.rendering = False
@ -133,9 +137,11 @@ class MessageView(QtGui.QTextBrowser):
self.mode = MessageView.MODE_PLAIN self.mode = MessageView.MODE_PLAIN
out = self.html.raw out = self.html.raw
if self.html.has_html: if self.html.has_html:
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + unicode( out = (
QtGui.QApplication.translate( '<div align="center" style="text-decoration: underline;"><b>'
"MessageView", "HTML detected, click here to display")) + "</b></div><br/>" + out + _translate(
"MessageView", "HTML detected, click here to display"
) + '</b></div><br/>' + out)
self.out = out self.out = out
self.outpos = 0 self.outpos = 0
self.setHtml("") self.setHtml("")
@ -144,10 +150,10 @@ class MessageView(QtGui.QTextBrowser):
def showHTML(self): def showHTML(self):
"""Render message as HTML""" """Render message as HTML"""
self.mode = MessageView.MODE_HTML self.mode = MessageView.MODE_HTML
out = self.html.sanitised self.out = (
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + unicode( '<div align="center" style="text-decoration: underline;"><b>'
QtGui.QApplication.translate("MessageView", "Click here to disable HTML")) + "</b></div><br/>" + out + _translate("MessageView", "Click here to disable HTML")
self.out = out + '</b></div><br/>' + self.html.sanitised)
self.outpos = 0 self.outpos = 0
self.setHtml("") self.setHtml("")
self.lazyRender() self.lazyRender()
@ -155,8 +161,6 @@ class MessageView(QtGui.QTextBrowser):
def setContent(self, data): def setContent(self, data):
"""Set message content from argument""" """Set message content from argument"""
self.html = SafeHTMLParser() self.html = SafeHTMLParser()
self.html.reset()
self.html.reset_safe()
self.html.allow_picture = True self.html.allow_picture = True
self.html.feed(data) self.html.feed(data)
self.html.close() self.html.close()

View File

@ -4,7 +4,7 @@ Network status tab widget definition.
import time import time
from PyQt4 import QtCore, QtGui from qtpy import QtCore, QtGui, QtWidgets
import l10n import l10n
import network.stats import network.stats
@ -17,14 +17,16 @@ from tr import _translate
from uisignaler import UISignaler from uisignaler import UISignaler
class NetworkStatus(QtGui.QWidget, RetranslateMixin): class NetworkStatus(QtWidgets.QWidget, RetranslateMixin):
"""Network status tab""" """Network status tab"""
def __init__(self, parent=None): def __init__(self, parent=None):
super(NetworkStatus, self).__init__(parent) super(NetworkStatus, self).__init__(parent)
widgets.load('networkstatus.ui', self) widgets.load('networkstatus.ui', self)
header = self.tableWidgetConnectionCount.horizontalHeader() header = self.tableWidgetConnectionCount.horizontalHeader()
header.setResizeMode(QtGui.QHeaderView.ResizeToContents) header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
header.setSectionResizeMode(2, QtWidgets.QHeaderView.Stretch)
# Somehow this value was 5 when I tested # Somehow this value was 5 when I tested
if header.sortIndicatorSection() > 4: if header.sortIndicatorSection() > 4:
@ -33,20 +35,17 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
self.startup = time.localtime() self.startup = time.localtime()
self.UISignalThread = UISignaler.get() self.UISignalThread = UISignaler.get()
# pylint: disable=no-member self.UISignalThread.updateNumberOfMessagesProcessed.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.updateNumberOfMessagesProcessed)
"updateNumberOfMessagesProcessed()"), self.updateNumberOfMessagesProcessed) self.UISignalThread.updateNumberOfPubkeysProcessed.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.updateNumberOfPubkeysProcessed)
"updateNumberOfPubkeysProcessed()"), self.updateNumberOfPubkeysProcessed) self.UISignalThread.updateNumberOfBroadcastsProcessed.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.updateNumberOfBroadcastsProcessed)
"updateNumberOfBroadcastsProcessed()"), self.updateNumberOfBroadcastsProcessed) self.UISignalThread.updateNetworkStatusTab.connect(
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( self.updateNetworkStatusTab)
"updateNetworkStatusTab(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.updateNetworkStatusTab)
self.timer = QtCore.QTimer() self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.runEveryTwoSeconds)
QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.runEveryTwoSeconds)
# pylint: enable=no-member
def startUpdate(self): def startUpdate(self):
"""Start a timer to update counters every 2 seconds""" """Start a timer to update counters every 2 seconds"""
@ -58,91 +57,66 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
"""Stop counter update timer""" """Stop counter update timer"""
self.timer.stop() self.timer.stop()
def formatBytes(self, num): @staticmethod
def formatBytes(num):
"""Format bytes nicely (SI prefixes)""" """Format bytes nicely (SI prefixes)"""
# pylint: disable=no-self-use for x in (
for x in [ _translate("networkstatus", "byte(s)", None, num),
_translate( "kB", "MB", "GB"
"networkstatus", ):
"byte(s)",
None,
QtCore.QCoreApplication.CodecForTr,
num),
"kB",
"MB",
"GB",
]:
if num < 1000.0: if num < 1000.0:
return "%3.0f %s" % (num, x) return "%3.0f %s" % (num, x)
num /= 1000.0 num /= 1000.0
return "%3.0f %s" % (num, 'TB') return "%3.0f %s" % (num, "TB")
def formatByteRate(self, num): @staticmethod
def formatByteRate(num):
"""Format transfer speed in kB/s""" """Format transfer speed in kB/s"""
# pylint: disable=no-self-use
num /= 1000 num /= 1000
return "%4.0f kB" % num return "%4.0f kB" % num
def updateNumberOfObjectsToBeSynced(self): def updateNumberOfObjectsToBeSynced(self):
"""Update the counter for number of objects to be synced""" """Update the counter for number of objects to be synced"""
self.labelSyncStatus.setText( self.labelSyncStatus.setText(_translate(
_translate( "networkstatus", "Object(s) to be synced: %n", None,
"networkstatus", network.stats.pendingDownload() + network.stats.pendingUpload()))
"Object(s) to be synced: %n",
None,
QtCore.QCoreApplication.CodecForTr,
network.stats.pendingDownload()
+ network.stats.pendingUpload()))
def updateNumberOfMessagesProcessed(self): def updateNumberOfMessagesProcessed(self):
"""Update the counter for number of processed messages""" """Update the counter for number of processed messages"""
self.updateNumberOfObjectsToBeSynced() self.updateNumberOfObjectsToBeSynced()
self.labelMessageCount.setText( self.labelMessageCount.setText(_translate(
_translate( "networkstatus", "Processed %n person-to-person message(s).",
"networkstatus", None, state.numberOfMessagesProcessed))
"Processed %n person-to-person message(s).",
None,
QtCore.QCoreApplication.CodecForTr,
state.numberOfMessagesProcessed))
def updateNumberOfBroadcastsProcessed(self): def updateNumberOfBroadcastsProcessed(self):
"""Update the counter for the number of processed broadcasts""" """Update the counter for the number of processed broadcasts"""
self.updateNumberOfObjectsToBeSynced() self.updateNumberOfObjectsToBeSynced()
self.labelBroadcastCount.setText( self.labelBroadcastCount.setText(_translate(
_translate( "networkstatus", "Processed %n broadcast message(s).", None,
"networkstatus", state.numberOfBroadcastsProcessed))
"Processed %n broadcast message(s).",
None,
QtCore.QCoreApplication.CodecForTr,
state.numberOfBroadcastsProcessed))
def updateNumberOfPubkeysProcessed(self): def updateNumberOfPubkeysProcessed(self):
"""Update the counter for the number of processed pubkeys""" """Update the counter for the number of processed pubkeys"""
self.updateNumberOfObjectsToBeSynced() self.updateNumberOfObjectsToBeSynced()
self.labelPubkeyCount.setText( self.labelPubkeyCount.setText(_translate(
_translate( "networkstatus", "Processed %n public key(s).", None,
"networkstatus", state.numberOfPubkeysProcessed))
"Processed %n public key(s).",
None,
QtCore.QCoreApplication.CodecForTr,
state.numberOfPubkeysProcessed))
def updateNumberOfBytes(self): def updateNumberOfBytes(self):
""" """
This function is run every two seconds, so we divide the rate of bytes This function is run every two seconds, so we divide the rate
sent and received by 2. of bytes sent and received by 2.
""" """
self.labelBytesRecvCount.setText( self.labelBytesRecvCount.setText(_translate(
_translate( "networkstatus", "Down: {0}/s Total: {1}").format(
"networkstatus", self.formatByteRate(network.stats.downloadSpeed()),
"Down: %1/s Total: %2").arg( self.formatBytes(network.stats.receivedBytes())
self.formatByteRate(network.stats.downloadSpeed()), ))
self.formatBytes(network.stats.receivedBytes()))) self.labelBytesSentCount.setText(_translate(
self.labelBytesSentCount.setText( "networkstatus", "Up: {0}/s Total: {1}").format(
_translate( self.formatByteRate(network.stats.uploadSpeed()),
"networkstatus", "Up: %1/s Total: %2").arg( self.formatBytes(network.stats.sentBytes())
self.formatByteRate(network.stats.uploadSpeed()), ))
self.formatBytes(network.stats.sentBytes())))
def updateNetworkStatusTab(self, outbound, add, destination): def updateNetworkStatusTab(self, outbound, add, destination):
"""Add or remove an entry to the list of connected peers""" """Add or remove an entry to the list of connected peers"""
@ -169,67 +143,67 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
if add: if add:
self.tableWidgetConnectionCount.insertRow(0) self.tableWidgetConnectionCount.insertRow(0)
self.tableWidgetConnectionCount.setItem( self.tableWidgetConnectionCount.setItem(
0, 0, 0, 0, QtWidgets.QTableWidgetItem(
QtGui.QTableWidgetItem("%s:%i" % (destination.host, destination.port)) "%s:%i" % (destination.host, destination.port)))
)
self.tableWidgetConnectionCount.setItem( self.tableWidgetConnectionCount.setItem(
0, 2, 0, 2, QtWidgets.QTableWidgetItem("%s" % (c.userAgent)))
QtGui.QTableWidgetItem("%s" % (c.userAgent))
)
self.tableWidgetConnectionCount.setItem( self.tableWidgetConnectionCount.setItem(
0, 3, 0, 3, QtWidgets.QTableWidgetItem("%s" % (c.tlsVersion)))
QtGui.QTableWidgetItem("%s" % (c.tlsVersion))
)
self.tableWidgetConnectionCount.setItem( self.tableWidgetConnectionCount.setItem(
0, 4, 0, 4, QtWidgets.QTableWidgetItem(
QtGui.QTableWidgetItem("%s" % (",".join(map(str, c.streams)))) "%s" % ",".join(map(str, c.streams))))
)
try: try:
# .. todo:: FIXME: hard coded stream no # .. todo:: FIXME: hard coded stream no
rating = "%.1f" % (knownnodes.knownNodes[1][destination]['rating']) rating = "%.1f" % knownnodes.knownNodes[1][destination]['rating']
except KeyError: except KeyError:
rating = "-" rating = "-"
self.tableWidgetConnectionCount.setItem( self.tableWidgetConnectionCount.setItem(
0, 1, 0, 1, QtWidgets.QTableWidgetItem("%s" % (rating)))
QtGui.QTableWidgetItem("%s" % (rating))
)
if outbound: if outbound:
brush = QtGui.QBrush(QtGui.QColor("yellow"), QtCore.Qt.SolidPattern) brush = QtGui.QBrush(
QtGui.QColor("yellow"), QtCore.Qt.SolidPattern)
else: else:
brush = QtGui.QBrush(QtGui.QColor("green"), QtCore.Qt.SolidPattern) brush = QtGui.QBrush(
QtGui.QColor("green"), QtCore.Qt.SolidPattern)
for j in range(1): for j in range(1):
self.tableWidgetConnectionCount.item(0, j).setBackground(brush) self.tableWidgetConnectionCount.item(0, j).setBackground(brush)
self.tableWidgetConnectionCount.item(0, 0).setData(QtCore.Qt.UserRole, destination) self.tableWidgetConnectionCount.item(0, 0).setData(
self.tableWidgetConnectionCount.item(0, 1).setData(QtCore.Qt.UserRole, outbound) QtCore.Qt.UserRole, destination)
self.tableWidgetConnectionCount.item(0, 1).setData(
QtCore.Qt.UserRole, outbound)
else: else:
if not BMConnectionPool().inboundConnections: if not BMConnectionPool().inboundConnections:
self.window().setStatusIcon('yellow') self.window().setStatusIcon('yellow')
for i in range(self.tableWidgetConnectionCount.rowCount()): for i in range(self.tableWidgetConnectionCount.rowCount()):
if self.tableWidgetConnectionCount.item(i, 0).data(QtCore.Qt.UserRole).toPyObject() != destination: if self.tableWidgetConnectionCount.item(i, 0).data(
QtCore.Qt.UserRole) != destination:
continue continue
if self.tableWidgetConnectionCount.item(i, 1).data(QtCore.Qt.UserRole).toPyObject() == outbound: if self.tableWidgetConnectionCount.item(i, 1).data(
QtCore.Qt.UserRole) == outbound:
self.tableWidgetConnectionCount.removeRow(i) self.tableWidgetConnectionCount.removeRow(i)
break break
self.tableWidgetConnectionCount.setUpdatesEnabled(True) self.tableWidgetConnectionCount.setUpdatesEnabled(True)
self.tableWidgetConnectionCount.setSortingEnabled(True) self.tableWidgetConnectionCount.setSortingEnabled(True)
self.labelTotalConnections.setText( self.labelTotalConnections.setText(_translate(
_translate( "networkstatus", "Total Connections: {0}").format(
"networkstatus", "Total Connections: %1").arg( self.tableWidgetConnectionCount.rowCount()
str(self.tableWidgetConnectionCount.rowCount()))) ))
# FYI: The 'singlelistener' thread sets the icon color to green when it # FYI: The 'singlelistener' thread sets the icon color to green
# receives an incoming connection, meaning that the user's firewall is # when it receives an incoming connection, meaning that the user's
# configured correctly. # firewall is configured correctly.
if self.tableWidgetConnectionCount.rowCount() and state.statusIconColor == 'red': if self.tableWidgetConnectionCount.rowCount():
self.window().setStatusIcon('yellow') if state.statusIconColor == 'red':
elif self.tableWidgetConnectionCount.rowCount() == 0 and state.statusIconColor != "red": self.window().setStatusIcon('yellow')
elif state.statusIconColor != 'red':
self.window().setStatusIcon('red') self.window().setStatusIcon('red')
# timer driven # timer driven
def runEveryTwoSeconds(self): def runEveryTwoSeconds(self):
"""Updates counters, runs every 2 seconds if the timer is running""" """Updates counters, runs every 2 seconds if the timer is running"""
self.labelLookupsPerSecond.setText(_translate("networkstatus", "Inventory lookups per second: %1").arg( self.labelLookupsPerSecond.setText(_translate(
str(Inventory().numberOfInventoryLookupsPerformed / 2))) "networkstatus", "Inventory lookups per second: {0}"
).format(Inventory().numberOfInventoryLookupsPerformed / 2))
Inventory().numberOfInventoryLookupsPerformed = 0 Inventory().numberOfInventoryLookupsPerformed = 0
self.updateNumberOfBytes() self.updateNumberOfBytes()
self.updateNumberOfObjectsToBeSynced() self.updateNumberOfObjectsToBeSynced()
@ -237,13 +211,12 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
def retranslateUi(self): def retranslateUi(self):
"""Conventional Qt Designer method for dynamic l10n""" """Conventional Qt Designer method for dynamic l10n"""
super(NetworkStatus, self).retranslateUi() super(NetworkStatus, self).retranslateUi()
self.labelTotalConnections.setText( self.labelTotalConnections.setText(_translate(
_translate( "networkstatus", "Total Connections: {0}"
"networkstatus", "Total Connections: %1").arg( ).format(self.tableWidgetConnectionCount.rowCount()))
str(self.tableWidgetConnectionCount.rowCount())))
self.labelStartupTime.setText(_translate( self.labelStartupTime.setText(_translate(
"networkstatus", "Since startup on %1" "networkstatus", "Since startup on {0}"
).arg(l10n.formatTimestamp(self.startup))) ).format(l10n.formatTimestamp(self.startup)))
self.updateNumberOfMessagesProcessed() self.updateNumberOfMessagesProcessed()
self.updateNumberOfBroadcastsProcessed() self.updateNumberOfBroadcastsProcessed()
self.updateNumberOfPubkeysProcessed() self.updateNumberOfPubkeysProcessed()

View File

@ -100,6 +100,9 @@
<property name="sortingEnabled"> <property name="sortingEnabled">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="wordWrap">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes"> <attribute name="horizontalHeaderCascadingSectionResizes">
<bool>true</bool> <bool>true</bool>
</attribute> </attribute>
@ -109,9 +112,6 @@
<attribute name="horizontalHeaderHighlightSections"> <attribute name="horizontalHeaderHighlightSections">
<bool>false</bool> <bool>false</bool>
</attribute> </attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible"> <attribute name="verticalHeaderVisible">
<bool>false</bool> <bool>false</bool>
</attribute> </attribute>
@ -296,11 +296,8 @@
<customwidget> <customwidget>
<class>STableWidget</class> <class>STableWidget</class>
<extends>QTableWidget</extends> <extends>QTableWidget</extends>
<header>bitmessageqt/settingsmixin.h</header> <header>bitmessageqt.settingsmixin</header>
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources>
<include location="bitmessage_icons.qrc"/>
</resources>
<connections/> <connections/>
</ui> </ui>

View File

@ -375,7 +375,7 @@ The 'Random Number' option is selected by default but deterministic addresses ha
<sender>radioButtonDeterministicAddress</sender> <sender>radioButtonDeterministicAddress</sender>
<signal>toggled(bool)</signal> <signal>toggled(bool)</signal>
<receiver>groupBoxDeterministic</receiver> <receiver>groupBoxDeterministic</receiver>
<slot>setShown(bool)</slot> <slot>setVisible(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>92</x> <x>92</x>
@ -391,7 +391,7 @@ The 'Random Number' option is selected by default but deterministic addresses ha
<sender>radioButtonRandomAddress</sender> <sender>radioButtonRandomAddress</sender>
<signal>toggled(bool)</signal> <signal>toggled(bool)</signal>
<receiver>groupBox</receiver> <receiver>groupBox</receiver>
<slot>setShown(bool)</slot> <slot>setVisible(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>72</x> <x>72</x>

View File

@ -1,10 +1,8 @@
""" """
src/bitmessageqt/newchandialog.py NewChanDialog class definition
=================================
""" """
from PyQt4 import QtCore, QtGui from qtpy import QtCore, QtWidgets
import widgets import widgets
from addresses import addBMIfNotPresent from addresses import addBMIfNotPresent
@ -15,30 +13,21 @@ from tr import _translate
from utils import str_chan from utils import str_chan
class NewChanDialog(QtGui.QDialog): class NewChanDialog(QtWidgets.QDialog):
"""The `New Chan` dialog""" """The "New Chan" dialog"""
def __init__(self, parent=None): def __init__(self, parent=None):
super(NewChanDialog, self).__init__(parent) super(NewChanDialog, self).__init__(parent)
widgets.load('newchandialog.ui', self) widgets.load('newchandialog.ui', self)
self.parent = parent self.parent = parent
self.chanAddress.setValidator( self.chanAddress.setValidator(AddressValidator(
AddressValidator( self.chanAddress, self.chanPassPhrase, self.validatorFeedback,
self.chanAddress, self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok), False))
self.chanPassPhrase, self.chanPassPhrase.setValidator(PassPhraseValidator(
self.validatorFeedback, self.chanPassPhrase, self.chanAddress, self.validatorFeedback,
self.buttonBox, self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok), False))
False))
self.chanPassPhrase.setValidator(
PassPhraseValidator(
self.chanPassPhrase,
self.chanAddress,
self.validatorFeedback,
self.buttonBox,
False))
self.timer = QtCore.QTimer() self.timer = QtCore.QTimer()
QtCore.QObject.connect( # pylint: disable=no-member self.timer.timeout.connect(self.delayedUpdateStatus)
self.timer, QtCore.SIGNAL("timeout()"), self.delayedUpdateStatus)
self.timer.start(500) # milliseconds self.timer.start(500) # milliseconds
self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.show() self.show()
@ -52,32 +41,47 @@ class NewChanDialog(QtGui.QDialog):
self.timer.stop() self.timer.stop()
self.hide() self.hide()
apiAddressGeneratorReturnQueue.queue.clear() apiAddressGeneratorReturnQueue.queue.clear()
if self.chanAddress.text().toUtf8() == "": passPhrase = self.chanPassPhrase.text().encode('utf-8')
addressGeneratorQueue.put( if self.chanAddress.text() == "":
('createChan', 4, 1, str_chan + ' ' + str(self.chanPassPhrase.text().toUtf8()), addressGeneratorQueue.put((
self.chanPassPhrase.text().toUtf8(), 'createChan', 4, 1,
True)) str_chan + ' ' + passPhrase, passPhrase, True
))
else: else:
addressGeneratorQueue.put( addressGeneratorQueue.put((
('joinChan', addBMIfNotPresent(self.chanAddress.text().toUtf8()), 'joinChan', addBMIfNotPresent(self.chanAddress.text()),
str_chan + ' ' + str(self.chanPassPhrase.text().toUtf8()), str_chan + ' ' + passPhrase, passPhrase, True
self.chanPassPhrase.text().toUtf8(), ))
True))
addressGeneratorReturnValue = apiAddressGeneratorReturnQueue.get(True) addressGeneratorReturnValue = apiAddressGeneratorReturnQueue.get(True)
if addressGeneratorReturnValue and addressGeneratorReturnValue[0] != 'chan name does not match address': if (
UISignalQueue.put(('updateStatusBar', _translate( len(addressGeneratorReturnValue) > 0
"newchandialog", "Successfully created / joined chan %1").arg(unicode(self.chanPassPhrase.text())))) and addressGeneratorReturnValue[0]
!= 'chan name does not match address'
):
UISignalQueue.put((
'updateStatusBar',
_translate(
"newchandialog",
"Successfully created / joined chan {0}"
).format(passPhrase)
))
self.parent.ui.tabWidget.setCurrentIndex( self.parent.ui.tabWidget.setCurrentIndex(
self.parent.ui.tabWidget.indexOf(self.parent.ui.chans) self.parent.ui.tabWidget.indexOf(self.parent.ui.chans)
) )
self.done(QtGui.QDialog.Accepted) self.done(QtWidgets.QDialog.Accepted)
else: else:
UISignalQueue.put(('updateStatusBar', _translate("newchandialog", "Chan creation / joining failed"))) UISignalQueue.put((
self.done(QtGui.QDialog.Rejected) 'updateStatusBar',
_translate("newchandialog", "Chan creation / joining failed")
))
self.done(QtWidgets.QDialog.Rejected)
def reject(self): def reject(self):
"""Cancel joining the chan""" """Cancel joining the chan"""
self.timer.stop() self.timer.stop()
self.hide() self.hide()
UISignalQueue.put(('updateStatusBar', _translate("newchandialog", "Chan creation / joining cancelled"))) UISignalQueue.put((
self.done(QtGui.QDialog.Rejected) 'updateStatusBar',
_translate("newchandialog", "Chan creation / joining cancelled")
))
self.done(QtWidgets.QDialog.Rejected)

View File

@ -1,18 +1,20 @@
from os import path from qtpy import QtWidgets
from PyQt4 import QtGui
from debug import logger
import widgets import widgets
class RetranslateMixin(object): class RetranslateMixin(object):
def retranslateUi(self): def retranslateUi(self):
defaults = QtGui.QWidget() defaults = QtWidgets.QWidget()
widgets.load(self.__class__.__name__.lower() + '.ui', defaults) widgets.load(self.__class__.__name__.lower() + '.ui', defaults)
for attr, value in defaults.__dict__.iteritems(): for attr, value in defaults.__dict__.iteritems():
setTextMethod = getattr(value, "setText", None) setTextMethod = getattr(value, "setText", None)
if callable(setTextMethod): if callable(setTextMethod):
getattr(self, attr).setText(getattr(defaults, attr).text()) getattr(self, attr).setText(getattr(defaults, attr).text())
elif isinstance(value, QtGui.QTableWidget): elif isinstance(value, QtWidgets.QTableWidget):
for i in range (value.columnCount()): for i in range(value.columnCount()):
getattr(self, attr).horizontalHeaderItem(i).setText(getattr(defaults, attr).horizontalHeaderItem(i).text()) getattr(self, attr).horizontalHeaderItem(i).setText(
for i in range (value.rowCount()): getattr(defaults, attr).horizontalHeaderItem(i).text())
getattr(self, attr).verticalHeaderItem(i).setText(getattr(defaults, attr).verticalHeaderItem(i).text()) for i in range(value.rowCount()):
getattr(self, attr).verticalHeaderItem(i).setText(
getattr(defaults, attr).verticalHeaderItem(i).text())

View File

@ -123,10 +123,6 @@ class SafeHTMLParser(HTMLParser):
self.sanitised += "&" + name + ";" self.sanitised += "&" + name + ";"
def feed(self, data): def feed(self, data):
try:
data = unicode(data, 'utf-8')
except UnicodeDecodeError:
data = unicode(data, 'utf-8', errors='replace')
HTMLParser.feed(self, data) HTMLParser.feed(self, data)
tmp = SafeHTMLParser.replace_pre(data) tmp = SafeHTMLParser.replace_pre(data)
tmp = self.uriregex1.sub(r'<a href="\1">\1</a>', tmp) tmp = self.uriregex1.sub(r'<a href="\1">\1</a>', tmp)

View File

@ -1,12 +1,13 @@
""" """
This module setting file is for settings SettingsDialog class definition
""" """
import ConfigParser import ConfigParser
import os import os
import sys import sys
import tempfile import tempfile
from PyQt4 import QtCore, QtGui from qtpy import QtCore, QtGui, QtWidgets
import debug import debug
import defaults import defaults
@ -37,7 +38,7 @@ def getSOCKSProxyType(config):
return result return result
class SettingsDialog(QtGui.QDialog): class SettingsDialog(QtWidgets.QDialog):
"""The "Settings" dialog""" """The "Settings" dialog"""
def __init__(self, parent=None, firstrun=False): def __init__(self, parent=None, firstrun=False):
super(SettingsDialog, self).__init__(parent) super(SettingsDialog, self).__init__(parent)
@ -71,7 +72,7 @@ class SettingsDialog(QtGui.QDialog):
self.tabWidgetSettings.setCurrentIndex( self.tabWidgetSettings.setCurrentIndex(
self.tabWidgetSettings.indexOf(self.tabNetworkSettings) self.tabWidgetSettings.indexOf(self.tabNetworkSettings)
) )
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) QtWidgets.QWidget.resize(self, QtWidgets.QWidget.sizeHint(self))
def adjust_from_config(self, config): def adjust_from_config(self, config):
"""Adjust all widgets state according to config settings""" """Adjust all widgets state according to config settings"""
@ -283,10 +284,10 @@ class SettingsDialog(QtGui.QDialog):
_translate("MainWindow", "Testing...")) _translate("MainWindow", "Testing..."))
nc = namecoin.namecoinConnection({ nc = namecoin.namecoinConnection({
'type': self.getNamecoinType(), 'type': self.getNamecoinType(),
'host': str(self.lineEditNamecoinHost.text().toUtf8()), 'host': str(self.lineEditNamecoinHost.text()),
'port': str(self.lineEditNamecoinPort.text().toUtf8()), 'port': str(self.lineEditNamecoinPort.text()),
'user': str(self.lineEditNamecoinUser.text().toUtf8()), 'user': str(self.lineEditNamecoinUser.text()),
'password': str(self.lineEditNamecoinPassword.text().toUtf8()) 'password': str(self.lineEditNamecoinPassword.text())
}) })
status, text = nc.test() status, text = nc.test()
self.labelNamecoinTestResult.setText(text) self.labelNamecoinTestResult.setText(text)
@ -319,8 +320,8 @@ class SettingsDialog(QtGui.QDialog):
self.config.set('bitmessagesettings', 'replybelow', str( self.config.set('bitmessagesettings', 'replybelow', str(
self.checkBoxReplyBelow.isChecked())) self.checkBoxReplyBelow.isChecked()))
lang = str(self.languageComboBox.itemData( lang = self.languageComboBox.itemData(
self.languageComboBox.currentIndex()).toString()) self.languageComboBox.currentIndex())
self.config.set('bitmessagesettings', 'userlocale', lang) self.config.set('bitmessagesettings', 'userlocale', lang)
self.parent.change_translation() self.parent.change_translation()
@ -402,7 +403,7 @@ class SettingsDialog(QtGui.QDialog):
self.config.set('bitmessagesettings', 'maxuploadrate', str( self.config.set('bitmessagesettings', 'maxuploadrate', str(
int(float(self.lineEditMaxUploadRate.text())))) int(float(self.lineEditMaxUploadRate.text()))))
except ValueError: except ValueError:
QtGui.QMessageBox.about( QtWidgets.QMessageBox.about(
self, _translate("MainWindow", "Number needed"), self, _translate("MainWindow", "Number needed"),
_translate( _translate(
"MainWindow", "MainWindow",
@ -443,7 +444,7 @@ class SettingsDialog(QtGui.QDialog):
float(self.lineEditSmallMessageDifficulty.text()) float(self.lineEditSmallMessageDifficulty.text())
* defaults.networkDefaultPayloadLengthExtraBytes))) * defaults.networkDefaultPayloadLengthExtraBytes)))
if self.comboBoxOpenCL.currentText().toUtf8() != self.config.safeGet( if self.comboBoxOpenCL.currentText() != self.config.safeGet(
'bitmessagesettings', 'opencl'): 'bitmessagesettings', 'opencl'):
self.config.set( self.config.set(
'bitmessagesettings', 'opencl', 'bitmessagesettings', 'opencl',
@ -457,7 +458,7 @@ class SettingsDialog(QtGui.QDialog):
or float(self.lineEditMaxAcceptableTotalDifficulty.text()) == 0 or float(self.lineEditMaxAcceptableTotalDifficulty.text()) == 0
): ):
if self.config.get( if self.config.get(
'bitmessagesettings', 'maxacceptablenoncetrialsperbyte' 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte'
) != str(int( ) != str(int(
float(self.lineEditMaxAcceptableTotalDifficulty.text()) float(self.lineEditMaxAcceptableTotalDifficulty.text())
* defaults.networkDefaultProofOfWorkNonceTrialsPerByte)): * defaults.networkDefaultProofOfWorkNonceTrialsPerByte)):
@ -474,7 +475,7 @@ class SettingsDialog(QtGui.QDialog):
or float(self.lineEditMaxAcceptableSmallMessageDifficulty.text()) == 0 or float(self.lineEditMaxAcceptableSmallMessageDifficulty.text()) == 0
): ):
if self.config.get( if self.config.get(
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes' 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes'
) != str(int( ) != str(int(
float(self.lineEditMaxAcceptableSmallMessageDifficulty.text()) float(self.lineEditMaxAcceptableSmallMessageDifficulty.text())
* defaults.networkDefaultPayloadLengthExtraBytes)): * defaults.networkDefaultPayloadLengthExtraBytes)):
@ -526,7 +527,7 @@ class SettingsDialog(QtGui.QDialog):
if state.maximumLengthOfTimeToBotherResendingMessages < 432000: if state.maximumLengthOfTimeToBotherResendingMessages < 432000:
# If the time period is less than 5 hours, we give # If the time period is less than 5 hours, we give
# zero values to all fields. No message will be sent again. # zero values to all fields. No message will be sent again.
QtGui.QMessageBox.about( QtWidgets.QMessageBox.about(
self, self,
_translate("MainWindow", "Will not resend ever"), _translate("MainWindow", "Will not resend ever"),
_translate( _translate(

View File

@ -1086,9 +1086,6 @@
<tabstop>checkBoxSocksListen</tabstop> <tabstop>checkBoxSocksListen</tabstop>
<tabstop>buttonBox</tabstop> <tabstop>buttonBox</tabstop>
</tabstops> </tabstops>
<resources>
<include location="bitmessage_icons.qrc"/>
</resources>
<connections> <connections>
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>

View File

@ -1,15 +1,15 @@
#!/usr/bin/python2.7
""" """
src/settingsmixin.py src/settingsmixin.py
==================== ====================
""" """
from PyQt4 import QtCore, QtGui from qtpy import QtCore, QtWidgets
class SettingsMixin(object): class SettingsMixin(object):
"""Mixin for adding geometry and state saving between restarts.""" """Mixin for adding geometry and state saving between restarts"""
def warnIfNoObjectName(self): def warnIfNoObjectName(self):
""" """
Handle objects which don't have a name. Currently it ignores them. Objects without a name can't have their Handle objects which don't have a name. Currently it ignores them. Objects without a name can't have their
@ -40,8 +40,9 @@ class SettingsMixin(object):
self.warnIfNoObjectName() self.warnIfNoObjectName()
settings = QtCore.QSettings() settings = QtCore.QSettings()
try: try:
geom = settings.value("/".join([str(self.objectName()), "geometry"])) geom = settings.value(
target.restoreGeometry(geom.toByteArray() if hasattr(geom, 'toByteArray') else geom) "/".join([str(self.objectName()), "geometry"]))
target.restoreGeometry(geom)
except Exception: except Exception:
pass pass
@ -51,13 +52,14 @@ class SettingsMixin(object):
settings = QtCore.QSettings() settings = QtCore.QSettings()
try: try:
state = settings.value("/".join([str(self.objectName()), "state"])) state = settings.value("/".join([str(self.objectName()), "state"]))
target.restoreState(state.toByteArray() if hasattr(state, 'toByteArray') else state) target.restoreState(state)
except Exception: except Exception:
pass pass
class SMainWindow(QtGui.QMainWindow, SettingsMixin): class SMainWindow(QtWidgets.QMainWindow, SettingsMixin):
"""Main window with Settings functionality.""" """Main window with Settings functionality"""
def loadSettings(self): def loadSettings(self):
"""Load main window settings.""" """Load main window settings."""
self.readGeometry(self) self.readGeometry(self)
@ -69,9 +71,9 @@ class SMainWindow(QtGui.QMainWindow, SettingsMixin):
self.writeGeometry(self) self.writeGeometry(self)
class STableWidget(QtGui.QTableWidget, SettingsMixin): class STableWidget(QtWidgets.QTableWidget, SettingsMixin):
"""Table widget with Settings functionality""" """Table widget with Settings functionality"""
# pylint: disable=too-many-ancestors
def loadSettings(self): def loadSettings(self):
"""Load table settings.""" """Load table settings."""
self.readState(self.horizontalHeader()) self.readState(self.horizontalHeader())
@ -81,8 +83,9 @@ class STableWidget(QtGui.QTableWidget, SettingsMixin):
self.writeState(self.horizontalHeader()) self.writeState(self.horizontalHeader())
class SSplitter(QtGui.QSplitter, SettingsMixin): class SSplitter(QtWidgets.QSplitter, SettingsMixin):
"""Splitter with Settings functionality.""" """Splitter with Settings functionality"""
def loadSettings(self): def loadSettings(self):
"""Load splitter settings""" """Load splitter settings"""
self.readState(self) self.readState(self)
@ -92,17 +95,17 @@ class SSplitter(QtGui.QSplitter, SettingsMixin):
self.writeState(self) self.writeState(self)
class STreeWidget(QtGui.QTreeWidget, SettingsMixin): class STreeWidget(QtWidgets.QTreeWidget, SettingsMixin):
"""Tree widget with settings functionality.""" """Tree widget with settings functionality"""
# pylint: disable=too-many-ancestors
def loadSettings(self): def loadSettings(self):
"""Load tree settings.""" """Load tree settings. Unimplemented."""
# recurse children # recurse children
# self.readState(self) # self.readState(self)
pass pass
def saveSettings(self): def saveSettings(self):
"""Save tree settings""" """Save tree settings. Unimplemented."""
# recurse children # recurse children
# self.writeState(self) # self.writeState(self)
pass pass

View File

@ -1,11 +1,11 @@
# pylint: disable=unused-argument """BMStatusBar class definition"""
"""Status bar Module"""
from time import time from time import time
from PyQt4 import QtGui
from qtpy import QtWidgets
class BMStatusBar(QtGui.QStatusBar): class BMStatusBar(QtWidgets.QStatusBar):
"""Status bar with queue and priorities""" """Status bar with queue and priorities"""
duration = 10000 duration = 10000
deleteAfter = 60 deleteAfter = 60
@ -16,21 +16,24 @@ class BMStatusBar(QtGui.QStatusBar):
self.timer = self.startTimer(BMStatusBar.duration) self.timer = self.startTimer(BMStatusBar.duration)
self.iterator = 0 self.iterator = 0
def timerEvent(self, event): def timerEvent(self, event): # pylint: disable=unused-argument
"""an event handler which allows to queue and prioritise messages to """an event handler which allows to queue and prioritise messages to
show in the status bar, for example if many messages come very quickly show in the status bar, for example if many messages come very quickly
after one another, it adds delays and so on""" after one another, it adds delays and so on"""
while len(self.important) > 0: while len(self.important) > 0:
self.iterator += 1 self.iterator += 1
try: try:
if time() > self.important[self.iterator][1] + BMStatusBar.deleteAfter: if (
self.important[self.iterator][1]
+ BMStatusBar.deleteAfter < time()
):
del self.important[self.iterator] del self.important[self.iterator]
self.iterator -= 1 self.iterator -= 1
continue continue
except IndexError: except IndexError:
self.iterator = -1 self.iterator = -1
continue continue
super(BMStatusBar, self).showMessage(self.important[self.iterator][0], 0) self.showMessage(self.important[self.iterator][0], 0)
break break
def addImportant(self, message): def addImportant(self, message):

View File

@ -1,13 +1,11 @@
"""Composing support request message functions.""" """Composing support request message functions."""
# pylint: disable=no-member
import ctypes import ctypes
import os
import ssl import ssl
import sys import sys
import time import time
from PyQt4 import QtCore
import account import account
import defaults import defaults
import network.stats import network.stats
@ -22,8 +20,8 @@ from l10n import getTranslationLanguage
from openclpow import openclEnabled from openclpow import openclEnabled
from pyelliptic.openssl import OpenSSL from pyelliptic.openssl import OpenSSL
from settings import getSOCKSProxyType from settings import getSOCKSProxyType
from version import softwareVersion
from tr import _translate from tr import _translate
from version import softwareVersion
# this is BM support address going to Peter Surda # this is BM support address going to Peter Surda
@ -31,7 +29,7 @@ OLD_SUPPORT_ADDRESS = 'BM-2cTkCtMYkrSPwFTpgcBrMrf5d8oZwvMZWK'
SUPPORT_ADDRESS = 'BM-2cUdgkDDAahwPAU6oD2A7DnjqZz3hgY832' SUPPORT_ADDRESS = 'BM-2cUdgkDDAahwPAU6oD2A7DnjqZz3hgY832'
SUPPORT_LABEL = _translate("Support", "PyBitmessage support") SUPPORT_LABEL = _translate("Support", "PyBitmessage support")
SUPPORT_MY_LABEL = _translate("Support", "My new address") SUPPORT_MY_LABEL = _translate("Support", "My new address")
SUPPORT_SUBJECT = 'Support request' SUPPORT_SUBJECT = _translate("Support", "Support request")
SUPPORT_MESSAGE = _translate("Support", ''' SUPPORT_MESSAGE = _translate("Support", '''
You can use this message to send a report to one of the PyBitmessage core \ You can use this message to send a report to one of the PyBitmessage core \
developers regarding PyBitmessage or the mailchuck.com email service. \ developers regarding PyBitmessage or the mailchuck.com email service. \
@ -55,6 +53,7 @@ Operating system: {}
Architecture: {}bit Architecture: {}bit
Python Version: {} Python Version: {}
OpenSSL Version: {} OpenSSL Version: {}
Qt API: {}
Frozen: {} Frozen: {}
Portable mode: {} Portable mode: {}
C PoW: {} C PoW: {}
@ -67,28 +66,35 @@ Connected hosts: {}
def checkAddressBook(myapp): def checkAddressBook(myapp):
"""
Add "PyBitmessage support" address to address book, remove old one if found.
"""
sqlExecute('DELETE from addressbook WHERE address=?', OLD_SUPPORT_ADDRESS) sqlExecute('DELETE from addressbook WHERE address=?', OLD_SUPPORT_ADDRESS)
queryreturn = sqlQuery('SELECT * FROM addressbook WHERE address=?', SUPPORT_ADDRESS) queryreturn = sqlQuery(
'SELECT * FROM addressbook WHERE address=?', SUPPORT_ADDRESS)
if queryreturn == []: if queryreturn == []:
sqlExecute( sqlExecute(
'INSERT INTO addressbook VALUES (?,?)', 'INSERT INTO addressbook VALUES (?,?)',
SUPPORT_LABEL.toUtf8(), SUPPORT_ADDRESS) SUPPORT_LABEL.encode('utf-8'), SUPPORT_ADDRESS)
myapp.rerenderAddressBook() myapp.rerenderAddressBook()
def checkHasNormalAddress(): def checkHasNormalAddress():
"""Returns first enabled normal address or False if not found."""
for address in account.getSortedAccounts(): for address in account.getSortedAccounts():
acct = account.accountClass(address) acct = account.accountClass(address)
if acct.type == AccountMixin.NORMAL and BMConfigParser().safeGetBoolean(address, 'enabled'): if acct.type == AccountMixin.NORMAL and BMConfigParser().safeGetBoolean(
address, 'enabled'):
return address return address
return False return False
def createAddressIfNeeded(myapp): def createAddressIfNeeded(myapp):
"""Checks if user has any anabled normal address, creates new one if no."""
if not checkHasNormalAddress(): if not checkHasNormalAddress():
queues.addressGeneratorQueue.put(( queues.addressGeneratorQueue.put((
'createRandomAddress', 4, 1, 'createRandomAddress', 4, 1,
str(SUPPORT_MY_LABEL.toUtf8()), SUPPORT_MY_LABEL.encode('utf-8'),
1, "", False, 1, "", False,
defaults.networkDefaultProofOfWorkNonceTrialsPerByte, defaults.networkDefaultProofOfWorkNonceTrialsPerByte,
defaults.networkDefaultPayloadLengthExtraBytes defaults.networkDefaultPayloadLengthExtraBytes
@ -100,15 +106,20 @@ def createAddressIfNeeded(myapp):
def createSupportMessage(myapp): def createSupportMessage(myapp):
"""
Prepare the support request message and switch to tab "Send"
"""
checkAddressBook(myapp) checkAddressBook(myapp)
address = createAddressIfNeeded(myapp) address = createAddressIfNeeded(myapp)
if state.shutdown: if state.shutdown:
return return
myapp.ui.lineEditSubject.setText(SUPPORT_SUBJECT) myapp.ui.lineEditSubject.setText(SUPPORT_SUBJECT)
addrIndex = myapp.ui.comboBoxSendFrom.findData( # addrIndex = myapp.ui.comboBoxSendFrom.findData(
address, QtCore.Qt.UserRole, # address, QtCore.Qt.UserRole,
QtCore.Qt.MatchFixedString | QtCore.Qt.MatchCaseSensitive) # QtCore.Qt.MatchFixedString | QtCore.Qt.MatchCaseSensitive
# )
addrIndex = myapp.ui.comboBoxSendFrom.findData(address)
if addrIndex == -1: # something is very wrong if addrIndex == -1: # something is very wrong
return return
myapp.ui.comboBoxSendFrom.setCurrentIndex(addrIndex) myapp.ui.comboBoxSendFrom.setCurrentIndex(addrIndex)
@ -119,15 +130,13 @@ def createSupportMessage(myapp):
if commit: if commit:
version += " GIT " + commit version += " GIT " + commit
os = sys.platform if sys.platform.startswith("win"):
if os == "win32": # pylint: disable=no-member
windowsversion = sys.getwindowsversion() osname = "Windows %s.%s" % sys.getwindowsversion()[:2]
os = "Windows " + str(windowsversion[0]) + "." + str(windowsversion[1])
else: else:
try: try:
from os import uname unixversion = os.uname()
unixversion = uname() osname = unixversion[0] + " " + unixversion[2]
os = unixversion[0] + " " + unixversion[2]
except: except:
pass pass
architecture = "32" if ctypes.sizeof(ctypes.c_voidp) == 4 else "64" architecture = "32" if ctypes.sizeof(ctypes.c_voidp) == 4 else "64"
@ -136,22 +145,26 @@ def createSupportMessage(myapp):
opensslversion = "%s (Python internal), %s (external for PyElliptic)" % ( opensslversion = "%s (Python internal), %s (external for PyElliptic)" % (
ssl.OPENSSL_VERSION, OpenSSL._version) ssl.OPENSSL_VERSION, OpenSSL._version)
qtapi = os.environ.get('QT_API', 'fallback')
frozen = "N/A" frozen = "N/A"
if paths.frozen: if paths.frozen:
frozen = paths.frozen frozen = paths.frozen
portablemode = "True" if state.appdata == paths.lookupExeFolder() else "False" portablemode = str(state.appdata == paths.lookupExeFolder())
cpow = "True" if proofofwork.bmpow else "False" cpow = "True" if proofofwork.bmpow else "False"
openclpow = str( openclpow = str(
BMConfigParser().safeGet('bitmessagesettings', 'opencl') BMConfigParser().safeGet('bitmessagesettings', 'opencl')
) if openclEnabled() else "None" ) if openclEnabled() else "None"
locale = getTranslationLanguage() locale = getTranslationLanguage()
socks = getSOCKSProxyType(BMConfigParser()) or "N/A" socks = getSOCKSProxyType(BMConfigParser()) or 'N/A'
upnp = BMConfigParser().safeGet('bitmessagesettings', 'upnp', "N/A") upnp = BMConfigParser().safeGet('bitmessagesettings', 'upnp', 'N/A')
connectedhosts = len(network.stats.connectedHostsList()) connectedhosts = len(network.stats.connectedHostsList())
myapp.ui.textEditMessage.setText(unicode(SUPPORT_MESSAGE, 'utf-8').format( myapp.ui.textEditMessage.setText(SUPPORT_MESSAGE.format(
version, os, architecture, pythonversion, opensslversion, frozen, version, osname, architecture, pythonversion, opensslversion, qtapi,
portablemode, cpow, openclpow, locale, socks, upnp, connectedhosts)) frozen, portablemode, cpow, openclpow, locale, socks, upnp,
connectedhosts
))
# single msg tab # single msg tab
myapp.ui.tabWidgetSend.setCurrentIndex( myapp.ui.tabWidgetSend.setCurrentIndex(

View File

@ -4,7 +4,7 @@ import Queue
import sys import sys
import unittest import unittest
from PyQt4 import QtCore, QtGui from qtpy import QtCore, QtWidgets
import bitmessageqt import bitmessageqt
import queues import queues
@ -16,7 +16,7 @@ class TestBase(unittest.TestCase):
def setUp(self): def setUp(self):
self.app = ( self.app = (
QtGui.QApplication.instance() QtWidgets.QApplication.instance()
or bitmessageqt.BitmessageQtApplication(sys.argv)) or bitmessageqt.BitmessageQtApplication(sys.argv))
self.window = self.app.activeWindow() self.window = self.app.activeWindow()
if not self.window: if not self.window:
@ -41,7 +41,7 @@ class TestMain(unittest.TestCase):
"""Check the results of _translate() with various args""" """Check the results of _translate() with various args"""
self.assertIsInstance( self.assertIsInstance(
_translate("MainWindow", "Test"), _translate("MainWindow", "Test"),
QtCore.QString unicode
) )

View File

@ -1,15 +1,34 @@
from qtpy import QtCore
from PyQt4.QtCore import QThread, SIGNAL
import sys import sys
import queues import queues
from network.node import Peer
class UISignaler(QThread): class UISignaler(QtCore.QThread):
_instance = None _instance = None
def __init__(self, parent=None): writeNewAddressToTable = QtCore.Signal(str, str, str)
QThread.__init__(self, parent) updateStatusBar = QtCore.Signal(object)
updateSentItemStatusByToAddress = QtCore.Signal(object, str)
updateSentItemStatusByAckdata = QtCore.Signal(object, str)
displayNewInboxMessage = QtCore.Signal(object, str, object, object, str)
displayNewSentMessage = QtCore.Signal(
object, str, str, object, object, str)
updateNetworkStatusTab = QtCore.Signal(bool, bool, Peer)
updateNumberOfMessagesProcessed = QtCore.Signal()
updateNumberOfPubkeysProcessed = QtCore.Signal()
updateNumberOfBroadcastsProcessed = QtCore.Signal()
setStatusIcon = QtCore.Signal(str)
changedInboxUnread = QtCore.Signal(str)
rerenderMessagelistFromLabels = QtCore.Signal()
rerenderMessagelistToLabels = QtCore.Signal()
rerenderAddressBook = QtCore.Signal()
rerenderSubscriptions = QtCore.Signal()
rerenderBlackWhiteList = QtCore.Signal()
removeInboxRowByMsgid = QtCore.Signal(str)
newVersionAvailable = QtCore.Signal(str)
displayAlert = QtCore.Signal(str, str, bool)
@classmethod @classmethod
def get(cls): def get(cls):
@ -22,58 +41,59 @@ class UISignaler(QThread):
command, data = queues.UISignalQueue.get() command, data = queues.UISignalQueue.get()
if command == 'writeNewAddressToTable': if command == 'writeNewAddressToTable':
label, address, streamNumber = data label, address, streamNumber = data
self.emit(SIGNAL( self.writeNewAddressToTable.emit(
"writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), label, address, str(streamNumber)) label, address, str(streamNumber))
elif command == 'updateStatusBar': elif command == 'updateStatusBar':
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"), data) self.updateStatusBar.emit(data)
elif command == 'updateSentItemStatusByToAddress': elif command == 'updateSentItemStatusByToAddress':
toAddress, message = data toAddress, message = data
self.emit(SIGNAL( self.updateSentItemStatusByToAddress.emit(toAddress, message)
"updateSentItemStatusByToAddress(PyQt_PyObject,PyQt_PyObject)"), toAddress, message)
elif command == 'updateSentItemStatusByAckdata': elif command == 'updateSentItemStatusByAckdata':
ackData, message = data ackData, message = data
self.emit(SIGNAL( self.updateSentItemStatusByAckdata.emit(ackData, message)
"updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), ackData, message)
elif command == 'displayNewInboxMessage': elif command == 'displayNewInboxMessage':
inventoryHash, toAddress, fromAddress, subject, body = data inventoryHash, toAddress, fromAddress, subject, body = data
self.emit(SIGNAL(
"displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewInboxMessage.emit(
inventoryHash, toAddress, fromAddress, subject, body) inventoryHash, toAddress, fromAddress,
subject, body)
elif command == 'displayNewSentMessage': elif command == 'displayNewSentMessage':
toAddress, fromLabel, fromAddress, subject, message, ackdata = data toAddress, fromLabel, fromAddress, subject, message, ackdata = data
self.emit(SIGNAL( self.displayNewSentMessage.emit(
"displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), toAddress, fromLabel, fromAddress,
toAddress, fromLabel, fromAddress, subject, message, ackdata) unicode(subject, 'utf-8'), message, ackdata)
elif command == 'updateNetworkStatusTab': elif command == 'updateNetworkStatusTab':
outbound, add, destination = data outbound, add, destination = data
self.emit(SIGNAL("updateNetworkStatusTab(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), outbound, add, destination) self.updateNetworkStatusTab.emit(outbound, add, destination)
elif command == 'updateNumberOfMessagesProcessed': elif command == 'updateNumberOfMessagesProcessed':
self.emit(SIGNAL("updateNumberOfMessagesProcessed()")) self.updateNumberOfMessagesProcessed.emit()
elif command == 'updateNumberOfPubkeysProcessed': elif command == 'updateNumberOfPubkeysProcessed':
self.emit(SIGNAL("updateNumberOfPubkeysProcessed()")) self.updateNumberOfPubkeysProcessed.emit()
elif command == 'updateNumberOfBroadcastsProcessed': elif command == 'updateNumberOfBroadcastsProcessed':
self.emit(SIGNAL("updateNumberOfBroadcastsProcessed()")) self.updateNumberOfBroadcastsProcessed.emit()
elif command == 'setStatusIcon': elif command == 'setStatusIcon':
self.emit(SIGNAL("setStatusIcon(PyQt_PyObject)"), data) self.setStatusIcon.emit(data)
elif command == 'changedInboxUnread': elif command == 'changedInboxUnread':
self.emit(SIGNAL("changedInboxUnread(PyQt_PyObject)"), data) self.changedInboxUnread.emit(data)
elif command == 'rerenderMessagelistFromLabels': elif command == 'rerenderMessagelistFromLabels':
self.emit(SIGNAL("rerenderMessagelistFromLabels()")) self.rerenderMessagelistFromLabels.emit()
elif command == 'rerenderMessagelistToLabels': elif command == 'rerenderMessagelistToLabels':
self.emit(SIGNAL("rerenderMessagelistToLabels()")) self.rerenderMessagelistToLabels.emit()
elif command == 'rerenderAddressBook': elif command == 'rerenderAddressBook':
self.emit(SIGNAL("rerenderAddressBook()")) self.rerenderAddressBook.emit()
elif command == 'rerenderSubscriptions': elif command == 'rerenderSubscriptions':
self.emit(SIGNAL("rerenderSubscriptions()")) self.rerenderSubscriptions.emit()
elif command == 'rerenderBlackWhiteList': elif command == 'rerenderBlackWhiteList':
self.emit(SIGNAL("rerenderBlackWhiteList()")) self.rerenderBlackWhiteList.emit()
elif command == 'removeInboxRowByMsgid': elif command == 'removeInboxRowByMsgid':
self.emit(SIGNAL("removeInboxRowByMsgid(PyQt_PyObject)"), data) self.removeInboxRowByMsgid.emit(data)
elif command == 'newVersionAvailable': elif command == 'newVersionAvailable':
self.emit(SIGNAL("newVersionAvailable(PyQt_PyObject)"), data) self.newVersionAvailable.emit(data)
elif command == 'alert': elif command == 'alert':
title, text, exitAfterUserClicksOk = data title, text, exitAfterUserClicksOk = data
self.emit(SIGNAL("displayAlert(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)"), title, text, exitAfterUserClicksOk) self.displayAlert.emit(title, text, exitAfterUserClicksOk)
else: else:
sys.stderr.write( sys.stderr.write(
'Command sent to UISignaler not recognized: %s\n' % command) 'Command sent to UISignaler not recognized: %s\n'
% command
)

View File

@ -1,7 +1,7 @@
import hashlib import hashlib
import os import os
from PyQt4 import QtGui from qtpy import QtGui
import state import state
from addresses import addBMIfNotPresent from addresses import addBMIfNotPresent
@ -30,16 +30,17 @@ def identiconize(address):
# It can be used as a pseudo-password to salt the generation of # It can be used as a pseudo-password to salt the generation of
# the identicons to decrease the risk of attacks where someone creates # the identicons to decrease the risk of attacks where someone creates
# an address to mimic someone else's identicon. # an address to mimic someone else's identicon.
identiconsuffix = BMConfigParser().get('bitmessagesettings', 'identiconsuffix') data = addBMIfNotPresent(address) + BMConfigParser().get(
'bitmessagesettings', 'identiconsuffix')
if identicon_lib[:len('qidenticon')] == 'qidenticon': if identicon_lib[:len('qidenticon')] == 'qidenticon':
# originally by: # originally by:
# :Author:Shin Adachi <shn@glucose.jp> # :Author:Shin Adachi <shn@glucose.jp>
# Licesensed under FreeBSD License. # Licesensed under FreeBSD License.
# stripped from PIL and uses QT instead (by sendiulo, same license) # stripped from PIL and uses QT instead (by sendiulo, same license)
import qidenticon import qidenticon
icon_hash = hashlib.md5( icon_hash = hashlib.md5(data).hexdigest()
addBMIfNotPresent(address) + identiconsuffix).hexdigest() use_two_colors = (
use_two_colors = identicon_lib[:len('qidenticon_two')] == 'qidenticon_two' identicon_lib[:len('qidenticon_two')] == 'qidenticon_two')
opacity = int( opacity = int(
identicon_lib not in ( identicon_lib not in (
'qidenticon_x', 'qidenticon_two_x', 'qidenticon_x', 'qidenticon_two_x',
@ -63,8 +64,7 @@ def identiconize(address):
# https://github.com/azaghal/pydenticon # https://github.com/azaghal/pydenticon
# note that it requires pillow (or PIL) to be installed: # note that it requires pillow (or PIL) to be installed:
# https://python-pillow.org/ # https://python-pillow.org/
idcon_render = Pydenticon( idcon_render = Pydenticon(data, size * 3)
addBMIfNotPresent(address) + identiconsuffix, size * 3)
rendering = idcon_render._render() rendering = idcon_render._render()
data = rendering.convert("RGBA").tostring("raw", "RGBA") data = rendering.convert("RGBA").tostring("raw", "RGBA")
qim = QtGui.QImage(data, size, size, QtGui.QImage.Format_ARGB32) qim = QtGui.QImage(data, size, size, QtGui.QImage.Format_ARGB32)
@ -105,11 +105,9 @@ def avatarize(address):
lower_default = state.appdata + 'avatars/' + 'default.' + ext.lower() lower_default = state.appdata + 'avatars/' + 'default.' + ext.lower()
upper_default = state.appdata + 'avatars/' + 'default.' + ext.upper() upper_default = state.appdata + 'avatars/' + 'default.' + ext.upper()
if os.path.isfile(lower_default): if os.path.isfile(lower_default):
default = lower_default
idcon.addFile(lower_default) idcon.addFile(lower_default)
return idcon return idcon
elif os.path.isfile(upper_default): elif os.path.isfile(upper_default):
default = upper_default
idcon.addFile(upper_default) idcon.addFile(upper_default)
return idcon return idcon
# If no avatar is found # If no avatar is found

View File

@ -1,13 +1,15 @@
from PyQt4 import uic from qtpy import uic
import os.path import os.path
import paths import paths
import sys
def resource_path(resFile): def resource_path(resFile):
baseDir = paths.codePath() baseDir = paths.codePath()
for subDir in ["ui", "bitmessageqt"]: for subDir in ("ui", "bitmessageqt"):
if os.path.isdir(os.path.join(baseDir, subDir)) and os.path.isfile(os.path.join(baseDir, subDir, resFile)): path = os.path.join(baseDir, subDir, resFile)
return os.path.join(baseDir, subDir, resFile) if os.path.isfile(path):
return path
def load(resFile, widget): def load(resFile, widget):
uic.loadUi(resource_path(resFile), widget) uic.loadUi(resource_path(resFile), widget)

View File

@ -1,5 +1,5 @@
""" """
A thread for creating addresses addressGenerator thread class definition
""" """
import hashlib import hashlib
import time import time
@ -214,10 +214,11 @@ class addressGenerator(StoppableThread):
queues.workerQueue.put(( queues.workerQueue.put((
'sendOutOrStoreMyV4Pubkey', address)) 'sendOutOrStoreMyV4Pubkey', address))
elif command == 'createDeterministicAddresses' \ elif command in (
or command == 'getDeterministicAddress' \ 'createDeterministicAddresses',
or command == 'createChan' or command == 'joinChan': 'getDeterministicAddress', 'createChan', 'joinChan'
if not deterministicPassphrase: ):
if len(deterministicPassphrase) == 0:
self.logger.warning( self.logger.warning(
'You are creating deterministic' 'You are creating deterministic'
' address(es) using a blank passphrase.' ' address(es) using a blank passphrase.'
@ -226,9 +227,8 @@ class addressGenerator(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateStatusBar', 'updateStatusBar',
tr._translate( tr._translate(
"MainWindow", "MainWindow", "Generating {0} new addresses."
"Generating %1 new addresses." ).format(str(numberOfAddressesToMake))
).arg(str(numberOfAddressesToMake))
)) ))
signingKeyNonce = 0 signingKeyNonce = 0
encryptionKeyNonce = 1 encryptionKeyNonce = 1
@ -332,17 +332,16 @@ class addressGenerator(StoppableThread):
'updateStatusBar', 'updateStatusBar',
tr._translate( tr._translate(
"MainWindow", "MainWindow",
"%1 is already in 'Your Identities'." "{0} is already in 'Your Identities'."
" Not adding it again." " Not adding it again."
).arg(address) ).format(address)
)) ))
else: else:
self.logger.debug('label: %s', label) self.logger.debug('label: %s', label)
BMConfigParser().set(address, 'label', label) BMConfigParser().set(address, 'label', label)
BMConfigParser().set(address, 'enabled', 'true') BMConfigParser().set(address, 'enabled', 'true')
BMConfigParser().set(address, 'decoy', 'false') BMConfigParser().set(address, 'decoy', 'false')
if command == 'joinChan' \ if command in ('joinChan', 'createChan'):
or command == 'createChan':
BMConfigParser().set(address, 'chan', 'true') BMConfigParser().set(address, 'chan', 'true')
BMConfigParser().set( BMConfigParser().set(
address, 'noncetrialsperbyte', address, 'noncetrialsperbyte',
@ -393,8 +392,10 @@ class addressGenerator(StoppableThread):
address) address)
# Done generating addresses. # Done generating addresses.
if command == 'createDeterministicAddresses' \ if command in (
or command == 'joinChan' or command == 'createChan': 'createDeterministicAddresses',
'joinChan', 'createChan'
):
queues.apiAddressGeneratorReturnQueue.put( queues.apiAddressGeneratorReturnQueue.put(
listOfNewAddressesToSendOutThroughTheAPI) listOfNewAddressesToSendOutThroughTheAPI)
elif command == 'getDeterministicAddress': elif command == 'getDeterministicAddress':

View File

@ -147,14 +147,11 @@ class objectProcessor(threading.Thread):
' WHERE ackdata=?', ' WHERE ackdata=?',
'ackreceived', int(time.time()), data[readPosition:]) 'ackreceived', int(time.time()), data[readPosition:])
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', 'updateSentItemStatusByAckdata', (
( data[readPosition:], tr._translate(
data[readPosition:],
tr._translate(
"MainWindow", "MainWindow",
"Acknowledgement of the message received %1" "Acknowledgement of the message received {0}"
).arg(l10n.formatTimestamp()) ).format(l10n.formatTimestamp()))
)
)) ))
else: else:
logger.debug('This object is not an acknowledgement bound for me.') logger.debug('This object is not an acknowledgement bound for me.')

View File

@ -24,14 +24,13 @@ import protocol
import queues import queues
import shared import shared
import state import state
import tr
from addresses import ( from addresses import (
calculateInventoryHash, decodeAddress, decodeVarint, encodeVarint calculateInventoryHash, decodeAddress, decodeVarint, encodeVarint)
)
from bmconfigparser import BMConfigParser from bmconfigparser import BMConfigParser
from helper_sql import sqlExecute, sqlQuery from helper_sql import sqlExecute, sqlQuery
from inventory import Inventory from inventory import Inventory
from network import knownnodes, StoppableThread from network import knownnodes, StoppableThread
from tr import _translate
def sizeof_fmt(num, suffix='h/s'): def sizeof_fmt(num, suffix='h/s'):
@ -215,9 +214,8 @@ class singleWorker(StoppableThread):
return privSigningKeyHex, privEncryptionKeyHex, \ return privSigningKeyHex, privEncryptionKeyHex, \
pubSigningKey, pubEncryptionKey pubSigningKey, pubEncryptionKey
def _doPOWDefaults(self, payload, TTL, def _doPOWDefaults(
log_prefix='', self, payload, TTL, log_prefix='', log_time=False):
log_time=False):
target = 2 ** 64 / ( target = 2 ** 64 / (
defaults.networkDefaultProofOfWorkNonceTrialsPerByte * ( defaults.networkDefaultProofOfWorkNonceTrialsPerByte * (
len(payload) + 8 + len(payload) + 8 +
@ -243,14 +241,16 @@ class singleWorker(StoppableThread):
'PoW took %.1f seconds, speed %s.', 'PoW took %.1f seconds, speed %s.',
delta, sizeof_fmt(nonce / delta) delta, sizeof_fmt(nonce / delta)
) )
except: # NameError except NameError:
pass pass
payload = pack('>Q', nonce) + payload payload = pack('>Q', nonce) + payload
return payload return payload
def doPOWForMyV2Pubkey(self, adressHash): def doPOWForMyV2Pubkey(self, adressHash):
""" This function also broadcasts out the pubkey """
message once it is done with the POW""" This function also broadcasts out the pubkey message once it is
done with the POW
"""
# Look up my stream number based on my address hash # Look up my stream number based on my address hash
myAddress = shared.myAddressesByHash[adressHash] myAddress = shared.myAddressesByHash[adressHash]
# status # status
@ -306,13 +306,14 @@ class singleWorker(StoppableThread):
def sendOutOrStoreMyV3Pubkey(self, adressHash): def sendOutOrStoreMyV3Pubkey(self, adressHash):
""" """
If this isn't a chan address, this function assembles the pubkey data, does the necessary POW and sends it out. If this isn't a chan address, this function assembles the pubkey
If it *is* a chan then it assembles the pubkey and stores is in the pubkey table so that we can send messages data, does the necessary POW and sends it out.
to "ourselves". If it *is* a chan then it assembles the pubkey and stores it in
the pubkey table so that we can send messages to "ourselves".
""" """
try: try:
myAddress = shared.myAddressesByHash[adressHash] myAddress = shared.myAddressesByHash[adressHash]
except: except KeyError:
# The address has been deleted. # The address has been deleted.
return return
if BMConfigParser().safeGetBoolean(myAddress, 'chan'): if BMConfigParser().safeGetBoolean(myAddress, 'chan'):
@ -389,9 +390,10 @@ class singleWorker(StoppableThread):
def sendOutOrStoreMyV4Pubkey(self, myAddress): def sendOutOrStoreMyV4Pubkey(self, myAddress):
""" """
It doesn't send directly anymore. It put is to a queue for another thread to send at an appropriate time, It doesn't send directly anymore. It put is to a queue for
whereas in the past it directly appended it to the outgoing buffer, I think. Same with all the other methods in another thread to send at an appropriate time, whereas in the
this class. past it directly appended it to the outgoing buffer, I think.
Same with all the other methods in this class.
""" """
if not BMConfigParser().has_section(myAddress): if not BMConfigParser().has_section(myAddress):
# The address has been deleted. # The address has been deleted.
@ -518,7 +520,10 @@ class singleWorker(StoppableThread):
queues.invQueue.put((streamNumber, inventoryHash)) queues.invQueue.put((streamNumber, inventoryHash))
def sendBroadcast(self): def sendBroadcast(self):
"""Send a broadcast-type object (assemble the object, perform PoW and put it to the inv announcement queue)""" """
Send a broadcast-type object (assemble the object, perform PoW
and put it to the inv announcement queue)
"""
# Reset just in case # Reset just in case
sqlExecute( sqlExecute(
'''UPDATE sent SET status='broadcastqueued' ''' '''UPDATE sent SET status='broadcastqueued' '''
@ -549,8 +554,7 @@ class singleWorker(StoppableThread):
except: except:
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Error! Could not find sender address" "Error! Could not find sender address"
" (your address) in the keys.dat file.")) " (your address) in the keys.dat file."))
@ -640,8 +644,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Doing work necessary to send broadcast...")) "Doing work necessary to send broadcast..."))
)) ))
@ -673,11 +676,9 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata, _translate(
tr._translate( "MainWindow", "Broadcast sent on {0}"
"MainWindow", ).format(l10n.formatTimestamp()))
"Broadcast sent on %1"
).arg(l10n.formatTimestamp()))
)) ))
# Update the status of the message in the 'sent' table to have # Update the status of the message in the 'sent' table to have
@ -689,7 +690,10 @@ class singleWorker(StoppableThread):
) )
def sendMsg(self): def sendMsg(self):
"""Send a message-type object (assemble the object, perform PoW and put it to the inv announcement queue)""" """
Send a message-type object (assemble the object, perform PoW
and put it to the inv announcement queue)
"""
# pylint: disable=too-many-nested-blocks # pylint: disable=too-many-nested-blocks
# Reset just in case # Reset just in case
sqlExecute( sqlExecute(
@ -785,8 +789,7 @@ class singleWorker(StoppableThread):
) )
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByToAddress', ( 'updateSentItemStatusByToAddress', (
toaddress, toaddress, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Encryption key was requested earlier.")) "Encryption key was requested earlier."))
)) ))
@ -858,8 +861,7 @@ class singleWorker(StoppableThread):
) )
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByToAddress', ( 'updateSentItemStatusByToAddress', (
toaddress, toaddress, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Sending a request for the" "Sending a request for the"
" recipient\'s encryption key.")) " recipient\'s encryption key."))
@ -883,8 +885,7 @@ class singleWorker(StoppableThread):
state.ackdataForWhichImWatching[ackdata] = 0 state.ackdataForWhichImWatching[ackdata] = 0
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Looking up the receiver\'s public key")) "Looking up the receiver\'s public key"))
)) ))
@ -941,15 +942,14 @@ class singleWorker(StoppableThread):
) )
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Problem: Destination is a mobile" "Problem: Destination is a mobile"
" device who requests that the" " device who requests that the"
" destination be included in the" " destination be included in the"
" message but this is disallowed in" " message but this is disallowed in"
" your settings. %1" " your settings. {0}"
).arg(l10n.formatTimestamp())) ).format(l10n.formatTimestamp()))
)) ))
# if the human changes their setting and then # if the human changes their setting and then
# sends another message or restarts their client, # sends another message or restarts their client,
@ -972,8 +972,7 @@ class singleWorker(StoppableThread):
defaults.networkDefaultPayloadLengthExtraBytes defaults.networkDefaultPayloadLengthExtraBytes
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Doing work necessary to send message.\n" "Doing work necessary to send message.\n"
"There is no required difficulty for" "There is no required difficulty for"
@ -1005,32 +1004,18 @@ class singleWorker(StoppableThread):
requiredAverageProofOfWorkNonceTrialsPerByte, requiredAverageProofOfWorkNonceTrialsPerByte,
requiredPayloadLengthExtraBytes requiredPayloadLengthExtraBytes
) )
queues.UISignalQueue.put((
queues.UISignalQueue.put( 'updateSentItemStatusByAckdata', (
( ackdata, _translate(
'updateSentItemStatusByAckdata', "MainWindow",
( "Doing work necessary to send message.\n"
ackdata, "Receiver\'s required difficulty: {0} and {1}"
tr._translate( ).format(
"MainWindow", float(requiredAverageProofOfWorkNonceTrialsPerByte) /
"Doing work necessary to send message.\n" defaults.networkDefaultProofOfWorkNonceTrialsPerByte,
"Receiver\'s required difficulty: %1" float(requiredPayloadLengthExtraBytes) /
" and %2" defaults.networkDefaultPayloadLengthExtraBytes))
).arg( ))
str(
float(requiredAverageProofOfWorkNonceTrialsPerByte) /
defaults.networkDefaultProofOfWorkNonceTrialsPerByte
)
).arg(
str(
float(requiredPayloadLengthExtraBytes) /
defaults.networkDefaultPayloadLengthExtraBytes
)
)
)
)
)
if status != 'forcepow': if status != 'forcepow':
maxacceptablenoncetrialsperbyte = BMConfigParser().getint( maxacceptablenoncetrialsperbyte = BMConfigParser().getint(
'bitmessagesettings', 'maxacceptablenoncetrialsperbyte') 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte')
@ -1050,18 +1035,19 @@ class singleWorker(StoppableThread):
ackdata) ackdata)
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Problem: The work demanded by" "Problem: The work demanded by the"
" the recipient (%1 and %2) is" " recipient ({0} and {1}) is more"
" more difficult than you are" " difficult than you are willing"
" willing to do. %3" " to do. {2}"
).arg(str(float(requiredAverageProofOfWorkNonceTrialsPerByte) / ).format(
defaults.networkDefaultProofOfWorkNonceTrialsPerByte)).arg( float(requiredAverageProofOfWorkNonceTrialsPerByte) /
str(float(requiredPayloadLengthExtraBytes) / defaults.networkDefaultProofOfWorkNonceTrialsPerByte,
defaults.networkDefaultPayloadLengthExtraBytes)).arg( float(requiredPayloadLengthExtraBytes) /
l10n.formatTimestamp())))) defaults.networkDefaultPayloadLengthExtraBytes,
l10n.formatTimestamp()))
))
continue continue
else: # if we are sending a message to ourselves or a chan.. else: # if we are sending a message to ourselves or a chan..
self.logger.info('Sending a message.') self.logger.info('Sending a message.')
@ -1075,15 +1061,14 @@ class singleWorker(StoppableThread):
except Exception as err: except Exception as err:
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Problem: You are trying to send a" "Problem: You are trying to send a"
" message to yourself or a chan but your" " message to yourself or a chan but your"
" encryption key could not be found in" " encryption key could not be found in"
" the keys.dat file. Could not encrypt" " the keys.dat file. Could not encrypt"
" message. %1" " message. {0}"
).arg(l10n.formatTimestamp())) ).format(l10n.formatTimestamp()))
)) ))
self.logger.error( self.logger.error(
'Error within sendMsg. Could not read the keys' 'Error within sendMsg. Could not read the keys'
@ -1100,8 +1085,7 @@ class singleWorker(StoppableThread):
defaults.networkDefaultPayloadLengthExtraBytes defaults.networkDefaultPayloadLengthExtraBytes
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Doing work necessary to send message.")) "Doing work necessary to send message."))
)) ))
@ -1123,8 +1107,7 @@ class singleWorker(StoppableThread):
except: except:
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Error! Could not find sender address" "Error! Could not find sender address"
" (your address) in the keys.dat file.")) " (your address) in the keys.dat file."))
@ -1177,8 +1160,7 @@ class singleWorker(StoppableThread):
# The fullAckPayload is a normal msg protocol message # The fullAckPayload is a normal msg protocol message
# with the proof of work already completed that the # with the proof of work already completed that the
# receiver of this message can easily send out. # receiver of this message can easily send out.
fullAckPayload = self.generateFullAckMessage( fullAckPayload = self.generateFullAckMessage(ackdata, TTL)
ackdata, toStreamNumber, TTL)
payload += encodeVarint(len(fullAckPayload)) payload += encodeVarint(len(fullAckPayload))
payload += fullAckPayload payload += fullAckPayload
dataToSign = pack('>Q', embeddedTime) + '\x00\x00\x00\x02' + \ dataToSign = pack('>Q', embeddedTime) + '\x00\x00\x00\x02' + \
@ -1190,8 +1172,7 @@ class singleWorker(StoppableThread):
# We have assembled the data that will be encrypted. # We have assembled the data that will be encrypted.
try: try:
encrypted = highlevelcrypto.encrypt( encrypted = highlevelcrypto.encrypt(
payload, "04" + hexlify(pubEncryptionKeyBase256) payload, "04" + hexlify(pubEncryptionKeyBase256))
)
except: except:
sqlExecute( sqlExecute(
'''UPDATE sent SET status='badkey' WHERE ackdata=? AND folder='sent' ''', '''UPDATE sent SET status='badkey' WHERE ackdata=? AND folder='sent' ''',
@ -1199,12 +1180,11 @@ class singleWorker(StoppableThread):
) )
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Problem: The recipient\'s encryption key is" "Problem: The recipient\'s encryption key is"
" no good. Could not encrypt message. %1" " no good. Could not encrypt message. {0}"
).arg(l10n.formatTimestamp())) ).format(l10n.formatTimestamp()))
)) ))
continue continue
@ -1268,21 +1248,19 @@ class singleWorker(StoppableThread):
not protocol.checkBitfield(behaviorBitfield, protocol.BITFIELD_DOESACK): not protocol.checkBitfield(behaviorBitfield, protocol.BITFIELD_DOESACK):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata, _translate(
tr._translate( "MainWindow", "Message sent. Sent at {0}"
"MainWindow", ).format(l10n.formatTimestamp()))
"Message sent. Sent at %1" ))
).arg(l10n.formatTimestamp()))))
else: else:
# not sending to a chan or one of my addresses # not sending to a chan or one of my addresses
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Message sent. Waiting for acknowledgement." "Message sent. Waiting for acknowledgement."
" Sent on %1" " Sent on {0}"
).arg(l10n.formatTimestamp())) ).format(l10n.formatTimestamp()))
)) ))
self.logger.info( self.logger.info(
'Broadcasting inv for my msg(within sendmsg function): %s', 'Broadcasting inv for my msg(within sendmsg function): %s',
@ -1411,8 +1389,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(('updateStatusBar', statusbar)) queues.UISignalQueue.put(('updateStatusBar', statusbar))
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByToAddress', ( 'updateSentItemStatusByToAddress', (
toAddress, toAddress, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Doing work necessary to request encryption key.")) "Doing work necessary to request encryption key."))
)) ))
@ -1436,30 +1413,31 @@ class singleWorker(StoppableThread):
int(time.time()), retryNumber + 1, sleeptill, toAddress) int(time.time()), retryNumber + 1, sleeptill, toAddress)
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateStatusBar', 'updateStatusBar', _translate(
tr._translate(
"MainWindow", "MainWindow",
"Broadcasting the public key request. This program will" "Broadcasting the public key request. This program will"
" auto-retry if they are offline.") " auto-retry if they are offline.")
)) ))
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByToAddress', ( 'updateSentItemStatusByToAddress', (
toAddress, toAddress, _translate(
tr._translate(
"MainWindow", "MainWindow",
"Sending public key request. Waiting for reply." "Sending public key request. Waiting for reply."
" Requested at %1" " Requested at {0}"
).arg(l10n.formatTimestamp())) ).format(l10n.formatTimestamp()))
)) ))
def generateFullAckMessage(self, ackdata, _, TTL): def generateFullAckMessage(self, ackdata, TTL):
""" """Create ACK packet"""
It might be perfectly fine to just use the same TTL for the ackdata that we use for the message. But I would # It might be perfectly fine to just use the same TTL for
rather it be more difficult for attackers to associate ackData with the associated msg object. However, users # the ackdata that we use for the message. But I would rather
would want the TTL of the acknowledgement to be about the same as they set for the message itself. So let's set # it be more difficult for attackers to associate ackData with
the TTL of the acknowledgement to be in one of three 'buckets': 1 hour, 7 days, or 28 days, whichever is # the associated msg object. However, users would want the TTL
relatively close to what the user specified. # of the acknowledgement to be about the same as they set
""" # for the message itself. So let's set the TTL of the
# acknowledgement to be in one of three 'buckets': 1 hour, 7
# days, or 28 days, whichever is relatively close to what the
# user specified.
if TTL < 24 * 60 * 60: # 1 day if TTL < 24 * 60 * 60: # 1 day
TTL = 24 * 60 * 60 # 1 day TTL = 24 * 60 * 60 # 1 day
elif TTL < 7 * 24 * 60 * 60: # 1 week elif TTL < 7 * 24 * 60 * 60: # 1 week

View File

@ -3,6 +3,9 @@ Utility functions to check the availability of dependencies
and suggest how it may be installed and suggest how it may be installed
""" """
# flake8: noqa:E402
# pylint: disable=relative-import
import sys import sys
# Only really old versions of Python don't have sys.hexversion. We don't # Only really old versions of Python don't have sys.hexversion. We don't
@ -16,6 +19,7 @@ if not hasattr(sys, 'hexversion') or sys.hexversion < 0x20300F0:
import logging import logging
import os import os
from distutils import version # noqa:E402
from importlib import import_module from importlib import import_module
# We can now use logging so set up a simple configuration # We can now use logging so set up a simple configuration
@ -49,22 +53,22 @@ PACKAGE_MANAGER = {
} }
PACKAGES = { PACKAGES = {
"PyQt4": { "qtpy": {
"OpenBSD": "py-qt4", "OpenBSD": "py-qtpy",
"FreeBSD": "py27-qt4", "FreeBSD": "py27-QtPy",
"Debian": "python-qt4", "Debian": "python-qtpy",
"Ubuntu": "python-qt4", "Ubuntu": "python-qtpy",
"Ubuntu 12": "python-qt4", "Ubuntu 12": "python-qtpy",
"openSUSE": "python-qt", "openSUSE": "python-QtPy",
"Fedora": "PyQt4", "Fedora": "python2-QtPy",
"Guix": "python2-pyqt@4.11.4", "Guix": "",
"Gentoo": "dev-python/PyQt4", "Gentoo": "dev-python/QtPy",
"optional": True, "optional": True,
"description": "description":
"You only need PyQt if you want to use the GUI." "You only need qtpy if you want to use the GUI."
" When only running as a daemon, this can be skipped.\n" " When only running as a daemon, this can be skipped.\n"
"However, you would have to install it manually" "Also maybe you need to install PyQt5 if your package manager"
" because setuptools does not support PyQt." " not installs it as qtpy dependency"
}, },
"msgpack": { "msgpack": {
"OpenBSD": "py-msgpack", "OpenBSD": "py-msgpack",
@ -135,17 +139,17 @@ detectOS.result = None
def detectOSRelease(): def detectOSRelease():
"""Detecting the release of OS""" """Detecting the release of OS"""
with open("/etc/os-release", 'r') as osRelease: with open("/etc/os-release", 'r') as osRelease:
version = None ver = None
for line in osRelease: for line in osRelease:
if line.startswith("NAME="): if line.startswith("NAME="):
detectOS.result = OS_RELEASE.get( detectOS.result = OS_RELEASE.get(
line.replace('"', '').split("=")[-1].strip().lower()) line.replace('"', '').split("=")[-1].strip().lower())
elif line.startswith("VERSION_ID="): elif line.startswith("VERSION_ID="):
try: try:
version = float(line.split("=")[1].replace("\"", "")) ver = float(line.split("=")[1].replace("\"", ""))
except ValueError: except ValueError:
pass pass
if detectOS.result == "Ubuntu" and version < 14: if detectOS.result == "Ubuntu" and ver < 14:
detectOS.result = "Ubuntu 12" detectOS.result = "Ubuntu 12"
@ -168,7 +172,7 @@ def try_import(module, log_extra=False):
def check_ripemd160(): def check_ripemd160():
"""Check availability of the RIPEMD160 hash function""" """Check availability of the RIPEMD160 hash function"""
try: try:
from fallback import RIPEMD160Hash # pylint: disable=relative-import from fallback import RIPEMD160Hash
except ImportError: except ImportError:
return False return False
return RIPEMD160Hash is not None return RIPEMD160Hash is not None
@ -363,21 +367,27 @@ def check_pyqt():
Here we are checking for PyQt4 with its version, as for it require Here we are checking for PyQt4 with its version, as for it require
PyQt 4.8 or later. PyQt 4.8 or later.
""" """
QtCore = try_import( # pylint: disable=no-member
'PyQt4.QtCore', 'PyBitmessage requires PyQt 4.8 or later and Qt 4.7 or later.') try:
from fallback import qtpy
except ImportError:
logger.error(
'PyBitmessage requires qtpy, PyQt 4.8 or later and Qt 4.7 or later.'
)
qtpy = None
if not QtCore: if not qtpy:
return False return False
logger.info('PyQt Version: %s', QtCore.PYQT_VERSION_STR) logger.info('PyQt Version: %s', qtpy.PYQT_VERSION)
logger.info('Qt Version: %s', QtCore.QT_VERSION_STR) logger.info('Qt Version: %s', qtpy.QT_VERSION)
passed = True passed = True
if QtCore.PYQT_VERSION < 0x40800: if version.LooseVersion(qtpy.PYQT_VERSION) < '4.8':
logger.error( logger.error(
'This version of PyQt is too old. PyBitmessage requries' 'This version of PyQt is too old. PyBitmessage requries'
' PyQt 4.8 or later.') ' PyQt 4.8 or later.')
passed = False passed = False
if QtCore.QT_VERSION < 0x40700: if version.LooseVersion(qtpy.QT_VERSION) < '4.7':
logger.error( logger.error(
'This version of Qt is too old. PyBitmessage requries' 'This version of Qt is too old. PyBitmessage requries'
' Qt 4.7 or later.') ' Qt 4.7 or later.')
@ -386,7 +396,7 @@ def check_pyqt():
def check_msgpack(): def check_msgpack():
"""Do sgpack module check. """Do msgpack module check.
simply checking if msgpack package with all its dependency simply checking if msgpack package with all its dependency
is available or not as recommended for messages coding. is available or not as recommended for messages coding.

View File

@ -30,3 +30,36 @@ else:
if data: if data:
hasher.update(data) hasher.update(data)
return hasher return hasher
try:
import qtpy
except ImportError:
try:
from PyQt5 import QtCore, QtGui, QtWidgets, QtNetwork, uic
except ImportError:
qtpy = None
else:
import sys
import types
QtCore.Signal = QtCore.pyqtSignal
context = {
'API': 'pyqt5', # for tr
'PYQT_VERSION': QtCore.PYQT_VERSION_STR,
'QT_VERSION': QtCore.QT_VERSION_STR,
'QtCore': QtCore,
'QtGui': QtGui,
'QtWidgets': QtWidgets,
'QtNetwork': QtNetwork,
'uic': uic
}
try:
from PyQt5 import QtTest
except ImportError:
pass
else:
context['QtTest'] = QtTest
qtpy = types.ModuleType(
'qtpy', 'PyQt5 based dynamic fallback for qtpy')
qtpy.__dict__.update(context)
sys.modules['qtpy'] = qtpy

View File

@ -155,5 +155,6 @@ class MsgDecode(object):
# Throw away any extra lines (headers) after the subject. # Throw away any extra lines (headers) after the subject.
if subject: if subject:
subject = subject.splitlines()[0] subject = subject.splitlines()[0]
self.subject = subject # Field types should be the same for all message types
self.body = body self.subject = unicode(subject, 'utf-8', 'replace')
self.body = unicode(body, 'utf-8', 'replace')

View File

@ -11,10 +11,10 @@ import socket
import sys import sys
import defaults import defaults
import tr # translate
from addresses import decodeAddress from addresses import decodeAddress
from bmconfigparser import BMConfigParser from bmconfigparser import BMConfigParser
from debug import logger from debug import logger
from tr import _translate
configSection = "bitmessagesettings" configSection = "bitmessagesettings"
@ -22,7 +22,6 @@ configSection = "bitmessagesettings"
class RPCError(Exception): class RPCError(Exception):
"""Error thrown when the RPC call returns an error.""" """Error thrown when the RPC call returns an error."""
error = None error = None
def __init__(self, data): def __init__(self, data):
@ -47,8 +46,8 @@ class namecoinConnection(object):
def __init__(self, options=None): def __init__(self, options=None):
""" """
Initialise. If options are given, take the connection settings from Initialise. If options are given, take the connection settings from
them instead of loading from the configs. This can be used to test them instead of loading from the configs. This can be used to test
currently entered connection settings in the config dialog without currently entered connection settings in the config dialog without
actually changing the values (yet). actually changing the values (yet).
""" """
@ -73,7 +72,7 @@ class namecoinConnection(object):
def query(self, string): def query(self, string):
""" """
Query for the bitmessage address corresponding to the given identity Query for the bitmessage address corresponding to the given identity
string. If it doesn't contain a slash, id/ is prepended. We return string. If it doesn't contain a slash, id/ is prepended. We return
the result as (Error, Address) pair, where the Error is an error the result as (Error, Address) pair, where the Error is an error
message to display or None in case of success. message to display or None in case of success.
""" """
@ -92,9 +91,9 @@ class namecoinConnection(object):
res = self.callRPC("data", ["getValue", string]) res = self.callRPC("data", ["getValue", string])
res = res["reply"] res = res["reply"]
if not res: if not res:
return (tr._translate( return (_translate(
"MainWindow", 'The name %1 was not found.' "MainWindow", "The name {0} was not found."
).arg(unicode(string)), None) ).format(string), None)
else: else:
assert False assert False
except RPCError as exc: except RPCError as exc:
@ -103,17 +102,17 @@ class namecoinConnection(object):
errmsg = exc.error["message"] errmsg = exc.error["message"]
else: else:
errmsg = exc.error errmsg = exc.error
return (tr._translate( return (_translate(
"MainWindow", 'The namecoin query failed (%1)' "MainWindow", "The namecoin query failed ({0})"
).arg(unicode(errmsg)), None) ).format(errmsg), None)
except AssertionError: except AssertionError:
return (tr._translate( return (_translate(
"MainWindow", 'Unknown namecoin interface type: %1' "MainWindow", "Unknown namecoin interface type: {0}"
).arg(unicode(self.nmctype)), None) ).format(self.nmctype), None)
except Exception: except Exception:
logger.exception("Namecoin query exception") logger.exception("Namecoin query exception")
return (tr._translate( return (_translate(
"MainWindow", 'The namecoin query failed.'), None) "MainWindow", "The namecoin query failed."), None)
try: try:
res = json.loads(res) res = json.loads(res)
@ -130,14 +129,16 @@ class namecoinConnection(object):
return ( return (
None, "%s <%s>" % (display_name, res) None, "%s <%s>" % (display_name, res)
) if valid else ( ) if valid else (
tr._translate( _translate(
"MainWindow", "MainWindow",
'The name %1 has no associated Bitmessage address.' "The name {0} has no associated Bitmessage address."
).arg(unicode(string)), None) ).format(string),
None
)
def test(self): def test(self):
""" """
Test the connection settings. This routine tries to query a "getinfo" Test the connection settings. This routine tries to query a "getinfo"
command, and builds either an error message or a success message with command, and builds either an error message or a success message with
some info from it. some info from it.
""" """
@ -157,33 +158,36 @@ class namecoinConnection(object):
versStr = "0.%d.%d" % (v1, v2) versStr = "0.%d.%d" % (v1, v2)
else: else:
versStr = "0.%d.%d.%d" % (v1, v2, v3) versStr = "0.%d.%d.%d" % (v1, v2, v3)
message = ( return (
'success', 'success', _translate(
tr._translate(
"MainWindow", "MainWindow",
'Success! Namecoind version %1 running.').arg( "Success! Namecoind version {0} running."
unicode(versStr))) ).format(versStr)
)
elif self.nmctype == "nmcontrol": elif self.nmctype == "nmcontrol":
res = self.callRPC("data", ["status"]) res = self.callRPC("data", ["status"])
prefix = "Plugin data running" prefix = "Plugin data running"
if ("reply" in res) and res["reply"][:len(prefix)] == prefix: if ("reply" in res) and res["reply"][:len(prefix)] == prefix:
return ('success', tr._translate("MainWindow", 'Success! NMControll is up and running.')) return (
'success', _translate(
"MainWindow",
"Success! NMControll is up and running.")
)
logger.error("Unexpected nmcontrol reply: %s", res) logger.error("Unexpected nmcontrol reply: %s", res)
message = ('failed', tr._translate("MainWindow", 'Couldn\'t understand NMControl.')) return (
'failed', _translate(
"MainWindow", "Couldn\'t understand NMControl.")
)
else: else:
print "Unsupported Namecoin type" sys.exit("Unsupported Namecoin type")
sys.exit(1)
return message
except Exception: except Exception:
logger.info("Namecoin connection test failure") logger.info("Namecoin connection test failure")
return ( return (
'failed', 'failed', _translate(
tr._translate(
"MainWindow", "The connection to namecoin failed.") "MainWindow", "The connection to namecoin failed.")
) )
@ -243,7 +247,9 @@ class namecoinConnection(object):
return result return result
def queryServer(self, data): def queryServer(self, data):
"""Helper routine sending data to the RPC server and returning the result.""" """
Helper routine sending data to the RPC server and returning the result.
"""
try: try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

View File

@ -139,9 +139,10 @@ class TCPConnection(BMProto, TLSDispatcher):
'updateStatusBar', 'updateStatusBar',
_translate( _translate(
"MainWindow", "MainWindow",
"The time on your computer, %1, may be wrong. " "The time on your computer, {0}, may be wrong. "
"Please verify your settings." "Please verify your settings."
).arg(l10n.formatTimestamp()))) ).format(l10n.formatTimestamp())
))
def state_connection_fully_established(self): def state_connection_fully_established(self):
""" """

View File

@ -6,7 +6,7 @@ A menu plugin showing QR-Code for bitmessage address in modal dialog.
import urllib import urllib
import qrcode import qrcode
from PyQt4 import QtCore, QtGui from qtpy import QtGui, QtCore, QtWidgets
from pybitmessage.tr import _translate from pybitmessage.tr import _translate
@ -39,23 +39,23 @@ class Image(qrcode.image.base.BaseImage): # pylint: disable=abstract-method
QtCore.Qt.black) QtCore.Qt.black)
class QRCodeDialog(QtGui.QDialog): class QRCodeDialog(QtWidgets.QDialog):
"""The dialog""" """The dialog"""
def __init__(self, parent): def __init__(self, parent):
super(QRCodeDialog, self).__init__(parent) super(QRCodeDialog, self).__init__(parent)
self.image = QtGui.QLabel(self) self.image = QtWidgets.QLabel(self)
self.label = QtGui.QLabel(self) self.label = QtWidgets.QLabel(self)
font = QtGui.QFont() font = QtGui.QFont()
font.setBold(True) font.setBold(True)
font.setWeight(75) font.setWeight(75)
self.label.setFont(font) self.label.setFont(font)
self.label.setAlignment( self.label.setAlignment(
QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
buttonBox = QtGui.QDialogButtonBox(self) buttonBox = QtWidgets.QDialogButtonBox(self)
buttonBox.setOrientation(QtCore.Qt.Horizontal) buttonBox.setOrientation(QtCore.Qt.Horizontal)
buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok) buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok)
buttonBox.accepted.connect(self.accept) buttonBox.accepted.connect(self.accept)
layout = QtGui.QVBoxLayout(self) layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.image) layout.addWidget(self.image)
layout.addWidget(self.label) layout.addWidget(self.label)
layout.addWidget(buttonBox) layout.addWidget(buttonBox)
@ -72,7 +72,7 @@ class QRCodeDialog(QtGui.QDialog):
self.label.setText(text) self.label.setText(text)
self.label.setToolTip(text) self.label.setToolTip(text)
self.label.setFixedWidth(pixmap.width()) self.label.setFixedWidth(pixmap.width())
self.setFixedSize(QtGui.QWidget.sizeHint(self)) self.setFixedSize(QtWidgets.QWidget.sizeHint(self))
def connect_plugin(form): def connect_plugin(form):

View File

@ -32,6 +32,7 @@ def get_plugins(group, point='', name=None, fallback=None):
except (AttributeError, except (AttributeError,
ImportError, ImportError,
ValueError, ValueError,
RuntimeError, # PyQt for example
pkg_resources.DistributionNotFound, pkg_resources.DistributionNotFound,
pkg_resources.UnknownExtra): pkg_resources.UnknownExtra):
logger.debug( logger.debug(

View File

@ -0,0 +1,10 @@
# https://github.com/pyinstaller/pyinstaller/wiki/Recipe-PyQt4-API-Version
import sip
sip.setapi(u'QDate', 2)
sip.setapi(u'QDateTime', 2)
sip.setapi(u'QString', 2)
sip.setapi(u'QTextStream', 2)
sip.setapi(u'QTime', 2)
sip.setapi(u'QUrl', 2)
sip.setapi(u'QVariant', 2)

View File

@ -10,9 +10,7 @@ Return a PIL Image class instance which have generated identicon image.
``size`` specifies `patch size`. Generated image size is 3 * ``size``. ``size`` specifies `patch size`. Generated image size is 3 * ``size``.
""" """
from PyQt4 import QtGui from qtpy import QtCore, QtGui
from PyQt4.QtCore import QPointF, QSize, Qt
from PyQt4.QtGui import QPainter, QPixmap, QPolygonF
class IdenticonRendererBase(object): class IdenticonRendererBase(object):
@ -37,10 +35,12 @@ class IdenticonRendererBase(object):
""" """
# decode the code # decode the code
middle, corner, side, foreColor, secondColor, swap_cross = self.decode(self.code, twoColor) middle, corner, side, foreColor, secondColor, swap_cross = \
self.decode(self.code, twoColor)
# make image # make image
image = QPixmap(QSize(size * 3 + penwidth, size * 3 + penwidth)) image = QtGui.QPixmap(
QtCore.QSize(size * 3 + penwidth, size * 3 + penwidth))
# fill background # fill background
backColor = QtGui.QColor(255, 255, 255, opacity) backColor = QtGui.QColor(255, 255, 255, opacity)
@ -54,26 +54,28 @@ class IdenticonRendererBase(object):
'backColor': backColor} 'backColor': backColor}
# middle patch # middle patch
image = self.drawPatchQt((1, 1), middle[2], middle[1], middle[0], **kwds) image = self.drawPatchQt(
(1, 1), middle[2], middle[1], middle[0], **kwds)
# side patch # side patch
kwds['foreColor'] = foreColor kwds['foreColor'] = foreColor
kwds['patch_type'] = side[0] kwds['patch_type'] = side[0]
for i in xrange(4): for i in range(4):
pos = [(1, 0), (2, 1), (1, 2), (0, 1)][i] pos = [(1, 0), (2, 1), (1, 2), (0, 1)][i]
image = self.drawPatchQt(pos, side[2] + 1 + i, side[1], **kwds) image = self.drawPatchQt(pos, side[2] + 1 + i, side[1], **kwds)
# corner patch # corner patch
kwds['foreColor'] = secondColor kwds['foreColor'] = secondColor
kwds['patch_type'] = corner[0] kwds['patch_type'] = corner[0]
for i in xrange(4): for i in range(4):
pos = [(0, 0), (2, 0), (2, 2), (0, 2)][i] pos = [(0, 0), (2, 0), (2, 2), (0, 2)][i]
image = self.drawPatchQt(pos, corner[2] + 1 + i, corner[1], **kwds) image = self.drawPatchQt(pos, corner[2] + 1 + i, corner[1], **kwds)
return image return image
def drawPatchQt(self, pos, turn, invert, patch_type, image, size, foreColor, def drawPatchQt(
backColor, penwidth): # pylint: disable=unused-argument self, pos, turn, invert, patch_type, image, size, foreColor,
backColor, penwidth): # pylint: disable=unused-argument
""" """
:param size: patch size :param size: patch size
""" """
@ -83,39 +85,44 @@ class IdenticonRendererBase(object):
invert = not invert invert = not invert
path = [(0., 0.), (1., 0.), (1., 1.), (0., 1.), (0., 0.)] path = [(0., 0.), (1., 0.), (1., 1.), (0., 1.), (0., 0.)]
polygon = QPolygonF([QPointF(x * size, y * size) for x, y in path]) polygon = QtGui.QPolygonF([
QtCore.QPointF(x * size, y * size) for x, y in path])
rot = turn % 4 rot = turn % 4
rect = [QPointF(0., 0.), QPointF(size, 0.), QPointF(size, size), QPointF(0., size)] rect = [
QtCore.QPointF(0., 0.), QtCore.QPointF(size, 0.),
QtCore.QPointF(size, size), QtCore.QPointF(0., size)]
rotation = [0, 90, 180, 270] rotation = [0, 90, 180, 270]
nopen = QtGui.QPen(foreColor, Qt.NoPen) nopen = QtGui.QPen(foreColor)
foreBrush = QtGui.QBrush(foreColor, Qt.SolidPattern) nopen.setStyle(QtCore.Qt.NoPen)
foreBrush = QtGui.QBrush(foreColor, QtCore.Qt.SolidPattern)
if penwidth > 0: if penwidth > 0:
pen_color = QtGui.QColor(255, 255, 255) pen_color = QtGui.QColor(255, 255, 255)
pen = QtGui.QPen(pen_color, Qt.SolidPattern) pen = QtGui.QPen(pen_color)
pen.setWidth(penwidth) pen.setWidth(penwidth)
painter = QPainter() painter = QtGui.QPainter()
painter.begin(image) painter.begin(image)
painter.setPen(nopen) painter.setPen(nopen)
painter.translate(pos[0] * size + penwidth / 2, pos[1] * size + penwidth / 2) painter.translate(
pos[0] * size + penwidth / 2, pos[1] * size + penwidth / 2)
painter.translate(rect[rot]) painter.translate(rect[rot])
painter.rotate(rotation[rot]) painter.rotate(rotation[rot])
if invert: if invert:
# subtract the actual polygon from a rectangle to invert it # subtract the actual polygon from a rectangle to invert it
poly_rect = QPolygonF(rect) poly_rect = QtGui.QPolygonF(rect)
polygon = poly_rect.subtracted(polygon) polygon = poly_rect.subtracted(polygon)
painter.setBrush(foreBrush) painter.setBrush(foreBrush)
if penwidth > 0: if penwidth > 0:
# draw the borders # draw the borders
painter.setPen(pen) painter.setPen(pen)
painter.drawPolygon(polygon, Qt.WindingFill) painter.drawPolygon(polygon, QtCore.Qt.WindingFill)
# draw the fill # draw the fill
painter.setPen(nopen) painter.setPen(nopen)
painter.drawPolygon(polygon, Qt.WindingFill) painter.drawPolygon(polygon, QtCore.Qt.WindingFill)
painter.end() painter.end()
@ -123,7 +130,6 @@ class IdenticonRendererBase(object):
def decode(self, code, twoColor): def decode(self, code, twoColor):
"""virtual functions""" """virtual functions"""
raise NotImplementedError raise NotImplementedError
@ -166,11 +172,12 @@ class DonRenderer(IdenticonRendererBase):
[(0, 0), (2, 0), (0, 2)], [(0, 0), (2, 0), (0, 2)],
# [15] empty: # [15] empty:
[]] []]
# get the [0] full square, [4] square standing on diagonale, [8] small centered square, or [15] empty tile: # get the [0] full square, [4] square standing on diagonale,
# [8] small centered square, or [15] empty tile:
MIDDLE_PATCH_SET = [0, 4, 8, 15] MIDDLE_PATCH_SET = [0, 4, 8, 15]
# modify path set # modify path set
for idx in xrange(len(PATH_SET)): for idx in range(len(PATH_SET)):
if PATH_SET[idx]: if PATH_SET[idx]:
p = [(vec[0] / 4.0, vec[1] / 4.0) for vec in PATH_SET[idx]] p = [(vec[0] / 4.0, vec[1] / 4.0) for vec in PATH_SET[idx]]
PATH_SET[idx] = p + p[:1] PATH_SET[idx] = p + p[:1]
@ -215,7 +222,8 @@ class DonRenderer(IdenticonRendererBase):
foreColor = QtGui.QColor(*foreColor) foreColor = QtGui.QColor(*foreColor)
if twoColor: if twoColor:
secondColor = (second_blue << 3, second_green << 3, second_red << 3) secondColor = (
second_blue << 3, second_green << 3, second_red << 3)
secondColor = QtGui.QColor(*secondColor) secondColor = QtGui.QColor(*secondColor)
else: else:
secondColor = foreColor secondColor = foreColor
@ -226,9 +234,9 @@ class DonRenderer(IdenticonRendererBase):
foreColor, secondColor, swap_cross foreColor, secondColor, swap_cross
def render_identicon(code, size, twoColor=False, opacity=255, penwidth=0, renderer=None): def render_identicon(
code, size, twoColor=False, opacity=255, penwidth=0, renderer=None):
"""Render an image""" """Render an image"""
if not renderer: if not renderer:
renderer = DonRenderer renderer = DonRenderer
return renderer(code).render(size, twoColor, opacity, penwidth) return renderer(code).render(size, twoColor, opacity, penwidth)

View File

@ -1,56 +1,33 @@
""" """
Translating text Slim layer providing environment agnostic _translate()
""" """
import os
import state import state
class translateClass: def _tr_dummy(context, text, disambiguation=None, n=None):
"""
This is used so that the translateText function can be used
when we are in daemon mode and not using any QT functions.
"""
# pylint: disable=old-style-class,too-few-public-methods
def __init__(self, context, text):
self.context = context
self.text = text
def arg(self, _):
"""Replace argument placeholders"""
if '%' in self.text:
# This doesn't actually do anything with the arguments
# because we don't have a UI in which to display this information anyway.
return translateClass(self.context, self.text.replace('%', '', 1))
return self.text
def _translate(context, text, disambiguation=None, encoding=None, n=None):
# pylint: disable=unused-argument # pylint: disable=unused-argument
return translateText(context, text, n) return text
def translateText(context, text, n=None): if state.enableGUI and not state.curses:
"""Translate text in context"""
try: try:
enableGUI = state.enableGUI from fallback import qtpy # noqa:F401
except AttributeError: # inside the plugin from qtpy import QtWidgets, QtCore, API
enableGUI = True except ImportError:
if enableGUI: _translate = _tr_dummy
try:
from PyQt4 import QtCore, QtGui
except Exception as err:
print 'PyBitmessage requires PyQt unless you want to run it as a daemon'\
' and interact with it using the API.'\
' You can download PyQt from http://www.riverbankcomputing.com/software/pyqt/download'\
' or by searching Google for \'PyQt Download\'.'\
' If you want to run in daemon mode, see https://bitmessage.org/wiki/Daemon'
print 'Error message:', err
os._exit(0) # pylint: disable=protected-access
if n is None:
return QtGui.QApplication.translate(context, text)
return QtGui.QApplication.translate(context, text, None, QtCore.QCoreApplication.CodecForTr, n)
else: else:
if '%' in text: if API == 'pyqt5':
return translateClass(context, text.replace('%', '', 1)) _translate = QtWidgets.QApplication.translate
return text else:
def _translate(context, text, disambiguation=None, n=None):
return (
QtWidgets.QApplication.translate(
context, text, disambiguation)
if n is None else
QtWidgets.QApplication.translate(
context, text, disambiguation,
QtCore.QCoreApplication.CodecForTr, n)
)
else:
_translate = _tr_dummy

View File

@ -269,9 +269,12 @@ class uPnPThread(StoppableThread):
with knownnodes.knownNodesLock: with knownnodes.knownNodesLock:
knownnodes.addKnownNode( knownnodes.addKnownNode(
1, self_peer, is_self=True) 1, self_peer, is_self=True)
queues.UISignalQueue.put(('updateStatusBar', tr._translate( queues.UISignalQueue.put((
"MainWindow", 'UPnP port mapping established on port %1' 'updateStatusBar', tr._translate(
).arg(str(self.extPort)))) "MainWindow",
"UPnP port mapping established on port {0}"
).format(self.extPort)
))
break break
except socket.timeout: except socket.timeout:
pass pass