diff --git a/lyse/__main__.py b/lyse/__main__.py
index be6c02c..edb5037 100644
--- a/lyse/__main__.py
+++ b/lyse/__main__.py
@@ -14,6 +14,7 @@
"""
import os
import labscript_utils.excepthook
+import importlib.metadata
# Associate app windows with OS menu shortcuts, must be before any GUI calls, apparently
import desktop_app
@@ -49,9 +50,11 @@
# qt imports
splash.update_text('importing qt modules')
-from qtutils.qt import QtCore, QtWidgets
+from qtutils.qt import QtCore, QtWidgets, QT_ENV
from qtutils.qt.QtCore import pyqtSignal as Signal
from qtutils import UiLoader
+QT_VERSION_STR = QtCore.qVersion()
+PYQT_VERSION_STR = importlib.metadata.version(QT_ENV)
# needs to be present so that qtutils icons referenced in .ui files can be resolved. Since this is
# magical is should not be implemented in this way.
@@ -104,6 +107,9 @@ def __init__(self, qapplication):
self.logger = setup_logging('lyse')
labscript_utils.excepthook.set_logger(self.logger)
self.logger.info('\n\n===============starting===============\n')
+ self.logger.info(f'Qt Environment: {QT_ENV}')
+ self.logger.info(f'PySide/PyQt version: {PYQT_VERSION_STR}')
+ self.logger.info(f'Qt version: {QT_VERSION_STR}')
# Second: read lyse config
self.setup_config()
@@ -115,11 +121,13 @@ def __init__(self, qapplication):
# Forth: start remote communication server
self.port = int(self.exp_config.get('ports', 'lyse'))
self.server = lyse.communication.WebServer(self, self.port)
+ self.logger.info(f'Started lyse server on port {self.port}')
# Last: UI setup
self.qapplication = qapplication
loader = UiLoader()
self.ui = loader.load(os.path.join(lyse.utils.LYSE_DIR, 'user_interface/main.ui'), LyseMainWindow(self))
+ self.logger.info('UI loaded')
self.connect_signals()
@@ -138,6 +146,7 @@ def __init__(self, qapplication):
self, to_multishot, from_multishot, self.output_box.port, multishot=True)
self.filebox = lyse.filebox.FileBox(self, self.ui.verticalLayout_filebox, self.exp_config,
to_singleshot, from_singleshot, to_multishot, from_multishot)
+ self.logger.info('Boxes loaded')
self.last_save_config_file = None
self.last_save_data = None
@@ -188,6 +197,7 @@ def load_the_config_file():
# Success - skip loading window geometry in load_configuration:
restore_window_geometry = False
self.ui.firstPaint.connect(lambda: QtCore.QTimer.singleShot(50, load_the_config_file))
+ self.logger.info('lyse configuration loaded')
self.ui.show()
@@ -284,12 +294,12 @@ def get_save_data(self):
box = self.singleshot_routinebox
save_data['singleshot'] = list(zip([routine.filepath for routine in box.routines],
- [box.model.item(row, box.COL_ACTIVE).checkState()
+ [lyse.utils.gui.get_check_state(box.model.item(row, box.COL_ACTIVE))
for row in range(box.model.rowCount())]))
save_data['lastsingleshotfolder'] = box.last_opened_routine_folder
box = self.multishot_routinebox
save_data['multishot'] = list(zip([routine.filepath for routine in box.routines],
- [box.model.item(row, box.COL_ACTIVE).checkState()
+ [lyse.utils.gui.get_check_state(box.model.item(row, box.COL_ACTIVE))
for row in range(box.model.rowCount())]))
save_data['lastmultishotfolder'] = box.last_opened_routine_folder
@@ -522,7 +532,7 @@ def delete_items(self, confirm):
signal.signal(signal.SIGINT, lambda *args: qapplication.exit())
splash.hide()
- qapplication.exec_()
+ qapplication.exec()
# Shutdown the webserver.
app.server.shutdown()
diff --git a/lyse/analysis_subprocess.py b/lyse/analysis_subprocess.py
index 0a0f100..7021162 100644
--- a/lyse/analysis_subprocess.py
+++ b/lyse/analysis_subprocess.py
@@ -475,5 +475,5 @@ def reset_figs(self):
if qapplication is None:
qapplication = QtWidgets.QApplication(sys.argv)
worker = AnalysisWorker(filepath, to_parent, from_parent)
- qapplication.exec_()
+ qapplication.exec()
diff --git a/lyse/filebox.py b/lyse/filebox.py
index 8cf23d3..b2e135b 100644
--- a/lyse/filebox.py
+++ b/lyse/filebox.py
@@ -142,7 +142,7 @@ def on_treeView_context_menu_requested(self, point):
menu = QtWidgets.QMenu(self.ui)
menu.addAction(self.action_set_selected_visible)
menu.addAction(self.action_set_selected_hidden)
- menu.exec_(QtGui.QCursor.pos())
+ menu.exec(QtGui.QCursor.pos())
def on_set_selected_triggered(self, visible):
selected_indexes = self.ui.treeView.selectedIndexes()
@@ -373,7 +373,7 @@ def mark_selection_not_done(self):
def on_view_context_menu_requested(self, point):
menu = QtWidgets.QMenu(self._view)
menu.addAction(self.action_remove_selected)
- menu.exec_(QtGui.QCursor.pos())
+ menu.exec(QtGui.QCursor.pos())
def on_double_click(self, index):
filepath_item = self._model.item(index.row(), self.COL_FILEPATH)
diff --git a/lyse/routines.py b/lyse/routines.py
index e638af3..1f4aa7a 100644
--- a/lyse/routines.py
+++ b/lyse/routines.py
@@ -54,12 +54,14 @@ def __init__(self, app, container, exp_config, filebox, from_filebox, to_filebox
self.to_filebox = to_filebox
self.output_box_port = output_box_port
- self.logger = logging.getLogger('lyse.RoutineBox.%s'%('multishot' if multishot else 'singleshot'))
+ self.logger = logging.getLogger('lyse.RoutineBox.%s'%('multishot' if multishot else 'singleshot'))
+ self.logger.info('starting')
loader = UiLoader()
loader.registerCustomWidget(lyse.widgets.TreeView)
self.ui = loader.load(os.path.join(lyse.utils.LYSE_DIR, 'user_interface/routinebox.ui'))
container.addWidget(self.ui)
+ self.logger.info('UI loaded')
if multishot:
self.ui.groupBox.setTitle('Multishot routines')
@@ -110,6 +112,7 @@ def __init__(self, app, container, exp_config, filebox, from_filebox, to_filebox
self.connect_signals()
+ self.logger.info('starting analysis loop')
self.analysis = threading.Thread(target = self.analysis_loop)
self.analysis.daemon = True
self.analysis.start()
@@ -170,7 +173,9 @@ def add_routines(self, routine_files, clear_existing=False):
if filepath in [routine.filepath for routine in self.routines]:
self.app.output_box.output('Warning: Ignoring duplicate analysis routine %s\n'%filepath, red=True)
continue
- routine = AnalysisRoutine(self.app, filepath, self.model, self.output_box_port, checked)
+ self.logger.info(f'adding routine for {filepath}')
+ routine = AnalysisRoutine(self.app, filepath, self.model, self.output_box_port,
+ QtCore.Qt.CheckState(checked))
self.routines.append(routine)
self.update_select_all_checkstate()
@@ -215,6 +220,7 @@ def remove_selection(self, confirm=True):
if routine.filepath in filepaths:
routine.remove()
self.routines.remove(routine)
+ self.logger.info(f'removing routine for {routine.filepath}')
self.update_select_all_checkstate()
def on_model_item_changed(self, item):
@@ -237,7 +243,7 @@ def on_treeView_context_menu_requested(self, point):
menu.addAction(self.action_set_selected_inactive)
menu.addAction(self.action_restart_selected)
menu.addAction(self.action_remove_selected)
- menu.exec_(QtGui.QCursor.pos())
+ menu.exec(QtGui.QCursor.pos())
def on_set_selected_triggered(self, active):
selected_indexes = self.ui.treeView.selectedIndexes()
@@ -423,8 +429,12 @@ def __init__(self, app, filepath, model, output_box_port, checked=QtCore.Qt.Chec
self.error = False
self.done = False
-
+
+ self.logger = logging.getLogger(f'lyse.AnalysisRoutine.{self.shortname}')
+
+ self.logger.info('starting worker')
self.to_worker, self.from_worker, self.worker = self.start_worker()
+ self.logger.info('analysis_subprocess started')
# Make a row to put into the model:
active_item = QtGui.QStandardItem()
diff --git a/lyse/user_interface/filebox.ui b/lyse/user_interface/filebox.ui
index d933201..93ecc98 100644
--- a/lyse/user_interface/filebox.ui
+++ b/lyse/user_interface/filebox.ui
@@ -14,71 +14,7 @@
Form
- QPushButton {
- border: none;
- padding: 4px;
- }
-
-QPushButton:hover {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #f6f7fa, stop: 1 #dadbde);
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
- QPushButton:pressed {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
-QPushButton:checked {
- background-color: #dadbde;
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
-QPushButton:hover:checked {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
-QToolButton {
- border: none;
- padding: 2px;
- }
-
-QToolButton:hover {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #f6f7fa, stop: 1 #dadbde);
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
- QToolButton:pressed {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
-QToolButton:checked {
- background-color: #dadbde;
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
-QToolButton:hover:checked {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
-QGroupBox
+ QGroupBox
{
font-weight: bold;
}
diff --git a/lyse/user_interface/main.ui b/lyse/user_interface/main.ui
index d984168..606ce4f 100644
--- a/lyse/user_interface/main.ui
+++ b/lyse/user_interface/main.ui
@@ -32,28 +32,28 @@
QPushButton:hover {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #f6f7fa, stop: 1 #dadbde);
- border: 1px solid #8f8f91;
+ stop: 0 palette(light), stop: 1 palette(window));
+ border: 1px solid palette(dark);
border-radius: 3px;
}
QPushButton:pressed {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
+ stop: 0 palette(window), stop: 1 palette(light));
+ border: 1px solid palette(dark);
border-radius: 3px;
}
QPushButton:checked {
- background-color: #dadbde;
- border: 1px solid #8f8f91;
+ background-color: palette(window);
+ border: 1px solid palette(dark);
border-radius: 3px;
}
QPushButton:hover:checked {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
+ stop: 0 palette(window), stop: 1 palette(light));
+ border: 1px solid palette(dark);
border-radius: 3px;
}
@@ -64,28 +64,28 @@ QToolButton {
QToolButton:hover {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #f6f7fa, stop: 1 #dadbde);
- border: 1px solid #8f8f91;
+ stop: 0 palette(light), stop: 1 palette(window));
+ border: 1px solid palette(dark);
border-radius: 3px;
}
QToolButton:pressed {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
+ stop: 0 palette(window), stop: 1 palette(light));
+ border: 1px solid palette(dark);
border-radius: 3px;
}
QToolButton:checked {
- background-color: #dadbde;
- border: 1px solid #8f8f91;
+ background-color: palette(window);
+ border: 1px solid palette(dark);
border-radius: 3px;
}
QToolButton:hover:checked {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
+ stop: 0 palette(window), stop: 1 palette(light));
+ border: 1px solid palette(dark);
border-radius: 3px;
}
diff --git a/lyse/user_interface/plot_window.ui b/lyse/user_interface/plot_window.ui
index 77ee24c..5b9f9c4 100644
--- a/lyse/user_interface/plot_window.ui
+++ b/lyse/user_interface/plot_window.ui
@@ -25,28 +25,28 @@
QPushButton:hover {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #f6f7fa, stop: 1 #dadbde);
- border: 1px solid #8f8f91;
+ stop: 0 palette(light), stop: 1 palette(window));
+ border: 1px solid palette(dark);
border-radius: 3px;
}
QPushButton:pressed {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
+ stop: 0 palette(window), stop: 1 palette(light));
+ border: 1px solid palette(dark);
border-radius: 3px;
}
QPushButton:checked {
- background-color: #dadbde;
- border: 1px solid #8f8f91;
+ background-color: palette(window);
+ border: 1px solid palette(dark);
border-radius: 3px;
}
QPushButton:hover:checked {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
+ stop: 0 palette(window), stop: 1 palette(light));
+ border: 1px solid palette(dark);
border-radius: 3px;
}
@@ -57,28 +57,28 @@ QToolButton {
QToolButton:hover {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #f6f7fa, stop: 1 #dadbde);
- border: 1px solid #8f8f91;
+ stop: 0 palette(light), stop: 1 palette(window));
+ border: 1px solid palette(dark);
border-radius: 3px;
}
QToolButton:pressed {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
+ stop: 0 palette(window), stop: 1 palette(light));
+ border: 1px solid palette(dark);
border-radius: 3px;
}
QToolButton:checked {
- background-color: #dadbde;
- border: 1px solid #8f8f91;
+ background-color: palette(window);
+ border: 1px solid palette(dark);
border-radius: 3px;
}
QToolButton:hover:checked {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
+ stop: 0 palette(window), stop: 1 palette(light));
+ border: 1px solid palette(dark);
border-radius: 3px;
}
diff --git a/lyse/user_interface/routinebox.ui b/lyse/user_interface/routinebox.ui
index 7f046f3..f147bb9 100644
--- a/lyse/user_interface/routinebox.ui
+++ b/lyse/user_interface/routinebox.ui
@@ -14,71 +14,7 @@
Form
- QPushButton {
- border: none;
- padding: 4px;
- }
-
-QPushButton:hover {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #f6f7fa, stop: 1 #dadbde);
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
- QPushButton:pressed {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
-QPushButton:checked {
- background-color: #dadbde;
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
-QPushButton:hover:checked {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
-QToolButton {
- border: none;
- padding: 2px;
- }
-
-QToolButton:hover {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #f6f7fa, stop: 1 #dadbde);
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
- QToolButton:pressed {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
-QToolButton:checked {
- background-color: #dadbde;
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
-QToolButton:hover:checked {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #dadbde, stop: 1 #f6f7fa);
- border: 1px solid #8f8f91;
- border-radius: 3px;
- }
-
-QGroupBox
+ QGroupBox
{
font-weight: bold;
}
diff --git a/lyse/utils/gui.py b/lyse/utils/gui.py
index c52cc7b..2c66041 100644
--- a/lyse/utils/gui.py
+++ b/lyse/utils/gui.py
@@ -103,8 +103,23 @@ def get_screen_geometry(qapplication):
"""Return the a list of the geometries of each screen: each a tuple of
left, top, width and height"""
geoms = []
- desktop = qapplication.desktop()
- for i in range(desktop.screenCount()):
- sg = desktop.screenGeometry(i)
- geoms.append((sg.left(), sg.top(), sg.width(), sg.height()))
- return geoms
\ No newline at end of file
+ screens = qapplication.screens()
+ for screen in screens:
+ sg = screen.geometry()
+ geoms.append((sg.x(), sg.y(), sg.width(), sg.height()))
+ return geoms
+
+def get_check_state(qcheckbox):
+ """Return check state of a QCheckBox as an integer
+
+ Shim to handle differences between PyQt5 and PySide6 enum implementations
+ """
+
+ try:
+ # PySide6 uses proper python Enum, access by value attribute
+ return qcheckbox.checkState().value
+ except AttributeError:
+ # PyQt5 uses custom float class, cast to int directly
+ return int(qcheckbox.checkState())
+ except Exception as e:
+ raise RuntimeError('Input is not a recognized QCheckBox type') from e
\ No newline at end of file
diff --git a/lyse/utils/tempfile2clipboard.py b/lyse/utils/tempfile2clipboard.py
index 224f112..e50bc4b 100644
--- a/lyse/utils/tempfile2clipboard.py
+++ b/lyse/utils/tempfile2clipboard.py
@@ -65,7 +65,7 @@ def main():
# Keep running until the clipboard contents change to something else:
app.clipboard().dataChanged.connect(app.quit)
- app.exec_()
+ app.exec()
if __name__ == '__main__':
diff --git a/pyproject.toml b/pyproject.toml
index 9a27b1d..79be505 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -34,7 +34,7 @@ dependencies = [
"matplotlib",
"numpy",
"pandas>=1.5",
- "qtutils>=2.2.2",
+ "qtutils>=4.0.0",
"scipy",
"tzlocal",
"zprocess>=2.2.2",