From 5d095454abfc90693c4efb514a85b9bfb0c85224 Mon Sep 17 00:00:00 2001 From: Nils <> Date: Sat, 6 Jun 2020 10:26:44 +0200 Subject: [PATCH] Fix recent qt or pyqt 5.15 segfault regarding mutliple QApplications --- template/documentation/build.py | 4 +++ template/documentation/german.adoc.template | 4 +-- template/qtgui/about.py | 3 +- template/qtgui/chooseSessionDirectory.py | 6 ++-- template/qtgui/helper.py | 2 ++ template/qtgui/mainwindow.py | 6 ++-- template/start.py | 31 ++++++++++----------- 7 files changed, 30 insertions(+), 26 deletions(-) diff --git a/template/documentation/build.py b/template/documentation/build.py index 976e9cf..4a92c4f 100644 --- a/template/documentation/build.py +++ b/template/documentation/build.py @@ -14,6 +14,10 @@ The correct out/ dir is already part of git. """ +#We still split between template and non-template, eventhough this is not the case in Argodejo. +#However, this enables an easier diff across projects to keep track of changes that we need to do manually here +#TODO: Unify in the future by creating calfbox and NSM client as documentation "modules" + #Make the readme import sys diff --git a/template/documentation/german.adoc.template b/template/documentation/german.adoc.template index 2ecd37f..5a7ff50 100644 --- a/template/documentation/german.adoc.template +++ b/template/documentation/german.adoc.template @@ -42,7 +42,7 @@ Falls nicht kann man auch selbst "bauen". .Abhängigkeiten* * Eine Liste der Abhängigkeit befindet sich in der README.md * Kompilieren und Installieren geht entweder mit einem Releasedownload oder mit der Git-Version: - ** Lade von https://www.laborejo.org/downloads die aktuelle Version herunter und entpacke sie. + ** Laden Sie von https://www.laborejo.org/downloads die aktuelle Version herunter und entpacken Sie sie. ** `git clone https://git.laborejo.org/lss/.git` * Wechseln Sie in das neue Verzeichnis und benutzen diese Befehle: *`./configure --prefix=/usr` @@ -107,7 +107,7 @@ So fügt man eine neue Sprache hinzu: * Wählen Sie die "Target Language", also Zielsprache, aus und benutzen das Programm um eine Übersetzung anzufertigen. * Senden Sie uns bitte die .ts Datei, z.B. per E-Mail an info@laborejo.org (s.u bei Bugs und Programmfehler für mehr Kontaktmöglichkeiten) -Die Übersetzung können Sie auch selbst, zum Testen, in Patroneo einbinden. Dafür sind rudimentäre +Die Übersetzung können Sie auch selbst, zum Testen, einbinden. Dafür sind rudimentäre Python Kentnisse nötig. * Im Qt Linguist "Datei" Menü ist eine "Release" Option. Das erstellt eine `.qm` Datei im gleichen Verzeichnis wie die `.ts` Datei.* Bearbeiten Sie `template/qtgui/resources/resources.qrc` und kopieren die Zeile `translations/de.qm` . Dabei das Länderkürzel zum Neuen ändern. diff --git a/template/qtgui/about.py b/template/qtgui/about.py index 34a693e..9dc66d6 100644 --- a/template/qtgui/about.py +++ b/template/qtgui/about.py @@ -80,7 +80,7 @@ class About(QtWidgets.QDialog): aboutLogoPixmap = QtGui.QPixmap(":aboutlogo.png") #pixmap_scaled = aboutLogoPixmap.scaled(self.ui.goldenratioLabel.size(), QtCore.Qt.KeepAspectRatio) #self.ui.goldenratioLabel.setPixmap(pixmap_scaled) - self.ui.goldenratioLabel.setPixmap(aboutLogoPixmap) + self.ui.goldenratioLabel.setPixmap(aboutLogoPixmap) """ #We don't want the user to get bombarded with information on the first start. @@ -115,6 +115,7 @@ class About(QtWidgets.QDialog): self.ui.showOnStartup.setChecked(settings.value("showAboutDialog", type=bool)) self.ui.numberSlider.setFocus(True) + def tricks(self): """For some reason translations do not work if saved as class variable. diff --git a/template/qtgui/chooseSessionDirectory.py b/template/qtgui/chooseSessionDirectory.py index 391e9b2..1da95cb 100644 --- a/template/qtgui/chooseSessionDirectory.py +++ b/template/qtgui/chooseSessionDirectory.py @@ -51,7 +51,7 @@ class ChooseSessionDirectory(QtWidgets.QDialog): qtApp.installTranslator(templateTranslator) super().__init__() #no parent, this is the top level window at this time. - + self.qtApp = qtApp self.setModal(True) #block until closed self.ui = Ui_TemplateChooseSessionDirectory() self.ui.setupUi(self) @@ -84,7 +84,7 @@ class ChooseSessionDirectory(QtWidgets.QDialog): self.ui.openFileDialogButton.setText("") self.ui.openFileDialogButton.setIcon(self.style().standardIcon(getattr(QtWidgets.QStyle, "SP_DialogOpenButton"))) self.ui.openFileDialogButton.clicked.connect(self.requestPathFromDialog) - self.exec() + self.exec() def requestPathFromDialog(self): @@ -107,7 +107,7 @@ class ChooseSessionDirectory(QtWidgets.QDialog): if not self.path in self.recentDirList: self.recentDirList.append(self.path) settings.setValue("recentDirectoriesWithouNSM", self.recentDirList) - super().accept() + super().accept() def reject(self): self.path = None diff --git a/template/qtgui/helper.py b/template/qtgui/helper.py index 5184057..f4fc1f9 100644 --- a/template/qtgui/helper.py +++ b/template/qtgui/helper.py @@ -19,6 +19,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ +import logging; logger = logging.getLogger(__name__); logger.info("import") + from PyQt5 import QtGui, QtWidgets from hashlib import md5 diff --git a/template/qtgui/mainwindow.py b/template/qtgui/mainwindow.py index 29e14de..e057133 100644 --- a/template/qtgui/mainwindow.py +++ b/template/qtgui/mainwindow.py @@ -40,8 +40,7 @@ from .menu import Menu from .resources import * from .about import About from .helper import setPaletteAndFont -from template.start import PATHS - +from template.start import PATHS, qtApp #Client modules from engine.config import * #imports METADATA import engine.api as api #This loads the engine and starts a session. @@ -51,7 +50,7 @@ from qtgui.resources import * #Construct QAppliction before constantsAndCOnfigs, which has the fontDB QtGui.QGuiApplication.setDesktopSettingsAware(False) #We need our own font so the user interface stays predictable QtGui.QGuiApplication.setDesktopFileName(PATHS["desktopfile"]) -qtApp = QtWidgets.QApplication(sysargv) +#qtApp imported from template.engine.start. Since Qt 5.15 or PyQt 5.15 you really can't have only one QApplication during program lifetime, even if you try to quit and del the first one. from qtgui.constantsAndConfigs import constantsAndConfigs @@ -167,7 +166,6 @@ class MainWindow(QtWidgets.QMainWindow): self.debugScriptRunner = DebugScriptRunner(apilocals=locals()) #needs to have trueInit called after the session and nsm was set up. Which happens in startEngine. self.debugScriptRunner.trueInit(nsmClient=self.nsmClient) - #Show the About Dialog the first time the program starts up. #This is the initial state user/system wide and not a saved in NSM nor bound to the NSM ID (like window position) settings = QtCore.QSettings("LaborejoSoftwareSuite", METADATA["shortName"]) diff --git a/template/start.py b/template/start.py index 481d251..09ba7eb 100644 --- a/template/start.py +++ b/template/start.py @@ -135,18 +135,19 @@ else: logger.info("PATHS: {}".format(PATHS)) +from PyQt5.QtWidgets import QApplication +qtApp = QApplication(sys.argv) +setPaletteAndFont(qtApp) + def exitWithMessage(message:str): title = f"""{METADATA["name"]} Error""" if sys.stdout.isatty(): sys.exit(title + ": " + message) else: - from PyQt5.QtWidgets import QMessageBox, QApplication + from PyQt5.QtWidgets import QMessageBox #This is the start file for the Qt client so we know at least that Qt is installed and use that for a warning. - qErrorApp = QApplication(sys.argv) - setPaletteAndFont(qErrorApp) - QMessageBox.critical(qErrorApp.desktop(), title, message) - qErrorApp.quit() + QMessageBox.critical(qtApp.desktop(), title, message) sys.exit(title + ": " + message) def setProcessName(executableName): @@ -172,19 +173,17 @@ def checkNsmOrExit(prettyName): import sys from os import getenv if not getenv("NSM_URL"): #NSMClient checks for this itself but we can anticipate an error and inform the user. - from PyQt5.QtWidgets import QMessageBox, QApplication - - qSessionDirApp = QApplication(sys.argv) - setPaletteAndFont(qSessionDirApp) - pathDialog = ChooseSessionDirectory(qSessionDirApp) - qSessionDirApp.quit() #pathDialog somehow survives - - if pathDialog.path: - startPseudoNSMServer(pathDialog.path) + + path = ChooseSessionDirectory(qtApp).path #ChooseSessionDirectory is calling exec. We can't call qtapp.exec_ because that blocks forever, even after quitting the window. + #qSessionDirApp.quit() + #del qSessionDirApp + #path = "/tmp" + + if path: + startPseudoNSMServer(path) else: sys.exit() - - + #message = f"""Please start {prettyName} only through the Non Session Manager (NSM) or use the --save command line parameter.""" #exitWithMessage(message)