diff --git a/.gitignore b/.gitignore
index 8e9f9031..b0bf5ae4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,5 @@ src/build
src/dist
src/.project
src/.pydevproject
-src/.settings/
\ No newline at end of file
+src/.settings/
+*.dll
\ No newline at end of file
diff --git a/README.md b/README.md
index 7a161d04..31db438d 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,14 @@ pseudo-mailing list:
BM-2D9QKN4teYRvoq2fyzpiftPh9WP9qggtzh
+This fork
+---------
+
+The purpose of this fork is to add features for server deployment for a
+bitmessage/email gateway. It contains merged support for OpenCL PoW and a
+couple of new/modified API calls.
+
+
References
----------
* [Project Website](https://bitmessage.org)
diff --git a/ebuildpackage/pybitmessage-0.3.5-1.ebuild b/ebuildpackage/pybitmessage-0.3.5-1.ebuild
deleted file mode 100755
index 01eddc4f..00000000
--- a/ebuildpackage/pybitmessage-0.3.5-1.ebuild
+++ /dev/null
@@ -1,32 +0,0 @@
-# $Header: $
-
-EAPI=5
-
-inherit git-2 python-r1
-
-PYTHON_COMPAT=( python2_7 )
-PYTHON_REQ_USE="sqlite"
-REQUIRED_USE="${PYTHON_REQUIRED_USE}"
-DESCRIPTION="Bitmessage is a P2P communications protocol used to send encrypted messages to another person or to many subscribers. It is decentralized and trustless, meaning that you need-not inherently trust any entities like root certificate authorities. It uses strong authentication which means that the sender of a message cannot be spoofed, and it aims to hide "non-content" data, like the sender and receiver of messages, from passive eavesdroppers like those running warrantless wiretapping programs."
-HOMEPAGE="https://github.com/Bitmessage/PyBitmessage"
-EGIT_REPO_URI="https://github.com/Bitmessage/PyBitmessage.git"
-LICENSE="MIT"
-SLOT="0"
-KEYWORDS="x86"
-DEPEND="dev-libs/popt
- ${PYTHON_DEPS}"
-RDEPEND="${DEPEND}
- dev-libs/openssl
- dev-python/PyQt4[]"
-
-src_configure() {
- econf --with-popt
-}
-
-src_compile() { :; }
-
-src_install() {
- emake DESTDIR="${D}" PREFIX="/usr" install
- # Install README and (Debian) changelog
- dodoc README.md debian/changelog
-}
diff --git a/osx.sh b/osx.sh
index eaa33183..e58a49f4 100755
--- a/osx.sh
+++ b/osx.sh
@@ -14,6 +14,8 @@ fi
echo "Creating OS X packages for Bitmessage."
+export PYBITMESSAGEVERSION=$1
+
cd src && python2.7 build_osx.py py2app
if [[ $? = "0" ]]; then
diff --git a/src/addresses.py b/src/addresses.py
index f6fbbf73..017eaa82 100644
--- a/src/addresses.py
+++ b/src/addresses.py
@@ -55,7 +55,7 @@ def decodeBase58(string, alphabet=ALPHABET):
def encodeVarint(integer):
if integer < 0:
- print 'varint cannot be < 0'
+ logger.error('varint cannot be < 0')
raise SystemExit
if integer < 253:
return pack('>B',integer)
@@ -66,7 +66,7 @@ def encodeVarint(integer):
if integer >= 4294967296 and integer < 18446744073709551616:
return pack('>B',255) + pack('>Q',integer)
if integer >= 18446744073709551616:
- print 'varint cannot be >= 18446744073709551616'
+ logger.error('varint cannot be >= 18446744073709551616')
raise SystemExit
class varintDecodeError(Exception):
@@ -185,25 +185,25 @@ def decodeAddress(address):
try:
addressVersionNumber, bytesUsedByVersionNumber = decodeVarint(data[:9])
except varintDecodeError as e:
- print e
+ logger.error(str(e))
status = 'varintmalformed'
return status,0,0,""
#print 'addressVersionNumber', addressVersionNumber
#print 'bytesUsedByVersionNumber', bytesUsedByVersionNumber
if addressVersionNumber > 4:
- print 'cannot decode address version numbers this high'
+ logger.error('cannot decode address version numbers this high')
status = 'versiontoohigh'
return status,0,0,""
elif addressVersionNumber == 0:
- print 'cannot decode address version numbers of zero.'
+ logger.error('cannot decode address version numbers of zero.')
status = 'versiontoohigh'
return status,0,0,""
try:
streamNumber, bytesUsedByStreamNumber = decodeVarint(data[bytesUsedByVersionNumber:])
except varintDecodeError as e:
- print e
+ logger.error(str(e))
status = 'varintmalformed'
return status,0,0,""
#print streamNumber
diff --git a/src/api.py b/src/api.py
index f142953b..7c355941 100644
--- a/src/api.py
+++ b/src/api.py
@@ -12,7 +12,7 @@ if __name__ == "__main__":
import sys
sys.exit(0)
-from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
+from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
import json
import shared
@@ -26,7 +26,7 @@ from pyelliptic.openssl import OpenSSL
from struct import pack
# Classes
-from helper_sql import sqlQuery,sqlExecute,SqlBulkExecute
+from helper_sql import sqlQuery,sqlExecute,SqlBulkExecute,sqlStoredProcedure
from debug import logger
# Helper Functions
@@ -43,6 +43,13 @@ class APIError(Exception):
def __str__(self):
return "API Error %04i: %s" % (self.error_number, self.error_message)
+
+class StoppableXMLRPCServer(SimpleXMLRPCServer):
+ def serve_forever(self):
+ while shared.shutdown == 0:
+ self.handle_request()
+
+
# This is one of several classes that constitute the API
# This class was written by Vaibhav Bhatia. Modified by Jonathan Warren (Atheros).
# http://code.activestate.com/recipes/501148-xmlrpc-serverclient-which-does-cookie-handling-and/
@@ -174,7 +181,14 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
return data
def HandleListAddressBookEntries(self, params):
- queryreturn = sqlQuery('''SELECT label, address from addressbook''')
+ if len(params) == 1:
+ label, = params
+ label = self._decode(label, "base64")
+ queryreturn = sqlQuery('''SELECT label, address from addressbook WHERE label = ?''', label)
+ elif len(params) > 1:
+ raise APIError(0, "Too many paremeters, max 1")
+ else:
+ queryreturn = sqlQuery('''SELECT label, address from addressbook''')
data = '{"addresses":['
for row in queryreturn:
label, address = row
@@ -956,6 +970,9 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
message, = params
shared.UISignalQueue.put(('updateStatusBar', message))
+ def HandleDeleteAndVacuum(self, params):
+ sqlStoredProcedure('deleteandvacuume')
+ return 'done'
handlers = {}
handlers['helloWorld'] = HandleHelloWorld
@@ -1006,6 +1023,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
handlers['getMessageDataByDestinationTag'] = HandleGetMessageDataByDestinationHash
handlers['clientStatus'] = HandleClientStatus
handlers['decodeAddress'] = HandleDecodeAddress
+ handlers['deleteAndVacuum'] = HandleDeleteAndVacuum
def _handle_request(self, method, params):
if (self.handlers.has_key(method)):
diff --git a/src/bitmessagecli.py b/src/bitmessagecli.py
new file mode 100644
index 00000000..87d71f05
--- /dev/null
+++ b/src/bitmessagecli.py
@@ -0,0 +1,1778 @@
+#!/usr/bin/env python2.7.x
+# Created by Adam Melton (.dok) referenceing https://bitmessage.org/wiki/API_Reference for API documentation
+# Distributed under the MIT/X11 software license. See http://www.opensource.org/licenses/mit-license.php.
+
+# This is an example of a daemon client for PyBitmessage 0.4.2, by .dok (Version 0.3.0)
+
+
+import ConfigParser
+import xmlrpclib
+import datetime
+import hashlib
+import getopt
+import imghdr
+import ntpath
+import json
+import time
+import sys
+import os
+
+api = ''
+keysName = 'keys.dat'
+keysPath = 'keys.dat'
+usrPrompt = 0 #0 = First Start, 1 = prompt, 2 = no prompt if the program is starting up
+knownAddresses = dict()
+
+def userInput(message): #Checks input for exit or quit. Also formats for input, etc
+ global usrPrompt
+ print '\n' + message
+ uInput = raw_input('> ')
+
+ if (uInput.lower() == 'exit'): #Returns the user to the main menu
+ usrPrompt = 1
+ main()
+
+ elif (uInput.lower() == 'quit'): #Quits the program
+ print '\n Bye\n'
+ sys.exit()
+ os.exit()
+ else:
+ return uInput
+
+def restartBmNotify(): #Prompts the user to restart Bitmessage.
+ print '\n *******************************************************************'
+ print ' WARNING: If Bitmessage is running locally, you must restart it now.'
+ print ' *******************************************************************\n'
+
+def safeConfigGetBoolean(section,field):
+ global keysPath
+ config = ConfigParser.SafeConfigParser()
+ config.read(keysPath)
+
+ try:
+ return config.getboolean(section,field)
+ except:
+ return False
+
+#Begin keys.dat interactions
+def lookupAppdataFolder(): #gets the appropriate folders for the .dat files depending on the OS. Taken from bitmessagemain.py
+ APPNAME = "PyBitmessage"
+ from os import path, environ
+ if sys.platform == 'darwin':
+ if "HOME" in environ:
+ dataFolder = path.join(os.environ["HOME"], "Library/Application support/", APPNAME) + '/'
+ else:
+ print ' Could not find home folder, please report this message and your OS X version to the Daemon Github.'
+ os.exit()
+
+ elif 'win32' in sys.platform or 'win64' in sys.platform:
+ dataFolder = path.join(environ['APPDATA'], APPNAME) + '\\'
+ else:
+ dataFolder = path.expanduser(path.join("~", ".config/" + APPNAME + "/"))
+ return dataFolder
+
+def configInit():
+ global keysName
+ config = ConfigParser.SafeConfigParser()
+
+ config.add_section('bitmessagesettings')
+ config.set('bitmessagesettings', 'port', '8444') #Sets the bitmessage port to stop the warning about the api not properly being setup. This is in the event that the keys.dat is in a different directory or is created locally to connect to a machine remotely.
+ config.set('bitmessagesettings','apienabled','true') #Sets apienabled to true in keys.dat
+
+ with open(keysName, 'wb') as configfile:
+ config.write(configfile)
+
+ print '\n ' + str(keysName) + ' Initalized in the same directory as daemon.py'
+ print ' You will now need to configure the ' + str(keysName) + ' file.\n'
+
+def apiInit(apiEnabled):
+ global keysPath
+ global usrPrompt
+ config = ConfigParser.SafeConfigParser()
+ config.read(keysPath)
+
+
+
+ if (apiEnabled == False): #API information there but the api is disabled.
+ uInput = userInput("The API is not enabled. Would you like to do that now, (Y)es or (N)o?").lower()
+
+ if uInput == "y": #
+ config.set('bitmessagesettings','apienabled','true') #Sets apienabled to true in keys.dat
+ with open(keysPath, 'wb') as configfile:
+ config.write(configfile)
+
+ print 'Done'
+ restartBmNotify()
+ return True
+
+ elif uInput == "n":
+ print ' \n************************************************************'
+ print ' Daemon will not work when the API is disabled. '
+ print ' Please refer to the Bitmessage Wiki on how to setup the API.'
+ print ' ************************************************************\n'
+ usrPrompt = 1
+ main()
+
+ else:
+ print '\n Invalid Entry\n'
+ usrPrompt = 1
+ main()
+ elif (apiEnabled == True): #API correctly setup
+ #Everything is as it should be
+ return True
+
+ else: #API information was not present.
+ print '\n ' + str(keysPath) + ' not properly configured!\n'
+ uInput = userInput("Would you like to do this now, (Y)es or (N)o?").lower()
+
+ if uInput == "y": #User said yes, initalize the api by writing these values to the keys.dat file
+ print ' '
+
+ apiUsr = userInput("API Username")
+ apiPwd = userInput("API Password")
+ apiInterface = userInput("API Interface. (127.0.0.1)")
+ apiPort = userInput("API Port")
+ apiEnabled = userInput("API Enabled? (True) or (False)").lower()
+ daemon = userInput("Daemon mode Enabled? (True) or (False)").lower()
+
+ if (daemon != 'true' and daemon != 'false'):
+ print '\n Invalid Entry for Daemon.\n'
+ uInput = 1
+ main()
+
+ print ' -----------------------------------\n'
+
+ config.set('bitmessagesettings', 'port', '8444') #sets the bitmessage port to stop the warning about the api not properly being setup. This is in the event that the keys.dat is in a different directory or is created locally to connect to a machine remotely.
+ config.set('bitmessagesettings','apienabled','true')
+ config.set('bitmessagesettings', 'apiport', apiPort)
+ config.set('bitmessagesettings', 'apiinterface', '127.0.0.1')
+ config.set('bitmessagesettings', 'apiusername', apiUsr)
+ config.set('bitmessagesettings', 'apipassword', apiPwd)
+ config.set('bitmessagesettings', 'daemon', daemon)
+ with open(keysPath, 'wb') as configfile:
+ config.write(configfile)
+
+ print '\n Finished configuring the keys.dat file with API information.\n'
+ restartBmNotify()
+ return True
+
+ elif uInput == "n":
+ print '\n ***********************************************************'
+ print ' Please refer to the Bitmessage Wiki on how to setup the API.'
+ print ' ***********************************************************\n'
+ usrPrompt = 1
+ main()
+ else:
+ print ' \nInvalid entry\n'
+ usrPrompt = 1
+ main()
+
+
+def apiData():
+ global keysName
+ global keysPath
+ global usrPrompt
+
+ config = ConfigParser.SafeConfigParser()
+ config.read(keysPath) #First try to load the config file (the keys.dat file) from the program directory
+
+ try:
+ config.get('bitmessagesettings','port')
+ appDataFolder = ''
+ except:
+ #Could not load the keys.dat file in the program directory. Perhaps it is in the appdata directory.
+ appDataFolder = lookupAppdataFolder()
+ keysPath = appDataFolder + keysPath
+ config = ConfigParser.SafeConfigParser()
+ config.read(keysPath)
+
+ try:
+ config.get('bitmessagesettings','port')
+ except:
+ #keys.dat was not there either, something is wrong.
+ print '\n ******************************************************************'
+ print ' There was a problem trying to access the Bitmessage keys.dat file'
+ print ' or keys.dat is not set up correctly'
+ print ' Make sure that daemon is in the same directory as Bitmessage. '
+ print ' ******************************************************************\n'
+
+ uInput = userInput("Would you like to create a keys.dat in the local directory, (Y)es or (N)o?").lower()
+
+ if (uInput == "y" or uInput == "yes"):
+ configInit()
+ keysPath = keysName
+ usrPrompt = 0
+ main()
+ elif (uInput == "n" or uInput == "no"):
+ print '\n Trying Again.\n'
+ usrPrompt = 0
+ main()
+ else:
+ print '\n Invalid Input.\n'
+
+ usrPrompt = 1
+ main()
+
+ try: #checks to make sure that everyting is configured correctly. Excluding apiEnabled, it is checked after
+ config.get('bitmessagesettings', 'apiport')
+ config.get('bitmessagesettings', 'apiinterface')
+ config.get('bitmessagesettings', 'apiusername')
+ config.get('bitmessagesettings', 'apipassword')
+ except:
+ apiInit("") #Initalize the keys.dat file with API information
+
+ #keys.dat file was found or appropriately configured, allow information retrieval
+ apiEnabled = apiInit(safeConfigGetBoolean('bitmessagesettings','apienabled')) #if false it will prompt the user, if true it will return true
+
+ config.read(keysPath)#read again since changes have been made
+ apiPort = int(config.get('bitmessagesettings', 'apiport'))
+ apiInterface = config.get('bitmessagesettings', 'apiinterface')
+ apiUsername = config.get('bitmessagesettings', 'apiusername')
+ apiPassword = config.get('bitmessagesettings', 'apipassword')
+
+ print '\n API data successfully imported.\n'
+
+ return "http://" + apiUsername + ":" + apiPassword + "@" + apiInterface+ ":" + str(apiPort) + "/" #Build the api credentials
+
+#End keys.dat interactions
+
+
+def apiTest(): #Tests the API connection to bitmessage. Returns true if it is connected.
+
+ try:
+ result = api.add(2,3)
+ except:
+ return False
+
+ if (result == 5):
+ return True
+ else:
+ return False
+
+def bmSettings(): #Allows the viewing and modification of keys.dat settings.
+ global keysPath
+ global usrPrompt
+ config = ConfigParser.SafeConfigParser()
+ keysPath = 'keys.dat'
+
+ config.read(keysPath)#Read the keys.dat
+ try:
+ port = config.get('bitmessagesettings', 'port')
+ except:
+ print '\n File not found.\n'
+ usrPrompt = 0
+ main()
+
+ startonlogon = safeConfigGetBoolean('bitmessagesettings', 'startonlogon')
+ minimizetotray = safeConfigGetBoolean('bitmessagesettings', 'minimizetotray')
+ showtraynotifications = safeConfigGetBoolean('bitmessagesettings', 'showtraynotifications')
+ startintray = safeConfigGetBoolean('bitmessagesettings', 'startintray')
+ defaultnoncetrialsperbyte = config.get('bitmessagesettings', 'defaultnoncetrialsperbyte')
+ defaultpayloadlengthextrabytes = config.get('bitmessagesettings', 'defaultpayloadlengthextrabytes')
+ daemon = safeConfigGetBoolean('bitmessagesettings', 'daemon')
+
+ socksproxytype = config.get('bitmessagesettings', 'socksproxytype')
+ sockshostname = config.get('bitmessagesettings', 'sockshostname')
+ socksport = config.get('bitmessagesettings', 'socksport')
+ socksauthentication = safeConfigGetBoolean('bitmessagesettings', 'socksauthentication')
+ socksusername = config.get('bitmessagesettings', 'socksusername')
+ sockspassword = config.get('bitmessagesettings', 'sockspassword')
+
+
+ print '\n -----------------------------------'
+ print ' | Current Bitmessage Settings |'
+ print ' -----------------------------------'
+ print ' port = ' + port
+ print ' startonlogon = ' + str(startonlogon)
+ print ' minimizetotray = ' + str(minimizetotray)
+ print ' showtraynotifications = ' + str(showtraynotifications)
+ print ' startintray = ' + str(startintray)
+ print ' defaultnoncetrialsperbyte = ' + defaultnoncetrialsperbyte
+ print ' defaultpayloadlengthextrabytes = ' + defaultpayloadlengthextrabytes
+ print ' daemon = ' + str(daemon)
+ print '\n ------------------------------------'
+ print ' | Current Connection Settings |'
+ print ' -----------------------------------'
+ print ' socksproxytype = ' + socksproxytype
+ print ' sockshostname = ' + sockshostname
+ print ' socksport = ' + socksport
+ print ' socksauthentication = ' + str(socksauthentication)
+ print ' socksusername = ' + socksusername
+ print ' sockspassword = ' + sockspassword
+ print ' '
+
+ uInput = userInput("Would you like to modify any of these settings, (Y)es or (N)o?").lower()
+
+ if uInput == "y":
+ while True: #loops if they mistype the setting name, they can exit the loop with 'exit'
+ invalidInput = False
+ uInput = userInput("What setting would you like to modify?").lower()
+ print ' '
+
+ if uInput == "port":
+ print ' Current port number: ' + port
+ uInput = userInput("Enter the new port number.")
+ config.set('bitmessagesettings', 'port', str(uInput))
+ elif uInput == "startonlogon":
+ print ' Current status: ' + str(startonlogon)
+ uInput = userInput("Enter the new status.")
+ config.set('bitmessagesettings', 'startonlogon', str(uInput))
+ elif uInput == "minimizetotray":
+ print ' Current status: ' + str(minimizetotray)
+ uInput = userInput("Enter the new status.")
+ config.set('bitmessagesettings', 'minimizetotray', str(uInput))
+ elif uInput == "showtraynotifications":
+ print ' Current status: ' + str(showtraynotifications)
+ uInput = userInput("Enter the new status.")
+ config.set('bitmessagesettings', 'showtraynotifications', str(uInput))
+ elif uInput == "startintray":
+ print ' Current status: ' + str(startintray)
+ uInput = userInput("Enter the new status.")
+ config.set('bitmessagesettings', 'startintray', str(uInput))
+ elif uInput == "defaultnoncetrialsperbyte":
+ print ' Current default nonce trials per byte: ' + defaultnoncetrialsperbyte
+ uInput = userInput("Enter the new defaultnoncetrialsperbyte.")
+ config.set('bitmessagesettings', 'defaultnoncetrialsperbyte', str(uInput))
+ elif uInput == "defaultpayloadlengthextrabytes":
+ print ' Current default payload length extra bytes: ' + defaultpayloadlengthextrabytes
+ uInput = userInput("Enter the new defaultpayloadlengthextrabytes.")
+ config.set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(uInput))
+ elif uInput == "daemon":
+ print ' Current status: ' + str(daemon)
+ uInput = userInput("Enter the new status.").lower()
+ config.set('bitmessagesettings', 'daemon', str(uInput))
+ elif uInput == "socksproxytype":
+ print ' Current socks proxy type: ' + socksproxytype
+ print "Possibilities: 'none', 'SOCKS4a', 'SOCKS5'."
+ uInput = userInput("Enter the new socksproxytype.")
+ config.set('bitmessagesettings', 'socksproxytype', str(uInput))
+ elif uInput == "sockshostname":
+ print ' Current socks host name: ' + sockshostname
+ uInput = userInput("Enter the new sockshostname.")
+ config.set('bitmessagesettings', 'sockshostname', str(uInput))
+ elif uInput == "socksport":
+ print ' Current socks port number: ' + socksport
+ uInput = userInput("Enter the new socksport.")
+ config.set('bitmessagesettings', 'socksport', str(uInput))
+ elif uInput == "socksauthentication":
+ print ' Current status: ' + str(socksauthentication)
+ uInput = userInput("Enter the new status.")
+ config.set('bitmessagesettings', 'socksauthentication', str(uInput))
+ elif uInput == "socksusername":
+ print ' Current socks username: ' + socksusername
+ uInput = userInput("Enter the new socksusername.")
+ config.set('bitmessagesettings', 'socksusername', str(uInput))
+ elif uInput == "sockspassword":
+ print ' Current socks password: ' + sockspassword
+ uInput = userInput("Enter the new password.")
+ config.set('bitmessagesettings', 'sockspassword', str(uInput))
+ else:
+ print "\n Invalid input. Please try again.\n"
+ invalidInput = True
+
+ if invalidInput != True: #don't prompt if they made a mistake.
+ uInput = userInput("Would you like to change another setting, (Y)es or (N)o?").lower()
+
+ if uInput != "y":
+ print '\n Changes Made.\n'
+ with open(keysPath, 'wb') as configfile:
+ config.write(configfile)
+ restartBmNotify()
+ break
+
+
+ elif uInput == "n":
+ usrPrompt = 1
+ main()
+ else:
+ print "Invalid input."
+ usrPrompt = 1
+ main()
+
+def validAddress(address):
+ address_information = api.decodeAddress(address)
+ address_information = eval(address_information)
+
+ if 'success' in str(address_information.get('status')).lower():
+ return True
+ else:
+ return False
+
+def getAddress(passphrase,vNumber,sNumber):
+ passphrase = passphrase.encode('base64')#passphrase must be encoded
+
+ return api.getDeterministicAddress(passphrase,vNumber,sNumber)
+
+def subscribe():
+ global usrPrompt
+
+ while True:
+ address = userInput("What address would you like to subscribe to?")
+
+ if (address == "c"):
+ usrPrompt = 1
+ print ' '
+ main()
+ elif (validAddress(address)== False):
+ print '\n Invalid. "c" to cancel. Please try again.\n'
+ else:
+ break
+
+ label = userInput("Enter a label for this address.")
+ label = label.encode('base64')
+
+ api.addSubscription(address,label)
+ print ('\n You are now subscribed to: ' + address + '\n')
+
+def unsubscribe():
+ global usrPrompt
+
+ while True:
+ address = userInput("What address would you like to unsubscribe from?")
+
+ if (address == "c"):
+ usrPrompt = 1
+ print ' '
+ main()
+ elif (validAddress(address)== False):
+ print '\n Invalid. "c" to cancel. Please try again.\n'
+ else:
+ break
+
+
+ uInput = userInput("Are you sure, (Y)es or (N)o?").lower()
+
+ api.deleteSubscription(address)
+ print ('\n You are now unsubscribed from: ' + address + '\n')
+
+def listSubscriptions():
+ global usrPrompt
+ #jsonAddresses = json.loads(api.listSubscriptions())
+ #numAddresses = len(jsonAddresses['addresses']) #Number of addresses
+ print '\nLabel, Address, Enabled\n'
+ try:
+ print api.listSubscriptions()
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+ '''for addNum in range (0, numAddresses): #processes all of the addresses and lists them out
+ label = jsonAddresses['addresses'][addNum]['label']
+ address = jsonAddresses['addresses'][addNum]['address']
+ enabled = jsonAddresses['addresses'][addNum]['enabled']
+
+ print label, address, enabled
+ '''
+ print ' '
+
+def createChan():
+ global usrPrompt
+ password = userInput("Enter channel name")
+ password = password.encode('base64')
+ try:
+ print api.createChan(password)
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+
+def joinChan():
+ global usrPrompt
+ while True:
+ address = userInput("Enter channel address")
+
+ if (address == "c"):
+ usrPrompt = 1
+ print ' '
+ main()
+ elif (validAddress(address)== False):
+ print '\n Invalid. "c" to cancel. Please try again.\n'
+ else:
+ break
+
+ password = userInput("Enter channel name")
+ password = password.encode('base64')
+ try:
+ print api.joinChan(password,address)
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+def leaveChan():
+ global usrPrompt
+ while True:
+ address = userInput("Enter channel address")
+
+ if (address == "c"):
+ usrPrompt = 1
+ print ' '
+ main()
+ elif (validAddress(address)== False):
+ print '\n Invalid. "c" to cancel. Please try again.\n'
+ else:
+ break
+
+ try:
+ print api.leaveChan(address)
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+
+def listAdd(): #Lists all of the addresses and their info
+ global usrPrompt
+ try:
+ jsonAddresses = json.loads(api.listAddresses())
+ numAddresses = len(jsonAddresses['addresses']) #Number of addresses
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+ #print '\nAddress Number,Label,Address,Stream,Enabled\n'
+ print '\n --------------------------------------------------------------------------'
+ print ' | # | Label | Address |S#|Enabled|'
+ print ' |---|-------------------|-------------------------------------|--|-------|'
+ for addNum in range (0, numAddresses): #processes all of the addresses and lists them out
+ label = str(jsonAddresses['addresses'][addNum]['label'])
+ address = str(jsonAddresses['addresses'][addNum]['address'])
+ stream = str(jsonAddresses['addresses'][addNum]['stream'])
+ enabled = str(jsonAddresses['addresses'][addNum]['enabled'])
+
+ if (len(label) > 19):
+ label = label[:16] + '...'
+
+ print ' |' + str(addNum).ljust(3) + '|' + label.ljust(19) + '|' + address.ljust(37) + '|' + stream.ljust(1), '|' + enabled.ljust(7) + '|'
+
+ print ' --------------------------------------------------------------------------\n'
+
+def genAdd(lbl,deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe): #Generate address
+ global usrPrompt
+ if deterministic == False: #Generates a new address with the user defined label. non-deterministic
+ addressLabel = lbl.encode('base64')
+ try:
+ generatedAddress = api.createRandomAddress(addressLabel)
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+ return generatedAddress
+
+ elif deterministic == True: #Generates a new deterministic address with the user inputs.
+ passphrase = passphrase.encode('base64')
+ try:
+ generatedAddress = api.createDeterministicAddresses(passphrase, numOfAdd, addVNum, streamNum, ripe)
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+ return generatedAddress
+ else:
+ return 'Entry Error'
+
+def delMilAddr(): #Generate address
+ global usrPrompt
+ try:
+ response = api.listAddresses2()
+ # if api is too old just return then fail
+ if "API Error 0020" in response: return
+ addresses = json.loads(response)
+ for entry in addresses['addresses']:
+ if entry['label'].decode('base64')[:6] == "random":
+ api.deleteAddress(entry['address'])
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+def genMilAddr(): #Generate address
+ global usrPrompt
+ maxn = 0
+ try:
+ response = api.listAddresses2()
+ if "API Error 0020" in response: return
+ addresses = json.loads(response)
+ for entry in addresses['addresses']:
+ if entry['label'].decode('base64')[:6] == "random":
+ newn = int(entry['label'].decode('base64')[6:])
+ if maxn < newn:
+ maxn = newn
+ except:
+ print "\n Some error\n"
+ print "\n Starting at " + str(maxn) + "\n"
+ for i in range(maxn, 10000):
+ lbl = "random" + str(i)
+ addressLabel = lbl.encode('base64')
+ try:
+ generatedAddress = api.createRandomAddress(addressLabel)
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+def saveFile(fileName, fileData): #Allows attachments and messages/broadcats to be saved
+
+ #This section finds all invalid characters and replaces them with ~
+ fileName = fileName.replace(" ", "")
+ fileName = fileName.replace("/", "~")
+ #fileName = fileName.replace("\\", "~") How do I get this to work...?
+ fileName = fileName.replace(":", "~")
+ fileName = fileName.replace("*", "~")
+ fileName = fileName.replace("?", "~")
+ fileName = fileName.replace('"', "~")
+ fileName = fileName.replace("<", "~")
+ fileName = fileName.replace(">", "~")
+ fileName = fileName.replace("|", "~")
+
+ directory = 'attachments'
+
+ if not os.path.exists(directory):
+ os.makedirs(directory)
+
+ filePath = directory +'/'+ fileName
+
+ '''try: #Checks if file already exists
+ with open(filePath):
+ print 'File Already Exists'
+ return
+ except IOError: pass'''
+
+
+ f = open(filePath, 'wb+') #Begin saving to file
+ f.write(fileData.decode("base64"))
+ f.close
+
+ print '\n Successfully saved '+ filePath + '\n'
+
+def attachment(): #Allows users to attach a file to their message or broadcast
+ theAttachmentS = ''
+
+ while True:
+
+ isImage = False
+ theAttachment = ''
+
+ while True:#loops until valid path is entered
+ filePath = userInput('\nPlease enter the path to the attachment or just the attachment name if in this folder.')
+
+ try:
+ with open(filePath): break
+ except IOError:
+ print '\n %s was not found on your filesystem or can not be opened.\n' % filePath
+ pass
+
+ #print filesize, and encoding estimate with confirmation if file is over X size (1mb?)
+ invSize = os.path.getsize(filePath)
+ invSize = (invSize / 1024) #Converts to kilobytes
+ round(invSize,2) #Rounds to two decimal places
+
+ if (invSize > 500.0):#If over 500KB
+ print '\n WARNING:The file that you are trying to attach is ', invSize, 'KB and will take considerable time to send.\n'
+ uInput = userInput('Are you sure you still want to attach it, (Y)es or (N)o?').lower()
+
+ if uInput != "y":
+ print '\n Attachment discarded.\n'
+ return ''
+ elif (invSize > 184320.0): #If larger than 180MB, discard.
+ print '\n Attachment too big, maximum allowed size:180MB\n'
+ main()
+
+ pathLen = len(str(ntpath.basename(filePath))) #Gets the length of the filepath excluding the filename
+ fileName = filePath[(len(str(filePath)) - pathLen):] #reads the filename
+
+ filetype = imghdr.what(filePath) #Tests if it is an image file
+ if filetype is not None:
+ print '\n ---------------------------------------------------'
+ print ' Attachment detected as an Image.'
+ print '
tags will automatically be included,'
+ print ' allowing the recipient to view the image'
+ print ' using the "View HTML code..." option in Bitmessage.'
+ print ' ---------------------------------------------------\n'
+ isImage = True
+ time.sleep(2)
+
+ print '\n Encoding Attachment, Please Wait ...\n' #Alert the user that the encoding process may take some time.
+
+ with open(filePath, 'rb') as f: #Begin the actual encoding
+ data = f.read(188743680) #Reads files up to 180MB, the maximum size for Bitmessage.
+ data = data.encode("base64")
+
+ if (isImage == True): #If it is an image, include image tags in the message
+ theAttachment = """
+
+
+
+Filename:%s
+Filesize:%sKB
+Encoding:base64
+
+
+
+

+
+""" % (fileName,invSize,fileName,filetype,data)
+ else: #Else it is not an image so do not include the embedded image code.
+ theAttachment = """
+
+
+
+Filename:%s
+Filesize:%sKB
+Encoding:base64
+
+""" % (fileName,invSize,fileName,fileName,data)
+
+ uInput = userInput('Would you like to add another attachment, (Y)es or (N)o?').lower()
+
+ if (uInput == 'y' or uInput == 'yes'):#Allows multiple attachments to be added to one message
+ theAttachmentS = str(theAttachmentS) + str(theAttachment)+ '\n\n'
+ elif (uInput == 'n' or uInput == 'no'):
+ break
+
+ theAttachmentS = theAttachmentS + theAttachment
+ return theAttachmentS
+
+def sendMsg(toAddress, fromAddress, subject, message): #With no arguments sent, sendMsg fills in the blanks. subject and message must be encoded before they are passed.
+ global usrPrompt
+ if (validAddress(toAddress)== False):
+ while True:
+ toAddress = userInput("What is the To Address?")
+
+ if (toAddress == "c"):
+ usrPrompt = 1
+ print ' '
+ main()
+ elif (validAddress(toAddress)== False):
+ print '\n Invalid Address. "c" to cancel. Please try again.\n'
+ else:
+ break
+
+
+ if (validAddress(fromAddress)== False):
+ try:
+ jsonAddresses = json.loads(api.listAddresses())
+ numAddresses = len(jsonAddresses['addresses']) #Number of addresses
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+ if (numAddresses > 1): #Ask what address to send from if multiple addresses
+ found = False
+ while True:
+ print ' '
+ fromAddress = userInput("Enter an Address or Address Label to send from.")
+
+ if fromAddress == "exit":
+ usrPrompt = 1
+ main()
+
+ for addNum in range (0, numAddresses): #processes all of the addresses
+ label = jsonAddresses['addresses'][addNum]['label']
+ address = jsonAddresses['addresses'][addNum]['address']
+ #stream = jsonAddresses['addresses'][addNum]['stream']
+ #enabled = jsonAddresses['addresses'][addNum]['enabled']
+ if (fromAddress == label): #address entered was a label and is found
+ fromAddress = address
+ found = True
+ break
+
+ if (found == False):
+ if(validAddress(fromAddress)== False):
+ print '\n Invalid Address. Please try again.\n'
+
+ else:
+ for addNum in range (0, numAddresses): #processes all of the addresses
+ #label = jsonAddresses['addresses'][addNum]['label']
+ address = jsonAddresses['addresses'][addNum]['address']
+ #stream = jsonAddresses['addresses'][addNum]['stream']
+ #enabled = jsonAddresses['addresses'][addNum]['enabled']
+ if (fromAddress == address): #address entered was a found in our addressbook.
+ found = True
+ break
+
+ if (found == False):
+ print '\n The address entered is not one of yours. Please try again.\n'
+
+ if (found == True):
+ break #Address was found
+
+ else: #Only one address in address book
+ print '\n Using the only address in the addressbook to send from.\n'
+ fromAddress = jsonAddresses['addresses'][0]['address']
+
+ if (subject == ''):
+ subject = userInput("Enter your Subject.")
+ subject = subject.encode('base64')
+ if (message == ''):
+ message = userInput("Enter your Message.")
+
+ uInput = userInput('Would you like to add an attachment, (Y)es or (N)o?').lower()
+ if uInput == "y":
+ message = message + '\n\n' + attachment()
+
+ message = message.encode('base64')
+
+ try:
+ ackData = api.sendMessage(toAddress, fromAddress, subject, message)
+ print '\n Message Status:', api.getStatus(ackData), '\n'
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+
+def sendBrd(fromAddress, subject, message): #sends a broadcast
+ global usrPrompt
+ if (fromAddress == ''):
+
+ try:
+ jsonAddresses = json.loads(api.listAddresses())
+ numAddresses = len(jsonAddresses['addresses']) #Number of addresses
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+ if (numAddresses > 1): #Ask what address to send from if multiple addresses
+ found = False
+ while True:
+ fromAddress = userInput("\nEnter an Address or Address Label to send from.")
+
+ if fromAddress == "exit":
+ usrPrompt = 1
+ main()
+
+ for addNum in range (0, numAddresses): #processes all of the addresses
+ label = jsonAddresses['addresses'][addNum]['label']
+ address = jsonAddresses['addresses'][addNum]['address']
+ #stream = jsonAddresses['addresses'][addNum]['stream']
+ #enabled = jsonAddresses['addresses'][addNum]['enabled']
+ if (fromAddress == label): #address entered was a label and is found
+ fromAddress = address
+ found = True
+ break
+
+ if (found == False):
+ if(validAddress(fromAddress)== False):
+ print '\n Invalid Address. Please try again.\n'
+
+ else:
+ for addNum in range (0, numAddresses): #processes all of the addresses
+ #label = jsonAddresses['addresses'][addNum]['label']
+ address = jsonAddresses['addresses'][addNum]['address']
+ #stream = jsonAddresses['addresses'][addNum]['stream']
+ #enabled = jsonAddresses['addresses'][addNum]['enabled']
+ if (fromAddress == address): #address entered was a found in our addressbook.
+ found = True
+ break
+
+ if (found == False):
+ print '\n The address entered is not one of yours. Please try again.\n'
+
+ if (found == True):
+ break #Address was found
+
+ else: #Only one address in address book
+ print '\n Using the only address in the addressbook to send from.\n'
+ fromAddress = jsonAddresses['addresses'][0]['address']
+
+ if (subject == ''):
+ subject = userInput("Enter your Subject.")
+ subject = subject.encode('base64')
+ if (message == ''):
+ message = userInput("Enter your Message.")
+
+ uInput = userInput('Would you like to add an attachment, (Y)es or (N)o?').lower()
+ if uInput == "y":
+ message = message + '\n\n' + attachment()
+
+ message = message.encode('base64')
+
+ try:
+ ackData = api.sendBroadcast(fromAddress, subject, message)
+ print '\n Message Status:', api.getStatus(ackData), '\n'
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+def inbox(unreadOnly = False): #Lists the messages by: Message Number, To Address Label, From Address Label, Subject, Received Time)
+ global usrPrompt
+ try:
+ inboxMessages = json.loads(api.getAllInboxMessages())
+ numMessages = len(inboxMessages['inboxMessages'])
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+ messagesPrinted = 0
+ messagesUnread = 0
+ for msgNum in range (0, numMessages): #processes all of the messages in the inbox
+ message = inboxMessages['inboxMessages'][msgNum]
+ # if we are displaying all messages or if this message is unread then display it
+ if not unreadOnly or not message['read']:
+ print ' -----------------------------------\n'
+ print ' Message Number:',msgNum #Message Number
+ print ' To:', getLabelForAddress(message['toAddress']) #Get the to address
+ print ' From:', getLabelForAddress(message['fromAddress']) #Get the from address
+ print ' Subject:', message['subject'].decode('base64') #Get the subject
+ print ' Received:', datetime.datetime.fromtimestamp(float(message['receivedTime'])).strftime('%Y-%m-%d %H:%M:%S')
+ messagesPrinted += 1
+ if not message['read']: messagesUnread += 1
+
+ if (messagesPrinted%20 == 0 and messagesPrinted != 0):
+ uInput = userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower()
+
+ print '\n -----------------------------------'
+ print ' There are %d unread messages of %d messages in the inbox.' % (messagesUnread, numMessages)
+ print ' -----------------------------------\n'
+
+def outbox():
+ global usrPrompt
+ try:
+ outboxMessages = json.loads(api.getAllSentMessages())
+ numMessages = len(outboxMessages['sentMessages'])
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+ for msgNum in range (0, numMessages): #processes all of the messages in the outbox
+ print '\n -----------------------------------\n'
+ print ' Message Number:',msgNum #Message Number
+ #print ' Message ID:', outboxMessages['sentMessages'][msgNum]['msgid']
+ print ' To:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['toAddress']) #Get the to address
+ print ' From:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['fromAddress']) #Get the from address
+ print ' Subject:', outboxMessages['sentMessages'][msgNum]['subject'].decode('base64') #Get the subject
+ print ' Status:', outboxMessages['sentMessages'][msgNum]['status'] #Get the subject
+
+ print ' Last Action Time:', datetime.datetime.fromtimestamp(float(outboxMessages['sentMessages'][msgNum]['lastActionTime'])).strftime('%Y-%m-%d %H:%M:%S')
+
+ if (msgNum%20 == 0 and msgNum != 0):
+ uInput = userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower()
+
+ print '\n -----------------------------------'
+ print ' There are ',numMessages,' messages in the outbox.'
+ print ' -----------------------------------\n'
+
+def readSentMsg(msgNum): #Opens a sent message for reading
+ global usrPrompt
+ try:
+ outboxMessages = json.loads(api.getAllSentMessages())
+ numMessages = len(outboxMessages['sentMessages'])
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+ print ' '
+
+ if (msgNum >= numMessages):
+ print '\n Invalid Message Number.\n'
+ main()
+
+ #Begin attachment detection
+ message = outboxMessages['sentMessages'][msgNum]['message'].decode('base64')
+
+ while True: #Allows multiple messages to be downloaded/saved
+ if (';base64,' in message): #Found this text in the message, there is probably an attachment.
+ attPos= message.index(";base64,") #Finds the attachment position
+ attEndPos = message.index("' />") #Finds the end of the attachment
+ #attLen = attEndPos - attPos #Finds the length of the message
+
+
+ if ('alt = "' in message): #We can get the filename too
+ fnPos = message.index('alt = "') #Finds position of the filename
+ fnEndPos = message.index('" src=') #Finds the end position
+ #fnLen = fnEndPos - fnPos #Finds the length of the filename
+
+ fileName = message[fnPos+7:fnEndPos]
+ else:
+ fnPos = attPos
+ fileName = 'Attachment'
+
+ uInput = userInput('\n Attachment Detected. Would you like to save the attachment, (Y)es or (N)o?').lower()
+ if (uInput == "y" or uInput == 'yes'):
+
+ attachment = message[attPos+9:attEndPos]
+ saveFile(fileName,attachment)
+
+ message = message[:fnPos] + '~~' + message[(attEndPos+4):]
+
+ else:
+ break
+
+ #End attachment Detection
+
+ print '\n To:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['toAddress']) #Get the to address
+ print ' From:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['fromAddress']) #Get the from address
+ print ' Subject:', outboxMessages['sentMessages'][msgNum]['subject'].decode('base64') #Get the subject
+ print ' Status:', outboxMessages['sentMessages'][msgNum]['status'] #Get the subject
+ print ' Last Action Time:', datetime.datetime.fromtimestamp(float(outboxMessages['sentMessages'][msgNum]['lastActionTime'])).strftime('%Y-%m-%d %H:%M:%S')
+ print ' Message:\n'
+ print message #inboxMessages['inboxMessages'][msgNum]['message'].decode('base64')
+ print ' '
+
+def readMsg(msgNum): #Opens a message for reading
+ global usrPrompt
+ try:
+ inboxMessages = json.loads(api.getAllInboxMessages())
+ numMessages = len(inboxMessages['inboxMessages'])
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+ if (msgNum >= numMessages):
+ print '\n Invalid Message Number.\n'
+ main()
+
+ #Begin attachment detection
+ message = inboxMessages['inboxMessages'][msgNum]['message'].decode('base64')
+
+ while True: #Allows multiple messages to be downloaded/saved
+ if (';base64,' in message): #Found this text in the message, there is probably an attachment.
+ attPos= message.index(";base64,") #Finds the attachment position
+ attEndPos = message.index("' />") #Finds the end of the attachment
+ #attLen = attEndPos - attPos #Finds the length of the message
+
+
+ if ('alt = "' in message): #We can get the filename too
+ fnPos = message.index('alt = "') #Finds position of the filename
+ fnEndPos = message.index('" src=') #Finds the end position
+ #fnLen = fnEndPos - fnPos #Finds the length of the filename
+
+ fileName = message[fnPos+7:fnEndPos]
+ else:
+ fnPos = attPos
+ fileName = 'Attachment'
+
+ uInput = userInput('\n Attachment Detected. Would you like to save the attachment, (Y)es or (N)o?').lower()
+ if (uInput == "y" or uInput == 'yes'):
+
+ attachment = message[attPos+9:attEndPos]
+ saveFile(fileName,attachment)
+
+ message = message[:fnPos] + '~~' + message[(attEndPos+4):]
+
+ else:
+ break
+
+ #End attachment Detection
+ print '\n To:', getLabelForAddress(inboxMessages['inboxMessages'][msgNum]['toAddress']) #Get the to address
+ print ' From:', getLabelForAddress(inboxMessages['inboxMessages'][msgNum]['fromAddress']) #Get the from address
+ print ' Subject:', inboxMessages['inboxMessages'][msgNum]['subject'].decode('base64') #Get the subject
+ print ' Received:',datetime.datetime.fromtimestamp(float(inboxMessages['inboxMessages'][msgNum]['receivedTime'])).strftime('%Y-%m-%d %H:%M:%S')
+ print ' Message:\n'
+ print message #inboxMessages['inboxMessages'][msgNum]['message'].decode('base64')
+ print ' '
+ return inboxMessages['inboxMessages'][msgNum]['msgid']
+
+def replyMsg(msgNum,forwardORreply): #Allows you to reply to the message you are currently on. Saves typing in the addresses and subject.
+ global usrPrompt
+ forwardORreply = forwardORreply.lower() #makes it lowercase
+ try:
+ inboxMessages = json.loads(api.getAllInboxMessages())
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+ fromAdd = inboxMessages['inboxMessages'][msgNum]['toAddress']#Address it was sent To, now the From address
+ message = inboxMessages['inboxMessages'][msgNum]['message'].decode('base64') #Message that you are replying too.
+
+ subject = inboxMessages['inboxMessages'][msgNum]['subject']
+ subject = subject.decode('base64')
+
+ if (forwardORreply == 'reply'):
+ toAdd = inboxMessages['inboxMessages'][msgNum]['fromAddress'] #Address it was From, now the To address
+ subject = "Re: " + subject
+
+ elif (forwardORreply == 'forward'):
+ subject = "Fwd: " + subject
+
+ while True:
+ toAdd = userInput("What is the To Address?")
+
+ if (toAdd == "c"):
+ usrPrompt = 1
+ print ' '
+ main()
+ elif (validAddress(toAdd)== False):
+ print '\n Invalid Address. "c" to cancel. Please try again.\n'
+ else:
+ break
+ else:
+ print '\n Invalid Selection. Reply or Forward only'
+ usrPrompt = 0
+ main()
+
+ subject = subject.encode('base64')
+
+ newMessage = userInput("Enter your Message.")
+
+ uInput = userInput('Would you like to add an attachment, (Y)es or (N)o?').lower()
+ if uInput == "y":
+ newMessage = newMessage + '\n\n' + attachment()
+
+ newMessage = newMessage + '\n\n------------------------------------------------------\n'
+ newMessage = newMessage + message
+ newMessage = newMessage.encode('base64')
+
+ sendMsg(toAdd, fromAdd, subject, newMessage)
+
+ main()
+
+def delMsg(msgNum): #Deletes a specified message from the inbox
+ global usrPrompt
+ try:
+ inboxMessages = json.loads(api.getAllInboxMessages())
+ msgId = inboxMessages['inboxMessages'][int(msgNum)]['msgid'] #gets the message ID via the message index number
+
+ msgAck = api.trashMessage(msgId)
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+ return msgAck
+
+def delSentMsg(msgNum): #Deletes a specified message from the outbox
+ global usrPrompt
+ try:
+ outboxMessages = json.loads(api.getAllSentMessages())
+ msgId = outboxMessages['sentMessages'][int(msgNum)]['msgid'] #gets the message ID via the message index number
+ msgAck = api.trashSentMessage(msgId)
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+ return msgAck
+
+def getLabelForAddress(address):
+ global usrPrompt
+
+ if address in knownAddresses:
+ return knownAddresses[address]
+ else:
+ buildKnownAddresses()
+ if address in knownAddresses:
+ return knownAddresses[address]
+
+ return address
+
+def buildKnownAddresses():
+ # add from address book
+ try:
+ response = api.listAddressBookEntries()
+ # if api is too old then fail
+ if "API Error 0020" in response: return
+ addressBook = json.loads(response)
+ for entry in addressBook['addresses']:
+ if entry['address'] not in knownAddresses:
+ knownAddresses[entry['address']] = "%s (%s)" % (entry['label'].decode('base64'), entry['address'])
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+ # add from my addresses
+ try:
+ response = api.listAddresses2()
+ # if api is too old just return then fail
+ if "API Error 0020" in response: return
+ addresses = json.loads(response)
+ for entry in addresses['addresses']:
+ if entry['address'] not in knownAddresses:
+ knownAddresses[entry['address']] = "%s (%s)" % (entry['label'].decode('base64'), entry['address'])
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+def listAddressBookEntries():
+ try:
+ response = api.listAddressBookEntries()
+ if "API Error" in response:
+ return getAPIErrorCode(response)
+ addressBook = json.loads(response)
+ print
+ print ' --------------------------------------------------------------'
+ print ' | Label | Address |'
+ print ' |--------------------|---------------------------------------|'
+ for entry in addressBook['addresses']:
+ label = entry['label'].decode('base64')
+ address = entry['address']
+ if (len(label) > 19): label = label[:16] + '...'
+ print ' | ' + label.ljust(19) + '| ' + address.ljust(37) + ' |'
+ print ' --------------------------------------------------------------'
+ print
+
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+def addAddressToAddressBook(address, label):
+ try:
+ response = api.addAddressBookEntry(address, label.encode('base64'))
+ if "API Error" in response:
+ return getAPIErrorCode(response)
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+def deleteAddressFromAddressBook(address):
+ try:
+ response = api.deleteAddressBookEntry(address)
+ if "API Error" in response:
+ return getAPIErrorCode(response)
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+def getAPIErrorCode(response):
+ if "API Error" in response:
+ # if we got an API error return the number by getting the number
+ # after the second space and removing the trailing colon
+ return int(response.split()[2][:-1])
+
+def markMessageRead(messageID):
+ try:
+ response = api.getInboxMessageByID(messageID, True)
+ if "API Error" in response:
+ return getAPIErrorCode(response)
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+def markMessageUnread(messageID):
+ try:
+ response = api.getInboxMessageByID(messageID, False)
+ if "API Error" in response:
+ return getAPIErrorCode(response)
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+
+def markAllMessagesRead():
+ try:
+ inboxMessages = json.loads(api.getAllInboxMessages())['inboxMessages']
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+ for message in inboxMessages:
+ if not message['read']:
+ markMessageRead(message['msgid'])
+
+def markAllMessagesUnread():
+ try:
+ inboxMessages = json.loads(api.getAllInboxMessages())['inboxMessages']
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+ for message in inboxMessages:
+ if message['read']:
+ markMessageUnread(message['msgid'])
+
+def clientStatus():
+ try:
+ clientStatus = json.loads(api.clientStatus())
+ except:
+ print '\n Connection Error\n'
+ usrPrompt = 0
+ main()
+ print "\nnetworkStatus: " + clientStatus['networkStatus'] + "\n"
+ print "\nnetworkConnections: " + str(clientStatus['networkConnections']) + "\n"
+ print "\nnumberOfPubkeysProcessed: " + str(clientStatus['numberOfPubkeysProcessed']) + "\n"
+ print "\nnumberOfMessagesProcessed: " + str(clientStatus['numberOfMessagesProcessed']) + "\n"
+ print "\nnumberOfBroadcastsProcessed: " + str(clientStatus['numberOfBroadcastsProcessed']) + "\n"
+
+
+def UI(usrInput): #Main user menu
+ global usrPrompt
+
+ if usrInput == "help" or usrInput == "h" or usrInput == "?":
+ print ' '
+ print ' -------------------------------------------------------------------------'
+ print ' | https://github.com/Dokument/PyBitmessage-Daemon |'
+ print ' |-----------------------------------------------------------------------|'
+ print ' | Command | Description |'
+ print ' |------------------------|----------------------------------------------|'
+ print ' | help | This help file. |'
+ print ' | apiTest | Tests the API |'
+ print ' | addInfo | Returns address information (If valid) |'
+ print ' | bmSettings | BitMessage settings |'
+ print ' | exit | Use anytime to return to main menu |'
+ print ' | quit | Quits the program |'
+ print ' |------------------------|----------------------------------------------|'
+ print ' | listAddresses | Lists all of the users addresses |'
+ print ' | generateAddress | Generates a new address |'
+ print ' | getAddress | Get determinist address from passphrase |'
+ print ' |------------------------|----------------------------------------------|'
+ print ' | listAddressBookEntries | Lists entries from the Address Book |'
+ print ' | addAddressBookEntry | Add address to the Address Book |'
+ print ' | deleteAddressBookEntry | Deletes address from the Address Book |'
+ print ' |------------------------|----------------------------------------------|'
+ print ' | subscribe | Subscribes to an address |'
+ print ' | unsubscribe | Unsubscribes from an address |'
+ #print ' | listSubscriptions | Lists all of the subscriptions. |'
+ print ' |------------------------|----------------------------------------------|'
+ print ' | create | Creates a channel |'
+ print ' | join | Joins a channel |'
+ print ' | leave | Leaves a channel |'
+ print ' |------------------------|----------------------------------------------|'
+ print ' | inbox | Lists the message information for the inbox |'
+ print ' | outbox | Lists the message information for the outbox |'
+ print ' | send | Send a new message or broadcast |'
+ print ' | unread | Lists all unread inbox messages |'
+ print ' | read | Reads a message from the inbox or outbox |'
+ print ' | save | Saves message to text file |'
+ print ' | delete | Deletes a message or all messages |'
+ print ' -------------------------------------------------------------------------'
+ print ' '
+ main()
+
+ elif usrInput == "apitest": #tests the API Connection.
+ if (apiTest() == True):
+ print '\n API connection test has: PASSED\n'
+ else:
+ print '\n API connection test has: FAILED\n'
+ main()
+
+ elif usrInput == "addinfo":
+ tmp_address = userInput('\nEnter the Bitmessage Address.')
+ address_information = api.decodeAddress(tmp_address)
+ address_information = eval(address_information)
+
+ print '\n------------------------------'
+
+ if 'success' in str(address_information.get('status')).lower():
+ print ' Valid Address'
+ print ' Address Version: %s' % str(address_information.get('addressVersion'))
+ print ' Stream Number: %s' % str(address_information.get('streamNumber'))
+ else:
+ print ' Invalid Address !'
+
+ print '------------------------------\n'
+ main()
+
+ elif usrInput == "bmsettings": #tests the API Connection.
+ bmSettings()
+ print ' '
+ main()
+
+ elif usrInput == "quit": #Quits the application
+ print '\n Bye\n'
+ sys.exit()
+ os.exit()
+
+ elif usrInput == "listaddresses": #Lists all of the identities in the addressbook
+ listAdd()
+ main()
+
+ elif usrInput == "generateaddress": #Generates a new address
+ uInput = userInput('\nWould you like to create a (D)eterministic or (R)andom address?').lower()
+
+ if uInput == "d" or uInput == "determinstic": #Creates a deterministic address
+ deterministic = True
+
+ #lbl = raw_input('Label the new address:') #currently not possible via the api
+ lbl = ''
+ passphrase = userInput('Enter the Passphrase.')#.encode('base64')
+ numOfAdd = int(userInput('How many addresses would you like to generate?'))
+ #addVNum = int(raw_input('Address version number (default "0"):'))
+ #streamNum = int(raw_input('Stream number (default "0"):'))
+ addVNum = 3
+ streamNum = 1
+ isRipe = userInput('Shorten the address, (Y)es or (N)o?').lower()
+
+ if isRipe == "y":
+ ripe = True
+ print genAdd(lbl,deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe)
+ main()
+ elif isRipe == "n":
+ ripe = False
+ print genAdd(lbl, deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe)
+ main()
+ elif isRipe == "exit":
+ usrPrompt = 1
+ main()
+ else:
+ print '\n Invalid input\n'
+ main()
+
+
+ elif uInput == "r" or uInput == "random": #Creates a random address with user-defined label
+ deterministic = False
+ null = ''
+ lbl = userInput('Enter the label for the new address.')
+
+ print genAdd(lbl,deterministic, null,null, null, null, null)
+ main()
+
+ else:
+ print '\n Invalid input\n'
+ main()
+
+ elif usrInput == "getaddress": #Gets the address for/from a passphrase
+ phrase = userInput("Enter the address passphrase.")
+ print '\n Working...\n'
+ #vNumber = int(raw_input("Enter the address version number:"))
+ #sNumber = int(raw_input("Enter the address stream number:"))
+
+ address = getAddress(phrase,4,1)#,vNumber,sNumber)
+ print ('\n Address: ' + address + '\n')
+
+ usrPrompt = 1
+ main()
+
+ elif usrInput == "subscribe": #Subsribe to an address
+ subscribe()
+ usrPrompt = 1
+ main()
+ elif usrInput == "unsubscribe": #Unsubscribe from an address
+ unsubscribe()
+ usrPrompt = 1
+ main()
+ elif usrInput == "listsubscriptions": #Unsubscribe from an address
+ listSubscriptions()
+ usrPrompt = 1
+ main()
+
+ elif usrInput == "create":
+ createChan()
+ userPrompt = 1
+ main()
+
+ elif usrInput == "join":
+ joinChan()
+ userPrompt = 1
+ main()
+
+ elif usrInput == "leave":
+ leaveChan()
+ userPrompt = 1
+ main()
+
+ elif usrInput == "inbox":
+ print '\n Loading...\n'
+ inbox()
+ main()
+
+ elif usrInput == "unread":
+ print '\n Loading...\n'
+ inbox(True)
+ main()
+
+ elif usrInput == "outbox":
+ print '\n Loading...\n'
+ outbox()
+ main()
+
+ elif usrInput == 'send': #Sends a message or broadcast
+ uInput = userInput('Would you like to send a (M)essage or (B)roadcast?').lower()
+
+ if (uInput == 'm' or uInput == 'message'):
+ null = ''
+ sendMsg(null,null,null,null)
+ main()
+ elif (uInput =='b' or uInput == 'broadcast'):
+ null = ''
+ sendBrd(null,null,null)
+ main()
+
+
+ elif usrInput == "read": #Opens a message from the inbox for viewing.
+
+ uInput = userInput("Would you like to read a message from the (I)nbox or (O)utbox?").lower()
+
+ if (uInput != 'i' and uInput != 'inbox' and uInput != 'o' and uInput != 'outbox'):
+ print '\n Invalid Input.\n'
+ usrPrompt = 1
+ main()
+
+ msgNum = int(userInput("What is the number of the message you wish to open?"))
+
+ if (uInput == 'i' or uInput == 'inbox'):
+ print '\n Loading...\n'
+ messageID = readMsg(msgNum)
+
+ uInput = userInput("\nWould you like to keep this message unread, (Y)es or (N)o?").lower()
+
+ if not (uInput == 'y' or uInput == 'yes'):
+ markMessageRead(messageID)
+ usrPrompt = 1
+
+ uInput = userInput("\nWould you like to (D)elete, (F)orward, (R)eply to, or (Exit) this message?").lower()
+
+ if (uInput == 'r' or uInput == 'reply'):
+ print '\n Loading...\n'
+ print ' '
+ replyMsg(msgNum,'reply')
+ usrPrompt = 1
+
+ elif (uInput == 'f' or uInput == 'forward'):
+ print '\n Loading...\n'
+ print ' '
+ replyMsg(msgNum,'forward')
+ usrPrompt = 1
+
+ elif (uInput == "d" or uInput == 'delete'):
+ uInput = userInput("Are you sure, (Y)es or (N)o?").lower()#Prevent accidental deletion
+
+ if uInput == "y":
+ delMsg(msgNum)
+ print '\n Message Deleted.\n'
+ usrPrompt = 1
+ else:
+ usrPrompt = 1
+ else:
+ print '\n Invalid entry\n'
+ usrPrompt = 1
+
+ elif (uInput == 'o' or uInput == 'outbox'):
+ readSentMsg(msgNum)
+
+ uInput = userInput("Would you like to (D)elete, or (Exit) this message?").lower() #Gives the user the option to delete the message
+
+ if (uInput == "d" or uInput == 'delete'):
+ uInput = userInput('Are you sure, (Y)es or (N)o?').lower() #Prevent accidental deletion
+
+ if uInput == "y":
+ delSentMsg(msgNum)
+ print '\n Message Deleted.\n'
+ usrPrompt = 1
+ else:
+ usrPrompt = 1
+ else:
+ print '\n Invalid Entry\n'
+ usrPrompt = 1
+
+ main()
+
+ elif usrInput == "save":
+
+ uInput = userInput("Would you like to save a message from the (I)nbox or (O)utbox?").lower()
+
+ if (uInput != 'i' and uInput == 'inbox' and uInput != 'o' and uInput == 'outbox'):
+ print '\n Invalid Input.\n'
+ usrPrompt = 1
+ main()
+
+ if (uInput == 'i' or uInput == 'inbox'):
+ inboxMessages = json.loads(api.getAllInboxMessages())
+ numMessages = len(inboxMessages['inboxMessages'])
+
+ while True:
+ msgNum = int(userInput("What is the number of the message you wish to save?"))
+
+ if (msgNum >= numMessages):
+ print '\n Invalid Message Number.\n'
+ else:
+ break
+
+ subject = inboxMessages['inboxMessages'][msgNum]['subject'].decode('base64')
+ message = inboxMessages['inboxMessages'][msgNum]['message']#Don't decode since it is done in the saveFile function
+
+ elif (uInput == 'o' or uInput == 'outbox'):
+ outboxMessages = json.loads(api.getAllSentMessages())
+ numMessages = len(outboxMessages['sentMessages'])
+
+ while True:
+ msgNum = int(userInput("What is the number of the message you wish to save?"))
+
+ if (msgNum >= numMessages):
+ print '\n Invalid Message Number.\n'
+ else:
+ break
+
+ subject = outboxMessages['sentMessages'][msgNum]['subject'].decode('base64')
+ message = outboxMessages['sentMessages'][msgNum]['message']#Don't decode since it is done in the saveFile function
+
+ subject = subject +'.txt'
+ saveFile(subject,message)
+
+ usrPrompt = 1
+ main()
+
+ elif usrInput == "delete": #will delete a message from the system, not reflected on the UI.
+
+ uInput = userInput("Would you like to delete a message from the (I)nbox or (O)utbox?").lower()
+
+ if (uInput == 'i' or uInput == 'inbox'):
+ inboxMessages = json.loads(api.getAllInboxMessages())
+ numMessages = len(inboxMessages['inboxMessages'])
+
+ while True:
+ msgNum = userInput('Enter the number of the message you wish to delete or (A)ll to empty the inbox.').lower()
+
+ if (msgNum == 'a' or msgNum == 'all'):
+ break
+ elif (int(msgNum) >= numMessages):
+ print '\n Invalid Message Number.\n'
+ else:
+ break
+
+ uInput = userInput("Are you sure, (Y)es or (N)o?").lower()#Prevent accidental deletion
+
+ if uInput == "y":
+ if (msgNum == 'a' or msgNum == 'all'):
+ print ' '
+ for msgNum in range (0, numMessages): #processes all of the messages in the inbox
+ print ' Deleting message ', msgNum+1, ' of ', numMessages
+ delMsg(0)
+
+ print '\n Inbox is empty.'
+ usrPrompt = 1
+ else:
+ delMsg(int(msgNum))
+
+ print '\n Notice: Message numbers may have changed.\n'
+ main()
+ else:
+ usrPrompt = 1
+ elif (uInput == 'o' or uInput == 'outbox'):
+ outboxMessages = json.loads(api.getAllSentMessages())
+ numMessages = len(outboxMessages['sentMessages'])
+
+ while True:
+ msgNum = userInput('Enter the number of the message you wish to delete or (A)ll to empty the inbox.').lower()
+
+ if (msgNum == 'a' or msgNum == 'all'):
+ break
+ elif (int(msgNum) >= numMessages):
+ print '\n Invalid Message Number.\n'
+ else:
+ break
+
+ uInput = userInput("Are you sure, (Y)es or (N)o?").lower()#Prevent accidental deletion
+
+ if uInput == "y":
+ if (msgNum == 'a' or msgNum == 'all'):
+ print ' '
+ for msgNum in range (0, numMessages): #processes all of the messages in the outbox
+ print ' Deleting message ', msgNum+1, ' of ', numMessages
+ delSentMsg(0)
+
+ print '\n Outbox is empty.'
+ usrPrompt = 1
+ else:
+ delSentMsg(int(msgNum))
+ print '\n Notice: Message numbers may have changed.\n'
+ main()
+ else:
+ usrPrompt = 1
+ else:
+ print '\n Invalid Entry.\n'
+ userPrompt = 1
+ main()
+
+ elif usrInput == "exit":
+ print '\n You are already at the main menu. Use "quit" to quit.\n'
+ usrPrompt = 1
+ main()
+
+ elif usrInput == "listaddressbookentries":
+ res = listAddressBookEntries()
+ if res == 20: print '\n Error: API function not supported.\n'
+ usrPrompt = 1
+ main()
+
+ elif usrInput == "addaddressbookentry":
+ address = userInput('Enter address')
+ label = userInput('Enter label')
+ res = addAddressToAddressBook(address, label)
+ if res == 16: print '\n Error: Address already exists in Address Book.\n'
+ if res == 20: print '\n Error: API function not supported.\n'
+ usrPrompt = 1
+ main()
+
+ elif usrInput == "deleteaddressbookentry":
+ address = userInput('Enter address')
+ res = deleteAddressFromAddressBook(address)
+ if res == 20: print '\n Error: API function not supported.\n'
+ usrPrompt = 1
+ main()
+
+ elif usrInput == "markallmessagesread":
+ markAllMessagesRead()
+ usrPrompt = 1
+ main()
+
+ elif usrInput == "markallmessagesunread":
+ markAllMessagesUnread()
+ usrPrompt = 1
+ main()
+
+ elif usrInput == "status":
+ clientStatus()
+ usrPrompt = 1
+ main()
+
+ elif usrInput == "million+":
+ genMilAddr()
+ usrPrompt = 1
+ main()
+
+ elif usrInput == "million-":
+ delMilAddr()
+ usrPrompt = 1
+ main()
+
+ else:
+ print '\n "',usrInput,'" is not a command.\n'
+ usrPrompt = 1
+ main()
+
+def main():
+ global api
+ global usrPrompt
+
+ if (usrPrompt == 0):
+ print '\n ------------------------------'
+ print ' | Bitmessage Daemon by .dok |'
+ print ' | Version 0.2.6 for BM 0.3.5 |'
+ print ' ------------------------------'
+ api = xmlrpclib.ServerProxy(apiData()) #Connect to BitMessage using these api credentials
+
+ if (apiTest() == False):
+ print '\n ****************************************************************'
+ print ' WARNING: You are not connected to the Bitmessage client.'
+ print ' Either Bitmessage is not running or your settings are incorrect.'
+ print ' Use the command "apiTest" or "bmSettings" to resolve this issue.'
+ print ' ****************************************************************\n'
+
+ print 'Type (H)elp for a list of commands.' #Startup message
+ usrPrompt = 2
+
+ #if (apiTest() == False):#Preform a connection test #taken out until I get the error handler working
+ # print '*************************************'
+ # print 'WARNING: No connection to Bitmessage.'
+ # print '*************************************'
+ # print ' '
+ elif (usrPrompt == 1):
+ print '\nType (H)elp for a list of commands.' #Startup message
+ usrPrompt = 2
+
+ try:
+ UI((raw_input('>').lower()).replace(" ", ""))
+ except EOFError:
+ UI("quit")
+
+if __name__ == "__main__":
+ main()
diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py
index bf1d74f2..2767e465 100755
--- a/src/bitmessagemain.py
+++ b/src/bitmessagemain.py
@@ -23,8 +23,7 @@ import sys
from subprocess import call
import time
-from SimpleXMLRPCServer import SimpleXMLRPCServer
-from api import MySimpleXMLRPCRequestHandler
+from api import MySimpleXMLRPCRequestHandler, StoppableXMLRPCServer
from helper_startup import isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections
import shared
@@ -44,7 +43,10 @@ from debug import logger
# Helper Functions
import helper_bootstrap
import helper_generic
-
+from helper_threading import *
+
+# singleton lock instance
+thisapp = None
def connectToStream(streamNumber):
shared.streamsInWhichIAmParticipating[streamNumber] = 'no data'
@@ -117,13 +119,24 @@ def _fixWinsock():
socket.IPV6_V6ONLY = 27
# This thread, of which there is only one, runs the API.
-class singleAPI(threading.Thread):
-
+class singleAPI(threading.Thread, StoppableThread):
def __init__(self):
- threading.Thread.__init__(self)
+ threading.Thread.__init__(self, name="singleAPI")
+ self.initStop()
+
+ def stopThread(self):
+ super(singleAPI, self).stopThread()
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ try:
+ s.connect((shared.config.get('bitmessagesettings', 'apiinterface'), shared.config.getint(
+ 'bitmessagesettings', 'apiport')))
+ s.shutdown(socket.SHUT_RDWR)
+ s.close()
+ except:
+ pass
def run(self):
- se = SimpleXMLRPCServer((shared.config.get('bitmessagesettings', 'apiinterface'), shared.config.getint(
+ se = StoppableXMLRPCServer((shared.config.get('bitmessagesettings', 'apiinterface'), shared.config.getint(
'bitmessagesettings', 'apiport')), MySimpleXMLRPCRequestHandler, True, True)
se.register_introspection_functions()
se.serve_forever()
@@ -139,11 +152,13 @@ if shared.useVeryEasyProofOfWorkForTesting:
class Main:
def start(self, daemon=False):
+ global thisapp
+
_fixWinsock()
shared.daemon = daemon
# is the application already running? If yes then exit.
- thisapp = singleton.singleinstance()
+ thisapp = singleton.singleinstance("", daemon)
# get curses flag
curses = False
@@ -203,6 +218,11 @@ class Main:
singleListenerThread.setup(selfInitiatedConnections)
singleListenerThread.daemon = True # close the main program even if there are threads left
singleListenerThread.start()
+
+ if shared.safeConfigGetBoolean('bitmessagesettings','upnp'):
+ import upnp
+ upnpThread = upnp.uPnPThread()
+ upnpThread.start()
if daemon == False and shared.safeConfigGetBoolean('bitmessagesettings', 'daemon') == False:
if curses == False:
diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py
index 1819628b..b6da74f9 100644
--- a/src/bitmessageqt/__init__.py
+++ b/src/bitmessageqt/__init__.py
@@ -1,3 +1,4 @@
+from debug import logger
withMessagingMenu = False
try:
from gi.repository import MessagingMenu
@@ -6,17 +7,38 @@ try:
except ImportError:
MessagingMenu = None
+try:
+ from PyQt4 import QtCore, QtGui
+ from PyQt4.QtCore import *
+ from PyQt4.QtGui import *
+ from PyQt4.QtNetwork import QLocalSocket, QLocalServer
+
+except Exception as err:
+ 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()
+
+try:
+ _encoding = QtGui.QApplication.UnicodeUTF8
+except AttributeError:
+ logger.exception('QtGui.QApplication.UnicodeUTF8 error', exc_info=True)
+
from addresses import *
import shared
from bitmessageui import *
from namecoin import namecoinConnection, ensureNamecoinOptions
from newaddressdialog import *
+from newaddresswizard import *
+from migrationwizard import *
+from foldertree import *
from addaddressdialog import *
from newsubscriptiondialog import *
from regenerateaddresses import *
from newchandialog import *
from specialaddressbehavior import *
+from emailgateway import *
from settings import *
+import settingsmixin
from about import *
from help import *
from iconglossary import *
@@ -31,143 +53,29 @@ import pickle
import platform
import textwrap
import debug
-from debug import logger
+import random
import subprocess
+import string
import datetime
from helper_sql import *
import l10n
-
-try:
- from PyQt4 import QtCore, QtGui
- from PyQt4.QtCore import *
- from PyQt4.QtGui import *
-
-except Exception as err:
- print 'PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download it from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\' (without quotes).'
- print 'Error message:', err
- sys.exit()
-
-try:
- _encoding = QtGui.QApplication.UnicodeUTF8
-except AttributeError:
- print 'QtGui.QApplication.UnicodeUTF8 error:', err
+import openclpow
+import types
+from utils import *
+from collections import OrderedDict
+from account import *
def _translate(context, text):
return QtGui.QApplication.translate(context, text)
-
-def identiconize(address):
- size = 48
-
- # If you include another identicon library, please generate an
- # example identicon with the following md5 hash:
- # 3fd4bf901b9d4ea1394f0fb358725b28
-
- try:
- identicon_lib = shared.config.get('bitmessagesettings', 'identiconlib')
- except:
- # default to qidenticon_two_x
- identicon_lib = 'qidenticon_two_x'
-
- # As an 'identiconsuffix' you could put "@bitmessge.ch" or "@bm.addr" to make it compatible with other identicon generators. (Note however, that E-Mail programs might convert the BM-address to lowercase first.)
- # It can be used as a pseudo-password to salt the generation of the identicons to decrease the risk
- # of attacks where someone creates an address to mimic someone else's identicon.
- identiconsuffix = shared.config.get('bitmessagesettings', 'identiconsuffix')
-
- if not shared.config.getboolean('bitmessagesettings', 'useidenticons'):
- idcon = QtGui.QIcon()
- return idcon
-
- if (identicon_lib[:len('qidenticon')] == 'qidenticon'):
- # print identicon_lib
- # originally by:
- # :Author:Shin Adachi
- # Licesensed under FreeBSD License.
- # stripped from PIL and uses QT instead (by sendiulo, same license)
- import qidenticon
- hash = hashlib.md5(addBMIfNotPresent(address)+identiconsuffix).hexdigest()
- use_two_colors = (identicon_lib[:len('qidenticon_two')] == 'qidenticon_two')
- opacity = int(not((identicon_lib == 'qidenticon_x') | (identicon_lib == 'qidenticon_two_x') | (identicon_lib == 'qidenticon_b') | (identicon_lib == 'qidenticon_two_b')))*255
- penwidth = 0
- image = qidenticon.render_identicon(int(hash, 16), size, use_two_colors, opacity, penwidth)
- # filename = './images/identicons/'+hash+'.png'
- # image.save(filename)
- idcon = QtGui.QIcon()
- idcon.addPixmap(image, QtGui.QIcon.Normal, QtGui.QIcon.Off)
- return idcon
- elif identicon_lib == 'pydenticon':
- # print identicon_lib
- # Here you could load pydenticon.py (just put it in the "src" folder of your Bitmessage source)
- from pydenticon import Pydenticon
- # It is not included in the source, because it is licensed under GPLv3
- # GPLv3 is a copyleft license that would influence our licensing
- # Find the source here: http://boottunes.googlecode.com/svn-history/r302/trunk/src/pydenticon.py
- # note that it requires PIL to be installed: http://www.pythonware.com/products/pil/
- idcon_render = Pydenticon(addBMIfNotPresent(address)+identiconsuffix, size*3)
- rendering = idcon_render._render()
- data = rendering.convert("RGBA").tostring("raw", "RGBA")
- qim = QImage(data, size, size, QImage.Format_ARGB32)
- pix = QPixmap.fromImage(qim)
- idcon = QtGui.QIcon()
- idcon.addPixmap(pix, QtGui.QIcon.Normal, QtGui.QIcon.Off)
- return idcon
-
-def avatarize(address):
- """
- loads a supported image for the given address' hash form 'avatars' folder
- falls back to default avatar if 'default.*' file exists
- falls back to identiconize(address)
- """
- idcon = QtGui.QIcon()
- hash = hashlib.md5(addBMIfNotPresent(address)).hexdigest()
- str_broadcast_subscribers = '[Broadcast subscribers]'
- if address == str_broadcast_subscribers:
- # don't hash [Broadcast subscribers]
- hash = address
- # http://pyqt.sourceforge.net/Docs/PyQt4/qimagereader.html#supportedImageFormats
- # print QImageReader.supportedImageFormats ()
- # QImageReader.supportedImageFormats ()
- extensions = ['PNG', 'GIF', 'JPG', 'JPEG', 'SVG', 'BMP', 'MNG', 'PBM', 'PGM', 'PPM', 'TIFF', 'XBM', 'XPM', 'TGA']
- # try to find a specific avatar
- for ext in extensions:
- lower_hash = shared.appdata + 'avatars/' + hash + '.' + ext.lower()
- upper_hash = shared.appdata + 'avatars/' + hash + '.' + ext.upper()
- if os.path.isfile(lower_hash):
- # print 'found avatar of ', address
- idcon.addFile(lower_hash)
- return idcon
- elif os.path.isfile(upper_hash):
- # print 'found avatar of ', address
- idcon.addFile(upper_hash)
- return idcon
- # if we haven't found any, try to find a default avatar
- for ext in extensions:
- lower_default = shared.appdata + 'avatars/' + 'default.' + ext.lower()
- upper_default = shared.appdata + 'avatars/' + 'default.' + ext.upper()
- if os.path.isfile(lower_default):
- default = lower_default
- idcon.addFile(lower_default)
- return idcon
- elif os.path.isfile(upper_default):
- default = upper_default
- idcon.addFile(upper_default)
- return idcon
- # If no avatar is found
- return identiconize(address)
-
def change_translation(locale):
global qtranslator
qtranslator = QtCore.QTranslator()
- translationpath = os.path.join(
- getattr(sys, '_MEIPASS', sys.path[0]),
- 'translations',
- 'bitmessage_' + locale
- )
+ translationpath = os.path.join (shared.codePath(), 'translations', 'bitmessage_' + locale)
qtranslator.load(translationpath)
QtGui.QApplication.installTranslator(qtranslator)
-
-class MyForm(QtGui.QMainWindow):
+class MyForm(settingsmixin.SMainWindow):
# sound type constants
SOUND_NONE = 0
@@ -183,7 +91,6 @@ class MyForm(QtGui.QMainWindow):
# the maximum frequency of message sounds in seconds
maxSoundFrequencySec = 60
- str_broadcast_subscribers = '[Broadcast subscribers]'
str_chan = '[chan]'
def init_file_menu(self):
@@ -199,13 +106,11 @@ class MyForm(QtGui.QMainWindow):
QtCore.SIGNAL(
"triggered()"),
self.click_actionRegenerateDeterministicAddresses)
- QtCore.QObject.connect(self.ui.actionJoinChan, QtCore.SIGNAL(
- "triggered()"),
+ 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.comboBoxSendFrom, QtCore.SIGNAL(
- "activated(int)"), self.redrawLabelFrom)
QtCore.QObject.connect(self.ui.pushButtonAddAddressBook, QtCore.SIGNAL(
"clicked()"), self.click_pushButtonAddAddressBook)
QtCore.QObject.connect(self.ui.pushButtonAddSubscription, QtCore.SIGNAL(
@@ -216,10 +121,6 @@ class MyForm(QtGui.QMainWindow):
"clicked()"), self.click_pushButtonTTL)
QtCore.QObject.connect(self.ui.pushButtonSend, QtCore.SIGNAL(
"clicked()"), self.click_pushButtonSend)
- QtCore.QObject.connect(self.ui.pushButtonLoadFromAddressBook,
- QtCore.SIGNAL(
- "clicked()"),
- self.click_pushButtonLoadFromAddressBook)
QtCore.QObject.connect(self.ui.pushButtonFetchNamecoinID, QtCore.SIGNAL(
"clicked()"), self.click_pushButtonFetchNamecoinID)
QtCore.QObject.connect(self.ui.radioButtonBlacklist, QtCore.SIGNAL(
@@ -245,9 +146,16 @@ class MyForm(QtGui.QMainWindow):
_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)
+ 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"),
@@ -259,61 +167,97 @@ class MyForm(QtGui.QMainWindow):
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.popMenuInbox = QtGui.QMenu(self)
- self.popMenuInbox.addAction(self.actionForceHtml)
- self.popMenuInbox.addAction(self.actionMarkUnread)
- self.popMenuInbox.addSeparator()
- self.popMenuInbox.addAction(self.actionReply)
- self.popMenuInbox.addAction(self.actionAddSenderToAddressBook)
- self.popMenuInbox.addSeparator()
- self.popMenuInbox.addAction(self.actionSaveMessageAs)
- self.popMenuInbox.addAction(self.actionTrashInboxMessage)
+ 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
+ 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.ui.treeWidgetYourIdentities.setContextMenuPolicy(
+ QtCore.Qt.CustomContextMenu)
+ if connectSignal:
+ self.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL(
+ 'customContextMenuRequested(const QPoint&)'),
+ self.on_context_menuYourIdentities)
+
+ def init_chan_popup_menu(self, connectSignal=True):
+ # Popup menu for the Channels tab
self.ui.addressContextMenuToolbar = QtGui.QToolBar()
# Actions
self.actionNew = self.ui.addressContextMenuToolbar.addAction(_translate(
"MainWindow", "New"), self.on_action_YourIdentitiesNew)
+ self.actionDelete = self.ui.addressContextMenuToolbar.addAction(
+ _translate("MainWindow", "Delete"),
+ self.on_action_YourIdentitiesDelete)
self.actionEnable = self.ui.addressContextMenuToolbar.addAction(
_translate(
- "MainWindow", "Enable"), self.on_action_YourIdentitiesEnable)
+ "MainWindow", "Enable"), self.on_action_Enable)
self.actionDisable = self.ui.addressContextMenuToolbar.addAction(
_translate(
- "MainWindow", "Disable"), self.on_action_YourIdentitiesDisable)
+ "MainWindow", "Disable"), self.on_action_Disable)
self.actionSetAvatar = self.ui.addressContextMenuToolbar.addAction(
_translate(
"MainWindow", "Set avatar..."),
- self.on_action_YourIdentitiesSetAvatar)
+ self.on_action_TreeWidgetSetAvatar)
self.actionClipboard = self.ui.addressContextMenuToolbar.addAction(
_translate(
"MainWindow", "Copy address to clipboard"),
- self.on_action_YourIdentitiesClipboard)
+ self.on_action_Clipboard)
self.actionSpecialAddressBehavior = self.ui.addressContextMenuToolbar.addAction(
_translate(
"MainWindow", "Special address behavior..."),
self.on_action_SpecialAddressBehaviorDialog)
- self.ui.tableWidgetYourIdentities.setContextMenuPolicy(
+
+ self.ui.treeWidgetChans.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu)
if connectSignal:
- self.connect(self.ui.tableWidgetYourIdentities, QtCore.SIGNAL(
+ self.connect(self.ui.treeWidgetChans, QtCore.SIGNAL(
'customContextMenuRequested(const QPoint&)'),
- self.on_context_menuYourIdentities)
- self.popMenu = QtGui.QMenu(self)
- self.popMenu.addAction(self.actionNew)
- self.popMenu.addSeparator()
- self.popMenu.addAction(self.actionClipboard)
- self.popMenu.addSeparator()
- self.popMenu.addAction(self.actionEnable)
- self.popMenu.addAction(self.actionDisable)
- self.popMenu.addAction(self.actionSetAvatar)
- self.popMenu.addAction(self.actionSpecialAddressBehavior)
+ self.on_context_menuChan)
def init_addressbook_popup_menu(self, connectSignal=True):
# Popup menu for the Address Book page
@@ -347,14 +291,6 @@ class MyForm(QtGui.QMainWindow):
self.connect(self.ui.tableWidgetAddressBook, QtCore.SIGNAL(
'customContextMenuRequested(const QPoint&)'),
self.on_context_menuAddressBook)
- 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.addSeparator()
- self.popMenuAddressBook.addAction(self.actionAddressBookNew)
- self.popMenuAddressBook.addAction(self.actionAddressBookDelete)
def init_subscriptions_popup_menu(self, connectSignal=True):
# Popup menu for the Subscriptions page
@@ -376,22 +312,13 @@ class MyForm(QtGui.QMainWindow):
self.on_action_SubscriptionsDisable)
self.actionsubscriptionsSetAvatar = self.ui.subscriptionsContextMenuToolbar.addAction(
_translate("MainWindow", "Set avatar..."),
- self.on_action_SubscriptionsSetAvatar)
- self.ui.tableWidgetSubscriptions.setContextMenuPolicy(
+ self.on_action_TreeWidgetSetAvatar)
+ self.ui.treeWidgetSubscriptions.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu)
if connectSignal:
- self.connect(self.ui.tableWidgetSubscriptions, QtCore.SIGNAL(
+ self.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL(
'customContextMenuRequested(const QPoint&)'),
self.on_context_menuSubscriptions)
- self.popMenuSubscriptions = QtGui.QMenu(self)
- self.popMenuSubscriptions.addAction(self.actionsubscriptionsNew)
- self.popMenuSubscriptions.addAction(self.actionsubscriptionsDelete)
- self.popMenuSubscriptions.addSeparator()
- self.popMenuSubscriptions.addAction(self.actionsubscriptionsEnable)
- self.popMenuSubscriptions.addAction(self.actionsubscriptionsDisable)
- self.popMenuSubscriptions.addAction(self.actionsubscriptionsSetAvatar)
- self.popMenuSubscriptions.addSeparator()
- self.popMenuSubscriptions.addAction(self.actionsubscriptionsClipboard)
def init_sent_popup_menu(self, connectSignal=True):
# Popup menu for the Sent page
@@ -407,12 +334,6 @@ class MyForm(QtGui.QMainWindow):
self.actionForceSend = self.ui.sentContextMenuToolbar.addAction(
_translate(
"MainWindow", "Force send"), self.on_action_ForceSend)
- self.ui.tableWidgetSent.setContextMenuPolicy(
- QtCore.Qt.CustomContextMenu)
- if connectSignal:
- self.connect(self.ui.tableWidgetSent, QtCore.SIGNAL(
- 'customContextMenuRequested(const QPoint&)'),
- self.on_context_menuSent)
# self.popMenuSent = QtGui.QMenu( self )
# self.popMenuSent.addAction( self.actionSentClipboard )
# self.popMenuSent.addAction( self.actionTrashSentMessage )
@@ -457,6 +378,198 @@ class MyForm(QtGui.QMainWindow):
self.popMenuBlacklist.addAction(self.actionBlacklistDisable)
self.popMenuBlacklist.addAction(self.actionBlacklistSetAvatar)
+ def rerenderTabTreeSubscriptions(self):
+ treeWidget = self.ui.treeWidgetSubscriptions
+ folders = Ui_FolderWidget.folderWeight.keys()
+ folders.remove("new")
+
+ # sort ascending when creating
+ if treeWidget.topLevelItemCount() == 0:
+ treeWidget.header().setSortIndicator(0, Qt.AscendingOrder)
+ # init dictionary
+
+ db = getSortedSubscriptions(True)
+ for address in db:
+ for folder in folders:
+ if not folder in db[address]:
+ db[address][folder] = {}
+
+ if treeWidget.isSortingEnabled():
+ treeWidget.setSortingEnabled(False)
+
+ widgets = {}
+ i = 0
+ while i < treeWidget.topLevelItemCount():
+ widget = treeWidget.topLevelItem(i)
+ if widget is not None:
+ toAddress = widget.address
+ else:
+ toAddress = None
+
+ if not toAddress 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 len(db[toAddress]) > 0:
+ 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)
+ widget.setFlags (widget.flags() | QtCore.Qt.ItemIsEditable)
+ i += 1
+
+ treeWidget.setSortingEnabled(True)
+
+
+ def rerenderTabTreeMessages(self):
+ self.rerenderTabTree('messages')
+
+ def rerenderTabTreeChans(self):
+ self.rerenderTabTree('chan')
+
+ def rerenderTabTree(self, tab):
+ 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, Qt.AscendingOrder)
+ # init dictionary
+ db = {}
+ enabled = {}
+
+ for toAddress in getSortedAccounts():
+ isEnabled = shared.config.getboolean(
+ toAddress, 'enabled')
+ isChan = shared.safeConfigGetBoolean(
+ toAddress, 'chan')
+ isMaillinglist = shared.safeConfigGetBoolean(
+ toAddress, 'mailinglist')
+
+ if tab == 'messages':
+ if isChan:
+ continue
+ elif tab == 'chan':
+ if not isChan:
+ continue
+
+ db[toAddress] = {}
+ for folder in folders:
+ db[toAddress][folder] = 0
+
+ enabled[toAddress] = isEnabled
+
+ # 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
+ if tab == "messages":
+ db[None] = {}
+ db[None]["inbox"] = total
+ db[None]["new"] = total
+ enabled[None] = True
+
+ if treeWidget.isSortingEnabled():
+ treeWidget.setSortingEnabled(False)
+
+ widgets = {}
+ i = 0
+ while i < treeWidget.topLevelItemCount():
+ widget = treeWidget.topLevelItem(i)
+ if widget is not None:
+ toAddress = widget.address
+ else:
+ toAddress = None
+
+ if not toAddress 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])
+ unread += db[toAddress][subwidget.folderName]
+ db[toAddress].pop(subwidget.folderName, None)
+ except:
+ widget.takeChild(j)
+ # no increment
+ continue
+ j += 1
+
+ # add missing folders
+ if len(db[toAddress]) > 0:
+ j = 0
+ for f, c in db[toAddress].iteritems():
+ subwidget = Ui_FolderWidget(widget, j, toAddress, f, 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 folder == "new":
+ continue
+ if toAddress is None and folder in ["trash", "sent"]:
+ continue
+ subwidget = Ui_FolderWidget(widget, j, toAddress, folder, db[toAddress][folder])
+ unread += db[toAddress][folder]
+ j += 1
+ widget.setUnreadCount(unread)
+ widget.setFlags (widget.flags() | QtCore.Qt.ItemIsEditable)
+ i += 1
+
+ treeWidget.setSortingEnabled(True)
+
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
@@ -464,20 +577,18 @@ class MyForm(QtGui.QMainWindow):
# Ask the user if we may delete their old version 1 addresses if they
# have any.
- configSections = shared.config.sections()
- for addressInKeysFile in configSections:
- if addressInKeysFile != 'bitmessagesettings':
- status, addressVersionNumber, streamNumber, hash = 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 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:
- shared.config.remove_section(addressInKeysFile)
- shared.writeKeysFile()
+ for addressInKeysFile in getSortedAccounts():
+ status, addressVersionNumber, streamNumber, hash = 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 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:
+ shared.config.remove_section(addressInKeysFile)
+ shared.writeKeysFile()
# Configure Bitmessage to start on startup (or remove the
# configuration) based on the setting in the keys.dat file
@@ -500,59 +611,40 @@ class MyForm(QtGui.QMainWindow):
self.totalNumberOfBytesReceived = 0
self.totalNumberOfBytesSent = 0
- self.ui.labelSendBroadcastWarning.setVisible(False)
-
self.timer = QtCore.QTimer()
self.timer.start(2000) # milliseconds
QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.runEveryTwoSeconds)
+ # e.g. for editing labels
+ self.recurDepth = 0
+
+ # switch back to this when replying
+ self.replyFromTab = None
+
self.init_file_menu()
self.init_inbox_popup_menu()
self.init_identities_popup_menu()
self.init_addressbook_popup_menu()
self.init_subscriptions_popup_menu()
+ self.init_chan_popup_menu()
self.init_sent_popup_menu()
self.init_blacklist_popup_menu()
+
+ # Initialize the user's list of addresses on the 'Chan' tab.
+ self.rerenderTabTreeChans()
- # Initialize the user's list of addresses on the 'Your Identities' tab.
- configSections = shared.config.sections()
- for addressInKeysFile in configSections:
- if addressInKeysFile != 'bitmessagesettings':
- isEnabled = shared.config.getboolean(
- addressInKeysFile, 'enabled')
- newItem = QtGui.QTableWidgetItem(unicode(
- shared.config.get(addressInKeysFile, 'label'), 'utf-8)'))
- if not isEnabled:
- newItem.setTextColor(QtGui.QColor(128, 128, 128))
- self.ui.tableWidgetYourIdentities.insertRow(0)
- newItem.setIcon(avatarize(addressInKeysFile))
- self.ui.tableWidgetYourIdentities.setItem(0, 0, newItem)
- newItem = QtGui.QTableWidgetItem(addressInKeysFile)
- newItem.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- if shared.safeConfigGetBoolean(addressInKeysFile, 'chan'):
- newItem.setTextColor(QtGui.QColor(216, 119, 0)) # orange
- if not isEnabled:
- newItem.setTextColor(QtGui.QColor(128, 128, 128))
- if shared.safeConfigGetBoolean(addressInKeysFile, 'mailinglist'):
- newItem.setTextColor(QtGui.QColor(137, 04, 177)) # magenta
- self.ui.tableWidgetYourIdentities.setItem(0, 1, newItem)
- newItem = QtGui.QTableWidgetItem(str(
- decodeAddress(addressInKeysFile)[2]))
- newItem.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- if not isEnabled:
- newItem.setTextColor(QtGui.QColor(128, 128, 128))
- self.ui.tableWidgetYourIdentities.setItem(0, 2, newItem)
- if isEnabled:
- status, addressVersionNumber, streamNumber, hash = decodeAddress(
- addressInKeysFile)
+ # Initialize the user's list of addresses on the 'Messages' tab.
+ self.rerenderTabTreeMessages()
- # Load inbox from messages database file
- self.loadInbox()
-
- # Load Sent items from database
- self.loadSent()
+ # Set welcome message
+ self.ui.textEditInboxMessage.setText(
+ """
+ Welcome to easy and secure Bitmessage
+ * send messages to other people
+ * send broadcast messages like twitter or
+ * discuss in chan(nel)s with other people
+ """
+ )
# Initialize the address book
self.rerenderAddressBook()
@@ -563,10 +655,10 @@ class MyForm(QtGui.QMainWindow):
# Initialize the inbox search
QtCore.QObject.connect(self.ui.inboxSearchLineEdit, QtCore.SIGNAL(
"returnPressed()"), self.inboxSearchLineEditPressed)
-
- # Initialize the sent search
- QtCore.QObject.connect(self.ui.sentSearchLineEdit, QtCore.SIGNAL(
- "returnPressed()"), self.sentSearchLineEditPressed)
+ QtCore.QObject.connect(self.ui.inboxSearchLineEditSubscriptions, QtCore.SIGNAL(
+ "returnPressed()"), self.inboxSearchLineEditPressed)
+ QtCore.QObject.connect(self.ui.inboxSearchLineEditChans, QtCore.SIGNAL(
+ "returnPressed()"), self.inboxSearchLineEditPressed)
# Initialize the Blacklist or Whitelist
if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'white':
@@ -574,16 +666,31 @@ class MyForm(QtGui.QMainWindow):
self.ui.radioButtonWhitelist.click()
self.rerenderBlackWhiteList()
- QtCore.QObject.connect(self.ui.tableWidgetYourIdentities, QtCore.SIGNAL(
- "itemChanged(QTableWidgetItem *)"), self.tableWidgetYourIdentitiesItemChanged)
+ # Initialize addressbook
QtCore.QObject.connect(self.ui.tableWidgetAddressBook, QtCore.SIGNAL(
"itemChanged(QTableWidgetItem *)"), self.tableWidgetAddressBookItemChanged)
- QtCore.QObject.connect(self.ui.tableWidgetSubscriptions, QtCore.SIGNAL(
- "itemChanged(QTableWidgetItem *)"), self.tableWidgetSubscriptionsItemChanged)
+
+ # show messages from message list
QtCore.QObject.connect(self.ui.tableWidgetInbox, QtCore.SIGNAL(
"itemSelectionChanged ()"), self.tableWidgetInboxItemClicked)
- QtCore.QObject.connect(self.ui.tableWidgetSent, QtCore.SIGNAL(
- "itemSelectionChanged ()"), self.tableWidgetSentItemClicked)
+ 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
+ QtCore.QObject.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL(
+ "itemSelectionChanged ()"), self.treeWidgetItemClicked)
+ QtCore.QObject.connect(self.ui.treeWidgetYourIdentities, QtCore.SIGNAL(
+ "itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged)
+ QtCore.QObject.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL(
+ "itemSelectionChanged ()"), self.treeWidgetItemClicked)
+ QtCore.QObject.connect(self.ui.treeWidgetSubscriptions, QtCore.SIGNAL(
+ "itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged)
+ QtCore.QObject.connect(self.ui.treeWidgetChans, QtCore.SIGNAL(
+ "itemSelectionChanged ()"), self.treeWidgetItemClicked)
+ QtCore.QObject.connect(self.ui.treeWidgetChans, QtCore.SIGNAL(
+ "itemChanged (QTreeWidgetItem *, int)"), self.treeWidgetItemChanged)
# Put the colored icon on the status bar
# self.ui.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/yellowicon.png"))
@@ -594,13 +701,14 @@ class MyForm(QtGui.QMainWindow):
self.numberOfMessagesProcessed = 0
self.numberOfBroadcastsProcessed = 0
self.numberOfPubkeysProcessed = 0
+ self.unreadCount = 0
# Set the icon sizes for the identicons
identicon_size = 3*7
self.ui.tableWidgetInbox.setIconSize(QtCore.QSize(identicon_size, identicon_size))
- self.ui.tableWidgetSent.setIconSize(QtCore.QSize(identicon_size, identicon_size))
- self.ui.tableWidgetYourIdentities.setIconSize(QtCore.QSize(identicon_size, identicon_size))
- self.ui.tableWidgetSubscriptions.setIconSize(QtCore.QSize(identicon_size, identicon_size))
+ self.ui.treeWidgetChans.setIconSize(QtCore.QSize(identicon_size, identicon_size))
+ self.ui.treeWidgetYourIdentities.setIconSize(QtCore.QSize(identicon_size, identicon_size))
+ self.ui.treeWidgetSubscriptions.setIconSize(QtCore.QSize(identicon_size, identicon_size))
self.ui.tableWidgetAddressBook.setIconSize(QtCore.QSize(identicon_size, identicon_size))
self.ui.tableWidgetBlacklist.setIconSize(QtCore.QSize(identicon_size, identicon_size))
@@ -641,6 +749,8 @@ class MyForm(QtGui.QMainWindow):
"rerenderBlackWhiteList()"), self.rerenderBlackWhiteList)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"removeInboxRowByMsgid(PyQt_PyObject)"), self.removeInboxRowByMsgid)
+ QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
+ "newVersionAvailable(PyQt_PyObject)"), self.newVersionAvailable)
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"displayAlert(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayAlert)
self.UISignalThread.start()
@@ -649,6 +759,7 @@ class MyForm(QtGui.QMainWindow):
# structures were initialized.
self.rerenderComboBoxSendFrom()
+ self.rerenderComboBoxSendFromBroadcast()
# Put the TTL slider in the correct spot
TTL = shared.config.getint('bitmessagesettings', 'ttl')
@@ -661,7 +772,9 @@ class MyForm(QtGui.QMainWindow):
QtCore.QObject.connect(self.ui.horizontalSliderTTL, QtCore.SIGNAL(
"valueChanged(int)"), self.updateTTL)
-
+
+ self.initSettings()
+
# Check to see whether we can connect to namecoin. Hide the 'Fetch Namecoin ID' button if we can't.
try:
options = {}
@@ -674,7 +787,7 @@ class MyForm(QtGui.QMainWindow):
if nc.test()[0] == 'failed':
self.ui.pushButtonFetchNamecoinID.hide()
except:
- print 'There was a problem testing for a Namecoin daemon. Hiding the Fetch Namecoin ID button'
+ logger.error('There was a problem testing for a Namecoin daemon. Hiding the Fetch Namecoin ID button')
self.ui.pushButtonFetchNamecoinID.hide()
def updateTTL(self, sliderPosition):
@@ -700,10 +813,6 @@ class MyForm(QtGui.QMainWindow):
if not self.actionShow.isChecked():
self.hide()
else:
- if sys.platform[0:3] == 'win':
- self.setWindowFlags(Qt.Window)
- # else:
- # self.showMaximized()
self.show()
self.setWindowState(
self.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)
@@ -781,250 +890,306 @@ class MyForm(QtGui.QMainWindow):
# Show the program window and select subscriptions tab
def appIndicatorSubscribe(self):
self.appIndicatorShow()
- self.ui.tabWidget.setCurrentIndex(4)
+ self.ui.tabWidget.setCurrentIndex(2)
- # Show the program window and select the address book tab
- def appIndicatorAddressBook(self):
+ # Show the program window and select channels tab
+ def appIndicatorChannel(self):
self.appIndicatorShow()
- self.ui.tabWidget.setCurrentIndex(5)
+ self.ui.tabWidget.setCurrentIndex(3)
+
+ def propagateUnreadCount(self, address = None, folder = "inbox", widget = None, type = 1):
+ def updateUnreadCount(item):
+ # if refreshing the account root, we need to rescan folders
+ if type == 0 or (folder is None and isinstance(item, Ui_FolderWidget)):
+ if addressItem.type in [AccountMixin.SUBSCRIPTION, AccountMixin.MAILINGLIST]:
+ xAddress = "fromaddress"
+ else:
+ xAddress = "toaddress"
+ xFolder = folder
+ if isinstance(item, Ui_FolderWidget):
+ xFolder = item.folderName
+ if address and xFolder:
+ queryreturn = sqlQuery("SELECT COUNT(*) FROM inbox WHERE " + xAddress + " = ? AND folder = ? AND read = 0", address, xFolder)
+ elif address:
+ queryreturn = sqlQuery("SELECT COUNT(*) FROM inbox WHERE " + xAddress + " = ? AND read = 0", address)
+ elif xFolder:
+ queryreturn = sqlQuery("SELECT COUNT(*) FROM inbox WHERE folder = ? AND read = 0", xFolder)
+ else:
+ queryreturn = sqlQuery("SELECT COUNT(*) FROM inbox WHERE read = 0")
+ for row in queryreturn:
+ item.setUnreadCount(int(row[0]))
+ if isinstance(item, Ui_AddressWidget) and item.type == AccountMixin.ALL:
+ self.drawTrayIcon(self.currentTrayIconFileName, self.findInboxUnreadCount())
+ elif type == 1:
+ item.setUnreadCount(item.unreadCount + 1)
+ if isinstance(item, Ui_AddressWidget) and item.type == AccountMixin.ALL:
+ self.drawTrayIcon(self.currentTrayIconFileName, self.findInboxUnreadCount(self.unreadCount + 1))
+ elif type == -1:
+ item.setUnreadCount(item.unreadCount - 1)
+ if isinstance(item, Ui_AddressWidget) and item.type == AccountMixin.ALL:
+ self.drawTrayIcon(self.currentTrayIconFileName, self.findInboxUnreadCount(self.unreadCount -1))
+
+ widgets = [self.ui.treeWidgetYourIdentities, self.ui.treeWidgetSubscriptions, self.ui.treeWidgetChans]
+ # FIXME this is a hack
+ if folder == "new":
+ folder = "inbox"
+ for treeWidget in widgets:
+ root = treeWidget.invisibleRootItem()
+ for i in range(root.childCount()):
+ addressItem = root.child(i)
+ if addressItem.type != AccountMixin.ALL and address is not None and addressItem.data(0, QtCore.Qt.UserRole) != address:
+ continue
+ updateUnreadCount(addressItem)
+ if addressItem.childCount == 0:
+ continue
+ for j in range(addressItem.childCount()):
+ folderItem = addressItem.child(j)
+ if folder is not None and folderItem.folderName != folder and addressItem.type != AccountMixin.ALL:
+ continue
+ updateUnreadCount(folderItem)
+
+ def addMessageListItem(self, tableWidget, items):
+ tableWidget.insertRow(0)
+ for i in range(len(items)):
+ tableWidget.setItem(0, i, items[i])
+
+ def addMessageListItemSent(self, tableWidget, toAddress, fromAddress, subject, status, ackdata, lastactiontime):
+ subject = shared.fixPotentiallyInvalidUTF8Data(subject)
+ acct = accountClass(fromAddress)
+ acct.parseMessage(toAddress, fromAddress, subject, "")
+
+ items = []
+ toAddressItem = QtGui.QTableWidgetItem(unicode(acct.toLabel, 'utf-8'))
+ toAddressItem.setToolTip(unicode(acct.toLabel, 'utf-8') + " (" + str(acct.toAddress) + ")")
+ toAddressItem.setIcon(avatarize(toAddress))
+ toAddressItem.setData(Qt.UserRole, str(toAddress))
+ toAddressItem.setTextColor(AccountColor(toAddress).accountColor())
+ toAddressItem.setFlags(
+ QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
+ items.append(toAddressItem)
+
+ fromAddressItem = QtGui.QTableWidgetItem(unicode(acct.fromLabel, 'utf-8'))
+ fromAddressItem.setToolTip(unicode(acct.fromLabel, 'utf-8') + " (" + str(acct.fromAddress) + ")")
+ fromAddressItem.setIcon(avatarize(fromAddress))
+ fromAddressItem.setData(Qt.UserRole, str(fromAddress))
+ fromAddressItem.setTextColor(AccountColor(fromAddress).accountColor())
+ fromAddressItem.setFlags(
+ QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
+ items.append(fromAddressItem)
+
+ subjectItem = QtGui.QTableWidgetItem(unicode(acct.subject, 'utf-8'))
+ subjectItem.setToolTip(unicode(acct.subject, 'utf-8'))
+ subjectItem.setData(Qt.UserRole, str(subject))
+ subjectItem.setFlags(
+ QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
+ items.append(subjectItem)
+
+ if status == 'awaitingpubkey':
+ statusText = _translate(
+ "MainWindow", "Waiting for their encryption key. Will request it again soon.")
+ elif status == 'doingpowforpubkey':
+ statusText = _translate(
+ "MainWindow", "Encryption key request queued.")
+ 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", "Need to do work to send message. Work is queued.")
+ 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 == '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(Qt.UserRole, 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):
+ font = QFont()
+ font.setBold(True)
+ if tableWidget == self.ui.tableWidgetInboxSubscriptions:
+ acct = accountClass(fromAddress)
+ else:
+ acct = accountClass(toAddress)
+ subject = shared.fixPotentiallyInvalidUTF8Data(subject)
+ acct.parseMessage(toAddress, fromAddress, subject, "")
+
+ items = []
+ #to
+ to_item = QtGui.QTableWidgetItem(unicode(acct.toLabel, 'utf-8'))
+ to_item.setToolTip(unicode(acct.toLabel, 'utf-8') + " (" + str(acct.toAddress) + ")")
+ to_item.setFlags(
+ QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
+ if not read:
+ to_item.setFont(font)
+ to_item.setData(Qt.UserRole, str(toAddress))
+ to_item.setTextColor(AccountColor(toAddress).accountColor())
+ to_item.setIcon(avatarize(toAddress))
+ items.append(to_item)
+ # from
+ from_item = QtGui.QTableWidgetItem(unicode(acct.fromLabel, 'utf-8'))
+ from_item.setToolTip(unicode(acct.fromLabel, 'utf-8') + " (" + str(fromAddress) + ")")
+ from_item.setFlags(
+ QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
+ if not read:
+ from_item.setFont(font)
+ from_item.setData(Qt.UserRole, str(fromAddress))
+ from_item.setTextColor(AccountColor(fromAddress).accountColor())
+ from_item.setIcon(avatarize(fromAddress))
+ items.append(from_item)
+ # subject
+ subject_item = QtGui.QTableWidgetItem(unicode(acct.subject, 'utf-8'))
+ subject_item.setToolTip(unicode(acct.subject, 'utf-8'))
+ subject_item.setData(Qt.UserRole, str(subject))
+ subject_item.setFlags(
+ QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
+ if not read:
+ subject_item.setFont(font)
+ items.append(subject_item)
+ # time received
+ time_item = myTableWidgetItem(l10n.formatTimestamp(received))
+ time_item.setToolTip(l10n.formatTimestamp(received))
+ time_item.setData(Qt.UserRole, 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
# Load Sent items from database
- def loadSent(self, where="", what=""):
+ def loadSent(self, tableWidget, account, where="", what=""):
what = "%" + what + "%"
- if where == "To":
+ if where == _translate("MainWindow", "To"):
where = "toaddress"
- elif where == "From":
+ elif where == _translate("MainWindow", "From"):
where = "fromaddress"
- elif where == "Subject":
+ elif where == _translate("MainWindow", "Subject"):
where = "subject"
- elif where == "Message":
+ elif where == _translate("MainWindow", "Message"):
where = "message"
else:
where = "toaddress || fromaddress || subject || message"
+ tableWidget.setSortingEnabled(False)
+
+ if tableWidget == self.ui.tableWidgetInboxChans or tableWidget == self.ui.tableWidgetInboxSubscriptions:
+ tableWidget.setColumnHidden(0, True)
+ tableWidget.setColumnHidden(1, False)
+ xAddress = 'toaddress'
+ else:
+ tableWidget.setColumnHidden(0, False)
+ tableWidget.setColumnHidden(1, True)
+ xAddress = 'fromaddress'
+
sqlStatement = '''
SELECT toaddress, fromaddress, subject, status, ackdata, lastactiontime
- FROM sent WHERE folder="sent" AND %s LIKE ?
+ FROM sent WHERE ''' + xAddress + '''=? AND folder="sent" AND %s LIKE ?
ORDER BY lastactiontime
''' % (where,)
- while self.ui.tableWidgetSent.rowCount() > 0:
- self.ui.tableWidgetSent.removeRow(0)
-
- queryreturn = sqlQuery(sqlStatement, what)
+ tableWidget.setRowCount(0)
+ acct = None
+ queryreturn = sqlQuery(sqlStatement, account, what)
for row in queryreturn:
toAddress, fromAddress, subject, status, ackdata, lastactiontime = row
- subject = shared.fixPotentiallyInvalidUTF8Data(subject)
+ self.addMessageListItemSent(tableWidget, toAddress, fromAddress, subject, status, ackdata, lastactiontime)
- if shared.config.has_section(fromAddress):
- fromLabel = shared.config.get(fromAddress, 'label')
+ tableWidget.setSortingEnabled(False)
+ tableWidget.horizontalHeader().setSortIndicator(3, Qt.DescendingOrder)
+ tableWidget.keyPressEvent = self.tableWidgetSentKeyPressEvent
+
+ # Load messages from database file
+ def loadMessagelist(self, tableWidget, account, folder="inbox", where="", what="", unreadOnly = False):
+ if folder == 'sent':
+ self.loadSent(tableWidget, account, where, what)
+ return
+
+ if what != "":
+ what = "%" + what + "%"
+ if where == _translate("MainWindow", "To"):
+ where = "toaddress"
+ elif where == _translate("MainWindow", "From"):
+ where = "fromaddress"
+ elif where == _translate("MainWindow", "Subject"):
+ where = "subject"
+ elif where == _translate("MainWindow", "Message"):
+ where = "message"
else:
- fromLabel = fromAddress
-
- toLabel = ''
- queryreturn = sqlQuery(
- '''select label from addressbook where address=?''', toAddress)
- if queryreturn != []:
- for row in queryreturn:
- toLabel, = row
- if toLabel == '':
- # It might be a broadcast message. We should check for that
- # label.
- queryreturn = sqlQuery(
- '''select label from subscriptions where address=?''', toAddress)
-
- if queryreturn != []:
- for row in queryreturn:
- toLabel, = row
-
- if toLabel == '':
- if shared.config.has_section(toAddress):
- toLabel = shared.config.get(toAddress, 'label')
- if toLabel == '':
- toLabel = toAddress
-
- self.ui.tableWidgetSent.insertRow(0)
- toAddressItem = QtGui.QTableWidgetItem(unicode(toLabel, 'utf-8'))
- toAddressItem.setToolTip(unicode(toLabel, 'utf-8'))
- toAddressItem.setIcon(avatarize(toAddress))
- toAddressItem.setData(Qt.UserRole, str(toAddress))
- toAddressItem.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- self.ui.tableWidgetSent.setItem(0, 0, toAddressItem)
-
- if fromLabel == '':
- fromLabel = fromAddress
- fromAddressItem = QtGui.QTableWidgetItem(unicode(fromLabel, 'utf-8'))
- fromAddressItem.setToolTip(unicode(fromLabel, 'utf-8'))
- fromAddressItem.setIcon(avatarize(fromAddress))
- fromAddressItem.setData(Qt.UserRole, str(fromAddress))
- fromAddressItem.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- self.ui.tableWidgetSent.setItem(0, 1, fromAddressItem)
-
- subjectItem = QtGui.QTableWidgetItem(unicode(subject, 'utf-8'))
- subjectItem.setToolTip(unicode(subject, 'utf-8'))
- subjectItem.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- self.ui.tableWidgetSent.setItem(0, 2, subjectItem)
-
- if status == 'awaitingpubkey':
- statusText = _translate(
- "MainWindow", "Waiting for their encryption key. Will request it again soon.")
- elif status == 'doingpowforpubkey':
- statusText = _translate(
- "MainWindow", "Encryption key request queued.")
- 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", "Need to do work to send message. Work is queued.")
- 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 == '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(Qt.UserRole, QByteArray(ackdata))
- newItem.setData(33, int(lastactiontime))
- newItem.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- self.ui.tableWidgetSent.setItem(0, 3, newItem)
- self.ui.tableWidgetSent.sortItems(3, Qt.DescendingOrder)
- self.ui.tableWidgetSent.keyPressEvent = self.tableWidgetSentKeyPressEvent
-
- # Load inbox from messages database file
- def loadInbox(self, where="", what=""):
- what = "%" + what + "%"
- if where == "To":
- where = "toaddress"
- elif where == "From":
- where = "fromaddress"
- elif where == "Subject":
- where = "subject"
- elif where == "Message":
- where = "message"
+ where = "toaddress || fromaddress || subject || message"
else:
- where = "toaddress || fromaddress || subject || message"
+ what = None
+
+ if tableWidget == self.ui.tableWidgetInboxSubscriptions:
+ xAddress = "fromaddress"
+ else:
+ xAddress = "toaddress"
+ sqlStatementBase = '''SELECT folder, msgid, toaddress, fromaddress, subject, received, read
+ FROM inbox '''
+ sqlStatementParts = []
+ sqlArguments = []
+ if account is not None:
+ sqlStatementParts.append(xAddress + " = ? ")
+ sqlArguments.append(account)
+ if folder is not None:
+ sqlStatementParts.append("folder = ? ")
+ sqlArguments.append(folder)
+ if what is not None:
+ sqlStatementParts.append("%s LIKE ?" % (where))
+ sqlArguments.append(what)
+ if unreadOnly:
+ sqlStatementParts.append("read = 0")
+ if len(sqlStatementParts) > 0:
+ sqlStatementBase += "WHERE " + " AND ".join(sqlStatementParts)
+ queryreturn = sqlQuery(sqlStatementBase, sqlArguments)
- sqlStatement = '''
- SELECT msgid, toaddress, fromaddress, subject, received, read
- FROM inbox WHERE folder="inbox" AND %s LIKE ?
- ORDER BY received
- ''' % (where,)
-
- while self.ui.tableWidgetInbox.rowCount() > 0:
- self.ui.tableWidgetInbox.removeRow(0)
-
- font = QFont()
- font.setBold(True)
- queryreturn = sqlQuery(sqlStatement, what)
+ tableWidget.setRowCount(0)
+ if account is not None:
+ tableWidget.setColumnHidden(0, True)
+ tableWidget.setColumnHidden(1, False)
+ else:
+ tableWidget.setColumnHidden(0, False)
+ tableWidget.setColumnHidden(1, False)
+ tableWidget.setSortingEnabled(False)
+
for row in queryreturn:
- msgid, toAddress, fromAddress, subject, received, read = row
- subject = shared.fixPotentiallyInvalidUTF8Data(subject)
- try:
- if toAddress == self.str_broadcast_subscribers:
- toLabel = self.str_broadcast_subscribers
- else:
- toLabel = shared.config.get(toAddress, 'label')
- except:
- toLabel = ''
- if toLabel == '':
- toLabel = toAddress
+ msgfolder, msgid, toAddress, fromAddress, subject, received, read = row
+ self.addMessageListItemInbox(tableWidget, msgfolder, msgid, toAddress, fromAddress, subject, received, read)
- fromLabel = ''
- if shared.config.has_section(fromAddress):
- fromLabel = shared.config.get(fromAddress, 'label')
-
- if fromLabel == '': # If the fromAddress isn't one of our addresses and isn't a chan
- queryreturn = sqlQuery(
- '''select label from addressbook where address=?''', fromAddress)
- if queryreturn != []:
- for row in queryreturn:
- fromLabel, = row
-
- if fromLabel == '': # If this address wasn't in our address book...
- queryreturn = sqlQuery(
- '''select label from subscriptions where address=?''', fromAddress)
- if queryreturn != []:
- for row in queryreturn:
- fromLabel, = row
- if fromLabel == '':
- fromLabel = fromAddress
-
- # message row
- self.ui.tableWidgetInbox.insertRow(0)
- # to
- to_item = QtGui.QTableWidgetItem(unicode(toLabel, 'utf-8'))
- to_item.setToolTip(unicode(toLabel, 'utf-8'))
- to_item.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- if not read:
- to_item.setFont(font)
- to_item.setData(Qt.UserRole, str(toAddress))
- if shared.safeConfigGetBoolean(toAddress, 'mailinglist'):
- to_item.setTextColor(QtGui.QColor(137, 04, 177)) # magenta
- if shared.safeConfigGetBoolean(str(toAddress), 'chan'):
- to_item.setTextColor(QtGui.QColor(216, 119, 0)) # orange
- to_item.setIcon(avatarize(toAddress))
- self.ui.tableWidgetInbox.setItem(0, 0, to_item)
- # from
- from_item = QtGui.QTableWidgetItem(unicode(fromLabel, 'utf-8'))
- from_item.setToolTip(unicode(fromLabel, 'utf-8'))
- from_item.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- if not read:
- from_item.setFont(font)
- from_item.setData(Qt.UserRole, str(fromAddress))
- if shared.safeConfigGetBoolean(str(fromAddress), 'chan'):
- from_item.setTextColor(QtGui.QColor(216, 119, 0)) # orange
- from_item.setIcon(avatarize(fromAddress))
- self.ui.tableWidgetInbox.setItem(0, 1, from_item)
- # subject
- subject_item = QtGui.QTableWidgetItem(unicode(subject, 'utf-8'))
- subject_item.setToolTip(unicode(subject, 'utf-8'))
- subject_item.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- if not read:
- subject_item.setFont(font)
- self.ui.tableWidgetInbox.setItem(0, 2, subject_item)
- # time received
- time_item = myTableWidgetItem(l10n.formatTimestamp(received))
- time_item.setToolTip(l10n.formatTimestamp(received))
- time_item.setData(Qt.UserRole, QByteArray(msgid))
- time_item.setData(33, int(received))
- time_item.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- if not read:
- time_item.setFont(font)
- self.ui.tableWidgetInbox.setItem(0, 3, time_item)
-
- self.ui.tableWidgetInbox.sortItems(3, Qt.DescendingOrder)
- self.ui.tableWidgetInbox.keyPressEvent = self.tableWidgetInboxKeyPressEvent
+ tableWidget.horizontalHeader().setSortIndicator(3, Qt.DescendingOrder)
+ tableWidget.setSortingEnabled(True)
+ tableWidget.keyPressEvent = self.tableWidgetInboxKeyPressEvent
# create application indicator
def appIndicatorInit(self, app):
@@ -1065,11 +1230,11 @@ class MyForm(QtGui.QMainWindow):
actionSubscribe.triggered.connect(self.appIndicatorSubscribe)
m.addAction(actionSubscribe)
- # Address book
- actionAddressBook = QtGui.QAction(_translate(
- "MainWindow", "Address Book"), m, checkable=False)
- actionAddressBook.triggered.connect(self.appIndicatorAddressBook)
- m.addAction(actionAddressBook)
+ # Channels
+ actionSubscribe = QtGui.QAction(_translate(
+ "MainWindow", "Channel"), m, checkable=False)
+ actionSubscribe.triggered.connect(self.appIndicatorChannel)
+ m.addAction(actionSubscribe)
# separator
actionSeparator = QtGui.QAction('', m, checkable=False)
@@ -1115,7 +1280,7 @@ class MyForm(QtGui.QMainWindow):
for row in queryreturn:
toAddress, read = row
if not read:
- if toAddress == self.str_broadcast_subscribers:
+ if toAddress == str_broadcast_subscribers:
if self.mmapp.has_source("Subscriptions"):
self.mmapp.remove_source("Subscriptions")
else:
@@ -1133,8 +1298,8 @@ class MyForm(QtGui.QMainWindow):
msgid, toAddress, read = row
try:
- if toAddress == self.str_broadcast_subscribers:
- toLabel = self.str_broadcast_subscribers
+ if toAddress == str_broadcast_subscribers:
+ toLabel = str_broadcast_subscribers
else:
toLabel = shared.config.get(toAddress, 'label')
except:
@@ -1143,7 +1308,7 @@ class MyForm(QtGui.QMainWindow):
toLabel = toAddress
if not read:
- if toLabel == self.str_broadcast_subscribers:
+ if toLabel == str_broadcast_subscribers:
# increment the unread subscriptions
unreadSubscriptions = unreadSubscriptions + 1
else:
@@ -1179,7 +1344,7 @@ class MyForm(QtGui.QMainWindow):
# has messageing menu been installed
if not withMessagingMenu:
- print 'WARNING: MessagingMenu is not available. Is libmessaging-menu-dev installed?'
+ logger.warning('WARNING: MessagingMenu is not available. Is libmessaging-menu-dev installed?')
return
# create the menu server
@@ -1192,7 +1357,7 @@ class MyForm(QtGui.QMainWindow):
self.ubuntuMessagingMenuUnread(True)
except Exception:
withMessagingMenu = False
- print 'WARNING: messaging menu disabled'
+ logger.warning('WARNING: messaging menu disabled')
# update the Ubuntu messaging menu
def ubuntuMessagingMenuUpdate(self, drawAttention, newItem, toLabel):
@@ -1204,11 +1369,11 @@ class MyForm(QtGui.QMainWindow):
# has messageing menu been installed
if not withMessagingMenu:
- print 'WARNING: messaging menu disabled or libmessaging-menu-dev not installed'
+ logger.warning('WARNING: messaging menu disabled or libmessaging-menu-dev not installed')
return
# remember this item to that the messaging menu can find it
- if toLabel == self.str_broadcast_subscribers:
+ if toLabel == str_broadcast_subscribers:
self.newBroadcastItem = newItem
else:
self.newMessageItem = newItem
@@ -1298,7 +1463,7 @@ class MyForm(QtGui.QMainWindow):
stdout=subprocess.PIPE)
gst_available=True
except:
- print "WARNING: gst123 must be installed in order to play mp3 sounds"
+ logger.warning("WARNING: gst123 must be installed in order to play mp3 sounds")
if not gst_available:
try:
subprocess.call(["mpg123", soundFilename],
@@ -1306,14 +1471,14 @@ class MyForm(QtGui.QMainWindow):
stdout=subprocess.PIPE)
gst_available=True
except:
- print "WARNING: mpg123 must be installed in order to play mp3 sounds"
+ logger.warning("WARNING: mpg123 must be installed in order to play mp3 sounds")
else:
try:
subprocess.call(["aplay", soundFilename],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
except:
- print "WARNING: aplay must be installed in order to play WAV sounds"
+ logger.warning("WARNING: aplay must be installed in order to play WAV sounds")
elif sys.platform[0:3] == 'win':
# use winsound on Windows
import winsound
@@ -1346,16 +1511,19 @@ class MyForm(QtGui.QMainWindow):
else:
self.tray.showMessage(title, subtitle, 1, 2000)
+ # set delete key in inbox
def tableWidgetInboxKeyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Delete:
self.on_action_InboxTrash()
- return QtGui.QTableWidget.keyPressEvent(self.ui.tableWidgetInbox, event)
+ return QtGui.QTableWidget.keyPressEvent(self.getCurrentMessagelist(), event)
+ # set delete key in inbox
def tableWidgetSentKeyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Delete:
self.on_action_SentTrash()
- return QtGui.QTableWidget.keyPressEvent(self.ui.tableWidgetSent, event)
+ return QtGui.QTableWidget.keyPressEvent(self.getCurrentMessagelist(), event)
+ # menu button 'manage keys'
def click_actionManageKeys(self):
if 'darwin' in sys.platform or 'linux' in sys.platform:
if shared.appdata == '':
@@ -1379,11 +1547,23 @@ class MyForm(QtGui.QMainWindow):
if reply == QtGui.QMessageBox.Yes:
shared.openKeysFile()
+ # menu button 'delete all treshed messages'
def click_actionDeleteAllTrashedMessages(self):
if QtGui.QMessageBox.question(self, _translate("MainWindow", "Delete trash?"), _translate("MainWindow", "Are you sure you want to delete all trashed messages?"), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) == QtGui.QMessageBox.No:
return
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")
+
+ # menu botton 'regenerate deterministic addresses'
def click_actionRegenerateDeterministicAddresses(self):
self.regenerateAddressesDialogInstance = regenerateAddressesDialog(
self)
@@ -1409,6 +1589,7 @@ class MyForm(QtGui.QMainWindow):
), self.regenerateAddressesDialogInstance.ui.lineEditPassphrase.text().toUtf8(), self.regenerateAddressesDialogInstance.ui.checkBoxEighteenByteRipe.isChecked()))
self.ui.tabWidget.setCurrentIndex(3)
+ # opens 'join chan' dialog
def click_actionJoinChan(self):
self.newChanDialogInstance = newChanDialog(self)
if self.newChanDialogInstance.exec_():
@@ -1420,7 +1601,7 @@ class MyForm(QtGui.QMainWindow):
shared.apiAddressGeneratorReturnQueue.queue.clear()
shared.addressGeneratorQueue.put(('createChan', 4, 1, self.str_chan + ' ' + str(self.newChanDialogInstance.ui.lineEditChanNameCreate.text().toUtf8()), self.newChanDialogInstance.ui.lineEditChanNameCreate.text().toUtf8()))
addressGeneratorReturnValue = shared.apiAddressGeneratorReturnQueue.get()
- print 'addressGeneratorReturnValue', addressGeneratorReturnValue
+ logger.debug('addressGeneratorReturnValue ' + str(addressGeneratorReturnValue))
if len(addressGeneratorReturnValue) == 0:
QMessageBox.about(self, _translate("MainWindow", "Address already present"), _translate(
"MainWindow", "Could not add chan because it appears to already be one of your identities."))
@@ -1445,7 +1626,7 @@ class MyForm(QtGui.QMainWindow):
shared.apiAddressGeneratorReturnQueue.queue.clear()
shared.addressGeneratorQueue.put(('joinChan', addBMIfNotPresent(self.newChanDialogInstance.ui.lineEditChanBitmessageAddress.text()), self.str_chan + ' ' + str(self.newChanDialogInstance.ui.lineEditChanNameJoin.text().toUtf8()), self.newChanDialogInstance.ui.lineEditChanNameJoin.text().toUtf8()))
addressGeneratorReturnValue = shared.apiAddressGeneratorReturnQueue.get()
- print 'addressGeneratorReturnValue', addressGeneratorReturnValue
+ logger.debug('addressGeneratorReturnValue ' + str(addressGeneratorReturnValue))
if addressGeneratorReturnValue == 'chan name does not match address':
QMessageBox.about(self, _translate("MainWindow", "Address does not match chan name"), _translate(
"MainWindow", "Although the Bitmessage address you entered was valid, it doesn\'t match the chan name."))
@@ -1458,6 +1639,7 @@ class MyForm(QtGui.QMainWindow):
QMessageBox.about(self, _translate("MainWindow", "Success"), _translate(
"MainWindow", "Successfully joined chan. "))
self.ui.tabWidget.setCurrentIndex(3)
+ self.rerenderAddressBook()
def showConnectDialog(self):
self.connectDialogInstance = connectDialog(self)
@@ -1468,11 +1650,18 @@ class MyForm(QtGui.QMainWindow):
else:
self.click_actionSettings()
+ def showMigrationWizard(self, level):
+ self.migrationWizardInstance = Ui_MigrationWizard(["a"])
+ if self.migrationWizardInstance.exec_():
+ pass
+ else:
+ pass
+
def changeEvent(self, event):
if event.type() == QtCore.QEvent.LanguageChange:
self.ui.retranslateUi(self)
self.init_inbox_popup_menu(False)
- self.init_identities_popup_menu(False)
+ self.init_chan_popup_menu(False)
self.init_addressbook_popup_menu(False)
self.init_subscriptions_popup_menu(False)
self.init_sent_popup_menu(False)
@@ -1480,9 +1669,7 @@ class MyForm(QtGui.QMainWindow):
if event.type() == QtCore.QEvent.WindowStateChange:
if self.windowState() & QtCore.Qt.WindowMinimized:
if shared.config.getboolean('bitmessagesettings', 'minimizetotray') and not 'darwin' in sys.platform:
- self.appIndicatorHide()
- if 'win32' in sys.platform or 'win64' in sys.platform:
- self.setWindowFlags(Qt.ToolTip)
+ QTimer.singleShot(0, self.appIndicatorHide)
elif event.oldState() & QtCore.Qt.WindowMinimized:
# The window state has just been changed to
# Normal/Maximised/FullScreen
@@ -1496,14 +1683,17 @@ class MyForm(QtGui.QMainWindow):
self.appIndicatorShowOrHideWindow()
def updateNumberOfMessagesProcessed(self):
+ self.ui.labelSyncStatus.setText(_translate("MainWindow", "Objects to be synced: %1").arg(str(sum(shared.numberOfObjectsThatWeHaveYetToGetPerPeer.itervalues()))))
self.ui.labelMessageCount.setText(_translate(
"MainWindow", "Processed %1 person-to-person messages.").arg(str(shared.numberOfMessagesProcessed)))
def updateNumberOfBroadcastsProcessed(self):
+ self.ui.labelSyncStatus.setText(_translate("MainWindow", "Objects to be synced: %1").arg(str(sum(shared.numberOfObjectsThatWeHaveYetToGetPerPeer.itervalues()))))
self.ui.labelBroadcastCount.setText(_translate(
"MainWindow", "Processed %1 broadcast messages.").arg(str(shared.numberOfBroadcastsProcessed)))
def updateNumberOfPubkeysProcessed(self):
+ self.ui.labelSyncStatus.setText(_translate("MainWindow", "Objects to be synced: %1").arg(str(sum(shared.numberOfObjectsThatWeHaveYetToGetPerPeer.itervalues()))))
self.ui.labelPubkeyCount.setText(_translate(
"MainWindow", "Processed %1 public keys.").arg(str(shared.numberOfPubkeysProcessed)))
@@ -1533,7 +1723,6 @@ class MyForm(QtGui.QMainWindow):
shared.numberOfBytesSent = 0
def updateNetworkStatusTab(self):
- # print 'updating network status tab'
totalNumberOfConnectionsFromAllStreams = 0 # One would think we could use len(sendDataQueues) for this but the number doesn't always match: just because we have a sendDataThread running doesn't mean that the connection has been fully established (with the exchange of version messages).
streamNumberTotals = {}
for host, streamNumber in shared.connectedHostsList.items():
@@ -1684,60 +1873,107 @@ class MyForm(QtGui.QMainWindow):
def drawTrayIcon(self, iconFileName, inboxUnreadCount):
self.tray.setIcon(self.calcTrayIcon(iconFileName, inboxUnreadCount))
- def changedInboxUnread(self):
+ def changedInboxUnread(self, row = None):
self.drawTrayIcon(self.currentTrayIconFileName, self.findInboxUnreadCount())
+ self.rerenderTabTreeMessages()
+ self.rerenderTabTreeSubscriptions()
+ self.rerenderTabTreeChans()
- def findInboxUnreadCount(self):
- queryreturn = sqlQuery('''SELECT count(*) from inbox WHERE folder='inbox' and read=0''')
- cnt = 0
- for row in queryreturn:
- cnt, = row
- return int(cnt)
+ def findInboxUnreadCount(self, count = None):
+ 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
def updateSentItemStatusByToAddress(self, toAddress, textToDisplay):
- for i in range(self.ui.tableWidgetSent.rowCount()):
- rowAddress = str(self.ui.tableWidgetSent.item(
- i, 0).data(Qt.UserRole).toPyObject())
- if toAddress == rowAddress:
- self.ui.tableWidgetSent.item(i, 3).setToolTip(textToDisplay)
- try:
- newlinePosition = textToDisplay.indexOf('\n')
- except: # If someone misses adding a "_translate" to a string before passing it to this function, this function won't receive a qstring which will cause an exception.
- newlinePosition = 0
- if newlinePosition > 1:
- self.ui.tableWidgetSent.item(i, 3).setText(
- textToDisplay[:newlinePosition])
- else:
- self.ui.tableWidgetSent.item(i, 3).setText(textToDisplay)
+ 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 = str(sent.item(
+ i, 0).data(Qt.UserRole).toPyObject())
+ if toAddress == rowAddress:
+ sent.item(i, 3).setToolTip(textToDisplay)
+ try:
+ newlinePosition = textToDisplay.indexOf('\n')
+ except: # If someone misses adding a "_translate" to a string before passing it to this function, this function won't receive a qstring which will cause an exception.
+ newlinePosition = 0
+ if newlinePosition > 1:
+ sent.item(i, 3).setText(
+ textToDisplay[:newlinePosition])
+ else:
+ sent.item(i, 3).setText(textToDisplay)
def updateSentItemStatusByAckdata(self, ackdata, textToDisplay):
- for i in range(self.ui.tableWidgetSent.rowCount()):
- toAddress = str(self.ui.tableWidgetSent.item(
- i, 0).data(Qt.UserRole).toPyObject())
- tableAckdata = self.ui.tableWidgetSent.item(
- i, 3).data(Qt.UserRole).toPyObject()
- status, addressVersionNumber, streamNumber, ripe = decodeAddress(
- toAddress)
- if ackdata == tableAckdata:
- self.ui.tableWidgetSent.item(i, 3).setToolTip(textToDisplay)
- try:
- newlinePosition = textToDisplay.indexOf('\n')
- except: # If someone misses adding a "_translate" to a string before passing it to this function, this function won't receive a qstring which will cause an exception.
- newlinePosition = 0
- if newlinePosition > 1:
- self.ui.tableWidgetSent.item(i, 3).setText(
- textToDisplay[:newlinePosition])
- else:
- self.ui.tableWidgetSent.item(i, 3).setText(textToDisplay)
+ 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 = str(sent.item(
+ i, 0).data(Qt.UserRole).toPyObject())
+ tableAckdata = sent.item(
+ i, 3).data(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 someone misses adding a "_translate" to a string before passing it to this function, this function won't receive a qstring which will cause an exception.
+ newlinePosition = 0
+ if newlinePosition > 1:
+ sent.item(i, 3).setText(
+ textToDisplay[:newlinePosition])
+ else:
+ sent.item(i, 3).setText(textToDisplay)
def removeInboxRowByMsgid(self, msgid): # msgid and inventoryHash are the same thing
- for i in range(self.ui.tableWidgetInbox.rowCount()):
- if msgid == str(self.ui.tableWidgetInbox.item(i, 3).data(Qt.UserRole).toPyObject()):
- self.statusBar().showMessage(_translate(
- "MainWindow", "Message trashed"))
- self.ui.tableWidgetInbox.removeRow(i)
- break
- self.changedInboxUnread()
+ 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(Qt.UserRole).toPyObject()):
+ self.statusBar().showMessage(_translate(
+ "MainWindow", "Message trashed"))
+ treeWidget = self.widgetConvert(inbox)
+ self.propagateUnreadCount(str(inbox.item(i, 1 if inbox == self.ui.tableWidgetInboxSubscriptions else 0).data(Qt.UserRole).toPyObject()), self.getCurrentFolder(treeWidget), treeWidget, 0)
+ inbox.removeRow(i)
+ break
+
+ def newVersionAvailable(self, version):
+# if (not (self.windowState() & QtCore.Qt.WindowActive)) or (self.windowState() & QtCore.Qt.WindowMinimized):
+# return
+ # only notify once until next restart
+ try:
+ if self.notifiedNewVersion:
+ return
+ except AttributeError:
+ pass
+
+ self.notifiedNewVersion = ".".join(str(n) for n in version)
+ message = "New "
+ if version[1] % 2:
+ message += "UNSTABLE"
+ else:
+ message += "stable"
+ message += " version of PyBitmessage is available: " + self.notifiedNewVersion + ". Download it from https://github.com/"
+ if version[0] == 0 and version[1] == 5:
+ message += "mailchuck"
+ else:
+ message += "Bitmessage"
+ message += "/PyBitmessage/releases/latest"
+ self.displayAlert("New release of PyBitmessage available", message, False)
def displayAlert(self, title, text, exitAfterUserClicksOk):
self.statusBar().showMessage(text)
@@ -1809,22 +2045,22 @@ class MyForm(QtGui.QMainWindow):
i, 0).setTextColor(QApplication.palette().text().color())
def rerenderSentFromLabels(self):
- for i in range(self.ui.tableWidgetSent.rowCount()):
- fromAddress = str(self.ui.tableWidgetSent.item(
+ for i in range(self.ui.tableWidgetInbox.rowCount()):
+ fromAddress = str(self.ui.tableWidgetInbox.item(
i, 1).data(Qt.UserRole).toPyObject())
# Message might be from an address we own like a chan address. Let's look for that label.
if shared.config.has_section(fromAddress):
fromLabel = shared.config.get(fromAddress, 'label')
else:
fromLabel = fromAddress
- self.ui.tableWidgetSent.item(
+ self.ui.tableWidgetInbox.item(
i, 1).setText(unicode(fromLabel, 'utf-8'))
- self.ui.tableWidgetSent.item(
+ self.ui.tableWidgetInbox.item(
i, 1).setIcon(avatarize(fromAddress))
def rerenderSentToLabels(self):
- for i in range(self.ui.tableWidgetSent.rowCount()):
- addressToLookup = str(self.ui.tableWidgetSent.item(
+ for i in range(self.ui.tableWidgetInbox.rowCount()):
+ addressToLookup = str(self.ui.tableWidgetInbox.item(
i, 0).data(Qt.UserRole).toPyObject())
toLabel = ''
queryreturn = sqlQuery(
@@ -1839,40 +2075,46 @@ class MyForm(QtGui.QMainWindow):
toLabel = shared.config.get(addressToLookup, 'label')
if toLabel == '':
toLabel = addressToLookup
- self.ui.tableWidgetSent.item(
+ self.ui.tableWidgetInbox.item(
i, 0).setText(unicode(toLabel, 'utf-8'))
def rerenderAddressBook(self):
+ def addRow (address, label, type):
+ self.ui.tableWidgetAddressBook.insertRow(0)
+ newItem = Ui_AddressBookWidgetItemLabel(address, unicode(label, 'utf-8'), type)
+ newItem.setData(Qt.UserRole, type)
+ self.ui.tableWidgetAddressBook.setItem(0, 0, newItem)
+ newItem = Ui_AddressBookWidgetItemAddress(address, unicode(label, 'utf-8'), type)
+ self.ui.tableWidgetAddressBook.setItem(0, 1, newItem)
+
+ self.ui.tableWidgetAddressBook.setSortingEnabled(False)
self.ui.tableWidgetAddressBook.setRowCount(0)
+
+ # subscriptions
+ queryreturn = sqlQuery('SELECT label, address FROM subscriptions WHERE enabled = 1')
+ for row in queryreturn:
+ label, address = row
+ addRow(address, label, AccountMixin.SUBSCRIPTION)
+
+ # chans
+ addresses = getSortedAccounts()
+ for address in addresses:
+ account = accountClass(address)
+ if (account.type == AccountMixin.CHAN and shared.safeConfigGetBoolean(address, 'enabled')):
+ addRow(address, account.getLabel(), AccountMixin.CHAN)
+
+ # normal accounts
queryreturn = sqlQuery('SELECT * FROM addressbook')
for row in queryreturn:
label, address = row
- self.ui.tableWidgetAddressBook.insertRow(0)
- newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8'))
- newItem.setIcon(avatarize(address))
- self.ui.tableWidgetAddressBook.setItem(0, 0, newItem)
- newItem = QtGui.QTableWidgetItem(address)
- newItem.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- self.ui.tableWidgetAddressBook.setItem(0, 1, newItem)
+ addRow(address, label, AccountMixin.NORMAL)
+
+ # sort
+ self.ui.tableWidgetAddressBook.sortItems(0, QtCore.Qt.AscendingOrder)
+ self.ui.tableWidgetAddressBook.setSortingEnabled(True)
def rerenderSubscriptions(self):
- self.ui.tableWidgetSubscriptions.setRowCount(0)
- queryreturn = sqlQuery('SELECT label, address, enabled FROM subscriptions')
- for row in queryreturn:
- label, address, enabled = row
- self.ui.tableWidgetSubscriptions.insertRow(0)
- newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8'))
- if not enabled:
- newItem.setTextColor(QtGui.QColor(128, 128, 128))
- newItem.setIcon(avatarize(address))
- self.ui.tableWidgetSubscriptions.setItem(0, 0, newItem)
- newItem = QtGui.QTableWidgetItem(address)
- newItem.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- if not enabled:
- newItem.setTextColor(QtGui.QColor(128, 128, 128))
- self.ui.tableWidgetSubscriptions.setItem(0, 1, newItem)
+ self.rerenderTabTreeSubscriptions()
def rerenderBlackWhiteList(self):
self.ui.tableWidgetBlacklist.setRowCount(0)
@@ -1898,18 +2140,33 @@ class MyForm(QtGui.QMainWindow):
def click_pushButtonTTL(self):
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."), QMessageBox.Ok)
+ "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."""), QMessageBox.Ok)
def click_pushButtonSend(self):
self.statusBar().showMessage('')
- toAddresses = str(self.ui.lineEditTo.text())
- fromAddress = str(self.ui.labelFrom.text())
- subject = str(self.ui.lineEditSubject.text().toUtf8())
- message = str(
- self.ui.textEditMessage.document().toPlainText().toUtf8())
+
+ if self.ui.tabWidgetSend.currentIndex() == 0:
+ # message to specific people
+ sendMessageToPeople = True
+ fromAddress = str(self.ui.comboBoxSendFrom.itemData(
+ self.ui.comboBoxSendFrom.currentIndex(),
+ Qt.UserRole).toString())
+ toAddresses = str(self.ui.lineEditTo.text())
+ subject = str(self.ui.lineEditSubject.text().toUtf8())
+ message = str(
+ self.ui.textEditMessage.document().toPlainText().toUtf8())
+ else:
+ # broadcast message
+ sendMessageToPeople = False
+ fromAddress = str(self.ui.comboBoxSendFromBroadcast.itemData(
+ self.ui.comboBoxSendFromBroadcast.currentIndex(),
+ Qt.UserRole).toString())
+ subject = str(self.ui.lineEditSubjectBroadcast.text().toUtf8())
+ message = str(
+ self.ui.textEditMessageBroadcast.document().toPlainText().toUtf8())
"""
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
@@ -1921,18 +2178,38 @@ more work your computer must do to send the message. A Time-To-Live of four or f
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)))
return
- if self.ui.radioButtonSpecific.isChecked(): # To send a message to specific people (rather than broadcast)
+
+ acct = accountClass(fromAddress)
+
+ if sendMessageToPeople: # To send a message to specific people (rather than broadcast)
toAddressesList = [s.strip()
for s in toAddresses.replace(',', ';').split(';')]
toAddressesList = list(set(
toAddressesList)) # 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.
for toAddress in toAddressesList:
if toAddress != '':
+ if toAddress.find("@") >= 0:
+ if isinstance(acct, GatewayAccount):
+ acct.createMessage(toAddress, fromAddress, subject, message)
+ subject = acct.subject
+ toAddress = acct.toAddress
+ else:
+ 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)
+ shared.config.set(fromAddress, 'label', email)
+ shared.config.set(fromAddress, 'gateway', 'mailchuck')
+ shared.writeKeysFile()
+ self.statusBar().showMessage(_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':
- with shared.printLock:
- print 'Error: Could not decode', toAddress, ':', status
+ logger.error('Error: Could not decode ' + toAddress + ':' + status)
if status == 'missingbm':
self.statusBar().showMessage(_translate(
@@ -1963,6 +2240,7 @@ more work your computer must do to send the message. A Time-To-Live of four or f
"MainWindow", "Error: You must specify a From address. If you don\'t have one, go to the \'Your Identities\' tab."))
else:
toAddress = addBMIfNotPresent(toAddress)
+
if addressVersionNumber > 4 or addressVersionNumber <= 1:
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)))
@@ -2008,12 +2286,15 @@ more work your computer must do to send the message. A Time-To-Live of four or f
shared.workerQueue.put(('sendmessage', toAddress))
self.ui.comboBoxSendFrom.setCurrentIndex(0)
- self.ui.labelFrom.setText('')
self.ui.lineEditTo.setText('')
self.ui.lineEditSubject.setText('')
self.ui.textEditMessage.setText('')
- self.ui.tabWidget.setCurrentIndex(2)
- self.ui.tableWidgetSent.setCurrentCell(0, 0)
+ if self.replyFromTab is not None:
+ self.ui.tabWidget.setCurrentIndex(self.replyFromTab)
+ self.replyFromTab = None
+ self.statusBar().showMessage(_translate(
+ "MainWindow", "Message queued."))
+ #self.ui.tableWidgetInbox.setCurrentCell(0, 0)
else:
self.statusBar().showMessage(_translate(
"MainWindow", "Your \'To\' field is empty."))
@@ -2027,7 +2308,7 @@ more work your computer must do to send the message. A Time-To-Live of four or f
# this is a broadcast message, but we can use it to update the
# user interface when the POW is done generating.
ackdata = OpenSSL.rand(32)
- toAddress = self.str_broadcast_subscribers
+ toAddress = str_broadcast_subscribers
ripe = ''
t = ('', # msgid. We don't know what this will be until the POW is done.
toAddress,
@@ -2048,20 +2329,20 @@ more work your computer must do to send the message. A Time-To-Live of four or f
sqlExecute(
'''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', *t)
- toLabel = self.str_broadcast_subscribers
+ toLabel = str_broadcast_subscribers
self.displayNewSentMessage(
toAddress, toLabel, fromAddress, subject, message, ackdata)
shared.workerQueue.put(('sendbroadcast', ''))
- self.ui.comboBoxSendFrom.setCurrentIndex(0)
- self.ui.labelFrom.setText('')
- self.ui.lineEditTo.setText('')
- self.ui.lineEditSubject.setText('')
- self.ui.textEditMessage.setText('')
- self.ui.tabWidget.setCurrentIndex(2)
- self.ui.tableWidgetSent.setCurrentCell(0, 0)
+ self.ui.comboBoxSendFromBroadcast.setCurrentIndex(0)
+ self.ui.lineEditSubjectBroadcast.setText('')
+ self.ui.textEditMessageBroadcast.setText('')
+ self.ui.tabWidget.setCurrentIndex(1)
+ self.ui.tableWidgetInboxSubscriptions.setCurrentCell(0, 0)
+ self.statusBar().showMessage(_translate(
+ "MainWindow", "Broadcast queued."))
def click_pushButtonLoadFromAddressBook(self):
self.ui.tabWidget.setCurrentIndex(5)
@@ -2083,38 +2364,51 @@ more work your computer must do to send the message. A Time-To-Live of four or f
self.statusBar().showMessage(_translate(
"MainWindow", "Fetched address from namecoin identity."))
- def redrawLabelFrom(self, index):
- self.ui.labelFrom.setText(
- self.ui.comboBoxSendFrom.itemData(index).toPyObject())
- self.setBroadcastEnablementDependingOnWhetherThisIsAChanAddress(self.ui.comboBoxSendFrom.itemData(index).toPyObject())
-
- def setBroadcastEnablementDependingOnWhetherThisIsAChanAddress(self, address):
+ def setBroadcastEnablementDependingOnWhetherThisIsAMailingListAddress(self, address):
# If this is a chan then don't let people broadcast because no one
# should subscribe to chan addresses.
- if shared.safeConfigGetBoolean(str(address), 'chan'):
- self.ui.radioButtonSpecific.click()
- self.ui.radioButtonBroadcast.setEnabled(False)
+ if shared.safeConfigGetBoolean(str(address), 'mailinglist'):
+ self.ui.tabWidgetSend.setCurrentIndex(1)
else:
- self.ui.radioButtonBroadcast.setEnabled(True)
+ self.ui.tabWidgetSend.setCurrentIndex(0)
def rerenderComboBoxSendFrom(self):
self.ui.comboBoxSendFrom.clear()
- self.ui.labelFrom.setText('')
- configSections = shared.config.sections()
- for addressInKeysFile in configSections:
- if addressInKeysFile != 'bitmessagesettings':
- isEnabled = shared.config.getboolean(
- addressInKeysFile, 'enabled') # I realize that this is poor programming practice but I don't care. It's easier for others to read.
- if isEnabled:
- self.ui.comboBoxSendFrom.insertItem(0, avatarize(addressInKeysFile), unicode(shared.config.get(
- addressInKeysFile, 'label'), 'utf-8'), addressInKeysFile)
+ for addressInKeysFile in getSortedAccounts():
+ isEnabled = shared.config.getboolean(
+ addressInKeysFile, 'enabled') # I realize that this is poor programming practice but I don't care. It's easier for others to read.
+ isMaillinglist = shared.safeConfigGetBoolean(addressInKeysFile, 'mailinglist')
+ if isEnabled and not isMaillinglist:
+ self.ui.comboBoxSendFrom.addItem(avatarize(addressInKeysFile), unicode(shared.config.get(
+ addressInKeysFile, 'label'), 'utf-8'), addressInKeysFile)
+# self.ui.comboBoxSendFrom.model().sort(1, Qt.AscendingOrder)
+ for i in range(self.ui.comboBoxSendFrom.count()):
+ address = str(self.ui.comboBoxSendFrom.itemData(i, Qt.UserRole).toString())
+ self.ui.comboBoxSendFrom.setItemData(i, AccountColor(address).accountColor(), Qt.ForegroundRole)
self.ui.comboBoxSendFrom.insertItem(0, '', '')
if(self.ui.comboBoxSendFrom.count() == 2):
self.ui.comboBoxSendFrom.setCurrentIndex(1)
- self.redrawLabelFrom(self.ui.comboBoxSendFrom.currentIndex())
else:
self.ui.comboBoxSendFrom.setCurrentIndex(0)
+ def rerenderComboBoxSendFromBroadcast(self):
+ self.ui.comboBoxSendFromBroadcast.clear()
+ for addressInKeysFile in getSortedAccounts():
+ isEnabled = shared.config.getboolean(
+ addressInKeysFile, 'enabled') # I realize that this is poor programming practice but I don't care. It's easier for others to read.
+ isChan = shared.safeConfigGetBoolean(addressInKeysFile, 'chan')
+ if isEnabled and not isChan:
+ self.ui.comboBoxSendFromBroadcast.addItem(avatarize(addressInKeysFile), unicode(shared.config.get(
+ addressInKeysFile, 'label'), 'utf-8'), addressInKeysFile)
+ for i in range(self.ui.comboBoxSendFromBroadcast.count()):
+ address = str(self.ui.comboBoxSendFromBroadcast.itemData(i, Qt.UserRole).toString())
+ self.ui.comboBoxSendFromBroadcast.setItemData(i, AccountColor(address).accountColor(), Qt.ForegroundRole)
+ self.ui.comboBoxSendFromBroadcast.insertItem(0, '', '')
+ if(self.ui.comboBoxSendFromBroadcast.count() == 2):
+ self.ui.comboBoxSendFromBroadcast.setCurrentIndex(1)
+ else:
+ self.ui.comboBoxSendFromBroadcast.setCurrentIndex(0)
+
# 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
@@ -2122,116 +2416,45 @@ more work your computer must do to send the message. A Time-To-Live of four or f
def displayNewSentMessage(self, toAddress, toLabel, fromAddress, subject, message, ackdata):
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
message = shared.fixPotentiallyInvalidUTF8Data(message)
- try:
- fromLabel = shared.config.get(fromAddress, 'label')
- except:
- fromLabel = ''
- if fromLabel == '':
- fromLabel = fromAddress
-
- self.ui.tableWidgetSent.setSortingEnabled(False)
- self.ui.tableWidgetSent.insertRow(0)
- if toLabel == '':
- newItem = QtGui.QTableWidgetItem(unicode(toAddress, 'utf-8'))
- newItem.setToolTip(unicode(toAddress, 'utf-8'))
- else:
- newItem = QtGui.QTableWidgetItem(unicode(toLabel, 'utf-8'))
- newItem.setToolTip(unicode(toLabel, 'utf-8'))
- newItem.setData(Qt.UserRole, str(toAddress))
- newItem.setIcon(avatarize(toAddress))
- self.ui.tableWidgetSent.setItem(0, 0, newItem)
- if fromLabel == '':
- newItem = QtGui.QTableWidgetItem(unicode(fromAddress, 'utf-8'))
- newItem.setToolTip(unicode(fromAddress, 'utf-8'))
- else:
- newItem = QtGui.QTableWidgetItem(unicode(fromLabel, 'utf-8'))
- newItem.setToolTip(unicode(fromLabel, 'utf-8'))
- newItem.setData(Qt.UserRole, str(fromAddress))
- newItem.setIcon(avatarize(fromAddress))
- self.ui.tableWidgetSent.setItem(0, 1, newItem)
- newItem = QtGui.QTableWidgetItem(unicode(subject, 'utf-8)'))
- newItem.setToolTip(unicode(subject, 'utf-8)'))
- #newItem.setData(Qt.UserRole, unicode(message, 'utf-8)')) # No longer hold the message in the table; we'll use a SQL query to display it as needed.
- self.ui.tableWidgetSent.setItem(0, 2, newItem)
- # newItem = QtGui.QTableWidgetItem('Doing work necessary to send
- # broadcast...'+
- # l10n.formatTimestamp())
- newItem = myTableWidgetItem(_translate("MainWindow", "Work is queued. %1").arg(l10n.formatTimestamp()))
- newItem.setToolTip(_translate("MainWindow", "Work is queued. %1").arg(l10n.formatTimestamp()))
- newItem.setData(Qt.UserRole, QByteArray(ackdata))
- newItem.setData(33, int(time.time()))
- self.ui.tableWidgetSent.setItem(0, 3, newItem)
- self.ui.textEditSentMessage.setPlainText(unicode(message, 'utf-8)'))
- self.ui.tableWidgetSent.setSortingEnabled(True)
+ acct = accountClass(fromAddress)
+ acct.parseMessage(toAddress, fromAddress, subject, message)
+ for sent in [self.ui.tableWidgetInbox, self.ui.tableWidgetInboxSubscriptions, self.ui.tableWidgetInboxChans]:
+ treeWidget = self.widgetConvert(sent)
+ if self.getCurrentFolder(treeWidget) != "sent":
+ continue
+ if treeWidget == self.ui.treeWidgetYourIdentities and self.getCurrentAccount(treeWidget) != fromAddress:
+ continue
+ elif treeWidget in [self.ui.treeWidgetSubscriptions, self.ui.treeWidgetChans] and self.getCurrentAccount(treeWidget) != toAddress:
+ continue
+
+ self.addMessageListItemSent(sent, toAddress, fromAddress, subject, "msgqueued", ackdata, time.time())
+ self.getAccountTextedit(acct).setPlainText(unicode(message, 'utf-8)'))
def displayNewInboxMessage(self, inventoryHash, toAddress, fromAddress, subject, message):
- subject = shared.fixPotentiallyInvalidUTF8Data(subject)
- fromLabel = ''
- queryreturn = sqlQuery(
- '''select label from addressbook where address=?''', fromAddress)
- if queryreturn != []:
- for row in queryreturn:
- fromLabel, = row
+ if toAddress == str_broadcast_subscribers:
+ acct = accountClass(fromAddress)
else:
- # There might be a label in the subscriptions table
- queryreturn = sqlQuery(
- '''select label from subscriptions where address=?''', fromAddress)
- if queryreturn != []:
- for row in queryreturn:
- fromLabel, = row
-
- try:
- if toAddress == self.str_broadcast_subscribers:
- toLabel = self.str_broadcast_subscribers
- else:
- toLabel = shared.config.get(toAddress, 'label')
- except:
- toLabel = ''
- if toLabel == '':
- toLabel = toAddress
-
- font = QFont()
- font.setBold(True)
- self.ui.tableWidgetInbox.setSortingEnabled(False)
- newItem = QtGui.QTableWidgetItem(unicode(toLabel, 'utf-8'))
- newItem.setToolTip(unicode(toLabel, 'utf-8'))
- newItem.setFont(font)
- newItem.setData(Qt.UserRole, str(toAddress))
- if shared.safeConfigGetBoolean(str(toAddress), 'mailinglist'):
- newItem.setTextColor(QtGui.QColor(137, 04, 177)) # magenta
- if shared.safeConfigGetBoolean(str(toAddress), 'chan'):
- newItem.setTextColor(QtGui.QColor(216, 119, 0)) # orange
- self.ui.tableWidgetInbox.insertRow(0)
- newItem.setIcon(avatarize(toAddress))
- self.ui.tableWidgetInbox.setItem(0, 0, newItem)
-
- if fromLabel == '':
- newItem = QtGui.QTableWidgetItem(unicode(fromAddress, 'utf-8'))
- newItem.setToolTip(unicode(fromAddress, 'utf-8'))
- if shared.config.getboolean('bitmessagesettings', 'showtraynotifications'):
- self.notifierShow(unicode(_translate("MainWindow",'New Message').toUtf8(),'utf-8'), unicode(_translate("MainWindow",'From ').toUtf8(),'utf-8') + unicode(fromAddress, 'utf-8'), self.SOUND_UNKNOWN, None)
+ acct = accountClass(toAddress)
+ inbox = self.getAccountMessagelist(acct)
+ ret = None
+ for treeWidget in [self.ui.treeWidgetYourIdentities, self.ui.treeWidgetSubscriptions, self.ui.treeWidgetChans]:
+ tableWidget = self.widgetConvert(treeWidget)
+ if tableWidget == inbox and self.getCurrentAccount(treeWidget) == acct.address and self.getCurrentFolder(treeWidget) in ["inbox", None]:
+ ret = self.addMessageListItemInbox(inbox, "inbox", inventoryHash, toAddress, fromAddress, subject, time.time(), 0)
+ elif treeWidget == self.ui.treeWidgetYourIdentities and self.getCurrentAccount(treeWidget) is None:
+ ret = self.addMessageListItemInbox(tableWidget, "inbox", inventoryHash, toAddress, fromAddress, subject, time.time(), 0)
+ if ret is None:
+ subject = shared.fixPotentiallyInvalidUTF8Data(subject)
+ acct.parseMessage(toAddress, fromAddress, subject, "")
else:
- newItem = QtGui.QTableWidgetItem(unicode(fromLabel, 'utf-8'))
- newItem.setToolTip(unicode(unicode(fromLabel, 'utf-8')))
- if shared.config.getboolean('bitmessagesettings', 'showtraynotifications'):
- self.notifierShow(unicode(_translate("MainWindow",'New Message').toUtf8(),'utf-8'), unicode(_translate("MainWindow",'From ').toUtf8(),'utf-8') + unicode(fromLabel, 'utf-8'), self.SOUND_KNOWN, unicode(fromLabel, 'utf-8'))
- newItem.setData(Qt.UserRole, str(fromAddress))
- newItem.setFont(font)
- newItem.setIcon(avatarize(fromAddress))
- self.ui.tableWidgetInbox.setItem(0, 1, newItem)
- newItem = QtGui.QTableWidgetItem(unicode(subject, 'utf-8)'))
- newItem.setToolTip(unicode(subject, 'utf-8)'))
- #newItem.setData(Qt.UserRole, unicode(message, 'utf-8)')) # No longer hold the message in the table; we'll use a SQL query to display it as needed.
- newItem.setFont(font)
- self.ui.tableWidgetInbox.setItem(0, 2, newItem)
- newItem = myTableWidgetItem(l10n.formatTimestamp())
- newItem.setToolTip(l10n.formatTimestamp())
- newItem.setData(Qt.UserRole, QByteArray(inventoryHash))
- newItem.setData(33, int(time.time()))
- newItem.setFont(font)
- self.ui.tableWidgetInbox.setItem(0, 3, newItem)
- self.ui.tableWidgetInbox.setSortingEnabled(True)
- self.ubuntuMessagingMenuUpdate(True, newItem, toLabel)
+ acct = ret
+ self.propagateUnreadCount(acct.address)
+ if shared.config.getboolean('bitmessagesettings', 'showtraynotifications'):
+ self.notifierShow(unicode(_translate("MainWindow",'New Message').toUtf8(),'utf-8'), unicode(_translate("MainWindow",'From ').toUtf8(),'utf-8') + unicode(acct.fromLabel, 'utf-8'), self.SOUND_UNKNOWN, None)
+ if self.getCurrentAccount() is not None and ((self.getCurrentFolder(treeWidget) != "inbox" and self.getCurrentFolder(treeWidget) is not None) or self.getCurrentAccount(treeWidget) != acct.address):
+ # Ubuntu should notify of new message irespective of whether it's in current message list or not
+ self.ubuntuMessagingMenuUpdate(True, None, acct.toLabel)
+ return
def click_pushButtonAddAddressBook(self):
self.AddAddressDialogInstance = AddAddressDialog(self)
@@ -2251,17 +2474,8 @@ more work your computer must do to send the message. A Time-To-Live of four or f
def addEntryToAddressBook(self,address,label):
queryreturn = sqlQuery('''select * from addressbook where address=?''', address)
if queryreturn == []:
- self.ui.tableWidgetAddressBook.setSortingEnabled(False)
- self.ui.tableWidgetAddressBook.insertRow(0)
- newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8'))
- newItem.setIcon(avatarize(address))
- self.ui.tableWidgetAddressBook.setItem(0, 0, newItem)
- newItem = QtGui.QTableWidgetItem(address)
- newItem.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- self.ui.tableWidgetAddressBook.setItem(0, 1, newItem)
- self.ui.tableWidgetAddressBook.setSortingEnabled(True)
sqlExecute('''INSERT INTO addressbook VALUES (?,?)''', str(label), address)
+ self.rerenderAddressBook()
self.rerenderInboxFromLabels()
self.rerenderSentToLabels()
else:
@@ -2273,20 +2487,12 @@ more work your computer must do to send the message. A Time-To-Live of four or f
#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 UI list
- self.ui.tableWidgetSubscriptions.setSortingEnabled(False)
- self.ui.tableWidgetSubscriptions.insertRow(0)
- newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8'))
- newItem.setIcon(avatarize(address))
- self.ui.tableWidgetSubscriptions.setItem(0,0,newItem)
- newItem = QtGui.QTableWidgetItem(address)
- newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
- self.ui.tableWidgetSubscriptions.setItem(0,1,newItem)
- self.ui.tableWidgetSubscriptions.setSortingEnabled(True)
#Add to database (perhaps this should be separated from the MyForm class)
sqlExecute('''INSERT INTO subscriptions VALUES (?,?,?)''',str(label),address,True)
self.rerenderInboxFromLabels()
shared.reloadBroadcastSendersForWhichImWatching()
+ self.rerenderAddressBook()
+ self.rerenderTabTreeSubscriptions()
def click_pushButtonAddSubscription(self):
self.NewSubscriptionDialogInstance = NewSubscriptionDialog(self)
@@ -2297,7 +2503,7 @@ more work your computer must do to send the message. A Time-To-Live of four or f
address = addBMIfNotPresent(str(self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text()))
# 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.statusBar().showMessage(_translate("MainWindow", "Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want."))
+ self.statusBar().showMessage(_translate("MainWindow", "Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want."))
return
label = self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8()
self.addSubscription(address, label)
@@ -2319,7 +2525,7 @@ more work your computer must do to send the message. A Time-To-Live of four or f
shared.objectProcessorQueue.put((objectType,payload))
def click_pushButtonStatusIcon(self):
- print 'click_pushButtonStatusIcon'
+ logger.debug('click_pushButtonStatusIcon')
self.iconGlossaryInstance = iconGlossaryDialog(self)
if self.iconGlossaryInstance.exec_():
pass
@@ -2361,6 +2567,12 @@ more work your computer must do to send the message. A Time-To-Live of four or f
"MainWindow", "You must restart Bitmessage for the port number change to take effect."))
shared.config.set('bitmessagesettings', 'port', str(
self.settingsDialogInstance.ui.lineEditTCPPort.text()))
+ if self.settingsDialogInstance.ui.checkBoxUPnP.isChecked() != shared.safeConfigGetBoolean('bitmessagesettings', 'upnp'):
+ shared.config.set('bitmessagesettings', 'upnp', str(self.settingsDialogInstance.ui.checkBoxUPnP.isChecked()))
+ if self.settingsDialogInstance.ui.checkBoxUPnP.isChecked():
+ import upnp
+ upnpThread = upnp.uPnPThread()
+ upnpThread.start()
#print 'self.settingsDialogInstance.ui.comboBoxProxyType.currentText()', self.settingsDialogInstance.ui.comboBoxProxyType.currentText()
#print 'self.settingsDialogInstance.ui.comboBoxProxyType.currentText())[0:5]', self.settingsDialogInstance.ui.comboBoxProxyType.currentText()[0:5]
if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none' and self.settingsDialogInstance.ui.comboBoxProxyType.currentText()[0:5] == 'SOCKS':
@@ -2415,6 +2627,9 @@ more work your computer must do to send the message. A Time-To-Live of four or f
shared.config.set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(int(float(
self.settingsDialogInstance.ui.lineEditSmallMessageDifficulty.text()) * shared.networkDefaultPayloadLengthExtraBytes)))
+ if openclpow.has_opencl() and self.settingsDialogInstance.ui.checkBoxOpenCL.isChecked() != shared.safeConfigGetBoolean("bitmessagesettings", "opencl"):
+ shared.config.set('bitmessagesettings', 'opencl', str(self.settingsDialogInstance.ui.checkBoxOpenCL.isChecked()))
+
acceptableDifficultyChanged = False
if float(self.settingsDialogInstance.ui.lineEditMaxAcceptableTotalDifficulty.text()) >= 1 or float(self.settingsDialogInstance.ui.lineEditMaxAcceptableTotalDifficulty.text()) == 0:
@@ -2597,9 +2812,7 @@ more work your computer must do to send the message. A Time-To-Live of four or f
self.dialog = SpecialAddressBehaviorDialog(self)
# For Modal dialogs
if self.dialog.exec_():
- currentRow = self.ui.tableWidgetYourIdentities.currentRow()
- addressAtCurrentRow = str(
- self.ui.tableWidgetYourIdentities.item(currentRow, 1).text())
+ addressAtCurrentRow = self.getCurrentAccount()
if shared.safeConfigGetBoolean(addressAtCurrentRow, 'chan'):
return
if self.dialog.ui.radioButtonBehaveNormalAddress.isChecked():
@@ -2607,22 +2820,57 @@ more work your computer must do to send the message. A Time-To-Live of four or f
addressAtCurrentRow), 'mailinglist', 'false')
# Set the color to either black or grey
if shared.config.getboolean(addressAtCurrentRow, 'enabled'):
- self.ui.tableWidgetYourIdentities.item(
- currentRow, 1).setTextColor(QApplication.palette()
+ self.setCurrentItemColor(QApplication.palette()
.text().color())
else:
- self.ui.tableWidgetYourIdentities.item(
- currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128))
+ self.setCurrentItemColor(QtGui.QColor(128, 128, 128))
else:
shared.config.set(str(
addressAtCurrentRow), 'mailinglist', 'true')
shared.config.set(str(addressAtCurrentRow), 'mailinglistname', str(
self.dialog.ui.lineEditMailingListName.text().toUtf8()))
- self.ui.tableWidgetYourIdentities.item(currentRow, 1).setTextColor(QtGui.QColor(137, 04, 177)) # magenta
+ self.setCurrentItemColor(QtGui.QColor(137, 04, 177)) #magenta
+ self.rerenderComboBoxSendFrom()
+ self.rerenderComboBoxSendFromBroadcast()
shared.writeKeysFile()
self.rerenderInboxToLabels()
+ def on_action_EmailGatewayDialog(self):
+ self.dialog = EmailGatewayDialog(self)
+ # For Modal dialogs
+ if self.dialog.exec_():
+ addressAtCurrentRow = self.getCurrentAccount()
+ acct = accountClass(addressAtCurrentRow)
+ # no chans / mailinglists
+ if acct.type != AccountMixin.NORMAL:
+ return
+ if self.dialog.ui.radioButtonUnregister.isChecked() and isinstance(acct, GatewayAccount):
+ acct.unregister()
+ shared.config.remove_option(addressAtCurrentRow, 'gateway')
+ shared.writeKeysFile()
+ elif self.dialog.ui.radioButtonRegister.isChecked():
+ email = str(self.dialog.ui.lineEditEmail.text().toUtf8())
+ acct = MailchuckAccount(addressAtCurrentRow)
+ acct.register(email)
+ shared.config.set(addressAtCurrentRow, 'label', email)
+ shared.config.set(addressAtCurrentRow, 'gateway', 'mailchuck')
+ self.getCurrentTreeWidget().currentItem().updateText()
+ shared.writeKeysFile()
+ else:
+ pass
+ #print "well nothing"
+# shared.writeKeysFile()
+# self.rerenderInboxToLabels()
+
def click_NewAddressDialog(self):
+ addresses = []
+ for addressInKeysFile in getSortedAccounts():
+ addresses.append(addressInKeysFile)
+# self.dialog = Ui_NewAddressWizard(addresses)
+# self.dialog.exec_()
+# print "Name: " + self.dialog.field("name").toString()
+# print "Email: " + self.dialog.field("email").toString()
+# return
self.dialog = NewAddressDialog(self)
# For Modal dialogs
if self.dialog.exec_():
@@ -2649,7 +2897,7 @@ more work your computer must do to send the message. A Time-To-Live of four or f
shared.addressGeneratorQueue.put(('createDeterministicAddresses', 4, streamNumberForAddress, "unused deterministic address", self.dialog.ui.spinBoxNumberOfAddressesToMake.value(
), self.dialog.ui.lineEditPassphrase.text().toUtf8(), self.dialog.ui.checkBoxEighteenByteRipe.isChecked()))
else:
- print 'new address dialog box rejected'
+ logger.debug('new address dialog box rejected')
# Quit selected from menu or application indicator
def quit(self):
@@ -2660,11 +2908,24 @@ more work your computer must do to send the message. A Time-To-Live of four or f
if reply is QtGui.QMessageBox.No:
return
'''
+ # save state and geometry self and all widgets
+ 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()
+
shared.doCleanShutdown()
self.tray.hide()
# unregister the messaging system
if self.mmapp is not None:
self.mmapp.unregister()
+
+# settings = QSettings("Bitmessage", "PyBitmessage")
+# settings.setValue("geometry", self.saveGeometry())
+# settings.setValue("state", self.saveState())
+
self.statusBar().showMessage(_translate(
"MainWindow", "All done. Closing user interface..."))
os._exit(0)
@@ -2689,10 +2950,10 @@ more work your computer must do to send the message. A Time-To-Live of four or f
self.quit()
def on_action_InboxMessageForceHtml(self):
- currentInboxRow = self.ui.tableWidgetInbox.currentRow()
-
- msgid = str(self.ui.tableWidgetInbox.item(
- currentInboxRow, 3).data(Qt.UserRole).toPyObject())
+ msgid = self.getCurrentMessageId()
+ textEdit = self.getCurrentMessageTextedit()
+ if not msgid:
+ return
queryreturn = sqlQuery(
'''select message from inbox where msgid=?''', msgid)
if queryreturn != []:
@@ -2713,29 +2974,42 @@ more work your computer must do to send the message. A Time-To-Live of four or f
content = ' '.join(lines) # To keep the whitespace between lines
content = shared.fixPotentiallyInvalidUTF8Data(content)
content = unicode(content, 'utf-8)')
- self.ui.textEditInboxMessage.setHtml(QtCore.QString(content))
+ textEdit.setHtml(QtCore.QString(content))
def on_action_InboxMarkUnread(self):
+ tableWidget = self.getCurrentMessagelist()
+ if not tableWidget:
+ return
font = QFont()
font.setBold(True)
inventoryHashesToMarkUnread = []
- for row in self.ui.tableWidgetInbox.selectedIndexes():
+ modified = 0
+ for row in tableWidget.selectedIndexes():
currentRow = row.row()
- inventoryHashToMarkUnread = str(self.ui.tableWidgetInbox.item(
+ inventoryHashToMarkUnread = str(tableWidget.item(
currentRow, 3).data(Qt.UserRole).toPyObject())
+ if inventoryHashToMarkUnread in inventoryHashesToMarkUnread:
+ # it returns columns as separate items, so we skip dupes
+ continue
+ if not tableWidget.item(currentRow, 0).font().bold():
+ modified += 1
inventoryHashesToMarkUnread.append(inventoryHashToMarkUnread)
- self.ui.tableWidgetInbox.item(currentRow, 0).setFont(font)
- self.ui.tableWidgetInbox.item(currentRow, 1).setFont(font)
- self.ui.tableWidgetInbox.item(currentRow, 2).setFont(font)
- self.ui.tableWidgetInbox.item(currentRow, 3).setFont(font)
+ tableWidget.item(currentRow, 0).setFont(font)
+ tableWidget.item(currentRow, 1).setFont(font)
+ tableWidget.item(currentRow, 2).setFont(font)
+ tableWidget.item(currentRow, 3).setFont(font)
#sqlite requires the exact number of ?s to prevent injection
sqlExecute('''UPDATE inbox SET read=0 WHERE msgid IN (%s)''' % (
"?," * len(inventoryHashesToMarkUnread))[:-1], *inventoryHashesToMarkUnread)
- self.changedInboxUnread()
- # self.ui.tableWidgetInbox.selectRow(currentRow + 1)
+ if modified == 1:
+ # performance optimisation
+ self.propagateUnreadCount(str(tableWidget.item(currentRow, 1 if tableWidget == self.ui.tableWidgetInboxSubscriptions else 0).data(Qt.UserRole).toPyObject()), self.getCurrentFolder())
+ else:
+ self.propagateUnreadCount(str(tableWidget.item(currentRow, 1 if tableWidget == self.ui.tableWidgetInboxSubscriptions else 0).data(Qt.UserRole).toPyObject()), self.getCurrentFolder(), self.getCurrentTreeWidget(), 0)
+ # tableWidget.selectRow(currentRow + 1)
# This doesn't de-select the last message if you try to mark it unread, but that doesn't interfere. Might not be necessary.
# We could also select upwards, but then our problem would be with the topmost message.
- # self.ui.tableWidgetInbox.clearSelection() manages to mark the message as read again.
+ # tableWidget.clearSelection() manages to mark the message as read again.
# Format predefined text on message reply.
def quoted_text(self, message):
@@ -2760,112 +3034,186 @@ more work your computer must do to send the message. A Time-To-Live of four or f
return '\n'.join([quote_line(l) for l in message.splitlines()]) + '\n\n'
def on_action_InboxReply(self):
- currentInboxRow = self.ui.tableWidgetInbox.currentRow()
- toAddressAtCurrentInboxRow = str(self.ui.tableWidgetInbox.item(
+ tableWidget = self.getCurrentMessagelist()
+ if not tableWidget:
+ return
+
+ # save this to return back after reply is done
+ self.replyFromTab = self.ui.tabWidget.currentIndex()
+
+ currentInboxRow = tableWidget.currentRow()
+ toAddressAtCurrentInboxRow = str(tableWidget.item(
currentInboxRow, 0).data(Qt.UserRole).toPyObject())
- fromAddressAtCurrentInboxRow = str(self.ui.tableWidgetInbox.item(
+ acct = accountClass(toAddressAtCurrentInboxRow)
+ fromAddressAtCurrentInboxRow = str(tableWidget.item(
currentInboxRow, 1).data(Qt.UserRole).toPyObject())
- msgid = str(self.ui.tableWidgetInbox.item(
+ msgid = str(tableWidget.item(
currentInboxRow, 3).data(Qt.UserRole).toPyObject())
queryreturn = sqlQuery(
'''select message from inbox where msgid=?''', msgid)
if queryreturn != []:
for row in queryreturn:
messageAtCurrentInboxRow, = row
- if toAddressAtCurrentInboxRow == self.str_broadcast_subscribers:
- self.ui.labelFrom.setText('')
+ acct.parseMessage(toAddressAtCurrentInboxRow, fromAddressAtCurrentInboxRow, unicode(tableWidget.item(currentInboxRow, 2).data(Qt.UserRole).toPyObject(), 'utf-8'), messageAtCurrentInboxRow)
+ widget = {
+ 'subject': self.ui.lineEditSubject,
+ 'from': self.ui.comboBoxSendFrom,
+ 'message': self.ui.textEditMessage
+ }
+ if toAddressAtCurrentInboxRow == str_broadcast_subscribers:
+ self.ui.tabWidgetSend.setCurrentIndex(0)
+# toAddressAtCurrentInboxRow = fromAddressAtCurrentInboxRow
elif not shared.config.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), QMessageBox.Ok)
- self.ui.labelFrom.setText('')
elif not shared.config.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."), QMessageBox.Ok)
- self.ui.labelFrom.setText('')
else:
- self.ui.labelFrom.setText(toAddressAtCurrentInboxRow)
- self.setBroadcastEnablementDependingOnWhetherThisIsAChanAddress(toAddressAtCurrentInboxRow)
+ self.setBroadcastEnablementDependingOnWhetherThisIsAMailingListAddress(toAddressAtCurrentInboxRow)
+ if self.ui.tabWidgetSend.currentIndex() == 1:
+ widget = {
+ 'subject': self.ui.lineEditSubjectBroadcast,
+ 'from': self.ui.comboBoxSendFromBroadcast,
+ 'message': self.ui.textEditMessageBroadcast
+ }
+ self.ui.tabWidgetSend.setCurrentIndex(1)
+ toAddressAtCurrentInboxRow = fromAddressAtCurrentInboxRow
- self.ui.lineEditTo.setText(str(fromAddressAtCurrentInboxRow))
+ self.ui.lineEditTo.setText(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 shared.config.has_section(toAddressAtCurrentInboxRow):
if shared.safeConfigGetBoolean(toAddressAtCurrentInboxRow, 'chan'):
- print 'original sent to a chan. Setting the to address in the reply to the chan address.'
+ logger.debug('original sent to a chan. Setting the to address in the reply to the chan address.')
self.ui.lineEditTo.setText(str(toAddressAtCurrentInboxRow))
- listOfAddressesInComboBoxSendFrom = [str(self.ui.comboBoxSendFrom.itemData(i).toPyObject()) for i in range(self.ui.comboBoxSendFrom.count())]
+ listOfAddressesInComboBoxSendFrom = [str(widget['from'].itemData(i).toPyObject()) for i in range(widget['from'].count())]
if toAddressAtCurrentInboxRow in listOfAddressesInComboBoxSendFrom:
currentIndex = listOfAddressesInComboBoxSendFrom.index(toAddressAtCurrentInboxRow)
- self.ui.comboBoxSendFrom.setCurrentIndex(currentIndex)
+ widget['from'].setCurrentIndex(currentIndex)
else:
- self.ui.comboBoxSendFrom.setCurrentIndex(0)
+ widget['from'].setCurrentIndex(0)
quotedText = self.quoted_text(unicode(messageAtCurrentInboxRow, 'utf-8'))
- self.ui.textEditMessage.setText(quotedText)
- if self.ui.tableWidgetInbox.item(currentInboxRow, 2).text()[0:3] in ['Re:', 'RE:']:
- self.ui.lineEditSubject.setText(
- self.ui.tableWidgetInbox.item(currentInboxRow, 2).text())
+ widget['message'].setText(quotedText)
+ if acct.subject[0:3] in ['Re:', 'RE:']:
+ widget['subject'].setText(acct.subject)
else:
- self.ui.lineEditSubject.setText(
- 'Re: ' + self.ui.tableWidgetInbox.item(currentInboxRow, 2).text())
- self.ui.radioButtonSpecific.setChecked(True)
+ widget['subject'].setText('Re: ' + acct.subject)
self.ui.tabWidget.setCurrentIndex(1)
def on_action_InboxAddSenderToAddressBook(self):
- currentInboxRow = self.ui.tableWidgetInbox.currentRow()
- # self.ui.tableWidgetInbox.item(currentRow,1).data(Qt.UserRole).toPyObject()
- addressAtCurrentInboxRow = str(self.ui.tableWidgetInbox.item(
+ tableWidget = self.getCurrentMessagelist()
+ if not tableWidget:
+ return
+ currentInboxRow = tableWidget.currentRow()
+ # tableWidget.item(currentRow,1).data(Qt.UserRole).toPyObject()
+ addressAtCurrentInboxRow = str(tableWidget.item(
currentInboxRow, 1).data(Qt.UserRole).toPyObject())
# Let's make sure that it isn't already in the address book
queryreturn = sqlQuery('''select * from addressbook where address=?''',
addressAtCurrentInboxRow)
if queryreturn == []:
- self.ui.tableWidgetAddressBook.insertRow(0)
- newItem = QtGui.QTableWidgetItem(
- '--New entry. Change label in Address Book.--')
- self.ui.tableWidgetAddressBook.setItem(0, 0, newItem)
- newItem.setIcon(avatarize(addressAtCurrentInboxRow))
- newItem = QtGui.QTableWidgetItem(addressAtCurrentInboxRow)
- newItem.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- self.ui.tableWidgetAddressBook.setItem(0, 1, newItem)
sqlExecute('''INSERT INTO addressbook VALUES (?,?)''',
'--New entry. Change label in Address Book.--',
addressAtCurrentInboxRow)
- self.ui.tabWidget.setCurrentIndex(5)
- self.ui.tableWidgetAddressBook.setCurrentCell(0, 0)
+ self.rerenderAddressBook()
self.statusBar().showMessage(_translate(
"MainWindow", "Entry added to the Address Book. Edit the label to your liking."))
else:
self.statusBar().showMessage(_translate(
"MainWindow", "Error: You cannot add the same address to your address book twice. Try renaming the existing one if you want."))
+ def on_action_InboxAddSenderToBlackList(self):
+ tableWidget = self.getCurrentMessagelist()
+ if not tableWidget:
+ return
+ currentInboxRow = tableWidget.currentRow()
+ # tableWidget.item(currentRow,1).data(Qt.UserRole).toPyObject()
+ addressAtCurrentInboxRow = str(tableWidget.item(
+ currentInboxRow, 1).data(Qt.UserRole).toPyObject())
+ # Let's make sure that it isn't already in the address book
+ queryreturn = sqlQuery('''select * from blacklist where address=?''',
+ addressAtCurrentInboxRow)
+ if queryreturn == []:
+ label = "\"" + unicode(tableWidget.item(currentInboxRow, 2).data(Qt.UserRole).toString(), 'utf-8') + "\" in " + shared.config.get(self.getCurrentAccount(), "label")
+ sqlExecute('''INSERT INTO blacklist VALUES (?,?, ?)''',
+ label,
+ addressAtCurrentInboxRow, True)
+ self.rerenderBlackWhiteList()
+ self.statusBar().showMessage(_translate(
+ "MainWindow", "Entry added to the blacklist. Edit the label to your liking."))
+ else:
+ self.statusBar().showMessage(_translate(
+ "MainWindow", "Error: You cannot add the same address to your blacklist twice. Try renaming the existing one if you want."))
+
# Send item on the Inbox tab to trash
def on_action_InboxTrash(self):
- while self.ui.tableWidgetInbox.selectedIndexes() != []:
- currentRow = self.ui.tableWidgetInbox.selectedIndexes()[0].row()
- inventoryHashToTrash = str(self.ui.tableWidgetInbox.item(
+ tableWidget = self.getCurrentMessagelist()
+ if not tableWidget:
+ return
+ unread = False
+ currentRow = 0
+ folder = self.getCurrentFolder()
+ shifted = QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ShiftModifier
+ while tableWidget.selectedIndexes():
+ currentRow = tableWidget.selectedIndexes()[0].row()
+ inventoryHashToTrash = str(tableWidget.item(
currentRow, 3).data(Qt.UserRole).toPyObject())
- sqlExecute('''UPDATE inbox SET folder='trash' WHERE msgid=?''', inventoryHashToTrash)
- self.ui.textEditInboxMessage.setText("")
- self.ui.tableWidgetInbox.removeRow(currentRow)
+ if folder == "trash" or shifted:
+ sqlExecute('''DELETE FROM inbox WHERE msgid=?''', inventoryHashToTrash)
+ else:
+ sqlExecute('''UPDATE inbox SET folder='trash' WHERE msgid=?''', inventoryHashToTrash)
+ if tableWidget.item(currentRow, 0).font().bold():
+ self.propagateUnreadCount(str(tableWidget.item(currentRow, 1 if tableWidget == self.ui.tableWidgetInboxSubscriptions else 0).data(Qt.UserRole).toPyObject()), folder, self.getCurrentTreeWidget(), -1)
+ if folder != "trash" and not shifted:
+ self.propagateUnreadCount(str(tableWidget.item(currentRow, 1 if tableWidget == self.ui.tableWidgetInboxSubscriptions else 0).data(Qt.UserRole).toPyObject()), "trash", self.getCurrentTreeWidget(), 1)
+
+ self.getCurrentMessageTextedit().setText("")
+ tableWidget.removeRow(currentRow)
self.statusBar().showMessage(_translate(
- "MainWindow", "Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back."))
+ "MainWindow", "Moved items to trash."))
if currentRow == 0:
- self.ui.tableWidgetInbox.selectRow(currentRow)
+ tableWidget.selectRow(currentRow)
else:
- self.ui.tableWidgetInbox.selectRow(currentRow - 1)
+ tableWidget.selectRow(currentRow - 1)
+
+ def on_action_TrashUndelete(self):
+ tableWidget = self.getCurrentMessagelist()
+ if not tableWidget:
+ return
+ unread = False
+ currentRow = 0
+ while tableWidget.selectedIndexes():
+ currentRow = tableWidget.selectedIndexes()[0].row()
+ inventoryHashToTrash = str(tableWidget.item(
+ currentRow, 3).data(Qt.UserRole).toPyObject())
+ sqlExecute('''UPDATE inbox SET folder='inbox' WHERE msgid=?''', inventoryHashToTrash)
+ if tableWidget.item(currentRow, 0).font().bold():
+ self.propagateUnreadCount(str(tableWidget.item(currentRow, 1 if tableWidget == self.ui.tableWidgetInboxSubscriptions else 0).data(Qt.UserRole).toPyObject()), "inbox", self.getCurrentTreeWidget(), 1)
+ self.propagateUnreadCount(str(tableWidget.item(currentRow, 1 if tableWidget == self.ui.tableWidgetInboxSubscriptions else 0).data(Qt.UserRole).toPyObject()), "trash", self.getCurrentTreeWidget(), -1)
+ self.getCurrentMessageTextedit().setText("")
+ tableWidget.removeRow(currentRow)
+ self.statusBar().showMessage(_translate(
+ "MainWindow", "Undeleted item."))
+ if currentRow == 0:
+ tableWidget.selectRow(currentRow)
+ else:
+ tableWidget.selectRow(currentRow - 1)
def on_action_InboxSaveMessageAs(self):
- currentInboxRow = self.ui.tableWidgetInbox.currentRow()
+ tableWidget = self.getCurrentMessagelist()
+ if not tableWidget:
+ return
+ currentInboxRow = tableWidget.currentRow()
try:
- subjectAtCurrentInboxRow = str(self.ui.tableWidgetInbox.item(currentInboxRow,2).text())
+ subjectAtCurrentInboxRow = str(tableWidget.item(currentInboxRow,2).text())
except:
subjectAtCurrentInboxRow = ''
# Retrieve the message data out of the SQL database
- msgid = str(self.ui.tableWidgetInbox.item(
+ msgid = str(tableWidget.item(
currentInboxRow, 3).data(Qt.UserRole).toPyObject())
queryreturn = sqlQuery(
'''select message from inbox where msgid=?''', msgid)
@@ -2882,28 +3230,40 @@ more work your computer must do to send the message. A Time-To-Live of four or f
f.write(message)
f.close()
except Exception, e:
- sys.stderr.write('Write error: '+ e)
+ logger.exception('Message not saved', exc_info=True)
self.statusBar().showMessage(_translate("MainWindow", "Write error."))
# Send item on the Sent tab to trash
def on_action_SentTrash(self):
- while self.ui.tableWidgetSent.selectedIndexes() != []:
- currentRow = self.ui.tableWidgetSent.selectedIndexes()[0].row()
- ackdataToTrash = str(self.ui.tableWidgetSent.item(
+ currentRow = 0
+ unread = False
+ tableWidget = self.getCurrentMessagelist()
+ if not tableWidget:
+ return
+ folder = self.getCurrentFolder()
+ shifted = (QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ShiftModifier) > 0
+ while tableWidget.selectedIndexes() != []:
+ currentRow = tableWidget.selectedIndexes()[0].row()
+ ackdataToTrash = str(tableWidget.item(
currentRow, 3).data(Qt.UserRole).toPyObject())
- sqlExecute('''UPDATE sent SET folder='trash' WHERE ackdata=?''', ackdataToTrash)
- self.ui.textEditSentMessage.setPlainText("")
- self.ui.tableWidgetSent.removeRow(currentRow)
+ if folder == "trash" or shifted:
+ sqlExecute('''DELETE FROM sent WHERE ackdata=?''', ackdataToTrash)
+ else:
+ sqlExecute('''UPDATE sent SET folder='trash' WHERE ackdata=?''', ackdataToTrash)
+ if tableWidget.item(currentRow, 0).font().bold():
+ self.propagateUnreadCount(str(tableWidget.item(currentRow, 1 if tableWidget == self.ui.tableWidgetInboxSubscriptions else 0).data(Qt.UserRole).toPyObject()), folder, self.getCurrentTreeWidget(), -1)
+ self.getCurrentMessageTextedit().setPlainText("")
+ tableWidget.removeRow(currentRow)
self.statusBar().showMessage(_translate(
- "MainWindow", "Moved items to trash. There is no user interface to view your trash, but it is still on disk if you are desperate to get it back."))
+ "MainWindow", "Moved items to trash."))
if currentRow == 0:
- self.ui.tableWidgetSent.selectRow(currentRow)
+ self.ui.tableWidgetInbox.selectRow(currentRow)
else:
- self.ui.tableWidgetSent.selectRow(currentRow - 1)
+ self.ui.tableWidgetInbox.selectRow(currentRow - 1)
def on_action_ForceSend(self):
- currentRow = self.ui.tableWidgetSent.currentRow()
- addressAtCurrentRow = str(self.ui.tableWidgetSent.item(
+ currentRow = self.ui.tableWidgetInbox.currentRow()
+ addressAtCurrentRow = str(self.ui.tableWidgetInbox.item(
currentRow, 0).data(Qt.UserRole).toPyObject())
toRipe = decodeAddress(addressAtCurrentRow)[3]
sqlExecute(
@@ -2917,8 +3277,8 @@ more work your computer must do to send the message. A Time-To-Live of four or f
shared.workerQueue.put(('sendmessage', ''))
def on_action_SentClipboard(self):
- currentRow = self.ui.tableWidgetSent.currentRow()
- addressAtCurrentRow = str(self.ui.tableWidgetSent.item(
+ currentRow = self.ui.tableWidgetInbox.currentRow()
+ addressAtCurrentRow = str(self.ui.tableWidgetInbox.item(
currentRow, 0).data(Qt.UserRole).toPyObject())
clipboard = QtGui.QApplication.clipboard()
clipboard.setText(str(addressAtCurrentRow))
@@ -2985,13 +3345,30 @@ more work your computer must do to send the message. A Time-To-Live of four or f
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.statusBar().showMessage(QtGui.QApplication.translate("MainWindow", "Error: You cannot add the same address to your subsciptions twice. Perhaps rename the existing one if you want."))
+ self.statusBar().showMessage(QtGui.QApplication.translate("MainWindow", "Error: You cannot add the same address to your subscriptions twice. Perhaps rename the existing one if you want."))
continue
labelAtCurrentRow = self.ui.tableWidgetAddressBook.item(currentRow,0).text().toUtf8()
self.addSubscription(addressAtCurrentRow, labelAtCurrentRow)
self.ui.tabWidget.setCurrentIndex(4)
def on_context_menuAddressBook(self, point):
+ 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.addSeparator()
+ self.popMenuAddressBook.addAction(self.actionAddressBookNew)
+ normal = True
+ for row in self.ui.tableWidgetAddressBook.selectedIndexes():
+ currentRow = row.row()
+ type = self.ui.tableWidgetAddressBook.item(
+ currentRow, 0).type
+ if 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))
@@ -3000,58 +3377,55 @@ more work your computer must do to send the message. A Time-To-Live of four or f
self.click_pushButtonAddSubscription()
def on_action_SubscriptionsDelete(self):
- print 'clicked Delete'
- currentRow = self.ui.tableWidgetSubscriptions.currentRow()
- labelAtCurrentRow = self.ui.tableWidgetSubscriptions.item(
- currentRow, 0).text().toUtf8()
- addressAtCurrentRow = self.ui.tableWidgetSubscriptions.item(
- currentRow, 1).text()
- sqlExecute('''DELETE FROM subscriptions WHERE label=? AND address=?''',
- str(labelAtCurrentRow), str(addressAtCurrentRow))
- self.ui.tableWidgetSubscriptions.removeRow(currentRow)
+ 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?"), QMessageBox.Yes|QMessageBox.No) != QMessageBox.Yes:
+ return
+ address = self.getCurrentAccount()
+ sqlExecute('''DELETE FROM subscriptions WHERE address=?''',
+ address)
+ self.rerenderTabTreeSubscriptions()
self.rerenderInboxFromLabels()
+ self.rerenderAddressBook()
shared.reloadBroadcastSendersForWhichImWatching()
def on_action_SubscriptionsClipboard(self):
- currentRow = self.ui.tableWidgetSubscriptions.currentRow()
- addressAtCurrentRow = self.ui.tableWidgetSubscriptions.item(
- currentRow, 1).text()
+ address = self.getCurrentAccount()
clipboard = QtGui.QApplication.clipboard()
- clipboard.setText(str(addressAtCurrentRow))
+ clipboard.setText(str(address))
def on_action_SubscriptionsEnable(self):
- currentRow = self.ui.tableWidgetSubscriptions.currentRow()
- labelAtCurrentRow = self.ui.tableWidgetSubscriptions.item(
- currentRow, 0).text().toUtf8()
- addressAtCurrentRow = self.ui.tableWidgetSubscriptions.item(
- currentRow, 1).text()
+ address = self.getCurrentAccount()
sqlExecute(
- '''update subscriptions set enabled=1 WHERE label=? AND address=?''',
- str(labelAtCurrentRow), str(addressAtCurrentRow))
- self.ui.tableWidgetSubscriptions.item(
- currentRow, 0).setTextColor(QApplication.palette().text().color())
- self.ui.tableWidgetSubscriptions.item(
- currentRow, 1).setTextColor(QApplication.palette().text().color())
+ '''update subscriptions set enabled=1 WHERE address=?''',
+ address)
+ account = self.getCurrentItem()
+ account.setEnabled(True)
+ self.rerenderAddressBook()
shared.reloadBroadcastSendersForWhichImWatching()
def on_action_SubscriptionsDisable(self):
- currentRow = self.ui.tableWidgetSubscriptions.currentRow()
- labelAtCurrentRow = self.ui.tableWidgetSubscriptions.item(
- currentRow, 0).text().toUtf8()
- addressAtCurrentRow = self.ui.tableWidgetSubscriptions.item(
- currentRow, 1).text()
+ address = self.getCurrentAccount()
sqlExecute(
- '''update subscriptions set enabled=0 WHERE label=? AND address=?''',
- str(labelAtCurrentRow), str(addressAtCurrentRow))
- self.ui.tableWidgetSubscriptions.item(
- currentRow, 0).setTextColor(QtGui.QColor(128, 128, 128))
- self.ui.tableWidgetSubscriptions.item(
- currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128))
+ '''update subscriptions set enabled=0 WHERE address=?''',
+ address)
+ account = self.getCurrentItem()
+ account.setEnabled(False)
+ self.rerenderAddressBook()
shared.reloadBroadcastSendersForWhichImWatching()
def on_context_menuSubscriptions(self, point):
+ self.popMenuSubscriptions = QtGui.QMenu(self)
+ self.popMenuSubscriptions.addAction(self.actionsubscriptionsNew)
+ self.popMenuSubscriptions.addAction(self.actionsubscriptionsDelete)
+ self.popMenuSubscriptions.addSeparator()
+ if self.getCurrentItem().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.exec_(
- self.ui.tableWidgetSubscriptions.mapToGlobal(point))
+ self.ui.treeWidgetSubscriptions.mapToGlobal(point))
# Group of functions for the Blacklist dialog box
def on_action_BlacklistNew(self):
@@ -3116,70 +3490,243 @@ more work your computer must do to send the message. A Time-To-Live of four or f
sqlExecute(
'''UPDATE whitelist SET enabled=0 WHERE address=?''', str(addressAtCurrentRow))
+ def widgetConvert (self, widget):
+ 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
+ else:
+ return None
+
+ def getCurrentTreeWidget(self):
+ currentIndex = self.ui.tabWidget.currentIndex();
+ treeWidgetList = [
+ self.ui.treeWidgetYourIdentities,
+ False,
+ self.ui.treeWidgetSubscriptions,
+ self.ui.treeWidgetChans
+ ]
+ if currentIndex >= 0 and currentIndex < len(treeWidgetList):
+ return treeWidgetList[currentIndex]
+ else:
+ return False
+
+ def getAccountTreeWidget(self, account):
+ try:
+ if account.type == AccountMixin.CHAN:
+ return self.ui.treeWidgetChans
+ elif account.type == AccountMixin.SUBSCRIPTION:
+ return self.ui.treeWidgetSubscriptions
+ else:
+ return self.ui.treeWidgetYourIdentities
+ except:
+ return self.ui.treeWidgetYourIdentities
+
+ def getCurrentMessagelist(self):
+ 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]
+ else:
+ return False
+
+ def getAccountMessagelist(self, account):
+ try:
+ if account.type == AccountMixin.CHAN:
+ return self.ui.tableWidgetInboxChans
+ elif account.type == AccountMixin.SUBSCRIPTION:
+ return self.ui.tableWidgetInboxSubscriptions
+ else:
+ return self.ui.tableWidgetInbox
+ except:
+ return self.ui.tableWidgetInbox
+
+ def getCurrentMessageId(self):
+ messagelist = self.getCurrentMessagelist()
+ if messagelist:
+ currentRow = messagelist.currentRow()
+ if currentRow >= 0:
+ msgid = str(messagelist.item(
+ currentRow, 3).data(Qt.UserRole).toPyObject()) # data is saved at the 4. column of the table...
+ return msgid
+ return False
+
+ def getCurrentMessageTextedit(self):
+ 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]
+ else:
+ return False
+
+ def getAccountTextedit(self, account):
+ try:
+ if account.type == AccountMixin.CHAN:
+ return self.ui.textEditInboxMessageChans
+ elif account.type == AccountMixin.SUBSCRIPTION:
+ return self.ui.textEditInboxSubscriptions
+ else:
+ return self.ui.textEditInboxMessage
+ except:
+ return self.ui.textEditInboxMessage
+
+ def getCurrentSearchLine(self):
+ currentIndex = self.ui.tabWidget.currentIndex();
+ messagelistList = [
+ self.ui.inboxSearchLineEdit,
+ False,
+ self.ui.inboxSearchLineEditSubscriptions,
+ self.ui.inboxSearchLineEditChans,
+ ]
+ if currentIndex >= 0 and currentIndex < len(messagelistList):
+ return messagelistList[currentIndex]
+ else:
+ return False
+
+ def getCurrentSearchOption(self):
+ 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()
+ else:
+ return False
+
# Group of functions for the Your Identities dialog box
+ def getCurrentItem(self, treeWidget = None):
+ if treeWidget is None:
+ treeWidget = self.getCurrentTreeWidget()
+ if treeWidget:
+ currentItem = treeWidget.currentItem()
+ if currentItem:
+ return currentItem
+ return False
+
+ def getCurrentAccount(self, treeWidget = None):
+ currentItem = self.getCurrentItem(treeWidget)
+ if currentItem:
+ account = currentItem.address
+ return account
+ else:
+ # TODO need debug msg?
+ return False
+
+ def getCurrentFolder(self, treeWidget = None):
+ if treeWidget is None:
+ treeWidget = self.getCurrentTreeWidget()
+ #treeWidget = self.ui.treeWidgetYourIdentities
+ if treeWidget:
+ currentItem = treeWidget.currentItem()
+ if currentItem and hasattr(currentItem, 'folderName'):
+ return currentItem.folderName
+ else:
+ return None
+
+ def setCurrentItemColor(self, color):
+ treeWidget = self.getCurrentTreeWidget()
+ if treeWidget:
+ brush = QtGui.QBrush()
+ brush.setStyle(QtCore.Qt.NoBrush)
+ brush.setColor(color)
+ currentItem = treeWidget.currentItem()
+ currentItem.setForeground(0, brush)
+
def on_action_YourIdentitiesNew(self):
self.click_NewAddressDialog()
- def on_action_YourIdentitiesEnable(self):
- currentRow = self.ui.tableWidgetYourIdentities.currentRow()
- addressAtCurrentRow = str(
- self.ui.tableWidgetYourIdentities.item(currentRow, 1).text())
- shared.config.set(addressAtCurrentRow, 'enabled', 'true')
- shared.writeKeysFile()
- self.ui.tableWidgetYourIdentities.item(
- currentRow, 0).setTextColor(QApplication.palette().text().color())
- self.ui.tableWidgetYourIdentities.item(
- currentRow, 1).setTextColor(QApplication.palette().text().color())
- self.ui.tableWidgetYourIdentities.item(
- currentRow, 2).setTextColor(QApplication.palette().text().color())
- if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'):
- self.ui.tableWidgetYourIdentities.item(currentRow, 1).setTextColor(QtGui.QColor(137, 04, 177)) # magenta
- if shared.safeConfigGetBoolean(addressAtCurrentRow, 'chan'):
- self.ui.tableWidgetYourIdentities.item(currentRow, 1).setTextColor(QtGui.QColor(216, 119, 0)) # orange
- shared.reloadMyAddressHashes()
-
- def on_action_YourIdentitiesDisable(self):
- currentRow = self.ui.tableWidgetYourIdentities.currentRow()
- addressAtCurrentRow = str(
- self.ui.tableWidgetYourIdentities.item(currentRow, 1).text())
- shared.config.set(str(addressAtCurrentRow), 'enabled', 'false')
- self.ui.tableWidgetYourIdentities.item(
- currentRow, 0).setTextColor(QtGui.QColor(128, 128, 128))
- self.ui.tableWidgetYourIdentities.item(
- currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128))
- self.ui.tableWidgetYourIdentities.item(
- currentRow, 2).setTextColor(QtGui.QColor(128, 128, 128))
- if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'):
- self.ui.tableWidgetYourIdentities.item(currentRow, 1).setTextColor(QtGui.QColor(137, 04, 177)) # magenta
+ def on_action_YourIdentitiesDelete(self):
+ account = self.getCurrentItem()
+ if account.type == AccountMixin.NORMAL:
+ return # maybe in the future
+ 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?"), QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes:
+ shared.config.remove_section(str(account.address))
+ else:
+ return
+ else:
+ return
shared.writeKeysFile()
shared.reloadMyAddressHashes()
+ self.rerenderAddressBook()
+ if account.type == AccountMixin.NORMAL:
+ self.rerenderTabTreeMessages()
+ elif account.type == AccountMixin.CHAN:
+ self.rerenderTabTreeChans()
- def on_action_YourIdentitiesClipboard(self):
- currentRow = self.ui.tableWidgetYourIdentities.currentRow()
- addressAtCurrentRow = self.ui.tableWidgetYourIdentities.item(
- currentRow, 1).text()
+ def on_action_Enable(self):
+ addressAtCurrentRow = self.getCurrentAccount()
+ self.enableIdentity(addressAtCurrentRow)
+ account = self.getCurrentItem()
+ account.setEnabled(True)
+
+ def enableIdentity(self, address):
+ shared.config.set(address, 'enabled', 'true')
+ shared.writeKeysFile()
+ shared.reloadMyAddressHashes()
+ self.rerenderAddressBook()
+
+ def on_action_Disable(self):
+ address = self.getCurrentAccount()
+ self.disableIdentity(address)
+ account = self.getCurrentItem()
+ account.setEnabled(False)
+
+ def disableIdentity(self, address):
+ shared.config.set(str(address), 'enabled', 'false')
+ shared.writeKeysFile()
+ shared.reloadMyAddressHashes()
+ self.rerenderAddressBook()
+
+ def on_action_Clipboard(self):
+ address = self.getCurrentAccount()
clipboard = QtGui.QApplication.clipboard()
- clipboard.setText(str(addressAtCurrentRow))
+ clipboard.setText(str(address))
+
+ #set avatar functions
+ def on_action_TreeWidgetSetAvatar(self):
+ address = self.getCurrentAccount()
+ self.setAvatar(address)
- def on_action_YourIdentitiesSetAvatar(self):
- self.on_action_SetAvatar(self.ui.tableWidgetYourIdentities)
-
def on_action_AddressBookSetAvatar(self):
self.on_action_SetAvatar(self.ui.tableWidgetAddressBook)
- def on_action_SubscriptionsSetAvatar(self):
- self.on_action_SetAvatar(self.ui.tableWidgetSubscriptions)
-
def on_action_BlacklistSetAvatar(self):
self.on_action_SetAvatar(self.ui.tableWidgetBlacklist)
-
+
def on_action_SetAvatar(self, thisTableWidget):
- # thisTableWidget = self.ui.tableWidgetYourIdentities
- if not os.path.exists(shared.appdata + 'avatars/'):
- os.makedirs(shared.appdata + 'avatars/')
currentRow = thisTableWidget.currentRow()
addressAtCurrentRow = thisTableWidget.item(
currentRow, 1).text()
+ setToIdenticon = not self.setAvatar(addressAtCurrentRow)
+ if setToIdenticon:
+ thisTableWidget.item(
+ currentRow, 0).setIcon(avatarize(addressAtCurrentRow))
+
+ def setAvatar(self, addressAtCurrentRow):
+ if not os.path.exists(shared.appdata + 'avatars/'):
+ os.makedirs(shared.appdata + 'avatars/')
hash = hashlib.md5(addBMIfNotPresent(addressAtCurrentRow)).hexdigest()
extensions = ['PNG', 'GIF', 'JPG', 'JPEG', 'SVG', 'BMP', 'MNG', 'PBM', 'PGM', 'PPM', 'TIFF', 'XBM', 'XPM', 'TGA']
# http://pyqt.sourceforge.net/Docs/PyQt4/qimagereader.html#supportedImageFormats
@@ -3229,25 +3776,79 @@ more work your computer must do to send the message. A Time-To-Live of four or f
if sourcefile != '':
copied = QtCore.QFile.copy(sourcefile, destination)
if not copied:
- print 'couldn\'t copy :('
- return False
+ logger.error('couldn\'t copy :(')
# set the icon
- thisTableWidget.item(
- currentRow, 0).setIcon(avatarize(addressAtCurrentRow))
- self.rerenderSubscriptions()
+ self.rerenderTabTreeMessages()
+ self.rerenderTabTreeSubscriptions()
+ self.rerenderTabTreeChans()
self.rerenderComboBoxSendFrom()
+ self.rerenderComboBoxSendFromBroadcast()
self.rerenderInboxFromLabels()
self.rerenderInboxToLabels()
self.rerenderSentFromLabels()
self.rerenderSentToLabels()
self.rerenderBlackWhiteList()
+ # generate identicon
+ return False
+
+ return True
def on_context_menuYourIdentities(self, point):
+ self.popMenuYourIdentities = QtGui.QMenu(self)
+ self.popMenuYourIdentities.addAction(self.actionNewYourIdentities)
+ self.popMenuYourIdentities.addSeparator()
+ self.popMenuYourIdentities.addAction(self.actionClipboardYourIdentities)
+ self.popMenuYourIdentities.addSeparator()
+ if self.getCurrentItem().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.exec_(
+ self.ui.treeWidgetYourIdentities.mapToGlobal(point))
+
+ # TODO make one popMenu
+ def on_context_menuChan(self, point):
+ self.popMenu = QtGui.QMenu(self)
+ self.popMenu.addAction(self.actionNew)
+ self.popMenu.addAction(self.actionDelete)
+ self.popMenu.addSeparator()
+ self.popMenu.addAction(self.actionClipboard)
+ self.popMenu.addSeparator()
+ if self.getCurrentItem().isEnabled:
+ self.popMenu.addAction(self.actionDisable)
+ else:
+ self.popMenu.addAction(self.actionEnable)
+ self.popMenu.addAction(self.actionSetAvatar)
self.popMenu.exec_(
- self.ui.tableWidgetYourIdentities.mapToGlobal(point))
+ self.ui.treeWidgetChans.mapToGlobal(point))
def on_context_menuInbox(self, point):
- self.popMenuInbox.exec_(self.ui.tableWidgetInbox.mapToGlobal(point))
+ tableWidget = self.getCurrentMessagelist()
+ if tableWidget:
+ currentFolder = self.getCurrentFolder()
+ if currentFolder is None:
+ pass
+ if currentFolder == 'sent':
+ self.on_context_menuSent(point)
+ else:
+ self.popMenuInbox = QtGui.QMenu(self)
+ self.popMenuInbox.addAction(self.actionForceHtml)
+ self.popMenuInbox.addAction(self.actionMarkUnread)
+ self.popMenuInbox.addSeparator()
+ self.popMenuInbox.addAction(self.actionReply)
+ self.popMenuInbox.addAction(self.actionAddSenderToAddressBook)
+ self.popMenuInbox.addSeparator()
+ self.popMenuInbox.addAction(self.actionAddSenderToBlackList)
+ self.popMenuInbox.addSeparator()
+ 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))
def on_context_menuSent(self, point):
self.popMenuSent = QtGui.QMenu(self)
@@ -3256,105 +3857,133 @@ more work your computer must do to send the message. A Time-To-Live of four or f
# Check to see if this item is toodifficult and display an additional
# menu option (Force Send) if it is.
- currentRow = self.ui.tableWidgetSent.currentRow()
- ackData = str(self.ui.tableWidgetSent.item(
- currentRow, 3).data(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.tableWidgetSent.mapToGlobal(point))
-
- def inboxSearchLineEditPressed(self):
- searchKeyword = self.ui.inboxSearchLineEdit.text().toUtf8().data()
- searchOption = self.ui.inboxSearchOptionCB.currentText().toUtf8().data()
- self.ui.inboxSearchLineEdit.setText(QString(""))
- self.ui.textEditInboxMessage.setPlainText(QString(""))
- self.loadInbox(searchOption, searchKeyword)
-
- def sentSearchLineEditPressed(self):
- searchKeyword = self.ui.sentSearchLineEdit.text().toUtf8().data()
- searchOption = self.ui.sentSearchOptionCB.currentText().toUtf8().data()
- self.ui.sentSearchLineEdit.setText(QString(""))
- self.ui.textEditInboxMessage.setPlainText(QString(""))
- self.loadSent(searchOption, searchKeyword)
-
- def tableWidgetInboxItemClicked(self):
currentRow = self.ui.tableWidgetInbox.currentRow()
if currentRow >= 0:
- font = QFont()
- font.setBold(False)
- self.ui.textEditInboxMessage.setCurrentFont(font)
-
- fromAddress = str(self.ui.tableWidgetInbox.item(
- currentRow, 1).data(Qt.UserRole).toPyObject())
- msgid = str(self.ui.tableWidgetInbox.item(
+ ackData = str(self.ui.tableWidgetInbox.item(
currentRow, 3).data(Qt.UserRole).toPyObject())
- queryreturn = sqlQuery(
- '''select message from inbox where msgid=?''', msgid)
- if queryreturn != []:
- for row in queryreturn:
- messageText, = row
- messageText = shared.fixPotentiallyInvalidUTF8Data(messageText)
- messageText = unicode(messageText, 'utf-8)')
- if len(messageText) > 30000:
- messageText = (
- messageText[:30000] + '\n' +
- '--- Display of the remainder of the message ' +
- 'truncated because it is too long.\n' +
- '--- To see the full message, right-click in the ' +
- 'Inbox view and select "View HTML code as formatted ' +
- 'text",\n' +
- '--- or select "Save message as..." to save it to a ' +
- 'file, or select "Reply" and ' +
- 'view the full message in the quote.')
- # If we have received this message from either a broadcast address
- # or from someone in our address book, display as HTML
- if decodeAddress(fromAddress)[3] in shared.broadcastSendersForWhichImWatching or shared.isAddressInMyAddressBook(fromAddress):
- self.ui.textEditInboxMessage.setText(messageText)
+ 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))
+
+ def inboxSearchLineEditPressed(self):
+ searchLine = self.getCurrentSearchLine()
+ searchOption = self.getCurrentSearchOption()
+ if searchLine:
+ searchKeyword = searchLine.text().toUtf8().data()
+ searchLine.setText(QString(""))
+ messageTextedit = self.getCurrentMessageTextedit()
+ if messageTextedit:
+ messageTextedit.setPlainText(QString(""))
+ messagelist = self.getCurrentMessagelist()
+ if messagelist:
+ account = self.getCurrentAccount()
+ folder = self.getCurrentFolder()
+ self.loadMessagelist(messagelist, account, folder, searchOption, searchKeyword)
+
+ def treeWidgetItemClicked(self):
+ messagelist = self.getCurrentMessagelist()
+ if messagelist:
+ account = self.getCurrentAccount()
+ folder = self.getCurrentFolder()
+ if folder == "new":
+ self.loadMessagelist(messagelist, account, None, unreadOnly = True)
else:
- self.ui.textEditInboxMessage.setPlainText(messageText)
+ self.loadMessagelist(messagelist, account, folder)
- self.ui.tableWidgetInbox.item(currentRow, 0).setFont(font)
- self.ui.tableWidgetInbox.item(currentRow, 1).setFont(font)
- self.ui.tableWidgetInbox.item(currentRow, 2).setFont(font)
- self.ui.tableWidgetInbox.item(currentRow, 3).setFont(font)
+ def treeWidgetItemChanged(self, item, column):
+ # only for manual edits. automatic edits (setText) are ignored
+ if column != 0:
+ return
+ # only account names of normal addresses (no chans/mailinglists)
+ if (not isinstance(item, Ui_AddressWidget)) or (not self.getCurrentTreeWidget()) or 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
+
+ newLabel = str(item.text(0))
+ if item.type == AccountMixin.SUBSCRIPTION:
+ oldLabel = item.label
+ else:
+ oldLabel = shared.config.get(str(item.address), 'label')
+ # unchanged, do not do anything either
+ if newLabel == oldLabel:
+ return
- inventoryHash = str(self.ui.tableWidgetInbox.item(
- currentRow, 3).data(Qt.UserRole).toPyObject())
- self.ubuntuMessagingMenuClear(inventoryHash)
- sqlExecute('''update inbox set read=1 WHERE msgid=?''', inventoryHash)
- self.changedInboxUnread()
+ # recursion prevention
+ if self.recurDepth > 0:
+ return
- def tableWidgetSentItemClicked(self):
- currentRow = self.ui.tableWidgetSent.currentRow()
- if currentRow >= 0:
- ackdata = str(self.ui.tableWidgetSent.item(
- currentRow, 3).data(Qt.UserRole).toPyObject())
- queryreturn = sqlQuery(
- '''select message from sent where ackdata=?''', ackdata)
- if queryreturn != []:
- for row in queryreturn:
- message, = row
- else:
- message = "Error occurred: could not load message from disk."
- message = unicode(message, 'utf-8)')
- self.ui.textEditSentMessage.setPlainText(message)
-
- def tableWidgetYourIdentitiesItemChanged(self):
- currentRow = self.ui.tableWidgetYourIdentities.currentRow()
- if currentRow >= 0:
- addressAtCurrentRow = self.ui.tableWidgetYourIdentities.item(
- currentRow, 1).text()
- shared.config.set(str(addressAtCurrentRow), 'label', str(
- self.ui.tableWidgetYourIdentities.item(currentRow, 0).text().toUtf8()))
- shared.writeKeysFile()
+ self.recurDepth += 1
+ item.setData(0, QtCore.Qt.EditRole, newLabel)
+ item.updateText()
+ if item.type == AccountMixin.MAILINGLIST:
+ self.rerenderComboBoxSendFromBroadcast()
+ elif item.type != AccountMixin.SUBSCRIPTION:
self.rerenderComboBoxSendFrom()
- # self.rerenderInboxFromLabels()
- self.rerenderInboxToLabels()
- self.rerenderSentFromLabels()
- # self.rerenderSentToLabels()
+ self.recurDepth -= 1
+
+ def tableWidgetInboxItemClicked(self):
+ folder = self.getCurrentFolder()
+ messageTextedit = self.getCurrentMessageTextedit()
+ if not messageTextedit:
+ return
+ queryreturn = []
+ message = ""
+
+ if folder == 'sent':
+ ackdata = self.getCurrentMessageId()
+ if ackdata and messageTextedit:
+ queryreturn = sqlQuery(
+ '''select message, 1 from sent where ackdata=?''', ackdata)
+ else:
+ msgid = self.getCurrentMessageId()
+ if msgid and messageTextedit:
+ queryreturn = sqlQuery(
+ '''select message, read from inbox where msgid=?''', msgid)
+
+ if queryreturn != []:
+ refresh = False
+ for row in queryreturn:
+ message, read = row
+ if folder != 'sent' and read == 0:
+ markread = sqlQuery(
+ '''UPDATE inbox SET read = 1 WHERE msgid = ?''', msgid)
+ refresh = True
+ if refresh:
+ tableWidget = self.getCurrentMessagelist()
+ if not tableWidget:
+ return
+ font = QFont()
+ font.setBold(False)
+# inventoryHashesToMarkRead = []
+ currentRow = tableWidget.currentRow()
+# inventoryHashToMarkRead = str(tableWidget.item(
+# currentRow, 3).data(Qt.UserRole).toPyObject())
+# inventoryHashesToMarkRead.append(inventoryHashToMarkRead)
+ tableWidget.item(currentRow, 0).setFont(font)
+ tableWidget.item(currentRow, 0).setTextColor(AccountColor(str(tableWidget.item(currentRow, 0).data(Qt.UserRole).toPyObject())).accountColor())
+ tableWidget.item(currentRow, 1).setFont(font)
+ tableWidget.item(currentRow, 1).setTextColor(AccountColor(str(tableWidget.item(currentRow, 1).data(Qt.UserRole).toPyObject())).accountColor())
+ tableWidget.item(currentRow, 2).setFont(font)
+ tableWidget.item(currentRow, 3).setFont(font)
+ self.propagateUnreadCount(str(tableWidget.item(currentRow, 1 if tableWidget == self.ui.tableWidgetInboxSubscriptions else 0).data(Qt.UserRole).toPyObject()), folder, self.getCurrentTreeWidget(), -1)
+
+ else:
+ data = self.getCurrentMessageId()
+ if data != False:
+ message = "Error occurred: could not load message from disk."
+ message = unicode(message, 'utf-8)')
+ messageTextedit.setCurrentFont(QtGui.QFont())
+ messageTextedit.setTextColor(QtGui.QColor())
+ messageTextedit.setPlainText(message)
def tableWidgetAddressBookItemChanged(self):
currentRow = self.ui.tableWidgetAddressBook.currentRow()
@@ -3364,47 +3993,34 @@ more work your computer must do to send the message. A Time-To-Live of four or f
sqlExecute('''UPDATE addressbook set label=? WHERE address=?''',
str(self.ui.tableWidgetAddressBook.item(currentRow, 0).text().toUtf8()),
str(addressAtCurrentRow))
- self.rerenderInboxFromLabels()
- self.rerenderSentToLabels()
-
- def tableWidgetSubscriptionsItemChanged(self):
- currentRow = self.ui.tableWidgetSubscriptions.currentRow()
- if currentRow >= 0:
- addressAtCurrentRow = self.ui.tableWidgetSubscriptions.item(
- currentRow, 1).text()
- sqlExecute('''UPDATE subscriptions set label=? WHERE address=?''',
- str(self.ui.tableWidgetSubscriptions.item(currentRow, 0).text().toUtf8()),
- str(addressAtCurrentRow))
+ self.ui.tableWidgetAddressBook.item(currentRow, 0).setLabel(str(self.ui.tableWidgetAddressBook.item(currentRow, 0).text().toUtf8()))
self.rerenderInboxFromLabels()
self.rerenderSentToLabels()
def writeNewAddressToTable(self, label, address, streamNumber):
- self.ui.tableWidgetYourIdentities.setSortingEnabled(False)
- self.ui.tableWidgetYourIdentities.insertRow(0)
- newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8'))
- newItem.setIcon(avatarize(address))
- self.ui.tableWidgetYourIdentities.setItem(
- 0, 0, newItem)
- newItem = QtGui.QTableWidgetItem(address)
- newItem.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- if shared.safeConfigGetBoolean(address, 'chan'):
- newItem.setTextColor(QtGui.QColor(216, 119, 0)) # orange
- self.ui.tableWidgetYourIdentities.setItem(0, 1, newItem)
- newItem = QtGui.QTableWidgetItem(streamNumber)
- newItem.setFlags(
- QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- self.ui.tableWidgetYourIdentities.setItem(0, 2, newItem)
- # self.ui.tableWidgetYourIdentities.setSortingEnabled(True)
+ self.rerenderTabTreeMessages()
+ self.rerenderTabTreeSubscriptions()
+ self.rerenderTabTreeChans()
self.rerenderComboBoxSendFrom()
+ self.rerenderComboBoxSendFromBroadcast()
def updateStatusBar(self, data):
if data != "":
- with shared.printLock:
- print 'Status bar:', data
+ logger.info('Status bar: ' + data)
self.statusBar().showMessage(data)
+ def initSettings(self):
+ 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()
+
class helpDialog(QtGui.QDialog):
@@ -3494,6 +4110,8 @@ class settingsDialog(QtGui.QDialog):
# On the Network settings tab:
self.ui.lineEditTCPPort.setText(str(
shared.config.get('bitmessagesettings', 'port')))
+ self.ui.checkBoxUPnP.setChecked(
+ shared.safeConfigGetBoolean('bitmessagesettings', 'upnp'))
self.ui.checkBoxAuthentication.setChecked(shared.config.getboolean(
'bitmessagesettings', 'socksauthentication'))
self.ui.checkBoxSocksListen.setChecked(shared.config.getboolean(
@@ -3540,6 +4158,16 @@ class settingsDialog(QtGui.QDialog):
self.ui.lineEditMaxAcceptableSmallMessageDifficulty.setText(str((float(shared.config.getint(
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes')) / shared.networkDefaultPayloadLengthExtraBytes)))
+ # OpenCL
+ if openclpow.has_opencl():
+ self.ui.checkBoxOpenCL.setEnabled(True)
+ else:
+ self.ui.checkBoxOpenCL.setEnabled(False)
+ if shared.safeConfigGetBoolean("bitmessagesettings", "opencl"):
+ self.ui.checkBoxOpenCL.setChecked(True)
+ else:
+ self.ui.checkBoxOpenCL.setChecked(False)
+
# Namecoin integration tab
nmctype = shared.config.get('bitmessagesettings', 'namecoinrpctype')
self.ui.lineEditNamecoinHost.setText(str(
@@ -3666,9 +4294,7 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog):
self.ui = Ui_SpecialAddressBehaviorDialog()
self.ui.setupUi(self)
self.parent = parent
- currentRow = parent.ui.tableWidgetYourIdentities.currentRow()
- addressAtCurrentRow = str(
- parent.ui.tableWidgetYourIdentities.item(currentRow, 1).text())
+ addressAtCurrentRow = parent.getCurrentAccount()
if not shared.safeConfigGetBoolean(addressAtCurrentRow, 'chan'):
if shared.safeConfigGetBoolean(addressAtCurrentRow, 'mailinglist'):
self.ui.radioButtonBehaviorMailingList.click()
@@ -3688,6 +4314,25 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog):
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self))
+class EmailGatewayDialog(QtGui.QDialog):
+
+ def __init__(self, parent):
+ QtGui.QWidget.__init__(self, parent)
+ self.ui = Ui_EmailGatewayDialog()
+ self.ui.setupUi(self)
+ self.parent = parent
+ addressAtCurrentRow = parent.getCurrentAccount()
+ acct = accountClass(addressAtCurrentRow)
+ if isinstance(acct, GatewayAccount):
+ self.ui.radioButtonUnregister.setEnabled(True)
+ else:
+ self.ui.radioButtonUnregister.setEnabled(False)
+ label = shared.config.get(addressAtCurrentRow, 'label')
+ if label.find("@mailchuck.com") > -1:
+ self.ui.lineEditEmail.setText(label)
+
+ QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self))
+
class AddAddressDialog(QtGui.QDialog):
@@ -3799,10 +4444,10 @@ class NewAddressDialog(QtGui.QDialog):
row = 1
# Let's fill out the 'existing address' combo box with addresses from
# the 'Your Identities' tab.
- while self.parent.ui.tableWidgetYourIdentities.item(row - 1, 1):
+ for addressInKeysFile in getSortedAccounts():
self.ui.radioButtonExisting.click()
self.ui.comboBoxExisting.addItem(
- self.parent.ui.tableWidgetYourIdentities.item(row - 1, 1).text())
+ addressInKeysFile)
row += 1
self.ui.groupBoxDeterministic.setHidden(True)
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self))
@@ -3894,6 +4539,8 @@ class UISignaler(QThread):
self.emit(SIGNAL("rerenderBlackWhiteList()"))
elif command == 'removeInboxRowByMsgid':
self.emit(SIGNAL("removeInboxRowByMsgid(PyQt_PyObject)"), data)
+ elif command == 'newVersionAvailable':
+ self.emit(SIGNAL("newVersionAvailable(PyQt_PyObject)"), data)
elif command == 'alert':
title, text, exitAfterUserClicksOk = data
self.emit(SIGNAL("displayAlert(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)"), title, text, exitAfterUserClicksOk)
@@ -3901,18 +4548,88 @@ class UISignaler(QThread):
sys.stderr.write(
'Command sent to UISignaler not recognized: %s\n' % command)
+
+app = None
+myapp = None
+
+class MySingleApplication(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):
+ 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, singleton.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):
+ if self.server:
+ self.server.close()
+
+ def on_new_connection(self):
+ global myapp
+ if myapp:
+ myapp.appIndicatorShow()
+
+def init():
+ global app
+ if not app:
+ app = MySingleApplication(sys.argv)
+ return app
+
def run():
- app = QtGui.QApplication(sys.argv)
+ global myapp
+ app = init()
change_translation(l10n.getTranslationLanguage())
app.setStyleSheet("QStatusBar::item { border: 0px solid black }")
myapp = MyForm()
- if not shared.config.getboolean('bitmessagesettings', 'startintray'):
- myapp.show()
-
myapp.appIndicatorInit(app)
myapp.ubuntuMessagingMenuInit()
myapp.notifierInit()
if shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'):
myapp.showConnectDialog() # ask the user if we may connect
+
+# try:
+# if shared.config.get('bitmessagesettings', 'mailchuck') < 1:
+# myapp.showMigrationWizard(shared.config.get('bitmessagesettings', 'mailchuck'))
+# except:
+# myapp.showMigrationWizard(0)
+
+ # only show after wizards and connect dialogs have completed
+ if not shared.config.getboolean('bitmessagesettings', 'startintray'):
+ myapp.show()
+
sys.exit(app.exec_())
diff --git a/src/bitmessageqt/account.py b/src/bitmessageqt/account.py
new file mode 100644
index 00000000..dc21d669
--- /dev/null
+++ b/src/bitmessageqt/account.py
@@ -0,0 +1,222 @@
+from PyQt4 import QtCore, QtGui
+
+import shared
+import re
+import sys
+import inspect
+from helper_sql import *
+from addresses import decodeAddress
+from foldertree import AccountMixin
+from pyelliptic.openssl import OpenSSL
+from utils import str_broadcast_subscribers
+import time
+
+def getSortedAccounts():
+ configSections = filter(lambda x: x != 'bitmessagesettings', shared.config.sections())
+ configSections.sort(cmp =
+ lambda x,y: cmp(unicode(shared.config.get(x, 'label'), 'utf-8').lower(), unicode(shared.config.get(y, 'label'), 'utf-8').lower())
+ )
+ return configSections
+
+def getSortedSubscriptions(count = False):
+ queryreturn = sqlQuery('SELECT label, address, enabled FROM subscriptions ORDER BY label COLLATE NOCASE ASC')
+ ret = {}
+ for row in queryreturn:
+ label, address, enabled = row
+ ret[address] = {}
+ ret[address]["inbox"] = {}
+ ret[address]["inbox"]['label'] = label
+ ret[address]["inbox"]['enabled'] = enabled
+ ret[address]["inbox"]['count'] = 0
+ if count:
+ queryreturn = sqlQuery('''SELECT fromaddress, folder, count(msgid) as cnt
+ FROM inbox, subscriptions
+ WHERE read = 0 AND subscriptions.address = inbox.fromaddress
+ GROUP BY inbox.fromaddress, folder''')
+ for row in queryreturn:
+ address, folder, cnt = row
+ ret[address][folder]['count'] = cnt
+ return ret
+
+def accountClass(address):
+ if not shared.config.has_section(address):
+ if address == str_broadcast_subscribers:
+ subscription = BroadcastAccount(address)
+ if subscription.type != AccountMixin.BROADCAST:
+ return None
+ else:
+ subscription = SubscriptionAccount(address)
+ if subscription.type != AccountMixin.SUBSCRIPTION:
+ return None
+ return subscription
+ try:
+ gateway = shared.config.get(address, "gateway")
+ for name, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass):
+# obj = g(address)
+ if issubclass(cls, GatewayAccount) and cls.gatewayName == gateway:
+ return cls(address)
+ # general gateway
+ return GatewayAccount(address)
+ except:
+ pass
+ # no gateway
+ return BMAccount(address)
+
+class AccountColor(AccountMixin):
+ def __init__(self, address, type = None):
+ self.isEnabled = True
+ self.address = address
+ if type is None:
+ if address is None:
+ self.type = AccountMixin.ALL
+ elif shared.safeConfigGetBoolean(self.address, 'mailinglist'):
+ self.type = AccountMixin.MAILINGLIST
+ elif shared.safeConfigGetBoolean(self.address, 'chan'):
+ self.type = AccountMixin.CHAN
+ elif sqlQuery(
+ '''select label from subscriptions where address=?''', self.address):
+ self.type = AccountMixin.SUBSCRIPTION
+ else:
+ self.type = AccountMixin.NORMAL
+ else:
+ self.type = type
+
+
+class BMAccount(object):
+ def __init__(self, address = None):
+ self.address = address
+ self.type = AccountMixin.NORMAL
+ if shared.config.has_section(address):
+ if shared.safeConfigGetBoolean(self.address, 'chan'):
+ self.type = AccountMixin.CHAN
+ elif shared.safeConfigGetBoolean(self.address, 'mailinglist'):
+ self.type = AccountMixin.MAILINGLIST
+ elif self.address == str_broadcast_subscribers:
+ self.type = AccountMixin.BROADCAST
+ else:
+ queryreturn = sqlQuery(
+ '''select label from subscriptions where address=?''', self.address)
+ if queryreturn:
+ self.type = AccountMixin.SUBSCRIPTION
+
+ def getLabel(self, address = None):
+ if address is None:
+ address = self.address
+ label = address
+ if shared.config.has_section(address):
+ label = shared.config.get(address, 'label')
+ queryreturn = sqlQuery(
+ '''select label from addressbook where address=?''', address)
+ if queryreturn != []:
+ for row in queryreturn:
+ label, = row
+ else:
+ queryreturn = sqlQuery(
+ '''select label from subscriptions where address=?''', address)
+ if queryreturn != []:
+ for row in queryreturn:
+ label, = row
+ return label
+
+ def parseMessage(self, toAddress, fromAddress, subject, message):
+ self.toAddress = toAddress
+ self.fromAddress = fromAddress
+ self.subject = subject
+ self.message = message
+ self.fromLabel = self.getLabel(fromAddress)
+ self.toLabel = self.getLabel(toAddress)
+
+
+class SubscriptionAccount(BMAccount):
+ pass
+
+
+class BroadcastAccount(BMAccount):
+ pass
+
+
+class GatewayAccount(BMAccount):
+ gatewayName = None
+ def __init__(self, address):
+ super(BMAccount, self).__init__(address)
+
+ def send(self):
+ status, addressVersionNumber, streamNumber, ripe = decodeAddress(self.toAddress)
+ ackdata = OpenSSL.rand(32)
+ t = ()
+ sqlExecute(
+ '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''',
+ '',
+ self.toAddress,
+ ripe,
+ self.fromAddress,
+ self.subject,
+ self.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.
+ 'msgqueued',
+ 0, # retryNumber
+ 'sent', # folder
+ 2, # encodingtype
+ shared.config.getint('bitmessagesettings', 'ttl')
+ )
+
+ shared.workerQueue.put(('sendmessage', self.toAddress))
+
+ def parseMessage(self, toAddress, fromAddress, subject, message):
+ super(BMAccount, self).parseMessage(toAddress, fromAddress, subject, message)
+
+class MailchuckAccount(GatewayAccount):
+ # set "gateway" in keys.dat to this
+ gatewayName = "mailchuck"
+ registrationAddress = "BM-2cVYYrhaY5Gbi3KqrX9Eae2NRNrkfrhCSA"
+ unregistrationAddress = "BM-2cVMAHTRjZHCTPMue75XBK5Tco175DtJ9J"
+ relayAddress = "BM-2cWim8aZwUNqxzjMxstnUMtVEUQJeezstf"
+ regExpIncoming = re.compile("(.*)MAILCHUCK-FROM::(\S+) \| (.*)")
+ regExpOutgoing = re.compile("(\S+) (.*)")
+ def __init__(self, address):
+ super(GatewayAccount, self).__init__(address)
+
+ def createMessage(self, toAddress, fromAddress, subject, message):
+ self.subject = toAddress + " " + subject
+ self.toAddress = self.relayAddress
+ self.fromAddress = fromAddress
+ self.message = message
+
+ def register(self, email):
+ self.toAddress = self.registrationAddress
+ self.subject = email
+ self.message = ""
+ self.fromAddress = self.address
+ self.send()
+
+ def unregister(self):
+ self.toAddress = self.unregistrationAddress
+ self.subject = ""
+ self.message = ""
+ self.fromAddress = self.address
+ self.send()
+
+ def parseMessage(self, toAddress, fromAddress, subject, message):
+ super(GatewayAccount, self).parseMessage(toAddress, fromAddress, subject, message)
+ if fromAddress == self.relayAddress:
+ matches = self.regExpIncoming.search(subject)
+ if not matches is None:
+ self.subject = ""
+ if not matches.group(1) is None:
+ self.subject += matches.group(1)
+ if not matches.group(3) is None:
+ self.subject += matches.group(3)
+ if not matches.group(2) is None:
+ self.fromLabel = matches.group(2)
+ self.fromAddress = matches.group(2)
+ if toAddress == self.relayAddress:
+ matches = self.regExpOutgoing.search(subject)
+ if not matches is None:
+ if not matches.group(2) is None:
+ self.subject = matches.group(2)
+ if not matches.group(1) is None:
+ self.toLabel = matches.group(1)
+ self.toAddress = matches.group(1)
\ No newline at end of file
diff --git a/src/bitmessageqt/bitmessageui.py b/src/bitmessageqt/bitmessageui.py
index e35b30cd..e303567f 100644
--- a/src/bitmessageqt/bitmessageui.py
+++ b/src/bitmessageqt/bitmessageui.py
@@ -2,12 +2,13 @@
# Form implementation generated from reading ui file 'bitmessageui.ui'
#
-# Created: Sun Mar 08 22:07:43 2015
-# by: PyQt4 UI code generator 4.10.3
+# Created: Mon Mar 23 22:18:07 2015
+# by: PyQt4 UI code generator 4.10.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
+import settingsmixin
try:
_fromUtf8 = QtCore.QString.fromUtf8
@@ -33,9 +34,8 @@ class Ui_MainWindow(object):
MainWindow.setTabShape(QtGui.QTabWidget.Rounded)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
- self.gridLayout = QtGui.QGridLayout(self.centralwidget)
- self.gridLayout.setMargin(0)
- self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
+ self.gridLayout_10 = QtGui.QGridLayout(self.centralwidget)
+ self.gridLayout_10.setObjectName(_fromUtf8("gridLayout_10"))
self.tabWidget = QtGui.QTabWidget(self.centralwidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
@@ -52,27 +52,52 @@ class Ui_MainWindow(object):
self.tabWidget.setObjectName(_fromUtf8("tabWidget"))
self.inbox = QtGui.QWidget()
self.inbox.setObjectName(_fromUtf8("inbox"))
- self.verticalLayout_2 = QtGui.QVBoxLayout(self.inbox)
- self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
- self.horizontalLayoutSearch = QtGui.QHBoxLayout()
- self.horizontalLayoutSearch.setContentsMargins(-1, 0, -1, -1)
- self.horizontalLayoutSearch.setObjectName(_fromUtf8("horizontalLayoutSearch"))
+ self.gridLayout = QtGui.QGridLayout(self.inbox)
+ self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
+ self.horizontalSplitter_3 = settingsmixin.SSplitter()
+ self.horizontalSplitter_3.setObjectName(_fromUtf8("horizontalSplitter_3"))
+ self.verticalSplitter_12 = settingsmixin.SSplitter()
+ self.verticalSplitter_12.setObjectName(_fromUtf8("verticalSplitter_12"))
+ self.verticalSplitter_12.setOrientation(QtCore.Qt.Vertical)
+ self.treeWidgetYourIdentities = settingsmixin.STreeWidget(self.inbox)
+ self.treeWidgetYourIdentities.setObjectName(_fromUtf8("treeWidgetYourIdentities"))
+ self.treeWidgetYourIdentities.resize(200, self.treeWidgetYourIdentities.height())
+ icon1 = QtGui.QIcon()
+ icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/identities.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off)
+ self.treeWidgetYourIdentities.headerItem().setIcon(0, icon1)
+ self.verticalSplitter_12.addWidget(self.treeWidgetYourIdentities)
+ self.pushButtonNewAddress = QtGui.QPushButton(self.inbox)
+ self.pushButtonNewAddress.setObjectName(_fromUtf8("pushButtonNewAddress"))
+ self.pushButtonNewAddress.resize(200, self.pushButtonNewAddress.height())
+ self.verticalSplitter_12.addWidget(self.pushButtonNewAddress)
+ self.verticalSplitter_12.setStretchFactor(0, 1)
+ self.verticalSplitter_12.setStretchFactor(1, 0)
+ self.verticalSplitter_12.setCollapsible(0, False)
+ self.verticalSplitter_12.setCollapsible(1, False)
+ self.verticalSplitter_12.handle(1).setEnabled(False)
+ self.horizontalSplitter_3.addWidget(self.verticalSplitter_12)
+ self.verticalSplitter_7 = settingsmixin.SSplitter()
+ self.verticalSplitter_7.setObjectName(_fromUtf8("verticalSplitter_7"))
+ self.verticalSplitter_7.setOrientation(QtCore.Qt.Vertical)
+ self.horizontalSplitterSearch = QtGui.QSplitter()
+ self.horizontalSplitterSearch.setObjectName(_fromUtf8("horizontalSplitterSearch"))
self.inboxSearchLineEdit = QtGui.QLineEdit(self.inbox)
self.inboxSearchLineEdit.setObjectName(_fromUtf8("inboxSearchLineEdit"))
- self.horizontalLayoutSearch.addWidget(self.inboxSearchLineEdit)
- self.inboxSearchOptionCB = QtGui.QComboBox(self.inbox)
- self.inboxSearchOptionCB.setObjectName(_fromUtf8("inboxSearchOptionCB"))
- self.inboxSearchOptionCB.addItem(_fromUtf8(""))
- self.inboxSearchOptionCB.addItem(_fromUtf8(""))
- self.inboxSearchOptionCB.addItem(_fromUtf8(""))
- self.inboxSearchOptionCB.addItem(_fromUtf8(""))
- self.inboxSearchOptionCB.addItem(_fromUtf8(""))
- self.horizontalLayoutSearch.addWidget(self.inboxSearchOptionCB)
- self.verticalLayout_2.addLayout(self.horizontalLayoutSearch)
- self.splitter = QtGui.QSplitter(self.inbox)
- self.splitter.setOrientation(QtCore.Qt.Vertical)
- self.splitter.setObjectName(_fromUtf8("splitter"))
- self.tableWidgetInbox = QtGui.QTableWidget(self.splitter)
+ self.horizontalSplitterSearch.addWidget(self.inboxSearchLineEdit)
+ self.inboxSearchOption = QtGui.QComboBox(self.inbox)
+ self.inboxSearchOption.setObjectName(_fromUtf8("inboxSearchOption"))
+ self.inboxSearchOption.addItem(_fromUtf8(""))
+ self.inboxSearchOption.addItem(_fromUtf8(""))
+ self.inboxSearchOption.addItem(_fromUtf8(""))
+ self.inboxSearchOption.addItem(_fromUtf8(""))
+ self.inboxSearchOption.addItem(_fromUtf8(""))
+ self.inboxSearchOption.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
+ self.horizontalSplitterSearch.addWidget(self.inboxSearchOption)
+ self.horizontalSplitterSearch.handle(1).setEnabled(False)
+ self.horizontalSplitterSearch.setStretchFactor(0, 1)
+ self.horizontalSplitterSearch.setStretchFactor(1, 0)
+ self.verticalSplitter_7.addWidget(self.horizontalSplitterSearch)
+ self.tableWidgetInbox = settingsmixin.STableWidget(self.inbox)
self.tableWidgetInbox.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.tableWidgetInbox.setAlternatingRowColors(True)
self.tableWidgetInbox.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
@@ -97,84 +122,170 @@ class Ui_MainWindow(object):
self.tableWidgetInbox.horizontalHeader().setStretchLastSection(True)
self.tableWidgetInbox.verticalHeader().setVisible(False)
self.tableWidgetInbox.verticalHeader().setDefaultSectionSize(26)
- self.textEditInboxMessage = QtGui.QTextEdit(self.splitter)
+ self.verticalSplitter_7.addWidget(self.tableWidgetInbox)
+ self.textEditInboxMessage = QtGui.QTextEdit(self.inbox)
self.textEditInboxMessage.setBaseSize(QtCore.QSize(0, 500))
self.textEditInboxMessage.setReadOnly(True)
self.textEditInboxMessage.setObjectName(_fromUtf8("textEditInboxMessage"))
- self.verticalLayout_2.addWidget(self.splitter)
- icon1 = QtGui.QIcon()
- icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/inbox.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
- self.tabWidget.addTab(self.inbox, icon1, _fromUtf8(""))
+ self.verticalSplitter_7.addWidget(self.textEditInboxMessage)
+ self.verticalSplitter_7.setStretchFactor(0, 0)
+ self.verticalSplitter_7.setStretchFactor(1, 1)
+ self.verticalSplitter_7.setStretchFactor(2, 2)
+ self.verticalSplitter_7.setCollapsible(0, False)
+ self.verticalSplitter_7.setCollapsible(1, False)
+ self.verticalSplitter_7.setCollapsible(2, False)
+ self.verticalSplitter_7.handle(1).setEnabled(False)
+ self.horizontalSplitter_3.addWidget(self.verticalSplitter_7)
+ self.horizontalSplitter_3.setStretchFactor(0, 0)
+ self.horizontalSplitter_3.setStretchFactor(1, 1)
+ self.horizontalSplitter_3.setCollapsible(0, False)
+ self.horizontalSplitter_3.setCollapsible(1, False)
+ self.gridLayout.addWidget(self.horizontalSplitter_3)
+ icon2 = QtGui.QIcon()
+ icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/inbox.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.tabWidget.addTab(self.inbox, icon2, _fromUtf8(""))
self.send = QtGui.QWidget()
self.send.setObjectName(_fromUtf8("send"))
- self.gridLayout_2 = QtGui.QGridLayout(self.send)
- self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
- self.pushButtonLoadFromAddressBook = QtGui.QPushButton(self.send)
+ self.gridLayout_7 = QtGui.QGridLayout(self.send)
+ self.gridLayout_7.setObjectName(_fromUtf8("gridLayout_7"))
+ self.horizontalSplitter = settingsmixin.SSplitter()
+ self.horizontalSplitter.setObjectName(_fromUtf8("horizontalSplitter"))
+ self.verticalSplitter_2 = settingsmixin.SSplitter()
+ self.verticalSplitter_2.setObjectName(_fromUtf8("verticalSplitter_2"))
+ self.verticalSplitter_2.setOrientation(QtCore.Qt.Vertical)
+ self.tableWidgetAddressBook = settingsmixin.STableWidget(self.send)
+ self.tableWidgetAddressBook.setAlternatingRowColors(True)
+ self.tableWidgetAddressBook.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
+ self.tableWidgetAddressBook.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
+ self.tableWidgetAddressBook.setObjectName(_fromUtf8("tableWidgetAddressBook"))
+ self.tableWidgetAddressBook.setColumnCount(2)
+ self.tableWidgetAddressBook.setRowCount(0)
+ self.tableWidgetAddressBook.resize(200, self.tableWidgetAddressBook.height())
+ item = QtGui.QTableWidgetItem()
+ icon3 = QtGui.QIcon()
+ icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/addressbook.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off)
+ item.setIcon(icon3)
+ self.tableWidgetAddressBook.setHorizontalHeaderItem(0, item)
+ item = QtGui.QTableWidgetItem()
+ self.tableWidgetAddressBook.setHorizontalHeaderItem(1, item)
+ self.tableWidgetAddressBook.horizontalHeader().setCascadingSectionResizes(True)
+ self.tableWidgetAddressBook.horizontalHeader().setDefaultSectionSize(200)
+ self.tableWidgetAddressBook.horizontalHeader().setHighlightSections(False)
+ self.tableWidgetAddressBook.horizontalHeader().setStretchLastSection(True)
+ self.tableWidgetAddressBook.verticalHeader().setVisible(False)
+ self.verticalSplitter_2.addWidget(self.tableWidgetAddressBook)
+ self.pushButtonAddAddressBook = QtGui.QPushButton(self.send)
+ self.pushButtonAddAddressBook.setObjectName(_fromUtf8("pushButtonAddAddressBook"))
+ self.pushButtonAddAddressBook.resize(200, self.pushButtonAddAddressBook.height())
+ self.verticalSplitter_2.addWidget(self.pushButtonAddAddressBook)
+ self.pushButtonFetchNamecoinID = QtGui.QPushButton(self.send)
+ self.pushButtonFetchNamecoinID.resize(200, self.pushButtonFetchNamecoinID.height())
font = QtGui.QFont()
- font.setPointSize(7)
- self.pushButtonLoadFromAddressBook.setFont(font)
- self.pushButtonLoadFromAddressBook.setObjectName(_fromUtf8("pushButtonLoadFromAddressBook"))
- self.gridLayout_2.addWidget(self.pushButtonLoadFromAddressBook, 3, 2, 1, 1)
- self.label_3 = QtGui.QLabel(self.send)
+ font.setPointSize(9)
+ self.pushButtonFetchNamecoinID.setFont(font)
+ self.pushButtonFetchNamecoinID.setObjectName(_fromUtf8("pushButtonFetchNamecoinID"))
+ self.verticalSplitter_2.addWidget(self.pushButtonFetchNamecoinID)
+ self.verticalSplitter_2.setStretchFactor(0, 1)
+ self.verticalSplitter_2.setStretchFactor(1, 0)
+ self.verticalSplitter_2.setStretchFactor(2, 0)
+ self.verticalSplitter_2.setCollapsible(0, False)
+ self.verticalSplitter_2.setCollapsible(1, False)
+ self.verticalSplitter_2.setCollapsible(2, False)
+ self.verticalSplitter_2.handle(1).setEnabled(False)
+ self.verticalSplitter_2.handle(2).setEnabled(False)
+ self.horizontalSplitter.addWidget(self.verticalSplitter_2)
+ self.verticalSplitter = settingsmixin.SSplitter()
+ self.verticalSplitter.setObjectName(_fromUtf8("verticalSplitter"))
+ self.verticalSplitter.setOrientation(QtCore.Qt.Vertical)
+ self.tabWidgetSend = QtGui.QTabWidget(self.send)
+ self.tabWidgetSend.setObjectName(_fromUtf8("tabWidgetSend"))
+ self.sendDirect = QtGui.QWidget()
+ self.sendDirect.setObjectName(_fromUtf8("sendDirect"))
+ self.gridLayout_8 = QtGui.QGridLayout(self.sendDirect)
+ self.gridLayout_8.setObjectName(_fromUtf8("gridLayout_8"))
+ self.verticalSplitter_5 = settingsmixin.SSplitter()
+ self.verticalSplitter_5.setObjectName(_fromUtf8("verticalSplitter_5"))
+ self.verticalSplitter_5.setOrientation(QtCore.Qt.Vertical)
+ self.gridLayout_2 = QtGui.QGridLayout()
+ self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
+ self.label_3 = QtGui.QLabel(self.sendDirect)
self.label_3.setObjectName(_fromUtf8("label_3"))
- self.gridLayout_2.addWidget(self.label_3, 4, 0, 1, 1)
- self.pushButtonSend = QtGui.QPushButton(self.send)
- self.pushButtonSend.setObjectName(_fromUtf8("pushButtonSend"))
- self.gridLayout_2.addWidget(self.pushButtonSend, 7, 8, 1, 1)
- self.horizontalSliderTTL = QtGui.QSlider(self.send)
- self.horizontalSliderTTL.setMinimumSize(QtCore.QSize(35, 0))
- self.horizontalSliderTTL.setMaximumSize(QtCore.QSize(70, 16777215))
- self.horizontalSliderTTL.setOrientation(QtCore.Qt.Horizontal)
- self.horizontalSliderTTL.setInvertedAppearance(False)
- self.horizontalSliderTTL.setInvertedControls(False)
- self.horizontalSliderTTL.setObjectName(_fromUtf8("horizontalSliderTTL"))
- self.gridLayout_2.addWidget(self.horizontalSliderTTL, 7, 6, 1, 1)
- spacerItem = QtGui.QSpacerItem(20, 297, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
- self.gridLayout_2.addItem(spacerItem, 6, 0, 1, 1)
- self.comboBoxSendFrom = QtGui.QComboBox(self.send)
+ self.gridLayout_2.addWidget(self.label_3, 2, 0, 1, 1)
+ self.label_2 = QtGui.QLabel(self.sendDirect)
+ self.label_2.setObjectName(_fromUtf8("label_2"))
+ self.gridLayout_2.addWidget(self.label_2, 0, 0, 1, 1)
+ self.lineEditSubject = QtGui.QLineEdit(self.sendDirect)
+ self.lineEditSubject.setText(_fromUtf8(""))
+ self.lineEditSubject.setObjectName(_fromUtf8("lineEditSubject"))
+ self.gridLayout_2.addWidget(self.lineEditSubject, 2, 1, 1, 1)
+ self.label = QtGui.QLabel(self.sendDirect)
+ self.label.setObjectName(_fromUtf8("label"))
+ self.gridLayout_2.addWidget(self.label, 1, 0, 1, 1)
+ self.comboBoxSendFrom = QtGui.QComboBox(self.sendDirect)
self.comboBoxSendFrom.setMinimumSize(QtCore.QSize(300, 0))
self.comboBoxSendFrom.setObjectName(_fromUtf8("comboBoxSendFrom"))
- self.gridLayout_2.addWidget(self.comboBoxSendFrom, 2, 1, 1, 1)
- self.labelHumanFriendlyTTLDescription = QtGui.QLabel(self.send)
- sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
- sizePolicy.setHorizontalStretch(0)
- sizePolicy.setVerticalStretch(0)
- sizePolicy.setHeightForWidth(self.labelHumanFriendlyTTLDescription.sizePolicy().hasHeightForWidth())
- self.labelHumanFriendlyTTLDescription.setSizePolicy(sizePolicy)
- self.labelHumanFriendlyTTLDescription.setMinimumSize(QtCore.QSize(45, 0))
- self.labelHumanFriendlyTTLDescription.setMaximumSize(QtCore.QSize(45, 16777215))
- self.labelHumanFriendlyTTLDescription.setObjectName(_fromUtf8("labelHumanFriendlyTTLDescription"))
- self.gridLayout_2.addWidget(self.labelHumanFriendlyTTLDescription, 7, 7, 1, 1)
- self.label_4 = QtGui.QLabel(self.send)
- self.label_4.setObjectName(_fromUtf8("label_4"))
- self.gridLayout_2.addWidget(self.label_4, 5, 0, 1, 1)
- self.label = QtGui.QLabel(self.send)
- self.label.setObjectName(_fromUtf8("label"))
- self.gridLayout_2.addWidget(self.label, 3, 0, 1, 1)
- self.radioButtonSpecific = QtGui.QRadioButton(self.send)
- self.radioButtonSpecific.setChecked(True)
- self.radioButtonSpecific.setObjectName(_fromUtf8("radioButtonSpecific"))
- self.gridLayout_2.addWidget(self.radioButtonSpecific, 0, 1, 1, 1)
- self.labelSendBroadcastWarning = QtGui.QLabel(self.send)
- self.labelSendBroadcastWarning.setEnabled(True)
- sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Ignored, QtGui.QSizePolicy.Preferred)
- sizePolicy.setHorizontalStretch(0)
- sizePolicy.setVerticalStretch(0)
- sizePolicy.setHeightForWidth(self.labelSendBroadcastWarning.sizePolicy().hasHeightForWidth())
- self.labelSendBroadcastWarning.setSizePolicy(sizePolicy)
- self.labelSendBroadcastWarning.setIndent(-1)
- self.labelSendBroadcastWarning.setObjectName(_fromUtf8("labelSendBroadcastWarning"))
- self.gridLayout_2.addWidget(self.labelSendBroadcastWarning, 7, 1, 1, 4)
- self.radioButtonBroadcast = QtGui.QRadioButton(self.send)
- self.radioButtonBroadcast.setObjectName(_fromUtf8("radioButtonBroadcast"))
- self.gridLayout_2.addWidget(self.radioButtonBroadcast, 1, 1, 1, 2)
+ self.gridLayout_2.addWidget(self.comboBoxSendFrom, 0, 1, 1, 1)
+ self.lineEditTo = QtGui.QLineEdit(self.sendDirect)
+ self.lineEditTo.setObjectName(_fromUtf8("lineEditTo"))
+ self.gridLayout_2.addWidget(self.lineEditTo, 1, 1, 1, 1)
+ self.gridLayout_2_Widget = QtGui.QWidget()
+ self.gridLayout_2_Widget.setLayout(self.gridLayout_2)
+ self.verticalSplitter_5.addWidget(self.gridLayout_2_Widget)
+ self.textEditMessage = QtGui.QTextEdit(self.sendDirect)
+ self.textEditMessage.setObjectName(_fromUtf8("textEditMessage"))
+ self.verticalSplitter_5.addWidget(self.textEditMessage)
+ self.verticalSplitter_5.setStretchFactor(0, 0)
+ self.verticalSplitter_5.setStretchFactor(1, 1)
+ self.verticalSplitter_5.setCollapsible(0, False)
+ self.verticalSplitter_5.setCollapsible(1, False)
+ self.verticalSplitter_5.handle(1).setEnabled(False)
+ self.gridLayout_8.addWidget(self.verticalSplitter_5, 0, 0, 1, 1)
+ self.tabWidgetSend.addTab(self.sendDirect, _fromUtf8(""))
+ self.sendBroadcast = QtGui.QWidget()
+ self.sendBroadcast.setObjectName(_fromUtf8("sendBroadcast"))
+ self.gridLayout_9 = QtGui.QGridLayout(self.sendBroadcast)
+ self.gridLayout_9.setObjectName(_fromUtf8("gridLayout_9"))
+ self.verticalSplitter_6 = settingsmixin.SSplitter()
+ self.verticalSplitter_6.setObjectName(_fromUtf8("verticalSplitter_6"))
+ self.verticalSplitter_6.setOrientation(QtCore.Qt.Vertical)
+ self.gridLayout_5 = QtGui.QGridLayout()
+ self.gridLayout_5.setObjectName(_fromUtf8("gridLayout_5"))
+ self.label_8 = QtGui.QLabel(self.sendBroadcast)
+ self.label_8.setObjectName(_fromUtf8("label_8"))
+ self.gridLayout_5.addWidget(self.label_8, 0, 0, 1, 1)
+ self.lineEditSubjectBroadcast = QtGui.QLineEdit(self.sendBroadcast)
+ self.lineEditSubjectBroadcast.setText(_fromUtf8(""))
+ self.lineEditSubjectBroadcast.setObjectName(_fromUtf8("lineEditSubjectBroadcast"))
+ self.gridLayout_5.addWidget(self.lineEditSubjectBroadcast, 1, 1, 1, 1)
+ self.label_7 = QtGui.QLabel(self.sendBroadcast)
+ self.label_7.setObjectName(_fromUtf8("label_7"))
+ self.gridLayout_5.addWidget(self.label_7, 1, 0, 1, 1)
+ self.comboBoxSendFromBroadcast = QtGui.QComboBox(self.sendBroadcast)
+ self.comboBoxSendFromBroadcast.setMinimumSize(QtCore.QSize(300, 0))
+ self.comboBoxSendFromBroadcast.setObjectName(_fromUtf8("comboBoxSendFromBroadcast"))
+ self.gridLayout_5.addWidget(self.comboBoxSendFromBroadcast, 0, 1, 1, 1)
+ self.gridLayout_5_Widget = QtGui.QWidget()
+ self.gridLayout_5_Widget.setLayout(self.gridLayout_5)
+ self.verticalSplitter_6.addWidget(self.gridLayout_5_Widget)
+ self.textEditMessageBroadcast = QtGui.QTextEdit(self.sendBroadcast)
+ self.textEditMessageBroadcast.setObjectName(_fromUtf8("textEditMessageBroadcast"))
+ self.verticalSplitter_6.addWidget(self.textEditMessageBroadcast)
+ self.verticalSplitter_6.setStretchFactor(0, 0)
+ self.verticalSplitter_6.setStretchFactor(1, 1)
+ self.verticalSplitter_6.setCollapsible(0, False)
+ self.verticalSplitter_6.setCollapsible(1, False)
+ self.verticalSplitter_6.handle(1).setEnabled(False)
+ self.gridLayout_9.addWidget(self.verticalSplitter_6, 0, 0, 1, 1)
+ self.tabWidgetSend.addTab(self.sendBroadcast, _fromUtf8(""))
+ self.verticalSplitter.addWidget(self.tabWidgetSend)
+ self.horizontalSplitter_5 = QtGui.QSplitter()
+ self.horizontalSplitter_5.setObjectName(_fromUtf8("horizontalSplitter_5"))
self.pushButtonTTL = QtGui.QPushButton(self.send)
- sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
- sizePolicy.setHorizontalStretch(0)
- sizePolicy.setVerticalStretch(0)
- sizePolicy.setHeightForWidth(self.pushButtonTTL.sizePolicy().hasHeightForWidth())
- self.pushButtonTTL.setSizePolicy(sizePolicy)
- self.pushButtonTTL.setMaximumSize(QtCore.QSize(32, 16777215))
+# sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
+# sizePolicy.setHorizontalStretch(0)
+# sizePolicy.setVerticalStretch(0)
+# sizePolicy.setHeightForWidth(self.pushButtonTTL.sizePolicy().hasHeightForWidth())
+# self.pushButtonTTL.setSizePolicy(sizePolicy)
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(0, 0, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
@@ -191,194 +302,252 @@ class Ui_MainWindow(object):
self.pushButtonTTL.setFont(font)
self.pushButtonTTL.setFlat(True)
self.pushButtonTTL.setObjectName(_fromUtf8("pushButtonTTL"))
- self.gridLayout_2.addWidget(self.pushButtonTTL, 7, 5, 1, 1)
- self.label_2 = QtGui.QLabel(self.send)
- self.label_2.setObjectName(_fromUtf8("label_2"))
- self.gridLayout_2.addWidget(self.label_2, 2, 0, 1, 1)
- self.lineEditTo = QtGui.QLineEdit(self.send)
- self.lineEditTo.setObjectName(_fromUtf8("lineEditTo"))
- self.gridLayout_2.addWidget(self.lineEditTo, 3, 1, 1, 1)
- self.textEditMessage = QtGui.QTextEdit(self.send)
- self.textEditMessage.setObjectName(_fromUtf8("textEditMessage"))
- self.gridLayout_2.addWidget(self.textEditMessage, 5, 1, 2, 8)
- self.pushButtonFetchNamecoinID = QtGui.QPushButton(self.send)
- font = QtGui.QFont()
- font.setPointSize(7)
- self.pushButtonFetchNamecoinID.setFont(font)
- self.pushButtonFetchNamecoinID.setObjectName(_fromUtf8("pushButtonFetchNamecoinID"))
- self.gridLayout_2.addWidget(self.pushButtonFetchNamecoinID, 3, 3, 1, 1)
- self.labelFrom = QtGui.QLabel(self.send)
- self.labelFrom.setText(_fromUtf8(""))
- self.labelFrom.setObjectName(_fromUtf8("labelFrom"))
- self.gridLayout_2.addWidget(self.labelFrom, 2, 2, 1, 7)
- self.lineEditSubject = QtGui.QLineEdit(self.send)
- self.lineEditSubject.setText(_fromUtf8(""))
- self.lineEditSubject.setObjectName(_fromUtf8("lineEditSubject"))
- self.gridLayout_2.addWidget(self.lineEditSubject, 4, 1, 1, 8)
- icon2 = QtGui.QIcon()
- icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/send.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
- self.tabWidget.addTab(self.send, icon2, _fromUtf8(""))
- self.sent = QtGui.QWidget()
- self.sent.setObjectName(_fromUtf8("sent"))
- self.verticalLayout = QtGui.QVBoxLayout(self.sent)
- self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
- self.horizontalLayout = QtGui.QHBoxLayout()
- self.horizontalLayout.setContentsMargins(-1, 0, -1, -1)
- self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
- self.sentSearchLineEdit = QtGui.QLineEdit(self.sent)
- self.sentSearchLineEdit.setObjectName(_fromUtf8("sentSearchLineEdit"))
- self.horizontalLayout.addWidget(self.sentSearchLineEdit)
- self.sentSearchOptionCB = QtGui.QComboBox(self.sent)
- self.sentSearchOptionCB.setObjectName(_fromUtf8("sentSearchOptionCB"))
- self.sentSearchOptionCB.addItem(_fromUtf8(""))
- self.sentSearchOptionCB.addItem(_fromUtf8(""))
- self.sentSearchOptionCB.addItem(_fromUtf8(""))
- self.sentSearchOptionCB.addItem(_fromUtf8(""))
- self.sentSearchOptionCB.addItem(_fromUtf8(""))
- self.horizontalLayout.addWidget(self.sentSearchOptionCB)
- self.verticalLayout.addLayout(self.horizontalLayout)
- self.splitter_2 = QtGui.QSplitter(self.sent)
- self.splitter_2.setOrientation(QtCore.Qt.Vertical)
- self.splitter_2.setObjectName(_fromUtf8("splitter_2"))
- self.tableWidgetSent = QtGui.QTableWidget(self.splitter_2)
- self.tableWidgetSent.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
- self.tableWidgetSent.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
- self.tableWidgetSent.setAlternatingRowColors(True)
- self.tableWidgetSent.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
- self.tableWidgetSent.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
- self.tableWidgetSent.setWordWrap(False)
- self.tableWidgetSent.setObjectName(_fromUtf8("tableWidgetSent"))
- self.tableWidgetSent.setColumnCount(4)
- self.tableWidgetSent.setRowCount(0)
- item = QtGui.QTableWidgetItem()
- self.tableWidgetSent.setHorizontalHeaderItem(0, item)
- item = QtGui.QTableWidgetItem()
- self.tableWidgetSent.setHorizontalHeaderItem(1, item)
- item = QtGui.QTableWidgetItem()
- self.tableWidgetSent.setHorizontalHeaderItem(2, item)
- item = QtGui.QTableWidgetItem()
- self.tableWidgetSent.setHorizontalHeaderItem(3, item)
- self.tableWidgetSent.horizontalHeader().setCascadingSectionResizes(True)
- self.tableWidgetSent.horizontalHeader().setDefaultSectionSize(130)
- self.tableWidgetSent.horizontalHeader().setHighlightSections(False)
- self.tableWidgetSent.horizontalHeader().setSortIndicatorShown(False)
- self.tableWidgetSent.horizontalHeader().setStretchLastSection(True)
- self.tableWidgetSent.verticalHeader().setVisible(False)
- self.tableWidgetSent.verticalHeader().setStretchLastSection(False)
- self.textEditSentMessage = QtGui.QTextEdit(self.splitter_2)
- self.textEditSentMessage.setReadOnly(True)
- self.textEditSentMessage.setObjectName(_fromUtf8("textEditSentMessage"))
- self.verticalLayout.addWidget(self.splitter_2)
- icon3 = QtGui.QIcon()
- icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/sent.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
- self.tabWidget.addTab(self.sent, icon3, _fromUtf8(""))
- self.youridentities = QtGui.QWidget()
- self.youridentities.setObjectName(_fromUtf8("youridentities"))
- self.gridLayout_3 = QtGui.QGridLayout(self.youridentities)
- self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3"))
- self.pushButtonNewAddress = QtGui.QPushButton(self.youridentities)
- self.pushButtonNewAddress.setObjectName(_fromUtf8("pushButtonNewAddress"))
- self.gridLayout_3.addWidget(self.pushButtonNewAddress, 0, 0, 1, 1)
- spacerItem1 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
- self.gridLayout_3.addItem(spacerItem1, 0, 1, 1, 1)
- self.tableWidgetYourIdentities = QtGui.QTableWidget(self.youridentities)
- self.tableWidgetYourIdentities.setFrameShadow(QtGui.QFrame.Sunken)
- self.tableWidgetYourIdentities.setLineWidth(1)
- self.tableWidgetYourIdentities.setAlternatingRowColors(True)
- self.tableWidgetYourIdentities.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
- self.tableWidgetYourIdentities.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
- self.tableWidgetYourIdentities.setObjectName(_fromUtf8("tableWidgetYourIdentities"))
- self.tableWidgetYourIdentities.setColumnCount(3)
- self.tableWidgetYourIdentities.setRowCount(0)
- item = QtGui.QTableWidgetItem()
- font = QtGui.QFont()
- font.setKerning(True)
- item.setFont(font)
- self.tableWidgetYourIdentities.setHorizontalHeaderItem(0, item)
- item = QtGui.QTableWidgetItem()
- self.tableWidgetYourIdentities.setHorizontalHeaderItem(1, item)
- item = QtGui.QTableWidgetItem()
- self.tableWidgetYourIdentities.setHorizontalHeaderItem(2, item)
- self.tableWidgetYourIdentities.horizontalHeader().setCascadingSectionResizes(True)
- self.tableWidgetYourIdentities.horizontalHeader().setDefaultSectionSize(346)
- self.tableWidgetYourIdentities.horizontalHeader().setMinimumSectionSize(52)
- self.tableWidgetYourIdentities.horizontalHeader().setSortIndicatorShown(True)
- self.tableWidgetYourIdentities.horizontalHeader().setStretchLastSection(True)
- self.tableWidgetYourIdentities.verticalHeader().setVisible(False)
- self.tableWidgetYourIdentities.verticalHeader().setDefaultSectionSize(26)
- self.tableWidgetYourIdentities.verticalHeader().setSortIndicatorShown(False)
- self.tableWidgetYourIdentities.verticalHeader().setStretchLastSection(False)
- self.gridLayout_3.addWidget(self.tableWidgetYourIdentities, 1, 0, 1, 2)
+ self.horizontalSplitter_5.addWidget(self.pushButtonTTL)
+ self.horizontalSliderTTL = QtGui.QSlider(self.send)
+ self.horizontalSliderTTL.setMinimumSize(QtCore.QSize(35, 0))
+ self.horizontalSliderTTL.setOrientation(QtCore.Qt.Horizontal)
+ self.horizontalSliderTTL.setInvertedAppearance(False)
+ self.horizontalSliderTTL.setInvertedControls(False)
+ self.horizontalSliderTTL.setObjectName(_fromUtf8("horizontalSliderTTL"))
+ self.horizontalSplitter_5.addWidget(self.horizontalSliderTTL)
+ self.labelHumanFriendlyTTLDescription = QtGui.QLabel(self.send)
+# sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
+# sizePolicy.setHorizontalStretch(0)
+# sizePolicy.setVerticalStretch(0)
+# sizePolicy.setHeightForWidth(self.labelHumanFriendlyTTLDescription.sizePolicy().hasHeightForWidth())
+# self.labelHumanFriendlyTTLDescription.setSizePolicy(sizePolicy)
+ self.labelHumanFriendlyTTLDescription.setMinimumSize(QtCore.QSize(45, 0))
+ self.labelHumanFriendlyTTLDescription.setObjectName(_fromUtf8("labelHumanFriendlyTTLDescription"))
+ self.horizontalSplitter_5.addWidget(self.labelHumanFriendlyTTLDescription)
+ self.pushButtonSend = QtGui.QPushButton(self.send)
+ self.pushButtonSend.setObjectName(_fromUtf8("pushButtonSend"))
+ self.horizontalSplitter_5.addWidget(self.pushButtonSend)
+ self.pushButtonTTL.setMaximumSize(QtCore.QSize(32, self.pushButtonSend.height()))
+ self.labelHumanFriendlyTTLDescription.setMaximumSize(QtCore.QSize(45, self.pushButtonSend.height()))
+ self.horizontalSliderTTL.setMaximumSize(QtCore.QSize(70, self.pushButtonSend.height()))
+ self.horizontalSplitter_5.resize(self.horizontalSplitter_5.width(), self.pushButtonSend.height())
+ self.horizontalSplitter_5.setStretchFactor(0, 0)
+ self.horizontalSplitter_5.setStretchFactor(1, 0)
+ self.horizontalSplitter_5.setStretchFactor(2, 0)
+ self.horizontalSplitter_5.setStretchFactor(3, 1)
+ self.horizontalSplitter_5.setCollapsible(0, False)
+ self.horizontalSplitter_5.setCollapsible(1, False)
+ self.horizontalSplitter_5.setCollapsible(2, False)
+ self.horizontalSplitter_5.setCollapsible(3, False)
+ self.horizontalSplitter_5.handle(1).setEnabled(False)
+ self.horizontalSplitter_5.handle(2).setEnabled(False)
+ self.horizontalSplitter_5.handle(3).setEnabled(False)
+ self.verticalSplitter.addWidget(self.horizontalSplitter_5)
+ self.verticalSplitter.setStretchFactor(0, 0)
+ self.verticalSplitter.setStretchFactor(1, 1)
+ self.verticalSplitter.setCollapsible(0, False)
+ self.verticalSplitter.setCollapsible(1, False)
+ self.verticalSplitter.handle(1).setEnabled(False)
+ self.horizontalSplitter.addWidget(self.verticalSplitter)
+ self.horizontalSplitter.setStretchFactor(0, 0)
+ self.horizontalSplitter.setStretchFactor(1, 1)
+ self.horizontalSplitter.setCollapsible(0, False)
+ self.horizontalSplitter.setCollapsible(1, False)
+ self.gridLayout_7.addWidget(self.horizontalSplitter, 0, 0, 1, 1)
icon4 = QtGui.QIcon()
- icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/identities.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
- self.tabWidget.addTab(self.youridentities, icon4, _fromUtf8(""))
+ icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/send.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.tabWidget.addTab(self.send, icon4, _fromUtf8(""))
self.subscriptions = QtGui.QWidget()
self.subscriptions.setObjectName(_fromUtf8("subscriptions"))
- self.gridLayout_4 = QtGui.QGridLayout(self.subscriptions)
- self.gridLayout_4.setObjectName(_fromUtf8("gridLayout_4"))
- self.label_5 = QtGui.QLabel(self.subscriptions)
- self.label_5.setWordWrap(True)
- self.label_5.setObjectName(_fromUtf8("label_5"))
- self.gridLayout_4.addWidget(self.label_5, 0, 0, 1, 2)
+ self.gridLayout_3 = QtGui.QGridLayout(self.subscriptions)
+ self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3"))
+ self.horizontalSplitter_4 = settingsmixin.SSplitter()
+ self.horizontalSplitter_4.setObjectName(_fromUtf8("horizontalSplitter_4"))
+ self.verticalSplitter_3 = settingsmixin.SSplitter()
+ self.verticalSplitter_3.setObjectName(_fromUtf8("verticalSplitter_3"))
+ self.verticalSplitter_3.setOrientation(QtCore.Qt.Vertical)
+ self.treeWidgetSubscriptions = settingsmixin.STreeWidget(self.subscriptions)
+ self.treeWidgetSubscriptions.setAlternatingRowColors(True)
+ self.treeWidgetSubscriptions.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
+ self.treeWidgetSubscriptions.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
+ self.treeWidgetSubscriptions.setObjectName(_fromUtf8("treeWidgetSubscriptions"))
+ self.treeWidgetSubscriptions.resize(200, self.treeWidgetSubscriptions.height())
+ icon5 = QtGui.QIcon()
+ icon5.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/subscriptions.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off)
+ self.treeWidgetSubscriptions.headerItem().setIcon(0, icon5)
+ self.verticalSplitter_3.addWidget(self.treeWidgetSubscriptions)
self.pushButtonAddSubscription = QtGui.QPushButton(self.subscriptions)
self.pushButtonAddSubscription.setObjectName(_fromUtf8("pushButtonAddSubscription"))
- self.gridLayout_4.addWidget(self.pushButtonAddSubscription, 1, 0, 1, 1)
- spacerItem2 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
- self.gridLayout_4.addItem(spacerItem2, 1, 1, 1, 1)
- self.tableWidgetSubscriptions = QtGui.QTableWidget(self.subscriptions)
- self.tableWidgetSubscriptions.setAlternatingRowColors(True)
- self.tableWidgetSubscriptions.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
- self.tableWidgetSubscriptions.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
- self.tableWidgetSubscriptions.setObjectName(_fromUtf8("tableWidgetSubscriptions"))
- self.tableWidgetSubscriptions.setColumnCount(2)
- self.tableWidgetSubscriptions.setRowCount(0)
+ self.pushButtonAddSubscription.resize(200, self.pushButtonAddSubscription.height())
+ self.verticalSplitter_3.addWidget(self.pushButtonAddSubscription)
+ self.verticalSplitter_3.setStretchFactor(0, 1)
+ self.verticalSplitter_3.setStretchFactor(1, 0)
+ self.verticalSplitter_3.setCollapsible(0, False)
+ self.verticalSplitter_3.setCollapsible(1, False)
+ self.verticalSplitter_3.handle(1).setEnabled(False)
+ self.horizontalSplitter_4.addWidget(self.verticalSplitter_3)
+ self.verticalSplitter_4 = settingsmixin.SSplitter()
+ self.verticalSplitter_4.setObjectName(_fromUtf8("verticalSplitter_4"))
+ self.verticalSplitter_4.setOrientation(QtCore.Qt.Vertical)
+ self.horizontalSplitter_2 = QtGui.QSplitter()
+ self.horizontalSplitter_2.setObjectName(_fromUtf8("horizontalSplitter_2"))
+ self.inboxSearchLineEditSubscriptions = QtGui.QLineEdit(self.subscriptions)
+ self.inboxSearchLineEditSubscriptions.setObjectName(_fromUtf8("inboxSearchLineEditSubscriptions"))
+ self.horizontalSplitter_2.addWidget(self.inboxSearchLineEditSubscriptions)
+ self.inboxSearchOptionSubscriptions = QtGui.QComboBox(self.subscriptions)
+ self.inboxSearchOptionSubscriptions.setObjectName(_fromUtf8("inboxSearchOptionSubscriptions"))
+ self.inboxSearchOptionSubscriptions.addItem(_fromUtf8(""))
+ self.inboxSearchOptionSubscriptions.addItem(_fromUtf8(""))
+ self.inboxSearchOptionSubscriptions.addItem(_fromUtf8(""))
+ self.inboxSearchOptionSubscriptions.addItem(_fromUtf8(""))
+ self.inboxSearchOptionSubscriptions.addItem(_fromUtf8(""))
+ self.inboxSearchOptionSubscriptions.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
+ self.horizontalSplitter_2.addWidget(self.inboxSearchOptionSubscriptions)
+ self.horizontalSplitter_2.handle(1).setEnabled(False)
+ self.horizontalSplitter_2.setStretchFactor(0, 1)
+ self.horizontalSplitter_2.setStretchFactor(1, 0)
+ self.verticalSplitter_4.addWidget(self.horizontalSplitter_2)
+ self.tableWidgetInboxSubscriptions = settingsmixin.STableWidget(self.subscriptions)
+ self.tableWidgetInboxSubscriptions.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
+ self.tableWidgetInboxSubscriptions.setAlternatingRowColors(True)
+ self.tableWidgetInboxSubscriptions.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
+ self.tableWidgetInboxSubscriptions.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
+ self.tableWidgetInboxSubscriptions.setWordWrap(False)
+ self.tableWidgetInboxSubscriptions.setObjectName(_fromUtf8("tableWidgetInboxSubscriptions"))
+ self.tableWidgetInboxSubscriptions.setColumnCount(4)
+ self.tableWidgetInboxSubscriptions.setRowCount(0)
item = QtGui.QTableWidgetItem()
- self.tableWidgetSubscriptions.setHorizontalHeaderItem(0, item)
+ self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(0, item)
item = QtGui.QTableWidgetItem()
- self.tableWidgetSubscriptions.setHorizontalHeaderItem(1, item)
- self.tableWidgetSubscriptions.horizontalHeader().setCascadingSectionResizes(True)
- self.tableWidgetSubscriptions.horizontalHeader().setDefaultSectionSize(400)
- self.tableWidgetSubscriptions.horizontalHeader().setHighlightSections(False)
- self.tableWidgetSubscriptions.horizontalHeader().setSortIndicatorShown(False)
- self.tableWidgetSubscriptions.horizontalHeader().setStretchLastSection(True)
- self.tableWidgetSubscriptions.verticalHeader().setVisible(False)
- self.gridLayout_4.addWidget(self.tableWidgetSubscriptions, 2, 0, 1, 2)
- icon5 = QtGui.QIcon()
- icon5.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/subscriptions.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
- self.tabWidget.addTab(self.subscriptions, icon5, _fromUtf8(""))
- self.addressbook = QtGui.QWidget()
- self.addressbook.setObjectName(_fromUtf8("addressbook"))
- self.gridLayout_5 = QtGui.QGridLayout(self.addressbook)
- self.gridLayout_5.setObjectName(_fromUtf8("gridLayout_5"))
- self.label_6 = QtGui.QLabel(self.addressbook)
- self.label_6.setWordWrap(True)
- self.label_6.setObjectName(_fromUtf8("label_6"))
- self.gridLayout_5.addWidget(self.label_6, 0, 0, 1, 2)
- self.pushButtonAddAddressBook = QtGui.QPushButton(self.addressbook)
- self.pushButtonAddAddressBook.setObjectName(_fromUtf8("pushButtonAddAddressBook"))
- self.gridLayout_5.addWidget(self.pushButtonAddAddressBook, 1, 0, 1, 1)
- spacerItem3 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
- self.gridLayout_5.addItem(spacerItem3, 1, 1, 1, 1)
- self.tableWidgetAddressBook = QtGui.QTableWidget(self.addressbook)
- self.tableWidgetAddressBook.setAlternatingRowColors(True)
- self.tableWidgetAddressBook.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
- self.tableWidgetAddressBook.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
- self.tableWidgetAddressBook.setObjectName(_fromUtf8("tableWidgetAddressBook"))
- self.tableWidgetAddressBook.setColumnCount(2)
- self.tableWidgetAddressBook.setRowCount(0)
+ self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(1, item)
item = QtGui.QTableWidgetItem()
- self.tableWidgetAddressBook.setHorizontalHeaderItem(0, item)
+ self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(2, item)
item = QtGui.QTableWidgetItem()
- self.tableWidgetAddressBook.setHorizontalHeaderItem(1, item)
- self.tableWidgetAddressBook.horizontalHeader().setCascadingSectionResizes(True)
- self.tableWidgetAddressBook.horizontalHeader().setDefaultSectionSize(400)
- self.tableWidgetAddressBook.horizontalHeader().setHighlightSections(False)
- self.tableWidgetAddressBook.horizontalHeader().setStretchLastSection(True)
- self.tableWidgetAddressBook.verticalHeader().setVisible(False)
- self.gridLayout_5.addWidget(self.tableWidgetAddressBook, 2, 0, 1, 2)
+ self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(3, item)
+ self.tableWidgetInboxSubscriptions.horizontalHeader().setCascadingSectionResizes(True)
+ self.tableWidgetInboxSubscriptions.horizontalHeader().setDefaultSectionSize(200)
+ self.tableWidgetInboxSubscriptions.horizontalHeader().setHighlightSections(False)
+ self.tableWidgetInboxSubscriptions.horizontalHeader().setMinimumSectionSize(27)
+ self.tableWidgetInboxSubscriptions.horizontalHeader().setSortIndicatorShown(False)
+ self.tableWidgetInboxSubscriptions.horizontalHeader().setStretchLastSection(True)
+ self.tableWidgetInboxSubscriptions.verticalHeader().setVisible(False)
+ self.tableWidgetInboxSubscriptions.verticalHeader().setDefaultSectionSize(26)
+ self.verticalSplitter_4.addWidget(self.tableWidgetInboxSubscriptions)
+ self.textEditInboxMessageSubscriptions = QtGui.QTextEdit(self.subscriptions)
+ self.textEditInboxMessageSubscriptions.setBaseSize(QtCore.QSize(0, 500))
+ self.textEditInboxMessageSubscriptions.setReadOnly(True)
+ self.textEditInboxMessageSubscriptions.setObjectName(_fromUtf8("textEditInboxMessageSubscriptions"))
+ self.verticalSplitter_4.addWidget(self.textEditInboxMessageSubscriptions)
+ self.verticalSplitter_4.setStretchFactor(0, 0)
+ self.verticalSplitter_4.setStretchFactor(1, 1)
+ self.verticalSplitter_4.setStretchFactor(2, 2)
+ self.verticalSplitter_4.setCollapsible(0, False)
+ self.verticalSplitter_4.setCollapsible(1, False)
+ self.verticalSplitter_4.setCollapsible(2, False)
+ self.verticalSplitter_4.handle(1).setEnabled(False)
+ self.horizontalSplitter_4.addWidget(self.verticalSplitter_4)
+ self.horizontalSplitter_4.setStretchFactor(0, 0)
+ self.horizontalSplitter_4.setStretchFactor(1, 1)
+ self.horizontalSplitter_4.setCollapsible(0, False)
+ self.horizontalSplitter_4.setCollapsible(1, False)
+ self.gridLayout_3.addWidget(self.horizontalSplitter_4, 0, 0, 1, 1)
icon6 = QtGui.QIcon()
- icon6.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/addressbook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
- self.tabWidget.addTab(self.addressbook, icon6, _fromUtf8(""))
+ icon6.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/subscriptions.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.tabWidget.addTab(self.subscriptions, icon6, _fromUtf8(""))
+ self.chans = QtGui.QWidget()
+ self.chans.setObjectName(_fromUtf8("chans"))
+ self.gridLayout_4 = QtGui.QGridLayout(self.chans)
+ self.gridLayout_4.setObjectName(_fromUtf8("gridLayout_4"))
+ self.horizontalSplitter_7 = settingsmixin.SSplitter()
+ self.horizontalSplitter_7.setObjectName(_fromUtf8("horizontalSplitter_7"))
+ self.verticalSplitter_17 = settingsmixin.SSplitter()
+ self.verticalSplitter_17.setObjectName(_fromUtf8("verticalSplitter_17"))
+ self.verticalSplitter_17.setOrientation(QtCore.Qt.Vertical)
+ self.treeWidgetChans = settingsmixin.STreeWidget(self.chans)
+ self.treeWidgetChans.setFrameShadow(QtGui.QFrame.Sunken)
+ self.treeWidgetChans.setLineWidth(1)
+ self.treeWidgetChans.setAlternatingRowColors(True)
+ self.treeWidgetChans.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
+ self.treeWidgetChans.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
+ self.treeWidgetChans.setObjectName(_fromUtf8("treeWidgetChans"))
+ self.treeWidgetChans.resize(200, self.treeWidgetChans.height())
+ icon7 = QtGui.QIcon()
+ icon7.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/can-icon-16px.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off)
+ self.treeWidgetChans.headerItem().setIcon(0, icon7)
+ self.verticalSplitter_17.addWidget(self.treeWidgetChans)
+ self.pushButtonAddChan = QtGui.QPushButton(self.chans)
+ self.pushButtonAddChan.setObjectName(_fromUtf8("pushButtonAddChan"))
+ self.pushButtonAddChan.resize(200, self.pushButtonAddChan.height())
+ self.verticalSplitter_17.addWidget(self.pushButtonAddChan)
+ self.verticalSplitter_17.setStretchFactor(0, 1)
+ self.verticalSplitter_17.setStretchFactor(1, 0)
+ self.verticalSplitter_17.setCollapsible(0, False)
+ self.verticalSplitter_17.setCollapsible(1, False)
+ self.verticalSplitter_17.handle(1).setEnabled(False)
+ self.horizontalSplitter_7.addWidget(self.verticalSplitter_17)
+ self.verticalSplitter_8 = settingsmixin.SSplitter()
+ self.verticalSplitter_8.setObjectName(_fromUtf8("verticalSplitter_8"))
+ self.verticalSplitter_8.setOrientation(QtCore.Qt.Vertical)
+ self.horizontalSplitter_6 = QtGui.QSplitter()
+ self.horizontalSplitter_6.setObjectName(_fromUtf8("horizontalSplitter_6"))
+ self.inboxSearchLineEditChans = QtGui.QLineEdit(self.chans)
+ self.inboxSearchLineEditChans.setObjectName(_fromUtf8("inboxSearchLineEditChans"))
+ self.horizontalSplitter_6.addWidget(self.inboxSearchLineEditChans)
+ self.inboxSearchOptionChans = QtGui.QComboBox(self.chans)
+ self.inboxSearchOptionChans.setObjectName(_fromUtf8("inboxSearchOptionChans"))
+ self.inboxSearchOptionChans.addItem(_fromUtf8(""))
+ self.inboxSearchOptionChans.addItem(_fromUtf8(""))
+ self.inboxSearchOptionChans.addItem(_fromUtf8(""))
+ self.inboxSearchOptionChans.addItem(_fromUtf8(""))
+ self.inboxSearchOptionChans.addItem(_fromUtf8(""))
+ self.inboxSearchOptionChans.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
+ self.horizontalSplitter_6.addWidget(self.inboxSearchOptionChans)
+ self.horizontalSplitter_6.handle(1).setEnabled(False)
+ self.horizontalSplitter_6.setStretchFactor(0, 1)
+ self.horizontalSplitter_6.setStretchFactor(1, 0)
+ self.verticalSplitter_8.addWidget(self.horizontalSplitter_6)
+ self.tableWidgetInboxChans = settingsmixin.STableWidget(self.chans)
+ self.tableWidgetInboxChans.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
+ self.tableWidgetInboxChans.setAlternatingRowColors(True)
+ self.tableWidgetInboxChans.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
+ self.tableWidgetInboxChans.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
+ self.tableWidgetInboxChans.setWordWrap(False)
+ self.tableWidgetInboxChans.setObjectName(_fromUtf8("tableWidgetInboxChans"))
+ self.tableWidgetInboxChans.setColumnCount(4)
+ self.tableWidgetInboxChans.setRowCount(0)
+ item = QtGui.QTableWidgetItem()
+ self.tableWidgetInboxChans.setHorizontalHeaderItem(0, item)
+ item = QtGui.QTableWidgetItem()
+ self.tableWidgetInboxChans.setHorizontalHeaderItem(1, item)
+ item = QtGui.QTableWidgetItem()
+ self.tableWidgetInboxChans.setHorizontalHeaderItem(2, item)
+ item = QtGui.QTableWidgetItem()
+ self.tableWidgetInboxChans.setHorizontalHeaderItem(3, item)
+ self.tableWidgetInboxChans.horizontalHeader().setCascadingSectionResizes(True)
+ self.tableWidgetInboxChans.horizontalHeader().setDefaultSectionSize(200)
+ self.tableWidgetInboxChans.horizontalHeader().setHighlightSections(False)
+ self.tableWidgetInboxChans.horizontalHeader().setMinimumSectionSize(27)
+ self.tableWidgetInboxChans.horizontalHeader().setSortIndicatorShown(False)
+ self.tableWidgetInboxChans.horizontalHeader().setStretchLastSection(True)
+ self.tableWidgetInboxChans.verticalHeader().setVisible(False)
+ self.tableWidgetInboxChans.verticalHeader().setDefaultSectionSize(26)
+ self.verticalSplitter_8.addWidget(self.tableWidgetInboxChans)
+ self.textEditInboxMessageChans = QtGui.QTextEdit(self.chans)
+ self.textEditInboxMessageChans.setBaseSize(QtCore.QSize(0, 500))
+ self.textEditInboxMessageChans.setReadOnly(True)
+ self.textEditInboxMessageChans.setObjectName(_fromUtf8("textEditInboxMessageChans"))
+ self.verticalSplitter_8.addWidget(self.textEditInboxMessageChans)
+ self.verticalSplitter_8.setStretchFactor(0, 0)
+ self.verticalSplitter_8.setStretchFactor(1, 1)
+ self.verticalSplitter_8.setStretchFactor(2, 2)
+ self.verticalSplitter_8.setCollapsible(0, False)
+ self.verticalSplitter_8.setCollapsible(1, False)
+ self.verticalSplitter_8.setCollapsible(2, False)
+ self.verticalSplitter_8.handle(1).setEnabled(False)
+ self.horizontalSplitter_7.addWidget(self.verticalSplitter_8)
+ self.horizontalSplitter_7.setStretchFactor(0, 0)
+ self.horizontalSplitter_7.setStretchFactor(1, 1)
+ self.horizontalSplitter_7.setCollapsible(0, False)
+ self.horizontalSplitter_7.setCollapsible(1, False)
+ self.gridLayout_4.addWidget(self.horizontalSplitter_7, 0, 0, 1, 1)
+ icon8 = QtGui.QIcon()
+ icon8.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/can-icon-16px.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.tabWidget.addTab(self.chans, icon8, _fromUtf8(""))
self.blackwhitelist = QtGui.QWidget()
self.blackwhitelist.setObjectName(_fromUtf8("blackwhitelist"))
self.gridLayout_6 = QtGui.QGridLayout(self.blackwhitelist)
@@ -393,9 +562,9 @@ class Ui_MainWindow(object):
self.pushButtonAddBlacklist = QtGui.QPushButton(self.blackwhitelist)
self.pushButtonAddBlacklist.setObjectName(_fromUtf8("pushButtonAddBlacklist"))
self.gridLayout_6.addWidget(self.pushButtonAddBlacklist, 2, 0, 1, 1)
- spacerItem4 = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
- self.gridLayout_6.addItem(spacerItem4, 2, 1, 1, 1)
- self.tableWidgetBlacklist = QtGui.QTableWidget(self.blackwhitelist)
+ spacerItem = QtGui.QSpacerItem(689, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
+ self.gridLayout_6.addItem(spacerItem, 2, 1, 1, 1)
+ self.tableWidgetBlacklist = settingsmixin.STableWidget(self.blackwhitelist)
self.tableWidgetBlacklist.setAlternatingRowColors(True)
self.tableWidgetBlacklist.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
self.tableWidgetBlacklist.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
@@ -413,20 +582,20 @@ class Ui_MainWindow(object):
self.tableWidgetBlacklist.horizontalHeader().setStretchLastSection(True)
self.tableWidgetBlacklist.verticalHeader().setVisible(False)
self.gridLayout_6.addWidget(self.tableWidgetBlacklist, 3, 0, 1, 2)
- icon7 = QtGui.QIcon()
- icon7.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/blacklist.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
- self.tabWidget.addTab(self.blackwhitelist, icon7, _fromUtf8(""))
+ icon9 = QtGui.QIcon()
+ icon9.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/blacklist.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.tabWidget.addTab(self.blackwhitelist, icon9, _fromUtf8(""))
self.networkstatus = QtGui.QWidget()
self.networkstatus.setObjectName(_fromUtf8("networkstatus"))
self.pushButtonStatusIcon = QtGui.QPushButton(self.networkstatus)
self.pushButtonStatusIcon.setGeometry(QtCore.QRect(680, 440, 21, 23))
self.pushButtonStatusIcon.setText(_fromUtf8(""))
- icon8 = QtGui.QIcon()
- icon8.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/redicon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
- self.pushButtonStatusIcon.setIcon(icon8)
+ icon10 = QtGui.QIcon()
+ icon10.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/redicon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.pushButtonStatusIcon.setIcon(icon10)
self.pushButtonStatusIcon.setFlat(True)
self.pushButtonStatusIcon.setObjectName(_fromUtf8("pushButtonStatusIcon"))
- self.tableWidgetConnectionCount = QtGui.QTableWidget(self.networkstatus)
+ self.tableWidgetConnectionCount = settingsmixin.STableWidget(self.networkstatus)
self.tableWidgetConnectionCount.setGeometry(QtCore.QRect(20, 70, 241, 241))
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(212, 208, 200))
@@ -470,22 +639,25 @@ class Ui_MainWindow(object):
self.labelBroadcastCount = QtGui.QLabel(self.networkstatus)
self.labelBroadcastCount.setGeometry(QtCore.QRect(350, 150, 351, 16))
self.labelBroadcastCount.setObjectName(_fromUtf8("labelBroadcastCount"))
+ self.labelSyncStatus = QtGui.QLabel(self.networkstatus)
+ self.labelSyncStatus.setGeometry(QtCore.QRect(350, 190, 331, 20))
+ self.labelSyncStatus.setObjectName(_fromUtf8("labelSyncStatus"))
self.labelLookupsPerSecond = QtGui.QLabel(self.networkstatus)
- self.labelLookupsPerSecond.setGeometry(QtCore.QRect(320, 250, 291, 16))
+ self.labelLookupsPerSecond.setGeometry(QtCore.QRect(320, 270, 291, 16))
self.labelLookupsPerSecond.setObjectName(_fromUtf8("labelLookupsPerSecond"))
self.labelBytesRecvCount = QtGui.QLabel(self.networkstatus)
- self.labelBytesRecvCount.setGeometry(QtCore.QRect(350, 210, 251, 16))
+ self.labelBytesRecvCount.setGeometry(QtCore.QRect(350, 230, 251, 16))
self.labelBytesRecvCount.setObjectName(_fromUtf8("labelBytesRecvCount"))
self.labelBytesSentCount = QtGui.QLabel(self.networkstatus)
- self.labelBytesSentCount.setGeometry(QtCore.QRect(350, 230, 251, 16))
+ self.labelBytesSentCount.setGeometry(QtCore.QRect(350, 250, 251, 16))
self.labelBytesSentCount.setObjectName(_fromUtf8("labelBytesSentCount"))
- icon9 = QtGui.QIcon()
- icon9.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/networkstatus.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
- self.tabWidget.addTab(self.networkstatus, icon9, _fromUtf8(""))
- self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1)
+ icon11 = QtGui.QIcon()
+ icon11.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/networkstatus.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.tabWidget.addTab(self.networkstatus, icon11, _fromUtf8(""))
+ self.gridLayout_10.addWidget(self.tabWidget, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
- self.menubar.setGeometry(QtCore.QRect(0, 0, 885, 21))
+ self.menubar.setGeometry(QtCore.QRect(0, 0, 885, 27))
self.menubar.setObjectName(_fromUtf8("menubar"))
self.menuFile = QtGui.QMenu(self.menubar)
self.menuFile.setObjectName(_fromUtf8("menuFile"))
@@ -537,7 +709,6 @@ class Ui_MainWindow(object):
self.menuFile.addAction(self.actionManageKeys)
self.menuFile.addAction(self.actionDeleteAllTrashedMessages)
self.menuFile.addAction(self.actionRegenerateDeterministicAddresses)
- self.menuFile.addAction(self.actionJoinChan)
self.menuFile.addAction(self.actionExit)
self.menuSettings.addAction(self.actionSettings)
self.menuHelp.addAction(self.actionHelp)
@@ -548,29 +719,15 @@ class Ui_MainWindow(object):
self.retranslateUi(MainWindow)
self.tabWidget.setCurrentIndex(0)
- QtCore.QObject.connect(self.radioButtonSpecific, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.lineEditTo.setEnabled)
- QtCore.QObject.connect(self.radioButtonSpecific, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.labelSendBroadcastWarning.hide)
- QtCore.QObject.connect(self.radioButtonBroadcast, QtCore.SIGNAL(_fromUtf8("clicked()")), self.labelSendBroadcastWarning.show)
+ self.tabWidgetSend.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
- MainWindow.setTabOrder(self.tabWidget, self.tableWidgetInbox)
MainWindow.setTabOrder(self.tableWidgetInbox, self.textEditInboxMessage)
- MainWindow.setTabOrder(self.textEditInboxMessage, self.radioButtonSpecific)
- MainWindow.setTabOrder(self.radioButtonSpecific, self.radioButtonBroadcast)
- MainWindow.setTabOrder(self.radioButtonBroadcast, self.comboBoxSendFrom)
+ MainWindow.setTabOrder(self.textEditInboxMessage, self.comboBoxSendFrom)
MainWindow.setTabOrder(self.comboBoxSendFrom, self.lineEditTo)
- MainWindow.setTabOrder(self.lineEditTo, self.pushButtonLoadFromAddressBook)
- MainWindow.setTabOrder(self.pushButtonLoadFromAddressBook, self.lineEditSubject)
+ MainWindow.setTabOrder(self.lineEditTo, self.lineEditSubject)
MainWindow.setTabOrder(self.lineEditSubject, self.textEditMessage)
- MainWindow.setTabOrder(self.textEditMessage, self.pushButtonSend)
- MainWindow.setTabOrder(self.pushButtonSend, self.tableWidgetSent)
- MainWindow.setTabOrder(self.tableWidgetSent, self.textEditSentMessage)
- MainWindow.setTabOrder(self.textEditSentMessage, self.pushButtonNewAddress)
- MainWindow.setTabOrder(self.pushButtonNewAddress, self.tableWidgetYourIdentities)
- MainWindow.setTabOrder(self.tableWidgetYourIdentities, self.pushButtonAddSubscription)
- MainWindow.setTabOrder(self.pushButtonAddSubscription, self.tableWidgetSubscriptions)
- MainWindow.setTabOrder(self.tableWidgetSubscriptions, self.pushButtonAddAddressBook)
- MainWindow.setTabOrder(self.pushButtonAddAddressBook, self.tableWidgetAddressBook)
- MainWindow.setTabOrder(self.tableWidgetAddressBook, self.radioButtonBlacklist)
+ MainWindow.setTabOrder(self.textEditMessage, self.pushButtonAddSubscription)
+ MainWindow.setTabOrder(self.pushButtonAddSubscription, self.radioButtonBlacklist)
MainWindow.setTabOrder(self.radioButtonBlacklist, self.radioButtonWhitelist)
MainWindow.setTabOrder(self.radioButtonWhitelist, self.pushButtonAddBlacklist)
MainWindow.setTabOrder(self.pushButtonAddBlacklist, self.tableWidgetBlacklist)
@@ -579,12 +736,14 @@ class Ui_MainWindow(object):
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "Bitmessage", None))
+ self.treeWidgetYourIdentities.headerItem().setText(0, _translate("MainWindow", "Identities", None))
+ self.pushButtonNewAddress.setText(_translate("MainWindow", "New Identity", None))
self.inboxSearchLineEdit.setPlaceholderText(_translate("MainWindow", "Search", None))
- self.inboxSearchOptionCB.setItemText(0, _translate("MainWindow", "All", None))
- self.inboxSearchOptionCB.setItemText(1, _translate("MainWindow", "To", None))
- self.inboxSearchOptionCB.setItemText(2, _translate("MainWindow", "From", None))
- self.inboxSearchOptionCB.setItemText(3, _translate("MainWindow", "Subject", None))
- self.inboxSearchOptionCB.setItemText(4, _translate("MainWindow", "Message", None))
+ self.inboxSearchOption.setItemText(0, _translate("MainWindow", "All", None))
+ self.inboxSearchOption.setItemText(1, _translate("MainWindow", "To", None))
+ self.inboxSearchOption.setItemText(2, _translate("MainWindow", "From", None))
+ self.inboxSearchOption.setItemText(3, _translate("MainWindow", "Subject", None))
+ self.inboxSearchOption.setItemText(4, _translate("MainWindow", "Message", None))
self.tableWidgetInbox.setSortingEnabled(True)
item = self.tableWidgetInbox.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "To", None))
@@ -594,66 +753,71 @@ class Ui_MainWindow(object):
item.setText(_translate("MainWindow", "Subject", None))
item = self.tableWidgetInbox.horizontalHeaderItem(3)
item.setText(_translate("MainWindow", "Received", None))
- self.tabWidget.setTabText(self.tabWidget.indexOf(self.inbox), _translate("MainWindow", "Inbox", None))
- self.pushButtonLoadFromAddressBook.setText(_translate("MainWindow", "Load from Address book", None))
+ self.tabWidget.setTabText(self.tabWidget.indexOf(self.inbox), _translate("MainWindow", "Messages", None))
+ self.tableWidgetAddressBook.setSortingEnabled(True)
+ item = self.tableWidgetAddressBook.horizontalHeaderItem(0)
+ item.setText(_translate("MainWindow", "Address book", None))
+ item = self.tableWidgetAddressBook.horizontalHeaderItem(1)
+ item.setText(_translate("MainWindow", "Address", None))
+ self.pushButtonAddAddressBook.setText(_translate("MainWindow", "Add Contact", None))
+ self.pushButtonFetchNamecoinID.setText(_translate("MainWindow", "Fetch Namecoin ID", None))
self.label_3.setText(_translate("MainWindow", "Subject:", None))
- self.pushButtonSend.setText(_translate("MainWindow", "Send", None))
- self.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "X days", None))
- self.label_4.setText(_translate("MainWindow", "Message:", None))
- self.label.setText(_translate("MainWindow", "To:", None))
- self.radioButtonSpecific.setText(_translate("MainWindow", "Send to one or more specific people", None))
- self.labelSendBroadcastWarning.setText(_translate("MainWindow", "Be aware that broadcasts are only encrypted with your address. Anyone who knows your address can read them.", None))
- self.radioButtonBroadcast.setText(_translate("MainWindow", "Broadcast to everyone who is subscribed to your address", None))
- self.pushButtonTTL.setText(_translate("MainWindow", "TTL:", None))
self.label_2.setText(_translate("MainWindow", "From:", None))
+ self.label.setText(_translate("MainWindow", "To:", None))
self.textEditMessage.setHtml(_translate("MainWindow", "\n"
"\n"
-"
", None))
- self.pushButtonFetchNamecoinID.setText(_translate("MainWindow", "Fetch Namecoin ID", None))
+"\n"
+"