Added pseudo-mailing-list feature; added Portable Mode feature #57

Merged
Atheros1 merged 9 commits from master into master 2013-02-27 18:27:29 +01:00
8 changed files with 688 additions and 106 deletions

View File

@ -275,6 +275,7 @@ if __name__ == "__main__":
print 'addressVersionNumber', addressVersionNumber print 'addressVersionNumber', addressVersionNumber
print 'streamNumber', streamNumber print 'streamNumber', streamNumber
print 'length of data(the ripe hash):', len(data) print 'length of data(the ripe hash):', len(data)
print 'ripe data:', data.encode('hex')
print '\n\nNow let us try making an address with given 2048-bit n and e values.' print '\n\nNow let us try making an address with given 2048-bit n and e values.'
testn = 16691381808213609635656612695328489234826227577985206736118595570304213887605602327717776979169783795560145663031146864154748634207927153095849203939039346778471192284119479329875655789428795925773927040539038073349089996911318012189546542694411685389074592231210678771416758973061752125295462189928432307067746658691146428088703129795340914596189054255127032271420140641112277113597275245807890920656563056790943850440012709593297328230145129809419550219898595770524436575484115680960823105256137731976622290028349172297572826751147335728017861413787053794003722218722212196385625462088929496952843002425059308041193 testn = 16691381808213609635656612695328489234826227577985206736118595570304213887605602327717776979169783795560145663031146864154748634207927153095849203939039346778471192284119479329875655789428795925773927040539038073349089996911318012189546542694411685389074592231210678771416758973061752125295462189928432307067746658691146428088703129795340914596189054255127032271420140641112277113597275245807890920656563056790943850440012709593297328230145129809419550219898595770524436575484115680960823105256137731976622290028349172297572826751147335728017861413787053794003722218722212196385625462088929496952843002425059308041193

View File

@ -6,14 +6,14 @@
#Right now, PyBitmessage only support connecting to stream 1. It doesn't yet contain logic to expand into further streams. #Right now, PyBitmessage only support connecting to stream 1. It doesn't yet contain logic to expand into further streams.
softwareVersion = '0.2.5' softwareVersion = '0.2.6'
verbose = 2 verbose = 2
maximumAgeOfAnObjectThatIAmWillingToAccept = 216000 #Equals two days and 12 hours. maximumAgeOfAnObjectThatIAmWillingToAccept = 216000 #Equals two days and 12 hours.
lengthOfTimeToLeaveObjectsInInventory = 237600 #Equals two days and 18 hours. This should be longer than maximumAgeOfAnObjectThatIAmWillingToAccept so that we don't process messages twice. lengthOfTimeToLeaveObjectsInInventory = 237600 #Equals two days and 18 hours. This should be longer than maximumAgeOfAnObjectThatIAmWillingToAccept so that we don't process messages twice.
lengthOfTimeToHoldOnToAllPubkeys = 2419200 #Equals 4 weeks. You could make this longer if you want but making it shorter would not be advisable because there is a very small possibility that it could keep you from obtaining a needed pubkey for a period of time. lengthOfTimeToHoldOnToAllPubkeys = 2419200 #Equals 4 weeks. You could make this longer if you want but making it shorter would not be advisable because there is a very small possibility that it could keep you from obtaining a needed pubkey for a period of time.
maximumAgeOfObjectsThatIAdvertiseToOthers = 216000 #Equals two days and 12 hours maximumAgeOfObjectsThatIAdvertiseToOthers = 216000 #Equals two days and 12 hours
maximumAgeOfNodesThatIAdvertiseToOthers = 10800 #Equals three hours maximumAgeOfNodesThatIAdvertiseToOthers = 10800 #Equals three hours
storeConfigFilesInSameDirectoryAsProgram = False storeConfigFilesInSameDirectoryAsProgramByDefault = False #The user may de-select Portable Mode in the settings if they want the config files to stay in the application data folder.
useVeryEasyProofOfWorkForTesting = False #If you set this to True while on the normal network, you won't be able to send or sometimes receive messages. useVeryEasyProofOfWorkForTesting = False #If you set this to True while on the normal network, you won't be able to send or sometimes receive messages.
import sys import sys
@ -29,6 +29,7 @@ from bitmessageui import *
from newaddressdialog import * from newaddressdialog import *
from newsubscriptiondialog import * from newsubscriptiondialog import *
from regenerateaddresses import * from regenerateaddresses import *
from specialaddressbehavior import *
from settings import * from settings import *
from about import * from about import *
from help import * from help import *
@ -50,6 +51,7 @@ import threading #used for the locks, not for the threads
import cStringIO import cStringIO
from time import strftime, localtime from time import strftime, localtime
import os import os
import shutil #used for moving the messages.dat file
import string import string
import socks import socks
#import pyelliptic #import pyelliptic
@ -73,7 +75,7 @@ class outgoingSynSender(QThread):
time.sleep(1) time.sleep(1)
resetTime = int(time.time()) #used below to clear out the alreadyAttemptedConnectionsList periodically so that we will retry connecting to hosts to which we have already tried to connect. resetTime = int(time.time()) #used below to clear out the alreadyAttemptedConnectionsList periodically so that we will retry connecting to hosts to which we have already tried to connect.
while True: while True:
#time.sleep(999999)#I'm using this to prevent connections for testing. #time.sleep(999999)#I sometimes use this to prevent connections for testing.
if len(self.selfInitiatedConnectionList) < 8: #maximum number of outgoing connections = 8 if len(self.selfInitiatedConnectionList) < 8: #maximum number of outgoing connections = 8
random.seed() random.seed()
HOST, = random.sample(knownNodes[self.streamNumber], 1) HOST, = random.sample(knownNodes[self.streamNumber], 1)
@ -479,7 +481,9 @@ class receiveDataThread(QThread):
headerData += 'inv\x00\x00\x00\x00\x00\x00\x00\x00\x00' headerData += 'inv\x00\x00\x00\x00\x00\x00\x00\x00\x00'
headerData += pack('>L',len(payload)) headerData += pack('>L',len(payload))
headerData += hashlib.sha512(payload).digest()[:4] headerData += hashlib.sha512(payload).digest()[:4]
printLock.acquire()
print 'Sending huge inv message with', numberOfObjects, 'objects to just this one peer' print 'Sending huge inv message with', numberOfObjects, 'objects to just this one peer'
printLock.release()
self.sock.send(headerData + payload) self.sock.send(headerData + payload)
#We have received a broadcast message #We have received a broadcast message
@ -627,7 +631,7 @@ class receiveDataThread(QThread):
sqlSubmitQueue.put(t) sqlSubmitQueue.put(t)
sqlReturnQueue.get() sqlReturnQueue.get()
sqlLock.release() sqlLock.release()
self.emit(SIGNAL("displayNewMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body) self.emit(SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body)
#Display timing data #Display timing data
printLock.acquire() printLock.acquire()
@ -712,7 +716,7 @@ class receiveDataThread(QThread):
sqlSubmitQueue.put(t) sqlSubmitQueue.put(t)
sqlReturnQueue.get() sqlReturnQueue.get()
sqlLock.release() sqlLock.release()
self.emit(SIGNAL("displayNewMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body) self.emit(SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body)
#We have received a msg message. #We have received a msg message.
@ -943,7 +947,7 @@ class receiveDataThread(QThread):
sqlSubmitQueue.put(t) sqlSubmitQueue.put(t)
sqlReturnQueue.get() sqlReturnQueue.get()
sqlLock.release() sqlLock.release()
self.emit(SIGNAL("displayNewMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body) self.emit(SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body)
#Now let us worry about the acknowledgement data #Now let us worry about the acknowledgement data
#We'll need to make sure that our client will properly process the ackData; if the packet is malformed, it might cause us to clear out self.data and an attacker could use that behavior to determine that we decoded this message. #We'll need to make sure that our client will properly process the ackData; if the packet is malformed, it might cause us to clear out self.data and an attacker could use that behavior to determine that we decoded this message.
ackDataValidThusFar = True ackDataValidThusFar = True
@ -1103,7 +1107,9 @@ class receiveDataThread(QThread):
for row in queryreturn: for row in queryreturn:
label, enabled = row label, enabled = row
if enabled: if enabled:
printLock.acquire()
print 'Message ignored because address is in blacklist.' print 'Message ignored because address is in blacklist.'
printLock.release()
blockMessage = True blockMessage = True
else: #We're using a whitelist else: #We're using a whitelist
t = (fromAddress,) t = (fromAddress,)
@ -1154,7 +1160,6 @@ class receiveDataThread(QThread):
else: else:
body = 'Unknown encoding type.\n\n' + repr(message) body = 'Unknown encoding type.\n\n' + repr(message)
subject = '' subject = ''
print 'within processmsg, self.inventoryHash is', self.inventoryHash.encode('hex')
if messageEncodingType <> 0: if messageEncodingType <> 0:
sqlLock.acquire() sqlLock.acquire()
t = (self.inventoryHash,toAddress,fromAddress,subject,int(time.time()),body,'inbox') t = (self.inventoryHash,toAddress,fromAddress,subject,int(time.time()),body,'inbox')
@ -1162,7 +1167,36 @@ class receiveDataThread(QThread):
sqlSubmitQueue.put(t) sqlSubmitQueue.put(t)
sqlReturnQueue.get() sqlReturnQueue.get()
sqlLock.release() sqlLock.release()
self.emit(SIGNAL("displayNewMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body) self.emit(SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.inventoryHash,toAddress,fromAddress,subject,body)
#Let us now check and see whether our receiving address is behaving as a mailing list
try:
isMailingList = config.getboolean(toAddress, 'mailinglist')
except:
isMailingList = False
if isMailingList:
try:
mailingListName = config.get(toAddress, 'mailinglistname')
except:
mailingListName = ''
#Let us send out this message as a broadcast
subject = self.addMailingListNameToSubject(subject,mailingListName)
#Let us now send this message out as a broadcast
message = 'Message ostensibly from ' + fromAddress + ':\n\n' + body
fromAddress = toAddress #The fromAddress for the broadcast is the toAddress (my address) for the msg message we are currently processing.
ackdata = OpenSSL.rand(32) #We don't actually need the ackdata for acknowledgement since this is a broadcast message but we can use it to update the user interface when the POW is done generating.
toAddress = '[Broadcast subscribers]'
ripe = ''
sqlLock.acquire()
t = ('',toAddress,ripe,fromAddress,subject,message,ackdata,int(time.time()),'broadcastpending',1,1,'sent')
sqlSubmitQueue.put('''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?)''')
sqlSubmitQueue.put(t)
sqlReturnQueue.get()
sqlLock.release()
workerQueue.put(('sendbroadcast',(fromAddress,subject,message)))
self.emit(SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),toAddress,'[Broadcast subscribers]',fromAddress,subject,message,ackdata)
#Now let's consider sending the acknowledgement. We'll need to make sure that our client will properly process the ackData; if the packet is malformed, we could clear out self.data and an attacker could use that behavior to determine that we were capable of decoding this message. #Now let's consider sending the acknowledgement. We'll need to make sure that our client will properly process the ackData; if the packet is malformed, we could clear out self.data and an attacker could use that behavior to determine that we were capable of decoding this message.
ackDataValidThusFar = True ackDataValidThusFar = True
if len(ackData) < 24: if len(ackData) < 24:
@ -1190,6 +1224,15 @@ class receiveDataThread(QThread):
print 'Average time for all message decryption successes since startup:', sum / len(successfullyDecryptMessageTimings) print 'Average time for all message decryption successes since startup:', sum / len(successfullyDecryptMessageTimings)
printLock.release() printLock.release()
def addMailingListNameToSubject(self,subject,mailingListName):
subject = subject.strip()
if subject[:3] == 'Re:' or subject[:3] == 'RE:':
subject = subject[3:].strip()
if '['+mailingListName+']' in subject:
return subject
else:
return '['+mailingListName+'] ' + subject
#We have received a pubkey #We have received a pubkey
def recpubkey(self): def recpubkey(self):
self.pubkeyProcessingStartTime = time.time() self.pubkeyProcessingStartTime = time.time()
@ -1205,7 +1248,7 @@ class receiveDataThread(QThread):
embeddedTime, = unpack('>I',self.data[readPosition:readPosition+4]) embeddedTime, = unpack('>I',self.data[readPosition:readPosition+4])
if embeddedTime < int(time.time())-lengthOfTimeToHoldOnToAllPubkeys-86400: #If the pubkey is more than a month old then reject it. (the 86400 is included to give an extra day of wiggle-room. If the wiggle-room is actually of any use, everyone on the network will delete this pubkey from their database the next time the cleanerThread cleans anyway- except for the node that actually wants the pubkey.) if embeddedTime < int(time.time())-lengthOfTimeToHoldOnToAllPubkeys-86400: #If the pubkey is more than a month old then reject it. (the 86400 is included to give an extra day of wiggle-room. If the wiggle-room is actually of any use, everyone on the network will delete this pubkey from their database the next time the cleanerThread cleans anyway- except for the node that actually wants the pubkey.)
printLock.acquire() printLock.acquire()
print 'The embedded time in this pubkey message is too old. Ignoring.' print 'The embedded time in this pubkey message is too old. Ignoring. Embedded time is:', embeddedTime
printLock.release() printLock.release()
return return
if embeddedTime > int(time.time()) + 10800: if embeddedTime > int(time.time()) + 10800:
@ -1519,7 +1562,13 @@ class receiveDataThread(QThread):
headerData += 'getdata\x00\x00\x00\x00\x00' headerData += 'getdata\x00\x00\x00\x00\x00'
headerData += pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce. headerData += pack('>L',len(payload)) #payload length. Note that we add an extra 8 for the nonce.
headerData += hashlib.sha512(payload).digest()[:4] headerData += hashlib.sha512(payload).digest()[:4]
try:
self.sock.send(headerData + payload) self.sock.send(headerData + payload)
except Exception, err:
if not 'Bad file descriptor' in err:
printLock.acquire()
sys.stderr.write('sock.send error: %s\n' % err)
printLock.release()
#We have received a getdata request from our peer #We have received a getdata request from our peer
def recgetdata(self): def recgetdata(self):
@ -1607,7 +1656,9 @@ class receiveDataThread(QThread):
numberOfAddressesIncluded, lengthOfNumberOfAddresses = decodeVarint(self.data[24:29]) numberOfAddressesIncluded, lengthOfNumberOfAddresses = decodeVarint(self.data[24:29])
if verbose >= 1: if verbose >= 1:
printLock.acquire()
print 'addr message contains', numberOfAddressesIncluded, 'IP addresses.' print 'addr message contains', numberOfAddressesIncluded, 'IP addresses.'
printLock.release()
#print 'lengthOfNumberOfAddresses', lengthOfNumberOfAddresses #print 'lengthOfNumberOfAddresses', lengthOfNumberOfAddresses
if numberOfAddressesIncluded > 1000: if numberOfAddressesIncluded > 1000:
@ -1678,7 +1729,9 @@ class receiveDataThread(QThread):
pickle.dump(knownNodes, output) pickle.dump(knownNodes, output)
output.close() output.close()
self.broadcastaddr(listOfAddressDetailsToBroadcastToPeers) self.broadcastaddr(listOfAddressDetailsToBroadcastToPeers)
printLock.acquire()
print 'knownNodes currently has', len(knownNodes[recaddrStream]), 'nodes for this stream.' print 'knownNodes currently has', len(knownNodes[recaddrStream]), 'nodes for this stream.'
printLock.release()
#Function runs when we want to broadcast an addr message to all of our peers. Runs when we learn of nodes that we didn't previously know about and want to share them with our peers. #Function runs when we want to broadcast an addr message to all of our peers. Runs when we learn of nodes that we didn't previously know about and want to share them with our peers.
def broadcastaddr(self,listOfAddressDetailsToBroadcastToPeers): def broadcastaddr(self,listOfAddressDetailsToBroadcastToPeers):
@ -2131,6 +2184,21 @@ def calculateTestnetAddressFromPubkey(pubkey):
base58encoded = arithmetic.changebase(binaryBitcoinAddress,256,58) base58encoded = arithmetic.changebase(binaryBitcoinAddress,256,58)
return "1"*numberOfZeroBytesOnBinaryBitcoinAddress + base58encoded return "1"*numberOfZeroBytesOnBinaryBitcoinAddress + base58encoded
def lookupAppdataFolder():
APPNAME = "PyBitmessage"
from os import path, environ
if sys.platform == 'darwin':
if "HOME" in environ:
appdata = 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 BitMessage Github.'
sys.exit()
elif 'win32' in sys.platform or 'win64' in sys.platform:
appdata = path.join(environ['APPDATA'], APPNAME) + '\\'
else:
appdata = path.expanduser(path.join("~", "." + APPNAME + "/"))
return appdata
#This thread exists because SQLITE3 is so un-threadsafe that we must submit queries to it and it puts results back in a different queue. They won't let us just use locks. #This thread exists because SQLITE3 is so un-threadsafe that we must submit queries to it and it puts results back in a different queue. They won't let us just use locks.
class sqlThread(QThread): class sqlThread(QThread):
@ -2229,6 +2297,8 @@ class singleCleaner(QThread):
while True: while True:
time.sleep(300) time.sleep(300)
#Clear the status bar in case a message has been sitting there for a while.
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"")
sqlLock.acquire() sqlLock.acquire()
for hash, storedValue in inventory.items(): for hash, storedValue in inventory.items():
objectType, streamNumber, payload, receivedTime = storedValue objectType, streamNumber, payload, receivedTime = storedValue
@ -2270,6 +2340,7 @@ class singleCleaner(QThread):
except: except:
pass pass
workerQueue.put(('sendmessage',toaddress)) workerQueue.put(('sendmessage',toaddress))
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"Doing work necessary to again attempt to request a public key...")
t = (int(time.time()),pubkeyretrynumber+1,toripe) t = (int(time.time()),pubkeyretrynumber+1,toripe)
sqlSubmitQueue.put('''UPDATE sent SET lastactiontime=?, pubkeyretrynumber=? WHERE toripe=?''') sqlSubmitQueue.put('''UPDATE sent SET lastactiontime=?, pubkeyretrynumber=? WHERE toripe=?''')
sqlSubmitQueue.put(t) sqlSubmitQueue.put(t)
@ -2284,9 +2355,9 @@ class singleCleaner(QThread):
sqlReturnQueue.get() sqlReturnQueue.get()
#self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Message sent again because the acknowledgement was never received. ' + strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time())))) #self.emit(SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"),ackdata,'Message sent again because the acknowledgement was never received. ' + strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))
workerQueue.put(('sendmessage',toaddress)) workerQueue.put(('sendmessage',toaddress))
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"Doing work necessary to again attempt to deliver a message...")
sqlLock.release() sqlLock.release()
#Clear the status bar in case a message has been sitting there for a while.
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),"")
#This thread, of which there is only one, does the heavy lifting: calculating POWs. #This thread, of which there is only one, does the heavy lifting: calculating POWs.
class singleWorker(QThread): class singleWorker(QThread):
@ -3044,6 +3115,8 @@ class settingsDialog(QtGui.QDialog):
self.ui.checkBoxMinimizeToTray.setChecked(config.getboolean('bitmessagesettings', 'minimizetotray')) self.ui.checkBoxMinimizeToTray.setChecked(config.getboolean('bitmessagesettings', 'minimizetotray'))
self.ui.checkBoxShowTrayNotifications.setChecked(config.getboolean('bitmessagesettings', 'showtraynotifications')) self.ui.checkBoxShowTrayNotifications.setChecked(config.getboolean('bitmessagesettings', 'showtraynotifications'))
self.ui.checkBoxStartInTray.setChecked(config.getboolean('bitmessagesettings', 'startintray')) self.ui.checkBoxStartInTray.setChecked(config.getboolean('bitmessagesettings', 'startintray'))
if appdata == '':
self.ui.checkBoxPortableMode.setChecked(True)
if 'darwin' in sys.platform: if 'darwin' in sys.platform:
self.ui.checkBoxStartOnLogon.setDisabled(True) self.ui.checkBoxStartOnLogon.setDisabled(True)
self.ui.checkBoxMinimizeToTray.setDisabled(True) self.ui.checkBoxMinimizeToTray.setDisabled(True)
@ -3077,6 +3150,7 @@ class settingsDialog(QtGui.QDialog):
self.ui.lineEditSocksUsername.setText(str(config.get('bitmessagesettings', 'socksusername'))) self.ui.lineEditSocksUsername.setText(str(config.get('bitmessagesettings', 'socksusername')))
self.ui.lineEditSocksPassword.setText(str(config.get('bitmessagesettings', 'sockspassword'))) self.ui.lineEditSocksPassword.setText(str(config.get('bitmessagesettings', 'sockspassword')))
QtCore.QObject.connect(self.ui.comboBoxProxyType, QtCore.SIGNAL("currentIndexChanged(int)"), self.comboBoxProxyTypeChanged) QtCore.QObject.connect(self.ui.comboBoxProxyType, QtCore.SIGNAL("currentIndexChanged(int)"), self.comboBoxProxyTypeChanged)
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
def comboBoxProxyTypeChanged(self,comboBoxIndex): def comboBoxProxyTypeChanged(self,comboBoxIndex):
if comboBoxIndex == 0: if comboBoxIndex == 0:
@ -3095,11 +3169,34 @@ class settingsDialog(QtGui.QDialog):
self.ui.lineEditSocksPassword.setEnabled(True) self.ui.lineEditSocksPassword.setEnabled(True)
self.ui.lineEditTCPPort.setEnabled(False) self.ui.lineEditTCPPort.setEnabled(False)
class SpecialAddressBehaviorDialog(QtGui.QDialog):
def __init__(self,parent):
QtGui.QWidget.__init__(self, parent)
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())
try:
isMailingList = config.getboolean(addressAtCurrentRow, 'mailinglist')
except:
isMailingList = False
if isMailingList:
self.ui.radioButtonBehaviorMailingList.click()
else:
self.ui.radioButtonBehaveNormalAddress.click()
try:
mailingListName = config.get(addressAtCurrentRow, 'mailinglistname')
except:
mailingListName = ''
self.ui.lineEditMailingListName.setText(unicode(mailingListName,'utf-8'))
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
class NewSubscriptionDialog(QtGui.QDialog): class NewSubscriptionDialog(QtGui.QDialog):
def __init__(self,parent): def __init__(self,parent):
QtGui.QWidget.__init__(self, parent) QtGui.QWidget.__init__(self, parent)
self.ui = Ui_NewSubscriptionDialog() #Jonathan changed this line self.ui = Ui_NewSubscriptionDialog()
self.ui.setupUi(self) #Jonathan left this line alone self.ui.setupUi(self)
self.parent = parent self.parent = parent
QtCore.QObject.connect(self.ui.lineEditSubscriptionAddress, QtCore.SIGNAL("textChanged(QString)"), self.subscriptionAddressChanged) QtCore.QObject.connect(self.ui.lineEditSubscriptionAddress, QtCore.SIGNAL("textChanged(QString)"), self.subscriptionAddressChanged)
@ -3219,6 +3316,7 @@ class MyForm(QtGui.QMainWindow):
self.actionEnable = self.ui.addressContextMenuToolbar.addAction("Enable", self.on_action_YourIdentitiesEnable) self.actionEnable = self.ui.addressContextMenuToolbar.addAction("Enable", self.on_action_YourIdentitiesEnable)
self.actionDisable = self.ui.addressContextMenuToolbar.addAction("Disable", self.on_action_YourIdentitiesDisable) self.actionDisable = self.ui.addressContextMenuToolbar.addAction("Disable", self.on_action_YourIdentitiesDisable)
self.actionClipboard = self.ui.addressContextMenuToolbar.addAction("Copy address to clipboard", self.on_action_YourIdentitiesClipboard) self.actionClipboard = self.ui.addressContextMenuToolbar.addAction("Copy address to clipboard", self.on_action_YourIdentitiesClipboard)
self.actionSpecialAddressBehavior = self.ui.addressContextMenuToolbar.addAction("Special address behavior...", self.on_action_SpecialAddressBehaviorDialog)
self.ui.tableWidgetYourIdentities.setContextMenuPolicy( QtCore.Qt.CustomContextMenu ) self.ui.tableWidgetYourIdentities.setContextMenuPolicy( QtCore.Qt.CustomContextMenu )
self.connect(self.ui.tableWidgetYourIdentities, QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'), self.on_context_menuYourIdentities) self.connect(self.ui.tableWidgetYourIdentities, QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'), self.on_context_menuYourIdentities)
self.popMenu = QtGui.QMenu( self ) self.popMenu = QtGui.QMenu( self )
@ -3228,6 +3326,7 @@ class MyForm(QtGui.QMainWindow):
self.popMenu.addSeparator() self.popMenu.addSeparator()
self.popMenu.addAction( self.actionEnable ) self.popMenu.addAction( self.actionEnable )
self.popMenu.addAction( self.actionDisable ) self.popMenu.addAction( self.actionDisable )
self.popMenu.addAction( self.actionSpecialAddressBehavior )
#Popup menu for the Address Book page #Popup menu for the Address Book page
self.ui.addressBookContextMenuToolbar = QtGui.QToolBar() self.ui.addressBookContextMenuToolbar = QtGui.QToolBar()
@ -3263,11 +3362,33 @@ class MyForm(QtGui.QMainWindow):
self.ui.sentContextMenuToolbar = QtGui.QToolBar() self.ui.sentContextMenuToolbar = QtGui.QToolBar()
# Actions # Actions
self.actionTrashSentMessage = self.ui.sentContextMenuToolbar.addAction("Move to Trash", self.on_action_SentTrash) self.actionTrashSentMessage = self.ui.sentContextMenuToolbar.addAction("Move to Trash", self.on_action_SentTrash)
self.actionSentClipboard = self.ui.sentContextMenuToolbar.addAction("Copy destination address to clipboard", self.on_action_SentClipboard)
self.ui.tableWidgetSent.setContextMenuPolicy( QtCore.Qt.CustomContextMenu ) self.ui.tableWidgetSent.setContextMenuPolicy( QtCore.Qt.CustomContextMenu )
self.connect(self.ui.tableWidgetSent, QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'), self.on_context_menuSent) self.connect(self.ui.tableWidgetSent, QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'), self.on_context_menuSent)
self.popMenuSent = QtGui.QMenu( self ) self.popMenuSent = QtGui.QMenu( self )
self.popMenuSent.addAction( self.actionSentClipboard )
self.popMenuSent.addAction( self.actionTrashSentMessage ) self.popMenuSent.addAction( self.actionTrashSentMessage )
#Popup menu for the Blacklist page
self.ui.blacklistContextMenuToolbar = QtGui.QToolBar()
# Actions
self.actionBlacklistNew = self.ui.blacklistContextMenuToolbar.addAction("Add new entry", self.on_action_BlacklistNew)
self.actionBlacklistDelete = self.ui.blacklistContextMenuToolbar.addAction("Delete", self.on_action_BlacklistDelete)
self.actionBlacklistClipboard = self.ui.blacklistContextMenuToolbar.addAction("Copy address to clipboard", self.on_action_BlacklistClipboard)
self.actionBlacklistEnable = self.ui.blacklistContextMenuToolbar.addAction("Enable", self.on_action_BlacklistEnable)
self.actionBlacklistDisable = self.ui.blacklistContextMenuToolbar.addAction("Disable", self.on_action_BlacklistDisable)
self.ui.tableWidgetBlacklist.setContextMenuPolicy( QtCore.Qt.CustomContextMenu )
self.connect(self.ui.tableWidgetBlacklist, QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'), self.on_context_menuBlacklist)
self.popMenuBlacklist = QtGui.QMenu( self )
#self.popMenuBlacklist.addAction( self.actionBlacklistNew )
self.popMenuBlacklist.addAction( self.actionBlacklistDelete )
self.popMenuBlacklist.addSeparator()
self.popMenuBlacklist.addAction( self.actionBlacklistClipboard )
self.popMenuBlacklist.addSeparator()
self.popMenuBlacklist.addAction( self.actionBlacklistEnable )
self.popMenuBlacklist.addAction( self.actionBlacklistDisable )
#Initialize the user's list of addresses on the 'Your Identities' tab. #Initialize the user's list of addresses on the 'Your Identities' tab.
configSections = config.sections() configSections = config.sections()
for addressInKeysFile in configSections: for addressInKeysFile in configSections:
@ -3282,6 +3403,11 @@ class MyForm(QtGui.QMainWindow):
newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
if not isEnabled: if not isEnabled:
newItem.setTextColor(QtGui.QColor(128,128,128)) newItem.setTextColor(QtGui.QColor(128,128,128))
try:
if config.getboolean(addressInKeysFile,'mailinglist'):
newItem.setTextColor(QtGui.QColor(137,04,177))#magenta
except:
pass #The 'mailinglist'
self.ui.tableWidgetYourIdentities.setItem(0, 1, newItem) self.ui.tableWidgetYourIdentities.setItem(0, 1, newItem)
newItem = QtGui.QTableWidgetItem(str(addressStream(addressInKeysFile))) newItem = QtGui.QTableWidgetItem(str(addressStream(addressInKeysFile)))
newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
@ -3330,6 +3456,11 @@ class MyForm(QtGui.QMainWindow):
newItem = QtGui.QTableWidgetItem(unicode(toLabel,'utf-8')) newItem = QtGui.QTableWidgetItem(unicode(toLabel,'utf-8'))
newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
newItem.setData(Qt.UserRole,str(toAddress)) newItem.setData(Qt.UserRole,str(toAddress))
try:
if config.getboolean(toAddress,'mailinglist'):
newItem.setTextColor(QtGui.QColor(137,04,177))
except:
pass #the 'mailinglist' setting was not found for this address.
self.ui.tableWidgetInbox.setItem(0,0,newItem) self.ui.tableWidgetInbox.setItem(0,0,newItem)
if fromLabel == '': if fromLabel == '':
newItem = QtGui.QTableWidgetItem(unicode(fromAddress,'utf-8')) newItem = QtGui.QTableWidgetItem(unicode(fromAddress,'utf-8'))
@ -3337,6 +3468,7 @@ class MyForm(QtGui.QMainWindow):
newItem = QtGui.QTableWidgetItem(unicode(fromLabel,'utf-8')) newItem = QtGui.QTableWidgetItem(unicode(fromLabel,'utf-8'))
newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
newItem.setData(Qt.UserRole,str(fromAddress)) newItem.setData(Qt.UserRole,str(fromAddress))
self.ui.tableWidgetInbox.setItem(0,1,newItem) self.ui.tableWidgetInbox.setItem(0,1,newItem)
newItem = QtGui.QTableWidgetItem(unicode(subject,'utf-8')) newItem = QtGui.QTableWidgetItem(unicode(subject,'utf-8'))
newItem.setData(Qt.UserRole,unicode(message,'utf-8)')) newItem.setData(Qt.UserRole,unicode(message,'utf-8)'))
@ -3495,13 +3627,17 @@ class MyForm(QtGui.QMainWindow):
def click_actionManageKeys(self): def click_actionManageKeys(self):
if 'darwin' in sys.platform or 'linux' in sys.platform: if 'darwin' in sys.platform or 'linux' in sys.platform:
reply = QtGui.QMessageBox.information(self, 'keys.dat?','You may manage your keys by editing the keys.dat file stored in\n' + appdata + '\nIt is important that you back up this file.', QMessageBox.Ok) if appdata == '':
reply = QtGui.QMessageBox.information(self, 'keys.dat?','You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file.', QMessageBox.Ok)
else:
QtGui.QMessageBox.information(self, 'keys.dat?','You may manage your keys by editing the keys.dat file stored in\n' + appdata + '\nIt is important that you back up this file.', QMessageBox.Ok)
elif sys.platform == 'win32' or sys.platform == 'win64': elif sys.platform == 'win32' or sys.platform == 'win64':
if appdata == '':
reply = QtGui.QMessageBox.question(self, 'Open keys.dat?','You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.)', QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
else:
reply = QtGui.QMessageBox.question(self, 'Open keys.dat?','You may manage your keys by editing the keys.dat file stored in\n' + appdata + '\nIt is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.)', QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) reply = QtGui.QMessageBox.question(self, 'Open keys.dat?','You may manage your keys by editing the keys.dat file stored in\n' + appdata + '\nIt is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.)', QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes: if reply == QtGui.QMessageBox.Yes:
self.openKeysFile() self.openKeysFile()
else:
pass
def click_actionRegenerateDeterministicAddresses(self): def click_actionRegenerateDeterministicAddresses(self):
self.regenerateAddressesDialogInstance = regenerateAddressesDialog(self) self.regenerateAddressesDialogInstance = regenerateAddressesDialog(self)
@ -3520,9 +3656,9 @@ class MyForm(QtGui.QMainWindow):
def openKeysFile(self): def openKeysFile(self):
if 'linux' in sys.platform: if 'linux' in sys.platform:
subprocess.call(["xdg-open", file]) subprocess.call(["xdg-open", appdata + 'keys.dat'])
else: else:
os.startfile(appdata + '\\keys.dat') os.startfile(appdata + 'keys.dat')
def changeEvent(self, event): def changeEvent(self, event):
if config.getboolean('bitmessagesettings', 'minimizetotray') and not 'darwin' in sys.platform: if config.getboolean('bitmessagesettings', 'minimizetotray') and not 'darwin' in sys.platform:
@ -3655,6 +3791,14 @@ class MyForm(QtGui.QMainWindow):
if toLabel == '': if toLabel == '':
toLabel = toAddress toLabel = toAddress
self.ui.tableWidgetInbox.item(i,0).setText(unicode(toLabel,'utf-8')) self.ui.tableWidgetInbox.item(i,0).setText(unicode(toLabel,'utf-8'))
#Set the color according to whether it is the address of a mailing list or not.
try:
if config.getboolean(toAddress,'mailinglist'):
self.ui.tableWidgetInbox.item(i,0).setTextColor(QtGui.QColor(137,04,177))
else:
self.ui.tableWidgetInbox.item(i,0).setTextColor(QtGui.QColor(0,0,0))
except:
self.ui.tableWidgetInbox.item(i,0).setTextColor(QtGui.QColor(0,0,0))
def rerenderSentFromLabels(self): def rerenderSentFromLabels(self):
for i in range(self.ui.tableWidgetSent.rowCount()): for i in range(self.ui.tableWidgetSent.rowCount()):
@ -3695,7 +3839,7 @@ class MyForm(QtGui.QMainWindow):
status,addressVersionNumber,streamNumber,ripe = decodeAddress(toAddress) status,addressVersionNumber,streamNumber,ripe = decodeAddress(toAddress)
if status <> 'success': if status <> 'success':
printLock.acquire() printLock.acquire()
print 'Status bar:', 'Error: Could not decode', toAddress, ':', status print 'Error: Could not decode', toAddress, ':', status
printLock.release() printLock.release()
if status == 'missingbm': if status == 'missingbm':
self.statusBar().showMessage('Error: Bitmessage addresses start with BM- Please check ' + toAddress) self.statusBar().showMessage('Error: Bitmessage addresses start with BM- Please check ' + toAddress)
@ -3780,7 +3924,11 @@ class MyForm(QtGui.QMainWindow):
self.ui.textEditSentMessage.setText(self.ui.tableWidgetSent.item(0,2).data(Qt.UserRole).toPyObject()) self.ui.textEditSentMessage.setText(self.ui.tableWidgetSent.item(0,2).data(Qt.UserRole).toPyObject())
self.ui.comboBoxSendFrom.setCurrentIndex(0)
self.ui.labelFrom.setText('') self.ui.labelFrom.setText('')
self.ui.lineEditTo.setText('')
self.ui.lineEditSubject.setText('')
self.ui.textEditMessage.setText('')
self.ui.tabWidget.setCurrentIndex(2) self.ui.tabWidget.setCurrentIndex(2)
self.ui.tableWidgetSent.setCurrentCell(0,0) self.ui.tableWidgetSent.setCurrentCell(0,0)
else: else:
@ -3834,7 +3982,11 @@ class MyForm(QtGui.QMainWindow):
self.ui.textEditSentMessage.setText(self.ui.tableWidgetSent.item(0,2).data(Qt.UserRole).toPyObject()) self.ui.textEditSentMessage.setText(self.ui.tableWidgetSent.item(0,2).data(Qt.UserRole).toPyObject())
self.ui.comboBoxSendFrom.setCurrentIndex(0)
self.ui.labelFrom.setText('') self.ui.labelFrom.setText('')
self.ui.lineEditTo.setText('')
self.ui.lineEditSubject.setText('')
self.ui.textEditMessage.setText('')
self.ui.tabWidget.setCurrentIndex(2) self.ui.tabWidget.setCurrentIndex(2)
self.ui.tableWidgetSent.setCurrentCell(0,0) self.ui.tableWidgetSent.setCurrentCell(0,0)
@ -3887,7 +4039,8 @@ class MyForm(QtGui.QMainWindow):
def connectObjectToSignals(self,object): def connectObjectToSignals(self,object):
QtCore.QObject.connect(object, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar) QtCore.QObject.connect(object, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
QtCore.QObject.connect(object, QtCore.SIGNAL("displayNewMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewMessage) QtCore.QObject.connect(object, QtCore.SIGNAL("displayNewInboxMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewInboxMessage)
QtCore.QObject.connect(object, QtCore.SIGNAL("displayNewSentMessage(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayNewSentMessage)
QtCore.QObject.connect(object, QtCore.SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByHash) QtCore.QObject.connect(object, QtCore.SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByHash)
QtCore.QObject.connect(object, QtCore.SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByAckdata) QtCore.QObject.connect(object, QtCore.SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByAckdata)
QtCore.QObject.connect(object, QtCore.SIGNAL("updateNetworkStatusTab(PyQt_PyObject,PyQt_PyObject)"), self.updateNetworkStatusTab) QtCore.QObject.connect(object, QtCore.SIGNAL("updateNetworkStatusTab(PyQt_PyObject,PyQt_PyObject)"), self.updateNetworkStatusTab)
@ -3896,8 +4049,37 @@ class MyForm(QtGui.QMainWindow):
QtCore.QObject.connect(object, QtCore.SIGNAL("incrementNumberOfBroadcastsProcessed()"), self.incrementNumberOfBroadcastsProcessed) QtCore.QObject.connect(object, QtCore.SIGNAL("incrementNumberOfBroadcastsProcessed()"), self.incrementNumberOfBroadcastsProcessed)
QtCore.QObject.connect(object, QtCore.SIGNAL("setStatusIcon(PyQt_PyObject)"), self.setStatusIcon) QtCore.QObject.connect(object, QtCore.SIGNAL("setStatusIcon(PyQt_PyObject)"), self.setStatusIcon)
def displayNewMessage(self,inventoryHash,toAddress,fromAddress,subject,message): #This function is called by the processmsg function when that function receives a message to an address that is acting as a pseudo-mailing-list. The message will be broadcast out. This function puts the message on the 'Sent' tab.
'''print 'test signals displayNewMessage' def displayNewSentMessage(self,toAddress,toLabel,fromAddress,subject,message,ackdata):
try:
fromLabel = config.get(fromAddress, 'label')
except:
fromLabel = ''
if fromLabel == '':
fromLabel = fromAddress
self.ui.tableWidgetSent.insertRow(0)
newItem = QtGui.QTableWidgetItem(unicode(toLabel,'utf-8'))
newItem.setData(Qt.UserRole,str(toAddress))
self.ui.tableWidgetSent.setItem(0,0,newItem)
if fromLabel == '':
newItem = QtGui.QTableWidgetItem(unicode(fromAddress,'utf-8'))
else:
newItem = QtGui.QTableWidgetItem(unicode(fromLabel,'utf-8'))
newItem.setData(Qt.UserRole,str(fromAddress))
self.ui.tableWidgetSent.setItem(0,1,newItem)
newItem = QtGui.QTableWidgetItem(unicode(subject,'utf-8)'))
newItem.setData(Qt.UserRole,unicode(message,'utf-8)'))
self.ui.tableWidgetSent.setItem(0,2,newItem)
#newItem = QtGui.QTableWidgetItem('Doing work necessary to send broadcast...'+strftime(config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))))
newItem = myTableWidgetItem('Doing work necessary to send broadcast...')
newItem.setData(Qt.UserRole,QByteArray(ackdata))
newItem.setData(33,int(time.time()))
self.ui.tableWidgetSent.setItem(0,3,newItem)
self.ui.textEditSentMessage.setText(self.ui.tableWidgetSent.item(0,2).data(Qt.UserRole).toPyObject())
def displayNewInboxMessage(self,inventoryHash,toAddress,fromAddress,subject,message):
'''print 'test signals displayNewInboxMessage'
print 'toAddress', toAddress print 'toAddress', toAddress
print 'fromAddress', fromAddress print 'fromAddress', fromAddress
print 'message', message''' print 'message', message'''
@ -3937,6 +4119,11 @@ class MyForm(QtGui.QMainWindow):
#msgid, toaddress, fromaddress, subject, received, message = row #msgid, toaddress, fromaddress, subject, received, message = row
newItem = QtGui.QTableWidgetItem(unicode(toLabel,'utf-8')) newItem = QtGui.QTableWidgetItem(unicode(toLabel,'utf-8'))
newItem.setData(Qt.UserRole,str(toAddress)) newItem.setData(Qt.UserRole,str(toAddress))
try:
if config.getboolean(str(toAddress),'mailinglist'):
newItem.setTextColor(QtGui.QColor(137,04,177))
except:
pass #the 'mailinglist' setting was not found for this address.
self.ui.tableWidgetInbox.insertRow(0) self.ui.tableWidgetInbox.insertRow(0)
self.ui.tableWidgetInbox.setItem(0,0,newItem) self.ui.tableWidgetInbox.setItem(0,0,newItem)
@ -4027,18 +4214,22 @@ class MyForm(QtGui.QMainWindow):
#Initialize the Blacklist or Whitelist table #Initialize the Blacklist or Whitelist table
listType = config.get('bitmessagesettings', 'blackwhitelist') listType = config.get('bitmessagesettings', 'blackwhitelist')
if listType == 'black': if listType == 'black':
sqlSubmitQueue.put('''SELECT label, address FROM blacklist''') sqlSubmitQueue.put('''SELECT label, address, enabled FROM blacklist''')
else: else:
sqlSubmitQueue.put('''SELECT label, address FROM whitelist''') sqlSubmitQueue.put('''SELECT label, address, enabled FROM whitelist''')
sqlSubmitQueue.put('') sqlSubmitQueue.put('')
queryreturn = sqlReturnQueue.get() queryreturn = sqlReturnQueue.get()
for row in queryreturn: for row in queryreturn:
label, address = row label, address, enabled = row
self.ui.tableWidgetBlacklist.insertRow(0) self.ui.tableWidgetBlacklist.insertRow(0)
newItem = QtGui.QTableWidgetItem(unicode(label,'utf-8')) newItem = QtGui.QTableWidgetItem(unicode(label,'utf-8'))
if not enabled:
newItem.setTextColor(QtGui.QColor(128,128,128))
self.ui.tableWidgetBlacklist.setItem(0,0,newItem) self.ui.tableWidgetBlacklist.setItem(0,0,newItem)
newItem = QtGui.QTableWidgetItem(address) newItem = QtGui.QTableWidgetItem(address)
newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) newItem.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
if not enabled:
newItem.setTextColor(QtGui.QColor(128,128,128))
self.ui.tableWidgetBlacklist.setItem(0,1,newItem) self.ui.tableWidgetBlacklist.setItem(0,1,newItem)
def click_pushButtonStatusIcon(self): def click_pushButtonStatusIcon(self):
@ -4057,6 +4248,7 @@ class MyForm(QtGui.QMainWindow):
def click_actionSettings(self): def click_actionSettings(self):
global statusIconColor global statusIconColor
global appdata
self.settingsDialogInstance = settingsDialog(self) self.settingsDialogInstance = settingsDialog(self)
if self.settingsDialogInstance.exec_(): if self.settingsDialogInstance.exec_():
config.set('bitmessagesettings', 'startonlogon', str(self.settingsDialogInstance.ui.checkBoxStartOnLogon.isChecked())) config.set('bitmessagesettings', 'startonlogon', str(self.settingsDialogInstance.ui.checkBoxStartOnLogon.isChecked()))
@ -4096,6 +4288,37 @@ class MyForm(QtGui.QMainWindow):
#startup for linux #startup for linux
pass pass
if appdata != '' and self.settingsDialogInstance.ui.checkBoxPortableMode.isChecked(): #If we are NOT using portable mode now but the user selected that we should...
config.set('bitmessagesettings','movemessagstoprog','true') #Tells bitmessage to move the messages.dat file to the program directory the next time the program starts.
#Write the keys.dat file to disk in the new location
with open('keys.dat', 'wb') as configfile:
config.write(configfile)
#Write the knownnodes.dat file to disk in the new location
output = open('knownnodes.dat', 'wb')
pickle.dump(knownNodes, output)
output.close()
os.remove(appdata + 'keys.dat')
os.remove(appdata + 'knownnodes.dat')
appdata = ''
QMessageBox.about(self, "Restart", "Bitmessage has moved most of your config files to the program directory but you must restart Bitmessage to move the last file (the file which holds messages).")
if appdata == '' and not self.settingsDialogInstance.ui.checkBoxPortableMode.isChecked(): #If we ARE using portable mode now but the user selected that we shouldn't...
appdata = lookupAppdataFolder()
if not os.path.exists(appdata):
os.makedirs(appdata)
config.set('bitmessagesettings','movemessagstoappdata','true') #Tells bitmessage to move the messages.dat file to the appdata directory the next time the program starts.
#Write the keys.dat file to disk in the new location
with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile)
#Write the knownnodes.dat file to disk in the new location
output = open(appdata + 'knownnodes.dat', 'wb')
pickle.dump(knownNodes, output)
output.close()
os.remove('keys.dat')
os.remove('knownnodes.dat')
QMessageBox.about(self, "Restart", "Bitmessage has moved most of your config files to the application data directory but you must restart Bitmessage to move the last file (the file which holds messages).")
def click_radioButtonBlacklist(self): def click_radioButtonBlacklist(self):
if config.get('bitmessagesettings', 'blackwhitelist') == 'white': if config.get('bitmessagesettings', 'blackwhitelist') == 'white':
config.set('bitmessagesettings','blackwhitelist','black') config.set('bitmessagesettings','blackwhitelist','black')
@ -4152,6 +4375,27 @@ class MyForm(QtGui.QMainWindow):
else: else:
self.statusBar().showMessage('The address you entered was invalid. Ignoring it.') self.statusBar().showMessage('The address you entered was invalid. Ignoring it.')
def on_action_SpecialAddressBehaviorDialog(self):
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())
if self.dialog.ui.radioButtonBehaveNormalAddress.isChecked():
config.set(str(addressAtCurrentRow),'mailinglist','false')
#Set the color to either black or grey
if config.getboolean(addressAtCurrentRow,'enabled'):
self.ui.tableWidgetYourIdentities.item(currentRow,1).setTextColor(QtGui.QColor(0,0,0))
else:
self.ui.tableWidgetYourIdentities.item(currentRow,1).setTextColor(QtGui.QColor(128,128,128))
else:
config.set(str(addressAtCurrentRow),'mailinglist','true')
config.set(str(addressAtCurrentRow),'mailinglistname',str(self.dialog.ui.lineEditMailingListName.text().toUtf8()))
self.ui.tableWidgetYourIdentities.item(currentRow,1).setTextColor(QtGui.QColor(137,04,177))
with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile)
self.rerenderInboxToLabels()
def click_NewAddressDialog(self): def click_NewAddressDialog(self):
self.dialog = NewAddressDialog(self) self.dialog = NewAddressDialog(self)
@ -4242,7 +4486,7 @@ class MyForm(QtGui.QMainWindow):
#self.ui.comboBoxSendFrom.setEditText(str(self.ui.tableWidgetInbox.item(currentInboxRow,0).text)) #self.ui.comboBoxSendFrom.setEditText(str(self.ui.tableWidgetInbox.item(currentInboxRow,0).text))
self.ui.textEditMessage.setText('\n\n------------------------------------------------------\n'+self.ui.tableWidgetInbox.item(currentInboxRow,2).data(Qt.UserRole).toPyObject()) self.ui.textEditMessage.setText('\n\n------------------------------------------------------\n'+self.ui.tableWidgetInbox.item(currentInboxRow,2).data(Qt.UserRole).toPyObject())
if self.ui.tableWidgetInbox.item(currentInboxRow,2).text()[0:3] == 'Re:': if self.ui.tableWidgetInbox.item(currentInboxRow,2).text()[0:3] == 'Re:':
self.ui.lineEditSubject.setText(str(self.ui.tableWidgetInbox.item(currentInboxRow,2).text())) self.ui.lineEditSubject.setText(self.ui.tableWidgetInbox.item(currentInboxRow,2).text())
else: else:
self.ui.lineEditSubject.setText('Re: '+self.ui.tableWidgetInbox.item(currentInboxRow,2).text()) self.ui.lineEditSubject.setText('Re: '+self.ui.tableWidgetInbox.item(currentInboxRow,2).text())
self.ui.radioButtonSpecific.setChecked(True) self.ui.radioButtonSpecific.setChecked(True)
@ -4304,6 +4548,11 @@ class MyForm(QtGui.QMainWindow):
sqlLock.release() sqlLock.release()
self.ui.tableWidgetSent.removeRow(currentRow) self.ui.tableWidgetSent.removeRow(currentRow)
self.statusBar().showMessage('Moved item 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.') self.statusBar().showMessage('Moved item 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.')
def on_action_SentClipboard(self):
currentRow = self.ui.tableWidgetSent.currentRow()
addressAtCurrentRow = str(self.ui.tableWidgetSent.item(currentRow,0).data(Qt.UserRole).toPyObject())
clipboard = QtGui.QApplication.clipboard()
clipboard.setText(str(addressAtCurrentRow))
#Group of functions for the Address Book dialog box #Group of functions for the Address Book dialog box
def on_action_AddressBookNew(self): def on_action_AddressBookNew(self):
@ -4363,27 +4612,97 @@ class MyForm(QtGui.QMainWindow):
def on_context_menuSubscriptions(self, point): def on_context_menuSubscriptions(self, point):
self.popMenuSubscriptions.exec_( self.ui.tableWidgetSubscriptions.mapToGlobal(point) ) self.popMenuSubscriptions.exec_( self.ui.tableWidgetSubscriptions.mapToGlobal(point) )
#Group of functions for the Blacklist dialog box
def on_action_BlacklistNew(self):
self.click_pushButtonAddBlacklist()
def on_action_BlacklistDelete(self):
print 'clicked Delete'
currentRow = self.ui.tableWidgetBlacklist.currentRow()
labelAtCurrentRow = self.ui.tableWidgetBlacklist.item(currentRow,0).text().toUtf8()
addressAtCurrentRow = self.ui.tableWidgetBlacklist.item(currentRow,1).text()
t = (str(labelAtCurrentRow),str(addressAtCurrentRow))
sqlLock.acquire()
if config.get('bitmessagesettings', 'blackwhitelist') == 'black':
sqlSubmitQueue.put('''DELETE FROM blacklist WHERE label=? AND address=?''')
sqlSubmitQueue.put(t)
sqlReturnQueue.get()
else:
sqlSubmitQueue.put('''DELETE FROM whitelist WHERE label=? AND address=?''')
sqlSubmitQueue.put(t)
sqlReturnQueue.get()
sqlLock.release()
self.ui.tableWidgetBlacklist.removeRow(currentRow)
def on_action_BlacklistClipboard(self):
currentRow = self.ui.tableWidgetBlacklist.currentRow()
addressAtCurrentRow = self.ui.tableWidgetBlacklist.item(currentRow,1).text()
clipboard = QtGui.QApplication.clipboard()
clipboard.setText(str(addressAtCurrentRow))
def on_context_menuBlacklist(self, point):
self.popMenuBlacklist.exec_( self.ui.tableWidgetBlacklist.mapToGlobal(point) )
def on_action_BlacklistEnable(self):
currentRow = self.ui.tableWidgetBlacklist.currentRow()
addressAtCurrentRow = self.ui.tableWidgetBlacklist.item(currentRow,1).text()
self.ui.tableWidgetBlacklist.item(currentRow,0).setTextColor(QtGui.QColor(0,0,0))
self.ui.tableWidgetBlacklist.item(currentRow,1).setTextColor(QtGui.QColor(0,0,0))
t = (str(addressAtCurrentRow),)
sqlLock.acquire()
if config.get('bitmessagesettings', 'blackwhitelist') == 'black':
sqlSubmitQueue.put('''UPDATE blacklist SET enabled=1 WHERE address=?''')
sqlSubmitQueue.put(t)
sqlReturnQueue.get()
else:
sqlSubmitQueue.put('''UPDATE whitelist SET enabled=1 WHERE address=?''')
sqlSubmitQueue.put(t)
sqlReturnQueue.get()
sqlLock.release()
def on_action_BlacklistDisable(self):
currentRow = self.ui.tableWidgetBlacklist.currentRow()
addressAtCurrentRow = self.ui.tableWidgetBlacklist.item(currentRow,1).text()
self.ui.tableWidgetBlacklist.item(currentRow,0).setTextColor(QtGui.QColor(128,128,128))
self.ui.tableWidgetBlacklist.item(currentRow,1).setTextColor(QtGui.QColor(128,128,128))
t = (str(addressAtCurrentRow),)
sqlLock.acquire()
if config.get('bitmessagesettings', 'blackwhitelist') == 'black':
sqlSubmitQueue.put('''UPDATE blacklist SET enabled=0 WHERE address=?''')
sqlSubmitQueue.put(t)
sqlReturnQueue.get()
else:
sqlSubmitQueue.put('''UPDATE whitelist SET enabled=0 WHERE address=?''')
sqlSubmitQueue.put(t)
sqlReturnQueue.get()
sqlLock.release()
#Group of functions for the Your Identities dialog box #Group of functions for the Your Identities dialog box
def on_action_YourIdentitiesNew(self): def on_action_YourIdentitiesNew(self):
self.click_NewAddressDialog() self.click_NewAddressDialog()
def on_action_YourIdentitiesEnable(self): def on_action_YourIdentitiesEnable(self):
currentRow = self.ui.tableWidgetYourIdentities.currentRow() currentRow = self.ui.tableWidgetYourIdentities.currentRow()
addressAtCurrentRow = self.ui.tableWidgetYourIdentities.item(currentRow,1).text() addressAtCurrentRow = str(self.ui.tableWidgetYourIdentities.item(currentRow,1).text())
config.set(str(addressAtCurrentRow),'enabled','true') config.set(addressAtCurrentRow,'enabled','true')
with open(appdata + 'keys.dat', 'wb') as configfile: with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile) config.write(configfile)
self.ui.tableWidgetYourIdentities.item(currentRow,0).setTextColor(QtGui.QColor(0,0,0)) self.ui.tableWidgetYourIdentities.item(currentRow,0).setTextColor(QtGui.QColor(0,0,0))
self.ui.tableWidgetYourIdentities.item(currentRow,1).setTextColor(QtGui.QColor(0,0,0)) self.ui.tableWidgetYourIdentities.item(currentRow,1).setTextColor(QtGui.QColor(0,0,0))
self.ui.tableWidgetYourIdentities.item(currentRow,2).setTextColor(QtGui.QColor(0,0,0)) self.ui.tableWidgetYourIdentities.item(currentRow,2).setTextColor(QtGui.QColor(0,0,0))
try:
if config.getboolean(addressAtCurrentRow,'mailinglist'):
self.ui.tableWidgetYourIdentities.item(currentRow,1).setTextColor(QtGui.QColor(137,04,177))
except:
pass
reloadMyAddressHashes() reloadMyAddressHashes()
def on_action_YourIdentitiesDisable(self): def on_action_YourIdentitiesDisable(self):
currentRow = self.ui.tableWidgetYourIdentities.currentRow() currentRow = self.ui.tableWidgetYourIdentities.currentRow()
addressAtCurrentRow = self.ui.tableWidgetYourIdentities.item(currentRow,1).text() addressAtCurrentRow = str(self.ui.tableWidgetYourIdentities.item(currentRow,1).text())
config.set(str(addressAtCurrentRow),'enabled','false') config.set(str(addressAtCurrentRow),'enabled','false')
self.ui.tableWidgetYourIdentities.item(currentRow,0).setTextColor(QtGui.QColor(128,128,128)) 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,1).setTextColor(QtGui.QColor(128,128,128))
self.ui.tableWidgetYourIdentities.item(currentRow,2).setTextColor(QtGui.QColor(128,128,128)) self.ui.tableWidgetYourIdentities.item(currentRow,2).setTextColor(QtGui.QColor(128,128,128))
try:
if config.getboolean(addressAtCurrentRow,'mailinglist'):
self.ui.tableWidgetYourIdentities.item(currentRow,1).setTextColor(QtGui.QColor(137,04,177))
except:
pass
with open(appdata + 'keys.dat', 'wb') as configfile: with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile) config.write(configfile)
reloadMyAddressHashes() reloadMyAddressHashes()
@ -4462,6 +4781,7 @@ class MyForm(QtGui.QMainWindow):
self.rerenderComboBoxSendFrom() self.rerenderComboBoxSendFrom()
def updateStatusBar(self,data): def updateStatusBar(self,data):
if data != "":
printLock.acquire() printLock.acquire()
print 'Status bar:', data print 'Status bar:', data
printLock.release() printLock.release()
@ -4520,36 +4840,29 @@ if __name__ == "__main__":
print 'This program requires sqlite version 3 or higher because 2 and lower cannot store NULL values. I see version:', sqlite3.sqlite_version_info print 'This program requires sqlite version 3 or higher because 2 and lower cannot store NULL values. I see version:', sqlite3.sqlite_version_info
sys.exit() sys.exit()
if not storeConfigFilesInSameDirectoryAsProgram: #First try to load the config file (the keys.dat file) from the program directory
APPNAME = "PyBitmessage" config = ConfigParser.SafeConfigParser()
from os import path, environ config.read('keys.dat')
if sys.platform == 'darwin': try:
if "HOME" in environ: config.get('bitmessagesettings', 'settingsversion')
appdata = path.join(os.environ["HOME"], "Library/Application support/", APPNAME) + '/' #settingsFileExistsInProgramDirectory = True
else: print 'Loading config files from same directory as program'
print 'Could not find home folder, please report this message and your OS X version to the BitMessage Github.' appdata = ''
sys.exit() except:
#Could not load the keys.dat file in the program directory. Perhaps it is in the appdata directory.
elif 'win32' in sys.platform or 'win64' in sys.platform: appdata = lookupAppdataFolder()
appdata = path.join(environ['APPDATA'], APPNAME) + '\\' #if not os.path.exists(appdata):
else: # os.makedirs(appdata)
appdata = path.expanduser(path.join("~", "." + APPNAME + "/"))
if not os.path.exists(appdata):
os.makedirs(appdata)
else:
appdata = ""
config = ConfigParser.SafeConfigParser() config = ConfigParser.SafeConfigParser()
config.read(appdata + 'keys.dat') config.read(appdata + 'keys.dat')
try: try:
config.get('bitmessagesettings', 'settingsversion') config.get('bitmessagesettings', 'settingsversion')
print 'Loading config files from', appdata print 'Loading existing config files from', appdata
except: except:
#This appears to be the first time running the program; there is no config file (or it cannot be accessed). Create config file. #This appears to be the first time running the program; there is no config file (or it cannot be accessed). Create config file.
config.add_section('bitmessagesettings') config.add_section('bitmessagesettings')
config.set('bitmessagesettings','settingsversion','1') config.set('bitmessagesettings','settingsversion','1')
#config.set('bitmessagesettings','bitstrength','2048')
config.set('bitmessagesettings','port','8444') config.set('bitmessagesettings','port','8444')
config.set('bitmessagesettings','timeformat','%%a, %%d %%b %%Y %%I:%%M %%p') config.set('bitmessagesettings','timeformat','%%a, %%d %%b %%Y %%I:%%M %%p')
config.set('bitmessagesettings','blackwhitelist','black') config.set('bitmessagesettings','blackwhitelist','black')
@ -4561,11 +4874,16 @@ if __name__ == "__main__":
config.set('bitmessagesettings','showtraynotifications','true') config.set('bitmessagesettings','showtraynotifications','true')
config.set('bitmessagesettings','startintray','false') config.set('bitmessagesettings','startintray','false')
if storeConfigFilesInSameDirectoryAsProgramByDefault:
#Just use the same directory as the program and forget about the appdata folder
appdata = ''
print 'Creating new config files in same directory as program.'
else:
print 'Creating new config files in', appdata
if not os.path.exists(appdata):
os.makedirs(appdata)
with open(appdata + 'keys.dat', 'wb') as configfile: with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile) config.write(configfile)
print 'Storing config files in', appdata
if config.getint('bitmessagesettings','settingsversion') == 1: if config.getint('bitmessagesettings','settingsversion') == 1:
config.set('bitmessagesettings','settingsversion','3') #If the settings version is equal to 2 then the sqlThread will modify the pubkeys table and change the settings version to 3. config.set('bitmessagesettings','settingsversion','3') #If the settings version is equal to 2 then the sqlThread will modify the pubkeys table and change the settings version to 3.
@ -4580,6 +4898,29 @@ if __name__ == "__main__":
with open(appdata + 'keys.dat', 'wb') as configfile: with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile) config.write(configfile)
#Let us now see if we should move the messages.dat file. There is an option in the settings to switch 'Portable Mode' on or off. Most of the files are moved instantly, but the messages.dat file cannot be moved while it is open. Now that it is not open we can move it now!
try:
config.getboolean('bitmessagesettings', 'movemessagstoprog')
#If we have reached this point then we must move the messages.dat file from the appdata folder to the program folder
print 'Moving messages.dat from its old location in the application data folder to its new home along side the program.'
shutil.move(lookupAppdataFolder()+'messages.dat','messages.dat')
config.remove_option('bitmessagesettings', 'movemessagstoprog')
with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile)
except:
pass
try:
config.getboolean('bitmessagesettings', 'movemessagstoappdata')
#If we have reached this point then we must move the messages.dat file from the appdata folder to the program folder
print 'Moving messages.dat from its old location next to the program to its new home in the application data folder.'
shutil.move('messages.dat',lookupAppdataFolder()+'messages.dat')
config.remove_option('bitmessagesettings', 'movemessagstoappdata')
with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile)
except:
pass
try: try:
pickleFile = open(appdata + 'knownnodes.dat', 'rb') pickleFile = open(appdata + 'knownnodes.dat', 'rb')
knownNodes = pickle.load(pickleFile) knownNodes = pickle.load(pickleFile)

View File

@ -10,9 +10,11 @@ def createDefaultKnownNodes(appdata):
############## Stream 1 ################ ############## Stream 1 ################
stream1 = {} stream1 = {}
stream1['66.108.210.244'] = (8080,int(time.time())) stream1['66.65.120.151'] = (8080,int(time.time()))
stream1['76.180.233.38'] = (8444,int(time.time()))
stream1['84.48.88.42'] = (8444,int(time.time()))
stream1['74.132.73.137'] = (8444,int(time.time()))
stream1['60.242.109.18'] = (8444,int(time.time())) stream1['60.242.109.18'] = (8444,int(time.time()))
stream1['84.48.88.49'] = (8444,int(time.time()))
############# Stream 2 ################# ############# Stream 2 #################
stream2 = {} stream2 = {}

View File

@ -70,7 +70,7 @@ def base10_multiply(a,n):
if (n%2) == 0: return base10_double(base10_multiply(a,n/2)) if (n%2) == 0: return base10_double(base10_multiply(a,n/2))
if (n%2) == 1: return base10_add(base10_double(base10_multiply(a,n/2)),a) if (n%2) == 1: return base10_add(base10_double(base10_multiply(a,n/2)),a)
def hex_to_point(h): return (decode(h[2:34],16),decode(h[34:],16)) def hex_to_point(h): return (decode(h[2:66],16),decode(h[66:],16))
def point_to_hex(p): return '04'+encode(p[0],16,64)+encode(p[1],16,64) def point_to_hex(p): return '04'+encode(p[0],16,64)+encode(p[1],16,64)
@ -86,9 +86,11 @@ def add(p1,p2):
else: else:
return point_to_hex(base10_add(hex_to_point(p1),hex_to_point(p2))) return point_to_hex(base10_add(hex_to_point(p1),hex_to_point(p2)))
def hash160(string): def hash_160(string):
intermed = hashlib.sha256(string).digest() intermed = hashlib.sha256(string).digest()
return hashlib.new('ripemd160').update(intermed).digest() ripemd160 = hashlib.new('ripemd160')
ripemd160.update(intermed)
return ripemd160.digest()
def dbl_sha256(string): def dbl_sha256(string):
return hashlib.sha256(hashlib.sha256(string).digest()).digest() return hashlib.sha256(hashlib.sha256(string).digest()).digest()
@ -99,5 +101,6 @@ def bin_to_b58check(inp):
checksum = dbl_sha256(inp_fmtd)[:4] checksum = dbl_sha256(inp_fmtd)[:4]
return '1' * leadingzbytes + changebase(inp_fmtd+checksum,256,58) return '1' * leadingzbytes + changebase(inp_fmtd+checksum,256,58)
#Convert a public key (in hex) to a Bitcoin address
def pubkey_to_address(pubkey): def pubkey_to_address(pubkey):
return bin_to_b58check(hash_160(changebase(pubkey,16,256))) return bin_to_b58check(hash_160(changebase(pubkey,16,256)))

View File

@ -2,8 +2,8 @@
# Form implementation generated from reading ui file 'settings.ui' # Form implementation generated from reading ui file 'settings.ui'
# #
# Created: Tue Dec 18 14:31:06 2012 # Created: Wed Feb 27 00:00:12 2013
# by: PyQt4 UI code generator 4.9.4 # by: PyQt4 UI code generator 4.9.5
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@ -30,29 +30,35 @@ class Ui_settingsDialog(object):
self.tabUserInterface = QtGui.QWidget() self.tabUserInterface = QtGui.QWidget()
self.tabUserInterface.setEnabled(True) self.tabUserInterface.setEnabled(True)
self.tabUserInterface.setObjectName(_fromUtf8("tabUserInterface")) self.tabUserInterface.setObjectName(_fromUtf8("tabUserInterface"))
self.formLayout = QtGui.QFormLayout(self.tabUserInterface) self.gridLayout_5 = QtGui.QGridLayout(self.tabUserInterface)
self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow) self.gridLayout_5.setObjectName(_fromUtf8("gridLayout_5"))
self.formLayout.setObjectName(_fromUtf8("formLayout"))
self.checkBoxStartOnLogon = QtGui.QCheckBox(self.tabUserInterface) self.checkBoxStartOnLogon = QtGui.QCheckBox(self.tabUserInterface)
self.checkBoxStartOnLogon.setObjectName(_fromUtf8("checkBoxStartOnLogon")) self.checkBoxStartOnLogon.setObjectName(_fromUtf8("checkBoxStartOnLogon"))
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.checkBoxStartOnLogon) self.gridLayout_5.addWidget(self.checkBoxStartOnLogon, 0, 0, 1, 1)
self.checkBoxStartInTray = QtGui.QCheckBox(self.tabUserInterface) self.checkBoxStartInTray = QtGui.QCheckBox(self.tabUserInterface)
self.checkBoxStartInTray.setObjectName(_fromUtf8("checkBoxStartInTray")) self.checkBoxStartInTray.setObjectName(_fromUtf8("checkBoxStartInTray"))
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.checkBoxStartInTray) self.gridLayout_5.addWidget(self.checkBoxStartInTray, 1, 0, 1, 1)
self.checkBoxMinimizeToTray = QtGui.QCheckBox(self.tabUserInterface) self.checkBoxMinimizeToTray = QtGui.QCheckBox(self.tabUserInterface)
self.checkBoxMinimizeToTray.setChecked(True) self.checkBoxMinimizeToTray.setChecked(True)
self.checkBoxMinimizeToTray.setObjectName(_fromUtf8("checkBoxMinimizeToTray")) self.checkBoxMinimizeToTray.setObjectName(_fromUtf8("checkBoxMinimizeToTray"))
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.checkBoxMinimizeToTray) self.gridLayout_5.addWidget(self.checkBoxMinimizeToTray, 2, 0, 1, 1)
self.checkBoxShowTrayNotifications = QtGui.QCheckBox(self.tabUserInterface) self.checkBoxShowTrayNotifications = QtGui.QCheckBox(self.tabUserInterface)
self.checkBoxShowTrayNotifications.setObjectName(_fromUtf8("checkBoxShowTrayNotifications")) self.checkBoxShowTrayNotifications.setObjectName(_fromUtf8("checkBoxShowTrayNotifications"))
self.formLayout.setWidget(3, QtGui.QFormLayout.SpanningRole, self.checkBoxShowTrayNotifications) self.gridLayout_5.addWidget(self.checkBoxShowTrayNotifications, 3, 0, 1, 1)
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.checkBoxPortableMode = QtGui.QCheckBox(self.tabUserInterface)
self.formLayout.setItem(4, QtGui.QFormLayout.LabelRole, spacerItem) self.checkBoxPortableMode.setObjectName(_fromUtf8("checkBoxPortableMode"))
self.gridLayout_5.addWidget(self.checkBoxPortableMode, 4, 0, 1, 1)
self.label_7 = QtGui.QLabel(self.tabUserInterface)
self.label_7.setWordWrap(True)
self.label_7.setObjectName(_fromUtf8("label_7"))
self.gridLayout_5.addWidget(self.label_7, 5, 0, 1, 1)
self.labelSettingsNote = QtGui.QLabel(self.tabUserInterface) self.labelSettingsNote = QtGui.QLabel(self.tabUserInterface)
self.labelSettingsNote.setText(_fromUtf8("")) self.labelSettingsNote.setText(_fromUtf8(""))
self.labelSettingsNote.setWordWrap(True) self.labelSettingsNote.setWordWrap(True)
self.labelSettingsNote.setObjectName(_fromUtf8("labelSettingsNote")) self.labelSettingsNote.setObjectName(_fromUtf8("labelSettingsNote"))
self.formLayout.setWidget(5, QtGui.QFormLayout.SpanningRole, self.labelSettingsNote) self.gridLayout_5.addWidget(self.labelSettingsNote, 6, 0, 1, 1)
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout_5.addItem(spacerItem, 7, 0, 1, 1)
self.tabWidgetSettings.addTab(self.tabUserInterface, _fromUtf8("")) self.tabWidgetSettings.addTab(self.tabUserInterface, _fromUtf8(""))
self.tabNetworkSettings = QtGui.QWidget() self.tabNetworkSettings = QtGui.QWidget()
self.tabNetworkSettings.setObjectName(_fromUtf8("tabNetworkSettings")) self.tabNetworkSettings.setObjectName(_fromUtf8("tabNetworkSettings"))
@ -145,6 +151,8 @@ class Ui_settingsDialog(object):
self.checkBoxStartInTray.setText(QtGui.QApplication.translate("settingsDialog", "Start Bitmessage in the tray (don\'t show main window)", None, QtGui.QApplication.UnicodeUTF8)) self.checkBoxStartInTray.setText(QtGui.QApplication.translate("settingsDialog", "Start Bitmessage in the tray (don\'t show main window)", None, QtGui.QApplication.UnicodeUTF8))
self.checkBoxMinimizeToTray.setText(QtGui.QApplication.translate("settingsDialog", "Minimize to tray", None, QtGui.QApplication.UnicodeUTF8)) self.checkBoxMinimizeToTray.setText(QtGui.QApplication.translate("settingsDialog", "Minimize to tray", None, QtGui.QApplication.UnicodeUTF8))
self.checkBoxShowTrayNotifications.setText(QtGui.QApplication.translate("settingsDialog", "Show notification when message received and minimzed to tray", None, QtGui.QApplication.UnicodeUTF8)) self.checkBoxShowTrayNotifications.setText(QtGui.QApplication.translate("settingsDialog", "Show notification when message received and minimzed to tray", None, QtGui.QApplication.UnicodeUTF8))
self.checkBoxPortableMode.setText(QtGui.QApplication.translate("settingsDialog", "Run in Portable Mode", None, QtGui.QApplication.UnicodeUTF8))
self.label_7.setText(QtGui.QApplication.translate("settingsDialog", "In Portable Mode, messages and config files are stored in the same directory as the program rather than the normal application-data folder. This makes it convenient to run Bitmessage from a USB thumb drive.", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabUserInterface), QtGui.QApplication.translate("settingsDialog", "User Interface", None, QtGui.QApplication.UnicodeUTF8)) self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabUserInterface), QtGui.QApplication.translate("settingsDialog", "User Interface", None, QtGui.QApplication.UnicodeUTF8))
self.groupBox.setTitle(QtGui.QApplication.translate("settingsDialog", "Listening port", None, QtGui.QApplication.UnicodeUTF8)) self.groupBox.setTitle(QtGui.QApplication.translate("settingsDialog", "Listening port", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("settingsDialog", "Listen for connections on port:", None, QtGui.QApplication.UnicodeUTF8)) self.label.setText(QtGui.QApplication.translate("settingsDialog", "Listen for connections on port:", None, QtGui.QApplication.UnicodeUTF8))

View File

@ -36,10 +36,7 @@
<attribute name="title"> <attribute name="title">
<string>User Interface</string> <string>User Interface</string>
</attribute> </attribute>
<layout class="QFormLayout" name="formLayout"> <layout class="QGridLayout" name="gridLayout_5">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QCheckBox" name="checkBoxStartOnLogon"> <widget class="QCheckBox" name="checkBoxStartOnLogon">
<property name="text"> <property name="text">
@ -64,7 +61,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="2"> <item row="3" column="0">
<widget class="QCheckBox" name="checkBoxShowTrayNotifications"> <widget class="QCheckBox" name="checkBoxShowTrayNotifications">
<property name="text"> <property name="text">
<string>Show notification when message received and minimzed to tray</string> <string>Show notification when message received and minimzed to tray</string>
@ -72,6 +69,33 @@
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="4" column="0">
<widget class="QCheckBox" name="checkBoxPortableMode">
<property name="text">
<string>Run in Portable Mode</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>In Portable Mode, messages and config files are stored in the same directory as the program rather than the normal application-data folder. This makes it convenient to run Bitmessage from a USB thumb drive.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="labelSettingsNote">
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="7" column="0">
<spacer name="verticalSpacer_2"> <spacer name="verticalSpacer_2">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -84,16 +108,6 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="5" column="0" colspan="2">
<widget class="QLabel" name="labelSettingsNote">
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tabNetworkSettings"> <widget class="QWidget" name="tabNetworkSettings">

64
specialaddressbehavior.py Normal file
View File

@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'specialaddressbehavior.ui'
#
# Created: Mon Feb 25 17:04:13 2013
# by: PyQt4 UI code generator 4.9.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_SpecialAddressBehaviorDialog(object):
def setupUi(self, SpecialAddressBehaviorDialog):
SpecialAddressBehaviorDialog.setObjectName(_fromUtf8("SpecialAddressBehaviorDialog"))
SpecialAddressBehaviorDialog.resize(386, 172)
self.gridLayout = QtGui.QGridLayout(SpecialAddressBehaviorDialog)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.radioButtonBehaveNormalAddress = QtGui.QRadioButton(SpecialAddressBehaviorDialog)
self.radioButtonBehaveNormalAddress.setChecked(True)
self.radioButtonBehaveNormalAddress.setObjectName(_fromUtf8("radioButtonBehaveNormalAddress"))
self.gridLayout.addWidget(self.radioButtonBehaveNormalAddress, 0, 0, 1, 1)
self.radioButtonBehaviorMailingList = QtGui.QRadioButton(SpecialAddressBehaviorDialog)
self.radioButtonBehaviorMailingList.setObjectName(_fromUtf8("radioButtonBehaviorMailingList"))
self.gridLayout.addWidget(self.radioButtonBehaviorMailingList, 1, 0, 1, 1)
self.label = QtGui.QLabel(SpecialAddressBehaviorDialog)
self.label.setWordWrap(True)
self.label.setObjectName(_fromUtf8("label"))
self.gridLayout.addWidget(self.label, 2, 0, 1, 1)
self.label_2 = QtGui.QLabel(SpecialAddressBehaviorDialog)
self.label_2.setObjectName(_fromUtf8("label_2"))
self.gridLayout.addWidget(self.label_2, 3, 0, 1, 1)
self.lineEditMailingListName = QtGui.QLineEdit(SpecialAddressBehaviorDialog)
self.lineEditMailingListName.setEnabled(False)
self.lineEditMailingListName.setObjectName(_fromUtf8("lineEditMailingListName"))
self.gridLayout.addWidget(self.lineEditMailingListName, 4, 0, 1, 1)
self.buttonBox = QtGui.QDialogButtonBox(SpecialAddressBehaviorDialog)
self.buttonBox.setMinimumSize(QtCore.QSize(368, 0))
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.gridLayout.addWidget(self.buttonBox, 5, 0, 1, 1)
self.retranslateUi(SpecialAddressBehaviorDialog)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), SpecialAddressBehaviorDialog.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), SpecialAddressBehaviorDialog.reject)
QtCore.QObject.connect(self.radioButtonBehaviorMailingList, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.lineEditMailingListName.setEnabled)
QtCore.QObject.connect(self.radioButtonBehaveNormalAddress, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.lineEditMailingListName.setDisabled)
QtCore.QMetaObject.connectSlotsByName(SpecialAddressBehaviorDialog)
SpecialAddressBehaviorDialog.setTabOrder(self.radioButtonBehaveNormalAddress, self.radioButtonBehaviorMailingList)
SpecialAddressBehaviorDialog.setTabOrder(self.radioButtonBehaviorMailingList, self.lineEditMailingListName)
SpecialAddressBehaviorDialog.setTabOrder(self.lineEditMailingListName, self.buttonBox)
def retranslateUi(self, SpecialAddressBehaviorDialog):
SpecialAddressBehaviorDialog.setWindowTitle(QtGui.QApplication.translate("SpecialAddressBehaviorDialog", "Special Address Behavior", None, QtGui.QApplication.UnicodeUTF8))
self.radioButtonBehaveNormalAddress.setText(QtGui.QApplication.translate("SpecialAddressBehaviorDialog", "Behave as a normal address", None, QtGui.QApplication.UnicodeUTF8))
self.radioButtonBehaviorMailingList.setText(QtGui.QApplication.translate("SpecialAddressBehaviorDialog", "Behave as a pseudo-mailing-list address", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("SpecialAddressBehaviorDialog", "Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers.", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("SpecialAddressBehaviorDialog", "Name of the pseudo-mailing-list:", None, QtGui.QApplication.UnicodeUTF8))

149
specialaddressbehavior.ui Normal file
View File

@ -0,0 +1,149 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SpecialAddressBehaviorDialog</class>
<widget class="QDialog" name="SpecialAddressBehaviorDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>386</width>
<height>172</height>
</rect>
</property>
<property name="windowTitle">
<string>Special Address Behavior</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QRadioButton" name="radioButtonBehaveNormalAddress">
<property name="text">
<string>Behave as a normal address</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="radioButtonBehaviorMailingList">
<property name="text">
<string>Behave as a pseudo-mailing-list address</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Mail received to a pseudo-mailing-list address will be automatically broadcast to subscribers.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Name of the pseudo-mailing-list:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLineEdit" name="lineEditMailingListName">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="minimumSize">
<size>
<width>368</width>
<height>0</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>radioButtonBehaveNormalAddress</tabstop>
<tabstop>radioButtonBehaviorMailingList</tabstop>
<tabstop>lineEditMailingListName</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SpecialAddressBehaviorDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>227</x>
<y>152</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>171</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SpecialAddressBehaviorDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>295</x>
<y>158</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>171</y>
</hint>
</hints>
</connection>
<connection>
<sender>radioButtonBehaviorMailingList</sender>
<signal>clicked(bool)</signal>
<receiver>lineEditMailingListName</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>95</x>
<y>40</y>
</hint>
<hint type="destinationlabel">
<x>94</x>
<y>123</y>
</hint>
</hints>
</connection>
<connection>
<sender>radioButtonBehaveNormalAddress</sender>
<signal>clicked(bool)</signal>
<receiver>lineEditMailingListName</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>139</x>
<y>19</y>
</hint>
<hint type="destinationlabel">
<x>187</x>
<y>123</y>
</hint>
</hints>
</connection>
</connections>
</ui>