def send_to_running_instance(socketname, command, target_arg, *, legacy_name=None, socket=None): """Try to send a commandline to a running instance. Blocks for CONNECT_TIMEOUT ms. Args: socketname: The name which should be used for the socket. command: The command to send to the running instance. target_arg: --target command line argument socket: The socket to read data from, or None. legacy_name: The legacy name to first try to connect to. Return: True if connecting was successful, False if no connection was made. """ if socket is None: socket = QLocalSocket() if (legacy_name is not None and _has_legacy_server(legacy_name)): name_to_use = legacy_name else: name_to_use = socketname log.ipc.debug("Connecting to {}".format(name_to_use)) socket.connectToServer(name_to_use) connected = socket.waitForConnected(CONNECT_TIMEOUT) if connected: log.ipc.info("Opening in existing instance") json_data = {'args': command, 'target_arg': target_arg, 'version': qutebrowser.__version__, 'protocol_version': PROTOCOL_VERSION} try: cwd = os.getcwd() except OSError: pass else: json_data['cwd'] = cwd line = json.dumps(json_data) + '\n' data = line.encode('utf-8') log.ipc.debug("Writing: {}".format(data)) socket.writeData(data) socket.waitForBytesWritten(WRITE_TIMEOUT) if socket.error() != QLocalSocket.UnknownSocketError: raise SocketError("writing to running instance", socket) else: socket.disconnectFromServer() if socket.state() != QLocalSocket.UnconnectedState: socket.waitForDisconnected(CONNECT_TIMEOUT) return True else: if socket.error() not in (QLocalSocket.ConnectionRefusedError, QLocalSocket.ServerNotFoundError): raise SocketError("connecting to running instance", socket) else: log.ipc.debug("No existing instance present (error {})".format( socket.error())) return False
def send_to_running_instance(cmdlist): """Try to send a commandline to a running instance. Blocks for CONNECT_TIMEOUT ms. Args: cmdlist: A list to send (URLs/commands) Return: True if connecting was successful, False if no connection was made. """ socket = QLocalSocket() socket.connectToServer(SOCKETNAME) connected = socket.waitForConnected(100) if connected: log.ipc.info("Opening in existing instance") line = json.dumps(cmdlist) + '\n' data = line.encode('utf-8') log.ipc.debug("Writing: {}".format(data)) socket.writeData(data) socket.waitForBytesWritten(WRITE_TIMEOUT) if socket.error() != QLocalSocket.UnknownSocketError: _socket_error("writing to running instance", socket) else: return True else: if socket.error() not in (QLocalSocket.ConnectionRefusedError, QLocalSocket.ServerNotFoundError): _socket_error("connecting to running instance", socket) else: log.ipc.debug("No existing instance present (error {})".format( socket.error())) return False
def _send_to_running_instance(self, payload: bytes, pid: int) -> None: from PyQt5.QtCore import QByteArray from PyQt5.QtNetwork import QLocalSocket named_pipe = f"{BUNDLE_IDENTIFIER}.protocol.{pid}" log.debug( f"Opening a local socket to the running instance on {named_pipe} " f"(payload={self.redact_payload(payload)})" ) client = QLocalSocket() try: client.connectToServer(named_pipe) if not client.waitForConnected(): log.error(f"Unable to open client socket: {client.errorString()}") return client.write(QByteArray(payload)) client.waitForBytesWritten() client.disconnectFromServer() if client.state() == QLocalSocket.ConnectedState: client.waitForDisconnected() finally: del client log.debug("Successfully closed client socket")
def init(): """Start listening to incoming connections.""" global _server if _server is not None: return server = QLocalServer(None) # find a free socket name to use for name in ids(): if server.listen(name): break else: # all names failed, try to contact and remove stale file if that fails socket = QLocalSocket() for name in ids(): socket.connectToServer(name) if not socket.waitForConnected(10000): QLocalServer.removeServer(name) if server.listen(name): break else: socket.disconnectFromServer() else: # no ids left, don't listen return app.aboutToQuit.connect(server.close) server.newConnection.connect(slot_new_connection) os.environ["FRESCOBALDI_SOCKET"] = name _server = server
def get(): """Return a remote Frescobaldi, or None if not available.""" socket = QLocalSocket() name = os.environ.get("FRESCOBALDI_SOCKET") for name in (name,) if name else ids(): socket.connectToServer(name) if socket.waitForConnected(5000): from . import api return api.Remote(socket)
def startClient(self) -> bool: Logger.log("i", "Checking for the presence of an ready running Cura instance.") single_instance_socket = QLocalSocket(self._application) Logger.log("d", "Full single instance server name: %s", single_instance_socket.fullServerName()) single_instance_socket.connectToServer("ultimaker-cura") single_instance_socket.waitForConnected(msecs = 3000) # wait for 3 seconds if single_instance_socket.state() != QLocalSocket.ConnectedState: return False # We only send the files that need to be opened. if not self._files_to_open: Logger.log("i", "No file need to be opened, do nothing.") return True if single_instance_socket.state() == QLocalSocket.ConnectedState: Logger.log("i", "Connection has been made to the single-instance Cura socket.") # Protocol is one line of JSON terminated with a carriage return. # "command" field is required and holds the name of the command to execute. # Other fields depend on the command. payload = {"command": "clear-all"} single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding = "ascii")) payload = {"command": "focus"} single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding = "ascii")) for filename in self._files_to_open: payload = {"command": "open", "filePath": os.path.abspath(filename)} single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding = "ascii")) payload = {"command": "close-connection"} single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding = "ascii")) single_instance_socket.flush() single_instance_socket.waitForDisconnected() return True
def send_to_running_instance(socketname, command): """Try to send a commandline to a running instance. Blocks for CONNECT_TIMEOUT ms. Args: socketname: The name which should be used for the socket. command: The command to send to the running instance. Return: True if connecting was successful, False if no connection was made. """ socket = QLocalSocket() log.ipc.debug("Connecting to {}".format(socketname)) socket.connectToServer(socketname) connected = socket.waitForConnected(100) if connected: log.ipc.info("Opening in existing instance") json_data = {'args': command} try: cwd = os.getcwd() except OSError: pass else: json_data['cwd'] = cwd line = json.dumps(json_data) + '\n' data = line.encode('utf-8') log.ipc.debug("Writing: {}".format(data)) socket.writeData(data) socket.waitForBytesWritten(WRITE_TIMEOUT) if socket.error() != QLocalSocket.UnknownSocketError: _socket_error("writing to running instance", socket) else: socket.disconnectFromServer() if socket.state() != QLocalSocket.UnconnectedState: socket.waitForDisconnected(100) return True else: if socket.error() not in (QLocalSocket.ConnectionRefusedError, QLocalSocket.ServerNotFoundError): _socket_error("connecting to running instance", socket) else: log.ipc.debug("No existing instance present (error {})".format( socket.error())) return False
class QSingleApplication(QApplication): messageReceived = pyqtSignal(str) def __init__(self, *args, **kwargs): super(QSingleApplication, self).__init__(*args, **kwargs) appid = QApplication.applicationFilePath().lower().split("/")[-1] self._socketName = "qtsingleapp-" + appid print("socketName", self._socketName) self._activationWindow = None self._activateOnMessage = False self._socketServer = None self._socketIn = None self._socketOut = None self._running = False # 先尝试连接 self._socketOut = QLocalSocket(self) self._socketOut.connectToServer(self._socketName) self._socketOut.error.connect(self.handleError) self._running = self._socketOut.waitForConnected() if not self._running: # 程序未运行 self._socketOut.close() del self._socketOut self._socketServer = QLocalServer(self) self._socketServer.listen(self._socketName) self._socketServer.newConnection.connect(self._onNewConnection) self.aboutToQuit.connect(self.removeServer) def handleError(self, message): print("handleError message: ", message) def isRunning(self): return self._running def activationWindow(self): return self._activationWindow def setActivationWindow(self, activationWindow, activateOnMessage=True): self._activationWindow = activationWindow self._activateOnMessage = activateOnMessage def activateWindow(self): if not self._activationWindow: return self._activationWindow.setWindowState( self._activationWindow.windowState() & ~Qt.WindowMinimized) self._activationWindow.raise_() self._activationWindow.activateWindow() def sendMessage(self, message, msecs=5000): if not self._socketOut: return False if not isinstance(message, bytes): message = str(message).encode() self._socketOut.write(message) if not self._socketOut.waitForBytesWritten(msecs): raise RuntimeError("Bytes not written within %ss" % (msecs / 1000.)) return True def _onNewConnection(self): if self._socketIn: self._socketIn.readyRead.disconnect(self._onReadyRead) self._socketIn = self._socketServer.nextPendingConnection() if not self._socketIn: return self._socketIn.readyRead.connect(self._onReadyRead) if self._activateOnMessage: self.activateWindow() def _onReadyRead(self): while 1: message = self._socketIn.readLine() if not message: break print("Message received: ", message) self.messageReceived.emit(message.data().decode()) def removeServer(self): self._socketServer.close() self._socketServer.removeServer(self._socketName)
class Eddy(QApplication): """ This class implements the main Qt application. """ messageReceived = pyqtSignal(str) def __init__(self, argv): """ Initialize Eddy. :type argv: list """ super().__init__(argv) parser = ArgumentParser() parser.add_argument('--nosplash', dest='nosplash', action='store_true') parser.add_argument('--tests', dest='tests', action='store_true') options, args = parser.parse_known_args(args=argv) self.inSocket = None self.inStream = None self.outSocket = QLocalSocket() self.outSocket.connectToServer(APPID) self.outStream = None self.isRunning = self.outSocket.waitForConnected() self.mainwindow = None self.pendingOpen = [] self.server = None # We do not initialize a new instance of Eddy if there is a process running # and we are not executing the tests suite: we'll create a socket instead so we can # exchange messages between the 2 processes (this one and the already running one). if self.isRunning and not options.tests: self.outStream = QTextStream(self.outSocket) self.outStream.setCodec('UTF-8') else: self.server = QLocalServer() self.server.listen(APPID) self.outSocket = None self.outStream = None connect(self.server.newConnection, self.newConnection) connect(self.messageReceived, self.readMessage) ############################################################################################################ # # # PERFORM EDDY INITIALIZATION # # # ############################################################################################################ # Draw the splashscreen. self.splashscreen = None if not options.nosplash: self.splashscreen = SplashScreen(min_splash_time=4) self.splashscreen.show() # Setup layout. self.setStyle(Clean('Fusion')) with open(expandPath('@eddy/ui/clean.qss')) as sheet: self.setStyleSheet(sheet.read()) # Create the main window. self.mainwindow = MainWindow() # Close the splashscreen. if self.splashscreen: self.splashscreen.wait(self.splashscreen.remaining) self.splashscreen.close() # Display the mainwindow. self.mainwindow.show() if Platform.identify() is Platform.Darwin: # On MacOS files being opened are handled as a QFileOpenEvent but since we don't # have a Main Window initialized we store them locally and we open them here. for filepath in self.pendingOpen: self.openFile(filepath) self.pendingOpen = [] else: # Perform document opening if files have been added to sys.argv. This is not # executed on Mac OS since this is already handled as a QFileOpenEvent instance. for filepath in argv: self.openFile(filepath) #################################################################################################################### # # # EVENTS # # # #################################################################################################################### def event(self, event): """ Executed when an event is received. :type event: T <= QEvent | QFileOpenEvent """ if event.type() == QEvent.FileOpen: self.pendingOpen = [event.file()] return True return super().event(event) #################################################################################################################### # # # INTERFACE # # # #################################################################################################################### def activate(self): """ Activate the application by raising the main window. """ if self.mainwindow: self.mainwindow.setWindowState((self.mainwindow.windowState() & ~Qt.WindowMinimized) | Qt.WindowActive) self.mainwindow.activateWindow() self.mainwindow.raise_() def openFile(self, filepath): """ Open the given file in the activation window. :type filepath: str :rtype: bool """ if self.mainwindow: if not isEmpty(filepath) and os.path.isfile(filepath) and filepath.endswith(Filetype.Graphol.extension): self.mainwindow.openFile(filepath) return True return False def sendMessage(self, message): """ Send a message to the other alive Eddy's process. :type message: str :rtype: bool """ if self.outStream: self.outStream = self.outStream << message << '\n' self.outStream.flush() return self.outSocket.waitForBytesWritten() return False #################################################################################################################### # # # SLOTS # # # #################################################################################################################### @pyqtSlot() def newConnection(self): """ Executed whenever a message is received. """ if self.inSocket: # Disconnect previously connected signal slot. disconnect(self.inSocket.readyRead, self.readyRead) # Create a new socket. self.inSocket = self.server.nextPendingConnection() if self.inSocket: self.inStream = QTextStream(self.inSocket) self.inStream.setCodec('UTF-8') connect(self.inSocket.readyRead, self.readyRead) self.activate() @pyqtSlot() def readyRead(self): """ Executed whenever we need to read a message. """ while True: message = self.inStream.readLine() if isEmpty(message): break self.messageReceived.emit(message) @pyqtSlot(str) def readMessage(self, message): """ Read a received message. :type message: str """ for filepath in message.split(' '): self.openFile(filepath)
class QSingleApplication(QApplication): messageReceived = pyqtSignal(str) def __init__(self, id, *argv): super(QSingleApplication, self).__init__(*argv) self._id = id self._activationWindow = None self._activateOnMessage = False self._server = None # Is there another instance running? self._outSocket = QLocalSocket() self._outSocket.connectToServer(self._id) self._outSocket.error.connect(self.handleError) self._isRunning = self._outSocket.waitForConnected() if self._isRunning: # Yes, there is. self._outStream = QTextStream(self._outSocket) self._outStream.setCodec('UTF-8') else: # No, there isn't. self._outSocket = None self._outStream = None self._inSocket = None self._inStream = None self._server = QLocalServer() self._server.listen(self._id) self._server.newConnection.connect(self._onNewConnection) self.aboutToQuit.connect(self.removeServer) def handleError(self, msg): print(msg) def server(self): return self._server def isRunning(self): return self._isRunning def id(self): return self._id def activationWindow(self): return self._activationWindow def setActivationWindow(self, activationWindow, activateOnMessage=True): self._activationWindow = activationWindow self._activateOnMessage = activateOnMessage def activateWindow(self): if not self._activationWindow: print("No registered ActivationWindow") return # Unfortunately this *doesn't* do much of any use, as it won't # bring the window to the foreground under KDE... sigh. self._activationWindow.setWindowState( self._activationWindow.windowState() & ~Qt.WindowMinimized) self._activationWindow.raise_() self._activationWindow.requestActivate() def sendMessage(self, msg, msecs=5000): if not self._outStream: return False self._outStream << msg << '\n' if not self._outSocket.waitForBytesWritten(msecs): raise RuntimeError("Bytes not written within %ss" % (msecs / 1000.)) def _onNewConnection(self): if self._inSocket: self._inSocket.readyRead.disconnect(self._onReadyRead) self._inSocket = self._server.nextPendingConnection() if not self._inSocket: return self._inStream = QTextStream(self._inSocket) self._inStream.setCodec('UTF-8') self._inSocket.readyRead.connect(self._onReadyRead) if self._activateOnMessage: self.activateWindow() def _onReadyRead(self): while True: msg = self._inStream.readLine() if not msg: break print("Message received") self.messageReceived.emit(msg) def removeServer(self): self._server.close() self._server.removeServer(self._id)
def __init__(self, pathObjects, parent=None): """Initialize the main tree controls Arguments: pathObjects -- a list of file objects to open parent -- the parent QObject if given """ super().__init__(parent) self.localControls = [] self.activeControl = None self.trayIcon = None self.isTrayMinimized = False self.configDialog = None self.sortDialog = None self.numberingDialog = None self.findTextDialog = None self.findConditionDialog = None self.findReplaceDialog = None self.filterTextDialog = None self.filterConditionDialog = None self.basicHelpView = None self.passwords = {} self.creatingLocalControlFlag = False globalref.mainControl = self self.allActions = {} try: # check for existing TreeLine session socket = QLocalSocket() socket.connectToServer('treeline3-session', QIODevice.WriteOnly) # if found, send files to open and exit TreeLine if socket.waitForConnected(1000): socket.write( bytes(repr([str(path) for path in pathObjects]), 'utf-8')) if socket.waitForBytesWritten(1000): socket.close() sys.exit(0) # start local server to listen for attempt to start new session self.serverSocket = QLocalServer() # remove any old servers still around after a crash in linux self.serverSocket.removeServer('treeline3-session') self.serverSocket.listen('treeline3-session') self.serverSocket.newConnection.connect(self.getSocket) except AttributeError: print(_('Warning: Could not create local socket')) mainVersion = '.'.join(__version__.split('.')[:2]) globalref.genOptions = options.Options('general', 'TreeLine', mainVersion, 'bellz') optiondefaults.setGenOptionDefaults(globalref.genOptions) globalref.miscOptions = options.Options('misc') optiondefaults.setMiscOptionDefaults(globalref.miscOptions) globalref.histOptions = options.Options('history') optiondefaults.setHistOptionDefaults(globalref.histOptions) globalref.toolbarOptions = options.Options('toolbar') optiondefaults.setToolbarOptionDefaults(globalref.toolbarOptions) globalref.keyboardOptions = options.Options('keyboard') optiondefaults.setKeyboardOptionDefaults(globalref.keyboardOptions) try: globalref.genOptions.readFile() globalref.miscOptions.readFile() globalref.histOptions.readFile() globalref.toolbarOptions.readFile() globalref.keyboardOptions.readFile() except IOError: errorDir = options.Options.basePath if not errorDir: errorDir = _('missing directory') QMessageBox.warning( None, 'TreeLine', _('Error - could not write config file to {}').format( errorDir)) options.Options.basePath = None iconPathList = self.findResourcePaths('icons', iconPath) globalref.toolIcons = icondict.IconDict( [path / 'toolbar' for path in iconPathList], ['', '32x32', '16x16']) globalref.toolIcons.loadAllIcons() windowIcon = globalref.toolIcons.getIcon('treelogo') if windowIcon: QApplication.setWindowIcon(windowIcon) globalref.treeIcons = icondict.IconDict(iconPathList, ['', 'tree']) icon = globalref.treeIcons.getIcon('default') qApp.setStyle(QStyleFactory.create('Fusion')) self.colorSet = colorset.ColorSet() if globalref.miscOptions['ColorTheme'] != 'system': self.colorSet.setAppColors() self.recentFiles = recentfiles.RecentFileList() if globalref.genOptions['AutoFileOpen'] and not pathObjects: recentPath = self.recentFiles.firstPath() if recentPath: pathObjects = [recentPath] self.setupActions() self.systemFont = QApplication.font() self.updateAppFont() if globalref.genOptions['MinToSysTray']: self.createTrayIcon() qApp.focusChanged.connect(self.updateActionsAvail) if pathObjects: for pathObj in pathObjects: self.openFile(pathObj, True) else: self.createLocalControl()
class SingleApplication(QtWidgets.QApplication): ''' Inheriting from QApplication, executing main App instead. Watching whether the app is already running. If so, quit befor execution. ''' messageReceived = QtCore.pyqtSignal(str) def __init__(self, id, *argv): super(SingleApplication, self).__init__(*argv) self._id = id self._activationWindow = None self._activateOnMessage = False # Check if another instance is running? self._outSocket = QLocalSocket() self._outSocket.connectToServer(self._id) self._isRunning = self._outSocket.waitForConnected() if self._isRunning: self._outStream = QtCore.QTextStream(self._outSocket) self._outStream.setCodec('UTF-8') else: self._outSocket = None self._outStream = None self._inSocket = None self._inStream = None self._server = QLocalServer() self._server.removeServer(self._id) # if existing after crash-exit self._server.listen(self._id) self._server.newConnection.connect(self._onNewConnection) def isRunning(self): return self._isRunning def id(self): return self._id def activationWindow(self): return self._activationWindow def setActivationWindow(self, activationWindow, activateOnMessage=True): self._activationWindow = activationWindow self._activateOnMessage = activateOnMessage def activateWindow(self): if not self._activationWindow: return self._activationWindow.setWindowState( self._activationWindow.windowState() & ~QtCore.Qt.WindowMinimized) self._activationWindow.show() self._activationWindow.activateWindow() def sendMessage(self, msg): if not self._outStream: return False self._outStream << msg << '\n' self._outStream.flush() return self._outSocket.waitForBytesWritten() def _onNewConnection(self): if self._inSocket: self._inSocket.readyRead.disconnect(self._onReadyRead) self._inSocket = self._server.nextPendingConnection() if not self._inSocket: return self._inStream = QtCore.QTextStream(self._inSocket) self._inStream.setCodec('UTF-8') self._inSocket.readyRead.connect(self._onReadyRead) if self._activateOnMessage: self.activateWindow() def _onReadyRead(self): while True: msg = self._inStream.readLine() if not msg: break self.messageReceived.emit(msg)
class SingleApplicationClient(object): """ Class implementing the single application client base class. """ def __init__(self, name): """ Constructor @param name name of the local server to connect to (string) """ self.name = name self.connected = False def connect(self): """ Public method to connect the single application client to its server. @return value indicating success or an error number. Value is one of: <table> <tr><td>0</td><td>No application is running</td></tr> <tr><td>1</td><td>Application is already running</td></tr> </table> """ self.sock = QLocalSocket() self.sock.connectToServer(self.name) if self.sock.waitForConnected(10000): self.connected = True return 1 else: err = self.sock.error() if err == QLocalSocket.ServerNotFoundError: return 0 else: return -err def disconnect(self): """ Public method to disconnect from the Single Appliocation server. """ self.sock.disconnectFromServer() self.connected = False def processArgs(self, args): """ Public method to process the command line args passed to the UI. <b>Note</b>: This method must be overridden by subclasses. @param args command line args (list of strings) @exception RuntimeError raised to indicate that this method must be implemented by a subclass """ raise RuntimeError("'processArgs' must be overridden") def sendCommand(self, cmd): """ Public method to send the command to the application server. @param cmd command to be sent (string) """ if self.connected: self.sock.write(cmd) self.sock.flush() def errstr(self): """ Public method to return a meaningful error string for the last error. @return error string for the last error (string) """ return self.sock.errorString()
class MainForm(QDialog): def __init__(self, parent = None): QDialog.__init__(self, parent) # If a Nemu instance is already running, this is as far as we go self.connectToRunning() self.holdOpen = False self.menuItems = [] self.allItems = [] self.favorites = [] self.currentItem = None self.menuFile = os.path.expanduser('~/.nemu/menu') self.favoritesFile = os.path.expanduser('~/.nemu/favorites') # NOTE: If you change this, also update migrate-settings self.settingsFile = os.path.expanduser('~/.nemu/settings') self.initSettings() self.server = QLocalServer() self.server.newConnection.connect(self.handleConnection) QLocalServer.removeServer('nemuSocket') self.server.listen('nemuSocket') self.configDir = os.path.expanduser('~/.nemu') if not os.path.isdir(self.configDir): os.mkdir(self.configDir) self.menuItems = self.loadConfig(self.menuFile, self.menuItems) self.favorites = self.loadConfig(self.favoritesFile, self.favorites) # Don't load directly into self.settings so we can add new default values as needed try: tempSettings = self.loadConfig(self.settingsFile, self.settings) for key, value in tempSettings.items(): self.settings[key] = value except SystemError: print('ERROR: Failed to load settings. You may need to run migrate-settings.') raise # This should never happen, but unfortunately bugs do, so clean up orphaned items. # We need to do this because these items won't show up in the UI, but may interfere with # merges if they duplicate something that is being merged in. self.menuItems[:] = [i for i in self.menuItems if i.parent == None or i.parent in self.menuItems] # Look for broken icon paths needSave = False for i in self.menuItems + self.favorites: if not os.path.exists(i.icon): i.findIcon() needSave = True if needSave: self.saveMenu() for i in self.menuItems: if not hasattr(i, 'imported'): i.imported = False self.setupUI() self.setContextMenuPolicy(Qt.ActionsContextMenu) self.createMenu(self) self.refresh(False) if len(self.menuItems) == 0: self.firstRun() self.show() self.keepaliveTimer = QTimer(self) self.keepaliveTimer.timeout.connect(self.keepalive) self.keepaliveTimer.start(60000) def initSettings(self): self.settings = dict() self.settings['width'] = 400 self.settings['height'] = 400 self.settings['quit'] = False self.settings['imported'] = [] self.settings['iconTheme'] = None def loadConfig(self, filename, default): if os.path.exists(filename): with open(filename, 'rb') as f: data = f.read().replace('PyQt4', 'PyQt5') return cPickle.loads(data) else: return default def setupUI(self): self.resize(self.settings['width'], self.settings['height']) self.setWindowFlags(Qt.FramelessWindowHint | Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint) #self.setWindowFlags(Qt.X11BypassWindowManagerHint) self.setWindowTitle('Nemu') self.setMouseTracking(True) iconPath = os.path.join(os.path.dirname(__file__), 'images') iconPath = os.path.join(iconPath, 'nemu.png') self.setWindowIcon(IconCache()[iconPath]) self.place() self.buttonListLayout = QVBoxLayout(self) self.setMargins(self.buttonListLayout) self.buttonLayout = QHBoxLayout() self.setMargins(self.buttonLayout) # Settings and Filter box self.filterLayout = QHBoxLayout() self.settingsButton = QPushButton() self.settingsButton.setIcon(QIcon(iconPath)) self.settingsButton.setMinimumHeight(35) self.settingsButton.clicked.connect(self.settingsClicked) self.filterLayout.addWidget(self.settingsButton, 0) self.filterLabel = QLabel("Filter") self.filterLayout.addWidget(self.filterLabel) self.filterBox = QLineEdit() self.filterBox.textChanged.connect(self.refresh) self.filterLayout.addWidget(self.filterBox) self.sizeGrip = QSizeGrip(self) self.sizeGrip.setMinimumSize(QSize(25, 25)) self.filterLayout.addWidget(self.sizeGrip, 0, Qt.AlignRight | Qt.AlignTop) self.buttonListLayout.addLayout(self.filterLayout) # Top buttons and labels self.backButton = QPushButton('Favorites') self.backButton.setMinimumHeight(35) self.backButton.clicked.connect(self.backClicked) self.buttonLayout.addWidget(self.backButton, 1) self.currentLabel = QLabel() self.currentLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.buttonLayout.addWidget(self.currentLabel, 1) self.buttonListLayout.addLayout(self.buttonLayout, 0) # Menu item display self.listSplitter = QSplitter() self.buttonListLayout.addWidget(self.listSplitter, 1) self.leftList = ListWidget(self.clearListMouseOver) self.listSplitter.addWidget(self.leftList) self.rightList = ListWidget(self.clearListMouseOver) self.listSplitter.addWidget(self.rightList) # Has to be done after adding widgets to the splitter or the size will get reset again if 'splitterState' in self.settings: self.listSplitter.restoreState(self.settings['splitterState']) def setMargins(self, layout, margin = 0): layout.setSpacing(margin) layout.setContentsMargins(margin, margin, margin, margin) def createMenu(self, widget): addFavoriteAction = QAction('Add to Favorites', self) addFavoriteAction.triggered.connect(self.addFavoriteClicked) widget.insertAction(None, addFavoriteAction) addAction = QAction("New...", self) addAction.triggered.connect(self.newClicked) widget.insertAction(None, addAction) editAction = QAction("Edit...", self) editAction.triggered.connect(self.editClicked) widget.insertAction(None, editAction) deleteAction = QAction("Delete", self) deleteAction.triggered.connect(self.deleteClicked) widget.insertAction(None, deleteAction) def hideOrClose(self): if self.settings['quit']: self.close() else: self.hide() def closeEvent(self, event): self.saveSettings() def hideEvent(self, event): self.releaseMouse() self.saveSettings() def mouseMoveEvent(self, event): if self.hasMouse(): self.releaseMouse() def leaveEvent(self, event): # If we set holdOpen, it means that we've opened a dialog, so we shouldn't grab if not self.hasMouse(): self.grabMouse() def mousePressEvent(self, event): if not self.hasMouse(): self.hideOrClose() def hasMouse(self): return self.geometry().contains(QCursor.pos()) def saveSettings(self): self.settings['splitterState'] = self.listSplitter.saveState() self.settings['width'] = self.width() self.settings['height'] = self.height() with open(self.settingsFile, 'wb') as f: cPickle.dump(self.settings, f) def place(self): desktop = qApp.desktop() screenSize = desktop.availableGeometry(QCursor.pos()) self.move(screenSize.x(), screenSize.y() + screenSize.height() - self.height()) def newClicked(self): form = AddForm() self.holdOpen = True form.exec_() self.checkMouse() self.holdOpen = False if form.accepted: item = MenuItem() item.name = form.name item.command = form.command item.working = form.working item.folder = form.folder item.icon = form.icon item.findIcon() clicked = self.getClicked() if clicked: parent = clicked.item.parent elif self.leftList.mouseOver: if self.currentItem != None: parent = self.currentItem.parent else: parent = None else: parent = self.currentItem item.parent = parent self.menuItems.append(item) self.refresh() def editClicked(self): form = AddForm() clicked = self.getClicked() if clicked == None: return item = clicked.item form.name = item.name form.command = item.command form.working = item.working form.folder = item.folder form.icon = item.icon form.populateFields() self.holdOpen = True form.exec_() self.checkMouse() self.holdOpen = False if form.accepted: item.name = form.name item.command = form.command item.working = form.working item.folder = form.folder item.icon = form.icon item.imported = False item.findIcon() self.refresh() def checkMouse(self): if not self.hasMouse(): self.grabMouse() def deleteClicked(self): clicked = self.getClicked() if clicked == None: return self.delete(clicked.item) self.refresh() # Delete item and all of its children so we don't leave around orphaned items def delete(self, item): for i in self.menuItems: if i.parent == item: i.deleted = True if item in self.menuItems: item.deleted = True item.imported = False if item in self.favorites: self.favorites.remove(item) def addFavoriteClicked(self): newFavorite = copy.copy(self.getClicked().item) newFavorite.parent = None self.favorites.append(newFavorite) self.refresh() def getClicked(self): for i in self.allItems: if i.mouseOver: return i def clearMouseOver(self): for i in self.allItems: i.mouseOver = False def clearListMouseOver(self): self.leftList.mouseOver = False self.rightList.mouseOver = False def refresh(self, save = True): self.leftList.clear() self.rightList.clear() self.allItems = [] sortedLeft = [] sortedRight = [] self.updateFilter() if self.currentItem != None: currParent = self.currentItem.parent for i in self.menuItems: if i.parent == currParent and not i.deleted and i.matchedFilter: sortedLeft.append(i) else: for i in self.favorites: sortedLeft.append(i) for i in self.menuItems: if i.parent == self.currentItem and not i.deleted and i.matchedFilter: sortedRight.append(i) sortedLeft.sort(key = lambda x: x.name) sortedLeft.sort(key = lambda x: not x.folder) sortedRight.sort(key = lambda x: x.name) sortedRight.sort(key = lambda x: not x.folder) for i in sortedLeft: self.leftList.add(self.createItem(i)) for i in sortedRight: self.rightList.add(self.createItem(i)) if save: self.saveMenu() def saveMenu(self): # Save the current menu status with open(self.menuFile, 'wb') as f: cPickle.dump(self.menuItems, f) with open(self.favoritesFile, 'wb') as f: cPickle.dump(self.favorites, f) def createItem(self, item): newItem = ListItem(item, self.clearMouseOver) newItem.clicked.connect(self.itemClicked) self.allItems.append(newItem) return newItem def updateFilter(self): filterValue = str(self.filterBox.text()) for i in self.menuItems: i.checkFilter(filterValue) def itemClicked(self): sender = self.sender() if sender.item.folder: self.setCurrentItem(sender.item) self.refresh(False) else: flags = ['f', 'F', 'u', 'U', 'd', 'D', 'n', 'N', 'i', 'k', 'v', 'm'] command = sender.item.command for i in flags: command = command.replace('%' + i, '') # %c needs a proper value in some cases command = command.replace('%c', '"%s"' % sender.item.name) working = sender.item.working if not os.path.isdir(working): working = None # Need to redirect stdout and stderr so if the process writes something it won't fail with open(os.path.devnull, 'w') as devnull: Popen(command + '&', stdout=devnull, stderr=devnull, shell=True, cwd=working) self.hideOrClose() def backClicked(self): if self.currentItem: self.setCurrentItem(self.currentItem.parent) self.refresh(False) def setCurrentItem(self, item): self.currentItem = item if item != None: self.currentLabel.setText(item.name) if item.parent != None: self.backButton.setText(item.parent.name) else: self.backButton.setText('Favorites') else: self.currentLabel.setText('') self.backButton.setText('Favorites') def settingsClicked(self): form = SettingsForm(self) form.quitCheck.setChecked(self.settings['quit']) theme = self.settings.get('iconTheme') if theme: form.themeCombo.setCurrentIndex(form.themeCombo.findText(theme)) self.holdOpen = True form.exec_() self.checkMouse() self.holdOpen = False if form.accepted: self.settings['quit'] = form.quitCheck.isChecked() def firstRun(self): QMessageBox.information(self, 'First Time?', 'Your menu is currently empty. It is recommended that you import an existing menu file.') self.settingsClicked() def connectToRunning(self): self.socket = QLocalSocket() self.socket.connectToServer('nemuSocket') self.socket.waitForConnected(1000) if self.socket.state() == QLocalSocket.ConnectedState: print 'Server found' if self.socket.waitForReadyRead(3000): line = self.socket.readLine() print line else: print self.socket.errorString() sys.exit() else: print 'No server running' def handleConnection(self): import datetime print "Got connection", datetime.datetime.now() connection = self.server.nextPendingConnection() connection.write('connected') del connection self.setCurrentItem(None) self.filterBox.setText('') self.refresh(False) self.show() print "Showed", datetime.datetime.now() return # Call periodically to keep data resident in memory (hopefully) def keepalive(self): if self.isHidden(): self.refresh(False)
return else: self.step = self.step + 1 self.prg.setValue(self.step) self.lab1.setText('正在加载...{}%'.format(self.step)) return # 运行 if __name__ == '__main__': try: app = QApplication(sys.argv) serverName = 'testServer' socket = QLocalSocket() socket.connectToServer(serverName) # 如果连接成功,表明server已经存在,当前已有实例在运行 if socket.waitForConnected(500): press_Data_App() app.quit() else: localServer = QLocalServer() localServer.listen(serverName) win_show = press_Data_App() # win_show.show() # 开机界面 UiSplash = Splash() UiSplash.show() # 开机界面关闭连接打开主界面 UiSplash.splashClose.connect(win_show.windowShow) sys.exit(app.exec_()) except Exception as e: print("程序启动异常:{}".format(e))
def check_server_connection(cls): sock = QLocalSocket() sock.connectToServer(cls.get_sock_name()) if sock.waitForConnected(1000): return IPcReader(sock) return None
class QtSingleApplication(QApplication): """ Adapted from https://stackoverflow.com/a/12712362/11038610 Published by Johan Rade under 2-clause BSD license, opensource.org/licenses/BSD-2-Clause """ message_received_event = pyqtSignal(str) def __init__(self, id, *argv): super().__init__(*argv) self._id = id if sys.platform.startswith('linux'): self.setStyle('Fusion') # Is there another instance running? self._outSocket = QLocalSocket() self._outSocket.connectToServer(self._id) self._isRunning = self._outSocket.waitForConnected() if self._isRunning: # Yes, there is. self._outStream = QTextStream(self._outSocket) self._outStream.setCodec('UTF-8') else: # No, there isn't. self._outSocket = None self._outStream = None self._inSocket = None self._inStream = None self._server = QLocalServer() self._server.removeServer(self._id) self._server.listen(self._id) self._server.newConnection.connect(self._onNewConnection) def isRunning(self): return self._isRunning def id(self): return self._id def sendMessage(self, msg): if not self._outStream: return False self._outStream << msg << '\n' self._outStream.flush() return self._outSocket.waitForBytesWritten() def _onNewConnection(self): if self._inSocket: self._inSocket.readyRead.disconnect(self._onReadyRead) self._inSocket = self._server.nextPendingConnection() if not self._inSocket: return self._inStream = QTextStream(self._inSocket) self._inStream.setCodec('UTF-8') self._inSocket.readyRead.connect(self._onReadyRead) def _onReadyRead(self): while True: msg = self._inStream.readLine() if not msg: break self.message_received_event.emit(msg)
class QtSingleApplication(QApplication): messageReceived = pyqtSignal(str) def __init__(self, _id, _viewer_id, *argv): if sys.platform.startswith( "darwin") and mp.current_process().name == "WebLCDs": import AppKit info = AppKit.NSBundle.mainBundle().infoDictionary( ) # @UndefinedVariable info["LSBackgroundOnly"] = "1" super(QtSingleApplication, self).__init__(*argv) self._id = _id self._viewer_id = _viewer_id self._activationWindow = None self._activateOnMessage = False self._outSocket = None self._isRunning = False self._server = None # we exclude the WebLCDs parallel process from participating any Artisan inter-app communication if mp.current_process().name != "WebLCDs": # Is there another instance running? self._outSocket = QLocalSocket() self._outSocket.connectToServer(self._id) self._isRunning = self._outSocket.waitForConnected(-1) if self._isRunning: # Yes, there is. self._outStream = QTextStream(self._outSocket) self._outStream.setCodec('UTF-8') # Is there another viewer running? self._outSocketViewer = QLocalSocket() self._outSocketViewer.connectToServer(self._viewer_id) self._isRunningViewer = self._outSocketViewer.waitForConnected( -1) if self._isRunningViewer: self._outStreamViewer = QTextStream(self._outSocketViewer) self._outStreamViewer.setCodec('UTF-8') else: # app is running, we announce us as viewer app # First we remove existing servers of that name that might not have been properly closed as the server died QLocalServer.removeServer(self._viewer_id) self._outSocketViewer = None self._outStreamViewer = None self._inSocket = None self._inStream = None self._server = QLocalServer() self._server.listen(self._viewer_id) self._server.newConnection.connect(self._onNewConnection) else: self._isRunningViewer = False # No, there isn't. # First we remove existing servers of that name that might not have been properly closed as the server died QLocalServer.removeServer(self._id) self._outSocket = None self._outStream = None self._inSocket = None self._inStream = None self._server = QLocalServer() self._server.listen(self._id) self._server.newConnection.connect(self._onNewConnection) def isRunning(self): return self._isRunning def isRunningViewer(self): return self._isRunningViewer def id(self): return self._id def activationWindow(self): return self._activationWindow def setActivationWindow(self, activationWindow, activateOnMessage=True): self._activationWindow = activationWindow self._activateOnMessage = activateOnMessage def activateWindow(self): if not self._activationWindow: return self._activationWindow.show() self._activationWindow.setWindowState( self._activationWindow.windowState() & ~Qt.WindowMinimized) self._activationWindow.raise_() self._activationWindow.activateWindow() def sendMessage(self, msg): if not self._outStream: return False self._outStream << msg << '\n' self._outStream.flush() return self._outSocket.waitForBytesWritten() @pyqtSlot() def _onNewConnection(self): if self._inSocket: self._inSocket.readyRead.disconnect(self._onReadyRead) self._inSocket = self._server.nextPendingConnection() if not self._inSocket: return self._inStream = QTextStream(self._inSocket) self._inStream.setCodec('UTF-8') self._inSocket.readyRead.connect(self._onReadyRead) if self._activateOnMessage and self._isRunning: self.activateWindow() @pyqtSlot() def _onReadyRead(self): while True: msg = self._inStream.readLine() if not msg: break self.messageReceived.emit(msg)
class QtSingleApplication(QApplication): """ This class makes sure that we can only start one Tribler application. When a user tries to open a second Tribler instance, the current active one will be brought to front. """ messageReceived = pyqtSignal(text_type) def __init__(self, win_id, *argv): logfunc = logging.info logfunc(sys._getframe().f_code.co_name + '()') QApplication.__init__(self, *argv) self._id = win_id self._activation_window = None self._activate_on_message = False # Is there another instance running? self._outSocket = QLocalSocket() self._outSocket.connectToServer(self._id) self._isRunning = self._outSocket.waitForConnected() self._outStream = None self._inSocket = None self._inStream = None self._server = None if self._isRunning: # Yes, there is. self._outStream = QTextStream(self._outSocket) self._outStream.setCodec('UTF-8') else: # No, there isn't, at least not properly. # Cleanup any past, crashed server. error = self._outSocket.error() logfunc(LOGVARSTR % ('self._outSocket.error()', error)) if error == QLocalSocket.ConnectionRefusedError: logfunc('received QLocalSocket.ConnectionRefusedError; removing server.') self.close() QLocalServer.removeServer(self._id) self._outSocket = None self._server = QLocalServer() self._server.listen(self._id) self._server.newConnection.connect(self._on_new_connection) logfunc(sys._getframe().f_code.co_name + '(): returning') def close(self): logfunc = logging.info logfunc(sys._getframe().f_code.co_name + '()') if self._inSocket: self._inSocket.disconnectFromServer() if self._outSocket: self._outSocket.disconnectFromServer() if self._server: self._server.close() logfunc(sys._getframe().f_code.co_name + '(): returning') def is_running(self): return self._isRunning def get_id(self): return self._id def activation_window(self): return self._activation_window def set_activation_window(self, activation_window, activate_on_message=True): self._activation_window = activation_window self._activate_on_message = activate_on_message def activate_window(self): if not self._activation_window: return self._activation_window.setWindowState( self._activation_window.windowState() & ~Qt.WindowMinimized) self._activation_window.raise_() def send_message(self, msg): if not self._outStream: return False self._outStream << msg << '\n' self._outStream.flush() return self._outSocket.waitForBytesWritten() def _on_new_connection(self): if self._inSocket: self._inSocket.readyRead.disconnect(self._on_ready_read) self._inSocket = self._server.nextPendingConnection() if not self._inSocket: return self._inStream = QTextStream(self._inSocket) self._inStream.setCodec('UTF-8') self._inSocket.readyRead.connect(self._on_ready_read) if self._activate_on_message: self.activate_window() def _on_ready_read(self): while True: msg = self._inStream.readLine() if not msg: break self.messageReceived.emit(msg)
class QtSingleApplication(QApplication): """QApplication que permite solo una instancia de la aplicación. """ messageReceived = pyqtSignal(str) def __init__(self, id, *argv): super(QtSingleApplication, self).__init__(*argv) self._id = id self._activationWindow = None self._activateOnMessage = False # Is there another instance running? self._outSocket = QLocalSocket() self._outSocket.connectToServer(self._id) self._isRunning = self._outSocket.waitForConnected() if self._isRunning: # Yes, there is. self._outStream = QTextStream(self._outSocket) self._outStream.setCodec('UTF-8') else: # No, there isn't. self._outSocket = None self._outStream = None self._inSocket = None self._inStream = None self._server = QLocalServer() self._server.listen(self._id) self._server.newConnection.connect(self._onNewConnection) def isRunning(self): return self._isRunning def id(self): return self._id def activationWindow(self): return self._activationWindow def setActivationWindow(self, activationWindow, activateOnMessage = True): self._activationWindow = activationWindow self._activateOnMessage = activateOnMessage def activateWindow(self): if not self._activationWindow: return self._activationWindow.setWindowState( self._activationWindow.windowState() & ~Qt.WindowMinimized) self._activationWindow.raise_() self._activationWindow.activateWindow() def sendMessage(self, msg): if not self._outStream: return False self._outStream << msg << '\n' # pylint: disable=W0104 self._outStream.flush() return self._outSocket.waitForBytesWritten() def _onNewConnection(self): if self._inSocket: self._inSocket.readyRead.disconnect(self._onReadyRead) self._inSocket = self._server.nextPendingConnection() if not self._inSocket: return self._inStream = QTextStream(self._inSocket) self._inStream.setCodec('UTF-8') self._inSocket.readyRead.connect(self._onReadyRead) if self._activateOnMessage: self.activateWindow() def _onReadyRead(self): while True: msg = self._inStream.readLine() if not msg: break self.messageReceived.emit(msg)
class QtSingleApplication(QApplication): messageReceived = pyqtSignal(str) def __init__(self, id, *argv): super(QtSingleApplication, self).__init__(*argv) self._id = id self._activationWindow = None self._activateOnMessage = False # Is there another instance running? self._outSocket = QLocalSocket() self._outSocket.connectToServer(self._id) self._isRunning = self._outSocket.waitForConnected(-1) if self._isRunning: # Yes, there is. self._outStream = QTextStream(self._outSocket) self._outStream.setCodec('UTF-8') else: # No, there isn't. # First we remoe existing servers of that name that might not have been properly closed as the server died QLocalServer.removeServer(self._id) self._outSocket = None self._outStream = None self._inSocket = None self._inStream = None self._server = QLocalServer() self._server.listen(self._id) self._server.newConnection.connect(self._onNewConnection) def isRunning(self): return self._isRunning def id(self): return self._id def activationWindow(self): return self._activationWindow def setActivationWindow(self, activationWindow, activateOnMessage=True): self._activationWindow = activationWindow self._activateOnMessage = activateOnMessage def activateWindow(self): if not self._activationWindow: return self._activationWindow.show() self._activationWindow.setWindowState( self._activationWindow.windowState() & ~Qt.WindowMinimized) self._activationWindow.raise_() self._activationWindow.activateWindow() def sendMessage(self, msg): if not self._outStream: return False self._outStream << msg << '\n' self._outStream.flush() return self._outSocket.waitForBytesWritten() def _onNewConnection(self): if self._inSocket: self._inSocket.readyRead.disconnect(self._onReadyRead) self._inSocket = self._server.nextPendingConnection() if not self._inSocket: return self._inStream = QTextStream(self._inSocket) self._inStream.setCodec('UTF-8') self._inSocket.readyRead.connect(self._onReadyRead) if self._activateOnMessage: self.activateWindow() def _onReadyRead(self): while True: msg = self._inStream.readLine() if not msg: break self.messageReceived.emit(msg)
def send_to_running_instance(socketname, command, target_arg, *, legacy_name=None, socket=None): """Try to send a commandline to a running instance. Blocks for CONNECT_TIMEOUT ms. Args: socketname: The name which should be used for the socket. command: The command to send to the running instance. target_arg: --target command line argument socket: The socket to read data from, or None. legacy_name: The legacy name to first try to connect to. Return: True if connecting was successful, False if no connection was made. """ if socket is None: socket = QLocalSocket() if (legacy_name is not None and _has_legacy_server(legacy_name)): name_to_use = legacy_name else: name_to_use = socketname log.ipc.debug("Connecting to {}".format(name_to_use)) socket.connectToServer(name_to_use) connected = socket.waitForConnected(CONNECT_TIMEOUT) if connected: log.ipc.info("Opening in existing instance") json_data = { 'args': command, 'target_arg': target_arg, 'version': qutebrowser.__version__, 'protocol_version': PROTOCOL_VERSION } try: cwd = os.getcwd() except OSError: pass else: json_data['cwd'] = cwd line = json.dumps(json_data) + '\n' data = line.encode('utf-8') log.ipc.debug("Writing: {}".format(data)) socket.writeData(data) socket.waitForBytesWritten(WRITE_TIMEOUT) if socket.error() != QLocalSocket.UnknownSocketError: raise SocketError("writing to running instance", socket) else: socket.disconnectFromServer() if socket.state() != QLocalSocket.UnconnectedState: socket.waitForDisconnected(CONNECT_TIMEOUT) return True else: if socket.error() not in (QLocalSocket.ConnectionRefusedError, QLocalSocket.ServerNotFoundError): raise SocketError("connecting to running instance", socket) else: log.ipc.debug("No existing instance present (error {})".format( socket.error())) return False
class QtSingleApplication(QApplication): messageReceived = pyqtSignal(str) def __init__(self, id, *argv): super(QtSingleApplication, self).__init__(*argv) self._id = id self._activationWindow = None self._activateOnMessage = False # Is there another instance running? self._outSocket = QLocalSocket() self._outSocket.connectToServer(self._id) self._isRunning = self._outSocket.waitForConnected() if self._isRunning: # Yes, there is. self._outStream = QTextStream(self._outSocket) self._outStream.setCodec("UTF-8") else: # No, there isn't. self._outSocket = None self._outStream = None self._inSocket = None self._inStream = None self._server = QLocalServer() self._server.listen(self._id) self._server.newConnection.connect(self._onNewConnection) def isRunning(self): return self._isRunning def id(self): return self._id def activationWindow(self): return self._activationWindow def setActivationWindow(self, activationWindow, activateOnMessage=True): self._activationWindow = activationWindow self._activateOnMessage = activateOnMessage def activateWindow(self): if not self._activationWindow: return self._activationWindow.show() self._activationWindow.setWindowState(self._activationWindow.windowState() & ~Qt.WindowMinimized) self._activationWindow.raise_() self._activationWindow.activateWindow() def sendMessage(self, msg): if not self._outStream: return False self._outStream << msg << "\n" self._outStream.flush() return self._outSocket.waitForBytesWritten() def _onNewConnection(self): if self._inSocket: self._inSocket.readyRead.disconnect(self._onReadyRead) self._inSocket = self._server.nextPendingConnection() if not self._inSocket: return self._inStream = QTextStream(self._inSocket) self._inStream.setCodec("UTF-8") self._inSocket.readyRead.connect(self._onReadyRead) if self._activateOnMessage: self.activateWindow() def _onReadyRead(self): while True: msg = self._inStream.readLine() if not msg: break self.messageReceived.emit(msg)
class Eddy(QApplication): """ This class implements the main Qt application. """ messageReceived = pyqtSignal(str) def __init__(self, argv): """ Initialize Eddy. :type argv: list """ super().__init__(argv) parser = ArgumentParser() parser.add_argument('--nosplash', dest='nosplash', action='store_true') parser.add_argument('--tests', dest='tests', action='store_true') options, args = parser.parse_known_args(args=argv) self.inSocket = None self.inStream = None self.outSocket = QLocalSocket() self.outSocket.connectToServer(APPID) self.outStream = None self.isRunning = self.outSocket.waitForConnected() self.mainwindow = None self.pendingOpen = [] self.server = None # We do not initialize a new instance of Eddy if there is a process running # and we are not executing the tests suite: we'll create a socket instead so we can # exchange messages between the 2 processes (this one and the already running one). if self.isRunning and not options.tests: self.outStream = QTextStream(self.outSocket) self.outStream.setCodec('UTF-8') else: self.server = QLocalServer() self.server.listen(APPID) self.outSocket = None self.outStream = None connect(self.server.newConnection, self.newConnection) connect(self.messageReceived, self.readMessage) ############################################################################################################ # # # PERFORM EDDY INITIALIZATION # # # ############################################################################################################ # Draw the splashscreen. self.splashscreen = None if not options.nosplash: self.splashscreen = SplashScreen(min_splash_time=4) self.splashscreen.show() # Setup layout. self.setStyle(Clean('Fusion')) with open(expandPath('@eddy/ui/clean.qss')) as sheet: self.setStyleSheet(sheet.read()) # Create the main window. self.mainwindow = MainWindow() # Close the splashscreen. if self.splashscreen: self.splashscreen.wait(self.splashscreen.remaining) self.splashscreen.close() # Display the mainwindow. self.mainwindow.show() if Platform.identify() is Platform.Darwin: # On MacOS files being opened are handled as a QFileOpenEvent but since we don't # have a Main Window initialized we store them locally and we open them here. for filepath in self.pendingOpen: self.openFile(filepath) self.pendingOpen = [] else: # Perform document opening if files have been added to sys.argv. This is not # executed on Mac OS since this is already handled as a QFileOpenEvent instance. for filepath in argv: self.openFile(filepath) #################################################################################################################### # # # EVENTS # # # #################################################################################################################### def event(self, event): """ Executed when an event is received. :type event: T <= QEvent | QFileOpenEvent """ if event.type() == QEvent.FileOpen: self.pendingOpen = [event.file()] return True return super().event(event) #################################################################################################################### # # # INTERFACE # # # #################################################################################################################### def activate(self): """ Activate the application by raising the main window. """ if self.mainwindow: self.mainwindow.setWindowState((self.mainwindow.windowState() & ~Qt.WindowMinimized) | Qt.WindowActive) self.mainwindow.activateWindow() self.mainwindow.raise_() def openFile(self, filepath): """ Open the given file in the activation window. :type filepath: str :rtype: bool """ if self.mainwindow: if not isEmpty(filepath) and os.path.isfile( filepath) and filepath.endswith( Filetype.Graphol.extension): self.mainwindow.openFile(filepath) return True return False def sendMessage(self, message): """ Send a message to the other alive Eddy's process. :type message: str :rtype: bool """ if self.outStream: self.outStream = self.outStream << message << '\n' self.outStream.flush() return self.outSocket.waitForBytesWritten() return False #################################################################################################################### # # # SLOTS # # # #################################################################################################################### @pyqtSlot() def newConnection(self): """ Executed whenever a message is received. """ if self.inSocket: # Disconnect previously connected signal slot. disconnect(self.inSocket.readyRead, self.readyRead) # Create a new socket. self.inSocket = self.server.nextPendingConnection() if self.inSocket: self.inStream = QTextStream(self.inSocket) self.inStream.setCodec('UTF-8') connect(self.inSocket.readyRead, self.readyRead) self.activate() @pyqtSlot() def readyRead(self): """ Executed whenever we need to read a message. """ while True: message = self.inStream.readLine() if isEmpty(message): break self.messageReceived.emit(message) @pyqtSlot(str) def readMessage(self, message): """ Read a received message. :type message: str """ for filepath in message.split(' '): self.openFile(filepath)
class QtSingleApplication(QApplication): """ This class makes sure that we can only start one Tribler application. When a user tries to open a second Tribler instance, the current active one will be brought to front. """ messageReceived = pyqtSignal(unicode) def __init__(self, win_id, *argv): logfunc = logging.info logfunc(sys._getframe().f_code.co_name + '()') QApplication.__init__(self, *argv) self._id = win_id self._activation_window = None self._activate_on_message = False # Is there another instance running? self._outSocket = QLocalSocket() self._outSocket.connectToServer(self._id) self._isRunning = self._outSocket.waitForConnected() self._outStream = None self._inSocket = None self._inStream = None self._server = None if self._isRunning: # Yes, there is. self._outStream = QTextStream(self._outSocket) self._outStream.setCodec('UTF-8') else: # No, there isn't, at least not properly. # Cleanup any past, crashed server. error = self._outSocket.error() logfunc(LOGVARSTR % ('self._outSocket.error()', error)) if error == QLocalSocket.ConnectionRefusedError: logfunc('received QLocalSocket.ConnectionRefusedError; ' + \ 'removing server.') self.close() QLocalServer.removeServer(self._id) self._outSocket = None self._server = QLocalServer() self._server.listen(self._id) self._server.newConnection.connect(self._on_new_connection) logfunc(sys._getframe().f_code.co_name + '(): returning') def close(self): logfunc = logging.info logfunc(sys._getframe().f_code.co_name + '()') if self._inSocket: self._inSocket.disconnectFromServer() if self._outSocket: self._outSocket.disconnectFromServer() if self._server: self._server.close() logfunc(sys._getframe().f_code.co_name + '(): returning') def is_running(self): return self._isRunning def get_id(self): return self._id def activation_window(self): return self._activation_window def set_activation_window(self, activation_window, activate_on_message=True): self._activation_window = activation_window self._activate_on_message = activate_on_message def activate_window(self): if not self._activation_window: return self._activation_window.setWindowState( self._activation_window.windowState() & ~Qt.WindowMinimized) self._activation_window.raise_() def send_message(self, msg): if not self._outStream: return False self._outStream << msg << '\n' self._outStream.flush() return self._outSocket.waitForBytesWritten() def _on_new_connection(self): if self._inSocket: self._inSocket.readyRead.disconnect(self._on_ready_read) self._inSocket = self._server.nextPendingConnection() if not self._inSocket: return self._inStream = QTextStream(self._inSocket) self._inStream.setCodec('UTF-8') self._inSocket.readyRead.connect(self._on_ready_read) if self._activate_on_message: self.activate_window() def _on_ready_read(self): while True: msg = self._inStream.readLine() if not msg: break self.messageReceived.emit(msg)
class QSingleApplication(QApplication): messageReceived = pyqtSignal(str) def __init__(self, name, *args, **kwargs): super(QSingleApplication, self).__init__(*args, **kwargs) self._socketName = name self._activationWindow = None self._socketServer = None self._socketIn = None self._socketOut = None self._running = False # 先尝试连接 self._socketOut = QLocalSocket(self) self._socketOut.connectToServer(self._socketName) self._socketOut.error.connect(self.handleError) self._running = self._socketOut.waitForConnected() if not self._running: # 程序未运行 self._socketOut.close() del self._socketOut # 创建本地server self._socketServer = QLocalServer(self) self._socketServer.listen(self._socketName) self._socketServer.newConnection.connect(self._onNewConnection) self.aboutToQuit.connect(self.removeServer) def handleError(self, message): print("handleError message: ", message) def isRunning(self): return self._running def activationWindow(self): return self._activationWindow def setActivationWindow(self, activationWindow): # 设置需要激活的窗口 self._activationWindow = activationWindow def activateWindow(self): try: self._activationWindow.setWindowState( self._activationWindow.windowState() & ~Qt.WindowMinimized) # self._activationWindow.raise_() self._activationWindow.showNormal() self._activationWindow.activateWindow() except Exception as e: print(e) def sendMessage(self, message, msecs=5000): if not self._socketOut: return False if not isinstance(message, bytes): message = str(message).encode() self._socketOut.write(message) if not self._socketOut.waitForBytesWritten(msecs): raise Exception("Bytes not written within %ss" % (msecs / 1000.)) return True def _onNewConnection(self): if self._socketIn: self._socketIn.readyRead.disconnect(self._onReadyRead) self._socketIn = self._socketServer.nextPendingConnection() if not self._socketIn: return self._socketIn.readyRead.connect(self._onReadyRead) def _onReadyRead(self): while 1: message = self._socketIn.readLine() if not message: break if message == b'show': self.activateWindow() self.messageReceived.emit(message.data().decode()) def removeServer(self): self._socketServer.close() self._socketServer.removeServer(self._socketName)