Browse Source

Fix recent qt or pyqt 5.15 segfault regarding mutliple QApplications

master
Nils 4 years ago
parent
commit
98c22ad292
  1. 4
      template/documentation/build.py
  2. 4
      template/documentation/german.adoc.template
  3. 3
      template/qtgui/about.py
  4. 6
      template/qtgui/chooseSessionDirectory.py
  5. 2
      template/qtgui/helper.py
  6. 6
      template/qtgui/mainwindow.py
  7. 31
      template/start.py

4
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 #Make the readme
import sys import sys

4
template/documentation/german.adoc.template

@ -42,7 +42,7 @@ Falls nicht kann man <name> auch selbst "bauen".
.Abhängigkeiten* .Abhängigkeiten*
* Eine Liste der Abhängigkeit befindet sich in der README.md * Eine Liste der Abhängigkeit befindet sich in der README.md
* Kompilieren und Installieren geht entweder mit einem Releasedownload oder mit der Git-Version: * 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/<shortName>.git` ** `git clone https://git.laborejo.org/lss/<shortName>.git`
* Wechseln Sie in das neue Verzeichnis und benutzen diese Befehle: * Wechseln Sie in das neue Verzeichnis und benutzen diese Befehle:
*`./configure --prefix=/usr` *`./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. * 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) * 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. 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 `<file>translations/de.qm</file>` . Dabei das Länderkürzel zum Neuen ändern. * 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 `<file>translations/de.qm</file>` . Dabei das Länderkürzel zum Neuen ändern.

3
template/qtgui/about.py

@ -80,7 +80,7 @@ class About(QtWidgets.QDialog):
aboutLogoPixmap = QtGui.QPixmap(":aboutlogo.png") aboutLogoPixmap = QtGui.QPixmap(":aboutlogo.png")
#pixmap_scaled = aboutLogoPixmap.scaled(self.ui.goldenratioLabel.size(), QtCore.Qt.KeepAspectRatio) #pixmap_scaled = aboutLogoPixmap.scaled(self.ui.goldenratioLabel.size(), QtCore.Qt.KeepAspectRatio)
#self.ui.goldenratioLabel.setPixmap(pixmap_scaled) #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. #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.showOnStartup.setChecked(settings.value("showAboutDialog", type=bool))
self.ui.numberSlider.setFocus(True) self.ui.numberSlider.setFocus(True)
def tricks(self): def tricks(self):
"""For some reason translations do not work if saved as class variable. """For some reason translations do not work if saved as class variable.

6
template/qtgui/chooseSessionDirectory.py

@ -51,7 +51,7 @@ class ChooseSessionDirectory(QtWidgets.QDialog):
qtApp.installTranslator(templateTranslator) qtApp.installTranslator(templateTranslator)
super().__init__() #no parent, this is the top level window at this time. super().__init__() #no parent, this is the top level window at this time.
self.qtApp = qtApp
self.setModal(True) #block until closed self.setModal(True) #block until closed
self.ui = Ui_TemplateChooseSessionDirectory() self.ui = Ui_TemplateChooseSessionDirectory()
self.ui.setupUi(self) self.ui.setupUi(self)
@ -84,7 +84,7 @@ class ChooseSessionDirectory(QtWidgets.QDialog):
self.ui.openFileDialogButton.setText("") self.ui.openFileDialogButton.setText("")
self.ui.openFileDialogButton.setIcon(self.style().standardIcon(getattr(QtWidgets.QStyle, "SP_DialogOpenButton"))) self.ui.openFileDialogButton.setIcon(self.style().standardIcon(getattr(QtWidgets.QStyle, "SP_DialogOpenButton")))
self.ui.openFileDialogButton.clicked.connect(self.requestPathFromDialog) self.ui.openFileDialogButton.clicked.connect(self.requestPathFromDialog)
self.exec() self.exec()
def requestPathFromDialog(self): def requestPathFromDialog(self):
@ -107,7 +107,7 @@ class ChooseSessionDirectory(QtWidgets.QDialog):
if not self.path in self.recentDirList: if not self.path in self.recentDirList:
self.recentDirList.append(self.path) self.recentDirList.append(self.path)
settings.setValue("recentDirectoriesWithouNSM", self.recentDirList) settings.setValue("recentDirectoriesWithouNSM", self.recentDirList)
super().accept() super().accept()
def reject(self): def reject(self):
self.path = None self.path = None

2
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 <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import logging; logger = logging.getLogger(__name__); logger.info("import")
from PyQt5 import QtGui, QtWidgets from PyQt5 import QtGui, QtWidgets
from hashlib import md5 from hashlib import md5

6
template/qtgui/mainwindow.py

@ -40,8 +40,7 @@ from .menu import Menu
from .resources import * from .resources import *
from .about import About from .about import About
from .helper import setPaletteAndFont from .helper import setPaletteAndFont
from template.start import PATHS from template.start import PATHS, qtApp
#Client modules #Client modules
from engine.config import * #imports METADATA from engine.config import * #imports METADATA
import engine.api as api #This loads the engine and starts a session. 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 #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.setDesktopSettingsAware(False) #We need our own font so the user interface stays predictable
QtGui.QGuiApplication.setDesktopFileName(PATHS["desktopfile"]) 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 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 = 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) self.debugScriptRunner.trueInit(nsmClient=self.nsmClient)
#Show the About Dialog the first time the program starts up. #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) #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"]) settings = QtCore.QSettings("LaborejoSoftwareSuite", METADATA["shortName"])

31
template/start.py

@ -135,18 +135,19 @@ else:
logger.info("PATHS: {}".format(PATHS)) logger.info("PATHS: {}".format(PATHS))
from PyQt5.QtWidgets import QApplication
qtApp = QApplication(sys.argv)
setPaletteAndFont(qtApp)
def exitWithMessage(message:str): def exitWithMessage(message:str):
title = f"""{METADATA["name"]} Error""" title = f"""{METADATA["name"]} Error"""
if sys.stdout.isatty(): if sys.stdout.isatty():
sys.exit(title + ": " + message) sys.exit(title + ": " + message)
else: 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. #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) QMessageBox.critical(qtApp.desktop(), title, message)
setPaletteAndFont(qErrorApp)
QMessageBox.critical(qErrorApp.desktop(), title, message)
qErrorApp.quit()
sys.exit(title + ": " + message) sys.exit(title + ": " + message)
def setProcessName(executableName): def setProcessName(executableName):
@ -172,19 +173,17 @@ def checkNsmOrExit(prettyName):
import sys import sys
from os import getenv from os import getenv
if not getenv("NSM_URL"): #NSMClient checks for this itself but we can anticipate an error and inform the user. 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
path = ChooseSessionDirectory(qtApp).path #ChooseSessionDirectory is calling exec. We can't call qtapp.exec_ because that blocks forever, even after quitting the window.
qSessionDirApp = QApplication(sys.argv) #qSessionDirApp.quit()
setPaletteAndFont(qSessionDirApp) #del qSessionDirApp
pathDialog = ChooseSessionDirectory(qSessionDirApp) #path = "/tmp"
qSessionDirApp.quit() #pathDialog somehow survives
if path:
if pathDialog.path: startPseudoNSMServer(path)
startPseudoNSMServer(pathDialog.path)
else: else:
sys.exit() sys.exit()
#message = f"""Please start {prettyName} only through the Non Session Manager (NSM) or use the --save command line parameter.""" #message = f"""Please start {prettyName} only through the Non Session Manager (NSM) or use the --save command line parameter."""
#exitWithMessage(message) #exitWithMessage(message)

Loading…
Cancel
Save