From e54133b553933fdd9f5e740637aabb8c8ef662da Mon Sep 17 00:00:00 2001 From: fuzzgun Date: Mon, 6 May 2013 12:16:26 +0100 Subject: [PATCH 01/12] Changelog --- debian/changelog | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/debian/changelog b/debian/changelog index a7d2a84c..65090451 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,58 @@ +pybitmessage (0.3.0-1) unstable; urgency=low + + * Don't use pubkeys table + to send pubkeys to peers now that we maintain them + in the inventory table for 28 days anyway + + * Display privacy warning when Broadcast is selected on Send tab + + * Merge branch 'master' of github.com:Bitmessage/PyBitmessage + + * Add .dat files to .gitignore + + * First bit of code necessary for version 3 addresses + + * Continued working on v3 addresses + + * Implimented broadcast encryption (testing completed) + + * Use sock.shutdown() before sock.close() + + * Test socket.close change + + * Add a simple printLock + + * Added extra statements for troubleshooting + + * set hard date for encrypted-broadcast switchover + + * Truncate display of long messages to avoid freezing the UI + + * Bump version number to 0.3.0 + + * Most daemon code done + + * Continued daemon mode implementation + + * More daemon related changes + + * API-related changes + + * Further deamon-related changes + + * Use different data structure + to maintain the number of connections shown on the Network Status tab + + * Better error handling around sock.sendall + + * Support switching to and from portable mode without restarting + + * Added API Function: getStatus + + * Close application if not daemon and PyQt not found + + -- Bob Mottram (4096 bits) Tue, 6 May 2013 12:06:00 +0100 + pybitmessage (0.2.8-1) unstable; urgency=low * Fixed Ubuntu & OS X issue: From e081e33f56c6649d153abea0ba03e263c6b5f014 Mon Sep 17 00:00:00 2001 From: fuzzgun Date: Mon, 6 May 2013 17:06:52 +0100 Subject: [PATCH 02/12] Added bitmessageqt directory to install scripts --- Makefile | 2 ++ debian/rules | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Makefile b/Makefile index ad8fc52c..891bf8c9 100755 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ install: mkdir -m 755 -p /usr/share/applications/$(APP)/images mkdir -m 755 -p /usr/share/applications/$(APP)/pyelliptic mkdir -m 755 -p /usr/share/applications/$(APP)/socks + mkdir -m 755 -p /usr/share/applications/$(APP)/bitmessageqt mkdir -m 755 -p /usr/share/pixmaps mkdir -m 755 -p /usr/share/icons mkdir -m 755 -p /usr/share/icons/hicolor @@ -30,6 +31,7 @@ install: install -m 644 src/images/*.ico /usr/share/applications/$(APP)/images install -m 644 src/pyelliptic/*.py /usr/share/applications/$(APP)/pyelliptic install -m 644 src/socks/*.py /usr/share/applications/$(APP)/socks + install -m 644 src/bitmessageqt/*.py /usr/share/applications/$(APP)/bitmessageqt install -m 755 debian/pybm /usr/bin install -m 644 desktop/$(APP).desktop /usr/share/applications/$(APP)/$(APP).desktop diff --git a/debian/rules b/debian/rules index ca977463..2d26c6e8 100755 --- a/debian/rules +++ b/debian/rules @@ -26,6 +26,7 @@ install: build clean mkdir -m 755 -p $(DEST_SHARE)/applications/$(APP)/images mkdir -m 755 -p $(DEST_SHARE)/applications/$(APP)/pyelliptic mkdir -m 755 -p $(DEST_SHARE)/applications/$(APP)/socks + mkdir -m 755 -p $(DEST_SHARE)/applications/$(APP)/bitmessageqt mkdir -m 755 -p $(DEST_SHARE)/pixmaps mkdir -m 755 -p $(DEST_SHARE)/icons mkdir -m 755 -p $(DEST_SHARE)/icons/hicolor @@ -42,6 +43,7 @@ install: build clean install -m 644 $(CURDIR)/src/images/*.ico $(DEST_SHARE)/applications/$(APP)/images install -m 644 $(CURDIR)/src/pyelliptic/*.py $(DEST_SHARE)/applications/$(APP)/pyelliptic install -m 644 $(CURDIR)/src/socks/*.py $(DEST_SHARE)/applications/$(APP)/socks + install -m 644 $(CURDIR)/src/bitmessageqt/*.py $(DEST_SHARE)/applications/$(APP)/bitmessageqt install -m 755 $(CURDIR)/debian/pybm $(DEST_MAIN) install -m 644 $(CURDIR)/desktop/$(APP).desktop $(DEST_SHARE)/applications/$(APP)/$(APP).desktop From a82771f7e1f908be93580fc778e39230cb19bffd Mon Sep 17 00:00:00 2001 From: fuzzgun Date: Mon, 6 May 2013 17:15:18 +0100 Subject: [PATCH 03/12] Changelog update --- debian/changelog | 69 ++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/debian/changelog b/debian/changelog index 65090451..8e8ed8c0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,55 +1,60 @@ pybitmessage (0.3.0-1) unstable; urgency=low - * Don't use pubkeys table - to send pubkeys to peers now that we maintain them - in the inventory table for 28 days anyway + * Added new API function: getStatus - * Display privacy warning when Broadcast is selected on Send tab + * Added error-handling around all sock.sendall() functions + in the receiveData thread so that if there is a problem + sending data, the threads will close gracefully - * Merge branch 'master' of github.com:Bitmessage/PyBitmessage + * Abandoned and removed the connectionsCount data structure; + use the connectedHostsList instead because it has proved to be + more accurate than trying to maintain the connectionsCount - * Add .dat files to .gitignore + * Added daemon mode. All UI code moved into a module and many + shared objects moved into shared.py - * First bit of code necessary for version 3 addresses + * Truncate display of very long messages to avoid freezing the UI - * Continued working on v3 addresses + * Added encrypted broadcasts for v3 addresses or v2 addresses + after 2013-05-28 10:00 UTC - * Implimented broadcast encryption (testing completed) + * No longer self.sock.close() from within receiveDataThreads, + let the sendDataThreads do it - * Use sock.shutdown() before sock.close() + * Swapped out the v2 announcements subscription address for a v3 + announcements subscription address - * Test socket.close change + * Vacuum the messages.dat file once a month: will greatly reduce the file size - * Add a simple printLock + * Added a settings table in message.dat - * Added extra statements for troubleshooting + * Implemented v3 addresses: + pubkey messages must now include two var_ints: nonce_trials_per_byte + and extra_bytes, and also be signed. When sending a message to a v3 + address, the sender must use these values in calculating its POW or + else the message will not be accepted by the receiver. - * set hard date for encrypted-broadcast switchover + * Display a privacy warning when selecting 'Send Broadcast from this address' - * Truncate display of long messages to avoid freezing the UI + * Added gitignore file - * Bump version number to 0.3.0 + * Added code in preparation for a switch from 32-bit time to 64-bit time. + Nodes will now advertise themselves as using protocol version 2. - * Most daemon code done + * Don't necessarily delete entries from the inventory after 2.5 days; + leave pubkeys there for 28 days so that we don't process the same ones + many times throughout a month. This was causing the 'pubkeys processed' + indicator on the 'Network Status' tab to not accurately reflect the + number of truly new addresses on the network. - * Continued daemon mode implementation + * Use 32 threads for outgoing connections in order to connect quickly - * More daemon related changes + * Fix typo when calling os.environ in the sys.platform=='darwin' case - * API-related changes + * Allow the cancelling of a message which is in the process of being + sent by trashing it then restarting Bitmessage - * Further deamon-related changes - - * Use different data structure - to maintain the number of connections shown on the Network Status tab - - * Better error handling around sock.sendall - - * Support switching to and from portable mode without restarting - - * Added API Function: getStatus - - * Close application if not daemon and PyQt not found + * Bug fix: can't delete address from address book -- Bob Mottram (4096 bits) Tue, 6 May 2013 12:06:00 +0100 From db114ea30b19228d8f8308566f0105c80f120fe8 Mon Sep 17 00:00:00 2001 From: fuzzgun Date: Mon, 6 May 2013 17:45:23 +0100 Subject: [PATCH 04/12] Added minimum version numbers to Debian control file --- debian/control | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/control b/debian/control index 975082c3..92a4eb15 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: pybitmessage Section: contrib/comm Priority: extra Maintainer: Jonathan Warren -Build-Depends: debhelper (>= 8.0.0), python, openssl, python-qt4, libqt4-dev, python-qt4-dev, sqlite3, libsqlite3-dev +Build-Depends: debhelper (>= 8.0.0), python (>= 2.7.0), openssl, python-qt4, libqt4-dev (>= 4.8.0), python-qt4-dev, sqlite3, libsqlite3-dev Standards-Version: 3.9.2 Homepage: https://bitmessage.org/ Vcs-Browser: https://github.com/Bitmessage/PyBitmessage @@ -10,7 +10,7 @@ Vcs-Git: https://github.com/Bitmessage/PyBitmessage.git Package: pybitmessage Architecture: all -Depends: ${misc:Depends}, python, openssl, python-qt4, libqt4-dev, python-qt4-dev, sqlite3, libsqlite3-dev +Depends: ${misc:Depends}, python (>= 2.7.0), openssl, python-qt4, libqt4-dev (>= 4.8.0), python-qt4-dev, sqlite3, libsqlite3-dev Description: Send encrypted messages to another person or to many subscribers Bitmessage is a P2P communications protocol used to send encrypted messages to another person or to many subscribers. It is decentralized and trustless, From 59211053dc8a3f2241e168be19520efac83ed159 Mon Sep 17 00:00:00 2001 From: fuzzgun Date: Tue, 7 May 2013 10:02:28 +0100 Subject: [PATCH 05/12] Changed Debian install directory and run script name based upon issue #135 --- Makefile | 55 +++++++++++++++++++----------------- debian/pybm | 2 +- debian/rules | 32 +++++++++++---------- desktop/pybitmessage.desktop | 2 +- 4 files changed, 48 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index 891bf8c9..91c682c9 100755 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ APP=pybitmessage VERSION=0.3.0 +DEST_SHARE=/usr/share +DEST_APP=$(DEST_SHARE)/$(APP) all: @@ -9,35 +11,36 @@ source: tar -cvzf ../$(APP)_$(VERSION).orig.tar.gz ../$(APP)-$(VERSION) --exclude=.git install: - mkdir -m 755 -p /usr/share/applications - mkdir -m 755 -p /usr/share/applications/$(APP) - mkdir -m 755 -p /usr/share/applications/$(APP)/images - mkdir -m 755 -p /usr/share/applications/$(APP)/pyelliptic - mkdir -m 755 -p /usr/share/applications/$(APP)/socks - mkdir -m 755 -p /usr/share/applications/$(APP)/bitmessageqt - mkdir -m 755 -p /usr/share/pixmaps - mkdir -m 755 -p /usr/share/icons - mkdir -m 755 -p /usr/share/icons/hicolor - mkdir -m 755 -p /usr/share/icons/hicolor/scalable - mkdir -m 755 -p /usr/share/icons/hicolor/scalable/apps - mkdir -m 755 -p /usr/share/icons/hicolor/24x24 - mkdir -m 755 -p /usr/share/icons/hicolor/24x24/apps + mkdir -m 755 -p $(DEST_APP) + mkdir -m 755 -p $(DEST_SHARE)/applications + mkdir -m 755 -p $(DEST_SHARE)/applications/$(APP) + mkdir -m 755 -p $(DEST_APP)/images + mkdir -m 755 -p $(DEST_APP)/pyelliptic + mkdir -m 755 -p $(DEST_APP)/socks + mkdir -m 755 -p $(DEST_APP)/bitmessageqt + mkdir -m 755 -p $(DEST_SHARE)/pixmaps + mkdir -m 755 -p $(DEST_SHARE)/icons + mkdir -m 755 -p $(DEST_SHARE)/icons/hicolor + mkdir -m 755 -p $(DEST_SHARE)/icons/hicolor/scalable + mkdir -m 755 -p $(DEST_SHARE)/icons/hicolor/scalable/apps + mkdir -m 755 -p $(DEST_SHARE)/icons/hicolor/24x24 + mkdir -m 755 -p $(DEST_SHARE)/icons/hicolor/24x24/apps - install -m 644 src/*.ui /usr/share/applications/$(APP) - install -m 644 src/*.py /usr/share/applications/$(APP) - install -m 644 src/*.qrc /usr/share/applications/$(APP) + install -m 644 src/*.ui $(DEST_APP) + install -m 644 src/*.py $(DEST_APP) + install -m 644 src/*.qrc $(DEST_APP) - install -m 644 src/images/*.png /usr/share/applications/$(APP)/images - install -m 644 src/images/*.ico /usr/share/applications/$(APP)/images - install -m 644 src/pyelliptic/*.py /usr/share/applications/$(APP)/pyelliptic - install -m 644 src/socks/*.py /usr/share/applications/$(APP)/socks - install -m 644 src/bitmessageqt/*.py /usr/share/applications/$(APP)/bitmessageqt - install -m 755 debian/pybm /usr/bin + install -m 644 src/images/*.png $(DEST_APP)/images + install -m 644 src/images/*.ico $(DEST_APP)/images + install -m 644 src/pyelliptic/*.py $(DEST_APP)/pyelliptic + install -m 644 src/socks/*.py $(DEST_APP)/socks + install -m 644 src/bitmessageqt/*.py $(DEST_APP)/bitmessageqt + install -m 755 debian/pybm /usr/bin/pybitmessage - install -m 644 desktop/$(APP).desktop /usr/share/applications/$(APP)/$(APP).desktop - install -m 644 src/images/can-icon-24px.png /usr/share/icons/hicolor/24x24/apps/$(APP).png - install -m 644 desktop/can-icon.svg /usr/share/icons/hicolor/scalable/apps/$(APP).svg - install -m 644 desktop/can-icon.svg /usr/share/pixmaps/$(APP).svg + install -m 644 desktop/$(APP).desktop $(DEST_SHARE)/applications/$(APP)/$(APP).desktop + install -m 644 src/images/can-icon-24px.png $(DEST_SHARE)/icons/hicolor/24x24/apps/$(APP).png + install -m 644 desktop/can-icon.svg $(DEST_SHARE)/icons/hicolor/scalable/apps/$(APP).svg + install -m 644 desktop/can-icon.svg $(DEST_SHARE)/pixmaps/$(APP).svg clean: rm -rf debian/$(APP) diff --git a/debian/pybm b/debian/pybm index 1d90ee60..d806eedd 100644 --- a/debian/pybm +++ b/debian/pybm @@ -1,4 +1,4 @@ #!/bin/bash -cd /usr/share/applications/pybitmessage +cd /usr/share/pybitmessage python bitmessagemain.py diff --git a/debian/rules b/debian/rules index 2d26c6e8..a5e5f162 100755 --- a/debian/rules +++ b/debian/rules @@ -1,8 +1,9 @@ #!/usr/bin/make -f APP=pybitmessage -DEST_MAIN = $(CURDIR)/debian/$(APP)/usr/bin -DEST_SHARE = $(CURDIR)/debian/$(APP)/usr/share +DEST_MAIN=$(CURDIR)/debian/$(APP)/usr/bin +DEST_SHARE=$(CURDIR)/debian/$(APP)/usr/share +DEST_APP=$(DEST_SHARE)/$(APP) build: build-stamp make @@ -21,12 +22,13 @@ install: build clean dh_installdirs mkdir -m 755 -p $(CURDIR)/debian/$(APP)/usr mkdir -m 755 -p $(CURDIR)/debian/$(APP)/usr/bin + mkdir -m 755 -p $(DEST_APP) mkdir -m 755 -p $(DEST_SHARE)/applications mkdir -m 755 -p $(DEST_SHARE)/applications/$(APP) - mkdir -m 755 -p $(DEST_SHARE)/applications/$(APP)/images - mkdir -m 755 -p $(DEST_SHARE)/applications/$(APP)/pyelliptic - mkdir -m 755 -p $(DEST_SHARE)/applications/$(APP)/socks - mkdir -m 755 -p $(DEST_SHARE)/applications/$(APP)/bitmessageqt + mkdir -m 755 -p $(DEST_APP)/images + mkdir -m 755 -p $(DEST_APP)/pyelliptic + mkdir -m 755 -p $(DEST_APP)/socks + mkdir -m 755 -p $(DEST_APP)/bitmessageqt mkdir -m 755 -p $(DEST_SHARE)/pixmaps mkdir -m 755 -p $(DEST_SHARE)/icons mkdir -m 755 -p $(DEST_SHARE)/icons/hicolor @@ -35,16 +37,16 @@ install: build clean mkdir -m 755 -p $(DEST_SHARE)/icons/hicolor/24x24 mkdir -m 755 -p $(DEST_SHARE)/icons/hicolor/24x24/apps - install -m 644 $(CURDIR)/src/*.ui $(DEST_SHARE)/applications/$(APP) - install -m 644 $(CURDIR)/src/*.py $(DEST_SHARE)/applications/$(APP) - install -m 644 $(CURDIR)/src/*.qrc $(DEST_SHARE)/applications/$(APP) + install -m 644 $(CURDIR)/src/*.ui $(DEST_APP) + install -m 644 $(CURDIR)/src/*.py $(DEST_APP) + install -m 644 $(CURDIR)/src/*.qrc $(DEST_APP) - install -m 644 $(CURDIR)/src/images/*.png $(DEST_SHARE)/applications/$(APP)/images - install -m 644 $(CURDIR)/src/images/*.ico $(DEST_SHARE)/applications/$(APP)/images - install -m 644 $(CURDIR)/src/pyelliptic/*.py $(DEST_SHARE)/applications/$(APP)/pyelliptic - install -m 644 $(CURDIR)/src/socks/*.py $(DEST_SHARE)/applications/$(APP)/socks - install -m 644 $(CURDIR)/src/bitmessageqt/*.py $(DEST_SHARE)/applications/$(APP)/bitmessageqt - install -m 755 $(CURDIR)/debian/pybm $(DEST_MAIN) + install -m 644 $(CURDIR)/src/images/*.png $(DEST_APP)/images + install -m 644 $(CURDIR)/src/images/*.ico $(DEST_APP)/images + install -m 644 $(CURDIR)/src/pyelliptic/*.py $(DEST_APP)/pyelliptic + install -m 644 $(CURDIR)/src/socks/*.py $(DEST_APP)/socks + install -m 644 $(CURDIR)/src/bitmessageqt/*.py $(DEST_APP)/bitmessageqt + install -m 755 $(CURDIR)/debian/pybm $(DEST_MAIN)/pybitmessage install -m 644 $(CURDIR)/desktop/$(APP).desktop $(DEST_SHARE)/applications/$(APP)/$(APP).desktop install -m 644 $(CURDIR)/src/images/can-icon-24px.png $(DEST_SHARE)/icons/hicolor/24x24/apps/$(APP).png diff --git a/desktop/pybitmessage.desktop b/desktop/pybitmessage.desktop index affd63d1..83da32cd 100644 --- a/desktop/pybitmessage.desktop +++ b/desktop/pybitmessage.desktop @@ -3,7 +3,7 @@ Type=Application Name=PyBitmessage GenericName=PyBitmessage Comment=Send encrypted messages to another person or to many subscribers -Exec=pybm %U +Exec=pybitmessage %U Icon=pybitmessage Terminal=false Categories=Network From 3ab48c2fe36d1eeb71f6e39682f5482dff0fc679 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Tue, 7 May 2013 16:25:01 -0400 Subject: [PATCH 06/12] Upon incoming connection, start the sendData thread before the receiveData thread --- src/bitmessagemain.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index f781b774..47631cfc 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -210,20 +210,20 @@ class singleListener(threading.Thread): print 'incoming connection is from a host in shared.connectedHostsList (we are already connected to it). Ignoring it.' a.close() a,(HOST,PORT) = sock.accept()""" - rd = receiveDataThread() - rd.daemon = True # close the main program even if there are threads left - #self.emit(SIGNAL("passObjectThrough(PyQt_PyObject)"),rd) objectsOfWhichThisRemoteNodeIsAlreadyAware = {} - rd.setup(a,HOST,PORT,-1,objectsOfWhichThisRemoteNodeIsAlreadyAware) - shared.printLock.acquire() - print self, 'connected to', HOST,'during INCOMING request.' - shared.printLock.release() - rd.start() sd = sendDataThread() sd.setup(a,HOST,PORT,-1,objectsOfWhichThisRemoteNodeIsAlreadyAware) sd.start() + rd = receiveDataThread() + rd.daemon = True # close the main program even if there are threads left + rd.setup(a,HOST,PORT,-1,objectsOfWhichThisRemoteNodeIsAlreadyAware) + rd.start() + + shared.printLock.acquire() + print self, 'connected to', HOST,'during INCOMING request.' + shared.printLock.release() #This thread is created either by the synSenderThread(for outgoing connections) or the singleListenerThread(for incoming connectiosn). class receiveDataThread(threading.Thread): From 38ae186a931e505514a62c938e1aeaed98b1ccc7 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Tue, 7 May 2013 16:31:18 -0400 Subject: [PATCH 07/12] added several printLocks to improve console output --- src/bitmessagemain.py | 3 ++- src/bitmessageqt/__init__.py | 2 ++ src/shared.py | 6 +++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index 47631cfc..c11f7013 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -297,7 +297,9 @@ class receiveDataThread(threading.Thread): try: del shared.connectedHostsList[self.HOST] except Exception, err: + shared.printLock.acquire() print 'Could not delete', self.HOST, 'from shared.connectedHostsList.', err + shared.printLock.release() shared.UISignalQueue.put(('updateNetworkStatusTab','no data')) shared.printLock.acquire() print 'The size of the connectedHostsList is now:', len(shared.connectedHostsList) @@ -2046,7 +2048,6 @@ class sendDataThread(threading.Thread): shared.printLock.release() self.versionSent = 1 - def run(self): while True: deststream,command,data = self.mailbox.get() diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 52dba18a..3c013ace 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -1315,7 +1315,9 @@ class MyForm(QtGui.QMainWindow): self.trayIcon.hide() self.statusBar().showMessage('All done. Closing user interface...') event.accept() + shared.printLock.acquire() print 'Done. (passed event.accept())' + shared.printLock.release() os._exit(0) def on_action_InboxMessageForceHtml(self): diff --git a/src/shared.py b/src/shared.py index 0eb7fa18..ed1baf22 100644 --- a/src/shared.py +++ b/src/shared.py @@ -149,7 +149,9 @@ def doCleanShutdown(): print 'Completed pickle.dump. Closing output...' output.close() knownNodesLock.release() + printLock.acquire() print 'Finished closing knownnodes.dat output file.' + printLock.release() UISignalQueue.put(('updateStatusBar','Done saving the knownNodes list of peers to disk.')) broadcastToSendDataQueues((0, 'shutdown', 'all')) @@ -165,8 +167,10 @@ def doCleanShutdown(): sqlSubmitQueue.put('SELECT address FROM subscriptions') sqlSubmitQueue.put('') sqlReturnQueue.get() - sqlLock.release() + sqlLock.release() + printLock.acquire() print 'Finished flushing inventory.' + printLock.release() sqlSubmitQueue.put('exit') if safeConfigGetBoolean('bitmessagesettings','daemon'): From 71448fe84a38ae659d07013d69ef3b81d55e7efb Mon Sep 17 00:00:00 2001 From: fuzzgun Date: Tue, 7 May 2013 22:22:34 +0100 Subject: [PATCH 08/12] Beginning of application indicator as per issue #135 --- src/bitmessageqt/__init__.py | 85 +++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 52dba18a..a9ed482d 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -460,6 +460,79 @@ class MyForm(QtGui.QMainWindow): #QtCore.QObject.connect(self.workerThread, QtCore.SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByAckdata) #QtCore.QObject.connect(self.workerThread, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar) + # an appindicator action which indicates the connection status + actionStatus = None + + # an appindicator action which shows of hides the program window + actionShow = None + + # show the application window + def appIndicatorShow(self): + if self.actionShow == None: + return + self.actionShow.setChecked(True) + self.show() + self.setWindowState(self.windowState() & QtCore.Qt.WindowMaximized) + + # application indicator show or hide + def appIndicatorShowBitmessage(self): + if self.actionShow == None: + return + if not self.actionShow.isChecked(): + self.hide() + self.setWindowState(self.windowState() & QtCore.Qt.WindowMinimized) + else: + self.show() + self.setWindowState(self.windowState() & QtCore.Qt.WindowMaximized) + + # TODO + def appIndicatorSend(self): + print 'Send' + self.appIndicatorShow() + + # TODO + def appIndicatorSubscribe(self): + print 'Subscribe' + self.appIndicatorShow() + + # TODO + def appIndicatorAddressBook(self): + print 'Address Book' + self.appIndicatorShow() + + # create application indicator + def createAppIndicator(self,app): + app.tray = QSystemTrayIcon(QtGui.QIcon("images/can-icon-24px.png"), app) + m = QMenu() + + self.actionStatus = QtGui.QAction('Not Connected',m,checkable=False) + m.addAction(self.actionStatus) + + # show bitmessage + self.actionShow = QtGui.QAction('Show Bitmessage',m,checkable=True) + self.actionShow.setChecked(True) + self.actionShow.triggered.connect(self.appIndicatorShowBitmessage) + m.addAction(self.actionShow) + + # Send + actionSend = QtGui.QAction('Send',m,checkable=False) + actionSend.triggered.connect(self.appIndicatorSend) + m.addAction(actionSend) + + # Subscribe + actionSubscribe = QtGui.QAction('Subscribe',m,checkable=False) + actionSubscribe.triggered.connect(self.appIndicatorSubscribe) + m.addAction(actionSubscribe) + + # Address book + actionAddressBook = QtGui.QAction('Address Book',m,checkable=False) + actionAddressBook.triggered.connect(self.appIndicatorAddressBook) + m.addAction(actionAddressBook) + + m.addAction("Quit", self.close) + app.tray.setContextMenu(m) + app.tray.show() + def tableWidgetInboxKeyPressEvent(self,event): if event.key() == QtCore.Qt.Key_Delete: self.on_action_InboxTrash() @@ -601,16 +674,22 @@ class MyForm(QtGui.QMainWindow): if color == 'red': self.ui.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/redicon.png")) shared.statusIconColor = 'red' + if self.actionStatus != None: + self.actionStatus.setText('Not Connected') if color == 'yellow': if self.statusBar().currentMessage() == 'Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won\'t send until you connect.': self.statusBar().showMessage('') self.ui.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/yellowicon.png")) shared.statusIconColor = 'yellow' + if self.actionStatus != None: + self.actionStatus.setText('Connection Ok') if color == 'green': if self.statusBar().currentMessage() == 'Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won\'t send until you connect.': self.statusBar().showMessage('') self.ui.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/greenicon.png")) shared.statusIconColor = 'green' + if self.actionStatus != None: + self.actionStatus.setText('Connection Good') def updateSentItemStatusByHash(self,toRipe,textToDisplay): for i in range(self.ui.tableWidgetSent.rowCount()): @@ -1944,6 +2023,8 @@ class UISignaler(QThread): else: sys.stderr.write('Command sent to UISignaler not recognized: %s\n' % command) + + def run(): app = QtGui.QApplication(sys.argv) app.setStyleSheet("QStatusBar::item { border: 0px solid black }") @@ -1957,4 +2038,6 @@ def run(): #self.hide() if 'win32' in sys.platform or 'win64' in sys.platform: myapp.setWindowFlags(Qt.ToolTip) - sys.exit(app.exec_()) \ No newline at end of file + myapp.createAppIndicator(app) + + sys.exit(app.exec_()) From ff5c7760d00eebffc75b3e3f811837ec2afdf4f0 Mon Sep 17 00:00:00 2001 From: fuzzgun Date: Tue, 7 May 2013 22:52:17 +0100 Subject: [PATCH 09/12] Application indicator selects tabs --- src/bitmessageqt/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index a9ed482d..9d205fb1 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -485,20 +485,20 @@ class MyForm(QtGui.QMainWindow): self.show() self.setWindowState(self.windowState() & QtCore.Qt.WindowMaximized) - # TODO + # Show the program window and select send tab def appIndicatorSend(self): - print 'Send' self.appIndicatorShow() + self.ui.tabWidget.setCurrentIndex(1) - # TODO + # Show the program window and select subscriptions tab def appIndicatorSubscribe(self): - print 'Subscribe' self.appIndicatorShow() + self.ui.tabWidget.setCurrentIndex(4) - # TODO + # Show the program window and select the address book tab def appIndicatorAddressBook(self): - print 'Address Book' self.appIndicatorShow() + self.ui.tabWidget.setCurrentIndex(5) # create application indicator def createAppIndicator(self,app): From 37aafec3322fc29af72054ad9e1cac346ce7e3b9 Mon Sep 17 00:00:00 2001 From: fuzzgun Date: Tue, 7 May 2013 22:58:47 +0100 Subject: [PATCH 10/12] Application indicator separators --- src/bitmessageqt/__init__.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 9d205fb1..352f9091 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -508,6 +508,11 @@ class MyForm(QtGui.QMainWindow): self.actionStatus = QtGui.QAction('Not Connected',m,checkable=False) m.addAction(self.actionStatus) + # separator + actionSeparator = QtGui.QAction('',m,checkable=False) + actionSeparator.setSeparator(True) + m.addAction(actionSeparator) + # show bitmessage self.actionShow = QtGui.QAction('Show Bitmessage',m,checkable=True) self.actionShow.setChecked(True) @@ -529,6 +534,12 @@ class MyForm(QtGui.QMainWindow): actionAddressBook.triggered.connect(self.appIndicatorAddressBook) m.addAction(actionAddressBook) + # separator + actionSeparator = QtGui.QAction('',m,checkable=False) + actionSeparator.setSeparator(True) + m.addAction(actionSeparator) + + # Quit m.addAction("Quit", self.close) app.tray.setContextMenu(m) app.tray.show() From 70f09095d905379dc6b8fd1032ddd3f27f8e2fe6 Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Wed, 8 May 2013 13:59:30 -0400 Subject: [PATCH 11/12] Support setting user-defined difficulty through the API --- src/api client.py | 6 ++-- src/bitmessagemain.py | 75 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/api client.py b/src/api client.py index 474cd065..b823a75a 100644 --- a/src/api client.py +++ b/src/api client.py @@ -25,12 +25,12 @@ print jsonAddresses print 'Now that we have our address data in a nice Python data structure, let\'s look at the first address (index 0) and print its label:' print jsonAddresses['addresses'][0]['label'] -print 'Uncomment the next two lines to create a new random address.' +print 'Uncomment the next two lines to create a new random address with slightly a slightly higher difficulty setting than normal.' #addressLabel = 'new address label'.encode('base64') -#print api.createRandomAddress(addressLabel) +#print api.createRandomAddress(addressLabel,False,1.05,1.1111) print 'Uncomment these next four lines to create new deterministic addresses.' -#passphrase = 'asdfasdfqwer'.encode('base64') +#passphrase = 'asdfasdfqwser'.encode('base64') #jsonDeterministicAddresses = api.createDeterministicAddresses(passphrase, 2, 3, 1, False) #print jsonDeterministicAddresses #print json.loads(jsonDeterministicAddresses) diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index c11f7013..d28c5bf1 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -3202,13 +3202,27 @@ class addressGenerator(threading.Thread): def run(self): while True: - addressVersionNumber,streamNumber,label,numberOfAddressesToMake,deterministicPassphrase,eighteenByteRipe = shared.addressGeneratorQueue.get() + queueValue = shared.addressGeneratorQueue.get() + nonceTrialsPerByte = 0 + payloadLengthExtraBytes = 0 + if len(queueValue) == 6: + addressVersionNumber,streamNumber,label,numberOfAddressesToMake,deterministicPassphrase,eighteenByteRipe = queueValue + elif len(queueValue) == 8: + addressVersionNumber,streamNumber,label,numberOfAddressesToMake,deterministicPassphrase,eighteenByteRipe,nonceTrialsPerByte,payloadLengthExtraBytes = queueValue + else: + sys.stderr.write('Programming error: A structure with the wrong number of values was passed into the addressGeneratorQueue. Here is the queueValue: %s\n' % queueValue) if addressVersionNumber < 3 or addressVersionNumber > 3: - sys.stderr.write('Program error: For some reason the address generator queue has been given a request to create version', addressVersionNumber,' addresses which it cannot do.\n') - if addressVersionNumber == 3: + sys.stderr.write('Program error: For some reason the address generator queue has been given a request to create at least one version %s address which it cannot do.\n' % addressVersionNumber) + if nonceTrialsPerByte == 0: + nonceTrialsPerByte = shared.config.getint('bitmessagesettings','defaultnoncetrialsperbyte') + if nonceTrialsPerByte < shared.networkDefaultProofOfWorkNonceTrialsPerByte: + nonceTrialsPerByte = shared.networkDefaultProofOfWorkNonceTrialsPerByte + if payloadLengthExtraBytes == 0: + payloadLengthExtraBytes = shared.config.getint('bitmessagesettings','defaultpayloadlengthextrabytes') + if payloadLengthExtraBytes < shared.networkDefaultPayloadLengthExtraBytes: + payloadLengthExtraBytes = shared.networkDefaultPayloadLengthExtraBytes + if addressVersionNumber == 3: #currently the only one supported. if deterministicPassphrase == "": - #statusbar = 'Generating one new address' - #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar) shared.UISignalQueue.put(('updateStatusBar','Generating one new address')) #This next section is a little bit strange. We're going to generate keys over and over until we #find one that starts with either \x00 or \x00\x00. Then when we pack them into a Bitmessage address, @@ -3237,7 +3251,6 @@ class addressGenerator(threading.Thread): print 'Generated address with ripe digest:', ripe.digest().encode('hex') print 'Address generator calculated', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix, 'addresses at', numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix/(time.time()-startTime),'addresses per second before finding one with the correct ripe-prefix.' address = encodeAddress(3,streamNumber,ripe.digest()) - #self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Finished generating address. Writing to keys.dat') #An excellent way for us to store our keys is in Wallet Import Format. Let us convert now. #https://en.bitcoin.it/wiki/Wallet_import_format @@ -3255,8 +3268,8 @@ class addressGenerator(threading.Thread): shared.config.set(address,'label',label) shared.config.set(address,'enabled','true') shared.config.set(address,'decoy','false') - shared.config.set(address,'noncetrialsperbyte',shared.config.get('bitmessagesettings','defaultnoncetrialsperbyte')) - shared.config.set(address,'payloadlengthextrabytes',shared.config.get('bitmessagesettings','defaultpayloadlengthextrabytes')) + shared.config.set(address,'noncetrialsperbyte',str(nonceTrialsPerByte)) + shared.config.set(address,'payloadlengthextrabytes',str(payloadLengthExtraBytes)) shared.config.set(address,'privSigningKey',privSigningKeyWIF) shared.config.set(address,'privEncryptionKey',privEncryptionKeyWIF) with open(shared.appdata + 'keys.dat', 'wb') as configfile: @@ -3329,8 +3342,8 @@ class addressGenerator(threading.Thread): shared.config.set(address,'label',label) shared.config.set(address,'enabled','true') shared.config.set(address,'decoy','false') - shared.config.set(address,'noncetrialsperbyte',shared.config.get('bitmessagesettings','defaultnoncetrialsperbyte')) - shared.config.set(address,'payloadlengthextrabytes',shared.config.get('bitmessagesettings','defaultpayloadlengthextrabytes')) + shared.config.set(address,'noncetrialsperbyte',str(nonceTrialsPerByte)) + shared.config.set(address,'payloadlengthextrabytes',str(payloadLengthExtraBytes)) shared.config.set(address,'privSigningKey',privSigningKeyWIF) shared.config.set(address,'privEncryptionKey',privEncryptionKeyWIF) with open(shared.appdata + 'keys.dat', 'wb') as configfile: @@ -3445,7 +3458,6 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): return a+b elif method == 'statusBar': message, = params - #apiSignalQueue.put(('updateStatusBar',message)) shared.UISignalQueue.put(('updateStatusBar',message)) elif method == 'listAddresses': data = '{"addresses":[' @@ -3465,13 +3477,26 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): elif len(params) == 1: label, = params eighteenByteRipe = False + nonceTrialsPerByte = shared.config.get('bitmessagesettings','defaultnoncetrialsperbyte') + payloadLengthExtraBytes = shared.config.get('bitmessagesettings','defaultpayloadlengthextrabytes') elif len(params) == 2: label, eighteenByteRipe = params + nonceTrialsPerByte = shared.config.get('bitmessagesettings','defaultnoncetrialsperbyte') + payloadLengthExtraBytes = shared.config.get('bitmessagesettings','defaultpayloadlengthextrabytes') + elif len(params) == 3: + label, eighteenByteRipe, totalDifficulty = params + nonceTrialsPerByte = int(shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty) + payloadLengthExtraBytes = shared.config.get('bitmessagesettings','defaultpayloadlengthextrabytes') + elif len(params) == 4: + label, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = params + nonceTrialsPerByte = int(shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty) + payloadLengthExtraBytes = int(shared.networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty) + else: + return 'API Error 0000: Too many parameters!' label = label.decode('base64') apiAddressGeneratorReturnQueue.queue.clear() streamNumberForAddress = 1 - #apiSignalQueue.put(('createRandomAddress',(label, eighteenByteRipe))) #params should be a twopul which equals (eighteenByteRipe, label) - shared.addressGeneratorQueue.put((3,streamNumberForAddress,label,1,"",eighteenByteRipe)) + shared.addressGeneratorQueue.put((3,streamNumberForAddress,label,1,"",eighteenByteRipe,nonceTrialsPerByte,payloadLengthExtraBytes)) return apiAddressGeneratorReturnQueue.get() elif method == 'createDeterministicAddresses': if len(params) == 0: @@ -3482,20 +3507,40 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): addressVersionNumber = 0 streamNumber = 0 eighteenByteRipe = False + nonceTrialsPerByte = shared.config.get('bitmessagesettings','defaultnoncetrialsperbyte') + payloadLengthExtraBytes = shared.config.get('bitmessagesettings','defaultpayloadlengthextrabytes') elif len(params) == 2: passphrase, numberOfAddresses = params addressVersionNumber = 0 streamNumber = 0 eighteenByteRipe = False + nonceTrialsPerByte = shared.config.get('bitmessagesettings','defaultnoncetrialsperbyte') + payloadLengthExtraBytes = shared.config.get('bitmessagesettings','defaultpayloadlengthextrabytes') elif len(params) == 3: passphrase, numberOfAddresses, addressVersionNumber = params streamNumber = 0 eighteenByteRipe = False + nonceTrialsPerByte = shared.config.get('bitmessagesettings','defaultnoncetrialsperbyte') + payloadLengthExtraBytes = shared.config.get('bitmessagesettings','defaultpayloadlengthextrabytes') elif len(params) == 4: passphrase, numberOfAddresses, addressVersionNumber, streamNumber = params eighteenByteRipe = False + nonceTrialsPerByte = shared.config.get('bitmessagesettings','defaultnoncetrialsperbyte') + payloadLengthExtraBytes = shared.config.get('bitmessagesettings','defaultpayloadlengthextrabytes') elif len(params) == 5: passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe = params + nonceTrialsPerByte = shared.config.get('bitmessagesettings','defaultnoncetrialsperbyte') + payloadLengthExtraBytes = shared.config.get('bitmessagesettings','defaultpayloadlengthextrabytes') + elif len(params) == 6: + passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty = params + nonceTrialsPerByte = int(shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty) + payloadLengthExtraBytes = shared.config.get('bitmessagesettings','defaultpayloadlengthextrabytes') + elif len(params) == 7: + passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = params + nonceTrialsPerByte = int(shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty) + payloadLengthExtraBytes = int(shared.networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty) + else: + return 'API Error 0000: Too many parameters!' if len(passphrase) == 0: return 'API Error 0001: The specified passphrase is blank.' passphrase = passphrase.decode('base64') @@ -3513,8 +3558,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): return 'API Error 0005: You have (accidentally?) specified too many addresses to make. Maximum 999. This check only exists to prevent mischief; if you really want to create more addresses than this, contact the Bitmessage developers and we can modify the check or you can do it yourself by searching the source code for this message.' apiAddressGeneratorReturnQueue.queue.clear() print 'Requesting that the addressGenerator create', numberOfAddresses, 'addresses.' - #apiSignalQueue.put(('createDeterministicAddresses',(passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe))) - shared.addressGeneratorQueue.put((addressVersionNumber,streamNumber,'unused API address',numberOfAddresses,passphrase,eighteenByteRipe)) + shared.addressGeneratorQueue.put((addressVersionNumber,streamNumber,'unused API address',numberOfAddresses,passphrase,eighteenByteRipe,nonceTrialsPerByte,payloadLengthExtraBytes)) data = '{"addresses":[' queueReturn = apiAddressGeneratorReturnQueue.get() for item in queueReturn: @@ -3548,7 +3592,6 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): shared.sqlReturnQueue.get() shared.sqlSubmitQueue.put('commit') shared.sqlLock.release() - #apiSignalQueue.put(('updateStatusBar','Per API: Trashed message (assuming message existed). UI not updated.')) shared.UISignalQueue.put(('updateStatusBar','Per API: Trashed message (assuming message existed). UI not updated.')) return 'Trashed message (assuming message existed). UI not updated. To double check, run getAllInboxMessages to see that the message disappeared, or restart Bitmessage and look in the normal Bitmessage GUI.' elif method == 'sendMessage': From 1b810667fddd5f0a58c1ea371cf91fe16e6fce1b Mon Sep 17 00:00:00 2001 From: Jonathan Warren Date: Wed, 8 May 2013 16:42:28 -0400 Subject: [PATCH 12/12] Got appIndicator working on Windows. Surly needs to be retested on Linux and OSX. --- src/bitmessageqt/__init__.py | 134 +++++++++++++++++------------------ 1 file changed, 65 insertions(+), 69 deletions(-) diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 88a3d644..c2b9e23d 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -424,10 +424,6 @@ class MyForm(QtGui.QMainWindow): self.numberOfBroadcastsProcessed = 0 self.numberOfPubkeysProcessed = 0 -#Below this point, it would be good if all of the necessary global data structures were initialized. - - self.rerenderComboBoxSendFrom() - self.UISignalThread = UISignaler() QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable) QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar) @@ -442,67 +438,62 @@ class MyForm(QtGui.QMainWindow): QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL("setStatusIcon(PyQt_PyObject)"), self.setStatusIcon) self.UISignalThread.start() - #self.connectToStream(1) +#Below this point, it would be good if all of the necessary global data structures were initialized. - #self.singleListenerThread = singleListener() - #self.singleListenerThread.start() - #QtCore.QObject.connect(self.singleListenerThread, QtCore.SIGNAL("passObjectThrough(PyQt_PyObject)"), self.connectObjectToSignals) + self.rerenderComboBoxSendFrom() - - #self.singleCleanerThread = singleCleaner() - #self.singleCleanerThread.start() - #QtCore.QObject.connect(self.singleCleanerThread, QtCore.SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByHash) - #QtCore.QObject.connect(self.singleCleanerThread, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar) - - #self.workerThread = singleWorker() - #self.workerThread.start() - #QtCore.QObject.connect(self.workerThread, QtCore.SIGNAL("updateSentItemStatusByHash(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByHash) - #QtCore.QObject.connect(self.workerThread, QtCore.SIGNAL("updateSentItemStatusByAckdata(PyQt_PyObject,PyQt_PyObject)"), self.updateSentItemStatusByAckdata) - #QtCore.QObject.connect(self.workerThread, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar) - - # an appindicator action which indicates the connection status - actionStatus = None - - # an appindicator action which shows of hides the program window - actionShow = None - - # show the application window - def appIndicatorShow(self): - if self.actionShow == None: - return - self.actionShow.setChecked(True) - self.show() - self.setWindowState(self.windowState() & QtCore.Qt.WindowMaximized) - - # application indicator show or hide - def appIndicatorShowBitmessage(self): - if self.actionShow == None: - return + #Show or hide the application window after clicking an item within the tray icon or, on Windows, the try icon itself. + def appIndicatorShowOrHideWindow(self): if not self.actionShow.isChecked(): self.hide() - self.setWindowState(self.windowState() & QtCore.Qt.WindowMinimized) else: - self.show() - self.setWindowState(self.windowState() & QtCore.Qt.WindowMaximized) + if sys.platform[0:3] == 'win': + self.setWindowFlags(Qt.Window) + self.show() + self.setWindowState(self.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive) + self.activateWindow() + else: + self.show() + self.setWindowState(self.windowState() & QtCore.Qt.WindowMaximized) + #Here is what I believe might be required for darwin: + #self.setWindowState(self.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive) + #self.activateWindow() + + """# application indicator show or hide + def appIndicatorShowBitmessage(self): + #if self.actionShow == None: + # return + print self.actionShow.isChecked() + if not self.actionShow.isChecked(): + self.hide() + #self.setWindowState(self.windowState() & QtCore.Qt.WindowMinimized) + else: + self.appIndicatorShowOrHideWindow()""" # Show the program window and select send tab def appIndicatorSend(self): - self.appIndicatorShow() + self.actionShow.setChecked(True) + self.appIndicatorShowOrHideWindow() self.ui.tabWidget.setCurrentIndex(1) # Show the program window and select subscriptions tab def appIndicatorSubscribe(self): - self.appIndicatorShow() + self.actionShow.setChecked(True) + self.appIndicatorShowOrHideWindow() self.ui.tabWidget.setCurrentIndex(4) # Show the program window and select the address book tab def appIndicatorAddressBook(self): - self.appIndicatorShow() + self.actionShow.setChecked(True) + self.appIndicatorShowOrHideWindow() self.ui.tabWidget.setCurrentIndex(5) # create application indicator def createAppIndicator(self,app): - app.tray = QSystemTrayIcon(QtGui.QIcon("images/can-icon-24px.png"), app) + self.tray = QSystemTrayIcon(QtGui.QIcon("images/can-icon-24px.png"), app) + if sys.platform[0:3] == 'win': + traySignal = "activated(QSystemTrayIcon::ActivationReason)" + QtCore.QObject.connect(self.tray, QtCore.SIGNAL(traySignal), self.__icon_activated) m = QMenu() self.actionStatus = QtGui.QAction('Not Connected',m,checkable=False) @@ -516,8 +507,9 @@ class MyForm(QtGui.QMainWindow): # show bitmessage self.actionShow = QtGui.QAction('Show Bitmessage',m,checkable=True) self.actionShow.setChecked(True) - self.actionShow.triggered.connect(self.appIndicatorShowBitmessage) - m.addAction(self.actionShow) + self.actionShow.triggered.connect(self.appIndicatorShowOrHideWindow) + if not sys.platform[0:3] == 'win': + m.addAction(self.actionShow) # Send actionSend = QtGui.QAction('Send',m,checkable=False) @@ -541,8 +533,12 @@ class MyForm(QtGui.QMainWindow): # Quit m.addAction("Quit", self.close) - app.tray.setContextMenu(m) - app.tray.show() + self.tray.setContextMenu(m) + self.tray.show() + if shared.config.getboolean('bitmessagesettings', 'startintray'): + self.hide() + #myapp.trayIcon.show()#This option seems to have been obsoleted by https://github.com/Bitmessage/PyBitmessage/pull/133/files + self.actionShow.setChecked(False) def tableWidgetInboxKeyPressEvent(self,event): if event.key() == QtCore.Qt.Key_Delete: @@ -591,11 +587,15 @@ class MyForm(QtGui.QMainWindow): os.startfile(shared.appdata + 'keys.dat') def changeEvent(self, event): + if event.type() == QtCore.QEvent.WindowStateChange: + if self.windowState() & QtCore.Qt.WindowMinimized: + self.actionShow.setChecked(False) if shared.config.getboolean('bitmessagesettings', 'minimizetotray') and not 'darwin' in sys.platform: if event.type() == QtCore.QEvent.WindowStateChange: if self.windowState() & QtCore.Qt.WindowMinimized: self.hide() - self.trayIcon.show() + + #self.trayIcon.show() #This may have been obsoleted by https://github.com/Bitmessage/PyBitmessage/issues/135 #self.hidden = True if 'win32' in sys.platform or 'win64' in sys.platform: self.setWindowFlags(Qt.ToolTip) @@ -606,7 +606,10 @@ class MyForm(QtGui.QMainWindow): def __icon_activated(self, reason): if reason == QtGui.QSystemTrayIcon.Trigger: - if 'linux' in sys.platform: + self.actionShow.setChecked(not self.actionShow.isChecked()) + self.appIndicatorShowOrHideWindow() + + """if 'linux' in sys.platform: self.trayIcon.hide() self.setWindowFlags(Qt.Window) self.show() @@ -621,7 +624,7 @@ class MyForm(QtGui.QMainWindow): #self.setWindowFlags(Qt.Window) #self.show() self.setWindowState(self.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive) - self.activateWindow() + self.activateWindow()""" def incrementNumberOfMessagesProcessed(self): self.numberOfMessagesProcessed += 1 @@ -685,22 +688,22 @@ class MyForm(QtGui.QMainWindow): if color == 'red': self.ui.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/redicon.png")) shared.statusIconColor = 'red' - if self.actionStatus != None: - self.actionStatus.setText('Not Connected') + #if self.actionStatus != None: + self.actionStatus.setText('Not Connected') if color == 'yellow': if self.statusBar().currentMessage() == 'Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won\'t send until you connect.': self.statusBar().showMessage('') self.ui.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/yellowicon.png")) shared.statusIconColor = 'yellow' - if self.actionStatus != None: - self.actionStatus.setText('Connection Ok') + #if self.actionStatus != None: + self.actionStatus.setText('Connected') if color == 'green': if self.statusBar().currentMessage() == 'Warning: You are currently not connected. Bitmessage will do the work necessary to send the message but it won\'t send until you connect.': self.statusBar().showMessage('') self.ui.pushButtonStatusIcon.setIcon(QIcon(":/newPrefix/images/greenicon.png")) shared.statusIconColor = 'green' - if self.actionStatus != None: - self.actionStatus.setText('Connection Good') + #if self.actionStatus != None: + self.actionStatus.setText('Connected') def updateSentItemStatusByHash(self,toRipe,textToDisplay): for i in range(self.ui.tableWidgetSent.rowCount()): @@ -1402,7 +1405,8 @@ class MyForm(QtGui.QMainWindow): else: event.ignore()''' shared.doCleanShutdown() - self.trayIcon.hide() + #self.trayIcon.hide() + self.tray.hide() self.statusBar().showMessage('All done. Closing user interface...') event.accept() shared.printLock.acquire() @@ -2037,20 +2041,12 @@ class UISignaler(QThread): sys.stderr.write('Command sent to UISignaler not recognized: %s\n' % command) - def run(): app = QtGui.QApplication(sys.argv) app.setStyleSheet("QStatusBar::item { border: 0px solid black }") myapp = MyForm() myapp.show() - if shared.config.getboolean('bitmessagesettings', 'startintray'): - myapp.hide() - myapp.trayIcon.show() - #self.hidden = True - #self.setWindowState(self.windowState() & QtCore.Qt.WindowMinimized) - #self.hide() - if 'win32' in sys.platform or 'win64' in sys.platform: - myapp.setWindowFlags(Qt.ToolTip) + if sys.platform[0:3] == 'win': + myapp.setWindowFlags(Qt.ToolTip) myapp.createAppIndicator(app) - sys.exit(app.exec_())