PyBitmessage/src/bitmessageqt/__init__.py

5145 lines
219 KiB
Python
Raw Normal View History

# pylint: disable=too-many-lines,broad-except,too-many-instance-attributes,global-statement,too-few-public-methods
# pylint: disable=too-many-statements,too-many-branches,attribute-defined-outside-init,too-many-arguments,no-member
# pylint: disable=unused-argument,no-self-use,too-many-locals,unused-variable,too-many-nested-blocks
# pylint: disable=too-many-return-statements,protected-access,super-init-not-called,non-parent-init-called
"""
Initialise the QT interface
"""
import hashlib
import locale
import os
import random
import string
import sys
import textwrap
import time
from datetime import datetime, timedelta
2018-05-17 09:51:21 +00:00
import debug
from debug import logger
try:
from PyQt4 import QtCore, QtGui
from PyQt4.QtNetwork import QLocalSocket, QLocalServer
except ImportError:
logmsg = (
'PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can'
' download it from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for '
'\'PyQt Download\' (without quotes).'
)
logger.critical(logmsg, exc_info=True)
sys.exit()
2018-05-17 09:51:21 +00:00
from sqlite3 import register_adapter # pylint: disable=wrong-import-order
import defaults
import helper_search
import knownnodes
import l10n
2015-11-26 01:37:07 +00:00
import openclpow
import paths
import queues
import shared
import shutdown
import state
import upnp
from bitmessageqt import sound, support, dialogs
from bitmessageqt.foldertree import (
AccountMixin, Ui_FolderWidget, Ui_AddressWidget, Ui_SubscriptionWidget, MessageList_AddressWidget,
MessageList_SubjectWidget, Ui_AddressBookWidgetItemLabel, Ui_AddressBookWidgetItemAddress,
)
from bitmessageqt.account import (
getSortedAccounts, getSortedSubscriptions, accountClass, BMAccount, GatewayAccount, MailchuckAccount, AccountColor,
)
from bitmessageqt.bitmessageui import Ui_MainWindow, settingsmixin
from bitmessageqt.messageview import MessageView
from bitmessageqt.migrationwizard import Ui_MigrationWizard
from bitmessageqt.settings import Ui_settingsDialog
from bitmessageqt.utils import str_broadcast_subscribers, avatarize
from bitmessageqt.uisignaler import UISignaler
from bitmessageqt.statusbar import BMStatusBar
from addresses import decodeAddress, addBMIfNotPresent
from bmconfigparser import BMConfigParser
from namecoin import namecoinConnection
from helper_ackPayload import genAckPayload
from helper_generic import powQueueSize
from helper_sql import sqlQuery, sqlExecute, sqlExecuteChunked, sqlStoredProcedure
from network.stats import pendingDownload, pendingUpload
from network.asyncore_pollchoose import set_rates
from proofofwork import getPowType
from tr import _translate
2013-06-25 20:26:12 +00:00
try:
2017-03-10 14:45:46 +00:00
from plugins.plugin import get_plugin, get_plugins
except ImportError:
get_plugins = False
qmytranslator = None
qsystranslator = None
def change_translation(newlocale):
"""Change a translation to a new locale"""
global qmytranslator, qsystranslator
try:
if not qmytranslator.isEmpty():
QtGui.QApplication.removeTranslator(qmytranslator)
except:
pass
try:
if not qsystranslator.isEmpty():
QtGui.QApplication.removeTranslator(qsystranslator)
except:
pass
qmytranslator = QtCore.QTranslator()
translationpath = os.path.join(paths.codePath(), 'translations', 'bitmessage_' + newlocale)
qmytranslator.load(translationpath)
QtGui.QApplication.installTranslator(qmytranslator)
qsystranslator = QtCore.QTranslator()
if paths.frozen:
translationpath = os.path.join(paths.codePath(), 'translations', 'qt_' + newlocale)
else:
translationpath = os.path.join(str(QtCore.QLibraryInfo.location(
QtCore.QLibraryInfo.TranslationsPath)), 'qt_' + newlocale)
qsystranslator.load(translationpath)
QtGui.QApplication.installTranslator(qsystranslator)
2013-11-01 23:25:24 +00:00
lang = locale.normalize(l10n.getTranslationLanguage())
langs = [lang.split(".")[0] + "." + l10n.encoding, lang.split(".")[0] + "." + 'UTF-8', lang]
if 'win32' in sys.platform or 'win64' in sys.platform:
langs = [l10n.getWindowsLocale(lang)]
for lang in langs:
try:
l10n.setlocale(locale.LC_ALL, lang)
if 'win32' not in sys.platform and 'win64' not in sys.platform:
l10n.encoding = locale.nl_langinfo(locale.CODESET)
else:
l10n.encoding = locale.getlocale()[1]
logger.info("Successfully set locale to %s", lang)
break
except:
logger.error("Failed to set locale to %s", lang, exc_info=True)
class MyForm(settingsmixin.SMainWindow): # pylint: disable=too-many-public-methods
"""TBC"""
# the last time that a message arrival sound was played
lastSoundTime = datetime.now() - timedelta(days=1)
# the maximum frequency of message sounds in seconds
maxSoundFrequencySec = 60
REPLY_TYPE_SENDER = 0
REPLY_TYPE_CHAN = 1
def init_file_menu(self):
"""Initialise the file menu"""
QtCore.QObject.connect(self.ui.actionExit, QtCore.SIGNAL(
"triggered()"), self.quit)
QtCore.QObject.connect(self.ui.actionNetworkSwitch, QtCore.SIGNAL(
"triggered()"), self.network_switch)
QtCore.QObject.connect(self.ui.actionManageKeys, QtCore.SIGNAL(
"triggered()"), self.click_actionManageKeys)
QtCore.QObject.connect(self.ui.actionDeleteAllTrashedMessages,
QtCore.SIGNAL(
"triggered()"),
self.click_actionDeleteAllTrashedMessages)
QtCore.QObject.connect(self.ui.actionRegenerateDeterministicAddresses,
QtCore.SIGNAL(
"triggered()"),
self.click_actionRegenerateDeterministicAddresses)
QtCore.QObject.connect(
self.ui.pushButtonAddChan,
QtCore.SIGNAL("clicked()"),
self.click_actionJoinChan) # also used for creating chans.
QtCore.QObject.connect(self.ui.pushButtonNewAddress, QtCore.SIGNAL(
"clicked()"), self.click_NewAddressDialog)
QtCore.QObject.connect(self.ui.pushButtonAddAddressBook, QtCore.SIGNAL(
"clicked()"), self.click_pushButtonAddAddressBook)
QtCore.QObject.connect(self.ui.pushButtonAddSubscription, QtCore.SIGNAL(
"clicked()"), self.click_pushButtonAddSubscription)
2015-03-03 19:04:12 +00:00
QtCore.QObject.connect(self.ui.pushButtonTTL, QtCore.SIGNAL(
"clicked()"), self.click_pushButtonTTL)
QtCore.QObject.connect(self.ui.pushButtonClear, QtCore.SIGNAL(
"clicked()"), self.click_pushButtonClear)
QtCore.QObject.connect(self.ui.pushButtonSend, QtCore.SIGNAL(
"clicked()"), self.click_pushButtonSend)
2015-03-21 10:37:08 +00:00
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):
"""Popup menu for the Inbox tab"""
2013-05-02 15:53:54 +00:00
self.ui.inboxContextMenuToolbar = QtGui.QToolBar()
# Actions
self.actionReply = self.ui.inboxContextMenuToolbar.addAction(_translate(
"MainWindow", "Reply to sender"), self.on_action_InboxReply)
self.actionReplyChan = self.ui.inboxContextMenuToolbar.addAction(_translate(
"MainWindow", "Reply to channel"), self.on_action_InboxReplyChan)
self.actionAddSenderToAddressBook = self.ui.inboxContextMenuToolbar.addAction(
_translate(
"MainWindow", "Add sender to your Address Book"),
self.on_action_InboxAddSenderToAddressBook)
self.actionAddSenderToBlackList = self.ui.inboxContextMenuToolbar.addAction(
_translate(
"MainWindow", "Add sender to your Blacklist"),
self.on_action_InboxAddSenderToBlackList)
self.actionTrashInboxMessage = self.ui.inboxContextMenuToolbar.addAction(
_translate("MainWindow", "Move to Trash"),
self.on_action_InboxTrash)
2015-11-01 09:56:37 +00:00
self.actionUndeleteTrashedMessage = self.ui.inboxContextMenuToolbar.addAction(
_translate("MainWindow", "Undelete"),
self.on_action_TrashUndelete)
self.actionForceHtml = self.ui.inboxContextMenuToolbar.addAction(
_translate(
"MainWindow", "View HTML code as formatted text"),
self.on_action_InboxMessageForceHtml)
self.actionSaveMessageAs = self.ui.inboxContextMenuToolbar.addAction(
_translate(
"MainWindow", "Save message as..."),
self.on_action_InboxSaveMessageAs)
self.actionMarkUnread = self.ui.inboxContextMenuToolbar.addAction(
_translate(
"MainWindow", "Mark Unread"), self.on_action_InboxMarkUnread)
# contextmenu messagelists
self.ui.tableWidgetInbox.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu)
if connectSignal:
self.connect(
self.ui.tableWidgetInbox,
QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'),
self.on_context_menuInbox)
self.ui.tableWidgetInboxSubscriptions.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu)
if connectSignal:
self.connect(
self.ui.tableWidgetInboxSubscriptions,
QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'),
self.on_context_menuInbox)
self.ui.tableWidgetInboxChans.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu)
if connectSignal:
self.connect(
self.ui.tableWidgetInboxChans,
QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'),
self.on_context_menuInbox)
def init_identities_popup_menu(self, connectSignal=True):
"""Popup menu for the Your Identities tab"""
2015-03-21 10:37:08 +00:00
self.ui.addressContextMenuToolbarYourIdentities = QtGui.QToolBar()
# Actions
self.actionNewYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction(_translate(
"MainWindow", "New"), self.on_action_YourIdentitiesNew)
self.actionEnableYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction(
_translate(
"MainWindow", "Enable"), self.on_action_Enable)
self.actionDisableYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction(
_translate(
"MainWindow", "Disable"), self.on_action_Disable)
self.actionSetAvatarYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction(
_translate(
"MainWindow", "Set avatar..."),
self.on_action_TreeWidgetSetAvatar)
self.actionClipboardYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction(
_translate(
"MainWindow", "Copy address to clipboard"),
self.on_action_Clipboard)
self.actionSpecialAddressBehaviorYourIdentities = self.ui.addressContextMenuToolbarYourIdentities.addAction(
_translate(
"MainWindow", "Special address behavior..."),
self.on_action_SpecialAddressBehaviorDialog)
self.actionEmailGateway = self.ui.addressContextMenuToolbarYourIdentities.addAction(
_translate(
"MainWindow", "Email gateway"),
self.on_action_EmailGatewayDialog)
self.actionMarkAllRead = self.ui.addressContextMenuToolbarYourIdentities.addAction(
_translate(
"MainWindow", "Mark all messages as read"),
self.on_action_MarkAllRead)
2015-03-21 10:37:08 +00:00
self.ui.treeWidgetYourIdentities.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu)
if connectSignal:
self.connect(
self.ui.treeWidgetYourIdentities,
QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'),
self.on_context_menuYourIdentities)
2015-03-21 10:37:08 +00:00
# load all gui.menu plugins with prefix 'address'
self.menu_plugins = {'address': []}
for plugin in get_plugins('gui.menu', 'address'):
try:
handler, title = plugin(self)
except TypeError:
continue
self.menu_plugins['address'].append(
self.ui.addressContextMenuToolbarYourIdentities.addAction(
title, handler
))
2015-03-21 10:37:08 +00:00
def init_chan_popup_menu(self, connectSignal=True):
"""Popup menu for the Channels tab"""
2013-05-02 15:53:54 +00:00
self.ui.addressContextMenuToolbar = QtGui.QToolBar()
# Actions
self.actionNew = self.ui.addressContextMenuToolbar.addAction(_translate(
"MainWindow", "New"), self.on_action_YourIdentitiesNew)
2015-11-09 17:22:38 +00:00
self.actionDelete = self.ui.addressContextMenuToolbar.addAction(
_translate("MainWindow", "Delete"),
self.on_action_YourIdentitiesDelete)
self.actionEnable = self.ui.addressContextMenuToolbar.addAction(
_translate(
2015-03-21 10:37:08 +00:00
"MainWindow", "Enable"), self.on_action_Enable)
self.actionDisable = self.ui.addressContextMenuToolbar.addAction(
_translate(
2015-03-21 10:37:08 +00:00
"MainWindow", "Disable"), self.on_action_Disable)
self.actionSetAvatar = self.ui.addressContextMenuToolbar.addAction(
_translate(
"MainWindow", "Set avatar..."),
2015-03-21 10:37:08 +00:00
self.on_action_TreeWidgetSetAvatar)
self.actionClipboard = self.ui.addressContextMenuToolbar.addAction(
_translate(
"MainWindow", "Copy address to clipboard"),
2015-03-21 10:37:08 +00:00
self.on_action_Clipboard)
self.actionSpecialAddressBehavior = self.ui.addressContextMenuToolbar.addAction(
_translate(
"MainWindow", "Special address behavior..."),
self.on_action_SpecialAddressBehaviorDialog)
self.ui.treeWidgetChans.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu)
if connectSignal:
self.connect(
self.ui.treeWidgetChans,
QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'),
self.on_context_menuChan)
def init_addressbook_popup_menu(self, connectSignal=True):
"""Popup menu for the Address Book page"""
2013-05-02 15:53:54 +00:00
self.ui.addressBookContextMenuToolbar = QtGui.QToolBar()
# Actions
self.actionAddressBookSend = self.ui.addressBookContextMenuToolbar.addAction(
_translate(
"MainWindow", "Send message to this address"),
self.on_action_AddressBookSend)
self.actionAddressBookClipboard = self.ui.addressBookContextMenuToolbar.addAction(
_translate(
"MainWindow", "Copy address to clipboard"),
self.on_action_AddressBookClipboard)
self.actionAddressBookSubscribe = self.ui.addressBookContextMenuToolbar.addAction(
_translate(
"MainWindow", "Subscribe to this address"),
self.on_action_AddressBookSubscribe)
self.actionAddressBookSetAvatar = self.ui.addressBookContextMenuToolbar.addAction(
_translate(
"MainWindow", "Set avatar..."),
self.on_action_AddressBookSetAvatar)
self.actionAddressBookSetSound = \
self.ui.addressBookContextMenuToolbar.addAction(
_translate("MainWindow", "Set notification sound..."),
self.on_action_AddressBookSetSound)
self.actionAddressBookNew = self.ui.addressBookContextMenuToolbar.addAction(
_translate(
"MainWindow", "Add New Address"), self.on_action_AddressBookNew)
self.actionAddressBookDelete = self.ui.addressBookContextMenuToolbar.addAction(
_translate(
"MainWindow", "Delete"), self.on_action_AddressBookDelete)
self.ui.tableWidgetAddressBook.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu)
if connectSignal:
self.connect(
self.ui.tableWidgetAddressBook,
QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'),
self.on_context_menuAddressBook)
2013-05-02 15:53:54 +00:00
def init_subscriptions_popup_menu(self, connectSignal=True):
"""Popup menu for the Subscriptions page"""
2013-05-02 15:53:54 +00:00
self.ui.subscriptionsContextMenuToolbar = QtGui.QToolBar()
# Actions
self.actionsubscriptionsNew = self.ui.subscriptionsContextMenuToolbar.addAction(
_translate("MainWindow", "New"), self.on_action_SubscriptionsNew)
self.actionsubscriptionsDelete = self.ui.subscriptionsContextMenuToolbar.addAction(
_translate("MainWindow", "Delete"),
self.on_action_SubscriptionsDelete)
self.actionsubscriptionsClipboard = self.ui.subscriptionsContextMenuToolbar.addAction(
_translate("MainWindow", "Copy address to clipboard"),
self.on_action_SubscriptionsClipboard)
self.actionsubscriptionsEnable = self.ui.subscriptionsContextMenuToolbar.addAction(
_translate("MainWindow", "Enable"),
self.on_action_SubscriptionsEnable)
self.actionsubscriptionsDisable = self.ui.subscriptionsContextMenuToolbar.addAction(
_translate("MainWindow", "Disable"),
self.on_action_SubscriptionsDisable)
self.actionsubscriptionsSetAvatar = self.ui.subscriptionsContextMenuToolbar.addAction(
_translate("MainWindow", "Set avatar..."),
2015-03-21 10:37:08 +00:00
self.on_action_TreeWidgetSetAvatar)
self.ui.treeWidgetSubscriptions.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu)
if connectSignal:
self.connect(
self.ui.treeWidgetSubscriptions,
QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'),
self.on_context_menuSubscriptions)
2013-05-02 15:53:54 +00:00
def init_sent_popup_menu(self, connectSignal=True):
"""Popup menu for the Sent page"""
2013-05-02 15:53:54 +00:00
self.ui.sentContextMenuToolbar = QtGui.QToolBar()
# Actions
self.actionTrashSentMessage = self.ui.sentContextMenuToolbar.addAction(
_translate(
"MainWindow", "Move to Trash"), self.on_action_SentTrash)
self.actionSentClipboard = self.ui.sentContextMenuToolbar.addAction(
_translate(
"MainWindow", "Copy destination address to clipboard"),
self.on_action_SentClipboard)
self.actionForceSend = self.ui.sentContextMenuToolbar.addAction(
_translate(
"MainWindow", "Force send"), self.on_action_ForceSend)
def rerenderTabTreeSubscriptions(self):
"""TBC"""
treeWidget = self.ui.treeWidgetSubscriptions
folders = Ui_FolderWidget.folderWeight.keys()
folders.remove("new")
# sort ascending when creating
if treeWidget.topLevelItemCount() == 0:
treeWidget.header().setSortIndicator(
0, QtCore.Qt.AscendingOrder)
# init dictionary
db = getSortedSubscriptions(True)
for address in db:
for folder in folders:
if folder not in db[address]:
db[address][folder] = {}
if treeWidget.isSortingEnabled():
treeWidget.setSortingEnabled(False)
i = 0
while i < treeWidget.topLevelItemCount():
widget = treeWidget.topLevelItem(i)
if widget is not None:
toAddress = widget.address
else:
toAddress = None
if toAddress not in db:
treeWidget.takeTopLevelItem(i)
# no increment
continue
unread = 0
j = 0
while j < widget.childCount():
subwidget = widget.child(j)
try:
subwidget.setUnreadCount(db[toAddress][subwidget.folderName]['count'])
unread += db[toAddress][subwidget.folderName]['count']
db[toAddress].pop(subwidget.folderName, None)
except:
widget.takeChild(j)
# no increment
continue
j += 1
# add missing folders
if db[toAddress]:
j = 0
for f, c in db[toAddress].iteritems():
try:
subwidget = Ui_FolderWidget(widget, j, toAddress, f, c['count'])
except KeyError:
subwidget = Ui_FolderWidget(widget, j, toAddress, f, 0)
j += 1
widget.setUnreadCount(unread)
db.pop(toAddress, None)
i += 1
i = 0
for toAddress in db:
widget = Ui_SubscriptionWidget(
treeWidget, i, toAddress,
db[toAddress]["inbox"]['count'],
db[toAddress]["inbox"]['label'],
db[toAddress]["inbox"]['enabled'])
j = 0
unread = 0
for folder in folders:
try:
subwidget = Ui_FolderWidget(widget, j, toAddress, folder, db[toAddress][folder]['count'])
unread += db[toAddress][folder]['count']
except KeyError:
subwidget = Ui_FolderWidget(widget, j, toAddress, folder, 0)
j += 1
widget.setUnreadCount(unread)
i += 1
treeWidget.setSortingEnabled(True)
def rerenderTabTreeMessages(self):
"""TBC"""
self.rerenderTabTree('messages')
def rerenderTabTreeChans(self):
"""TBC"""
self.rerenderTabTree('chan')
2015-03-21 10:37:08 +00:00
def rerenderTabTree(self, tab):
"""TBC"""
2015-03-21 10:37:08 +00:00
if tab == 'messages':
treeWidget = self.ui.treeWidgetYourIdentities
elif tab == 'chan':
treeWidget = self.ui.treeWidgetChans
folders = Ui_FolderWidget.folderWeight.keys()
# sort ascending when creating
if treeWidget.topLevelItemCount() == 0:
treeWidget.header().setSortIndicator(
0, QtCore.Qt.AscendingOrder)
# init dictionary
db = {}
enabled = {}
for toAddress in getSortedAccounts():
isEnabled = BMConfigParser().getboolean(
toAddress, 'enabled')
isChan = BMConfigParser().safeGetBoolean(
toAddress, 'chan')
2015-10-01 08:15:23 +00:00
2016-01-24 17:25:33 +00:00
if treeWidget == self.ui.treeWidgetYourIdentities:
2015-10-01 08:15:23 +00:00
if isChan:
continue
2016-01-24 17:25:33 +00:00
elif treeWidget == self.ui.treeWidgetChans:
2015-10-01 08:15:23 +00:00
if not isChan:
continue
db[toAddress] = {}
2015-10-01 08:15:23 +00:00
for folder in folders:
db[toAddress][folder] = 0
enabled[toAddress] = isEnabled
2015-10-01 08:15:23 +00:00
# get number of (unread) messages
total = 0
queryreturn = sqlQuery(
'SELECT toaddress, folder, count(msgid) as cnt FROM inbox WHERE read = 0 GROUP BY toaddress, folder')
for row in queryreturn:
toaddress, folder, cnt = row
total += cnt
if toaddress in db and folder in db[toaddress]:
db[toaddress][folder] = cnt
2016-01-24 17:25:33 +00:00
if treeWidget == self.ui.treeWidgetYourIdentities:
db[None] = {}
db[None]["inbox"] = total
db[None]["new"] = total
2016-03-16 17:30:47 +00:00
db[None]["sent"] = 0
db[None]["trash"] = 0
enabled[None] = True
if treeWidget.isSortingEnabled():
treeWidget.setSortingEnabled(False)
i = 0
while i < treeWidget.topLevelItemCount():
widget = treeWidget.topLevelItem(i)
2015-11-09 17:22:38 +00:00
if widget is not None:
toAddress = widget.address
else:
toAddress = None
if toAddress not in db:
treeWidget.takeTopLevelItem(i)
# no increment
continue
unread = 0
j = 0
while j < widget.childCount():
subwidget = widget.child(j)
try:
subwidget.setUnreadCount(db[toAddress][subwidget.folderName])
2016-04-28 08:12:06 +00:00
if subwidget.folderName not in ["new", "trash", "sent"]:
unread += db[toAddress][subwidget.folderName]
db[toAddress].pop(subwidget.folderName, None)
except:
widget.takeChild(j)
# no increment
continue
j += 1
# add missing folders
if db[toAddress]:
j = 0
for f, c in db[toAddress].iteritems():
if toAddress is not None and tab == 'messages' and folder == "new":
continue
subwidget = Ui_FolderWidget(widget, j, toAddress, f, c)
2016-04-28 08:12:06 +00:00
if subwidget.folderName not in ["new", "trash", "sent"]:
unread += c
j += 1
widget.setUnreadCount(unread)
db.pop(toAddress, None)
i += 1
i = 0
for toAddress in db:
widget = Ui_AddressWidget(treeWidget, i, toAddress, db[toAddress]["inbox"], enabled[toAddress])
j = 0
unread = 0
for folder in folders:
if toAddress is not None and tab == 'messages' and folder == "new":
continue
subwidget = Ui_FolderWidget(widget, j, toAddress, folder, db[toAddress][folder])
2016-04-28 08:12:06 +00:00
if subwidget.folderName not in ["new", "trash", "sent"]:
unread += db[toAddress][folder]
j += 1
widget.setUnreadCount(unread)
i += 1
treeWidget.setSortingEnabled(True)
2015-03-21 10:37:08 +00:00
def __init__(self, parent=None):
"""TBC"""
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# Ask the user if we may delete their old version 1 addresses if they
# have any.
for addressInKeysFile in getSortedAccounts():
status, addressVersionNumber, streamNumber, addressHash = decodeAddress(
addressInKeysFile)
if addressVersionNumber == 1:
displayMsg = _translate(
"MainWindow",
'One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer '
2018-05-17 09:51:21 +00:00
'supported. May we delete it now?'
).arg(addressInKeysFile)
reply = QtGui.QMessageBox.question(
self, 'Message', displayMsg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
BMConfigParser().remove_section(addressInKeysFile)
BMConfigParser().save()
# Configure Bitmessage to start on startup (or remove the
# configuration) based on the setting in the keys.dat file
if 'win32' in sys.platform or 'win64' in sys.platform:
# Auto-startup for Windows
RUN_PATH = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
2018-02-09 10:11:48 +00:00
self.settings = QtCore.QSettings(RUN_PATH, QtCore.QSettings.NativeFormat)
# In case the user moves the program and the registry entry is no longer
# valid, this will delete the old registry entry.
self.settings.remove("PyBitmessage")
if BMConfigParser().getboolean('bitmessagesettings', 'startonlogon'):
self.settings.setValue("PyBitmessage", sys.argv[0])
elif 'darwin' in sys.platform:
# startup for mac
pass
elif 'linux' in sys.platform:
# startup for linux
pass
# e.g. for editing labels
self.recurDepth = 0
# switch back to this when replying
self.replyFromTab = None
2017-01-16 22:38:18 +00:00
# so that quit won't loop
self.quitAccepted = False
self.init_file_menu()
self.init_inbox_popup_menu()
self.init_identities_popup_menu()
self.init_addressbook_popup_menu()
self.init_subscriptions_popup_menu()
2015-03-21 10:37:08 +00:00
self.init_chan_popup_menu()
self.init_sent_popup_menu()
2016-03-17 21:09:46 +00:00
2015-03-21 10:37:08 +00:00
# Initialize the user's list of addresses on the 'Chan' tab.
self.rerenderTabTreeChans()
2015-03-21 10:37:08 +00:00
# Initialize the user's list of addresses on the 'Messages' tab.
self.rerenderTabTreeMessages()
2015-03-21 10:37:08 +00:00
# Set welcome message
self.ui.textEditInboxMessage.setText(_translate("MainWindow", """
2015-03-21 10:37:08 +00:00
Welcome to easy and secure Bitmessage
* send messages to other people
2015-03-21 10:37:08 +00:00
* send broadcast messages like twitter or
* discuss in chan(nel)s with other people
"""))
2013-05-02 15:53:54 +00:00
# Initialize the address book
self.rerenderAddressBook()
# Initialize the Subscriptions
self.rerenderSubscriptions()
2013-05-02 15:53:54 +00:00
2013-07-12 08:24:24 +00:00
# Initialize the inbox search
QtCore.QObject.connect(self.ui.inboxSearchLineEdit, QtCore.SIGNAL(
"returnPressed()"), self.inboxSearchLineEditReturnPressed)
QtCore.QObject.connect(self.ui.inboxSearchLineEditSubscriptions, QtCore.SIGNAL(
"returnPressed()"), self.inboxSearchLineEditReturnPressed)
QtCore.QObject.connect(self.ui.inboxSearchLineEditChans, QtCore.SIGNAL(
"returnPressed()"), self.inboxSearchLineEditReturnPressed)
QtCore.QObject.connect(self.ui.inboxSearchLineEdit, QtCore.SIGNAL(
"textChanged(QString)"), self.inboxSearchLineEditUpdated)
QtCore.QObject.connect(self.ui.inboxSearchLineEditSubscriptions, QtCore.SIGNAL(
"textChanged(QString)"), self.inboxSearchLineEditUpdated)
QtCore.QObject.connect(self.ui.inboxSearchLineEditChans, QtCore.SIGNAL(
"textChanged(QString)"), self.inboxSearchLineEditUpdated)
2013-07-12 08:24:24 +00:00
# Initialize addressbook
QtCore.QObject.connect(self.ui.tableWidgetAddressBook, QtCore.SIGNAL(
"itemChanged(QTableWidgetItem *)"), self.tableWidgetAddressBookItemChanged)
# This is necessary for the completer to work if multiple recipients
QtCore.QObject.connect(self.ui.lineEditTo, QtCore.SIGNAL(
"cursorPositionChanged(int, int)"), self.ui.lineEditTo.completer().onCursorPositionChanged)
# show messages from message list
QtCore.QObject.connect(self.ui.tableWidgetInbox, QtCore.SIGNAL(
"itemSelectionChanged ()"), self.tableWidgetInboxItemClicked)
QtCore.QObject.connect(self.ui.tableWidgetInboxSubscriptions, QtCore.SIGNAL(
"itemSelectionChanged ()"), self.tableWidgetInboxItemClicked)
QtCore.QObject.connect(self.ui.tableWidgetInboxChans, QtCore.SIGNAL(
"itemSelectionChanged ()"), self.tableWidgetInboxItemClicked)
# tree address lists
2015-03-21 10:37:08 +00:00
QtCore.QObject.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL(
"itemSelectionChanged ()"), self.treeWidgetItemClicked)
QtCore.QObject.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL(
"itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged)
2015-03-21 10:37:08 +00:00
QtCore.QObject.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL(
"itemSelectionChanged ()"), self.treeWidgetItemClicked)
QtCore.QObject.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL(
"itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged)
QtCore.QObject.connect(self.ui.treeWidgetChans, QtCore.SIGNAL(
"itemSelectionChanged ()"), self.treeWidgetItemClicked)
QtCore.QObject.connect(self.ui.treeWidgetChans, QtCore.SIGNAL(
"itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged)
QtCore.QObject.connect(
self.ui.tabWidget, QtCore.SIGNAL("currentChanged(int)"),
self.tabWidgetCurrentChanged
)
# Put the colored icon on the status bar
2016-03-16 17:04:18 +00:00
# self.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/yellowicon.png"))
self.setStatusBar(BMStatusBar())
2013-05-02 15:53:54 +00:00
self.statusbar = self.statusBar()
2016-03-16 17:04:18 +00:00
self.pushButtonStatusIcon = QtGui.QPushButton(self)
self.pushButtonStatusIcon.setText('')
self.pushButtonStatusIcon.setIcon(
QtGui.QIcon(':/newPrefix/images/redicon.png'))
2016-03-16 17:04:18 +00:00
self.pushButtonStatusIcon.setFlat(True)
self.statusbar.insertPermanentWidget(0, self.pushButtonStatusIcon)
QtCore.QObject.connect(self.pushButtonStatusIcon, QtCore.SIGNAL(
"clicked()"), self.click_pushButtonStatusIcon)
2013-05-02 15:53:54 +00:00
self.numberOfMessagesProcessed = 0
self.numberOfBroadcastsProcessed = 0
self.numberOfPubkeysProcessed = 0
self.unreadCount = 0
2013-05-02 15:53:54 +00:00
# Set the icon sizes for the identicons
identicon_size = 3 * 7
self.ui.tableWidgetInbox.setIconSize(QtCore.QSize(identicon_size, identicon_size))
self.ui.treeWidgetChans.setIconSize(QtCore.QSize(identicon_size, identicon_size))
self.ui.treeWidgetYourIdentities.setIconSize(QtCore.QSize(identicon_size, identicon_size))
2015-03-21 10:37:08 +00:00
self.ui.treeWidgetSubscriptions.setIconSize(QtCore.QSize(identicon_size, identicon_size))
self.ui.tableWidgetAddressBook.setIconSize(QtCore.QSize(identicon_size, identicon_size))
2016-03-16 18:27:12 +00:00
self.UISignalThread = UISignaler.get()
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
2015-03-09 06:35:32 +00:00
"updateSentItemStatusByToAddress(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByToAddress)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByAckdata)
QtCore.QObject.connect(
self.UISignalThread, QtCore.SIGNAL(
"displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),
self.displayNewInboxMessage)
QtCore.QObject.connect(
self.UISignalThread, QtCore.SIGNAL(
("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,"
"PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)")),
self.displayNewSentMessage)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"setStatusIcon(PyQt_PyObject)"), self.setStatusIcon)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"changedInboxUnread(PyQt_PyObject)"), self.changedInboxUnread)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"rerenderMessagelistFromLabels()"), self.rerenderMessagelistFromLabels)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"rerenderMessgelistToLabels()"), self.rerenderMessagelistToLabels)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"rerenderAddressBook()"), self.rerenderAddressBook)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"rerenderSubscriptions()"), self.rerenderSubscriptions)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"removeInboxRowByMsgid(PyQt_PyObject)"), self.removeInboxRowByMsgid)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"newVersionAvailable(PyQt_PyObject)"), self.newVersionAvailable)
2013-09-05 00:14:25 +00:00
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"displayAlert(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayAlert)
2013-05-02 15:53:54 +00:00
self.UISignalThread.start()
# Key press in tree view
self.ui.treeWidgetYourIdentities.keyPressEvent = self.treeWidgetKeyPressEvent
self.ui.treeWidgetSubscriptions.keyPressEvent = self.treeWidgetKeyPressEvent
self.ui.treeWidgetChans.keyPressEvent = self.treeWidgetKeyPressEvent
# Key press in messagelist
self.ui.tableWidgetInbox.keyPressEvent = self.tableWidgetKeyPressEvent
self.ui.tableWidgetInboxSubscriptions.keyPressEvent = self.tableWidgetKeyPressEvent
self.ui.tableWidgetInboxChans.keyPressEvent = self.tableWidgetKeyPressEvent
# Key press in messageview
self.ui.textEditInboxMessage.keyPressEvent = self.textEditKeyPressEvent
self.ui.textEditInboxMessageSubscriptions.keyPressEvent = self.textEditKeyPressEvent
self.ui.textEditInboxMessageChans.keyPressEvent = self.textEditKeyPressEvent
# Below this point, it would be good if all of the necessary global data
# structures were initialized.
2013-05-02 15:53:54 +00:00
self.rerenderComboBoxSendFrom()
2015-03-21 10:37:08 +00:00
self.rerenderComboBoxSendFromBroadcast()
2015-03-03 19:04:12 +00:00
# Put the TTL slider in the correct spot
TTL = BMConfigParser().getint('bitmessagesettings', 'ttl')
if TTL < 3600: # an hour
2015-03-03 19:04:12 +00:00
TTL = 3600
elif TTL > 28 * 24 * 60 * 60: # 28 days
TTL = 28 * 24 * 60 * 60
self.ui.horizontalSliderTTL.setSliderPosition((TTL - 3600) ** (1 / 3.199))
2015-03-03 19:04:12 +00:00
self.updateHumanFriendlyTTLDescription(TTL)
2015-03-03 19:04:12 +00:00
QtCore.QObject.connect(self.ui.horizontalSliderTTL, QtCore.SIGNAL(
"valueChanged(int)"), self.updateTTL)
self.initSettings()
self.namecoin = namecoinConnection()
# Check to see whether we can connect to namecoin.
# Hide the 'Fetch Namecoin ID' button if we can't.
if BMConfigParser().safeGetBoolean(
'bitmessagesettings', 'dontconnect'
) or self.namecoin.test()[0] == 'failed':
logger.warning(
'There was a problem testing for a Namecoin daemon. Hiding the'
' Fetch Namecoin ID button')
2015-03-21 10:37:08 +00:00
self.ui.pushButtonFetchNamecoinID.hide()
2015-03-19 17:44:10 +00:00
def updateTTL(self, sliderPosition):
"""TBC"""
2015-03-19 17:44:10 +00:00
TTL = int(sliderPosition ** 3.199 + 3600)
self.updateHumanFriendlyTTLDescription(TTL)
BMConfigParser().set('bitmessagesettings', 'ttl', str(TTL))
BMConfigParser().save()
2015-03-19 17:44:10 +00:00
def updateHumanFriendlyTTLDescription(self, TTL):
"""TBC"""
numberOfHours = int(round(TTL / (60 * 60)))
font = QtGui.QFont()
stylesheet = ""
2015-03-19 17:44:10 +00:00
if numberOfHours < 48:
self.ui.labelHumanFriendlyTTLDescription.setText(
_translate("MainWindow", "%n hour(s)", None, QtCore.QCoreApplication.CodecForTr, numberOfHours) +
", " +
_translate("MainWindow", "not recommended for chans", None, QtCore.QCoreApplication.CodecForTr)
)
stylesheet = "QLabel { color : red; }"
font.setBold(True)
2015-03-19 17:44:10 +00:00
else:
numberOfDays = int(round(TTL / (24 * 60 * 60)))
self.ui.labelHumanFriendlyTTLDescription.setText(
_translate(
"MainWindow",
"%n day(s)",
None,
QtCore.QCoreApplication.CodecForTr,
numberOfDays))
font.setBold(False)
self.ui.labelHumanFriendlyTTLDescription.setStyleSheet(stylesheet)
self.ui.labelHumanFriendlyTTLDescription.setFont(font)
def appIndicatorShowOrHideWindow(self):
"""
Show or hide the application window after clicking an item within the tray icon or, on Windows,
the try icon itself.
"""
if not self.actionShow.isChecked():
self.hide()
else:
self.show()
self.setWindowState(
self.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)
self.raise_()
2013-05-15 16:36:30 +00:00
self.activateWindow()
def appIndicatorShow(self):
"""show the application window"""
if self.actionShow is None:
return
2013-05-14 15:44:51 +00:00
if not self.actionShow.isChecked():
self.actionShow.setChecked(True)
self.appIndicatorShowOrHideWindow()
def appIndicatorHide(self):
"""unchecks the show item on the application indicator"""
if self.actionShow is None:
return
2013-05-14 15:44:51 +00:00
if self.actionShow.isChecked():
self.actionShow.setChecked(False)
self.appIndicatorShowOrHideWindow()
def appIndicatorSwitchQuietMode(self):
"""TBC"""
BMConfigParser().set(
'bitmessagesettings', 'showtraynotifications',
str(not self.actionQuiet.isChecked())
)
def appIndicatorInbox(self, item=None):
"""Show the program window and select inbox tab"""
self.appIndicatorShow()
# select inbox
self.ui.tabWidget.setCurrentIndex(
self.ui.tabWidget.indexOf(self.ui.inbox)
)
self.ui.treeWidgetYourIdentities.setCurrentItem(
self.ui.treeWidgetYourIdentities.topLevelItem(0).child(0)
)
if item:
self.ui.tableWidgetInbox.setCurrentItem(item)
self.tableWidgetInboxItemClicked()
else:
self.ui.tableWidgetInbox.setCurrentCell(0, 0)
def appIndicatorSend(self):
"""Show the program window and select send tab"""
self.appIndicatorShow()
self.ui.tabWidget.setCurrentIndex(
self.ui.tabWidget.indexOf(self.ui.send)
)
def appIndicatorSubscribe(self):
"""Show the program window and select subscriptions tab"""
self.appIndicatorShow()
self.ui.tabWidget.setCurrentIndex(
self.ui.tabWidget.indexOf(self.ui.subscriptions)
)
def appIndicatorChannel(self):
"""Show the program window and select channels tab"""
self.appIndicatorShow()
self.ui.tabWidget.setCurrentIndex(
self.ui.tabWidget.indexOf(self.ui.chans)
)
def updateUnreadStatus(self, widget, row, msgid, unread=True):
"""
Switch unread for item of msgid and related items in
other STableWidgets "All Accounts" and "Chans"
"""
related = [self.ui.tableWidgetInbox, self.ui.tableWidgetInboxChans]
try:
related.remove(widget)
related = related.pop()
except ValueError:
rrow = None
related = []
else:
# maybe use instead:
# rrow = related.row(msgid), msgid should be QTableWidgetItem
# related = related.findItems(msgid, QtCore.Qt.MatchExactly),
# returns an empty list
for rrow in xrange(related.rowCount()):
if msgid == str(related.item(rrow, 3).data(
QtCore.Qt.UserRole).toPyObject()):
break
else:
rrow = None
status = widget.item(row, 0).unread
if status == unread:
font = QtGui.QFont()
font.setBold(not status)
widget.item(row, 3).setFont(font)
for col in (0, 1, 2):
widget.item(row, col).setUnread(not status)
try:
related.item(rrow, 3).setFont(font)
except (TypeError, AttributeError):
pass
else:
for col in (0, 1, 2):
related.item(rrow, col).setUnread(not status)
def propagateUnreadCount(self, address=None, folder="inbox", widget=None, type_arg=1):
"""TBC"""
widgets = [self.ui.treeWidgetYourIdentities, self.ui.treeWidgetSubscriptions, self.ui.treeWidgetChans]
queryReturn = sqlQuery(
"SELECT toaddress, folder, COUNT(msgid) AS cnt FROM inbox WHERE read = 0 GROUP BY toaddress, folder")
totalUnread = {}
normalUnread = {}
for row in queryReturn:
normalUnread[row[0]] = {}
if row[1] in ["trash"]:
continue
normalUnread[row[0]][row[1]] = row[2]
if row[1] in totalUnread:
totalUnread[row[1]] += row[2]
else:
totalUnread[row[1]] = row[2]
queryReturn = sqlQuery(
"SELECT fromaddress, folder, COUNT(msgid) AS cnt FROM inbox "
2018-05-17 09:51:21 +00:00
"WHERE read = 0 AND toaddress = ? GROUP BY fromaddress, folder",
str_broadcast_subscribers)
broadcastsUnread = {}
for row in queryReturn:
broadcastsUnread[row[0]] = {}
broadcastsUnread[row[0]][row[1]] = row[2]
for treeWidget in widgets:
root = treeWidget.invisibleRootItem()
for i in range(root.childCount()):
addressItem = root.child(i)
newCount = 0
if addressItem.type == AccountMixin.ALL:
newCount = sum(totalUnread.itervalues())
self.drawTrayIcon(self.currentTrayIconFileName, newCount)
elif addressItem.type == AccountMixin.SUBSCRIPTION:
if addressItem.address in broadcastsUnread:
newCount = sum(broadcastsUnread[addressItem.address].itervalues())
elif addressItem.address in normalUnread:
newCount = sum(normalUnread[addressItem.address].itervalues())
if newCount != addressItem.unreadCount:
addressItem.setUnreadCount(newCount)
if addressItem.childCount == 0:
continue
for j in range(addressItem.childCount()):
folderItem = addressItem.child(j)
newCount = 0
folderName = folderItem.folderName
if folderName == "new":
folderName = "inbox"
if addressItem.type == AccountMixin.ALL and folderName in totalUnread:
newCount = totalUnread[folderName]
elif addressItem.type == AccountMixin.SUBSCRIPTION:
if addressItem.address in broadcastsUnread and folderName in broadcastsUnread[
addressItem.address]:
newCount = broadcastsUnread[addressItem.address][folderName]
elif addressItem.address in normalUnread and folderName in normalUnread[addressItem.address]:
newCount = normalUnread[addressItem.address][folderName]
if newCount != folderItem.unreadCount:
folderItem.setUnreadCount(newCount)
def addMessageListItem(self, tableWidget, items):
"""TBC"""
sortingEnabled = tableWidget.isSortingEnabled()
if sortingEnabled:
tableWidget.setSortingEnabled(False)
tableWidget.insertRow(0)
for i, _ in enumerate(items):
tableWidget.setItem(0, i, items[i])
if sortingEnabled:
tableWidget.setSortingEnabled(True)
def addMessageListItemSent(self, tableWidget, toAddress, fromAddress, subject, status, ackdata, lastactiontime):
"""TBC"""
acct = accountClass(fromAddress)
2016-03-22 15:30:12 +00:00
if acct is None:
acct = BMAccount(fromAddress)
acct.parseMessage(toAddress, fromAddress, subject, "")
items = []
MessageList_AddressWidget(items, str(toAddress), unicode(acct.toLabel, 'utf-8'))
MessageList_AddressWidget(items, str(fromAddress), unicode(acct.fromLabel, 'utf-8'))
MessageList_SubjectWidget(items, str(subject), unicode(acct.subject, 'utf-8', 'replace'))
if status == 'awaitingpubkey':
statusText = _translate(
"MainWindow", "Waiting for their encryption key. Will request it again soon.")
elif status == 'doingpowforpubkey':
statusText = _translate(
"MainWindow", "Doing work necessary to request encryption key.")
elif status == 'msgqueued':
statusText = _translate(
"MainWindow", "Queued.")
elif status == 'msgsent':
statusText = _translate("MainWindow", "Message sent. Waiting for acknowledgement. Sent at %1").arg(
l10n.formatTimestamp(lastactiontime))
elif status == 'msgsentnoackexpected':
statusText = _translate("MainWindow", "Message sent. Sent at %1").arg(
l10n.formatTimestamp(lastactiontime))
elif status == 'doingmsgpow':
statusText = _translate(
"MainWindow", "Doing work necessary to send message.")
elif status == 'ackreceived':
statusText = _translate("MainWindow", "Acknowledgement of the message received %1").arg(
l10n.formatTimestamp(lastactiontime))
elif status == 'broadcastqueued':
statusText = _translate(
"MainWindow", "Broadcast queued.")
elif status == 'doingbroadcastpow':
statusText = _translate(
"MainWindow", "Doing work necessary to send broadcast.")
elif status == 'broadcastsent':
statusText = _translate(
"MainWindow", "Broadcast on %1").arg(
l10n.formatTimestamp(lastactiontime))
elif status == 'toodifficult':
statusText = _translate(
"MainWindow",
"Problem: The work demanded by the recipient is more difficult than you are willing to do. %1").arg(
l10n.formatTimestamp(lastactiontime))
elif status == 'badkey':
statusText = _translate(
"MainWindow",
"Problem: The recipient\'s encryption key is no good. Could not encrypt message. %1").arg(
l10n.formatTimestamp(lastactiontime))
elif status == 'forcepow':
statusText = _translate(
"MainWindow", "Forced difficulty override. Send should start soon.")
else:
statusText = _translate("MainWindow", "Unknown status: %1 %2").arg(status).arg(
l10n.formatTimestamp(lastactiontime))
newItem = myTableWidgetItem(statusText)
newItem.setToolTip(statusText)
newItem.setData(QtCore.Qt.UserRole, QtCore.QByteArray(ackdata))
newItem.setData(33, int(lastactiontime))
newItem.setFlags(
QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
items.append(newItem)
self.addMessageListItem(tableWidget, items)
return acct
def addMessageListItemInbox(self, tableWidget, msgfolder, msgid, toAddress, fromAddress, subject, received, read):
"""TBC"""
font = QtGui.QFont()
font.setBold(True)
if toAddress == str_broadcast_subscribers:
acct = accountClass(fromAddress)
else:
acct = accountClass(toAddress)
2015-12-19 23:59:25 +00:00
if acct is None:
acct = accountClass(fromAddress)
if acct is None:
acct = BMAccount(fromAddress)
acct.parseMessage(toAddress, fromAddress, subject, "")
items = []
# to
MessageList_AddressWidget(items, toAddress, unicode(acct.toLabel, 'utf-8'), not read)
# from
MessageList_AddressWidget(items, fromAddress, unicode(acct.fromLabel, 'utf-8'), not read)
# subject
MessageList_SubjectWidget(items, str(subject), unicode(acct.subject, 'utf-8', 'replace'), not read)
# time received
time_item = myTableWidgetItem(l10n.formatTimestamp(received))
time_item.setToolTip(l10n.formatTimestamp(received))
time_item.setData(QtCore.Qt.UserRole, QtCore.QByteArray(msgid))
time_item.setData(33, int(received))
time_item.setFlags(
QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
if not read:
time_item.setFont(font)
items.append(time_item)
self.addMessageListItem(tableWidget, items)
return acct
def loadSent(self, tableWidget, account, where="", what=""):
"""Load Sent items from database"""
if tableWidget == self.ui.tableWidgetInboxSubscriptions:
tableWidget.setColumnHidden(0, True)
tableWidget.setColumnHidden(1, False)
xAddress = 'toaddress'
elif tableWidget == self.ui.tableWidgetInboxChans:
tableWidget.setColumnHidden(0, False)
tableWidget.setColumnHidden(1, True)
xAddress = 'both'
else:
tableWidget.setColumnHidden(0, False)
2016-03-16 17:30:47 +00:00
if account is None:
tableWidget.setColumnHidden(1, False)
else:
tableWidget.setColumnHidden(1, True)
xAddress = 'fromaddress'
2013-07-12 08:42:52 +00:00
tableWidget.setUpdatesEnabled(False)
tableWidget.setSortingEnabled(False)
2015-11-01 09:09:04 +00:00
tableWidget.setRowCount(0)
queryreturn = helper_search.search_sql(xAddress, account, "sent", where, what, False)
2013-07-12 08:24:24 +00:00
for row in queryreturn:
toAddress, fromAddress, subject, status, ackdata, lastactiontime = row
self.addMessageListItemSent(tableWidget, toAddress, fromAddress, subject, status, ackdata, lastactiontime)
tableWidget.horizontalHeader().setSortIndicator(
3, QtCore.Qt.DescendingOrder)
tableWidget.setSortingEnabled(True)
tableWidget.horizontalHeaderItem(3).setText(_translate("MainWindow", "Sent", None))
tableWidget.setUpdatesEnabled(True)
2013-07-12 08:24:24 +00:00
def loadMessagelist(self, tableWidget, account, folder="inbox", where="", what="", unreadOnly=False):
"""Load messages from database file"""
if folder == 'sent':
self.loadSent(tableWidget, account, where, what)
return
if tableWidget == self.ui.tableWidgetInboxSubscriptions:
xAddress = "fromaddress"
else:
xAddress = "toaddress"
if account is not None:
tableWidget.setColumnHidden(0, True)
tableWidget.setColumnHidden(1, False)
else:
tableWidget.setColumnHidden(0, False)
tableWidget.setColumnHidden(1, False)
tableWidget.setUpdatesEnabled(False)
tableWidget.setSortingEnabled(False)
tableWidget.setRowCount(0)
queryreturn = helper_search.search_sql(xAddress, account, folder, where, what, unreadOnly)
2015-03-19 17:25:50 +00:00
for row in queryreturn:
msgfolder, msgid, toAddress, fromAddress, subject, received, read = row
self.addMessageListItemInbox(tableWidget, msgfolder, msgid, toAddress,
fromAddress, subject, received, read)
2015-03-19 17:25:50 +00:00
tableWidget.horizontalHeader().setSortIndicator(
3, QtCore.Qt.DescendingOrder)
tableWidget.setSortingEnabled(True)
tableWidget.selectRow(0)
tableWidget.horizontalHeaderItem(3).setText(_translate("MainWindow", "Received", None))
tableWidget.setUpdatesEnabled(True)
2015-03-19 17:25:50 +00:00
def appIndicatorInit(self, this_app):
"""create application indicator"""
self.initTrayIcon("can-icon-24px-red.png", this_app)
traySignal = "activated(QSystemTrayIcon::ActivationReason)"
QtCore.QObject.connect(self.tray, QtCore.SIGNAL(
traySignal), self.__icon_activated)
2013-05-14 15:44:51 +00:00
m = QtGui.QMenu()
self.actionStatus = QtGui.QAction(_translate(
"MainWindow", "Not Connected"), m, checkable=False)
m.addAction(self.actionStatus)
2013-05-07 21:58:47 +00:00
# separator
actionSeparator = QtGui.QAction('', m, checkable=False)
2013-05-07 21:58:47 +00:00
actionSeparator.setSeparator(True)
m.addAction(actionSeparator)
# show bitmessage
self.actionShow = QtGui.QAction(_translate(
"MainWindow", "Show Bitmessage"), m, checkable=True)
self.actionShow.setChecked(not BMConfigParser().getboolean(
'bitmessagesettings', 'startintray'))
self.actionShow.triggered.connect(self.appIndicatorShowOrHideWindow)
if sys.platform[0:3] != 'win':
m.addAction(self.actionShow)
# quiet mode
self.actionQuiet = QtGui.QAction(_translate(
"MainWindow", "Quiet Mode"), m, checkable=True)
self.actionQuiet.setChecked(not BMConfigParser().getboolean(
'bitmessagesettings', 'showtraynotifications'))
self.actionQuiet.triggered.connect(self.appIndicatorSwitchQuietMode)
m.addAction(self.actionQuiet)
# Send
actionSend = QtGui.QAction(_translate(
"MainWindow", "Send"), m, checkable=False)
actionSend.triggered.connect(self.appIndicatorSend)
m.addAction(actionSend)
# Subscribe
actionSubscribe = QtGui.QAction(_translate(
"MainWindow", "Subscribe"), m, checkable=False)
actionSubscribe.triggered.connect(self.appIndicatorSubscribe)
m.addAction(actionSubscribe)
# Channels
actionSubscribe = QtGui.QAction(_translate(
"MainWindow", "Channel"), m, checkable=False)
actionSubscribe.triggered.connect(self.appIndicatorChannel)
m.addAction(actionSubscribe)
2013-05-07 21:58:47 +00:00
# separator
actionSeparator = QtGui.QAction('', m, checkable=False)
2013-05-07 21:58:47 +00:00
actionSeparator.setSeparator(True)
m.addAction(actionSeparator)
# Quit
m.addAction(_translate(
"MainWindow", "Quit"), self.quit)
2013-05-14 15:44:51 +00:00
self.tray.setContextMenu(m)
self.tray.show()
def getUnread(self):
"""returns the number of unread messages and subscriptions"""
counters = [0, 0]
queryreturn = sqlQuery('''
SELECT msgid, toaddress, read FROM inbox where folder='inbox'
''')
for msgid, toAddress, read in queryreturn:
if not read:
# increment the unread subscriptions if True (1)
# else messages (0)
counters[toAddress == str_broadcast_subscribers] += 1
return counters
def playSound(self, category, label): # pylint: disable=inconsistent-return-statements
"""play a sound"""
2013-08-01 13:48:01 +00:00
# filename of the sound to be played
soundFilename = None
2013-08-01 13:48:01 +00:00
def _choose_ext(basename): # pylint: disable=inconsistent-return-statements
"""TBC"""
for ext in sound.extensions:
if os.path.isfile(os.extsep.join([basename, ext])):
return os.extsep + ext
2013-08-01 13:48:01 +00:00
# if the address had a known label in the address book
if label:
# Does a sound file exist for this particular contact?
soundFilename = state.appdata + 'sounds/' + label
ext = _choose_ext(soundFilename)
if not ext:
category = sound.SOUND_KNOWN
soundFilename = None
if soundFilename is None:
# Avoid making sounds more frequently than the threshold.
# This suppresses playing sounds repeatedly when there
# are many new messages
if not sound.is_connection_sound(category):
# elapsed time since the last sound was played
dt = datetime.now() - self.lastSoundTime
# suppress sounds which are more frequent than the threshold
if not dt.total_seconds() < self.maxSoundFrequencySec:
# the sound is for an address which exists in the address book
if category is sound.SOUND_KNOWN:
soundFilename = state.appdata + 'sounds/known'
# the sound is for an unknown address
elif category is sound.SOUND_UNKNOWN:
soundFilename = state.appdata + 'sounds/unknown'
# initial connection sound
elif category is sound.SOUND_CONNECTED:
soundFilename = state.appdata + 'sounds/connected'
# disconnected sound
elif category is sound.SOUND_DISCONNECTED:
soundFilename = state.appdata + 'sounds/disconnected'
# sound when the connection status becomes green
elif category is sound.SOUND_CONNECTION_GREEN:
soundFilename = state.appdata + 'sounds/green'
if soundFilename is None:
logger.warning("Probably wrong category number in playSound()")
return
if not sound.is_connection_sound(category):
# record the last time that a received message sound was played
self.lastSoundTime = datetime.now()
try: # try already known format
soundFilename += ext
except (TypeError, NameError):
ext = _choose_ext(soundFilename)
if not ext:
try: # if no user sound file found try to play from theme
return self._theme_player(category, label)
except TypeError:
return
soundFilename += ext
self._player(soundFilename)
def sqlInit(self):
"""Adapters and converters for QT <-> sqlite"""
register_adapter(QtCore.QByteArray, str)
def indicatorInit(self):
""" Try init the distro specific appindicator, for example the Ubuntu MessagingMenu"""
def _noop_update(*args, **kwargs):
pass
try:
self.indicatorUpdate = get_plugin('indicator')(self)
except (NameError, TypeError):
2017-12-01 23:45:01 +00:00
logger.warning("No indicator plugin found")
self.indicatorUpdate = _noop_update
def notifierInit(self):
"""initialise the message notifier"""
def _simple_notify(
title, subtitle, category, label=None, icon=None):
self.tray.showMessage(title, subtitle, 1, 2000)
self._notifier = _simple_notify
2017-03-10 14:45:46 +00:00
# does nothing if isAvailable returns false
self._player = QtGui.QSound.play
if not get_plugins:
return
2017-03-10 14:45:46 +00:00
_plugin = get_plugin('notification.message')
if _plugin:
self._notifier = _plugin
else:
logger.warning("No notification.message plugin found")
self._theme_player = get_plugin('notification.sound', 'theme')
if not QtGui.QSound.isAvailable():
2017-03-10 14:45:46 +00:00
_plugin = get_plugin(
'notification.sound', 'file', fallback='file.fallback')
if _plugin:
self._player = _plugin
else:
logger.warning("No notification.sound plugin found")
def notifierShow(
self, title, subtitle, category, label=None, icon=None):
"""TBC"""
self.playSound(category, label)
self._notifier(
unicode(title), unicode(subtitle), category, label, icon)
def treeWidgetKeyPressEvent(self, event):
"""tree"""
return self.handleKeyPress(event, self.getCurrentTreeWidget())
def tableWidgetKeyPressEvent(self, event):
"""inbox / sent"""
return self.handleKeyPress(event, self.getCurrentMessagelist())
def textEditKeyPressEvent(self, event):
"""messageview"""
return self.handleKeyPress(event, self.getCurrentMessageTextedit())
2013-05-02 15:53:54 +00:00
def handleKeyPress(self, event, focus=None): # pylint: disable=inconsistent-return-statements
"""TBC"""
messagelist = self.getCurrentMessagelist()
folder = self.getCurrentFolder()
if event.key() == QtCore.Qt.Key_Delete:
if isinstance(focus, (MessageView, QtGui.QTableWidget)):
if folder == "sent":
self.on_action_SentTrash()
else:
self.on_action_InboxTrash()
event.ignore()
elif QtGui.QApplication.queryKeyboardModifiers() == QtCore.Qt.NoModifier:
if event.key() == QtCore.Qt.Key_N:
currentRow = messagelist.currentRow()
if currentRow < messagelist.rowCount() - 1:
messagelist.selectRow(currentRow + 1)
event.ignore()
elif event.key() == QtCore.Qt.Key_P:
currentRow = messagelist.currentRow()
if currentRow > 0:
messagelist.selectRow(currentRow - 1)
event.ignore()
elif event.key() == QtCore.Qt.Key_R:
if messagelist == self.ui.tableWidgetInboxChans:
self.on_action_InboxReplyChan()
else:
self.on_action_InboxReply()
event.ignore()
elif event.key() == QtCore.Qt.Key_C:
currentAddress = self.getCurrentAccount()
if currentAddress:
self.setSendFromComboBox(currentAddress)
self.ui.tabWidgetSend.setCurrentIndex(
self.ui.tabWidgetSend.indexOf(self.ui.sendDirect)
)
self.ui.tabWidget.setCurrentIndex(
self.ui.tabWidget.indexOf(self.ui.send)
)
self.ui.lineEditTo.setFocus()
event.ignore()
elif event.key() == QtCore.Qt.Key_F:
searchline = self.getCurrentSearchLine(retObj=True)
if searchline:
searchline.setFocus()
event.ignore()
if not event.isAccepted():
return
if isinstance(focus, MessageView):
return MessageView.keyPressEvent(focus, event)
elif isinstance(focus, QtGui.QTableWidget):
return QtGui.QTableWidget.keyPressEvent(focus, event)
elif isinstance(focus, QtGui.QTreeWidget):
return QtGui.QTreeWidget.keyPressEvent(focus, event)
2013-05-02 15:53:54 +00:00
def click_actionManageKeys(self):
"""menu button 'manage keys'"""
2013-05-02 15:53:54 +00:00
if 'darwin' in sys.platform or 'linux' in sys.platform:
if state.appdata == '':
# reply = QtGui.QMessageBox.information(self, 'keys.dat?','You
# may manage your keys by editing the keys.dat file stored in
# the same directory as this program. It is important that you
# back up this file.', QMessageBox.Ok)
reply = QtGui.QMessageBox.information(
self,
'keys.dat?',
_translate(
"MainWindow",
("You may manage your keys by editing the keys.dat file stored in the same directory as this "
"program. It is important that you back up this file.")),
QtGui.QMessageBox.Ok)
2013-06-12 12:22:04 +00:00
2013-05-02 15:53:54 +00:00
else:
QtGui.QMessageBox.information(
self,
'keys.dat?',
_translate(
"MainWindow",
("You may manage your keys by editing the keys.dat file stored in\n %1 \nIt is important "
"that you back up this file.")).arg(
state.appdata),
QtGui.QMessageBox.Ok)
2013-05-02 15:53:54 +00:00
elif sys.platform == 'win32' or sys.platform == 'win64':
if state.appdata == '':
reply = QtGui.QMessageBox.question(
self,
_translate(
"MainWindow",
"Open keys.dat?"),
_translate(
"MainWindow",
("You may manage your keys by editing the keys.dat file stored in the same directory as this "
"program. It is important that you back up this file. Would you like to open the file now? "
"(Be sure to close Bitmessage before making any changes.)")),
QtGui.QMessageBox.Yes,
QtGui.QMessageBox.No)
2013-05-02 15:53:54 +00:00
else:
reply = QtGui.QMessageBox.question(
self,
_translate(
"MainWindow",
"Open keys.dat?"),
_translate(
"MainWindow",
("You may manage your keys by editing the keys.dat file stored in\n %1 \nIt is important "
"that you back up this file. Would you like to open the file now? (Be sure to close "
"Bitmessage before making any changes.)")).arg(
state.appdata),
QtGui.QMessageBox.Yes,
QtGui.QMessageBox.No)
2013-05-02 15:53:54 +00:00
if reply == QtGui.QMessageBox.Yes:
shared.openKeysFile()
2013-05-02 15:53:54 +00:00
def click_actionDeleteAllTrashedMessages(self):
"""menu button 'delete all treshed messages'"""
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:
return
2013-08-27 00:01:19 +00:00
sqlStoredProcedure('deleteandvacuume')
self.rerenderTabTreeMessages()
self.rerenderTabTreeSubscriptions()
self.rerenderTabTreeChans()
if self.getCurrentFolder(self.ui.treeWidgetYourIdentities) == "trash":
self.loadMessagelist(
self.ui.tableWidgetInbox, self.getCurrentAccount(
self.ui.treeWidgetYourIdentities), "trash")
elif self.getCurrentFolder(self.ui.treeWidgetSubscriptions) == "trash":
self.loadMessagelist(
self.ui.tableWidgetInboxSubscriptions,
self.getCurrentAccount(
self.ui.treeWidgetSubscriptions),
"trash")
elif self.getCurrentFolder(self.ui.treeWidgetChans) == "trash":
self.loadMessagelist(
self.ui.tableWidgetInboxChans,
self.getCurrentAccount(
self.ui.treeWidgetChans),
"trash")
2013-05-02 15:53:54 +00:00
def click_actionRegenerateDeterministicAddresses(self):
"""menu button 'regenerate deterministic addresses'"""
dialog = dialogs.RegenerateAddressesDialog(self)
if dialog.exec_():
if dialog.lineEditPassphrase.text() == "":
QtGui.QMessageBox.about(
self, _translate("MainWindow", "bad passphrase"),
_translate(
"MainWindow",
"You must type your passphrase. If you don\'t"
" have one then this is not the form for you."
))
return
streamNumberForAddress = int(dialog.lineEditStreamNumber.text())
try:
addressVersionNumber = int(
dialog.lineEditAddressVersionNumber.text())
except:
QtGui.QMessageBox.about(
self,
_translate("MainWindow", "Bad address version number"),
_translate(
"MainWindow",
"Your address version number must be a number:"
" either 3 or 4."
))
return
if addressVersionNumber < 3 or addressVersionNumber > 4:
QtGui.QMessageBox.about(
self,
_translate("MainWindow", "Bad address version number"),
_translate(
"MainWindow",
"Your address version number must be either 3 or 4."
))
return
queues.addressGeneratorQueue.put((
'createDeterministicAddresses',
addressVersionNumber, streamNumberForAddress,
"regenerated deterministic address",
dialog.spinBoxNumberOfAddressesToMake.value(),
dialog.lineEditPassphrase.text().toUtf8(),
dialog.checkBoxEighteenByteRipe.isChecked()
))
self.ui.tabWidget.setCurrentIndex(
self.ui.tabWidget.indexOf(self.ui.chans)
)
2013-05-02 15:53:54 +00:00
2013-07-22 05:10:22 +00:00
def click_actionJoinChan(self):
"""opens 'join chan' dialog"""
dialogs.NewChanDialog(self)
2013-07-22 05:10:22 +00:00
def showConnectDialog(self):
"""TBC"""
dialog = dialogs.ConnectDialog(self)
if dialog.exec_():
if dialog.radioButtonConnectNow.isChecked():
BMConfigParser().remove_option(
'bitmessagesettings', 'dontconnect')
BMConfigParser().save()
elif dialog.radioButtonConfigureNetwork.isChecked():
self.click_actionSettings()
else:
self._firstrun = False
def showMigrationWizard(self, level):
"""TBC"""
self.migrationWizardInstance = Ui_MigrationWizard(["a"])
if self.migrationWizardInstance.exec_():
pass
else:
pass
2013-05-02 15:53:54 +00:00
def changeEvent(self, event):
"""TBC"""
if event.type() == QtCore.QEvent.LanguageChange:
self.ui.retranslateUi(self)
self.init_inbox_popup_menu(False)
self.init_identities_popup_menu(False)
2015-03-21 10:37:08 +00:00
self.init_chan_popup_menu(False)
self.init_addressbook_popup_menu(False)
self.init_subscriptions_popup_menu(False)
self.init_sent_popup_menu(False)
2016-03-17 21:09:46 +00:00
self.ui.blackwhitelist.init_blacklist_popup_menu(False)
if event.type() == QtCore.QEvent.WindowStateChange:
if self.windowState() & QtCore.Qt.WindowMinimized:
if BMConfigParser().getboolean('bitmessagesettings', 'minimizetotray'):
if 'darwin' not in sys.platform:
QtCore.QTimer.singleShot(0, self.appIndicatorHide)
2015-01-06 22:55:01 +00:00
elif event.oldState() & QtCore.Qt.WindowMinimized:
# The window state has just been changed to
# Normal/Maximised/FullScreen
pass
2013-05-02 15:53:54 +00:00
def __icon_activated(self, reason):
"""TBC"""
2013-05-02 15:53:54 +00:00
if reason == QtGui.QSystemTrayIcon.Trigger:
self.actionShow.setChecked(not self.actionShow.isChecked())
self.appIndicatorShowOrHideWindow()
# Indicates whether or not there is a connection to the Bitmessage network
connected = False
def setStatusIcon(self, color):
"""Set the status icon"""
_notifications_enabled = not BMConfigParser().getboolean(
'bitmessagesettings', 'hidetrayconnectionnotifications')
2013-05-02 15:53:54 +00:00
if color == 'red':
2016-03-16 17:04:18 +00:00
self.pushButtonStatusIcon.setIcon(
QtGui.QIcon(":/newPrefix/images/redicon.png"))
2013-05-02 15:53:54 +00:00
shared.statusIconColor = 'red'
# if the connection is lost then show a notification
if self.connected and _notifications_enabled:
self.notifierShow(
'Bitmessage',
_translate("MainWindow", "Connection lost"),
sound.SOUND_DISCONNECTED)
if not BMConfigParser().safeGetBoolean('bitmessagesettings', 'upnp') and \
BMConfigParser().get('bitmessagesettings', 'socksproxytype') == "none":
self.updateStatusBar(
_translate(
"MainWindow",
"Problems connecting? Try enabling UPnP in the Network"
" Settings"
))
self.connected = False
if self.actionStatus is not None:
self.actionStatus.setText(_translate(
"MainWindow", "Not Connected"))
self.setTrayIconFile("can-icon-24px-red.png")
2013-05-02 15:53:54 +00:00
if color == 'yellow':
if self.statusbar.currentMessage() == ('Warning: You are currently not connected. Bitmessage will do '
'the work necessary to send the message but it won\'t send until '
'you connect.'):
self.statusbar.clearMessage()
self.pushButtonStatusIcon.setIcon(
QtGui.QIcon(":/newPrefix/images/yellowicon.png"))
2013-05-02 15:53:54 +00:00
shared.statusIconColor = 'yellow'
# if a new connection has been established then show a notification
if not self.connected and _notifications_enabled:
self.notifierShow(
'Bitmessage',
_translate("MainWindow", "Connected"),
sound.SOUND_CONNECTED)
self.connected = True
if self.actionStatus is not None:
self.actionStatus.setText(_translate(
"MainWindow", "Connected"))
self.setTrayIconFile("can-icon-24px-yellow.png")
2013-05-02 15:53:54 +00:00
if color == 'green':
if self.statusbar.currentMessage() == ('Warning: You are currently not connected. Bitmessage will do the '
'work necessary to send the message but it won\'t send until you '
'connect.'):
self.statusbar.clearMessage()
2016-03-16 17:04:18 +00:00
self.pushButtonStatusIcon.setIcon(
QtGui.QIcon(":/newPrefix/images/greenicon.png"))
2013-05-02 15:53:54 +00:00
shared.statusIconColor = 'green'
if not self.connected and _notifications_enabled:
self.notifierShow(
'Bitmessage',
_translate("MainWindow", "Connected"),
sound.SOUND_CONNECTION_GREEN)
self.connected = True
if self.actionStatus is not None:
self.actionStatus.setText(_translate(
"MainWindow", "Connected"))
self.setTrayIconFile("can-icon-24px-green.png")
def initTrayIcon(self, iconFileName, this_app):
"""TBC"""
self.currentTrayIconFileName = iconFileName
self.tray = QtGui.QSystemTrayIcon(
self.calcTrayIcon(iconFileName, self.findInboxUnreadCount()), this_app)
def setTrayIconFile(self, iconFileName):
"""TBC"""
self.currentTrayIconFileName = iconFileName
self.drawTrayIcon(iconFileName, self.findInboxUnreadCount())
def calcTrayIcon(self, iconFileName, inboxUnreadCount):
"""TBC"""
pixmap = QtGui.QPixmap(":/newPrefix/images/" + iconFileName)
if inboxUnreadCount > 0:
# choose font and calculate font parameters
fontName = "Lucida"
fontSize = 10
font = QtGui.QFont(fontName, fontSize, QtGui.QFont.Bold)
fontMetrics = QtGui.QFontMetrics(font)
# text
txt = str(inboxUnreadCount)
rect = fontMetrics.boundingRect(txt)
# margins that we add in the top-right corner
marginX = 2
marginY = 0 # it looks like -2 is also ok due to the error of metric
# if it renders too wide we need to change it to a plus symbol
if rect.width() > 20:
txt = "+"
fontSize = 15
font = QtGui.QFont(fontName, fontSize, QtGui.QFont.Bold)
fontMetrics = QtGui.QFontMetrics(font)
rect = fontMetrics.boundingRect(txt)
# draw text
painter = QtGui.QPainter()
painter.begin(pixmap)
painter.setPen(
QtGui.QPen(QtGui.QColor(255, 0, 0), QtCore.Qt.SolidPattern))
painter.setFont(font)
painter.drawText(24 - rect.right() - marginX, -rect.top() + marginY, txt)
painter.end()
return QtGui.QIcon(pixmap)
def drawTrayIcon(self, iconFileName, inboxUnreadCount):
"""TBC"""
self.tray.setIcon(self.calcTrayIcon(iconFileName, inboxUnreadCount))
def changedInboxUnread(self, row=None):
"""TBC"""
self.drawTrayIcon(
self.currentTrayIconFileName, self.findInboxUnreadCount())
self.rerenderTabTreeMessages()
self.rerenderTabTreeSubscriptions()
self.rerenderTabTreeChans()
def findInboxUnreadCount(self, count=None):
"""TBC"""
if count is None:
queryreturn = sqlQuery('''SELECT count(*) from inbox WHERE folder='inbox' and read=0''')
cnt = 0
for row in queryreturn:
cnt, = row
self.unreadCount = int(cnt)
else:
self.unreadCount = count
return self.unreadCount
2013-05-02 15:53:54 +00:00
def updateSentItemStatusByToAddress(self, toAddress, textToDisplay):
"""TBC"""
for sent in [self.ui.tableWidgetInbox, self.ui.tableWidgetInboxSubscriptions, self.ui.tableWidgetInboxChans]:
treeWidget = self.widgetConvert(sent)
if self.getCurrentFolder(treeWidget) != "sent":
continue
if treeWidget in [self.ui.treeWidgetSubscriptions,
self.ui.treeWidgetChans] and self.getCurrentAccount(treeWidget) != toAddress:
continue
for i in range(sent.rowCount()):
rowAddress = sent.item(i, 0).data(QtCore.Qt.UserRole)
if toAddress == rowAddress:
sent.item(i, 3).setToolTip(textToDisplay)
try:
newlinePosition = textToDisplay.indexOf('\n')
except: # If no "_translate" appended to string before passing in, there's no qstring
newlinePosition = 0
if newlinePosition > 1:
sent.item(i, 3).setText(
textToDisplay[:newlinePosition])
else:
sent.item(i, 3).setText(textToDisplay)
2013-05-02 15:53:54 +00:00
def updateSentItemStatusByAckdata(self, ackdata, textToDisplay):
"""TBC"""
if isinstance(ackdata, str):
ackdata = QtCore.QByteArray(ackdata)
for sent in [self.ui.tableWidgetInbox, self.ui.tableWidgetInboxSubscriptions, self.ui.tableWidgetInboxChans]:
treeWidget = self.widgetConvert(sent)
if self.getCurrentFolder(treeWidget) != "sent":
continue
for i in range(sent.rowCount()):
toAddress = sent.item(
i, 0).data(QtCore.Qt.UserRole)
tableAckdata = sent.item(
i, 3).data(QtCore.Qt.UserRole).toPyObject()
status, addressVersionNumber, streamNumber, ripe = decodeAddress(
toAddress)
if ackdata == tableAckdata:
sent.item(i, 3).setToolTip(textToDisplay)
try:
newlinePosition = textToDisplay.indexOf('\n')
except: # If no "_translate" appended to string before passing in, there's no qstring
newlinePosition = 0
if newlinePosition > 1:
sent.item(i, 3).setText(
textToDisplay[:newlinePosition])
else:
sent.item(i, 3).setText(textToDisplay)
2013-05-02 15:53:54 +00:00
def removeInboxRowByMsgid(self, msgid): # msgid and inventoryHash are the same thing
"""TBC"""
for inbox in ([
self.ui.tableWidgetInbox,
self.ui.tableWidgetInboxSubscriptions,
self.ui.tableWidgetInboxChans]):
for i in range(inbox.rowCount()):
if msgid == str(inbox.item(i, 3).data(QtCore.Qt.UserRole).toPyObject()):
self.updateStatusBar(
_translate("MainWindow", "Message trashed"))
treeWidget = self.widgetConvert(inbox)
self.propagateUnreadCount(
inbox.item(
i,
1 if inbox.item(
i,
1).type == AccountMixin.SUBSCRIPTION else 0).data(
QtCore.Qt.UserRole),
self.getCurrentFolder(treeWidget),
treeWidget,
0)
inbox.removeRow(i)
break
def newVersionAvailable(self, version):
"""TBC"""
self.notifiedNewVersion = ".".join(str(n) for n in version)
self.updateStatusBar(
_translate(
"MainWindow",
"New version of PyBitmessage is available: %1. Download it"
" from https://github.com/Bitmessage/PyBitmessage/releases/latest"
).arg(self.notifiedNewVersion)
)
2013-09-05 00:14:25 +00:00
def displayAlert(self, title, text, exitAfterUserClicksOk):
"""TBC"""
self.updateStatusBar(text)
QtGui.QMessageBox.critical(self, title, text, QtGui.QMessageBox.Ok)
2013-09-05 00:14:25 +00:00
if exitAfterUserClicksOk:
sys.exit(0)
2013-09-05 00:14:25 +00:00
def rerenderMessagelistFromLabels(self):
"""TBC"""
for messagelist in (
self.ui.tableWidgetInbox,
self.ui.tableWidgetInboxChans,
self.ui.tableWidgetInboxSubscriptions):
for i in range(messagelist.rowCount()):
messagelist.item(i, 1).setLabel()
2013-05-02 15:53:54 +00:00
def rerenderMessagelistToLabels(self):
"""TBC"""
for messagelist in (
self.ui.tableWidgetInbox,
self.ui.tableWidgetInboxChans,
self.ui.tableWidgetInboxSubscriptions):
for i in range(messagelist.rowCount()):
messagelist.item(i, 0).setLabel()
2013-05-02 15:53:54 +00:00
def rerenderAddressBook(self):
"""TBC"""
def addRow(address, label, arg_type):
"""TBC"""
self.ui.tableWidgetAddressBook.insertRow(0)
newItem = Ui_AddressBookWidgetItemLabel(address, unicode(label, 'utf-8'), arg_type)
self.ui.tableWidgetAddressBook.setItem(0, 0, newItem)
newItem = Ui_AddressBookWidgetItemAddress(address, unicode(label, 'utf-8'), arg_type)
self.ui.tableWidgetAddressBook.setItem(0, 1, newItem)
oldRows = {}
for i in range(self.ui.tableWidgetAddressBook.rowCount()):
item = self.ui.tableWidgetAddressBook.item(i, 0)
oldRows[item.address] = [item.label, item.type, i]
if self.ui.tableWidgetAddressBook.rowCount() == 0:
self.ui.tableWidgetAddressBook.horizontalHeader().setSortIndicator(0, QtCore.Qt.AscendingOrder)
if self.ui.tableWidgetAddressBook.isSortingEnabled():
self.ui.tableWidgetAddressBook.setSortingEnabled(False)
newRows = {}
# subscriptions
queryreturn = sqlQuery('SELECT label, address FROM subscriptions WHERE enabled = 1')
for row in queryreturn:
label, address = row
newRows[address] = [label, AccountMixin.SUBSCRIPTION]
# chans
addresses = getSortedAccounts()
for address in addresses:
account = accountClass(address)
if (account.type == AccountMixin.CHAN and BMConfigParser().safeGetBoolean(address, 'enabled')):
newRows[address] = [account.getLabel(), AccountMixin.CHAN]
# normal accounts
queryreturn = sqlQuery('SELECT * FROM addressbook')
for row in queryreturn:
label, address = row
newRows[address] = [label, AccountMixin.NORMAL]
completerList = []
for address in sorted(oldRows, key=lambda x: oldRows[x][2], reverse=True):
if address in newRows:
2016-04-29 09:43:40 +00:00
completerList.append(unicode(newRows[address][0], encoding="UTF-8") + " <" + address + ">")
newRows.pop(address)
else:
self.ui.tableWidgetAddressBook.removeRow(oldRows[address][2])
for address in newRows:
addRow(address, newRows[address][0], newRows[address][1])
2016-04-29 09:43:40 +00:00
completerList.append(unicode(newRows[address][0], encoding="UTF-8") + " <" + address + ">")
# sort
self.ui.tableWidgetAddressBook.sortByColumn(
0, QtCore.Qt.AscendingOrder)
self.ui.tableWidgetAddressBook.setSortingEnabled(True)
self.ui.lineEditTo.completer().model().setStringList(completerList)
def rerenderSubscriptions(self):
"""TBC"""
self.rerenderTabTreeSubscriptions()
2015-03-03 19:04:12 +00:00
def click_pushButtonTTL(self):
"""TBC"""
2015-03-03 19:04:12 +00:00
QtGui.QMessageBox.information(self, 'Time To Live', _translate(
"MainWindow",
("The TTL, or Time-To-Live is the length of time that 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.")), QtGui.QMessageBox.Ok)
2015-03-03 19:04:12 +00:00
def click_pushButtonClear(self):
"""TBC"""
self.ui.lineEditSubject.setText("")
self.ui.lineEditTo.setText("")
self.ui.textEditMessage.setText("")
self.ui.comboBoxSendFrom.setCurrentIndex(0)
2013-05-02 15:53:54 +00:00
def click_pushButtonSend(self):
"""
TBC
Regarding the line below `if len(message) > (2 ** 18 - 500):`:
The whole network message must fit in 2^18 bytes.
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
be a better use of time to support message continuation so that
users can send messages of any length.
"""
encoding = 3 if QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ShiftModifier else 2
self.statusbar.clearMessage()
2015-03-21 10:37:08 +00:00
if self.ui.tabWidgetSend.currentIndex() == \
self.ui.tabWidgetSend.indexOf(self.ui.sendDirect):
# message to specific people
2015-03-21 10:37:08 +00:00
sendMessageToPeople = True
2015-09-30 08:22:41 +00:00
fromAddress = str(self.ui.comboBoxSendFrom.itemData(
self.ui.comboBoxSendFrom.currentIndex(),
QtCore.Qt.UserRole).toString())
toAddresses = str(self.ui.lineEditTo.text().toUtf8())
2015-03-21 10:37:08 +00:00
subject = str(self.ui.lineEditSubject.text().toUtf8())
message = str(
self.ui.textEditMessage.document().toPlainText().toUtf8())
else:
# broadcast message
2015-03-21 10:37:08 +00:00
sendMessageToPeople = False
2015-09-30 08:22:41 +00:00
fromAddress = str(self.ui.comboBoxSendFromBroadcast.itemData(
self.ui.comboBoxSendFromBroadcast.currentIndex(),
QtCore.Qt.UserRole).toString())
2015-03-21 10:37:08 +00:00
subject = str(self.ui.lineEditSubjectBroadcast.text().toUtf8())
message = str(
self.ui.textEditMessageBroadcast.document().toPlainText().toUtf8())
if len(message) > (2 ** 18 - 500):
QtGui.QMessageBox.about(
self, _translate("MainWindow", "Message too long"),
_translate(
"MainWindow",
"The message that you are trying to send is too long"
" by %1 bytes. (The maximum is 261644 bytes). Please"
" cut it down before sending."
).arg(len(message) - (2 ** 18 - 500)))
2014-08-27 07:14:32 +00:00
return
acct = accountClass(fromAddress)
2015-03-21 10:37:08 +00:00
if sendMessageToPeople: # To send a message to specific people (rather than broadcast)
toAddressesList = [s.strip()
for s in toAddresses.replace(',', ';').split(';')]
# remove duplicate addresses. If the user has one address with a BM- and
# the same address without the BM-, this will not catch it. They'll send
# the message to the person twice.
toAddressesList = list(set(toAddressesList))
2013-05-02 15:53:54 +00:00
for toAddress in toAddressesList:
if toAddress != '':
# label plus address
if "<" in toAddress and ">" in toAddress:
toAddress = toAddress.split('<')[1].split('>')[0]
# email address
if toAddress.find("@") >= 0:
if isinstance(acct, GatewayAccount):
acct.createMessage(toAddress, fromAddress, subject, message)
subject = acct.subject
toAddress = acct.toAddress
else:
if QtGui.QMessageBox.question(
self, "Sending an email?",
_translate(
"MainWindow",
("You are trying to send an email instead of a bitmessage. This requires "
"registering with a gateway. Attempt to register?")),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) != QtGui.QMessageBox.Yes:
continue
email = acct.getLabel()
if email[-14:] != "@mailchuck.com": # attempt register
# 12 character random email address
email = ''.join(random.SystemRandom().choice(string.ascii_lowercase)
for _ in range(12)) + "@mailchuck.com"
acct = MailchuckAccount(fromAddress)
acct.register(email)
BMConfigParser().set(fromAddress, 'label', email)
BMConfigParser().set(fromAddress, 'gateway', 'mailchuck')
BMConfigParser().save()
self.updateStatusBar(
_translate(
"MainWindow",
("Error: Your account wasn't registered at an email gateway. Sending registration"
" now as %1, please wait for the registration to be processed before retrying "
"sending.")
).arg(email)
)
return
status, addressVersionNumber, streamNumber, ripe = decodeAddress(
toAddress)
if status != 'success':
try:
2016-10-26 00:19:26 +00:00
toAddress = unicode(toAddress, 'utf-8', 'ignore')
except:
pass
logger.error('Error: Could not decode recipient address ' + toAddress + ':' + status)
2013-05-02 15:53:54 +00:00
if status == 'missingbm':
self.updateStatusBar(_translate(
"MainWindow",
"Error: Bitmessage addresses start with"
" BM- Please check the recipient address %1"
).arg(toAddress))
2013-05-02 15:53:54 +00:00
elif status == 'checksumfailed':
self.updateStatusBar(_translate(
"MainWindow",
"Error: The recipient address %1 is not"
" typed or copied correctly. Please check it."
).arg(toAddress))
2013-05-02 15:53:54 +00:00
elif status == 'invalidcharacters':
self.updateStatusBar(_translate(
"MainWindow",
"Error: The recipient address %1 contains"
" invalid characters. Please check it."
).arg(toAddress))
2013-05-02 15:53:54 +00:00
elif status == 'versiontoohigh':
self.updateStatusBar(_translate(
"MainWindow",
"Error: The version of the recipient address"
" %1 is too high. Either you need to upgrade"
" your Bitmessage software or your"
" acquaintance is being clever."
).arg(toAddress))
2013-05-02 15:53:54 +00:00
elif status == 'ripetooshort':
self.updateStatusBar(_translate(
"MainWindow",
"Error: Some data encoded in the recipient"
" address %1 is too short. There might be"
" something wrong with the software of"
" your acquaintance."
).arg(toAddress))
2013-05-02 15:53:54 +00:00
elif status == 'ripetoolong':
self.updateStatusBar(_translate(
"MainWindow",
"Error: Some data encoded in the recipient"
" address %1 is too long. There might be"
" something wrong with the software of"
" your acquaintance."
).arg(toAddress))
2014-08-27 07:14:32 +00:00
elif status == 'varintmalformed':
self.updateStatusBar(_translate(
"MainWindow",
"Error: Some data encoded in the recipient"
" address %1 is malformed. There might be"
" something wrong with the software of"
" your acquaintance."
).arg(toAddress))
2013-05-02 15:53:54 +00:00
else:
self.updateStatusBar(_translate(
"MainWindow",
"Error: Something is wrong with the"
" recipient address %1."
).arg(toAddress))
2013-05-02 15:53:54 +00:00
elif fromAddress == '':
self.updateStatusBar(_translate(
"MainWindow",
("Error: You must specify a From address. If you don\'t have one, go to the"
" \'Your Identities\' tab.")))
2013-05-02 15:53:54 +00:00
else:
toAddress = addBMIfNotPresent(toAddress)
2015-09-30 08:22:41 +00:00
if addressVersionNumber > 4 or addressVersionNumber <= 1:
QtGui.QMessageBox.about(
self,
_translate(
"MainWindow",
"Address version number"),
_translate(
"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)))
2013-05-02 15:53:54 +00:00
continue
if streamNumber > 1 or streamNumber == 0:
QtGui.QMessageBox.about(
self,
_translate(
"MainWindow",
"Stream number"),
_translate(
"MainWindow",
("Concerning the address %1, Bitmessage cannot handle stream numbers of %2. "
"Perhaps upgrade Bitmessage to the latest version.")
).arg(toAddress).arg(
str(streamNumber)))
2013-05-02 15:53:54 +00:00
continue
self.statusbar.clearMessage()
2013-05-02 15:53:54 +00:00
if shared.statusIconColor == 'red':
self.updateStatusBar(
_translate(
"MainWindow",
("Warning: You are currently not connected. Bitmessage will do the work necessary"
" to send the message but it won\'t send until you connect.")
)
)
stealthLevel = BMConfigParser().safeGetInt(
'bitmessagesettings', 'ackstealthlevel')
2017-09-30 09:19:44 +00:00
ackdata = genAckPayload(streamNumber, stealthLevel)
2013-08-27 00:01:19 +00:00
t = ()
sqlExecute(
2015-03-09 06:35:32 +00:00
'''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''',
2013-08-27 00:01:19 +00:00
'',
toAddress,
ripe,
fromAddress,
subject,
message,
ackdata,
int(time.time()), # sentTime (this will never change)
int(time.time()), # lastActionTime
0, # sleepTill time. This will get set when the POW gets done.
2013-08-27 00:01:19 +00:00
'msgqueued',
0, # retryNumber
'sent', # folder
encoding, # encodingtype
BMConfigParser().getint('bitmessagesettings', 'ttl')
)
2013-05-02 15:53:54 +00:00
toLabel = ''
2013-08-27 00:01:19 +00:00
queryreturn = sqlQuery('''select label from addressbook where address=?''',
toAddress)
if queryreturn != []:
2013-05-02 15:53:54 +00:00
for row in queryreturn:
toLabel, = row
self.displayNewSentMessage(
toAddress, toLabel, fromAddress, subject, message, ackdata)
queues.workerQueue.put(('sendmessage', toAddress))
2013-05-02 15:53:54 +00:00
self.ui.comboBoxSendFrom.setCurrentIndex(0)
self.ui.lineEditTo.setText('')
self.ui.lineEditSubject.setText('')
self.ui.textEditMessage.reset()
if self.replyFromTab is not None:
self.ui.tabWidget.setCurrentIndex(self.replyFromTab)
self.replyFromTab = None
self.updateStatusBar(_translate(
"MainWindow", "Message queued."))
# self.ui.tableWidgetInbox.setCurrentCell(0, 0)
2013-05-02 15:53:54 +00:00
else:
self.updateStatusBar(_translate(
"MainWindow", "Your \'To\' field is empty."))
else: # User selected 'Broadcast'
2013-05-02 15:53:54 +00:00
if fromAddress == '':
self.updateStatusBar(_translate(
"MainWindow",
"Error: You must specify a From address. If you don\'t"
" have one, go to the \'Your Identities\' tab."
))
2013-05-02 15:53:54 +00:00
else:
self.statusbar.clearMessage()
# We don't actually need the ackdata for acknowledgement since
# this is a broadcast message, but we can use it to update the
# user interface when the POW is done generating.
streamNumber = decodeAddress(fromAddress)[2]
2017-09-30 09:19:44 +00:00
ackdata = genAckPayload(streamNumber, 0)
toAddress = str_broadcast_subscribers
2013-05-02 15:53:54 +00:00
ripe = ''
t = (
'', # msgid. We don't know what this will be until the POW is done.
toAddress,
ripe,
fromAddress,
subject,
message,
ackdata,
int(time.time()), # sentTime (this will never change)
int(time.time()), # lastActionTime
0, # sleepTill time. This will get set when the POW gets done.
'broadcastqueued',
0, # retryNumber
'sent', # folder
encoding, # encoding type
BMConfigParser().getint('bitmessagesettings', 'ttl')
)
2013-08-27 00:01:19 +00:00
sqlExecute(
2015-03-09 06:35:32 +00:00
'''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', *t)
2013-05-02 15:53:54 +00:00
toLabel = str_broadcast_subscribers
self.displayNewSentMessage(
toAddress, toLabel, fromAddress, subject, message, ackdata)
2013-05-02 15:53:54 +00:00
queues.workerQueue.put(('sendbroadcast', ''))
2013-05-02 15:53:54 +00:00
2015-03-21 10:37:08 +00:00
self.ui.comboBoxSendFromBroadcast.setCurrentIndex(0)
self.ui.lineEditSubjectBroadcast.setText('')
self.ui.textEditMessageBroadcast.reset()
self.ui.tabWidget.setCurrentIndex(
self.ui.tabWidget.indexOf(self.ui.send)
)
self.ui.tableWidgetInboxSubscriptions.setCurrentCell(0, 0)
self.updateStatusBar(_translate(
"MainWindow", "Broadcast queued."))
2013-05-02 15:53:54 +00:00
def click_pushButtonLoadFromAddressBook(self):
"""TBC"""
2013-05-02 15:53:54 +00:00
self.ui.tabWidget.setCurrentIndex(5)
for i in range(4):
time.sleep(0.1)
self.statusbar.clearMessage()
2013-05-02 15:53:54 +00:00
time.sleep(0.1)
self.updateStatusBar(_translate(
"MainWindow",
"Right click one or more entries in your address book and"
" select \'Send message to this address\'."
))
2013-05-02 15:53:54 +00:00
def click_pushButtonFetchNamecoinID(self):
"""TBC"""
nc = namecoinConnection()
identities = str(self.ui.lineEditTo.text().toUtf8()).split(";")
err, addr = nc.query(identities[-1].strip())
if err is not None:
self.updateStatusBar(
_translate("MainWindow", "Error: %1").arg(err))
else:
identities[-1] = addr
self.ui.lineEditTo.setText("; ".join(identities))
self.updateStatusBar(_translate(
"MainWindow", "Fetched address from namecoin identity."))
def setBroadcastEnablementDependingOnWhetherThisIsAMailingListAddress(self, address):
"""If this is a chan then don't let people broadcast because no one should subscribe to chan addresses."""
self.ui.tabWidgetSend.setCurrentIndex(
self.ui.tabWidgetSend.indexOf(
self.ui.sendBroadcast
if BMConfigParser().safeGetBoolean(str(address), 'mailinglist')
else self.ui.sendDirect
))
2013-05-02 15:53:54 +00:00
def rerenderComboBoxSendFrom(self):
"""TBC"""
2013-05-02 15:53:54 +00:00
self.ui.comboBoxSendFrom.clear()
for addressInKeysFile in getSortedAccounts():
# I realize that this is poor programming practice but I don't care. It's easier for others to read.
isEnabled = BMConfigParser().getboolean(addressInKeysFile, 'enabled')
isMaillinglist = BMConfigParser().safeGetBoolean(addressInKeysFile, 'mailinglist')
if isEnabled and not isMaillinglist:
label = unicode(BMConfigParser().get(addressInKeysFile, 'label'), 'utf-8', 'ignore').strip()
if label == "":
label = addressInKeysFile
self.ui.comboBoxSendFrom.addItem(avatarize(addressInKeysFile), label, addressInKeysFile)
2015-10-31 19:27:28 +00:00
for i in range(self.ui.comboBoxSendFrom.count()):
address = str(self.ui.comboBoxSendFrom.itemData(
i, QtCore.Qt.UserRole).toString())
self.ui.comboBoxSendFrom.setItemData(
i, AccountColor(address).accountColor(),
QtCore.Qt.ForegroundRole)
self.ui.comboBoxSendFrom.insertItem(0, '', '')
if self.ui.comboBoxSendFrom.count() == 2:
2013-05-02 15:53:54 +00:00
self.ui.comboBoxSendFrom.setCurrentIndex(1)
else:
self.ui.comboBoxSendFrom.setCurrentIndex(0)
2015-03-21 10:37:08 +00:00
def rerenderComboBoxSendFromBroadcast(self):
"""TBC"""
2015-03-21 10:37:08 +00:00
self.ui.comboBoxSendFromBroadcast.clear()
for addressInKeysFile in getSortedAccounts():
# I realize that this is poor programming practice but I don't care. It's easier for others to read.
isEnabled = BMConfigParser().getboolean(addressInKeysFile, 'enabled')
isChan = BMConfigParser().safeGetBoolean(addressInKeysFile, 'chan')
if isEnabled and not isChan:
label = unicode(BMConfigParser().get(addressInKeysFile, 'label'), 'utf-8', 'ignore').strip()
if label == "":
label = addressInKeysFile
self.ui.comboBoxSendFromBroadcast.addItem(avatarize(addressInKeysFile), label, addressInKeysFile)
2015-10-31 19:27:28 +00:00
for i in range(self.ui.comboBoxSendFromBroadcast.count()):
address = str(self.ui.comboBoxSendFromBroadcast.itemData(
i, QtCore.Qt.UserRole).toString())
self.ui.comboBoxSendFromBroadcast.setItemData(
i, AccountColor(address).accountColor(),
QtCore.Qt.ForegroundRole)
2015-03-21 10:37:08 +00:00
self.ui.comboBoxSendFromBroadcast.insertItem(0, '', '')
if self.ui.comboBoxSendFromBroadcast.count() == 2:
2015-03-21 10:37:08 +00:00
self.ui.comboBoxSendFromBroadcast.setCurrentIndex(1)
else:
self.ui.comboBoxSendFromBroadcast.setCurrentIndex(0)
def displayNewSentMessage(self, toAddress, toLabel, fromAddress, subject, message, ackdata):
"""
This function is called by the processmsg function when that function
receives a message to an address that is acting as a
pseudo-mailing-list. The message will be broadcast out. This function
puts the message on the 'Sent' tab.
"""
acct = accountClass(fromAddress)
acct.parseMessage(toAddress, fromAddress, subject, message)
tab = -1
for sent in [self.ui.tableWidgetInbox, self.ui.tableWidgetInboxSubscriptions, self.ui.tableWidgetInboxChans]:
tab += 1
if tab == 1:
tab = 2
treeWidget = self.widgetConvert(sent)
if self.getCurrentFolder(treeWidget) != "sent":
continue
if all(
[
treeWidget == self.ui.treeWidgetYourIdentities,
self.getCurrentAccount(treeWidget) not in (fromAddress, None, False),
]
):
continue
elif all(
[
treeWidget in [self.ui.treeWidgetSubscriptions, self.ui.treeWidgetChans],
self.getCurrentAccount(treeWidget) != toAddress,
]
):
continue
elif not helper_search.check_match(
toAddress,
fromAddress,
subject,
message,
self.getCurrentSearchOption(tab),
self.getCurrentSearchLine(tab),
):
continue
self.addMessageListItemSent(sent, toAddress, fromAddress, subject, "msgqueued", ackdata, time.time())
self.getAccountTextedit(acct).setPlainText(unicode(message, 'utf-8', 'replace'))
sent.setCurrentCell(0, 0)
2013-05-02 15:53:54 +00:00
def displayNewInboxMessage(self, inventoryHash, toAddress, fromAddress, subject, message):
"""TBC"""
if toAddress == str_broadcast_subscribers:
acct = accountClass(fromAddress)
else:
acct = accountClass(toAddress)
inbox = self.getAccountMessagelist(acct)
ret = None
tab = -1
for treeWidget in [
self.ui.treeWidgetYourIdentities,
self.ui.treeWidgetSubscriptions,
self.ui.treeWidgetChans,
]:
tab += 1
if tab == 1:
tab = 2
tableWidget = self.widgetConvert(treeWidget)
if not helper_search.check_match(
toAddress,
fromAddress,
subject,
message,
self.getCurrentSearchOption(tab),
self.getCurrentSearchLine(tab),
):
continue
if all(
[
tableWidget == inbox,
self.getCurrentAccount(treeWidget) == acct.address,
self.getCurrentFolder(treeWidget) in ["inbox", None],
]
):
ret = self.addMessageListItemInbox(
inbox,
"inbox",
inventoryHash,
toAddress,
fromAddress,
subject,
time.time(),
0,
)
elif treeWidget == all(
[
self.ui.treeWidgetYourIdentities,
self.getCurrentAccount(treeWidget) is None,
self.getCurrentFolder(treeWidget) in ["inbox", "new", None]
]
):
ret = self.addMessageListItemInbox(
tableWidget,
"inbox",
inventoryHash,
toAddress,
fromAddress,
subject,
time.time(),
0,
)
if ret is None:
acct.parseMessage(toAddress, fromAddress, subject, "")
else:
acct = ret
self.propagateUnreadCount(acct.address)
if BMConfigParser().getboolean(
'bitmessagesettings', 'showtraynotifications'):
self.notifierShow(
_translate("MainWindow", "New Message"),
_translate("MainWindow", "From %1").arg(
unicode(acct.fromLabel, 'utf-8')),
sound.SOUND_UNKNOWN
)
if any(
[
all(
[
self.getCurrentAccount() is not None,
self.getCurrentFolder(treeWidget) != "inbox", # pylint: disable=undefined-loop-variable
self.getCurrentFolder(treeWidget) is not None, # pylint: disable=undefined-loop-variable
]
),
self.getCurrentAccount(treeWidget) != acct.address # pylint: disable=undefined-loop-variable
]
):
# Ubuntu should notify of new message irespective of
# whether it's in current message list or not
self.indicatorUpdate(True, to_label=acct.toLabel)
# cannot find item to pass here ):
if hasattr(acct, "feedback") and acct.feedback != GatewayAccount.ALL_OK:
if acct.feedback == GatewayAccount.REGISTRATION_DENIED:
dialogs.EmailGatewayDialog(
self, BMConfigParser(), acct).exec_()
2013-05-02 15:53:54 +00:00
def click_pushButtonAddAddressBook(self, dialog=None):
"""TBC"""
if not dialog:
dialog = dialogs.AddAddressDialog(self)
dialog.exec_()
try:
address, label = dialog.data
except AttributeError:
return
# First we must check to see if the address is already in the
# address book. The user cannot add it again or else it will
# cause problems when updating and deleting the entry.
if shared.isAddressInMyAddressBook(address):
self.updateStatusBar(_translate(
"MainWindow",
"Error: You cannot add the same address to your"
" address book twice. Try renaming the existing one"
" if you want."
))
return
self.addEntryToAddressBook(address, label)
2013-05-02 15:53:54 +00:00
def addEntryToAddressBook(self, address, label):
"""TBC"""
if shared.isAddressInMyAddressBook(address):
return
sqlExecute('''INSERT INTO addressbook VALUES (?,?)''', label, address)
self.rerenderMessagelistFromLabels()
self.rerenderMessagelistToLabels()
self.rerenderAddressBook()
2013-07-22 05:10:22 +00:00
def addSubscription(self, address, label):
"""TBC"""
# This should be handled outside of this function, for error displaying
# and such, but it must also be checked here.
if shared.isAddressInMySubscriptionsList(address):
return
# Add to database (perhaps this should be separated from the MyForm class)
sqlExecute(
'''INSERT INTO subscriptions VALUES (?,?,?)''',
label, address, True
)
self.rerenderMessagelistFromLabels()
shared.reloadBroadcastSendersForWhichImWatching()
self.rerenderAddressBook()
self.rerenderTabTreeSubscriptions()
2013-05-02 15:53:54 +00:00
def click_pushButtonAddSubscription(self):
"""TBC"""
dialog = dialogs.NewSubscriptionDialog(self)
dialog.exec_()
try:
address, label = dialog.data
except AttributeError:
return
# We must check to see if the address is already in the
# subscriptions list. The user cannot add it again or else it
# will cause problems when updating and deleting the entry.
if shared.isAddressInMySubscriptionsList(address):
self.updateStatusBar(_translate(
"MainWindow",
"Error: You cannot add the same address to your"
" subscriptions twice. Perhaps rename the existing one"
" if you want."
))
return
self.addSubscription(address, label)
# Now, if the user wants to display old broadcasts, let's get
# them out of the inventory and put them
# to the objectProcessorQueue to be processed
if dialog.checkBoxDisplayMessagesAlreadyInInventory.isChecked():
for value in dialog.recent:
queues.objectProcessorQueue.put((
value.type, value.payload
))
2013-05-02 15:53:54 +00:00
def click_pushButtonStatusIcon(self):
"""TBC"""
dialogs.IconGlossaryDialog(self, config=BMConfigParser()).exec_()
2013-05-02 15:53:54 +00:00
def click_actionHelp(self):
"""TBC"""
dialogs.HelpDialog(self).exec_()
2013-05-02 15:53:54 +00:00
def click_actionSupport(self):
"""TBC"""
support.createSupportMessage(self)
2013-05-02 15:53:54 +00:00
def click_actionAbout(self):
"""TBC"""
dialogs.AboutDialog(self).exec_()
2013-05-02 15:53:54 +00:00
def click_actionSettings(self):
"""TBC"""
2013-05-02 15:53:54 +00:00
self.settingsDialogInstance = settingsDialog(self)
if self._firstrun:
self.settingsDialogInstance.ui.tabWidgetSettings.setCurrentIndex(1)
2013-05-02 15:53:54 +00:00
if self.settingsDialogInstance.exec_():
if self._firstrun:
BMConfigParser().remove_option(
'bitmessagesettings', 'dontconnect')
BMConfigParser().set('bitmessagesettings', 'startonlogon', str(
self.settingsDialogInstance.ui.checkBoxStartOnLogon.isChecked()))
BMConfigParser().set('bitmessagesettings', 'minimizetotray', str(
self.settingsDialogInstance.ui.checkBoxMinimizeToTray.isChecked()))
BMConfigParser().set('bitmessagesettings', 'trayonclose', str(
self.settingsDialogInstance.ui.checkBoxTrayOnClose.isChecked()))
BMConfigParser().set('bitmessagesettings', 'hidetrayconnectionnotifications', str(
self.settingsDialogInstance.ui.checkBoxHideTrayConnectionNotifications.isChecked()))
BMConfigParser().set('bitmessagesettings', 'showtraynotifications', str(
self.settingsDialogInstance.ui.checkBoxShowTrayNotifications.isChecked()))
BMConfigParser().set('bitmessagesettings', 'startintray', str(
self.settingsDialogInstance.ui.checkBoxStartInTray.isChecked()))
BMConfigParser().set('bitmessagesettings', 'willinglysendtomobile', str(
self.settingsDialogInstance.ui.checkBoxWillinglySendToMobile.isChecked()))
BMConfigParser().set('bitmessagesettings', 'useidenticons', str(
2013-11-01 23:25:24 +00:00
self.settingsDialogInstance.ui.checkBoxUseIdenticons.isChecked()))
BMConfigParser().set('bitmessagesettings', 'replybelow', str(
self.settingsDialogInstance.ui.checkBoxReplyBelow.isChecked()))
lang = str(self.settingsDialogInstance.ui.languageComboBox.itemData(
self.settingsDialogInstance.ui.languageComboBox.currentIndex()).toString())
BMConfigParser().set('bitmessagesettings', 'userlocale', lang)
change_translation(l10n.getTranslationLanguage())
if int(BMConfigParser().get('bitmessagesettings', 'port')) != int(
self.settingsDialogInstance.ui.lineEditTCPPort.text()):
if not BMConfigParser().safeGetBoolean('bitmessagesettings', 'dontconnect'):
QtGui.QMessageBox.about(self, _translate("MainWindow", "Restart"), _translate(
"MainWindow", "You must restart Bitmessage for the port number change to take effect."))
BMConfigParser().set('bitmessagesettings', 'port', str(
self.settingsDialogInstance.ui.lineEditTCPPort.text()))
if self.settingsDialogInstance.ui.checkBoxUPnP.isChecked() != BMConfigParser().safeGetBoolean(
'bitmessagesettings', 'upnp'
):
BMConfigParser().set(
'bitmessagesettings', 'upnp',
str(self.settingsDialogInstance.ui.checkBoxUPnP.isChecked()))
if self.settingsDialogInstance.ui.checkBoxUPnP.isChecked():
upnpThread = upnp.uPnPThread()
upnpThread.start()
if all(
[
BMConfigParser().get(
'bitmessagesettings',
'socksproxytype') == 'none',
self.settingsDialogInstance.ui.comboBoxProxyType.currentText()[0:5] == 'SOCKS',
]
):
2013-05-02 15:53:54 +00:00
if shared.statusIconColor != 'red':
QtGui.QMessageBox.about(
self,
_translate(
"MainWindow",
"Restart"),
_translate(
"MainWindow",
("Bitmessage will use your proxy from now on but you may want to manually restart "
"Bitmessage now to close existing connections (if any).")))
if all(
[
BMConfigParser().get('bitmessagesettings', 'socksproxytype')[0:5] == 'SOCKS',
self.settingsDialogInstance.ui.comboBoxProxyType.currentText()[0:5] != 'SOCKS',
]
):
self.statusbar.clearMessage()
state.resetNetworkProtocolAvailability() # just in case we changed something in the network connectivity
if self.settingsDialogInstance.ui.comboBoxProxyType.currentText()[0:5] == 'SOCKS':
BMConfigParser().set('bitmessagesettings', 'socksproxytype', str(
self.settingsDialogInstance.ui.comboBoxProxyType.currentText()))
else:
BMConfigParser().set('bitmessagesettings', 'socksproxytype', 'none')
BMConfigParser().set('bitmessagesettings', 'socksauthentication', str(
self.settingsDialogInstance.ui.checkBoxAuthentication.isChecked()))
BMConfigParser().set('bitmessagesettings', 'sockshostname', str(
self.settingsDialogInstance.ui.lineEditSocksHostname.text()))
BMConfigParser().set('bitmessagesettings', 'socksport', str(
self.settingsDialogInstance.ui.lineEditSocksPort.text()))
BMConfigParser().set('bitmessagesettings', 'socksusername', str(
self.settingsDialogInstance.ui.lineEditSocksUsername.text()))
BMConfigParser().set('bitmessagesettings', 'sockspassword', str(
self.settingsDialogInstance.ui.lineEditSocksPassword.text()))
BMConfigParser().set('bitmessagesettings', 'sockslisten', str(
self.settingsDialogInstance.ui.checkBoxSocksListen.isChecked()))
try:
# Rounding to integers just for aesthetics
BMConfigParser().set('bitmessagesettings', 'maxdownloadrate', str(
int(float(self.settingsDialogInstance.ui.lineEditMaxDownloadRate.text()))))
BMConfigParser().set('bitmessagesettings', 'maxuploadrate', str(
int(float(self.settingsDialogInstance.ui.lineEditMaxUploadRate.text()))))
except ValueError:
QtGui.QMessageBox.about(self, _translate("MainWindow", "Number needed"), _translate(
"MainWindow", "Your maximum download and upload rate must be numbers. Ignoring what you typed."))
else:
set_rates(BMConfigParser().safeGetInt("bitmessagesettings", "maxdownloadrate"),
BMConfigParser().safeGetInt("bitmessagesettings", "maxuploadrate"))
BMConfigParser().set('bitmessagesettings', 'maxoutboundconnections', str(
int(float(self.settingsDialogInstance.ui.lineEditMaxOutboundConnections.text()))))
BMConfigParser().set('bitmessagesettings', 'namecoinrpctype',
self.settingsDialogInstance.getNamecoinType())
BMConfigParser().set('bitmessagesettings', 'namecoinrpchost', str(
self.settingsDialogInstance.ui.lineEditNamecoinHost.text()))
BMConfigParser().set('bitmessagesettings', 'namecoinrpcport', str(
self.settingsDialogInstance.ui.lineEditNamecoinPort.text()))
BMConfigParser().set('bitmessagesettings', 'namecoinrpcuser', str(
self.settingsDialogInstance.ui.lineEditNamecoinUser.text()))
BMConfigParser().set('bitmessagesettings', 'namecoinrpcpassword', str(
self.settingsDialogInstance.ui.lineEditNamecoinPassword.text()))
# Demanded difficulty tab
2013-05-02 15:53:54 +00:00
if float(self.settingsDialogInstance.ui.lineEditTotalDifficulty.text()) >= 1:
BMConfigParser().set('bitmessagesettings', 'defaultnoncetrialsperbyte', str(int(float(
self.settingsDialogInstance.ui.lineEditTotalDifficulty.text()
) * defaults.networkDefaultProofOfWorkNonceTrialsPerByte)))
2013-05-02 15:53:54 +00:00
if float(self.settingsDialogInstance.ui.lineEditSmallMessageDifficulty.text()) >= 1:
BMConfigParser().set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(int(float(
self.settingsDialogInstance.ui.lineEditSmallMessageDifficulty.text()
) * defaults.networkDefaultPayloadLengthExtraBytes)))
if self.settingsDialogInstance.ui.comboBoxOpenCL.currentText().toUtf8(
) != BMConfigParser().safeGet("bitmessagesettings", "opencl"):
BMConfigParser().set(
'bitmessagesettings', 'opencl',
str(self.settingsDialogInstance.ui.comboBoxOpenCL.currentText()))
queues.workerQueue.put(('resetPoW', ''))
2015-11-26 01:37:07 +00:00
acceptableDifficultyChanged = False
if any(
[
float(self.settingsDialogInstance.ui.lineEditMaxAcceptableTotalDifficulty.text()) >= 1,
float(self.settingsDialogInstance.ui.lineEditMaxAcceptableTotalDifficulty.text()) == 0,
]
):
if BMConfigParser().get(
'bitmessagesettings',
'maxacceptablenoncetrialsperbyte',
) != str(
int(
float(
self.settingsDialogInstance.ui.lineEditMaxAcceptableTotalDifficulty.text()
) * defaults.networkDefaultProofOfWorkNonceTrialsPerByte
)
):
# the user changed the max acceptable total difficulty
acceptableDifficultyChanged = True
BMConfigParser().set('bitmessagesettings', 'maxacceptablenoncetrialsperbyte', str(int(float(
self.settingsDialogInstance.ui.lineEditMaxAcceptableTotalDifficulty.text()
) * defaults.networkDefaultProofOfWorkNonceTrialsPerByte)))
if any(
[
float(self.settingsDialogInstance.ui.lineEditMaxAcceptableSmallMessageDifficulty.text()) >= 1,
float(self.settingsDialogInstance.ui.lineEditMaxAcceptableSmallMessageDifficulty.text()) == 0,
]
):
if BMConfigParser().get(
'bitmessagesettings',
'maxacceptablepayloadlengthextrabytes',
) != str(
int(
float(
self.settingsDialogInstance.ui.lineEditMaxAcceptableSmallMessageDifficulty.text()
) * defaults.networkDefaultPayloadLengthExtraBytes
)
):
# the user changed the max acceptable small message difficulty
acceptableDifficultyChanged = True
BMConfigParser().set('bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', str(int(float(
self.settingsDialogInstance.ui.lineEditMaxAcceptableSmallMessageDifficulty.text()
) * defaults.networkDefaultPayloadLengthExtraBytes)))
if acceptableDifficultyChanged:
# It might now be possible to send msgs which were previously marked as toodifficult.
# Let us change them to 'msgqueued'. The singleWorker will try to send them and will again
# mark them as toodifficult if the receiver's required difficulty is still higher than
# we are willing to do.
sqlExecute('''UPDATE sent SET status='msgqueued' WHERE status='toodifficult' ''')
queues.workerQueue.put(('sendmessage', ''))
# start:UI setting to stop trying to send messages after X days/months
# I'm open to changing this UI to something else if someone has a better idea.
if all(
[
self.settingsDialogInstance.ui.lineEditDays.text() == '',
self.settingsDialogInstance.ui.lineEditMonths.text() == '',
]
): # We need to handle this special case. Bitmessage has its default behavior. The input is blank/blank
BMConfigParser().set('bitmessagesettings', 'stopresendingafterxdays', '')
BMConfigParser().set('bitmessagesettings', 'stopresendingafterxmonths', '')
shared.maximumLengthOfTimeToBotherResendingMessages = float('inf')
try:
float(self.settingsDialogInstance.ui.lineEditDays.text())
lineEditDaysIsValidFloat = True
except:
lineEditDaysIsValidFloat = False
try:
float(self.settingsDialogInstance.ui.lineEditMonths.text())
lineEditMonthsIsValidFloat = True
except:
lineEditMonthsIsValidFloat = False
if lineEditDaysIsValidFloat and not lineEditMonthsIsValidFloat:
self.settingsDialogInstance.ui.lineEditMonths.setText("0")
if lineEditMonthsIsValidFloat and not lineEditDaysIsValidFloat:
self.settingsDialogInstance.ui.lineEditDays.setText("0")
if lineEditDaysIsValidFloat or lineEditMonthsIsValidFloat:
if all(
[
float(self.settingsDialogInstance.ui.lineEditDays.text()) >= 0,
float(self.settingsDialogInstance.ui.lineEditMonths.text()) >= 0,
]
):
shared.maximumLengthOfTimeToBotherResendingMessages = sum(
float(str(self.settingsDialogInstance.ui.lineEditDays.text())) * 24 * 60 * 60,
float(str(self.settingsDialogInstance.ui.lineEditMonths.text())) * (60 * 60 * 24 * 365) / 12,
)
# If the time period is less than 5 hours, we give zero values to all
# fields. No message will be sent again.
if shared.maximumLengthOfTimeToBotherResendingMessages < 432000:
QtGui.QMessageBox.about(
self,
_translate(
"MainWindow",
"Will not resend ever"),
_translate(
"MainWindow",
("Note that the time limit you entered is less than the amount of time Bitmessage "
"waits for the first resend attempt therefore your messages will never be resent.")))
BMConfigParser().set('bitmessagesettings', 'stopresendingafterxdays', '0')
BMConfigParser().set('bitmessagesettings', 'stopresendingafterxmonths', '0')
shared.maximumLengthOfTimeToBotherResendingMessages = 0
else:
BMConfigParser().set('bitmessagesettings', 'stopresendingafterxdays', str(float(
self.settingsDialogInstance.ui.lineEditDays.text())))
BMConfigParser().set('bitmessagesettings', 'stopresendingafterxmonths', str(float(
self.settingsDialogInstance.ui.lineEditMonths.text())))
2013-05-02 15:53:54 +00:00
BMConfigParser().save()
2013-05-02 15:53:54 +00:00
if 'win32' in sys.platform or 'win64' in sys.platform:
# Auto-startup for Windows
2013-05-02 15:53:54 +00:00
RUN_PATH = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
2018-02-09 10:11:48 +00:00
self.settings = QtCore.QSettings(RUN_PATH, QtCore.QSettings.NativeFormat)
if BMConfigParser().getboolean('bitmessagesettings', 'startonlogon'):
self.settings.setValue("PyBitmessage", sys.argv[0])
2013-05-02 15:53:54 +00:00
else:
self.settings.remove("PyBitmessage")
elif 'darwin' in sys.platform:
# startup for mac
2013-05-02 15:53:54 +00:00
pass
elif 'linux' in sys.platform:
# startup for linux
2013-05-02 15:53:54 +00:00
pass
# If we are NOT using portable mode now but the user selected that we should...
if state.appdata != paths.lookupExeFolder():
if self.settingsDialogInstance.ui.checkBoxPortableMode.isChecked():
# Write the keys.dat file to disk in the new location
sqlStoredProcedure('movemessagstoprog')
with open(paths.lookupExeFolder() + 'keys.dat', 'wb') as configfile:
BMConfigParser().write(configfile)
# Write the knownnodes.dat file to disk in the new location
knownnodes.saveKnownNodes(paths.lookupExeFolder())
os.remove(state.appdata + 'keys.dat')
os.remove(state.appdata + 'knownnodes.dat')
previousAppdataLocation = state.appdata
state.appdata = paths.lookupExeFolder()
debug.restartLoggingInUpdatedAppdataLocation()
try:
os.remove(previousAppdataLocation + 'debug.log')
os.remove(previousAppdataLocation + 'debug.log.1')
except:
pass
# If we ARE using portable mode now but the user selected that we shouldn't...
if state.appdata == paths.lookupExeFolder():
if not self.settingsDialogInstance.ui.checkBoxPortableMode.isChecked():
state.appdata = paths.lookupAppdataFolder()
if not os.path.exists(state.appdata):
os.makedirs(state.appdata)
sqlStoredProcedure('movemessagstoappdata')
# Write the keys.dat file to disk in the new location
BMConfigParser().save()
# Write the knownnodes.dat file to disk in the new location
knownnodes.saveKnownNodes(state.appdata)
os.remove(paths.lookupExeFolder() + 'keys.dat')
os.remove(paths.lookupExeFolder() + 'knownnodes.dat')
debug.restartLoggingInUpdatedAppdataLocation()
try:
os.remove(paths.lookupExeFolder() + 'debug.log')
os.remove(paths.lookupExeFolder() + 'debug.log.1')
except:
pass
2013-05-02 15:53:54 +00:00
def on_action_SpecialAddressBehaviorDialog(self):
"""TBC"""
dialogs.SpecialAddressBehaviorDialog(self, BMConfigParser())
2015-03-21 10:37:08 +00:00
def on_action_EmailGatewayDialog(self):
"""TBC"""
dialog = dialogs.EmailGatewayDialog(self, config=BMConfigParser())
# For Modal dialogs
dialog.exec_()
try:
acct = dialog.data
except AttributeError:
return
# Only settings remain here
acct.settings()
for i in range(self.ui.comboBoxSendFrom.count()):
if str(self.ui.comboBoxSendFrom.itemData(i).toPyObject()) \
== acct.fromAddress:
self.ui.comboBoxSendFrom.setCurrentIndex(i)
break
else:
self.ui.comboBoxSendFrom.setCurrentIndex(0)
self.ui.lineEditTo.setText(acct.toAddress)
self.ui.lineEditSubject.setText(acct.subject)
self.ui.textEditMessage.setText(acct.message)
self.ui.tabWidgetSend.setCurrentIndex(
self.ui.tabWidgetSend.indexOf(self.ui.sendDirect)
)
self.ui.tabWidget.setCurrentIndex(
self.ui.tabWidget.indexOf(self.ui.send)
)
self.ui.textEditMessage.setFocus()
def on_action_MarkAllRead(self):
"""TBC"""
if QtGui.QMessageBox.question(
self, "Marking all messages as read?",
_translate(
"MainWindow",
"Are you sure you would like to mark all messages read?"
), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
) != QtGui.QMessageBox.Yes:
return
# addressAtCurrentRow = self.getCurrentAccount()
tableWidget = self.getCurrentMessagelist()
idCount = tableWidget.rowCount()
if idCount == 0:
return
font = QtGui.QFont()
font.setBold(False)
msgids = []
for i in range(0, idCount):
msgids.append(str(tableWidget.item(
i, 3).data(QtCore.Qt.UserRole).toPyObject()))
tableWidget.item(i, 0).setUnread(False)
tableWidget.item(i, 1).setUnread(False)
tableWidget.item(i, 2).setUnread(False)
tableWidget.item(i, 3).setFont(font)
markread = sqlExecuteChunked(
"UPDATE %s SET read = 1 WHERE %s IN({0}) AND read=0" % (
('sent', 'ackdata') if self.getCurrentFolder() == 'sent'
else ('inbox', 'msgid')
), idCount, *msgids
)
if markread > 0:
self.propagateUnreadCount()
# addressAtCurrentRow, self.getCurrentFolder(), None, 0)
2013-05-02 15:53:54 +00:00
def click_NewAddressDialog(self):
"""TBC"""
dialogs.NewAddressDialog(self)
2013-05-02 15:53:54 +00:00
def network_switch(self):
"""TBC"""
dontconnect_option = not BMConfigParser().safeGetBoolean(
'bitmessagesettings', 'dontconnect')
BMConfigParser().set(
'bitmessagesettings', 'dontconnect', str(dontconnect_option))
BMConfigParser().save()
self.ui.updateNetworkSwitchMenuLabel(dontconnect_option)
self.ui.pushButtonFetchNamecoinID.setHidden(
dontconnect_option or self.namecoin.test()[0] == 'failed'
)
def quit(self):
"""Quit selected from menu or application indicator"""
2017-01-16 22:38:18 +00:00
if self.quitAccepted:
return
self.show()
self.raise_()
self.activateWindow()
waitForPow = True
waitForConnection = False
waitForSync = False
# C PoW currently doesn't support interrupting and OpenCL is untested
if getPowType() == "python" and (powQueueSize() > 0 or pendingUpload() > 0):
reply = QtGui.QMessageBox.question(
self,
_translate(
"MainWindow",
"Proof of work pending"),
_translate(
"MainWindow",
"%n object(s) pending proof of work",
None,
QtCore.QCoreApplication.CodecForTr,
powQueueSize()) +
", " +
_translate(
"MainWindow",
"%n object(s) waiting to be distributed",
None,
QtCore.QCoreApplication.CodecForTr,
pendingUpload()) +
"\n\n" +
_translate(
"MainWindow",
"Wait until these tasks finish?"),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel,
QtGui.QMessageBox.Cancel)
if reply == QtGui.QMessageBox.No:
waitForPow = False
elif reply == QtGui.QMessageBox.Cancel:
return
if pendingDownload() > 0:
reply = QtGui.QMessageBox.question(
self,
_translate(
"MainWindow",
"Synchronisation pending"),
_translate(
"MainWindow",
("Bitmessage hasn't synchronised with the network, %n object(s) to be downloaded. If you quit "
"now, it may cause delivery delays. Wait until the synchronisation finishes?"),
None,
QtCore.QCoreApplication.CodecForTr,
pendingDownload()),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel,
QtGui.QMessageBox.Cancel)
if reply == QtGui.QMessageBox.Yes:
waitForSync = True
elif reply == QtGui.QMessageBox.Cancel:
return
if shared.statusIconColor == 'red' and not BMConfigParser().safeGetBoolean(
'bitmessagesettings', 'dontconnect'):
reply = QtGui.QMessageBox.question(
self,
_translate(
"MainWindow",
"Not connected"),
_translate(
"MainWindow",
("Bitmessage isn't connected to the network. If you quit now, it may cause delivery delays. "
"Wait until connected and the synchronisation finishes?")),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel,
QtGui.QMessageBox.Cancel)
if reply == QtGui.QMessageBox.Yes:
waitForConnection = True
waitForSync = True
elif reply == QtGui.QMessageBox.Cancel:
return
2017-01-16 22:38:18 +00:00
self.quitAccepted = True
self.updateStatusBar(_translate(
"MainWindow", "Shutting down PyBitmessage... %1%").arg(0))
if waitForConnection:
self.updateStatusBar(_translate(
"MainWindow", "Waiting for network connection..."))
while shared.statusIconColor == 'red':
time.sleep(0.5)
QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000
)
# this probably will not work correctly, because there is a delay between
# the status icon turning red and inventory exchange, but it's better than
# nothing.
if waitForSync:
self.updateStatusBar(_translate(
"MainWindow", "Waiting for finishing synchronisation..."))
while pendingDownload() > 0:
time.sleep(0.5)
QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000
)
if waitForPow:
# check if PoW queue empty
maxWorkerQueue = 0
curWorkerQueue = powQueueSize()
while curWorkerQueue > 0:
# worker queue size
curWorkerQueue = powQueueSize()
if curWorkerQueue > maxWorkerQueue:
maxWorkerQueue = curWorkerQueue
if curWorkerQueue > 0:
self.updateStatusBar(
_translate(
"MainWindow",
"Waiting for PoW to finish... %1%",
).arg(50 * (maxWorkerQueue - curWorkerQueue) / maxWorkerQueue)
)
time.sleep(0.5)
QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000
)
self.updateStatusBar(_translate(
"MainWindow", "Shutting down Pybitmessage... %1%").arg(50))
QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000
)
if maxWorkerQueue > 0:
# a bit of time so that the hashHolder is populated
time.sleep(0.5)
QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000
)
# check if upload (of objects created locally) pending
self.updateStatusBar(_translate(
"MainWindow", "Waiting for objects to be sent... %1%").arg(50))
maxPendingUpload = max(1, pendingUpload())
while pendingUpload() > 1:
self.updateStatusBar(
_translate(
"MainWindow",
"Waiting for objects to be sent... %1%"
).arg(int(50 + 20 * (pendingUpload() / maxPendingUpload)))
)
time.sleep(0.5)
QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000
)
QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000
)
QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000
)
# save state and geometry self and all widgets
self.updateStatusBar(_translate(
"MainWindow", "Saving settings... %1%").arg(70))
QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000
)
self.saveSettings()
for attr, obj in self.ui.__dict__.iteritems():
if hasattr(obj, "__class__") \
and isinstance(obj, settingsmixin.SettingsMixin):
saveMethod = getattr(obj, "saveSettings", None)
if callable(saveMethod):
obj.saveSettings()
self.updateStatusBar(_translate(
"MainWindow", "Shutting down core... %1%").arg(80))
QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000
)
shutdown.doCleanShutdown()
self.updateStatusBar(_translate(
"MainWindow", "Stopping notifications... %1%").arg(90))
self.tray.hide()
self.updateStatusBar(_translate(
"MainWindow", "Shutdown imminent... %1%").arg(100))
shared.thisapp.cleanup()
logger.info("Shutdown complete")
2017-01-16 22:38:18 +00:00
super(MyForm, myapp).close()
sys.exit(0)
2013-05-02 15:53:54 +00:00
def closeEvent(self, event):
"""window close event"""
self.appIndicatorHide()
trayonclose = False
try:
trayonclose = BMConfigParser().getboolean(
'bitmessagesettings', 'trayonclose')
except Exception:
2013-05-14 15:44:51 +00:00
pass
# always ignore, it shuts down by itself
2017-01-16 22:38:18 +00:00
if self.quitAccepted:
event.accept()
return
event.ignore()
if not trayonclose:
# quit the application
self.quit()
2013-05-02 15:53:54 +00:00
def on_action_InboxMessageForceHtml(self):
"""TBC"""
msgid = self.getCurrentMessageId()
textEdit = self.getCurrentMessageTextedit()
if not msgid:
return
queryreturn = sqlQuery(
'''select message from inbox where msgid=?''', msgid)
if queryreturn != []:
for row in queryreturn:
messageText, = row
lines = messageText.split('\n')
totalLines = len(lines)
for i in xrange(totalLines):
if 'Message ostensibly from ' in lines[i]:
lines[i] = '<p style="font-size: 12px; color: grey;">%s</span></p>' % (
lines[i])
2013-05-02 15:53:54 +00:00
elif lines[i] == '------------------------------------------------------':
lines[i] = '<hr>'
elif lines[i] == '' and (i + 1) < totalLines and \
lines[i + 1] != '------------------------------------------------------':
lines[i] = '<br><br>'
content = ' '.join(lines) # To keep the whitespace between lines
content = shared.fixPotentiallyInvalidUTF8Data(content)
content = unicode(content, 'utf-8)')
textEdit.setHtml(QtCore.QString(content))
2013-05-02 15:53:54 +00:00
2013-07-26 02:00:54 +00:00
def on_action_InboxMarkUnread(self):
"""TBC"""
tableWidget = self.getCurrentMessagelist()
if not tableWidget:
return
msgids = set()
for row in tableWidget.selectedIndexes():
2013-07-26 02:00:54 +00:00
currentRow = row.row()
msgid = str(tableWidget.item(
currentRow, 3).data(QtCore.Qt.UserRole).toPyObject())
msgids.add(msgid)
self.updateUnreadStatus(tableWidget, currentRow, msgid, False)
idCount = len(msgids)
sqlExecuteChunked(
'''UPDATE inbox SET read=0 WHERE msgid IN ({0}) AND read=1''',
idCount, *msgids
)
self.propagateUnreadCount()
def quoted_text(self, message):
"""Format predefined text on message reply."""
if not BMConfigParser().safeGetBoolean('bitmessagesettings', 'replybelow'):
return '\n\n------------------------------------------------------\n' + message
quoteWrapper = textwrap.TextWrapper(
replace_whitespace=False,
initial_indent='> ',
subsequent_indent='> ',
break_long_words=False,
break_on_hyphens=False,
)
def quote_line(line):
"""TBC"""
# Do quote empty lines.
if line == '' or line.isspace():
return '> '
# Quote already quoted lines, but do not wrap them.
elif line[0:2] == '> ':
return '> ' + line
# Wrap and quote lines/paragraphs new to this message.
return quoteWrapper.fill(line)
return '\n'.join([quote_line(l) for l in message.splitlines()]) + '\n\n'
def setSendFromComboBox(self, address=None):
"""TBC"""
if address is None:
messagelist = self.getCurrentMessagelist()
if messagelist:
currentInboxRow = messagelist.currentRow()
address = messagelist.item(
currentInboxRow, 0).address
for box in [self.ui.comboBoxSendFrom, self.ui.comboBoxSendFromBroadcast]:
listOfAddressesInComboBoxSendFrom = [str(box.itemData(i).toPyObject()) for i in range(box.count())]
if address in listOfAddressesInComboBoxSendFrom:
currentIndex = listOfAddressesInComboBoxSendFrom.index(address)
box.setCurrentIndex(currentIndex)
else:
box.setCurrentIndex(0)
def on_action_InboxReplyChan(self):
"""TBC"""
self.on_action_InboxReply(self.REPLY_TYPE_CHAN)
def on_action_InboxReply(self, replyType=None):
"""TBC"""
tableWidget = self.getCurrentMessagelist()
if not tableWidget:
return
if replyType is None:
replyType = self.REPLY_TYPE_SENDER
# save this to return back after reply is done
self.replyFromTab = self.ui.tabWidget.currentIndex()
currentInboxRow = tableWidget.currentRow()
toAddressAtCurrentInboxRow = tableWidget.item(
currentInboxRow, 0).address
acct = accountClass(toAddressAtCurrentInboxRow)
fromAddressAtCurrentInboxRow = tableWidget.item(
currentInboxRow, 1).address
msgid = str(tableWidget.item(
currentInboxRow, 3).data(QtCore.Qt.UserRole).toPyObject())
queryreturn = sqlQuery(
'''select message from inbox where msgid=?''', msgid)
if queryreturn != []:
for row in queryreturn:
messageAtCurrentInboxRow, = row
acct.parseMessage(
toAddressAtCurrentInboxRow,
fromAddressAtCurrentInboxRow,
tableWidget.item(
currentInboxRow,
2).subject,
messageAtCurrentInboxRow)
widget = {
'subject': self.ui.lineEditSubject,
'from': self.ui.comboBoxSendFrom,
'message': self.ui.textEditMessage
}
if toAddressAtCurrentInboxRow == str_broadcast_subscribers:
self.ui.tabWidgetSend.setCurrentIndex(
self.ui.tabWidgetSend.indexOf(self.ui.sendDirect)
)
elif not BMConfigParser().has_section(toAddressAtCurrentInboxRow):
QtGui.QMessageBox.information(
self, _translate("MainWindow", "Address is gone"),
_translate("MainWindow", "Bitmessage cannot find your address %1. Perhaps you removed it?").arg(
toAddressAtCurrentInboxRow),
QtGui.QMessageBox.Ok)
elif not BMConfigParser().getboolean(toAddressAtCurrentInboxRow, 'enabled'):
QtGui.QMessageBox.information(
self,
_translate(
"MainWindow",
"Address disabled"),
_translate(
"MainWindow",
("Error: The address from which you are trying to send is disabled. You\'ll have to enable it on "
"the \'Your Identities\' tab before using it.")),
QtGui.QMessageBox.Ok)
2013-05-02 15:53:54 +00:00
else:
self.setBroadcastEnablementDependingOnWhetherThisIsAMailingListAddress(toAddressAtCurrentInboxRow)
broadcast_tab_index = self.ui.tabWidgetSend.indexOf(
self.ui.sendBroadcast
)
if self.ui.tabWidgetSend.currentIndex() == broadcast_tab_index:
widget = {
'subject': self.ui.lineEditSubjectBroadcast,
'from': self.ui.comboBoxSendFromBroadcast,
'message': self.ui.textEditMessageBroadcast
}
self.ui.tabWidgetSend.setCurrentIndex(broadcast_tab_index)
toAddressAtCurrentInboxRow = fromAddressAtCurrentInboxRow
if fromAddressAtCurrentInboxRow == tableWidget.item(currentInboxRow, 1).label or (
isinstance(acct, GatewayAccount) and fromAddressAtCurrentInboxRow == acct.relayAddress):
self.ui.lineEditTo.setText(str(acct.fromAddress))
else:
self.ui.lineEditTo.setText(
''.join(
[
tableWidget.item(currentInboxRow, 1).label,
" <",
str(acct.fromAddress) + ">",
]
)
)
# If the previous message was to a chan then we should send our reply to
# the chan rather than to the particular person who sent the message.
if acct.type == AccountMixin.CHAN and replyType == self.REPLY_TYPE_CHAN:
logger.debug('original sent to a chan. Setting the to address in the reply to the chan address.')
if toAddressAtCurrentInboxRow == tableWidget.item(currentInboxRow, 0).label:
self.ui.lineEditTo.setText(str(toAddressAtCurrentInboxRow))
else:
self.ui.lineEditTo.setText(tableWidget.item(
currentInboxRow, 0).label + " <" + str(acct.toAddress) + ">")
self.setSendFromComboBox(toAddressAtCurrentInboxRow)
quotedText = self.quoted_text(unicode(messageAtCurrentInboxRow, 'utf-8', 'replace'))
widget['message'].setPlainText(quotedText)
if acct.subject[0:3] in ['Re:', 'RE:']:
widget['subject'].setText(tableWidget.item(currentInboxRow, 2).label)
2013-05-02 15:53:54 +00:00
else:
widget['subject'].setText('Re: ' + tableWidget.item(currentInboxRow, 2).label)
self.ui.tabWidget.setCurrentIndex(
self.ui.tabWidget.indexOf(self.ui.send)
)
2016-01-12 15:49:04 +00:00
widget['message'].setFocus()
2013-05-02 15:53:54 +00:00
def on_action_InboxAddSenderToAddressBook(self):
"""TBC"""
tableWidget = self.getCurrentMessagelist()
if not tableWidget:
return
currentInboxRow = tableWidget.currentRow()
# tableWidget.item(currentRow,1).data(Qt.UserRole).toPyObject()
addressAtCurrentInboxRow = tableWidget.item(
currentInboxRow, 1).data(QtCore.Qt.UserRole)
self.ui.tabWidget.setCurrentIndex(
self.ui.tabWidget.indexOf(self.ui.send)
)
self.click_pushButtonAddAddressBook(
dialogs.AddAddressDialog(self, addressAtCurrentInboxRow))
2013-05-02 15:53:54 +00:00
def on_action_InboxAddSenderToBlackList(self):
"""TBC"""
tableWidget = self.getCurrentMessagelist()
if not tableWidget:
return
currentInboxRow = tableWidget.currentRow()
# tableWidget.item(currentRow,1).data(Qt.UserRole).toPyObject()
addressAtCurrentInboxRow = tableWidget.item(
currentInboxRow, 1).data(QtCore.Qt.UserRole)
recipientAddress = tableWidget.item(
currentInboxRow, 0).data(QtCore.Qt.UserRole)
# Let's make sure that it isn't already in the address book
queryreturn = sqlQuery('''select * from blacklist where address=?''',
addressAtCurrentInboxRow)
if queryreturn == []:
label = "\"" + tableWidget.item(currentInboxRow,
2).subject + "\" in " + BMConfigParser().get(recipientAddress,
"label")
sqlExecute('''INSERT INTO blacklist VALUES (?,?, ?)''',
2015-11-14 17:53:11 +00:00
label,
addressAtCurrentInboxRow, True)
2016-03-17 21:09:46 +00:00
self.ui.blackwhitelist.rerenderBlackWhiteList()
self.updateStatusBar(
_translate(
"MainWindow",
"Entry added to the blacklist. Edit the label to your liking."
)
)
else:
self.updateStatusBar(
_translate(
"MainWindow",
("Error: You cannot add the same address to your blacklist"
" twice. Try renaming the existing one if you want.")
)
)
def deleteRowFromMessagelist(self, row=None, inventoryHash=None, ackData=None, messageLists=None):
"""TBC"""
if messageLists is None:
messageLists = (
self.ui.tableWidgetInbox,
self.ui.tableWidgetInboxChans,
self.ui.tableWidgetInboxSubscriptions)
elif not isinstance(messageLists, (list, tuple)):
messageLists = (messageLists)
for messageList in messageLists:
if row is not None:
inventoryHash = str(messageList.item(row, 3).data(
QtCore.Qt.UserRole).toPyObject())
messageList.removeRow(row)
elif inventoryHash is not None:
for i in range(messageList.rowCount() - 1, -1, -1):
if messageList.item(i, 3).data(QtCore.Qt.UserRole).toPyObject() == inventoryHash:
messageList.removeRow(i)
elif ackData is not None:
for i in range(messageList.rowCount() - 1, -1, -1):
if messageList.item(i, 3).data(QtCore.Qt.UserRole).toPyObject() == ackData:
messageList.removeRow(i)
2013-05-02 15:53:54 +00:00
def on_action_InboxTrash(self):
"""Send item on the Inbox tab to trash"""
tableWidget = self.getCurrentMessagelist()
if not tableWidget:
return
currentRow = 0
folder = self.getCurrentFolder()
shifted = QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ShiftModifier
tableWidget.setUpdatesEnabled(False)
inventoryHashesToTrash = []
# ranges in reversed order
for r in sorted(tableWidget.selectedRanges(), key=lambda r: r.topRow())[::-1]:
for i in range(r.bottomRow() - r.topRow() + 1):
inventoryHashToTrash = str(tableWidget.item(
r.topRow() + i, 3).data(QtCore.Qt.UserRole).toPyObject())
if inventoryHashToTrash in inventoryHashesToTrash:
continue
inventoryHashesToTrash.append(inventoryHashToTrash)
2018-01-28 11:48:25 +00:00
currentRow = r.topRow()
self.getCurrentMessageTextedit().setText("")
tableWidget.model().removeRows(r.topRow(), r.bottomRow() - r.topRow() + 1)
idCount = len(inventoryHashesToTrash)
if folder == "trash" or shifted:
sqlExecuteChunked('''DELETE FROM inbox WHERE msgid IN ({0})''',
idCount, *inventoryHashesToTrash)
2013-05-02 15:53:54 +00:00
else:
sqlExecuteChunked('''UPDATE inbox SET folder='trash' WHERE msgid IN ({0})''',
idCount, *inventoryHashesToTrash)
tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1)
tableWidget.setUpdatesEnabled(True)
self.propagateUnreadCount(self.getCurrentAccount, folder)
self.updateStatusBar(_translate(
"MainWindow", "Moved items to trash."))
2015-11-01 09:56:37 +00:00
def on_action_TrashUndelete(self):
"""TBC"""
2015-11-01 09:56:37 +00:00
tableWidget = self.getCurrentMessagelist()
if not tableWidget:
return
currentRow = 0
tableWidget.setUpdatesEnabled(False)
inventoryHashesToTrash = []
# ranges in reversed order
for r in sorted(tableWidget.selectedRanges(), key=lambda r: r.topRow())[::-1]:
for i in range(r.bottomRow() - r.topRow() + 1):
inventoryHashToTrash = str(tableWidget.item(
r.topRow() + i, 3).data(QtCore.Qt.UserRole).toPyObject())
if inventoryHashToTrash in inventoryHashesToTrash:
continue
inventoryHashesToTrash.append(inventoryHashToTrash)
2018-01-28 11:48:25 +00:00
currentRow = r.topRow()
self.getCurrentMessageTextedit().setText("")
tableWidget.model().removeRows(r.topRow(), r.bottomRow() - r.topRow() + 1)
2015-11-01 09:56:37 +00:00
if currentRow == 0:
tableWidget.selectRow(currentRow)
else:
tableWidget.selectRow(currentRow - 1)
idCount = len(inventoryHashesToTrash)
sqlExecuteChunked('''UPDATE inbox SET folder='inbox' WHERE msgid IN({0})''',
idCount, *inventoryHashesToTrash)
tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1)
tableWidget.setUpdatesEnabled(True)
self.propagateUnreadCount(self.getCurrentAccount)
self.updateStatusBar(_translate("MainWindow", "Undeleted item."))
2013-05-02 15:53:54 +00:00
2013-06-16 22:28:18 +00:00
def on_action_InboxSaveMessageAs(self):
"""TBC"""
tableWidget = self.getCurrentMessagelist()
if not tableWidget:
return
currentInboxRow = tableWidget.currentRow()
try:
subjectAtCurrentInboxRow = str(tableWidget.item(
currentInboxRow, 2).data(QtCore.Qt.UserRole))
except:
subjectAtCurrentInboxRow = ''
# Retrieve the message data out of the SQL database
msgid = str(tableWidget.item(
currentInboxRow, 3).data(QtCore.Qt.UserRole).toPyObject())
queryreturn = sqlQuery(
'''select message from inbox where msgid=?''', msgid)
if queryreturn != []:
for row in queryreturn:
message, = row
2013-06-16 22:28:18 +00:00
defaultFilename = "".join(x for x in subjectAtCurrentInboxRow if x.isalnum()) + '.txt'
filename = QtGui.QFileDialog.getSaveFileName(
self, _translate("MainWindow", "Save As..."),
defaultFilename, "Text files (*.txt);;All files (*.*)")
2013-06-16 22:28:18 +00:00
if filename == '':
return
try:
f = open(filename, 'w')
f.write(message)
2013-06-16 22:28:18 +00:00
f.close()
except Exception:
logger.exception('Message not saved', exc_info=True)
self.updateStatusBar(_translate("MainWindow", "Write error."))
2013-06-16 22:28:18 +00:00
2013-05-02 15:53:54 +00:00
def on_action_SentTrash(self):
"""Send item on the Sent tab to trash"""
2015-11-01 09:59:11 +00:00
currentRow = 0
tableWidget = self.getCurrentMessagelist()
if not tableWidget:
return
folder = self.getCurrentFolder()
shifted = (QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ShiftModifier) > 0
2015-11-01 09:59:11 +00:00
while tableWidget.selectedIndexes() != []:
currentRow = tableWidget.selectedIndexes()[0].row()
ackdataToTrash = str(tableWidget.item(
currentRow, 3).data(QtCore.Qt.UserRole).toPyObject())
if folder == "trash" or shifted:
sqlExecute('''DELETE FROM sent WHERE ackdata=?''', ackdataToTrash)
else:
sqlExecute('''UPDATE sent SET folder='trash' WHERE ackdata=?''', ackdataToTrash)
2016-01-24 11:16:41 +00:00
if tableWidget.item(currentRow, 0).unread:
self.propagateUnreadCount(
tableWidget.item(
currentRow,
1 if tableWidget.item(currentRow, 1).type == AccountMixin.SUBSCRIPTION else 0
).data(QtCore.Qt.UserRole),
folder,
self.getCurrentTreeWidget(),
-1,
)
2015-11-01 09:59:11 +00:00
self.getCurrentMessageTextedit().setPlainText("")
tableWidget.removeRow(currentRow)
self.updateStatusBar(_translate(
"MainWindow", "Moved items to trash."))
self.ui.tableWidgetInbox.selectRow(
currentRow if currentRow == 0 else currentRow - 1)
2013-05-02 15:53:54 +00:00
def on_action_ForceSend(self):
"""TBC"""
currentRow = self.ui.tableWidgetInbox.currentRow()
addressAtCurrentRow = self.ui.tableWidgetInbox.item(
currentRow, 0).data(QtCore.Qt.UserRole)
toRipe = decodeAddress(addressAtCurrentRow)[3]
2013-08-27 00:01:19 +00:00
sqlExecute(
'''UPDATE sent SET status='forcepow' WHERE toripe=? AND status='toodifficult' and folder='sent' ''',
toRipe)
queryreturn = sqlQuery('''select ackdata FROM sent WHERE status='forcepow' ''')
for row in queryreturn:
ackdata, = row
queues.UISignalQueue.put(('updateSentItemStatusByAckdata', (
ackdata, 'Overriding maximum-difficulty setting. Work queued.')))
queues.workerQueue.put(('sendmessage', ''))
2013-05-02 15:53:54 +00:00
def on_action_SentClipboard(self):
"""TBC"""
currentRow = self.ui.tableWidgetInbox.currentRow()
addressAtCurrentRow = self.ui.tableWidgetInbox.item(
currentRow, 0).data(QtCore.Qt.UserRole)
2013-05-02 15:53:54 +00:00
clipboard = QtGui.QApplication.clipboard()
clipboard.setText(str(addressAtCurrentRow))
def on_action_AddressBookNew(self):
"""Group of functions for the Address Book dialog box"""
2013-05-02 15:53:54 +00:00
self.click_pushButtonAddAddressBook()
2013-05-02 15:53:54 +00:00
def on_action_AddressBookDelete(self):
"""TBC"""
2013-05-02 15:53:54 +00:00
while self.ui.tableWidgetAddressBook.selectedIndexes() != []:
currentRow = self.ui.tableWidgetAddressBook.selectedIndexes()[
0].row()
labelAtCurrentRow = self.ui.tableWidgetAddressBook.item(
currentRow, 0).text().toUtf8()
addressAtCurrentRow = self.ui.tableWidgetAddressBook.item(
currentRow, 1).text()
2013-08-27 00:01:19 +00:00
sqlExecute('''DELETE FROM addressbook WHERE label=? AND address=?''',
str(labelAtCurrentRow), str(addressAtCurrentRow))
2013-05-02 15:53:54 +00:00
self.ui.tableWidgetAddressBook.removeRow(currentRow)
self.rerenderMessagelistFromLabels()
self.rerenderMessagelistToLabels()
2013-05-02 15:53:54 +00:00
def on_action_AddressBookClipboard(self):
"""TBC"""
2013-05-02 15:53:54 +00:00
fullStringOfAddresses = ''
listOfSelectedRows = {}
for i in range(len(self.ui.tableWidgetAddressBook.selectedIndexes())):
listOfSelectedRows[
self.ui.tableWidgetAddressBook.selectedIndexes()[i].row()] = 0
2013-05-02 15:53:54 +00:00
for currentRow in listOfSelectedRows:
addressAtCurrentRow = self.ui.tableWidgetAddressBook.item(
currentRow, 1).text()
2013-05-02 15:53:54 +00:00
if fullStringOfAddresses == '':
fullStringOfAddresses = addressAtCurrentRow
else:
fullStringOfAddresses += ', ' + str(addressAtCurrentRow)
2013-05-02 15:53:54 +00:00
clipboard = QtGui.QApplication.clipboard()
clipboard.setText(fullStringOfAddresses)
2013-05-02 15:53:54 +00:00
def on_action_AddressBookSend(self):
"""TBC"""
2013-05-02 15:53:54 +00:00
listOfSelectedRows = {}
for i in range(len(self.ui.tableWidgetAddressBook.selectedIndexes())):
listOfSelectedRows[
self.ui.tableWidgetAddressBook.selectedIndexes()[i].row()] = 0
2013-05-02 15:53:54 +00:00
for currentRow in listOfSelectedRows:
addressAtCurrentRow = self.ui.tableWidgetAddressBook.item(
currentRow, 0).address
labelAtCurrentRow = self.ui.tableWidgetAddressBook.item(
currentRow, 0).label
stringToAdd = labelAtCurrentRow + " <" + addressAtCurrentRow + ">"
2013-05-02 15:53:54 +00:00
if self.ui.lineEditTo.text() == '':
self.ui.lineEditTo.setText(stringToAdd)
2013-05-02 15:53:54 +00:00
else:
2016-04-29 09:43:40 +00:00
self.ui.lineEditTo.setText(unicode(
self.ui.lineEditTo.text().toUtf8(), encoding="UTF-8") + '; ' + stringToAdd)
2013-05-02 15:53:54 +00:00
if listOfSelectedRows == {}:
self.updateStatusBar(_translate(
"MainWindow", "No addresses selected."))
2013-05-02 15:53:54 +00:00
else:
self.statusbar.clearMessage()
self.ui.tabWidget.setCurrentIndex(
self.ui.tabWidget.indexOf(self.ui.send)
)
2013-05-02 15:53:54 +00:00
def on_action_AddressBookSubscribe(self):
"""TBC"""
listOfSelectedRows = {}
for i in range(len(self.ui.tableWidgetAddressBook.selectedIndexes())):
listOfSelectedRows[self.ui.tableWidgetAddressBook.selectedIndexes()[i].row()] = 0
for currentRow in listOfSelectedRows:
addressAtCurrentRow = str(self.ui.tableWidgetAddressBook.item(currentRow, 1).text())
# Then subscribe to it... provided it's not already in the address book
if shared.isAddressInMySubscriptionsList(addressAtCurrentRow):
self.updateStatusBar(_translate(
"MainWindow",
"Error: You cannot add the same address to your"
" subscriptions twice. Perhaps rename the existing"
" one if you want."))
2013-06-14 02:27:52 +00:00
continue
labelAtCurrentRow = self.ui.tableWidgetAddressBook.item(currentRow, 0).text().toUtf8()
2013-07-22 05:10:22 +00:00
self.addSubscription(addressAtCurrentRow, labelAtCurrentRow)
self.ui.tabWidget.setCurrentIndex(
self.ui.tabWidget.indexOf(self.ui.subscriptions)
)
2013-05-02 15:53:54 +00:00
def on_context_menuAddressBook(self, point):
"""TBC"""
self.popMenuAddressBook = QtGui.QMenu(self)
self.popMenuAddressBook.addAction(self.actionAddressBookSend)
self.popMenuAddressBook.addAction(self.actionAddressBookClipboard)
self.popMenuAddressBook.addAction(self.actionAddressBookSubscribe)
self.popMenuAddressBook.addAction(self.actionAddressBookSetAvatar)
self.popMenuAddressBook.addAction(self.actionAddressBookSetSound)
self.popMenuAddressBook.addSeparator()
self.popMenuAddressBook.addAction(self.actionAddressBookNew)
normal = True
for row in self.ui.tableWidgetAddressBook.selectedIndexes():
currentRow = row.row()
row_type = self.ui.tableWidgetAddressBook.item(
2015-12-01 00:09:28 +00:00
currentRow, 0).type
if row_type != AccountMixin.NORMAL:
normal = False
if normal:
# only if all selected addressbook items are normal, allow delete
self.popMenuAddressBook.addAction(self.actionAddressBookDelete)
self.popMenuAddressBook.exec_(
self.ui.tableWidgetAddressBook.mapToGlobal(point))
2013-05-02 15:53:54 +00:00
def on_action_SubscriptionsNew(self):
"""Group of functions for the Subscriptions dialog box"""
2013-05-02 15:53:54 +00:00
self.click_pushButtonAddSubscription()
2013-05-02 15:53:54 +00:00
def on_action_SubscriptionsDelete(self):
"""TBC"""
if QtGui.QMessageBox.question(
self, "Delete subscription?",
_translate(
"MainWindow",
"If you delete the subscription, messages that you"
" already received will become inaccessible. Maybe"
" you can consider disabling the subscription instead."
" Disabled subscriptions will not receive new"
" messages, but you can still view messages you"
" already received.\n\nAre you sure you want to"
" delete the subscription?"
), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
) != QtGui.QMessageBox.Yes:
return
address = self.getCurrentAccount()
sqlExecute('''DELETE FROM subscriptions WHERE address=?''',
address)
self.rerenderTabTreeSubscriptions()
self.rerenderMessagelistFromLabels()
self.rerenderAddressBook()
2013-05-02 15:53:54 +00:00
shared.reloadBroadcastSendersForWhichImWatching()
2013-05-02 15:53:54 +00:00
def on_action_SubscriptionsClipboard(self):
"""TBC"""
address = self.getCurrentAccount()
2013-05-02 15:53:54 +00:00
clipboard = QtGui.QApplication.clipboard()
clipboard.setText(str(address))
2013-05-02 15:53:54 +00:00
def on_action_SubscriptionsEnable(self):
"""TBC"""
address = self.getCurrentAccount()
2013-08-27 00:01:19 +00:00
sqlExecute(
'''update subscriptions set enabled=1 WHERE address=?''',
address)
account = self.getCurrentItem()
account.setEnabled(True)
self.rerenderAddressBook()
2013-05-02 15:53:54 +00:00
shared.reloadBroadcastSendersForWhichImWatching()
2013-05-02 15:53:54 +00:00
def on_action_SubscriptionsDisable(self):
"""TBC"""
address = self.getCurrentAccount()
2013-08-27 00:01:19 +00:00
sqlExecute(
'''update subscriptions set enabled=0 WHERE address=?''',
address)
account = self.getCurrentItem()
account.setEnabled(False)
self.rerenderAddressBook()
2013-05-02 15:53:54 +00:00
shared.reloadBroadcastSendersForWhichImWatching()
2013-05-02 15:53:54 +00:00
def on_context_menuSubscriptions(self, point):
"""TBC"""
currentItem = self.getCurrentItem()
self.popMenuSubscriptions = QtGui.QMenu(self)
if isinstance(currentItem, Ui_AddressWidget):
self.popMenuSubscriptions.addAction(self.actionsubscriptionsNew)
self.popMenuSubscriptions.addAction(self.actionsubscriptionsDelete)
self.popMenuSubscriptions.addSeparator()
if currentItem.isEnabled:
self.popMenuSubscriptions.addAction(self.actionsubscriptionsDisable)
else:
self.popMenuSubscriptions.addAction(self.actionsubscriptionsEnable)
self.popMenuSubscriptions.addAction(self.actionsubscriptionsSetAvatar)
self.popMenuSubscriptions.addSeparator()
self.popMenuSubscriptions.addAction(self.actionsubscriptionsClipboard)
self.popMenuSubscriptions.addSeparator()
# preloaded gui.menu plugins with prefix 'address'
for plugin in self.menu_plugins['address']:
self.popMenuSubscriptions.addAction(plugin)
self.popMenuSubscriptions.addSeparator()
self.popMenuSubscriptions.addAction(self.actionMarkAllRead)
self.popMenuSubscriptions.exec_(
self.ui.treeWidgetSubscriptions.mapToGlobal(point))
2013-05-02 15:53:54 +00:00
def widgetConvert(self, widget): # pylint: disable=inconsistent-return-statements
"""TBC"""
if widget == self.ui.tableWidgetInbox:
return self.ui.treeWidgetYourIdentities
elif widget == self.ui.tableWidgetInboxSubscriptions:
return self.ui.treeWidgetSubscriptions
elif widget == self.ui.tableWidgetInboxChans:
return self.ui.treeWidgetChans
elif widget == self.ui.treeWidgetYourIdentities:
return self.ui.tableWidgetInbox
elif widget == self.ui.treeWidgetSubscriptions:
return self.ui.tableWidgetInboxSubscriptions
elif widget == self.ui.treeWidgetChans:
return self.ui.tableWidgetInboxChans
2015-03-21 10:37:08 +00:00
def getCurrentTreeWidget(self):
"""TBC"""
currentIndex = self.ui.tabWidget.currentIndex()
2015-03-21 10:37:08 +00:00
treeWidgetList = [
self.ui.treeWidgetYourIdentities,
False,
self.ui.treeWidgetSubscriptions,
self.ui.treeWidgetChans
]
return treeWidgetList[currentIndex] if currentIndex >= 0 and currentIndex < len(treeWidgetList) else False
2015-03-21 10:37:08 +00:00
def getAccountTreeWidget(self, account):
"""TBC"""
try:
2015-11-26 18:41:20 +00:00
if account.type == AccountMixin.CHAN:
return self.ui.treeWidgetChans
2015-11-26 18:41:20 +00:00
elif account.type == AccountMixin.SUBSCRIPTION:
return self.ui.treeWidgetSubscriptions
return self.ui.treeWidgetYourIdentities
except:
return self.ui.treeWidgetYourIdentities
def getCurrentMessagelist(self):
"""TBC"""
currentIndex = self.ui.tabWidget.currentIndex()
messagelistList = [
self.ui.tableWidgetInbox,
False,
self.ui.tableWidgetInboxSubscriptions,
self.ui.tableWidgetInboxChans,
]
if currentIndex >= 0 and currentIndex < len(messagelistList):
return messagelistList[currentIndex]
return False
def getAccountMessagelist(self, account):
"""TBC"""
try:
2015-11-26 18:41:20 +00:00
if account.type == AccountMixin.CHAN:
return self.ui.tableWidgetInboxChans
2015-11-26 18:41:20 +00:00
elif account.type == AccountMixin.SUBSCRIPTION:
return self.ui.tableWidgetInboxSubscriptions
return self.ui.tableWidgetInbox
except:
return self.ui.tableWidgetInbox
def getCurrentMessageId(self):
"""TBC"""
messagelist = self.getCurrentMessagelist()
if messagelist:
currentRow = messagelist.currentRow()
if currentRow >= 0:
msgid = str(messagelist.item(
currentRow, 3).data(QtCore.Qt.UserRole).toPyObject())
# data is saved at the 4. column of the table...
return msgid
return False
def getCurrentMessageTextedit(self):
"""TBC"""
currentIndex = self.ui.tabWidget.currentIndex()
messagelistList = [
self.ui.textEditInboxMessage,
False,
self.ui.textEditInboxMessageSubscriptions,
self.ui.textEditInboxMessageChans,
]
if currentIndex >= 0 and currentIndex < len(messagelistList):
return messagelistList[currentIndex]
return False
def getAccountTextedit(self, account):
"""TBC"""
try:
2015-11-26 18:41:20 +00:00
if account.type == AccountMixin.CHAN:
return self.ui.textEditInboxMessageChans
2015-11-26 18:41:20 +00:00
elif account.type == AccountMixin.SUBSCRIPTION:
return self.ui.textEditInboxSubscriptions
return self.ui.textEditInboxMessage
except:
return self.ui.textEditInboxMessage
def getCurrentSearchLine(self, currentIndex=None, retObj=False): # pylint: disable=inconsistent-return-statements
"""TBC"""
if currentIndex is None:
currentIndex = self.ui.tabWidget.currentIndex()
messagelistList = [
self.ui.inboxSearchLineEdit,
False,
self.ui.inboxSearchLineEditSubscriptions,
self.ui.inboxSearchLineEditChans,
]
if currentIndex >= 0 and currentIndex < len(messagelistList):
if retObj:
return messagelistList[currentIndex]
return messagelistList[currentIndex].text().toUtf8().data()
def getCurrentSearchOption(self, currentIndex=None): # pylint: disable=inconsistent-return-statements
"""TBC"""
if currentIndex is None:
currentIndex = self.ui.tabWidget.currentIndex()
messagelistList = [
self.ui.inboxSearchOption,
False,
self.ui.inboxSearchOptionSubscriptions,
self.ui.inboxSearchOptionChans,
]
if currentIndex >= 0 and currentIndex < len(messagelistList):
return messagelistList[currentIndex].currentText().toUtf8().data()
def getCurrentItem(self, treeWidget=None):
"""Group of functions for the Your Identities dialog box"""
if treeWidget is None:
treeWidget = self.getCurrentTreeWidget()
2015-03-21 10:37:08 +00:00
if treeWidget:
currentItem = treeWidget.currentItem()
if currentItem:
return currentItem
return False
def getCurrentAccount(self, treeWidget=None):
"""TODO: debug msg in else?"""
currentItem = self.getCurrentItem(treeWidget)
if currentItem:
account = currentItem.address
return account
return False
def getCurrentFolder(self, treeWidget=None): # pylint: disable=inconsistent-return-statements
"""TBC"""
2015-03-21 10:37:08 +00:00
if treeWidget is None:
treeWidget = self.getCurrentTreeWidget()
2015-03-21 10:37:08 +00:00
if treeWidget:
currentItem = treeWidget.currentItem()
if currentItem and hasattr(currentItem, 'folderName'):
return currentItem.folderName
2015-03-21 10:37:08 +00:00
def setCurrentItemColor(self, color):
"""TBC"""
2015-03-21 10:37:08 +00:00
treeWidget = self.getCurrentTreeWidget()
if treeWidget:
brush = QtGui.QBrush()
brush.setStyle(QtCore.Qt.NoBrush)
brush.setColor(color)
2015-03-21 10:37:08 +00:00
currentItem = treeWidget.currentItem()
currentItem.setForeground(0, brush)
2013-05-02 15:53:54 +00:00
def on_action_YourIdentitiesNew(self):
"""TBC"""
2013-05-02 15:53:54 +00:00
self.click_NewAddressDialog()
2015-11-09 17:22:38 +00:00
def on_action_YourIdentitiesDelete(self):
"""TBC"""
2015-11-09 17:22:38 +00:00
account = self.getCurrentItem()
2015-11-26 18:41:20 +00:00
if account.type == AccountMixin.NORMAL:
return # maybe in the future
2015-11-26 18:41:20 +00:00
elif account.type == AccountMixin.CHAN:
if QtGui.QMessageBox.question(
self, "Delete channel?",
_translate(
"MainWindow",
"If you delete the channel, messages that you"
" already received will become inaccessible."
" Maybe you can consider disabling the channel"
" instead. Disabled channels will not receive new"
" messages, but you can still view messages you"
" already received.\n\nAre you sure you want to"
" delete the channel?"
), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
) == QtGui.QMessageBox.Yes:
BMConfigParser().remove_section(str(account.address))
2015-11-09 17:22:38 +00:00
else:
return
else:
return
BMConfigParser().save()
2015-11-09 17:22:38 +00:00
shared.reloadMyAddressHashes()
self.rerenderAddressBook()
self.rerenderComboBoxSendFrom()
2015-11-26 18:41:20 +00:00
if account.type == AccountMixin.NORMAL:
2015-11-09 17:22:38 +00:00
self.rerenderTabTreeMessages()
2015-11-26 18:41:20 +00:00
elif account.type == AccountMixin.CHAN:
2015-11-09 17:22:38 +00:00
self.rerenderTabTreeChans()
2015-03-21 10:37:08 +00:00
def on_action_Enable(self):
"""TBC"""
2015-03-21 10:37:08 +00:00
addressAtCurrentRow = self.getCurrentAccount()
self.enableIdentity(addressAtCurrentRow)
account = self.getCurrentItem()
account.setEnabled(True)
2015-03-21 10:37:08 +00:00
def enableIdentity(self, address):
"""TBC"""
BMConfigParser().set(address, 'enabled', 'true')
BMConfigParser().save()
2013-05-02 15:53:54 +00:00
shared.reloadMyAddressHashes()
self.rerenderAddressBook()
2015-03-21 10:37:08 +00:00
def on_action_Disable(self):
"""TBC"""
2015-03-21 10:37:08 +00:00
address = self.getCurrentAccount()
self.disableIdentity(address)
account = self.getCurrentItem()
account.setEnabled(False)
2015-03-21 10:37:08 +00:00
def disableIdentity(self, address):
"""TBC"""
BMConfigParser().set(str(address), 'enabled', 'false')
BMConfigParser().save()
2013-05-02 15:53:54 +00:00
shared.reloadMyAddressHashes()
self.rerenderAddressBook()
2015-03-21 10:37:08 +00:00
def on_action_Clipboard(self):
"""TBC"""
address = self.getCurrentAccount()
2013-05-02 15:53:54 +00:00
clipboard = QtGui.QApplication.clipboard()
clipboard.setText(str(address))
def on_action_ClipboardMessagelist(self):
"""TBC"""
tableWidget = self.getCurrentMessagelist()
currentColumn = tableWidget.currentColumn()
currentRow = tableWidget.currentRow()
if currentColumn not in [0, 1, 2]: # to, from, subject
if self.getCurrentFolder() == "sent":
currentColumn = 0
else:
currentColumn = 1
if self.getCurrentFolder() == "sent":
myAddress = tableWidget.item(currentRow, 1).data(QtCore.Qt.UserRole)
otherAddress = tableWidget.item(currentRow, 0).data(QtCore.Qt.UserRole)
else:
myAddress = tableWidget.item(currentRow, 0).data(QtCore.Qt.UserRole)
otherAddress = tableWidget.item(currentRow, 1).data(QtCore.Qt.UserRole)
account = accountClass(myAddress)
if all(
[
isinstance(account, GatewayAccount),
otherAddress == account.relayAddress,
any(
[
currentColumn in [0, 2] and self.getCurrentFolder() == "sent",
currentColumn in [1, 2] and self.getCurrentFolder() != "sent",
]
),
]
):
text = str(tableWidget.item(currentRow, currentColumn).label)
else:
text = tableWidget.item(currentRow, currentColumn).data(QtCore.Qt.UserRole)
text = unicode(str(text), 'utf-8', 'ignore')
clipboard = QtGui.QApplication.clipboard()
clipboard.setText(text)
2015-03-21 10:37:08 +00:00
def on_action_TreeWidgetSetAvatar(self):
"""set avatar functions"""
address = self.getCurrentAccount()
self.setAvatar(address)
def on_action_AddressBookSetAvatar(self):
"""TBC"""
self.on_action_SetAvatar(self.ui.tableWidgetAddressBook)
def on_action_SetAvatar(self, thisTableWidget):
"""TBC"""
currentRow = thisTableWidget.currentRow()
addressAtCurrentRow = thisTableWidget.item(
2013-09-20 12:30:53 +00:00
currentRow, 1).text()
2015-03-21 10:37:08 +00:00
setToIdenticon = not self.setAvatar(addressAtCurrentRow)
if setToIdenticon:
thisTableWidget.item(
currentRow, 0).setIcon(avatarize(addressAtCurrentRow))
def setAvatar(self, addressAtCurrentRow):
"""TBC"""
if not os.path.exists(state.appdata + 'avatars/'):
os.makedirs(state.appdata + 'avatars/')
addressHash = hashlib.md5(addBMIfNotPresent(addressAtCurrentRow)).hexdigest()
extensions = [
'PNG',
'GIF',
'JPG',
'JPEG',
'SVG',
'BMP',
'MNG',
'PBM',
'PGM',
'PPM',
'TIFF',
'XBM',
'XPM',
'TGA']
2013-09-20 12:30:53 +00:00
# http://pyqt.sourceforge.net/Docs/PyQt4/qimagereader.html#supportedImageFormats
names = {
'BMP': 'Windows Bitmap',
'GIF': 'Graphic Interchange Format',
'JPG': 'Joint Photographic Experts Group',
'JPEG': 'Joint Photographic Experts Group',
'MNG': 'Multiple-image Network Graphics',
'PNG': 'Portable Network Graphics',
'PBM': 'Portable Bitmap',
'PGM': 'Portable Graymap',
'PPM': 'Portable Pixmap',
'TIFF': 'Tagged Image File Format',
'XBM': 'X11 Bitmap',
'XPM': 'X11 Pixmap',
'SVG': 'Scalable Vector Graphics',
'TGA': 'Targa Image Format'}
2013-09-20 12:30:53 +00:00
filters = []
all_images_filter = []
current_files = []
2013-09-20 12:30:53 +00:00
for ext in extensions:
filters += [names[ext] + ' (*.' + ext.lower() + ')']
all_images_filter += ['*.' + ext.lower()]
upper = state.appdata + 'avatars/' + addressHash + '.' + ext.upper()
lower = state.appdata + 'avatars/' + addressHash + '.' + ext.lower()
if os.path.isfile(lower):
current_files += [lower]
elif os.path.isfile(upper):
current_files += [upper]
2013-09-20 12:30:53 +00:00
filters[0:0] = ['Image files (' + ' '.join(all_images_filter) + ')']
filters[1:1] = ['All files (*.*)']
sourcefile = QtGui.QFileDialog.getOpenFileName(
self, _translate("MainWindow", "Set avatar..."),
filter=';;'.join(filters)
)
2013-09-20 12:30:53 +00:00
# determine the correct filename (note that avatars don't use the suffix)
destination = state.appdata + 'avatars/' + addressHash + '.' + sourcefile.split('.')[-1]
2013-09-20 12:30:53 +00:00
exists = QtCore.QFile.exists(destination)
if sourcefile == '':
# ask for removal of avatar
if exists | current_files:
displayMsg = _translate("MainWindow", "Do you really want to remove this avatar?")
overwrite = QtGui.QMessageBox.question(
self, 'Message', displayMsg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
else:
overwrite = QtGui.QMessageBox.No
else:
# ask whether to overwrite old avatar
if exists | current_files:
displayMsg = _translate(
"MainWindow",
"You have already set an avatar for this address. Do you really want to overwrite it?")
overwrite = QtGui.QMessageBox.question(
self, 'Message', displayMsg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
else:
overwrite = QtGui.QMessageBox.No
# copy the image file to the appdata folder
if not exists | overwrite == QtGui.QMessageBox.Yes:
2013-09-20 12:30:53 +00:00
if overwrite == QtGui.QMessageBox.Yes:
for file_name in current_files:
QtCore.QFile.remove(file_name)
2013-09-20 12:30:53 +00:00
QtCore.QFile.remove(destination)
# copy it
if sourcefile != '':
copied = QtCore.QFile.copy(sourcefile, destination)
if not copied:
logger.error('couldn\'t copy :(')
2013-09-20 12:30:53 +00:00
# set the icon
self.rerenderTabTreeMessages()
self.rerenderTabTreeSubscriptions()
self.rerenderTabTreeChans()
self.rerenderComboBoxSendFrom()
2015-03-21 10:37:08 +00:00
self.rerenderComboBoxSendFromBroadcast()
self.rerenderMessagelistFromLabels()
self.rerenderMessagelistToLabels()
2016-03-17 21:09:46 +00:00
self.ui.blackwhitelist.rerenderBlackWhiteList()
2015-03-21 10:37:08 +00:00
# generate identicon
return False
return True
def on_action_AddressBookSetSound(self):
"""TBC"""
widget = self.ui.tableWidgetAddressBook
self.setAddressSound(widget.item(widget.currentRow(), 0).text())
def setAddressSound(self, addr):
"""TBC"""
filters = [unicode(_translate(
"MainWindow", "Sound files (%s)" %
' '.join(['*%s%s' % (os.extsep, ext) for ext in sound.extensions])
))]
sourcefile = unicode(QtGui.QFileDialog.getOpenFileName(
self, _translate("MainWindow", "Set notification sound..."),
filter=';;'.join(filters)
))
if not sourcefile:
return
destdir = os.path.join(state.appdata, 'sounds')
destfile = unicode(addr) + os.path.splitext(sourcefile)[-1]
destination = os.path.join(destdir, destfile)
if sourcefile == destination:
return
pattern = destfile.lower()
for item in os.listdir(destdir):
if item.lower() == pattern:
overwrite = QtGui.QMessageBox.question(
self, _translate("MainWindow", "Message"),
_translate(
"MainWindow",
"You have already set a notification sound"
" for this address book entry."
" Do you really want to overwrite it?"),
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No
) == QtGui.QMessageBox.Yes
if overwrite:
QtCore.QFile.remove(os.path.join(destdir, item))
break
if not QtCore.QFile.copy(sourcefile, destination):
logger.error(
'couldn\'t copy %s to %s', sourcefile, destination)
2013-05-02 15:53:54 +00:00
def on_context_menuYourIdentities(self, point):
"""TBC"""
currentItem = self.getCurrentItem()
self.popMenuYourIdentities = QtGui.QMenu(self)
if isinstance(currentItem, Ui_AddressWidget):
self.popMenuYourIdentities.addAction(self.actionNewYourIdentities)
self.popMenuYourIdentities.addSeparator()
self.popMenuYourIdentities.addAction(self.actionClipboardYourIdentities)
self.popMenuYourIdentities.addSeparator()
if currentItem.isEnabled:
self.popMenuYourIdentities.addAction(self.actionDisableYourIdentities)
else:
self.popMenuYourIdentities.addAction(self.actionEnableYourIdentities)
self.popMenuYourIdentities.addAction(self.actionSetAvatarYourIdentities)
self.popMenuYourIdentities.addAction(self.actionSpecialAddressBehaviorYourIdentities)
self.popMenuYourIdentities.addAction(self.actionEmailGateway)
self.popMenuYourIdentities.addSeparator()
if currentItem.type != AccountMixin.ALL:
# preloaded gui.menu plugins with prefix 'address'
for plugin in self.menu_plugins['address']:
self.popMenuYourIdentities.addAction(plugin)
self.popMenuYourIdentities.addSeparator()
self.popMenuYourIdentities.addAction(self.actionMarkAllRead)
2015-03-21 10:37:08 +00:00
self.popMenuYourIdentities.exec_(
self.ui.treeWidgetYourIdentities.mapToGlobal(point))
def on_context_menuChan(self, point):
"""TODO: make one popMenu"""
currentItem = self.getCurrentItem()
self.popMenu = QtGui.QMenu(self)
if isinstance(currentItem, Ui_AddressWidget):
self.popMenu.addAction(self.actionNew)
self.popMenu.addAction(self.actionDelete)
self.popMenu.addSeparator()
self.popMenu.addAction(self.actionClipboard)
self.popMenu.addSeparator()
if currentItem.isEnabled:
self.popMenu.addAction(self.actionDisable)
else:
self.popMenu.addAction(self.actionEnable)
self.popMenu.addAction(self.actionSetAvatar)
self.popMenu.addSeparator()
# preloaded gui.menu plugins with prefix 'address'
for plugin in self.menu_plugins['address']:
self.popMenu.addAction(plugin)
self.popMenu.addSeparator()
self.popMenu.addAction(self.actionMarkAllRead)
self.popMenu.exec_(
self.ui.treeWidgetChans.mapToGlobal(point))
2013-05-02 15:53:54 +00:00
def on_context_menuInbox(self, point):
"""TBC"""
tableWidget = self.getCurrentMessagelist()
if tableWidget:
currentFolder = self.getCurrentFolder()
if currentFolder is None:
pass
if currentFolder == 'sent':
self.on_context_menuSent(point)
else:
2015-11-01 09:56:37 +00:00
self.popMenuInbox = QtGui.QMenu(self)
self.popMenuInbox.addAction(self.actionForceHtml)
self.popMenuInbox.addAction(self.actionMarkUnread)
self.popMenuInbox.addSeparator()
address = tableWidget.item(
tableWidget.currentRow(), 0).data(QtCore.Qt.UserRole)
account = accountClass(address)
if account.type == AccountMixin.CHAN:
self.popMenuInbox.addAction(self.actionReplyChan)
2015-11-01 09:56:37 +00:00
self.popMenuInbox.addAction(self.actionReply)
self.popMenuInbox.addAction(self.actionAddSenderToAddressBook)
self.actionClipboardMessagelist = self.ui.inboxContextMenuToolbar.addAction(
_translate(
"MainWindow", "Copy subject to clipboard"
if tableWidget.currentColumn() == 2 else "Copy address to clipboard"),
self.on_action_ClipboardMessagelist)
self.popMenuInbox.addAction(self.actionClipboardMessagelist)
2015-11-01 09:56:37 +00:00
self.popMenuInbox.addSeparator()
self.popMenuInbox.addAction(self.actionAddSenderToBlackList)
self.popMenuInbox.addSeparator()
2015-11-01 09:56:37 +00:00
self.popMenuInbox.addAction(self.actionSaveMessageAs)
if currentFolder == "trash":
self.popMenuInbox.addAction(self.actionUndeleteTrashedMessage)
else:
self.popMenuInbox.addAction(self.actionTrashInboxMessage)
self.popMenuInbox.exec_(tableWidget.mapToGlobal(point))
2013-05-02 15:53:54 +00:00
def on_context_menuSent(self, point):
"""TBC"""
self.popMenuSent = QtGui.QMenu(self)
self.popMenuSent.addAction(self.actionSentClipboard)
self.popMenuSent.addAction(self.actionTrashSentMessage)
# Check to see if this item is toodifficult and display an additional
# menu option (Force Send) if it is.
currentRow = self.ui.tableWidgetInbox.currentRow()
if currentRow >= 0:
ackData = str(self.ui.tableWidgetInbox.item(
currentRow, 3).data(QtCore.Qt.UserRole).toPyObject())
queryreturn = sqlQuery('''SELECT status FROM sent where ackdata=?''', ackData)
for row in queryreturn:
status, = row
if status == 'toodifficult':
self.popMenuSent.addAction(self.actionForceSend)
self.popMenuSent.exec_(self.ui.tableWidgetInbox.mapToGlobal(point))
2013-05-02 15:53:54 +00:00
def inboxSearchLineEditUpdated(self, text):
"""TBC"""
# dynamic search for too short text is slow
if len(str(text)) < 3:
return
messagelist = self.getCurrentMessagelist()
searchOption = self.getCurrentSearchOption()
if messagelist:
account = self.getCurrentAccount()
folder = self.getCurrentFolder()
self.loadMessagelist(messagelist, account, folder, searchOption, str(text))
def inboxSearchLineEditReturnPressed(self):
"""TBC"""
logger.debug("Search return pressed")
searchLine = self.getCurrentSearchLine()
messagelist = self.getCurrentMessagelist()
if len(str(searchLine)) < 3:
searchOption = self.getCurrentSearchOption()
account = self.getCurrentAccount()
folder = self.getCurrentFolder()
self.loadMessagelist(messagelist, account, folder, searchOption, searchLine)
if messagelist:
messagelist.setFocus()
def treeWidgetItemClicked(self):
"""TBC"""
searchLine = self.getCurrentSearchLine()
searchOption = self.getCurrentSearchOption()
messageTextedit = self.getCurrentMessageTextedit()
if messageTextedit:
messageTextedit.setPlainText(QtCore.QString(""))
messagelist = self.getCurrentMessagelist()
if messagelist:
account = self.getCurrentAccount()
folder = self.getCurrentFolder()
treeWidget = self.getCurrentTreeWidget()
# refresh count indicator
self.propagateUnreadCount(account.address if hasattr(account, 'address') else None, folder, treeWidget, 0)
self.loadMessagelist(messagelist, account, folder, searchOption, searchLine)
2013-05-02 15:53:54 +00:00
def treeWidgetItemChanged(self, item, column):
"""TBC"""
# only for manual edits. automatic edits (setText) are ignored
if column != 0:
return
# only account names of normal addresses (no chans/mailinglists)
if any(
[
not isinstance(item, Ui_AddressWidget),
not self.getCurrentTreeWidget(),
self.getCurrentTreeWidget().currentItem() is None,
]
):
return
# not visible
if (not self.getCurrentItem()) or (not isinstance(self.getCurrentItem(), Ui_AddressWidget)):
return
# only currently selected item
if item.address != self.getCurrentAccount():
return
# "All accounts" can't be renamed
if item.type == AccountMixin.ALL:
return
newLabel = unicode(item.text(0), 'utf-8', 'ignore')
oldLabel = item.defaultLabel()
# unchanged, do not do anything either
if newLabel == oldLabel:
return
# recursion prevention
if self.recurDepth > 0:
return
self.recurDepth += 1
if item.type == AccountMixin.NORMAL or item.type == AccountMixin.MAILINGLIST:
self.rerenderComboBoxSendFromBroadcast()
if item.type == AccountMixin.NORMAL or item.type == AccountMixin.CHAN:
self.rerenderComboBoxSendFrom()
self.rerenderMessagelistFromLabels()
if item.type != AccountMixin.SUBSCRIPTION:
self.rerenderMessagelistToLabels()
if item.type in (AccountMixin.NORMAL, AccountMixin.CHAN, AccountMixin.SUBSCRIPTION):
self.rerenderAddressBook()
self.recurDepth -= 1
def tableWidgetInboxItemClicked(self):
"""TBC"""
folder = self.getCurrentFolder()
messageTextedit = self.getCurrentMessageTextedit()
if not messageTextedit:
return
msgid = self.getCurrentMessageId()
if msgid:
queryreturn = sqlQuery(
'''SELECT message FROM %s WHERE %s=?''' % (
('sent', 'ackdata') if folder == 'sent'
else ('inbox', 'msgid')
), msgid
)
try:
message = queryreturn[-1][0]
except NameError:
message = ""
except IndexError:
message = _translate(
"MainWindow",
"Error occurred: could not load message from disk."
)
else:
2016-01-24 11:16:41 +00:00
tableWidget = self.getCurrentMessagelist()
currentRow = tableWidget.currentRow()
# refresh
if tableWidget.item(currentRow, 0).unread is True:
self.updateUnreadStatus(tableWidget, currentRow, msgid)
# propagate
if all(
[
folder != 'sent',
sqlExecute('''UPDATE inbox SET read=1 WHERE msgid=? AND read=0''', msgid) > 0,
]
):
self.propagateUnreadCount()
messageTextedit.setCurrentFont(QtGui.QFont())
messageTextedit.setTextColor(QtGui.QColor())
messageTextedit.setContent(message)
2013-05-02 15:53:54 +00:00
def tableWidgetAddressBookItemChanged(self, item):
"""TBC"""
if item.type == AccountMixin.CHAN:
self.rerenderComboBoxSendFrom()
self.rerenderMessagelistFromLabels()
self.rerenderMessagelistToLabels()
completerList = self.ui.lineEditTo.completer().model().stringList()
for i, this_item in enumerate(completerList):
if unicode(this_item).endswith(" <" + item.address + ">"):
this_item = item.label + " <" + item.address + ">"
2017-02-14 12:57:20 +00:00
self.ui.lineEditTo.completer().model().setStringList(completerList)
2013-05-02 15:53:54 +00:00
def tabWidgetCurrentChanged(self, n):
"""TBC"""
if n == self.ui.tabWidget.indexOf(self.ui.networkstatus):
self.ui.networkstatus.startUpdate()
else:
self.ui.networkstatus.stopUpdate()
def writeNewAddressToTable(self, label, address, streamNumber):
"""TBC"""
self.rerenderTabTreeMessages()
self.rerenderTabTreeSubscriptions()
self.rerenderTabTreeChans()
2013-05-02 15:53:54 +00:00
self.rerenderComboBoxSendFrom()
2015-03-21 10:37:08 +00:00
self.rerenderComboBoxSendFromBroadcast()
self.rerenderAddressBook()
2013-05-02 15:53:54 +00:00
def updateStatusBar(self, data):
"""TBC"""
if isinstance(data, (tuple, list)):
option = data[1]
message = data[0]
else:
option = 0
message = data
if message != "":
logger.info('Status bar: %s', message)
if option == 1:
self.statusbar.addImportant(message)
else:
self.statusbar.showMessage(message, 10000)
2013-05-02 15:53:54 +00:00
def initSettings(self):
"""TBC"""
QtCore.QCoreApplication.setOrganizationName("PyBitmessage")
QtCore.QCoreApplication.setOrganizationDomain("bitmessage.org")
QtCore.QCoreApplication.setApplicationName("pybitmessageqt")
self.loadSettings()
for attr, obj in self.ui.__dict__.iteritems():
if hasattr(obj, "__class__") and \
isinstance(obj, settingsmixin.SettingsMixin):
loadMethod = getattr(obj, "loadSettings", None)
if callable(loadMethod):
obj.loadSettings()
2013-05-02 15:53:54 +00:00
2013-05-02 15:53:54 +00:00
class settingsDialog(QtGui.QDialog):
"""TBC"""
def __init__(self, parent):
"""TBC"""
2013-05-02 15:53:54 +00:00
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_settingsDialog()
self.ui.setupUi(self)
self.parent = parent
self.ui.checkBoxStartOnLogon.setChecked(
BMConfigParser().getboolean('bitmessagesettings', 'startonlogon'))
self.ui.checkBoxMinimizeToTray.setChecked(
BMConfigParser().getboolean('bitmessagesettings', 'minimizetotray'))
self.ui.checkBoxTrayOnClose.setChecked(
BMConfigParser().safeGetBoolean('bitmessagesettings', 'trayonclose'))
self.ui.checkBoxHideTrayConnectionNotifications.setChecked(
BMConfigParser().getboolean("bitmessagesettings", "hidetrayconnectionnotifications"))
self.ui.checkBoxShowTrayNotifications.setChecked(
BMConfigParser().getboolean('bitmessagesettings', 'showtraynotifications'))
self.ui.checkBoxStartInTray.setChecked(
BMConfigParser().getboolean('bitmessagesettings', 'startintray'))
self.ui.checkBoxWillinglySendToMobile.setChecked(
BMConfigParser().safeGetBoolean('bitmessagesettings', 'willinglysendtomobile'))
2013-11-01 23:25:24 +00:00
self.ui.checkBoxUseIdenticons.setChecked(
BMConfigParser().safeGetBoolean('bitmessagesettings', 'useidenticons'))
self.ui.checkBoxReplyBelow.setChecked(
BMConfigParser().safeGetBoolean('bitmessagesettings', 'replybelow'))
if state.appdata == paths.lookupExeFolder():
2013-05-02 15:53:54 +00:00
self.ui.checkBoxPortableMode.setChecked(True)
else:
try:
import tempfile
tempfile.NamedTemporaryFile(
dir=paths.lookupExeFolder(), delete=True
).close() # should autodelete
except:
self.ui.checkBoxPortableMode.setDisabled(True)
2013-05-02 15:53:54 +00:00
if 'darwin' in sys.platform:
self.ui.checkBoxStartOnLogon.setDisabled(True)
2013-11-02 04:19:54 +00:00
self.ui.checkBoxStartOnLogon.setText(_translate(
"MainWindow", "Start-on-login not yet supported on your OS."))
2013-05-02 15:53:54 +00:00
self.ui.checkBoxMinimizeToTray.setDisabled(True)
2013-11-02 04:19:54 +00:00
self.ui.checkBoxMinimizeToTray.setText(_translate(
"MainWindow", "Minimize-to-tray not yet supported on your OS."))
2013-05-02 15:53:54 +00:00
self.ui.checkBoxShowTrayNotifications.setDisabled(True)
2013-11-02 04:19:54 +00:00
self.ui.checkBoxShowTrayNotifications.setText(_translate(
"MainWindow", "Tray notifications not yet supported on your OS."))
2013-05-02 15:53:54 +00:00
elif 'linux' in sys.platform:
self.ui.checkBoxStartOnLogon.setDisabled(True)
2013-11-02 04:19:54 +00:00
self.ui.checkBoxStartOnLogon.setText(_translate(
"MainWindow", "Start-on-login not yet supported on your OS."))
# On the Network settings tab:
self.ui.lineEditTCPPort.setText(str(
BMConfigParser().get('bitmessagesettings', 'port')))
self.ui.checkBoxUPnP.setChecked(
BMConfigParser().safeGetBoolean('bitmessagesettings', 'upnp'))
self.ui.checkBoxAuthentication.setChecked(BMConfigParser().getboolean(
'bitmessagesettings', 'socksauthentication'))
self.ui.checkBoxSocksListen.setChecked(BMConfigParser().getboolean(
'bitmessagesettings', 'sockslisten'))
if str(BMConfigParser().get('bitmessagesettings', 'socksproxytype')) == 'none':
2013-05-02 15:53:54 +00:00
self.ui.comboBoxProxyType.setCurrentIndex(0)
self.ui.lineEditSocksHostname.setEnabled(False)
self.ui.lineEditSocksPort.setEnabled(False)
self.ui.lineEditSocksUsername.setEnabled(False)
self.ui.lineEditSocksPassword.setEnabled(False)
self.ui.checkBoxAuthentication.setEnabled(False)
self.ui.checkBoxSocksListen.setEnabled(False)
elif str(BMConfigParser().get('bitmessagesettings', 'socksproxytype')) == 'SOCKS4a':
2013-05-02 15:53:54 +00:00
self.ui.comboBoxProxyType.setCurrentIndex(1)
elif str(BMConfigParser().get('bitmessagesettings', 'socksproxytype')) == 'SOCKS5':
2013-05-02 15:53:54 +00:00
self.ui.comboBoxProxyType.setCurrentIndex(2)
self.ui.lineEditSocksHostname.setText(str(
BMConfigParser().get('bitmessagesettings', 'sockshostname')))
self.ui.lineEditSocksPort.setText(str(
BMConfigParser().get('bitmessagesettings', 'socksport')))
self.ui.lineEditSocksUsername.setText(str(
BMConfigParser().get('bitmessagesettings', 'socksusername')))
self.ui.lineEditSocksPassword.setText(str(
BMConfigParser().get('bitmessagesettings', 'sockspassword')))
QtCore.QObject.connect(self.ui.comboBoxProxyType, QtCore.SIGNAL(
"currentIndexChanged(int)"), self.comboBoxProxyTypeChanged)
self.ui.lineEditMaxDownloadRate.setText(str(
BMConfigParser().get('bitmessagesettings', 'maxdownloadrate')))
self.ui.lineEditMaxUploadRate.setText(str(
BMConfigParser().get('bitmessagesettings', 'maxuploadrate')))
self.ui.lineEditMaxOutboundConnections.setText(str(
BMConfigParser().get('bitmessagesettings', 'maxoutboundconnections')))
# Demanded difficulty tab
self.ui.lineEditTotalDifficulty.setText(
str(
float(
BMConfigParser().getint('bitmessagesettings', 'defaultnoncetrialsperbyte')
) / defaults.networkDefaultProofOfWorkNonceTrialsPerByte
)
)
self.ui.lineEditSmallMessageDifficulty.setText(
str(
float(
BMConfigParser().getint('bitmessagesettings', 'defaultpayloadlengthextrabytes')
) / defaults.networkDefaultPayloadLengthExtraBytes
)
)
# Max acceptable difficulty tab
self.ui.lineEditMaxAcceptableTotalDifficulty.setText(
str(
float(
BMConfigParser().getint('bitmessagesettings', 'maxacceptablenoncetrialsperbyte')
) / defaults.networkDefaultProofOfWorkNonceTrialsPerByte
)
)
self.ui.lineEditMaxAcceptableSmallMessageDifficulty.setText(
str(
float(
BMConfigParser().getint('bitmessagesettings', 'maxacceptablepayloadlengthextrabytes')
) / defaults.networkDefaultPayloadLengthExtraBytes
)
)
2015-11-26 01:37:07 +00:00
# OpenCL
if openclpow.openclAvailable():
self.ui.comboBoxOpenCL.setEnabled(True)
2015-11-26 01:37:07 +00:00
else:
self.ui.comboBoxOpenCL.setEnabled(False)
self.ui.comboBoxOpenCL.clear()
self.ui.comboBoxOpenCL.addItem("None")
self.ui.comboBoxOpenCL.addItems(openclpow.vendors)
self.ui.comboBoxOpenCL.setCurrentIndex(0)
for i in range(self.ui.comboBoxOpenCL.count()):
if self.ui.comboBoxOpenCL.itemText(i) == BMConfigParser().safeGet('bitmessagesettings', 'opencl'):
self.ui.comboBoxOpenCL.setCurrentIndex(i)
break
2015-11-26 01:37:07 +00:00
# Namecoin integration tab
nmctype = BMConfigParser().get('bitmessagesettings', 'namecoinrpctype')
self.ui.lineEditNamecoinHost.setText(str(
BMConfigParser().get('bitmessagesettings', 'namecoinrpchost')))
self.ui.lineEditNamecoinPort.setText(str(
BMConfigParser().get('bitmessagesettings', 'namecoinrpcport')))
self.ui.lineEditNamecoinUser.setText(str(
BMConfigParser().get('bitmessagesettings', 'namecoinrpcuser')))
self.ui.lineEditNamecoinPassword.setText(str(
BMConfigParser().get('bitmessagesettings', 'namecoinrpcpassword')))
if nmctype == "namecoind":
self.ui.radioButtonNamecoinNamecoind.setChecked(True)
elif nmctype == "nmcontrol":
self.ui.radioButtonNamecoinNmcontrol.setChecked(True)
self.ui.lineEditNamecoinUser.setEnabled(False)
self.ui.labelNamecoinUser.setEnabled(False)
self.ui.lineEditNamecoinPassword.setEnabled(False)
self.ui.labelNamecoinPassword.setEnabled(False)
else:
assert False
QtCore.QObject.connect(self.ui.radioButtonNamecoinNamecoind, QtCore.SIGNAL(
"toggled(bool)"), self.namecoinTypeChanged)
QtCore.QObject.connect(self.ui.radioButtonNamecoinNmcontrol, QtCore.SIGNAL(
"toggled(bool)"), self.namecoinTypeChanged)
QtCore.QObject.connect(self.ui.pushButtonNamecoinTest, QtCore.SIGNAL(
"clicked()"), self.click_pushButtonNamecoinTest)
# Message Resend tab
self.ui.lineEditDays.setText(str(
BMConfigParser().get('bitmessagesettings', 'stopresendingafterxdays')))
self.ui.lineEditMonths.setText(str(
BMConfigParser().get('bitmessagesettings', 'stopresendingafterxmonths')))
2013-05-30 20:25:42 +00:00
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self))
2013-05-02 15:53:54 +00:00
def comboBoxProxyTypeChanged(self, comboBoxIndex):
"""TBC"""
2013-05-02 15:53:54 +00:00
if comboBoxIndex == 0:
self.ui.lineEditSocksHostname.setEnabled(False)
self.ui.lineEditSocksPort.setEnabled(False)
self.ui.lineEditSocksUsername.setEnabled(False)
self.ui.lineEditSocksPassword.setEnabled(False)
self.ui.checkBoxAuthentication.setEnabled(False)
self.ui.checkBoxSocksListen.setEnabled(False)
2013-05-02 15:53:54 +00:00
elif comboBoxIndex == 1 or comboBoxIndex == 2:
self.ui.lineEditSocksHostname.setEnabled(True)
self.ui.lineEditSocksPort.setEnabled(True)
self.ui.checkBoxAuthentication.setEnabled(True)
self.ui.checkBoxSocksListen.setEnabled(True)
2013-05-02 15:53:54 +00:00
if self.ui.checkBoxAuthentication.isChecked():
self.ui.lineEditSocksUsername.setEnabled(True)
self.ui.lineEditSocksPassword.setEnabled(True)
def getNamecoinType(self):
"""Check status of namecoin integration radio buttons and translate it to a string as in the options."""
if self.ui.radioButtonNamecoinNamecoind.isChecked():
return "namecoind"
elif self.ui.radioButtonNamecoinNmcontrol.isChecked():
return "nmcontrol"
logger.info("Neither namecoind nor nmcontrol were checked. This is a fatal error")
sys.exit(1)
def namecoinTypeChanged(self, checked):
"""Namecoin connection type was changed."""
nmctype = self.getNamecoinType()
assert nmctype == "namecoind" or nmctype == "nmcontrol"
isNamecoind = (nmctype == "namecoind")
self.ui.lineEditNamecoinUser.setEnabled(isNamecoind)
self.ui.labelNamecoinUser.setEnabled(isNamecoind)
self.ui.lineEditNamecoinPassword.setEnabled(isNamecoind)
self.ui.labelNamecoinPassword.setEnabled(isNamecoind)
if isNamecoind:
self.ui.lineEditNamecoinPort.setText(defaults.namecoinDefaultRpcPort)
else:
self.ui.lineEditNamecoinPort.setText("9000")
def click_pushButtonNamecoinTest(self):
"""Test the namecoin settings specified in the settings dialog."""
self.ui.labelNamecoinTestResult.setText(_translate(
"MainWindow", "Testing..."))
options = {}
options["type"] = self.getNamecoinType()
options["host"] = str(self.ui.lineEditNamecoinHost.text().toUtf8())
options["port"] = str(self.ui.lineEditNamecoinPort.text().toUtf8())
options["user"] = str(self.ui.lineEditNamecoinUser.text().toUtf8())
options["password"] = str(self.ui.lineEditNamecoinPassword.text().toUtf8())
nc = namecoinConnection(options)
2013-08-14 23:46:59 +00:00
response = nc.test()
responseStatus = response[0]
responseText = response[1]
self.ui.labelNamecoinTestResult.setText(responseText)
if responseStatus == 'success':
2015-03-21 10:37:08 +00:00
self.parent.ui.pushButtonFetchNamecoinID.show()
class myTableWidgetItem(QtGui.QTableWidgetItem):
"""
In order for the time columns on the Inbox and Sent tabs to be sorted correctly (rather than alphabetically),
we need to overload the < operator and use this class instead of QTableWidgetItem.
"""
def __lt__(self, other):
2013-05-02 15:53:54 +00:00
return int(self.data(33).toPyObject()) < int(other.data(33).toPyObject())
app = None
myapp = None
class MySingleApplication(QtGui.QApplication):
"""
Listener to allow our Qt form to get focus when another instance of the
application is open.
Based off this nice reimplmentation of MySingleApplication:
http://stackoverflow.com/a/12712362/2679626
"""
# Unique identifier for this application
uuid = '6ec0149b-96e1-4be1-93ab-1465fb3ebf7c'
def __init__(self, *argv):
"""TBC"""
super(MySingleApplication, self).__init__(*argv)
_id = MySingleApplication.uuid
self.server = None
self.is_running = False
socket = QLocalSocket()
socket.connectToServer(_id)
self.is_running = socket.waitForConnected()
# Cleanup past crashed servers
if not self.is_running:
if socket.error() == QLocalSocket.ConnectionRefusedError:
socket.disconnectFromServer()
QLocalServer.removeServer(_id)
socket.abort()
# Checks if there's an instance of the local server id running
if self.is_running:
# This should be ignored, singleinstance.py will take care of exiting me.
pass
else:
# Nope, create a local server with this id and assign on_new_connection
# for whenever a second instance tries to run focus the application.
self.server = QLocalServer()
self.server.listen(_id)
self.server.newConnection.connect(self.on_new_connection)
def __del__(self):
"""TBC"""
if self.server:
self.server.close()
def on_new_connection(self):
"""TBC"""
if myapp:
myapp.appIndicatorShow()
def init():
"""TBC"""
global app
if not app:
app = MySingleApplication(sys.argv)
return app
2013-05-02 15:53:54 +00:00
def run():
"""Run the gui"""
global myapp
running_app = init()
change_translation(l10n.getTranslationLanguage())
2013-05-02 15:53:54 +00:00
app.setStyleSheet("QStatusBar::item { border: 0px solid black }")
myapp = MyForm()
myapp.sqlInit()
myapp.appIndicatorInit(running_app)
myapp.indicatorInit()
myapp.notifierInit()
myapp._firstrun = BMConfigParser().safeGetBoolean(
'bitmessagesettings', 'dontconnect')
if myapp._firstrun:
myapp.showConnectDialog() # ask the user if we may connect
myapp.ui.updateNetworkSwitchMenuLabel()
# only show after wizards and connect dialogs have completed
if not BMConfigParser().getboolean('bitmessagesettings', 'startintray'):
myapp.show()
sys.exit(app.exec_())