Nils
3 years ago
7 changed files with 169 additions and 4 deletions
@ -0,0 +1,160 @@ |
|||
#! /usr/bin/env python3 |
|||
# -*- coding: utf-8 -*- |
|||
""" |
|||
Copyright 2022, Nils Hilbricht, Germany ( https://www.hilbricht.net ) |
|||
|
|||
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ). |
|||
|
|||
This application is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
""" |
|||
|
|||
import logging; logger = logging.getLogger(__name__); logger.info("import") |
|||
|
|||
#Standard Library |
|||
import pathlib |
|||
from os import getenv, listdir |
|||
from sys import argv as sysargv |
|||
|
|||
|
|||
#Third Party |
|||
from PyQt5 import QtCore, QtGui, QtWidgets |
|||
|
|||
#Our own files |
|||
from .movesessionroot import nsmVersionGreater160 |
|||
|
|||
|
|||
def checkForRunningNsmd(qtApp, PATHS:dict): |
|||
"""Before we start the engine with our own nsmd server: |
|||
nsmd >= 1.6.0 introduced run file discovery of sessions and empty nsmd. |
|||
|
|||
Ask the user if they want to connect to one of these. |
|||
|
|||
Injects the path into PATHS["url"], which is used by engine.api.startEngine() |
|||
""" |
|||
|
|||
|
|||
if PATHS["url"] or any("url" in param for param in sysargv): #this is really the same test twice... |
|||
#This is not our problem anymore. |
|||
return |
|||
|
|||
|
|||
if not nsmVersionGreater160(): |
|||
return #see docstring |
|||
|
|||
parent = qtApp.desktop() |
|||
|
|||
|
|||
if not getenv("XDG_RUNTIME_DIR"): |
|||
logger.warning("Your system has no environment variable $XDG_RUNTIME_DIR. That is unusual for Linux. Automatic detection of already running sessions deactivated.") |
|||
return #On Linux that should exist. But if not, no reason to crash. |
|||
|
|||
|
|||
logger.info("Detecting if there are already nsmd or sessions running under this user") |
|||
|
|||
session_rundir = pathlib.Path(getenv("XDG_RUNTIME_DIR"), "nsm") |
|||
logger.info(f"Supposed nsmd session rundir: {session_rundir}") |
|||
nsmd_rundir = pathlib.Path(getenv("XDG_RUNTIME_DIR"), "nsm", "d") |
|||
logger.info(f"Supposed nsmd server rundir: {nsmd_rundir}") |
|||
|
|||
if not session_rundir.exists() or not session_rundir.is_dir(): |
|||
logger.info("nsmd rundir does not exist. Continue.") |
|||
return |
|||
|
|||
existing_daemons = listdir(nsmd_rundir) |
|||
existing_sessions = listdir(session_rundir) |
|||
if existing_sessions: |
|||
existing_sessions.remove("d") #Remove the daemon subdir |
|||
|
|||
if not existing_daemons: |
|||
logger.info("nsmd rundir exist, but is empty. Continue.") |
|||
return #if there are no daemons there are no sessions. |
|||
|
|||
#There are nsmd running under this user, maybe even open sessions. |
|||
#Now build a list for the user to choose from. |
|||
#If a session is running on an nsmd show this, otherwise show the empty nsmd |
|||
sessions = [] |
|||
nsmd_pids = set() |
|||
for s in existing_sessions: |
|||
res = {} |
|||
sessions.append(res) |
|||
with open(pathlib.Path(session_rundir, s), "r") as f: |
|||
res["hashName"] = s #name of the lockfile. has hash postfix. |
|||
res["path"] = pathlib.Path(f.readline().strip("\n")) #file path in ~/.local/share/nsm |
|||
res["name"] = res["path"].name #present this to the user. |
|||
res["url"] = f.readline().strip("\n") #nsmd url |
|||
res["pid"] = int(f.readline().strip("\n")) #nsmd pid |
|||
nsmd_pids.add(res["pid"]) |
|||
|
|||
|
|||
daemons = [] |
|||
for d in existing_daemons: |
|||
#d is a file with a PID as name. e.g. 9627 |
|||
#inside is the NSM_URL. |
|||
if int(d) in nsmd_pids: #we already have a running session on this server |
|||
continue |
|||
else: #empty nsmd. |
|||
res = {} |
|||
daemons.append(res) |
|||
with open(pathlib.Path(nsmd_rundir, d), "r") as f: |
|||
res["pid"] = d |
|||
res["url"] = f.readline().strip("\n") #just the first line |
|||
res["name"] = QtCore.QCoreApplication.translate("StartChooseRunningSession", "Empty Server") + " " + res["url"] |
|||
|
|||
#We now have all empty nsmd in var daemons |
|||
|
|||
assert sessions or daemons |
|||
|
|||
PATHS["url"] = ChooseSessionWidget(qtApp, sessions+daemons).url #"Global Variable" |
|||
|
|||
|
|||
class ChooseSessionWidget(QtWidgets.QDialog): |
|||
"""return value in self.url. Might be None""" |
|||
|
|||
def __init__(self, qtApp, sessionDicts:list): |
|||
|
|||
super().__init__() #QDialog can't parent to qtApp |
|||
|
|||
self.qtApp = qtApp |
|||
self.setModal(True) #block until closed |
|||
|
|||
self.layout = QtWidgets.QVBoxLayout() |
|||
self.setLayout(self.layout) |
|||
|
|||
self.label = QtWidgets.QLabel(self) |
|||
self.label.setText(QtCore.QCoreApplication.translate("StartChooseRunningSession", "Select session or server to connect to.\nCancel to start our own server.")) |
|||
self.layout.addWidget(self.label) |
|||
|
|||
self.comboBox = QtWidgets.QComboBox(self) |
|||
self.layout.addWidget(self.comboBox) |
|||
|
|||
for s in sessionDicts: |
|||
self.comboBox.addItem(s["name"], s["url"]) #Show name, use url as data. |
|||
|
|||
self.buttonBox = QtWidgets.QDialogButtonBox(self) |
|||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal) |
|||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) |
|||
self.buttonBox.setObjectName("buttonBox") |
|||
self.layout.addWidget(self.buttonBox) |
|||
self.buttonBox.accepted.connect(self.accept) |
|||
self.buttonBox.rejected.connect(self.reject) |
|||
|
|||
self.exec() |
|||
|
|||
def accept(self): |
|||
self.url = self.comboBox.currentData() #easy abstraction so that the caller does not need to know our widget name |
|||
super().accept() |
|||
|
|||
def reject(self): |
|||
self.url = None |
|||
super().reject() |
Loading…
Reference in new issue