diff --git a/Qt/Bungloo.py b/Qt/Bungloo.py index d9d0e46..6a065e7 100755 --- a/Qt/Bungloo.py +++ b/Qt/Bungloo.py @@ -1,17 +1,17 @@ #!/usr/bin/env python2 -import os, sys, pickle, subprocess, shutil +import os, sys, pickle, subprocess, shutil, json from PyQt4 import QtCore, QtGui, QtWebKit, QtNetwork RUNNING_LOCAL = os.path.basename(sys.argv[0]) == "Bungloo.py" RUNNING_ON_WINDOWS = os.name == "nt" if RUNNING_LOCAL or RUNNING_ON_WINDOWS: - import Windows, Helper + import Windows, Helper, SingleApplication else: - from bungloo import Windows, Helper + from bungloo import Windows, Helper, SingleApplication -class Bungloo: +class Bungloo(): def __init__(self): @@ -19,7 +19,6 @@ class Bungloo: sslConfig.setProtocol(QtNetwork.QSsl.TlsV1) QtNetwork.QSslConfiguration.setDefaultConfiguration(sslConfig) - self.app = QtGui.QApplication(sys.argv) self.new_message_windows = [] self.controller = Controller(self) self.console = Console() @@ -33,10 +32,8 @@ class Bungloo: if self.controller.stringForKey("user_access_token") != "": self.authentification_succeded() - self.app.exec_() - def resources_path(self): - if RUNNING_LOCAL: + if RUNNING_LOCAL: return os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..')) else: return Helper.Helper.get_resource_path() @@ -95,6 +92,14 @@ class Bungloo: def next_show(self): self.timeline.evaluateJavaScript("bungloo.sidebar.showContentForNext();") + def handleMessage(self, args): + # argv is just a array of words which you can get in from the outside + argv = json.loads(str(args)) + if len(argv) > 0: + if argv[0] == "--new-message": + self.controller.openNewMessageWidow(" ".join(argv[1:])) + + class Controller(QtCore.QObject): @@ -169,11 +174,9 @@ class Controller(QtCore.QObject): pass @QtCore.pyqtSlot(str) - def openNewMessageWidow(self, string): - new_message_window = Windows.NewPost(self.app) - new_message_window.show() - new_message_window.setAttribute(QtCore.Qt.WA_DeleteOnClose) - self.app.new_message_windows.append(new_message_window) + def openNewMessageWidow(self, is_private=False, string=""): + string = str(string) + self.openNewMessageWindowInReplyTostatusIdwithStringIsPrivate(None, None, string, is_private) @QtCore.pyqtSlot(str, str, str, bool) def openNewMessageWindowInReplyTostatusIdwithStringIsPrivate(self, entity, status_id, string, is_private): @@ -183,6 +186,11 @@ class Controller(QtCore.QObject): new_message_window.show() new_message_window.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.app.new_message_windows.append(new_message_window) + new_message_window.activateWindow() + new_message_window.setFocus() + new_message_window.textInput.setFocus() + new_message_window.show() + new_message_window.raise_() def sendMessage(self, message): text = message.text @@ -288,4 +296,25 @@ class Console(QtCore.QObject): if __name__ == "__main__": - Bungloo() + + key = 'BUNGLOO' + + if len(sys.argv) > 1 and sys.argv[1] == "--help": + print """ +Usage: bungloo [option [text]] + + Options: + --new-message [text] Opens new message window with text + --search text Opens search with text + """ + sys.exit(1) + + app = SingleApplication.SingleApplicationWithMessaging(sys.argv, key) + if app.isRunning(): + app.sendMessage(json.dumps(sys.argv[1:])) + sys.exit(1) + + bungloo = Bungloo() + app.connect(app, QtCore.SIGNAL('messageAvailable'), bungloo.handleMessage) + + sys.exit(app.exec_()) diff --git a/Qt/SingleApplication.py b/Qt/SingleApplication.py new file mode 100755 index 0000000..d9d807f --- /dev/null +++ b/Qt/SingleApplication.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python2 + +# from http://stackoverflow.com/questions/8786136/pyqt-how-to-detect-and-close-ui-if-its-already-running + +from PyQt4 import QtGui, QtCore, QtNetwork + +class SingleApplication(QtGui.QApplication): + def __init__(self, argv, key): + QtGui.QApplication.__init__(self, argv) + self._memory = QtCore.QSharedMemory(self) + self._memory.setKey(key) + if self._memory.attach(): + self._running = True + else: + self._running = False + if not self._memory.create(1): + raise RuntimeError( + self._memory.errorString().toLocal8Bit().data()) + + def isRunning(self): + return self._running + +class SingleApplicationWithMessaging(SingleApplication): + def __init__(self, argv, key): + SingleApplication.__init__(self, argv, key) + self._key = key + self._timeout = 1000 + self._server = QtNetwork.QLocalServer(self) + if not self.isRunning(): + self._server.newConnection.connect(self.handleMessage) + self._server.listen(self._key) + + def handleMessage(self): + socket = self._server.nextPendingConnection() + if socket.waitForReadyRead(self._timeout): + self.emit(QtCore.SIGNAL('messageAvailable'), + QtCore.QString.fromUtf8(socket.readAll().data())) + socket.disconnectFromServer() + else: + QtCore.qDebug(socket.errorString().toLatin1()) + + def sendMessage(self, message): + if self.isRunning(): + socket = QtNetwork.QLocalSocket(self) + socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly) + if not socket.waitForConnected(self._timeout): + print(socket.errorString().toLocal8Bit().data()) + return False + socket.write(unicode(message).encode('utf-8')) + if not socket.waitForBytesWritten(self._timeout): + print(socket.errorString().toLocal8Bit().data()) + return False + socket.disconnectFromServer() + return True + return False + +class Window(QtGui.QWidget): + def __init__(self): + QtGui.QWidget.__init__(self) + self.edit = QtGui.QLineEdit(self) + self.edit.setMinimumWidth(300) + layout = QtGui.QVBoxLayout(self) + layout.addWidget(self.edit) + + def handleMessage(self, message): + self.edit.setText(message) + +if __name__ == '__main__': + + import sys + + key = 'FOO_BAR' + + if len(sys.argv) > 1: + app = SingleApplicationWithMessaging(sys.argv, key) + if app.isRunning(): + app.sendMessage(sys.argv[1]) + sys.exit(1) + else: + app = SingleApplication(sys.argv, key) + if app.isRunning(): + print('app is already running') + sys.exit(1) + + window = Window() + app.connect(app, QtCore.SIGNAL('messageAvailable'), + window.handleMessage) + window.show() + + sys.exit(app.exec_()) \ No newline at end of file diff --git a/Qt/Windows.py b/Qt/Windows.py index 9a68ce2..b47d8ae 100644 --- a/Qt/Windows.py +++ b/Qt/Windows.py @@ -442,6 +442,9 @@ class NewPost(Helper.RestorableWindow): def toggleIsPrivate(self): self.setIsPrivate(not self.isPrivate) + def setString(self, string): + self.inReplyToStatusIdWithString(None, None, string) + def inReplyToStatusIdWithString(self, reply_to, status_id, string): self.reply_to_entity = reply_to self.status_id = status_id