From 9283ce87766f1736326d0aa9c9d38ff01ae66fb2 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Wed, 4 Sep 2013 17:33:39 -0400 Subject: [PATCH 1/5] When replying using chan address, send to whole chan not just sender --- src/bitmessageqt/__init__.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 209c7129..c17ccbca 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -2291,7 +2291,15 @@ class MyForm(QtGui.QMainWindow): else: self.ui.labelFrom.setText(toAddressAtCurrentInboxRow) self.setBroadcastEnablementDependingOnWhetherThisIsAChanAddress(toAddressAtCurrentInboxRow) + self.ui.lineEditTo.setText(str(fromAddressAtCurrentInboxRow)) + + # 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.' + self.ui.lineEditTo.setText(str(toAddressAtCurrentInboxRow)) + self.ui.comboBoxSendFrom.setCurrentIndex(0) # self.ui.comboBoxSendFrom.setEditText(str(self.ui.tableWidgetInbox.item(currentInboxRow,0).text)) self.ui.textEditMessage.setText('\n\n------------------------------------------------------\n' + self.ui.tableWidgetInbox.item( -- 2.45.1 From 48a3bdfefc5d85f03ac24ba7d8554f5d723df507 Mon Sep 17 00:00:00 2001 From: "Grant T. Olson" Date: Wed, 4 Sep 2013 19:25:44 -0400 Subject: [PATCH 2/5] Add chan true/false to listAddresses results --- src/bitmessagemain.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index a73f81e1..ab4e80ba 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -168,8 +168,12 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): data if len(data) > 20: data += ',' + if shared.config.has_option(addressInKeysFile, 'chan'): + chan = shared.config.getboolean(addressInKeysFile, 'chan') + else: + chan = False data += json.dumps({'label': shared.config.get(addressInKeysFile, 'label'), 'address': addressInKeysFile, 'stream': - streamNumber, 'enabled': shared.config.getboolean(addressInKeysFile, 'enabled')}, indent=4, separators=(',', ': ')) + streamNumber, 'enabled': shared.config.getboolean(addressInKeysFile, 'enabled'), 'chan': chan}, indent=4, separators=(',', ': ')) data += ']}' return data elif method == 'listAddressBook' or method == 'listAddressbook': -- 2.45.1 From c06bbc14f814b52eee89070eb33a5e9fd8bd7baf Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Wed, 4 Sep 2013 20:14:25 -0400 Subject: [PATCH 3/5] Give user feedback when disk is full --- src/bitmessagemain.py | 1 + src/bitmessageqt/__init__.py | 11 +++++ src/class_receiveDataThread.py | 11 ++++- src/class_sqlThread.py | 80 ++++++++++++++++++++++++++++++---- src/shared.py | 1 + 5 files changed, 93 insertions(+), 11 deletions(-) diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index a73f81e1..fb6f8012 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -859,6 +859,7 @@ if shared.useVeryEasyProofOfWorkForTesting: class Main: def start(self, daemon=False): + shared.daemon = daemon # is the application already running? If yes then exit. thisapp = singleton.singleinstance() diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index c17ccbca..35df2607 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -431,6 +431,8 @@ class MyForm(QtGui.QMainWindow): "rerenderSubscriptions()"), self.rerenderSubscriptions) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( "removeInboxRowByMsgid(PyQt_PyObject)"), self.removeInboxRowByMsgid) + QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( + "displayAlert(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.displayAlert) self.UISignalThread.start() # Below this point, it would be good if all of the necessary global data @@ -1406,6 +1408,12 @@ class MyForm(QtGui.QMainWindow): self.ui.tableWidgetInbox.removeRow(i) break + def displayAlert(self, title, text, exitAfterUserClicksOk): + self.statusBar().showMessage(text) + QtGui.QMessageBox.critical(self, title, text, QMessageBox.Ok) + if exitAfterUserClicksOk: + os._exit(0) + def rerenderInboxFromLabels(self): for i in range(self.ui.tableWidgetInbox.rowCount()): addressToLookup = str(self.ui.tableWidgetInbox.item( @@ -3197,6 +3205,9 @@ class UISignaler(QThread): self.emit(SIGNAL("rerenderSubscriptions()")) elif command == 'removeInboxRowByMsgid': self.emit(SIGNAL("removeInboxRowByMsgid(PyQt_PyObject)"), data) + elif command == 'alert': + title, text, exitAfterUserClicksOk = data + self.emit(SIGNAL("displayAlert(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)"), title, text, exitAfterUserClicksOk) else: sys.stderr.write( 'Command sent to UISignaler not recognized: %s\n' % command) diff --git a/src/class_receiveDataThread.py b/src/class_receiveDataThread.py index 1ec15b8a..914d3f84 100644 --- a/src/class_receiveDataThread.py +++ b/src/class_receiveDataThread.py @@ -1772,8 +1772,15 @@ class receiveDataThread(threading.Thread): if needToWriteKnownNodesToDisk: # Runs if any nodes were new to us. Also, share those nodes with our peers. shared.knownNodesLock.acquire() output = open(shared.appdata + 'knownnodes.dat', 'wb') - pickle.dump(shared.knownNodes, output) - output.close() + try: + pickle.dump(shared.knownNodes, output) + output.close() + except Exception as err: + if "Errno 28" in str(err): + logger.fatal('(while receiveDataThread needToWriteKnownNodesToDisk) Alert: Your disk or data storage volume is full. ') + shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + if shared.daemon: + os._exit(0) shared.knownNodesLock.release() self.broadcastaddr(listOfAddressDetailsToBroadcastToPeers) with shared.printLock: diff --git a/src/class_sqlThread.py b/src/class_sqlThread.py index 47e41b42..34109172 100644 --- a/src/class_sqlThread.py +++ b/src/class_sqlThread.py @@ -7,6 +7,7 @@ import sys import os from debug import logger from namecoin import ensureNamecoinOptions +import tr#anslate # 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 @@ -18,7 +19,7 @@ class sqlThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) - def run(self): + def run(self): self.conn = sqlite3.connect(shared.appdata + 'messages.dat') self.conn.text_factory = str self.cur = self.conn.cursor() @@ -230,7 +231,15 @@ class sqlThread(threading.Thread): logger.fatal('PyBitmessage will now exit very abruptly. You may now see threading errors related to this abrupt exit but the problem you need to solve is related to SQLite.\n\n') os._exit(0) except Exception as err: - logger.error(err) + if str(err) == 'database or disk is full': + logger.fatal('(While null value test) Alert: Your disk or data storage volume is full. sqlThread will now exit.') + shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + if shared.daemon: + os._exit(0) + else: + return + else: + logger.error(err) # Let us check to see the last time we vaccumed the messages.dat file. # If it has been more than a month let's do it now. @@ -242,7 +251,16 @@ class sqlThread(threading.Thread): value, = row if int(value) < int(time.time()) - 2592000: logger.info('It has been a long time since the messages.dat file has been vacuumed. Vacuuming now...') - self.cur.execute( ''' VACUUM ''') + try: + self.cur.execute( ''' VACUUM ''') + except Exception as err: + if str(err) == 'database or disk is full': + logger.fatal('(While VACUUM) Alert: Your disk or data storage volume is full. sqlThread will now exit.') + shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + if shared.daemon: + os._exit(0) + else: + return item = '''update settings set value=? WHERE key='lastvacuumtime';''' parameters = (int(time.time()),) self.cur.execute(item, parameters) @@ -250,7 +268,16 @@ class sqlThread(threading.Thread): while True: item = shared.sqlSubmitQueue.get() if item == 'commit': - self.conn.commit() + try: + self.conn.commit() + except Exception as err: + if str(err) == 'database or disk is full': + logger.fatal('(While committing) Alert: Your disk or data storage volume is full. sqlThread will now exit.') + shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + if shared.daemon: + os._exit(0) + else: + return elif item == 'exit': self.conn.close() logger.info('sqlThread exiting gracefully.') @@ -259,7 +286,16 @@ class sqlThread(threading.Thread): elif item == 'movemessagstoprog': logger.debug('the sqlThread is moving the messages.dat file to the local program directory.') - self.conn.commit() + try: + self.conn.commit() + except Exception as err: + if str(err) == 'database or disk is full': + logger.fatal('(while movemessagstoprog) Alert: Your disk or data storage volume is full. sqlThread will now exit.') + shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + if shared.daemon: + os._exit(0) + else: + return self.conn.close() shutil.move( shared.lookupAppdataFolder() + 'messages.dat', 'messages.dat') @@ -269,7 +305,16 @@ class sqlThread(threading.Thread): elif item == 'movemessagstoappdata': logger.debug('the sqlThread is moving the messages.dat file to the Appdata folder.') - self.conn.commit() + try: + self.conn.commit() + except Exception as err: + if str(err) == 'database or disk is full': + logger.fatal('(while movemessagstoappdata) Alert: Your disk or data storage volume is full. sqlThread will now exit.') + shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + if shared.daemon: + os._exit(0) + else: + return self.conn.close() shutil.move( 'messages.dat', shared.lookupAppdataFolder() + 'messages.dat') @@ -280,7 +325,16 @@ class sqlThread(threading.Thread): self.cur.execute('''delete from inbox where folder='trash' ''') self.cur.execute('''delete from sent where folder='trash' ''') self.conn.commit() - self.cur.execute( ''' VACUUM ''') + try: + self.cur.execute( ''' VACUUM ''') + except Exception as err: + if str(err) == 'database or disk is full': + logger.fatal('(while deleteandvacuume) Alert: Your disk or data storage volume is full. sqlThread will now exit.') + shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + if shared.daemon: + os._exit(0) + else: + return else: parameters = shared.sqlSubmitQueue.get() # print 'item', item @@ -288,8 +342,16 @@ class sqlThread(threading.Thread): try: self.cur.execute(item, parameters) except Exception as err: - logger.fatal('Major error occurred when trying to execute a SQL statement within the sqlThread. Please tell Atheros about this error message or post it in the forum! Error occurred while trying to execute statement: "%s" Here are the parameters; you might want to censor this data with asterisks (***) as it can contain private information: %s. Here is the actual error message thrown by the sqlThread: %s', str(item), str(repr(parameters)), str(err)) - logger.fatal('This program shall now abruptly exit!') + if str(err) == 'database or disk is full': + logger.fatal('(while cur.execute) Alert: Your disk or data storage volume is full. sqlThread will now exit.') + shared.UISignalQueue.put(('alert', (tr.translateText("MainWindow", "Disk full"), tr.translateText("MainWindow", 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), True))) + if shared.daemon: + os._exit(0) + else: + return + else: + logger.fatal('Major error occurred when trying to execute a SQL statement within the sqlThread. Please tell Atheros about this error message or post it in the forum! Error occurred while trying to execute statement: "%s" Here are the parameters; you might want to censor this data with asterisks (***) as it can contain private information: %s. Here is the actual error message thrown by the sqlThread: %s', str(item), str(repr(parameters)), str(err)) + logger.fatal('This program shall now abruptly exit!') os._exit(0) diff --git a/src/shared.py b/src/shared.py index 949e14d6..e7718959 100644 --- a/src/shared.py +++ b/src/shared.py @@ -67,6 +67,7 @@ numberOfMessagesProcessed = 0 numberOfBroadcastsProcessed = 0 numberOfPubkeysProcessed = 0 numberOfInventoryLookupsPerformed = 0 +daemon = False #If changed, these values will cause particularly unexpected behavior: You won't be able to either send or receive messages because the proof of work you do (or demand) won't match that done or demanded by others. Don't change them! networkDefaultProofOfWorkNonceTrialsPerByte = 320 #The amount of work that should be performed (and demanded) per byte of the payload. Double this number to double the work. -- 2.45.1 From db81f0c11ed9f58cd585ed95f6ffb1b7d2b0635c Mon Sep 17 00:00:00 2001 From: "Grant T. Olson" Date: Thu, 5 Sep 2013 06:31:52 -0400 Subject: [PATCH 4/5] Add add/deleteAddressBook APIs, extract address verification into reuable code, and make some QT stuff re-renderable --- src/bitmessagemain.py | 114 +++++++++++++++-------------------- src/bitmessageqt/__init__.py | 32 +++++++--- 2 files changed, 72 insertions(+), 74 deletions(-) diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index a73f81e1..229b8a16 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -148,6 +148,25 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): except TypeError as e: raise APIError(22, "Decode error - " + str(e)) + def _verifyAddress(self, address): + status, addressVersionNumber, streamNumber, ripe = decodeAddress(address) + if status != 'success': + logger.warn('API Error 0007: Could not decode address %s. Status: %s.', address, status) + + if status == 'checksumfailed': + raise APIError(8, 'Checksum failed for address: ' + address) + if status == 'invalidcharacters': + raise APIError(9, 'Invalid characters in address: ' + address) + if status == 'versiontoohigh': + raise APIError(10, 'Address version number too high (or zero) in address: ' + address) + raise APIError(7, 'Could not decode address: ' + address + ' : ' + status) + if addressVersionNumber < 2 or addressVersionNumber > 3: + raise APIError(11, 'The address version number currently must be 2 or 3. Others aren\'t supported. Check the address.') + if streamNumber != 1: + raise APIError(12, 'The stream number must be 1. Others aren\'t supported. Check the address.') + + return (status, addressVersionNumber, streamNumber, ripe) + def _handle_request(self, method, params): if method == 'helloWorld': (a, b) = params @@ -183,6 +202,33 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): data += json.dumps({'label':label.encode('base64'), 'address': address}, indent=4, separators=(',', ': ')) data += ']}' return data + elif method == 'addAddressBook' or method == 'addAddressbook': + if len(params) != 2: + raise APIError(0, "I need label and address") + label, address = params + label = self._decode(label, "base64") + address = addBMIfNotPresent(address) + self._verifyAddress(address) + queryreturn = sqlQuery("SELECT address FROM addressbook WHERE address=?", address) + if queryreturn != []: + raise APIError(16, 'You already have this address in your address book.') + + sqlExecute("INSERT INTO addressbook VALUES(?,?)", label, address) + shared.UISignalQueue.put(('rerenderInboxFromLabels','')) + shared.UISignalQueue.put(('rerenderSentToLabels','')) + shared.UISignalQueue.put(('rerenderAddressBook','')) + return "Added address %s to address book" % address + elif method == 'deleteAddressBook' or method == 'deleteAddressbook': + if len(params) != 1: + raise APIError(0, "I need an address") + address, = params + address = addBMIfNotPresent(address) + self._verifyAddress(address) + sqlExecute('DELETE FROM addressbook WHERE address=?', address) + shared.UISignalQueue.put(('rerenderInboxFromLabels','')) + shared.UISignalQueue.put(('rerenderSentToLabels','')) + shared.UISignalQueue.put(('rerenderAddressBook','')) + return "Deleted address book entry for %s if it existed" % address elif method == 'createRandomAddress': if len(params) == 0: raise APIError(0, 'I need parameters!') @@ -496,40 +542,10 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): raise APIError(6, 'The encoding type must be 2 because that is the only one this program currently supports.') subject = self._decode(subject, "base64") message = self._decode(message, "base64") - status, addressVersionNumber, streamNumber, toRipe = decodeAddress( - toAddress) - if status != 'success': - logger.warn('API Error 0007: Could not decode address %s. Status: %s.', toAddress, status) - - if status == 'checksumfailed': - raise APIError(8, 'Checksum failed for address: ' + toAddress) - if status == 'invalidcharacters': - raise APIError(9, 'Invalid characters in address: ' + toAddress) - if status == 'versiontoohigh': - raise APIError(10, 'Address version number too high (or zero) in address: ' + toAddress) - raise APIError(7, 'Could not decode address: ' + toAddress + ' : ' + status) - if addressVersionNumber < 2 or addressVersionNumber > 3: - raise APIError(11, 'The address version number currently must be 2 or 3. Others aren\'t supported. Check the toAddress.') - if streamNumber != 1: - raise APIError(12, 'The stream number must be 1. Others aren\'t supported. Check the toAddress.') - status, addressVersionNumber, streamNumber, fromRipe = decodeAddress( - fromAddress) - if status != 'success': - logger.warn('API Error 0007: Could not decode address %s. Status: %s.', fromAddress, status) - - if status == 'checksumfailed': - raise APIError(8, 'Checksum failed for address: ' + fromAddress) - if status == 'invalidcharacters': - raise APIError(9, 'Invalid characters in address: ' + fromAddress) - if status == 'versiontoohigh': - raise APIError(10, 'Address version number too high (or zero) in address: ' + fromAddress) - raise APIError(7, 'Could not decode address: ' + fromAddress + ' : ' + status) - if addressVersionNumber < 2 or addressVersionNumber > 3: - raise APIError(11, 'The address version number currently must be 2 or 3. Others aren\'t supported. Check the fromAddress.') - if streamNumber != 1: - raise APIError(12, 'The stream number must be 1. Others aren\'t supported. Check the fromAddress.') toAddress = addBMIfNotPresent(toAddress) fromAddress = addBMIfNotPresent(fromAddress) + status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(toAddress) + self._verifyAddress(fromAddress) try: fromAddressEnabled = shared.config.getboolean( fromAddress, 'enabled') @@ -570,23 +586,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): subject = self._decode(subject, "base64") message = self._decode(message, "base64") - status, addressVersionNumber, streamNumber, fromRipe = decodeAddress( - fromAddress) - if status != 'success': - logger.warn('API Error 0007: Could not decode address %s. Status: %s.', fromAddress, status) - - if status == 'checksumfailed': - raise APIError(8, 'Checksum failed for address: ' + fromAddress) - if status == 'invalidcharacters': - raise APIError(9, 'Invalid characters in address: ' + fromAddress) - if status == 'versiontoohigh': - raise APIError(10, 'Address version number too high (or zero) in address: ' + fromAddress) - raise APIError(7, 'Could not decode address: ' + fromAddress + ' : ' + status) - if addressVersionNumber < 2 or addressVersionNumber > 3: - raise APIError(11, 'the address version number currently must be 2 or 3. Others aren\'t supported. Check the fromAddress.') - if streamNumber != 1: - raise APIError(12, 'the stream number must be 1. Others aren\'t supported. Check the fromAddress.') fromAddress = addBMIfNotPresent(fromAddress) + self._verifyAddress(fromAddress) try: fromAddressEnabled = shared.config.getboolean( fromAddress, 'enabled') @@ -638,22 +639,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): if len(params) > 2: raise APIError(0, 'I need either 1 or 2 parameters!') address = addBMIfNotPresent(address) - status, addressVersionNumber, streamNumber, toRipe = decodeAddress( - address) - if status != 'success': - logger.warn('API Error 0007: Could not decode address %s. Status: %s.', address, status) - - if status == 'checksumfailed': - raise APIError(8, 'Checksum failed for address: ' + address) - if status == 'invalidcharacters': - raise APIError(9, 'Invalid characters in address: ' + address) - if status == 'versiontoohigh': - raise APIError(10, 'Address version number too high (or zero) in address: ' + address) - raise APIError(7, 'Could not decode address: ' + address + ' : ' + status) - if addressVersionNumber < 2 or addressVersionNumber > 3: - raise APIError(11, 'The address version number currently must be 2 or 3. Others aren\'t supported.') - if streamNumber != 1: - raise APIError(12, 'The stream number must be 1. Others aren\'t supported.') + self._verifyAddress(address) # First we must check to see if the address is already in the # subscriptions list. queryreturn = sqlQuery('''select * from subscriptions where address=?''', address) diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 209c7129..6fd3615c 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -351,16 +351,7 @@ class MyForm(QtGui.QMainWindow): self.loadSent() # Initialize the address book - queryreturn = sqlQuery('SELECT * FROM addressbook') - for row in queryreturn: - label, address = row - self.ui.tableWidgetAddressBook.insertRow(0) - newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8')) - 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.rerenderAddressBook() # Initialize the Subscriptions self.rerenderSubscriptions() @@ -427,6 +418,10 @@ class MyForm(QtGui.QMainWindow): "setStatusIcon(PyQt_PyObject)"), self.setStatusIcon) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( "rerenderInboxFromLabels()"), self.rerenderInboxFromLabels) + QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( + "rerenderSentToLabels()"), self.rerenderSentToLabels) + QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( + "rerenderAddressBook()"), self.rerenderAddressBook) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( "rerenderSubscriptions()"), self.rerenderSubscriptions) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( @@ -1478,6 +1473,19 @@ class MyForm(QtGui.QMainWindow): self.ui.tableWidgetSent.item( i, 0).setText(unicode(toLabel, 'utf-8')) + def rerenderAddressBook(self): + self.ui.tableWidgetAddressBook.setRowCount(0) + queryreturn = sqlQuery('SELECT * FROM addressbook') + for row in queryreturn: + label, address = row + self.ui.tableWidgetAddressBook.insertRow(0) + newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8')) + 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) + def rerenderSubscriptions(self): self.ui.tableWidgetSubscriptions.setRowCount(0) queryreturn = sqlQuery('SELECT label, address, enabled FROM subscriptions') @@ -3185,6 +3193,10 @@ class UISignaler(QThread): self.emit(SIGNAL("setStatusIcon(PyQt_PyObject)"), data) elif command == 'rerenderInboxFromLabels': self.emit(SIGNAL("rerenderInboxFromLabels()")) + elif command == 'rerenderSentToLabels': + self.emit(SIGNAL("rerenderSentToLabels()")) + elif command == 'rerenderAddressBook': + self.emit(SIGNAL("rerenderAddressBook()")) elif command == 'rerenderSubscriptions': self.emit(SIGNAL("rerenderSubscriptions()")) elif command == 'removeInboxRowByMsgid': -- 2.45.1 From bfd79e0ae18bdd88533a53ee35f06ea5cefe09b0 Mon Sep 17 00:00:00 2001 From: "Grant T. Olson" Date: Thu, 5 Sep 2013 06:42:12 -0400 Subject: [PATCH 5/5] Use same argument order as addSubscription for addAddressBook --- src/bitmessagemain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index 229b8a16..dce43f40 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -205,7 +205,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): elif method == 'addAddressBook' or method == 'addAddressbook': if len(params) != 2: raise APIError(0, "I need label and address") - label, address = params + address, label = params label = self._decode(label, "base64") address = addBMIfNotPresent(address) self._verifyAddress(address) -- 2.45.1