From 9fbd6de30ce995191ceec11999bf64c58218214a Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 16 Sep 2023 23:52:13 +0100 Subject: [PATCH] Qt{5 -> 6} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some changes are due to deprecations in Qt6 which were outright removed in PyQt, for instance QRegExp or the x()/y() QMouseEvent properties. Most of the diff is due to enumeration values now no longer being available directly in the parent namespace. This commit is purposefully restricted to the mechanical changes, no reformatting/… is done to keep the diff easy to validate. --- README.rst | 2 +- artiq/applets/big_number.py | 6 +- artiq/applets/image.py | 2 +- artiq/applets/plot_hist.py | 4 +- artiq/applets/plot_xy.py | 4 +- artiq/applets/plot_xy_hist.py | 4 +- artiq/applets/progress_bar.py | 2 +- artiq/applets/simple.py | 2 +- artiq/browser/datasets.py | 16 ++-- artiq/browser/experiments.py | 24 ++--- artiq/browser/files.py | 30 +++--- artiq/dashboard/applets_ccb.py | 36 ++++---- artiq/dashboard/datasets.py | 32 +++---- artiq/dashboard/experiments.py | 32 +++---- artiq/dashboard/explorer.py | 50 +++++----- artiq/dashboard/moninj.py | 29 +++--- artiq/dashboard/schedule.py | 24 ++--- artiq/dashboard/shortcuts.py | 20 ++-- .../no_hardware/repository/custom_applet.py | 2 +- artiq/frontend/artiq_browser.py | 28 +++--- artiq/frontend/artiq_dashboard.py | 10 +- artiq/gui/applets.py | 92 +++++++++---------- artiq/gui/entries.py | 5 +- artiq/gui/flowlayout.py | 8 +- artiq/gui/fuzzy_select.py | 34 +++---- artiq/gui/log.py | 64 ++++++------- artiq/gui/models.py | 26 +++--- artiq/gui/scanwidget.py | 62 ++++++------- artiq/gui/scientific_spinbox.py | 12 +-- artiq/gui/tools.py | 16 ++-- artiq/gui/waitingspinnerwidget.py | 20 ++-- doc/manual/conf.py | 2 +- doc/manual/introduction.rst | 2 +- flake.nix | 12 +-- setup.py | 2 +- 35 files changed, 359 insertions(+), 357 deletions(-) diff --git a/README.rst b/README.rst index 2f3e09021..b93402f56 100644 --- a/README.rst +++ b/README.rst @@ -15,7 +15,7 @@ ARTIQ and its dependencies are available in the form of Nix packages (for Linux) ARTIQ is supported by M-Labs and developed openly. Components, features, fixes, improvements, and extensions are often `funded `_ by and developed for the partnering research groups. -Core technologies employed include `Python `_, `Migen `_, `Migen-AXI `_, `Rust `_, `MiSoC `_/`VexRiscv `_, `LLVM `_/`llvmlite `_, and `Qt5 `_. +Core technologies employed include `Python `_, `Migen `_, `Migen-AXI `_, `Rust `_, `MiSoC `_/`VexRiscv `_, `LLVM `_/`llvmlite `_, and `Qt6 `_. | Website: https://m-labs.hk/experiment-control/artiq | (US-hosted mirror: https://m-labs-intl.com/experiment-control/artiq) diff --git a/artiq/applets/big_number.py b/artiq/applets/big_number.py index 7bf077fe2..58a1d6e4c 100755 --- a/artiq/applets/big_number.py +++ b/artiq/applets/big_number.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -from PyQt5 import QtWidgets, QtCore, QtGui +from PyQt6 import QtWidgets, QtCore, QtGui from artiq.applets.simple import SimpleApplet from artiq.tools import scale_from_metadata from artiq.gui.tools import LayoutWidget @@ -17,7 +17,7 @@ class QCancellableLineEdit(QtWidgets.QLineEdit): editCancelled = QtCore.pyqtSignal() def keyPressEvent(self, event): - if event.key() == QtCore.Qt.Key_Escape: + if event.key() == QtCore.Qt.Key.Key_Escape: self.editCancelled.emit() else: super().keyPressEvent(event) @@ -44,7 +44,7 @@ class NumberWidget(LayoutWidget): self.edit_widget = QCancellableLineEdit() self.edit_widget.setValidator(QtGui.QDoubleValidator()) - self.edit_widget.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.edit_widget.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter) self.edit_widget.editCancelled.connect(self.cancel_edit) self.edit_widget.returnPressed.connect(self.confirm_edit) self.number_area.addWidget(self.edit_widget) diff --git a/artiq/applets/image.py b/artiq/applets/image.py index 75cecd05a..3948e1552 100755 --- a/artiq/applets/image.py +++ b/artiq/applets/image.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -import PyQt5 # make sure pyqtgraph imports Qt5 +import PyQt6 # make sure pyqtgraph imports Qt6 import pyqtgraph from artiq.applets.simple import SimpleApplet diff --git a/artiq/applets/plot_hist.py b/artiq/applets/plot_hist.py index 5d386cc6c..03c275bdc 100755 --- a/artiq/applets/plot_hist.py +++ b/artiq/applets/plot_hist.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 -import PyQt5 # make sure pyqtgraph imports Qt5 -from PyQt5.QtCore import QTimer +import PyQt6 # make sure pyqtgraph imports Qt6 +from PyQt6.QtCore import QTimer import pyqtgraph from artiq.applets.simple import TitleApplet diff --git a/artiq/applets/plot_xy.py b/artiq/applets/plot_xy.py index df3dc2aaf..033d2d1cd 100755 --- a/artiq/applets/plot_xy.py +++ b/artiq/applets/plot_xy.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 import numpy as np -import PyQt5 # make sure pyqtgraph imports Qt5 -from PyQt5.QtCore import QTimer +import PyQt6 # make sure pyqtgraph imports Qt6 +from PyQt6.QtCore import QTimer import pyqtgraph from artiq.applets.simple import TitleApplet diff --git a/artiq/applets/plot_xy_hist.py b/artiq/applets/plot_xy_hist.py index f757b520d..fb916f0bc 100755 --- a/artiq/applets/plot_xy_hist.py +++ b/artiq/applets/plot_xy_hist.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 import numpy as np -from PyQt5 import QtWidgets -from PyQt5.QtCore import QTimer +from PyQt6 import QtWidgets +from PyQt6.QtCore import QTimer import pyqtgraph from artiq.applets.simple import SimpleApplet diff --git a/artiq/applets/progress_bar.py b/artiq/applets/progress_bar.py index 9ea7db836..cdc6208a8 100644 --- a/artiq/applets/progress_bar.py +++ b/artiq/applets/progress_bar.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -from PyQt5 import QtWidgets +from PyQt6 import QtWidgets from artiq.applets.simple import SimpleApplet diff --git a/artiq/applets/simple.py b/artiq/applets/simple.py index 837ecfa54..b9e74e90d 100644 --- a/artiq/applets/simple.py +++ b/artiq/applets/simple.py @@ -273,7 +273,7 @@ class SimpleApplet: # HACK: if the window has a frame, there will be garbage # (usually white) displayed at its right and bottom borders # after it is embedded. - self.main_widget.setWindowFlags(QtCore.Qt.FramelessWindowHint) + self.main_widget.setWindowFlags(QtCore.Qt.WindowType.FramelessWindowHint) self.main_widget.show() win_id = int(self.main_widget.winId()) self.loop.run_until_complete(self.ipc.embed(win_id)) diff --git a/artiq/browser/datasets.py b/artiq/browser/datasets.py index 6e5473786..d748ce153 100644 --- a/artiq/browser/datasets.py +++ b/artiq/browser/datasets.py @@ -1,7 +1,7 @@ import logging import asyncio -from PyQt5 import QtCore, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets from sipyco.pc_rpc import AsyncioClient as RPCClient @@ -62,8 +62,8 @@ class DatasetsDock(QtWidgets.QDockWidget): def __init__(self, dataset_sub, dataset_ctl): QtWidgets.QDockWidget.__init__(self, "Datasets") self.setObjectName("Datasets") - self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | - QtWidgets.QDockWidget.DockWidgetFloatable) + self.setFeatures(QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable) grid = LayoutWidget() self.setWidget(grid) @@ -74,9 +74,9 @@ class DatasetsDock(QtWidgets.QDockWidget): grid.addWidget(self.search, 0, 0) self.table = QtWidgets.QTreeView() - self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) + self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows) self.table.setSelectionMode( - QtWidgets.QAbstractItemView.SingleSelection) + QtWidgets.QAbstractItemView.SelectionMode.SingleSelection) grid.addWidget(self.table, 1, 0) metadata_grid = LayoutWidget() @@ -85,13 +85,13 @@ class DatasetsDock(QtWidgets.QDockWidget): "rid start_time".split()): metadata_grid.addWidget(QtWidgets.QLabel(label), i, 0) v = QtWidgets.QLabel() - v.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse) + v.setTextInteractionFlags(QtCore.Qt.TextInteractionFlag.TextSelectableByMouse) metadata_grid.addWidget(v, i, 1) self.metadata[label] = v grid.addWidget(metadata_grid, 2, 0) - self.table.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) - upload_action = QtWidgets.QAction("Upload dataset to master", + self.table.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.ActionsContextMenu) + upload_action = QtGui.QAction("Upload dataset to master", self.table) upload_action.triggered.connect(self.upload_clicked) self.table.addAction(upload_action) diff --git a/artiq/browser/experiments.py b/artiq/browser/experiments.py index c5cf9c54c..8cbd81661 100644 --- a/artiq/browser/experiments.py +++ b/artiq/browser/experiments.py @@ -4,7 +4,7 @@ import os from functools import partial from collections import OrderedDict -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets import h5py from sipyco import pyon @@ -33,13 +33,13 @@ class _ArgumentEditor(EntryTreeWidget): recompute_arguments = QtWidgets.QPushButton("Recompute all arguments") recompute_arguments.setIcon( QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_BrowserReload)) + QtWidgets.QStyle.StandardPixmap.SP_BrowserReload)) recompute_arguments.clicked.connect(self._recompute_arguments_clicked) load = QtWidgets.QPushButton("Set arguments from HDF5") load.setToolTip("Set arguments from currently selected HDF5 file") load.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DialogApplyButton)) + QtWidgets.QStyle.StandardPixmap.SP_DialogApplyButton)) load.clicked.connect(self._load_clicked) buttons = LayoutWidget() @@ -86,7 +86,7 @@ class _ExperimentDock(QtWidgets.QMdiSubWindow): self.resize(100*qfm.averageCharWidth(), 30*qfm.lineSpacing()) self.setWindowTitle(expurl) self.setWindowIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_FileDialogContentsView)) + QtWidgets.QStyle.StandardPixmap.SP_FileDialogContentsView)) self.setAcceptDrops(True) self.layout = QtWidgets.QGridLayout() @@ -126,22 +126,22 @@ class _ExperimentDock(QtWidgets.QMdiSubWindow): run = QtWidgets.QPushButton("Analyze") run.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DialogOkButton)) + QtWidgets.QStyle.StandardPixmap.SP_DialogOkButton)) run.setToolTip("Run analysis stage (Ctrl+Return)") run.setShortcut("CTRL+RETURN") - run.setSizePolicy(QtWidgets.QSizePolicy.Expanding, - QtWidgets.QSizePolicy.Expanding) + run.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, + QtWidgets.QSizePolicy.Policy.Expanding) self.layout.addWidget(run, 2, 4) run.clicked.connect(self._run_clicked) self._run = run terminate = QtWidgets.QPushButton("Terminate") terminate.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DialogCancelButton)) + QtWidgets.QStyle.StandardPixmap.SP_DialogCancelButton)) terminate.setToolTip("Terminate analysis (Ctrl+Backspace)") terminate.setShortcut("CTRL+BACKSPACE") - terminate.setSizePolicy(QtWidgets.QSizePolicy.Expanding, - QtWidgets.QSizePolicy.Expanding) + terminate.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, + QtWidgets.QSizePolicy.Policy.Expanding) self.layout.addWidget(terminate, 3, 4) terminate.clicked.connect(self._terminate_clicked) terminate.setEnabled(False) @@ -316,7 +316,7 @@ class ExperimentsArea(QtWidgets.QMdiArea): asyncio.ensure_future(sub.load_hdf5_task(path)) def mousePressEvent(self, ev): - if ev.button() == QtCore.Qt.LeftButton: + if ev.button() == QtCore.Qt.MouseButton.LeftButton: self.select_experiment() def paintEvent(self, event): @@ -406,7 +406,7 @@ class ExperimentsArea(QtWidgets.QMdiArea): exc_info=True) dock = _ExperimentDock(self, expurl, {}) asyncio.ensure_future(dock._recompute_arguments()) - dock.setAttribute(QtCore.Qt.WA_DeleteOnClose) + dock.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) self.addSubWindow(dock) dock.show() dock.sigClosed.connect(partial(self.on_dock_closed, dock)) diff --git a/artiq/browser/files.py b/artiq/browser/files.py index dd97f45a9..cb457b7fa 100644 --- a/artiq/browser/files.py +++ b/artiq/browser/files.py @@ -3,7 +3,7 @@ import os from datetime import datetime import h5py -from PyQt5 import QtCore, QtWidgets, QtGui +from PyQt6 import QtCore, QtWidgets, QtGui from sipyco import pyon @@ -69,15 +69,15 @@ class ZoomIconView(QtWidgets.QListView): def __init__(self): QtWidgets.QListView.__init__(self) self._char_width = QtGui.QFontMetrics(self.font()).averageCharWidth() - self.setViewMode(self.IconMode) + self.setViewMode(self.ViewMode.IconMode) w = self._char_width*self.default_size self.setIconSize(QtCore.QSize(w, int(w*self.aspect))) - self.setFlow(self.LeftToRight) - self.setResizeMode(self.Adjust) + self.setFlow(self.Flow.LeftToRight) + self.setResizeMode(self.ResizeMode.Adjust) self.setWrapping(True) def wheelEvent(self, ev): - if ev.modifiers() & QtCore.Qt.ControlModifier: + if ev.modifiers() & QtCore.Qt.KeyboardModifier.ControlModifier: a = self._char_width*self.min_size b = self._char_width*self.max_size w = self.iconSize().width()*self.zoom_step**( @@ -88,16 +88,16 @@ class ZoomIconView(QtWidgets.QListView): QtWidgets.QListView.wheelEvent(self, ev) -class Hdf5FileSystemModel(QtWidgets.QFileSystemModel): +class Hdf5FileSystemModel(QtGui.QFileSystemModel): def __init__(self): - QtWidgets.QFileSystemModel.__init__(self) - self.setFilter(QtCore.QDir.Drives | QtCore.QDir.NoDotAndDotDot | - QtCore.QDir.AllDirs | QtCore.QDir.Files) + QtGui.QFileSystemModel.__init__(self) + self.setFilter(QtCore.QDir.Filter.Drives | QtCore.QDir.Filter.NoDotAndDotDot | + QtCore.QDir.Filter.AllDirs | QtCore.QDir.Filter.Files) self.setNameFilterDisables(False) self.setIconProvider(ThumbnailIconProvider()) def data(self, idx, role): - if role == QtCore.Qt.ToolTipRole: + if role == QtCore.Qt.ItemDataRole.ToolTipRole: info = self.fileInfo(idx) h5 = open_h5(info) if h5 is not None: @@ -114,7 +114,7 @@ class Hdf5FileSystemModel(QtWidgets.QFileSystemModel): except: logger.warning("unable to read metadata from %s", info.filePath(), exc_info=True) - return QtWidgets.QFileSystemModel.data(self, idx, role) + return QtGui.QFileSystemModel.data(self, idx, role) class FilesDock(QtWidgets.QDockWidget): @@ -125,7 +125,7 @@ class FilesDock(QtWidgets.QDockWidget): def __init__(self, datasets, browse_root=""): QtWidgets.QDockWidget.__init__(self, "Files") self.setObjectName("Files") - self.setFeatures(self.DockWidgetMovable | self.DockWidgetFloatable) + self.setFeatures(self.DockWidgetFeature.DockWidgetMovable | self.DockWidgetFeature.DockWidgetFloatable) self.splitter = QtWidgets.QSplitter() self.setWidget(self.splitter) @@ -147,8 +147,8 @@ class FilesDock(QtWidgets.QDockWidget): self.rt.setRootIndex(rt_model.mapFromSource( self.model.setRootPath(browse_root))) self.rt.setHeaderHidden(True) - self.rt.setSelectionBehavior(self.rt.SelectRows) - self.rt.setSelectionMode(self.rt.SingleSelection) + self.rt.setSelectionBehavior(self.rt.SelectionBehavior.SelectRows) + self.rt.setSelectionMode(self.rt.SelectionMode.SingleSelection) self.rt.selectionModel().currentChanged.connect( self.tree_current_changed) self.rt.setRootIsDecorated(False) @@ -252,7 +252,7 @@ class FilesDock(QtWidgets.QDockWidget): 100, lambda: self.rt.scrollTo( self.rt.model().mapFromSource(self.model.index(path)), - self.rt.PositionAtCenter) + self.rt.ScrollHint.PositionAtCenter) ) self.model.directoryLoaded.connect(scroll_when_loaded) idx = self.rt.model().mapFromSource(idx) diff --git a/artiq/dashboard/applets_ccb.py b/artiq/dashboard/applets_ccb.py index 29afbbc1d..5b8faa4c9 100644 --- a/artiq/dashboard/applets_ccb.py +++ b/artiq/dashboard/applets_ccb.py @@ -1,7 +1,7 @@ import asyncio import logging -from PyQt5 import QtCore, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets from artiq.gui import applets @@ -13,58 +13,58 @@ class AppletsCCBDock(applets.AppletsDock): def __init__(self, *args, **kwargs): applets.AppletsDock.__init__(self, *args, **kwargs) - sep = QtWidgets.QAction(self.table) + sep = QtGui.QAction(self.table) sep.setSeparator(True) self.table.addAction(sep) ccbp_group_menu = QtWidgets.QMenu() - actiongroup = QtWidgets.QActionGroup(self.table) + actiongroup = QtGui.QActionGroup(self.table) actiongroup.setExclusive(True) - self.ccbp_group_none = QtWidgets.QAction("No policy", self.table) + self.ccbp_group_none = QtGui.QAction("No policy", self.table) self.ccbp_group_none.setCheckable(True) self.ccbp_group_none.triggered.connect(lambda: self.set_ccbp("")) ccbp_group_menu.addAction(self.ccbp_group_none) actiongroup.addAction(self.ccbp_group_none) - self.ccbp_group_ignore = QtWidgets.QAction("Ignore requests", self.table) + self.ccbp_group_ignore = QtGui.QAction("Ignore requests", self.table) self.ccbp_group_ignore.setCheckable(True) self.ccbp_group_ignore.triggered.connect(lambda: self.set_ccbp("ignore")) ccbp_group_menu.addAction(self.ccbp_group_ignore) actiongroup.addAction(self.ccbp_group_ignore) - self.ccbp_group_create = QtWidgets.QAction("Create applets", self.table) + self.ccbp_group_create = QtGui.QAction("Create applets", self.table) self.ccbp_group_create.setCheckable(True) self.ccbp_group_create.triggered.connect(lambda: self.set_ccbp("create")) ccbp_group_menu.addAction(self.ccbp_group_create) actiongroup.addAction(self.ccbp_group_create) - self.ccbp_group_enable = QtWidgets.QAction("Create and enable/disable applets", - self.table) + self.ccbp_group_enable = QtGui.QAction("Create and enable/disable applets", + self.table) self.ccbp_group_enable.setCheckable(True) self.ccbp_group_enable.triggered.connect(lambda: self.set_ccbp("enable")) ccbp_group_menu.addAction(self.ccbp_group_enable) actiongroup.addAction(self.ccbp_group_enable) - self.ccbp_group_action = QtWidgets.QAction("Group CCB policy", self.table) + self.ccbp_group_action = QtGui.QAction("Group CCB policy", self.table) self.ccbp_group_action.setMenu(ccbp_group_menu) self.table.addAction(self.ccbp_group_action) self.table.itemSelectionChanged.connect(self.update_group_ccbp_menu) self.update_group_ccbp_menu() ccbp_global_menu = QtWidgets.QMenu() - actiongroup = QtWidgets.QActionGroup(self.table) + actiongroup = QtGui.QActionGroup(self.table) actiongroup.setExclusive(True) - self.ccbp_global_ignore = QtWidgets.QAction("Ignore requests", self.table) + self.ccbp_global_ignore = QtGui.QAction("Ignore requests", self.table) self.ccbp_global_ignore.setCheckable(True) ccbp_global_menu.addAction(self.ccbp_global_ignore) actiongroup.addAction(self.ccbp_global_ignore) - self.ccbp_global_create = QtWidgets.QAction("Create applets", self.table) + self.ccbp_global_create = QtGui.QAction("Create applets", self.table) self.ccbp_global_create.setCheckable(True) self.ccbp_global_create.setChecked(True) ccbp_global_menu.addAction(self.ccbp_global_create) actiongroup.addAction(self.ccbp_global_create) - self.ccbp_global_enable = QtWidgets.QAction("Create and enable/disable applets", - self.table) + self.ccbp_global_enable = QtGui.QAction("Create and enable/disable applets", + self.table) self.ccbp_global_enable.setCheckable(True) ccbp_global_menu.addAction(self.ccbp_global_enable) actiongroup.addAction(self.ccbp_global_enable) - ccbp_global_action = QtWidgets.QAction("Global CCB policy", self.table) + ccbp_global_action = QtGui.QAction("Global CCB policy", self.table) ccbp_global_action.setMenu(ccbp_global_menu) self.table.addAction(ccbp_global_action) @@ -196,7 +196,7 @@ class AppletsCCBDock(applets.AppletsDock): logger.debug("Applet %s already exists and no update required", name) if ccbp == "enable": - applet.setCheckState(0, QtCore.Qt.Checked) + applet.setCheckState(0, QtCore.Qt.CheckState.Checked) def ccb_disable_applet(self, name, group=None): """Disables an applet. @@ -216,7 +216,7 @@ class AppletsCCBDock(applets.AppletsDock): return parent, applet = self.locate_applet(name, group, False) if applet is not None: - applet.setCheckState(0, QtCore.Qt.Unchecked) + applet.setCheckState(0, QtCore.Qt.CheckState.Unchecked) def ccb_disable_applet_group(self, group): """Disables all the applets in a group. @@ -246,7 +246,7 @@ class AppletsCCBDock(applets.AppletsDock): return else: wi = nwi - wi.setCheckState(0, QtCore.Qt.Unchecked) + wi.setCheckState(0, QtCore.Qt.CheckState.Unchecked) def ccb_notify(self, message): try: diff --git a/artiq/dashboard/datasets.py b/artiq/dashboard/datasets.py index 749828d61..5d9befad9 100644 --- a/artiq/dashboard/datasets.py +++ b/artiq/dashboard/datasets.py @@ -2,7 +2,7 @@ import asyncio import logging import numpy as np -from PyQt5 import QtCore, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets from sipyco import pyon from artiq.tools import scale_from_metadata, short_format, exc_to_warning @@ -63,11 +63,11 @@ class CreateEditDialog(QtWidgets.QDialog): self.cancel = QtWidgets.QPushButton('&Cancel') self.buttons = QtWidgets.QDialogButtonBox(self) self.buttons.addButton( - self.ok, QtWidgets.QDialogButtonBox.AcceptRole) + self.ok, QtWidgets.QDialogButtonBox.ButtonRole.AcceptRole) self.buttons.addButton( - self.cancel, QtWidgets.QDialogButtonBox.RejectRole) + self.cancel, QtWidgets.QDialogButtonBox.ButtonRole.RejectRole) grid.setRowStretch(6, 1) - grid.addWidget(self.buttons, 7, 0, 1, 3, alignment=QtCore.Qt.AlignHCenter) + grid.addWidget(self.buttons, 7, 0, 1, 3, alignment=QtCore.Qt.AlignmentFlag.AlignHCenter) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) @@ -125,7 +125,7 @@ class CreateEditDialog(QtWidgets.QDialog): pyon.encode(result) except: pixmap = self.style().standardPixmap( - QtWidgets.QStyle.SP_MessageBoxWarning) + QtWidgets.QStyle.StandardPixmap.SP_MessageBoxWarning) self.data_type.setPixmap(pixmap) self.ok.setEnabled(False) else: @@ -181,8 +181,8 @@ class DatasetsDock(QtWidgets.QDockWidget): def __init__(self, dataset_sub, dataset_ctl): QtWidgets.QDockWidget.__init__(self, "Datasets") self.setObjectName("Datasets") - self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | - QtWidgets.QDockWidget.DockWidgetFloatable) + self.setFeatures(QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable) self.dataset_ctl = dataset_ctl grid = LayoutWidget() @@ -194,27 +194,27 @@ class DatasetsDock(QtWidgets.QDockWidget): grid.addWidget(self.search, 0, 0) self.table = QtWidgets.QTreeView() - self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) + self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows) self.table.setSelectionMode( - QtWidgets.QAbstractItemView.SingleSelection) + QtWidgets.QAbstractItemView.SelectionMode.SingleSelection) grid.addWidget(self.table, 1, 0) - self.table.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) - create_action = QtWidgets.QAction("New dataset", self.table) + self.table.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.ActionsContextMenu) + create_action = QtGui.QAction("New dataset", self.table) create_action.triggered.connect(self.create_clicked) create_action.setShortcut("CTRL+N") - create_action.setShortcutContext(QtCore.Qt.WidgetShortcut) + create_action.setShortcutContext(QtCore.Qt.ShortcutContext.WidgetShortcut) self.table.addAction(create_action) - edit_action = QtWidgets.QAction("Edit dataset", self.table) + edit_action = QtGui.QAction("Edit dataset", self.table) edit_action.triggered.connect(self.edit_clicked) edit_action.setShortcut("RETURN") - edit_action.setShortcutContext(QtCore.Qt.WidgetShortcut) + edit_action.setShortcutContext(QtCore.Qt.ShortcutContext.WidgetShortcut) self.table.doubleClicked.connect(self.edit_clicked) self.table.addAction(edit_action) - delete_action = QtWidgets.QAction("Delete dataset", self.table) + delete_action = QtGui.QAction("Delete dataset", self.table) delete_action.triggered.connect(self.delete_clicked) delete_action.setShortcut("DELETE") - delete_action.setShortcutContext(QtCore.Qt.WidgetShortcut) + delete_action.setShortcutContext(QtCore.Qt.ShortcutContext.WidgetShortcut) self.table.addAction(delete_action) self.table_model = Model(dict()) diff --git a/artiq/dashboard/experiments.py b/artiq/dashboard/experiments.py index 10bfa5a0c..53323b2d4 100644 --- a/artiq/dashboard/experiments.py +++ b/artiq/dashboard/experiments.py @@ -4,7 +4,7 @@ import os from functools import partial from collections import OrderedDict -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets import h5py from sipyco import pyon @@ -44,12 +44,12 @@ class _ArgumentEditor(EntryTreeWidget): recompute_arguments = QtWidgets.QPushButton("Recompute all arguments") recompute_arguments.setIcon( QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_BrowserReload)) + QtWidgets.QStyle.StandardPixmap.SP_BrowserReload)) recompute_arguments.clicked.connect(dock._recompute_arguments_clicked) load_hdf5 = QtWidgets.QPushButton("Load HDF5") load_hdf5.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DialogOpenButton)) + QtWidgets.QStyle.StandardPixmap.SP_DialogOpenButton)) load_hdf5.clicked.connect(dock._load_hdf5_clicked) buttons = LayoutWidget() @@ -101,7 +101,7 @@ class _ExperimentDock(QtWidgets.QMdiSubWindow): self.resize(100 * qfm.averageCharWidth(), 30 * qfm.lineSpacing()) self.setWindowTitle(expurl) self.setWindowIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_FileDialogContentsView)) + QtWidgets.QStyle.StandardPixmap.SP_FileDialogContentsView)) self.layout = QtWidgets.QGridLayout() top_widget = QtWidgets.QWidget() @@ -237,21 +237,21 @@ class _ExperimentDock(QtWidgets.QMdiSubWindow): submit = QtWidgets.QPushButton("Submit") submit.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DialogOkButton)) + QtWidgets.QStyle.StandardPixmap.SP_DialogOkButton)) submit.setToolTip("Schedule the experiment (Ctrl+Return)") submit.setShortcut("CTRL+RETURN") - submit.setSizePolicy(QtWidgets.QSizePolicy.Expanding, - QtWidgets.QSizePolicy.Expanding) + submit.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, + QtWidgets.QSizePolicy.Policy.Expanding) self.layout.addWidget(submit, 1, 4, 2, 1) submit.clicked.connect(self.submit_clicked) reqterm = QtWidgets.QPushButton("Terminate instances") reqterm.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DialogCancelButton)) + QtWidgets.QStyle.StandardPixmap.SP_DialogCancelButton)) reqterm.setToolTip("Request termination of instances (Ctrl+Backspace)") reqterm.setShortcut("CTRL+BACKSPACE") - reqterm.setSizePolicy(QtWidgets.QSizePolicy.Expanding, - QtWidgets.QSizePolicy.Expanding) + reqterm.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, + QtWidgets.QSizePolicy.Policy.Expanding) self.layout.addWidget(reqterm, 3, 4) reqterm.clicked.connect(self.reqterm_clicked) @@ -306,7 +306,7 @@ class _ExperimentDock(QtWidgets.QMdiSubWindow): def contextMenuEvent(self, event): menu = QtWidgets.QMenu(self) reset_sched = menu.addAction("Reset scheduler settings") - action = menu.exec_(self.mapToGlobal(event.pos())) + action = menu.exec(self.mapToGlobal(event.pos())) if action == reset_sched: asyncio.ensure_future(self._recompute_sched_options_task()) @@ -423,7 +423,7 @@ class _QuickOpenDialog(QtWidgets.QDialog): QtWidgets.QDialog.done(self, r) def _open_experiment(self, exp_name, modifiers): - if modifiers & QtCore.Qt.ControlModifier: + if modifiers & QtCore.Qt.KeyboardModifier.ControlModifier: try: self.manager.submit(exp_name) except: @@ -467,10 +467,10 @@ class ExperimentManager: self.open_experiments = dict() self.is_quick_open_shown = False - quick_open_shortcut = QtWidgets.QShortcut( - QtCore.Qt.CTRL + QtCore.Qt.Key_P, + quick_open_shortcut = QtGui.QShortcut( + QtGui.QKeySequence("Ctrl+P"), main_window) - quick_open_shortcut.setContext(QtCore.Qt.ApplicationShortcut) + quick_open_shortcut.setContext(QtCore.Qt.ShortcutContext.ApplicationShortcut) quick_open_shortcut.activated.connect(self.show_quick_open) def set_dataset_model(self, model): @@ -589,7 +589,7 @@ class ExperimentManager: del self.submission_arguments[expurl] dock = _ExperimentDock(self, expurl) self.open_experiments[expurl] = dock - dock.setAttribute(QtCore.Qt.WA_DeleteOnClose) + dock.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) self.main_window.centralWidget().addSubWindow(dock) dock.show() dock.sigClosed.connect(partial(self.on_dock_closed, expurl)) diff --git a/artiq/dashboard/explorer.py b/artiq/dashboard/explorer.py index f8c8df1f0..f13358a31 100644 --- a/artiq/dashboard/explorer.py +++ b/artiq/dashboard/explorer.py @@ -3,7 +3,7 @@ import logging import re from functools import partial -from PyQt5 import QtCore, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets from artiq.gui.tools import LayoutWidget from artiq.gui.models import DictSyncTreeSepModel @@ -37,7 +37,8 @@ class _OpenFileDialog(QtWidgets.QDialog): self.file_list.doubleClicked.connect(self.accept) buttons = QtWidgets.QDialogButtonBox( - QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel) + QtWidgets.QDialogButtonBox.StandardButton.Ok | + QtWidgets.QDialogButtonBox.StandardButton.Cancel) grid.addWidget(buttons, 2, 0, 1, 2) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) @@ -52,7 +53,7 @@ class _OpenFileDialog(QtWidgets.QDialog): item = QtWidgets.QListWidgetItem() item.setText("..") item.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_FileDialogToParent)) + QtWidgets.QStyle.StandardPixmap.SP_FileDialogToParent)) self.file_list.addItem(item) try: @@ -64,9 +65,9 @@ class _OpenFileDialog(QtWidgets.QDialog): return for name in sorted(contents, key=lambda x: (x[-1] not in "\\/", x)): if name[-1] in "\\/": - icon = QtWidgets.QStyle.SP_DirIcon + icon = QtWidgets.QStyle.StandardPixmap.SP_DirIcon else: - icon = QtWidgets.QStyle.SP_FileIcon + icon = QtWidgets.QStyle.StandardPixmap.SP_FileIcon if name[-3:] != ".py": continue item = QtWidgets.QListWidgetItem() @@ -163,8 +164,8 @@ class ExplorerDock(QtWidgets.QDockWidget): schedule_ctl, experiment_db_ctl, device_db_ctl): QtWidgets.QDockWidget.__init__(self, "Explorer") self.setObjectName("Explorer") - self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | - QtWidgets.QDockWidget.DockWidgetFloatable) + self.setFeatures(QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable) top_widget = LayoutWidget() self.setWidget(top_widget) @@ -175,7 +176,7 @@ class ExplorerDock(QtWidgets.QDockWidget): top_widget.addWidget(QtWidgets.QLabel("Revision:"), 0, 0) self.revision = QtWidgets.QLabel() - self.revision.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse) + self.revision.setTextInteractionFlags(QtCore.Qt.TextInteractionFlag.TextSelectableByMouse) top_widget.addWidget(self.revision, 0, 1) self.stack = QtWidgets.QStackedWidget() @@ -187,14 +188,14 @@ class ExplorerDock(QtWidgets.QDockWidget): self.el = QtWidgets.QTreeView() self.el.setHeaderHidden(True) - self.el.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems) + self.el.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectItems) self.el.doubleClicked.connect( partial(self.expname_action, "open_experiment")) self.el_buttons.addWidget(self.el, 0, 0, colspan=2) open = QtWidgets.QPushButton("Open") open.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DialogOpenButton)) + QtWidgets.QStyle.StandardPixmap.SP_DialogOpenButton)) open.setToolTip("Open the selected experiment (Return)") self.el_buttons.addWidget(open, 1, 0) open.clicked.connect( @@ -202,7 +203,7 @@ class ExplorerDock(QtWidgets.QDockWidget): submit = QtWidgets.QPushButton("Submit") submit.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DialogOkButton)) + QtWidgets.QStyle.StandardPixmap.SP_DialogOkButton)) submit.setToolTip("Schedule the selected experiment (Ctrl+Return)") self.el_buttons.addWidget(submit, 1, 1) submit.clicked.connect( @@ -211,41 +212,41 @@ class ExplorerDock(QtWidgets.QDockWidget): self.explist_model = Model(dict()) explist_sub.add_setmodel_callback(self.set_model) - self.el.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) - open_action = QtWidgets.QAction("Open", self.el) + self.el.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.ActionsContextMenu) + open_action = QtGui.QAction("Open", self.el) open_action.triggered.connect( partial(self.expname_action, "open_experiment")) open_action.setShortcut("RETURN") - open_action.setShortcutContext(QtCore.Qt.WidgetShortcut) + open_action.setShortcutContext(QtCore.Qt.ShortcutContext.WidgetShortcut) self.el.addAction(open_action) - submit_action = QtWidgets.QAction("Submit", self.el) + submit_action = QtGui.QAction("Submit", self.el) submit_action.triggered.connect( partial(self.expname_action, "submit")) submit_action.setShortcut("CTRL+RETURN") - submit_action.setShortcutContext(QtCore.Qt.WidgetShortcut) + submit_action.setShortcutContext(QtCore.Qt.ShortcutContext.WidgetShortcut) self.el.addAction(submit_action) - reqterm_action = QtWidgets.QAction("Request termination of instances", self.el) + reqterm_action = QtGui.QAction("Request termination of instances", self.el) reqterm_action.triggered.connect( partial(self.expname_action, "request_inst_term")) reqterm_action.setShortcut("CTRL+BACKSPACE") - reqterm_action.setShortcutContext(QtCore.Qt.WidgetShortcut) + reqterm_action.setShortcutContext(QtCore.Qt.ShortcutContext.WidgetShortcut) self.el.addAction(reqterm_action) set_shortcut_menu = QtWidgets.QMenu() for i in range(12): - action = QtWidgets.QAction("F" + str(i + 1), self.el) + action = QtGui.QAction("F" + str(i+1), self.el) action.triggered.connect(partial(self.set_shortcut, i)) set_shortcut_menu.addAction(action) - set_shortcut_action = QtWidgets.QAction("Set shortcut", self.el) + set_shortcut_action = QtGui.QAction("Set shortcut", self.el) set_shortcut_action.setMenu(set_shortcut_menu) self.el.addAction(set_shortcut_action) - sep = QtWidgets.QAction(self.el) + sep = QtGui.QAction(self.el) sep.setSeparator(True) self.el.addAction(sep) - scan_repository_action = QtWidgets.QAction("Scan repository HEAD", + scan_repository_action = QtGui.QAction("Scan repository HEAD", self.el) def scan_repository(): @@ -253,15 +254,14 @@ class ExplorerDock(QtWidgets.QDockWidget): scan_repository_action.triggered.connect(scan_repository) self.el.addAction(scan_repository_action) - scan_ddb_action = QtWidgets.QAction("Scan device database", self.el) - + scan_ddb_action = QtGui.QAction("Scan device database", self.el) def scan_ddb(): asyncio.ensure_future(device_db_ctl.scan()) scan_ddb_action.triggered.connect(scan_ddb) self.el.addAction(scan_ddb_action) self.current_directory = "" - open_file_action = QtWidgets.QAction("Open file outside repository", + open_file_action = QtGui.QAction("Open file outside repository", self.el) open_file_action.triggered.connect( lambda: _OpenFileDialog(self, self.exp_manager, diff --git a/artiq/dashboard/moninj.py b/artiq/dashboard/moninj.py index e314c960b..65b190eac 100644 --- a/artiq/dashboard/moninj.py +++ b/artiq/dashboard/moninj.py @@ -4,7 +4,7 @@ import textwrap from collections import namedtuple from functools import partial -from PyQt5 import QtCore, QtWidgets +from PyQt6 import QtCore, QtWidgets, QtGui from artiq.coredevice.comm_moninj import CommMonInj, TTLOverride, TTLProbe from artiq.coredevice.ad9912_reg import AD9912_SER_CONF @@ -23,7 +23,7 @@ class _CancellableLineEdit(QtWidgets.QLineEdit): def keyPressEvent(self, event): key = event.key() - if key == QtCore.Qt.Key_Escape: + if key == QtCore.Qt.Key.Key_Escape: self.esc_cb(event) QtWidgets.QLineEdit.keyPressEvent(self, event) @@ -31,9 +31,8 @@ class _CancellableLineEdit(QtWidgets.QLineEdit): class _MoninjWidget(QtWidgets.QFrame): def __init__(self, title): QtWidgets.QFrame.__init__(self) - self.setFrameShape(QtWidgets.QFrame.Box) - self.setFrameShape(QtWidgets.QFrame.Box) - self.setFrameShadow(QtWidgets.QFrame.Raised) + self.setFrameShape(QtWidgets.QFrame.Shape.Box) + self.setFrameShadow(QtWidgets.QFrame.Shadow.Raised) self.setFixedHeight(100) self.setFixedWidth(150) self.grid = QtWidgets.QGridLayout() @@ -43,7 +42,9 @@ class _MoninjWidget(QtWidgets.QFrame): self.setLayout(self.grid) title = elide(title, 20) label = QtWidgets.QLabel(title) - label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignTop) + label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + label.setSizePolicy(QtWidgets.QSizePolicy.Policy.Ignored, + QtWidgets.QSizePolicy.Policy.Preferred) self.grid.addWidget(label, 1, 1) @@ -60,7 +61,7 @@ class _TTLWidget(_MoninjWidget): self.grid.addWidget(self.stack, 2, 1) self.direction = QtWidgets.QLabel() - self.direction.setAlignment(QtCore.Qt.AlignCenter) + self.direction.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) self.stack.addWidget(self.direction) grid_cb = LayoutWidget() @@ -80,7 +81,7 @@ class _TTLWidget(_MoninjWidget): self.stack.addWidget(grid_cb) self.value = QtWidgets.QLabel() - self.value.setAlignment(QtCore.Qt.AlignCenter) + self.value.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) self.grid.addWidget(self.value, 3, 1) self.grid.setRowStretch(1, 1) @@ -215,11 +216,11 @@ class _DDSWidget(_MoninjWidget): grid_disp.layout.setVerticalSpacing(0) self.value_label = QtWidgets.QLabel() - self.value_label.setAlignment(QtCore.Qt.AlignCenter) + self.value_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) grid_disp.addWidget(self.value_label, 0, 1, 1, 2) unit = QtWidgets.QLabel("MHz") - unit.setAlignment(QtCore.Qt.AlignCenter) + unit.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) grid_disp.addWidget(unit, 0, 3, 1, 1) self.data_stack.addWidget(grid_disp) @@ -231,10 +232,10 @@ class _DDSWidget(_MoninjWidget): grid_edit.layout.setVerticalSpacing(0) self.value_edit = _CancellableLineEdit(self) - self.value_edit.setAlignment(QtCore.Qt.AlignRight) + self.value_edit.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight) grid_edit.addWidget(self.value_edit, 0, 1, 1, 2) unit = QtWidgets.QLabel("MHz") - unit.setAlignment(QtCore.Qt.AlignCenter) + unit.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) grid_edit.addWidget(unit, 0, 3, 1, 1) self.data_stack.addWidget(grid_edit) @@ -799,8 +800,8 @@ class _MonInjDock(QDockWidgetCloseDetect): def __init__(self, name, manager): QtWidgets.QDockWidget.__init__(self, "MonInj") self.setObjectName(name) - self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | - QtWidgets.QDockWidget.DockWidgetFloatable) + self.setFeatures(QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable) grid = LayoutWidget() self.setWidget(grid) self.manager = manager diff --git a/artiq/dashboard/schedule.py b/artiq/dashboard/schedule.py index 94c229258..8ea213239 100644 --- a/artiq/dashboard/schedule.py +++ b/artiq/dashboard/schedule.py @@ -3,7 +3,7 @@ import time from functools import partial import logging -from PyQt5 import QtCore, QtWidgets, QtGui +from PyQt6 import QtCore, QtWidgets, QtGui from artiq.gui.models import DictSyncModel from artiq.tools import elide @@ -61,31 +61,31 @@ class ScheduleDock(QtWidgets.QDockWidget): def __init__(self, schedule_ctl, schedule_sub): QtWidgets.QDockWidget.__init__(self, "Schedule") self.setObjectName("Schedule") - self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | - QtWidgets.QDockWidget.DockWidgetFloatable) + self.setFeatures(QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable) self.schedule_ctl = schedule_ctl self.table = QtWidgets.QTableView() - self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) - self.table.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) + self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows) + self.table.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.SingleSelection) self.table.verticalHeader().setSectionResizeMode( - QtWidgets.QHeaderView.ResizeToContents) + QtWidgets.QHeaderView.ResizeMode.ResizeToContents) self.table.verticalHeader().hide() self.setWidget(self.table) - self.table.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) - request_termination_action = QtWidgets.QAction("Request termination", self.table) + self.table.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.ActionsContextMenu) + request_termination_action = QtGui.QAction("Request termination", self.table) request_termination_action.triggered.connect(partial(self.delete_clicked, True)) request_termination_action.setShortcut("DELETE") - request_termination_action.setShortcutContext(QtCore.Qt.WidgetShortcut) + request_termination_action.setShortcutContext(QtCore.Qt.ShortcutContext.WidgetShortcut) self.table.addAction(request_termination_action) - delete_action = QtWidgets.QAction("Delete", self.table) + delete_action = QtGui.QAction("Delete", self.table) delete_action.triggered.connect(partial(self.delete_clicked, False)) delete_action.setShortcut("SHIFT+DELETE") - delete_action.setShortcutContext(QtCore.Qt.WidgetShortcut) + delete_action.setShortcutContext(QtCore.Qt.ShortcutContext.WidgetShortcut) self.table.addAction(delete_action) - terminate_pipeline = QtWidgets.QAction( + terminate_pipeline = QtGui.QAction( "Gracefully terminate all in pipeline", self.table) terminate_pipeline.triggered.connect(self.terminate_pipeline_clicked) self.table.addAction(terminate_pipeline) diff --git a/artiq/dashboard/shortcuts.py b/artiq/dashboard/shortcuts.py index 30217b5f6..cac8c1e54 100644 --- a/artiq/dashboard/shortcuts.py +++ b/artiq/dashboard/shortcuts.py @@ -1,7 +1,7 @@ import logging from functools import partial -from PyQt5 import QtCore, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets logger = logging.getLogger(__name__) @@ -11,8 +11,8 @@ class ShortcutsDock(QtWidgets.QDockWidget): def __init__(self, main_window, exp_manager): QtWidgets.QDockWidget.__init__(self, "Shortcuts") self.setObjectName("Shortcuts") - self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | - QtWidgets.QDockWidget.DockWidgetFloatable) + self.setFeatures(QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable) layout = QtWidgets.QGridLayout() top_widget = QtWidgets.QWidget() @@ -36,25 +36,25 @@ class ShortcutsDock(QtWidgets.QDockWidget): layout.addWidget(QtWidgets.QLabel("F" + str(i + 1)), row, 0) label = QtWidgets.QLabel() - label.setSizePolicy(QtWidgets.QSizePolicy.Ignored, - QtWidgets.QSizePolicy.Ignored) + label.setSizePolicy(QtWidgets.QSizePolicy.Policy.Ignored, + QtWidgets.QSizePolicy.Policy.Ignored) layout.addWidget(label, row, 1) clear = QtWidgets.QToolButton() clear.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DialogDiscardButton)) + QtWidgets.QStyle.StandardPixmap.SP_DialogDiscardButton)) layout.addWidget(clear, row, 2) clear.clicked.connect(partial(self.set_shortcut, i, "")) open = QtWidgets.QToolButton() open.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DialogOpenButton)) + QtWidgets.QStyle.StandardPixmap.SP_DialogOpenButton)) layout.addWidget(open, row, 3) open.clicked.connect(partial(self._open_experiment, i)) submit = QtWidgets.QPushButton("Submit") submit.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DialogOkButton)) + QtWidgets.QStyle.StandardPixmap.SP_DialogOkButton)) layout.addWidget(submit, row, 4) submit.clicked.connect(partial(self._activated, i)) @@ -68,8 +68,8 @@ class ShortcutsDock(QtWidgets.QDockWidget): "open": open, "submit": submit } - shortcut = QtWidgets.QShortcut("F" + str(i + 1), main_window) - shortcut.setContext(QtCore.Qt.ApplicationShortcut) + shortcut = QtGui.QShortcut("F" + str(i+1), main_window) + shortcut.setContext(QtCore.Qt.ShortcutContext.ApplicationShortcut) shortcut.activated.connect(partial(self._activated, i)) def _activated(self, nr): diff --git a/artiq/examples/no_hardware/repository/custom_applet.py b/artiq/examples/no_hardware/repository/custom_applet.py index 0bc124325..78eb5618c 100644 --- a/artiq/examples/no_hardware/repository/custom_applet.py +++ b/artiq/examples/no_hardware/repository/custom_applet.py @@ -1,4 +1,4 @@ -from PyQt5 import QtWidgets +from PyQt6 import QtWidgets from artiq.applets.simple import SimpleApplet diff --git a/artiq/frontend/artiq_browser.py b/artiq/frontend/artiq_browser.py index 751c57d2e..c6c5d1b76 100755 --- a/artiq/frontend/artiq_browser.py +++ b/artiq/frontend/artiq_browser.py @@ -7,7 +7,7 @@ import os import logging import sys -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets from qasync import QEventLoop from sipyco.asyncio_tools import atexit_register_coroutine @@ -68,9 +68,9 @@ class Browser(QtWidgets.QMainWindow): browse_root, dataset_sub) smgr.register(self.experiments) self.experiments.setHorizontalScrollBarPolicy( - QtCore.Qt.ScrollBarAsNeeded) + QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded) self.experiments.setVerticalScrollBarPolicy( - QtCore.Qt.ScrollBarAsNeeded) + QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded) self.setCentralWidget(self.experiments) self.files = files.FilesDock(dataset_sub, browse_root) @@ -91,29 +91,29 @@ class Browser(QtWidgets.QMainWindow): self.log = log.LogDock(None, "log") smgr.register(self.log) - self.log.setFeatures(self.log.DockWidgetMovable | - self.log.DockWidgetFloatable) + self.log.setFeatures(self.log.DockWidgetFeature.DockWidgetMovable | + self.log.DockWidgetFeature.DockWidgetFloatable) - self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.files) - self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.applets) - self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.datasets) - self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.log) + self.addDockWidget(QtCore.Qt.DockWidgetArea.LeftDockWidgetArea, self.files) + self.addDockWidget(QtCore.Qt.DockWidgetArea.BottomDockWidgetArea, self.applets) + self.addDockWidget(QtCore.Qt.DockWidgetArea.RightDockWidgetArea, self.datasets) + self.addDockWidget(QtCore.Qt.DockWidgetArea.BottomDockWidgetArea, self.log) g = self.menuBar().addMenu("&Experiment") - a = QtWidgets.QAction("&Open", self) + a = QtGui.QAction("&Open", self) a.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DialogOpenButton)) - a.setShortcuts(QtGui.QKeySequence.Open) + QtWidgets.QStyle.StandardPixmap.SP_DialogOpenButton)) + a.setShortcuts(QtGui.QKeySequence.StandardKey.Open) a.setStatusTip("Open an experiment") a.triggered.connect(self.experiments.select_experiment) g.addAction(a) g = self.menuBar().addMenu("&View") - a = QtWidgets.QAction("Cascade", self) + a = QtGui.QAction("Cascade", self) a.setStatusTip("Cascade experiment windows") a.triggered.connect(self.experiments.cascadeSubWindows) g.addAction(a) - a = QtWidgets.QAction("Tile", self) + a = QtGui.QAction("Tile", self) a.setStatusTip("Tile experiment windows") a.triggered.connect(self.experiments.tileSubWindows) g.addAction(a) diff --git a/artiq/frontend/artiq_dashboard.py b/artiq/frontend/artiq_dashboard.py index a0606c391..297081ac3 100755 --- a/artiq/frontend/artiq_dashboard.py +++ b/artiq/frontend/artiq_dashboard.py @@ -7,7 +7,7 @@ import importlib import os import logging -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets from qasync import QEventLoop from sipyco.pc_rpc import AsyncioClient, Client @@ -186,8 +186,8 @@ def main(): main_window = MainWindow(args.server if server_name is None else server_name) smgr.register(main_window) mdi_area = MdiArea() - mdi_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - mdi_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) + mdi_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded) + mdi_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded) main_window.setCentralWidget(mdi_area) # create UI components @@ -257,10 +257,10 @@ def main(): d_datasets, d_applets, d_waveform, d_interactive_args ] - main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, right_docks[0]) + main_window.addDockWidget(QtCore.Qt.DockWidgetArea.RightDockWidgetArea, right_docks[0]) for d1, d2 in zip(right_docks, right_docks[1:]): main_window.tabifyDockWidget(d1, d2) - main_window.addDockWidget(QtCore.Qt.BottomDockWidgetArea, d_schedule) + main_window.addDockWidget(QtCore.Qt.DockWidgetArea.BottomDockWidgetArea, d_schedule) # load/initialize state if os.name == "nt": diff --git a/artiq/gui/applets.py b/artiq/gui/applets.py index 9609fbac0..36e826a7d 100644 --- a/artiq/gui/applets.py +++ b/artiq/gui/applets.py @@ -9,7 +9,7 @@ from functools import partial from itertools import count from types import SimpleNamespace -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets from sipyco.pipe_ipc import AsyncioParentComm from sipyco.logging_tools import LogParser @@ -388,8 +388,8 @@ class _CompleterDelegate(QtWidgets.QStyledItemDelegate): completer = QtWidgets.QCompleter() completer.splitPath = lambda path: path.replace("/", ".").split(".") completer.setModelSorting( - QtWidgets.QCompleter.CaseSensitivelySortedModel) - completer.setCompletionRole(QtCore.Qt.DisplayRole) + QtWidgets.QCompleter.ModelSorting.CaseSensitivelySortedModel) + completer.setCompletionRole(QtCore.Qt.ItemDataRole.DisplayRole) if hasattr(self, "model"): # "TODO: Optimize updates in the source model" # - Qt (qcompleter.cpp), never ceasing to disappoint. @@ -420,8 +420,8 @@ class AppletsDock(QtWidgets.QDockWidget): """ QtWidgets.QDockWidget.__init__(self, "Applets") self.setObjectName("Applets") - self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | - QtWidgets.QDockWidget.DockWidgetFloatable) + self.setFeatures(QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable) self.main_window = main_window self.dataset_sub = dataset_sub @@ -435,18 +435,18 @@ class AppletsDock(QtWidgets.QDockWidget): self.table = QtWidgets.QTreeWidget() self.table.setColumnCount(2) self.table.setHeaderLabels(["Name", "Command"]) - self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) - self.table.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) + self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows) + self.table.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.SingleSelection) self.table.header().setStretchLastSection(True) self.table.header().setSectionResizeMode( - QtWidgets.QHeaderView.ResizeToContents) - self.table.setTextElideMode(QtCore.Qt.ElideNone) + QtWidgets.QHeaderView.ResizeMode.ResizeToContents) + self.table.setTextElideMode(QtCore.Qt.TextElideMode.ElideNone) self.table.setDragEnabled(True) self.table.viewport().setAcceptDrops(True) self.table.setDropIndicatorShown(True) - self.table.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove) + self.table.setDragDropMode(QtWidgets.QAbstractItemView.DragDropMode.InternalMove) self.setWidget(self.table) @@ -454,44 +454,44 @@ class AppletsDock(QtWidgets.QDockWidget): self.table.setItemDelegateForColumn(1, completer_delegate) dataset_sub.add_setmodel_callback(completer_delegate.set_model) - self.table.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) - new_action = QtWidgets.QAction("New applet", self.table) + self.table.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.ActionsContextMenu) + new_action = QtGui.QAction("New applet", self.table) new_action.triggered.connect(partial(self.new_with_parent, self.new)) self.table.addAction(new_action) templates_menu = QtWidgets.QMenu() for name, template in _templates: spec = {"ty": "command", "command": template} - action = QtWidgets.QAction(name, self.table) + action = QtGui.QAction(name, self.table) action.triggered.connect(partial( self.new_with_parent, self.new, spec=spec)) templates_menu.addAction(action) - restart_action = QtWidgets.QAction("New applet from template", self.table) + restart_action = QtGui.QAction("New applet from template", self.table) restart_action.setMenu(templates_menu) self.table.addAction(restart_action) - restart_action = QtWidgets.QAction("Restart selected applet or group", self.table) + restart_action = QtGui.QAction("Restart selected applet or group", self.table) restart_action.setShortcut("CTRL+R") - restart_action.setShortcutContext(QtCore.Qt.WidgetShortcut) + restart_action.setShortcutContext(QtCore.Qt.ShortcutContext.WidgetShortcut) restart_action.triggered.connect(self.restart) self.table.addAction(restart_action) - delete_action = QtWidgets.QAction("Delete selected applet or group", self.table) + delete_action = QtGui.QAction("Delete selected applet or group", self.table) delete_action.setShortcut("DELETE") - delete_action.setShortcutContext(QtCore.Qt.WidgetShortcut) + delete_action.setShortcutContext(QtCore.Qt.ShortcutContext.WidgetShortcut) delete_action.triggered.connect(self.delete) self.table.addAction(delete_action) - close_nondocked_action = QtWidgets.QAction("Close non-docked applets", self.table) + close_nondocked_action = QtGui.QAction("Close non-docked applets", self.table) close_nondocked_action.setShortcut("CTRL+ALT+W") - close_nondocked_action.setShortcutContext(QtCore.Qt.ApplicationShortcut) + close_nondocked_action.setShortcutContext(QtCore.Qt.ShortcutContext.ApplicationShortcut) close_nondocked_action.triggered.connect(self.close_nondocked) self.table.addAction(close_nondocked_action) - new_group_action = QtWidgets.QAction("New group", self.table) + new_group_action = QtGui.QAction("New group", self.table) new_group_action.triggered.connect(partial(self.new_with_parent, self.new_group)) self.table.addAction(new_group_action) self.table.itemChanged.connect(self.item_changed) # HACK - self.table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) + self.table.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers) self.table.itemDoubleClicked.connect(self.open_editor) def open_editor(self, item, column): @@ -518,7 +518,7 @@ class AppletsDock(QtWidgets.QDockWidget): del item.applet_code elif spec["ty"] == "code": item.setIcon(1, QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_FileIcon)) + QtWidgets.QStyle.StandardPixmap.SP_FileIcon)) item.applet_code = spec["code"] else: raise ValueError @@ -530,7 +530,7 @@ class AppletsDock(QtWidgets.QDockWidget): def create(self, item, name, spec): dock = _AppletDock(self.dataset_sub, self.dataset_ctl, self.expmgr, item.applet_uid, name, spec, self.extra_substitutes) - self.main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) + self.main_window.addDockWidget(QtCore.Qt.DockWidgetArea.RightDockWidgetArea, dock) dock.setFloating(True) asyncio.ensure_future(dock.start(), loop=self._loop) dock.sigClosed.connect(partial(self.on_dock_closed, item, dock)) @@ -547,7 +547,7 @@ class AppletsDock(QtWidgets.QDockWidget): dock.spec = self.get_spec(item) if column == 0: - if item.checkState(0) == QtCore.Qt.Checked: + if item.checkState(0) == QtCore.Qt.CheckState.Checked: if item.applet_dock is None: name = item.text(0) spec = self.get_spec(item) @@ -572,7 +572,7 @@ class AppletsDock(QtWidgets.QDockWidget): def on_dock_closed(self, item, dock): item.applet_geometry = dock.saveGeometry() asyncio.ensure_future(dock.terminate(), loop=self._loop) - item.setCheckState(0, QtCore.Qt.Unchecked) + item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) def get_untitled(self): existing_names = set() @@ -602,18 +602,18 @@ class AppletsDock(QtWidgets.QDockWidget): name = self.get_untitled() item = QtWidgets.QTreeWidgetItem([name, ""]) item.ty = "applet" - item.setFlags(QtCore.Qt.ItemIsSelectable | - QtCore.Qt.ItemIsUserCheckable | - QtCore.Qt.ItemIsEditable | - QtCore.Qt.ItemIsDragEnabled | - QtCore.Qt.ItemNeverHasChildren | - QtCore.Qt.ItemIsEnabled) - item.setCheckState(0, QtCore.Qt.Unchecked) + item.setFlags(QtCore.Qt.ItemFlag.ItemIsSelectable | + QtCore.Qt.ItemFlag.ItemIsUserCheckable | + QtCore.Qt.ItemFlag.ItemIsEditable | + QtCore.Qt.ItemFlag.ItemIsDragEnabled | + QtCore.Qt.ItemFlag.ItemNeverHasChildren | + QtCore.Qt.ItemFlag.ItemIsEnabled) + item.setCheckState(0, QtCore.Qt.CheckState.Unchecked) item.applet_uid = uid item.applet_dock = None item.applet_geometry = None item.setIcon(0, QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_ComputerIcon)) + QtWidgets.QStyle.StandardPixmap.SP_ComputerIcon)) self.set_spec(item, spec) if parent is None: self.table.addTopLevelItem(item) @@ -626,15 +626,15 @@ class AppletsDock(QtWidgets.QDockWidget): name = self.get_untitled() item = QtWidgets.QTreeWidgetItem([name, attr]) item.ty = "group" - item.setFlags(QtCore.Qt.ItemIsSelectable | - QtCore.Qt.ItemIsEditable | - QtCore.Qt.ItemIsUserCheckable | - QtCore.Qt.ItemIsTristate | - QtCore.Qt.ItemIsDragEnabled | - QtCore.Qt.ItemIsDropEnabled | - QtCore.Qt.ItemIsEnabled) + item.setFlags(QtCore.Qt.ItemFlag.ItemIsSelectable | + QtCore.Qt.ItemFlag.ItemIsEditable | + QtCore.Qt.ItemFlag.ItemIsUserCheckable | + QtCore.Qt.ItemFlag.ItemIsAutoTristate | + QtCore.Qt.ItemFlag.ItemIsDragEnabled | + QtCore.Qt.ItemFlag.ItemIsDropEnabled | + QtCore.Qt.ItemFlag.ItemIsEnabled) item.setIcon(0, QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DirIcon)) + QtWidgets.QStyle.StandardPixmap.SP_DirIcon)) if parent is None: self.table.addTopLevelItem(item) else: @@ -712,7 +712,7 @@ class AppletsDock(QtWidgets.QDockWidget): cwi = wi.child(row) if cwi.ty == "applet": uid = cwi.applet_uid - enabled = cwi.checkState(0) == QtCore.Qt.Checked + enabled = cwi.checkState(0) == QtCore.Qt.CheckState.Checked name = cwi.text(0) spec = self.get_spec(cwi) geometry = cwi.applet_geometry @@ -744,7 +744,7 @@ class AppletsDock(QtWidgets.QDockWidget): geometry = QtCore.QByteArray(geometry) item.applet_geometry = geometry if enabled: - item.setCheckState(0, QtCore.Qt.Checked) + item.setCheckState(0, QtCore.Qt.CheckState.Checked) elif wis[0] == "group": _, name, attr, expanded, state_child = wis item = self.new_group(name, attr, parent=parent) @@ -761,11 +761,11 @@ class AppletsDock(QtWidgets.QDockWidget): for i in range(wi.childCount()): cwi = wi.child(i) if cwi.ty == "applet": - if cwi.checkState(0) == QtCore.Qt.Checked: + if cwi.checkState(0) == QtCore.Qt.CheckState.Checked: if cwi.applet_dock is not None: if not cwi.applet_dock.isFloating(): continue - cwi.setCheckState(0, QtCore.Qt.Unchecked) + cwi.setCheckState(0, QtCore.Qt.CheckState.Unchecked) elif cwi.ty == "group": walk(cwi) walk(self.table.invisibleRootItem()) diff --git a/artiq/gui/entries.py b/artiq/gui/entries.py index 43daa7a5b..0a726a77e 100644 --- a/artiq/gui/entries.py +++ b/artiq/gui/entries.py @@ -2,7 +2,7 @@ import logging from collections import OrderedDict from functools import partial -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets from artiq.gui.tools import LayoutWidget, disable_scroll_wheel, WheelFilter from artiq.gui.scanwidget import ScanWidget @@ -540,7 +540,8 @@ class _ExplicitScan(LayoutWidget): float_regexp = r"(([+-]?\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?)" regexp = "(float)?( +float)* *".replace("float", float_regexp) - self.value.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(regexp))) + self.value.setValidator(QtGui.QRegularExpressionValidator( + QtCore.QRegularExpression(regexp))) self.value.setText(" ".join([str(x) for x in state["sequence"]])) def update(text): diff --git a/artiq/gui/flowlayout.py b/artiq/gui/flowlayout.py index da6973d90..d597197e0 100644 --- a/artiq/gui/flowlayout.py +++ b/artiq/gui/flowlayout.py @@ -39,8 +39,8 @@ ############################################################################# -from PyQt5.QtCore import QPoint, QRect, QSize, Qt -from PyQt5.QtWidgets import (QApplication, QLayout, QPushButton, QSizePolicy, +from PyQt6.QtCore import QPoint, QRect, QSize, Qt +from PyQt6.QtWidgets import (QApplication, QLayout, QPushButton, QSizePolicy, QWidget) @@ -113,8 +113,8 @@ class FlowLayout(QLayout): for item in self.itemList: wid = item.widget() - spaceX = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal) - spaceY = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical) + spaceX = self.spacing() + wid.style().layoutSpacing(QSizePolicy.ControlType.PushButton, QSizePolicy.ControlType.PushButton, Qt.Orientation.Horizontal) + spaceY = self.spacing() + wid.style().layoutSpacing(QSizePolicy.ControlType.PushButton, QSizePolicy.ControlType.PushButton, Qt.Orientation.Vertical) nextX = x + item.sizeHint().width() + spaceX if nextX - spaceX > rect.right() and lineHeight > 0: x = rect.x() diff --git a/artiq/gui/fuzzy_select.py b/artiq/gui/fuzzy_select.py index fe1daa668..36d8db2d3 100644 --- a/artiq/gui/fuzzy_select.py +++ b/artiq/gui/fuzzy_select.py @@ -2,7 +2,7 @@ import re from functools import partial from typing import List, Tuple -from PyQt5 import QtCore, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets from artiq.gui.tools import LayoutWidget @@ -19,7 +19,7 @@ class FuzzySelectWidget(LayoutWidget): #: Raised when an entry has been selected, giving the label of the user #: choice and any additional QEvent.modifiers() (e.g. Ctrl key pressed). - finished = QtCore.pyqtSignal(str, int) + finished = QtCore.pyqtSignal(str, QtCore.Qt.KeyboardModifier) def __init__(self, choices: List[Tuple[str, int]] = [], @@ -138,16 +138,16 @@ class FuzzySelectWidget(LayoutWidget): first_action = None last_action = None for choice in filtered_choices: - action = QtWidgets.QAction(choice, self.menu) + action = QtGui.QAction(choice, self.menu) action.triggered.connect(partial(self._finish, action, choice)) - action.modifiers = 0 + action.modifiers = QtCore.Qt.KeyboardModifier.NoModifier self.menu.addAction(action) if not first_action: first_action = action last_action = action if num_omitted > 0: - action = QtWidgets.QAction("<{} not shown>".format(num_omitted), + action = QtGui.QAction("<{} not shown>".format(num_omitted), self.menu) action.setEnabled(False) self.menu.addAction(action) @@ -239,9 +239,9 @@ class _FocusEventFilter(QtCore.QObject): focus_lost = QtCore.pyqtSignal() def eventFilter(self, obj, event): - if event.type() == QtCore.QEvent.FocusIn: + if event.type() == QtCore.QEvent.Type.FocusIn: self.focus_gained.emit() - elif event.type() == QtCore.QEvent.FocusOut: + elif event.type() == QtCore.QEvent.Type.FocusOut: self.focus_lost.emit() return False @@ -251,8 +251,8 @@ class _EscapeKeyFilter(QtCore.QObject): escape_pressed = QtCore.pyqtSignal() def eventFilter(self, obj, event): - if event.type() == QtCore.QEvent.KeyPress: - if event.key() == QtCore.Qt.Key_Escape: + if event.type() == QtCore.QEvent.Type.KeyPress: + if event.key() == QtCore.Qt.Key.Key_Escape: self.escape_pressed.emit() return False @@ -266,13 +266,13 @@ class _UpDownKeyFilter(QtCore.QObject): self.last_item = last_item def eventFilter(self, obj, event): - if event.type() == QtCore.QEvent.KeyPress: - if event.key() == QtCore.Qt.Key_Down: + if event.type() == QtCore.QEvent.Type.KeyPress: + if event.key() == QtCore.Qt.Key.Key_Down: self.menu.setActiveAction(self.first_item) self.menu.setFocus() return True - if event.key() == QtCore.Qt.Key_Up: + if event.key() == QtCore.Qt.Key.Key_Up: self.menu.setActiveAction(self.last_item) self.menu.setFocus() return True @@ -286,16 +286,16 @@ class _NonUpDownKeyFilter(QtCore.QObject): self.target = target def eventFilter(self, obj, event): - if event.type() == QtCore.QEvent.KeyPress: + if event.type() == QtCore.QEvent.Type.KeyPress: k = event.key() - if k in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter): + if k in (QtCore.Qt.Key.Key_Return, QtCore.Qt.Key.Key_Enter): action = obj.activeAction() if action is not None: action.modifiers = event.modifiers() return False - if (k != QtCore.Qt.Key_Down and k != QtCore.Qt.Key_Up - and k != QtCore.Qt.Key_Enter - and k != QtCore.Qt.Key_Return): + if (k != QtCore.Qt.Key.Key_Down and k != QtCore.Qt.Key.Key_Up + and k != QtCore.Qt.Key.Key_Enter + and k != QtCore.Qt.Key.Key_Return): QtWidgets.QApplication.sendEvent(self.target, event) return True return False diff --git a/artiq/gui/log.py b/artiq/gui/log.py index 3b5095f98..d0f0c147d 100644 --- a/artiq/gui/log.py +++ b/artiq/gui/log.py @@ -3,7 +3,7 @@ import time import re from functools import partial -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets from sipyco.logging_tools import SourceFilter from artiq.gui.tools import (LayoutWidget, log_level_to_name, @@ -20,7 +20,7 @@ class _ModelItem: class _LogFilterProxyModel(QtCore.QSortFilterProxyModel): def __init__(self): super().__init__() - self.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive) + self.setFilterCaseSensitivity(QtCore.Qt.CaseSensitivity.CaseInsensitive) self.setRecursiveFilteringEnabled(True) self.filter_level = 0 @@ -28,13 +28,13 @@ class _LogFilterProxyModel(QtCore.QSortFilterProxyModel): source = self.sourceModel() index0 = source.index(source_row, 0, source_parent) index1 = source.index(source_row, 1, source_parent) - level = source.data(index0, QtCore.Qt.UserRole) + level = source.data(index0, QtCore.Qt.ItemDataRole.UserRole) if level >= self.filter_level: - regex = self.filterRegExp() - index0_text = source.data(index0, QtCore.Qt.DisplayRole) - msg_text = source.data(index1, QtCore.Qt.DisplayRole) - return (regex.indexIn(index0_text) != -1 or regex.indexIn(msg_text) != -1) + regex = self.filterRegularExpression() + index0_text = source.data(index0, QtCore.Qt.ItemDataRole.DisplayRole) + msg_text = source.data(index1, QtCore.Qt.ItemDataRole.DisplayRole) + return (regex.match(index0_text).hasMatch() or regex.match(msg_text).hasMatch()) else: return False @@ -57,7 +57,7 @@ class _Model(QtCore.QAbstractItemModel): timer.timeout.connect(self.timer_tick) timer.start(100) - self.fixed_font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont) + self.fixed_font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.SystemFont.FixedFont) self.white = QtGui.QBrush(QtGui.QColor(255, 255, 255)) self.black = QtGui.QBrush(QtGui.QColor(0, 0, 0)) @@ -66,8 +66,8 @@ class _Model(QtCore.QAbstractItemModel): self.error_bg = QtGui.QBrush(QtGui.QColor(255, 150, 150)) def headerData(self, col, orientation, role): - if (orientation == QtCore.Qt.Horizontal - and role == QtCore.Qt.DisplayRole): + if (orientation == QtCore.Qt.Orientation.Horizontal + and role == QtCore.Qt.ItemDataRole.DisplayRole): return self.headers[col] return None @@ -155,9 +155,9 @@ class _Model(QtCore.QAbstractItemModel): else: msgnum = item.parent.row - if role == QtCore.Qt.FontRole and index.column() == 1: + if role == QtCore.Qt.ItemDataRole.FontRole and index.column() == 1: return self.fixed_font - elif role == QtCore.Qt.BackgroundRole: + elif role == QtCore.Qt.ItemDataRole.BackgroundRole: level = self.entries[msgnum][0] if level >= logging.ERROR: return self.error_bg @@ -165,13 +165,13 @@ class _Model(QtCore.QAbstractItemModel): return self.warning_bg else: return self.white - elif role == QtCore.Qt.ForegroundRole: + elif role == QtCore.Qt.ItemDataRole.ForegroundRole: level = self.entries[msgnum][0] if level <= logging.DEBUG: return self.debug_fg else: return self.black - elif role == QtCore.Qt.DisplayRole: + elif role == QtCore.Qt.ItemDataRole.DisplayRole: v = self.entries[msgnum] column = index.column() if item.parent is self: @@ -184,7 +184,7 @@ class _Model(QtCore.QAbstractItemModel): return "" else: return v[3][item.row+1] - elif role == QtCore.Qt.ToolTipRole: + elif role == QtCore.Qt.ItemDataRole.ToolTipRole: v = self.entries[msgnum] if item.parent is self: lineno = 0 @@ -193,7 +193,7 @@ class _Model(QtCore.QAbstractItemModel): return (log_level_to_name(v[0]) + ", " + time.strftime("%m/%d %H:%M:%S", time.localtime(v[2])) + "\n" + v[3][lineno]) - elif role == QtCore.Qt.UserRole: + elif role == QtCore.Qt.ItemDataRole.UserRole: return self.entries[msgnum][0] @@ -218,13 +218,13 @@ class LogDock(QDockWidgetCloseDetect): scrollbottom = QtWidgets.QToolButton() scrollbottom.setToolTip("Scroll to bottom") scrollbottom.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_ArrowDown)) + QtWidgets.QStyle.StandardPixmap.SP_ArrowDown)) grid.addWidget(scrollbottom, 0, 3) scrollbottom.clicked.connect(self.scroll_to_bottom) clear = QtWidgets.QToolButton() clear.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_DialogResetButton)) + QtWidgets.QStyle.StandardPixmap.SP_DialogResetButton)) grid.addWidget(clear, 0, 4) clear.clicked.connect(lambda: self.model.clear()) @@ -232,7 +232,7 @@ class LogDock(QDockWidgetCloseDetect): newdock = QtWidgets.QToolButton() newdock.setToolTip("Create new log dock") newdock.setIcon(QtWidgets.QApplication.style().standardIcon( - QtWidgets.QStyle.SP_FileDialogNewFolder)) + QtWidgets.QStyle.StandardPixmap.SP_FileDialogNewFolder)) # note the lambda, the default parameter is overriden otherwise newdock.clicked.connect(lambda: manager.create_new_dock()) grid.addWidget(newdock, 0, 5) @@ -240,27 +240,27 @@ class LogDock(QDockWidgetCloseDetect): self.log = QtWidgets.QTreeView() self.log.setHorizontalScrollMode( - QtWidgets.QAbstractItemView.ScrollPerPixel) + QtWidgets.QAbstractItemView.ScrollMode.ScrollPerPixel) self.log.setVerticalScrollMode( - QtWidgets.QAbstractItemView.ScrollPerPixel) - self.log.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) + QtWidgets.QAbstractItemView.ScrollMode.ScrollPerPixel) + self.log.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded) grid.addWidget(self.log, 1, 0, colspan=6 if manager else 5) self.scroll_at_bottom = False self.scroll_value = 0 - self.log.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) - copy_action = QtWidgets.QAction("Copy entry to clipboard", self.log) + self.log.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.ActionsContextMenu) + copy_action = QtGui.QAction("Copy entry to clipboard", self.log) copy_action.triggered.connect(self.copy_to_clipboard) self.log.addAction(copy_action) - clear_action = QtWidgets.QAction("Clear", self.log) + clear_action = QtGui.QAction("Clear", self.log) clear_action.triggered.connect(lambda: self.model.clear()) self.log.addAction(clear_action) # If Qt worked correctly, this would be nice to have. Alas, resizeSections # is broken when the horizontal scrollbar is enabled. - # sizeheader_action = QtWidgets.QAction("Resize header", self.log) + # sizeheader_action = QtGui.QAction("Resize header", self.log) # sizeheader_action.triggered.connect( - # lambda: self.log.header().resizeSections(QtWidgets.QHeaderView.ResizeToContents)) + # lambda: self.log.header().resizeSections(QtWidgets.QHeaderView.ResizeMode.ResizeToContents)) # self.log.addAction(sizeheader_action) cw = QtGui.QFontMetrics(self.font()).averageCharWidth() @@ -279,7 +279,7 @@ class LogDock(QDockWidgetCloseDetect): self.filter_level.currentIndexChanged.connect(self.apply_level_filter) def apply_text_filter(self): - self.proxy_model.setFilterRegExp(self.filter_freetext.text()) + self.proxy_model.setFilterRegularExpression(self.filter_freetext.text()) def apply_level_filter(self): self.proxy_model.apply_filter_level(self.filter_level.currentText()) @@ -366,7 +366,7 @@ class LogDockManager: dock = LogDock(self, name) self.docks[name] = dock if add_to_area: - self.main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) + self.main_window.addDockWidget(QtCore.Qt.DockWidgetArea.RightDockWidgetArea, dock) dock.setFloating(True) dock.sigClosed.connect(partial(self.on_dock_closed, name)) self.update_closable() @@ -379,8 +379,8 @@ class LogDockManager: self.update_closable() def update_closable(self): - flags = (QtWidgets.QDockWidget.DockWidgetMovable | - QtWidgets.QDockWidget.DockWidgetFloatable) + flags = (QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetFloatable) if len(self.docks) > 1: flags |= QtWidgets.QDockWidget.DockWidgetClosable for dock in self.docks.values(): @@ -396,7 +396,7 @@ class LogDockManager: dock = LogDock(self, name) self.docks[name] = dock dock.restore_state(dock_state) - self.main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) + self.main_window.addDockWidget(QtCore.Qt.DockWidgetArea.RightDockWidgetArea, dock) dock.sigClosed.connect(partial(self.on_dock_closed, name)) self.update_closable() diff --git a/artiq/gui/models.py b/artiq/gui/models.py index 4d6f19c22..810fa4505 100644 --- a/artiq/gui/models.py +++ b/artiq/gui/models.py @@ -1,4 +1,4 @@ -from PyQt5 import QtCore +from PyQt6 import QtCore from sipyco.sync_struct import Subscriber, process_mod @@ -91,15 +91,15 @@ class DictSyncModel(QtCore.QAbstractTableModel): return len(self.headers) def data(self, index, role): - if not index.isValid() or role != QtCore.Qt.DisplayRole: + if not index.isValid() or role != QtCore.Qt.ItemDataRole.DisplayRole: return None else: k = self.row_to_key[index.row()] return self.convert(k, self.backing_store[k], index.column()) def headerData(self, col, orientation, role): - if (orientation == QtCore.Qt.Horizontal and - role == QtCore.Qt.DisplayRole): + if (orientation == QtCore.Qt.Orientation.Horizontal and + role == QtCore.Qt.ItemDataRole.DisplayRole): return self.headers[col] return None @@ -170,15 +170,15 @@ class ListSyncModel(QtCore.QAbstractTableModel): return len(self.headers) def data(self, index, role): - if not index.isValid() or role != QtCore.Qt.DisplayRole: + if not index.isValid() or role != QtCore.Qt.ItemDataRole.DisplayRole: return None else: return self.convert(self.backing_store[index.row()], index.column()) def headerData(self, col, orientation, role): - if (orientation == QtCore.Qt.Horizontal and - role == QtCore.Qt.DisplayRole): + if (orientation == QtCore.Qt.Orientation.Horizontal and + role == QtCore.Qt.ItemDataRole.DisplayRole): return self.headers[col] return None @@ -271,8 +271,8 @@ class DictSyncTreeSepModel(QtCore.QAbstractItemModel): return len(self.headers) def headerData(self, col, orientation, role): - if (orientation == QtCore.Qt.Horizontal and - role == QtCore.Qt.DisplayRole): + if (orientation == QtCore.Qt.Orientation.Horizontal and + role == QtCore.Qt.ItemDataRole.DisplayRole): return self.headers[col] return None @@ -394,19 +394,19 @@ class DictSyncTreeSepModel(QtCore.QAbstractItemModel): return key def data(self, index, role): - if not index.isValid() or (role != QtCore.Qt.DisplayRole - and role != QtCore.Qt.ToolTipRole): + if not index.isValid() or (role != QtCore.Qt.ItemDataRole.DisplayRole + and role != QtCore.Qt.ItemDataRole.ToolTipRole): return None else: column = index.column() - if column == 0 and role == QtCore.Qt.DisplayRole: + if column == 0 and role == QtCore.Qt.ItemDataRole.DisplayRole: return index.internalPointer().name else: key = self.index_to_key(index) if key is None: return None else: - if role == QtCore.Qt.DisplayRole: + if role == QtCore.Qt.ItemDataRole.DisplayRole: convert = self.convert else: convert = self.convert_tooltip diff --git a/artiq/gui/scanwidget.py b/artiq/gui/scanwidget.py index e3231c6ab..b2aeb8bde 100644 --- a/artiq/gui/scanwidget.py +++ b/artiq/gui/scanwidget.py @@ -1,6 +1,6 @@ import logging -from PyQt5 import QtGui, QtCore, QtWidgets +from PyQt6 import QtGui, QtCore, QtWidgets import numpy as np from .ticker import Ticker @@ -23,15 +23,15 @@ class ScanWidget(QtWidgets.QWidget): self.ticker = Ticker() - self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) - action = QtWidgets.QAction("V&iew range", self) + self.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.ActionsContextMenu) + action = QtGui.QAction("V&iew range", self) action.setShortcut(QtGui.QKeySequence("CTRL+i")) - action.setShortcutContext(QtCore.Qt.WidgetShortcut) + action.setShortcutContext(QtCore.Qt.ShortcutContext.WidgetShortcut) action.triggered.connect(self.viewRange) self.addAction(action) - action = QtWidgets.QAction("Sna&p range", self) + action = QtGui.QAction("Sna&p range", self) action.setShortcut(QtGui.QKeySequence("CTRL+p")) - action.setShortcutContext(QtCore.Qt.WidgetShortcut) + action.setShortcutContext(QtCore.Qt.ShortcutContext.WidgetShortcut) action.triggered.connect(self.snapRange) self.addAction(action) @@ -143,56 +143,56 @@ class ScanWidget(QtWidgets.QWidget): if ev.buttons() ^ ev.button(): # buttons changed ev.ignore() return - if ev.modifiers() & QtCore.Qt.ShiftModifier: + if ev.modifiers() & QtCore.Qt.KeyboardModifier.ShiftModifier: self._drag = "select" - self.setStart(self._pixelToAxis(ev.x())) + self.setStart(self._pixelToAxis(ev.position().x())) self.setStop(self._start) - elif ev.modifiers() & QtCore.Qt.ControlModifier: + elif ev.modifiers() & QtCore.Qt.KeyboardModifier.ControlModifier: self._drag = "zoom" - self._offset = QtCore.QPoint(ev.x(), 0) + self._offset = QtCore.QPoint(ev.position().x(), 0) self._rubber = QtWidgets.QRubberBand( QtWidgets.QRubberBand.Rectangle, self) self._rubber.setGeometry(QtCore.QRect( - self._offset, QtCore.QPoint(ev.x(), self.height() - 1))) + self._offset, QtCore.QPoint(ev.position().x(), self.height() - 1))) self._rubber.show() else: qfm = QtGui.QFontMetrics(self.font()) - if ev.y() <= 2.5*qfm.lineSpacing(): + if ev.position().y() <= 2.5*qfm.lineSpacing(): self._drag = "axis" - self._offset = ev.x() - self._axisView[0] + self._offset = ev.position().x() - self._axisView[0] # testing should match inverse drawing order for start/stop elif abs(self._axisToPixel(self._stop) - - ev.x()) < qfm.lineSpacing()/2: + ev.position().x()) < qfm.lineSpacing()/2: self._drag = "stop" - self._offset = ev.x() - self._axisToPixel(self._stop) + self._offset = ev.position().x() - self._axisToPixel(self._stop) elif abs(self._axisToPixel(self._start) - - ev.x()) < qfm.lineSpacing()/2: + ev.position().x()) < qfm.lineSpacing()/2: self._drag = "start" - self._offset = ev.x() - self._axisToPixel(self._start) + self._offset = ev.position().x() - self._axisToPixel(self._start) else: self._drag = "both" - self._offset = (ev.x() - self._axisToPixel(self._start), - ev.x() - self._axisToPixel(self._stop)) + self._offset = (ev.position().x() - self._axisToPixel(self._start), + ev.position().x() - self._axisToPixel(self._stop)) def mouseMoveEvent(self, ev): if not self._drag: ev.ignore() return if self._drag == "select": - self.setStop(self._pixelToAxis(ev.x())) + self.setStop(self._pixelToAxis(ev.position().x())) elif self._drag == "zoom": self._rubber.setGeometry(QtCore.QRect( - self._offset, QtCore.QPoint(ev.x(), self.height() - 1) + self._offset, QtCore.QPoint(ev.position().x(), self.height() - 1) ).normalized()) elif self._drag == "axis": - self._setView(ev.x() - self._offset, self._axisView[1]) + self._setView(ev.position().x() - self._offset, self._axisView[1]) elif self._drag == "start": - self.setStart(self._pixelToAxis(ev.x() - self._offset)) + self.setStart(self._pixelToAxis(ev.position().x() - self._offset)) elif self._drag == "stop": - self.setStop(self._pixelToAxis(ev.x() - self._offset)) + self.setStop(self._pixelToAxis(ev.position().x() - self._offset)) elif self._drag == "both": - self.setStart(self._pixelToAxis(ev.x() - self._offset[0])) - self.setStop(self._pixelToAxis(ev.x() - self._offset[1])) + self.setStart(self._pixelToAxis(ev.position().x() - self._offset[0])) + self.setStop(self._pixelToAxis(ev.position().x() - self._offset[1])) def mouseReleaseEvent(self, ev): if self._drag == "zoom": @@ -217,10 +217,10 @@ class ScanWidget(QtWidgets.QWidget): y = round(ev.angleDelta().y()/120.) if not y: return - if ev.modifiers() & QtCore.Qt.ShiftModifier: + if ev.modifiers() & QtCore.Qt.KeyboardModifier.ShiftModifier: self.setNum(max(1, self._num + y)) else: - self._zoom(self.zoomFactor**y, ev.x()) + self._zoom(self.zoomFactor**y, ev.position().x()) def resizeEvent(self, ev): if not ev.oldSize().isValid() or not ev.oldSize().width(): @@ -245,8 +245,8 @@ class ScanWidget(QtWidgets.QWidget): ticks, prefix, labels = self.ticker(self._pixelToAxis(0), self._pixelToAxis(self.width())) rect = QtCore.QRect(0, 0, self.width(), lineSpacing) - painter.drawText(rect, QtCore.Qt.AlignLeft, prefix) - painter.drawText(rect, QtCore.Qt.AlignRight, self.suffix) + painter.drawText(rect, QtCore.Qt.AlignmentFlag.AlignLeft, prefix) + painter.drawText(rect, QtCore.Qt.AlignmentFlag.AlignRight, self.suffix) painter.translate(0, lineSpacing + ascent) @@ -264,7 +264,7 @@ class ScanWidget(QtWidgets.QWidget): painter.drawLine(int(p), 0, int(p), int(lineSpacing/2)) painter.translate(0, int(lineSpacing/2)) - for x, c in (self._start, QtCore.Qt.blue), (self._stop, QtCore.Qt.red): + for x, c in (self._start, QtCore.Qt.GlobalColor.blue), (self._stop, QtCore.Qt.GlobalColor.red): x = self._axisToPixel(x) painter.setPen(c) painter.setBrush(c) diff --git a/artiq/gui/scientific_spinbox.py b/artiq/gui/scientific_spinbox.py index fcbf48c29..7faedae02 100644 --- a/artiq/gui/scientific_spinbox.py +++ b/artiq/gui/scientific_spinbox.py @@ -1,6 +1,6 @@ import re from math import inf, copysign -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets _float_acceptable = re.compile( @@ -16,8 +16,8 @@ class ScientificSpinBox(QtWidgets.QDoubleSpinBox): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setGroupSeparatorShown(False) - self.setInputMethodHints(QtCore.Qt.ImhNone) - self.setCorrectionMode(self.CorrectToPreviousValue) + self.setInputMethodHints(QtCore.Qt.InputMethodHint.ImhNone) + self.setCorrectionMode(self.CorrectionMode.CorrectToPreviousValue) # singleStep: resolution for step, buttons, accelerators # decimals: absolute rounding granularity # sigFigs: number of significant digits shown @@ -69,11 +69,11 @@ class ScientificSpinBox(QtWidgets.QDoubleSpinBox): clean = clean.rsplit(self.suffix(), 1)[0] try: float(clean) # faster than matching - return QtGui.QValidator.Acceptable, text, pos + return QtGui.QValidator.State.Acceptable, text, pos except ValueError: if re.fullmatch(_float_intermediate, clean): - return QtGui.QValidator.Intermediate, text, pos - return QtGui.QValidator.Invalid, text, pos + return QtGui.QValidator.State.Intermediate, text, pos + return QtGui.QValidator.State.Invalid, text, pos def stepBy(self, s): if abs(s) < 10: # unaccelerated buttons, keys, wheel/trackpad diff --git a/artiq/gui/tools.py b/artiq/gui/tools.py index 957823780..2b277c3e7 100644 --- a/artiq/gui/tools.py +++ b/artiq/gui/tools.py @@ -1,7 +1,7 @@ import asyncio import logging -from PyQt5 import QtCore, QtWidgets +from PyQt6 import QtCore, QtWidgets class DoubleClickLineEdit(QtWidgets.QLineEdit): @@ -56,9 +56,9 @@ class WheelFilter(QtCore.QObject): self.ignore_with_modifier = ignore_with_modifier def eventFilter(self, obj, event): - if event.type() != QtCore.QEvent.Wheel: + if event.type() != QtCore.QEvent.Type.Wheel: return False - has_modifier = event.modifiers() != QtCore.Qt.NoModifier + has_modifier = event.modifiers() != QtCore.Qt.KeyboardModifier.NoModifier if has_modifier == self.ignore_with_modifier: event.ignore() return True @@ -66,7 +66,7 @@ class WheelFilter(QtCore.QObject): def disable_scroll_wheel(widget): - widget.setFocusPolicy(QtCore.Qt.StrongFocus) + widget.setFocusPolicy(QtCore.Qt.FocusPolicy.StrongFocus) widget.installEventFilter(WheelFilter(widget)) @@ -91,8 +91,8 @@ class LayoutWidget(QtWidgets.QWidget): async def get_open_file_name(parent, caption, dir, filter): """like QtWidgets.QFileDialog.getOpenFileName(), but a coroutine""" dialog = QtWidgets.QFileDialog(parent, caption, dir, filter) - dialog.setFileMode(dialog.ExistingFile) - dialog.setAcceptMode(dialog.AcceptOpen) + dialog.setFileMode(dialog.FileMode.ExistingFile) + dialog.setAcceptMode(dialog.AcceptMode.AcceptOpen) fut = asyncio.Future() def on_accept(): @@ -124,7 +124,7 @@ async def get_save_file_name(parent, caption, dir, filter, suffix=None): # http://stackoverflow.com/questions/250890/using-qsortfilterproxymodel-with-a-tree-model class QRecursiveFilterProxyModel(QtCore.QSortFilterProxyModel): def filterAcceptsRow(self, source_row, source_parent): - regexp = self.filterRegExp() + regexp = self.filterRegularExpression() if not regexp.isEmpty(): source_index = self.sourceModel().index( source_row, self.filterKeyColumn(), source_parent) @@ -133,6 +133,6 @@ class QRecursiveFilterProxyModel(QtCore.QSortFilterProxyModel): if self.filterAcceptsRow(i, source_index): return True key = self.sourceModel().data(source_index, self.filterRole()) - return regexp.indexIn(key) != -1 + return regexp.match(key).hasMatch() return QtCore.QSortFilterProxyModel.filterAcceptsRow( self, source_row, source_parent) diff --git a/artiq/gui/waitingspinnerwidget.py b/artiq/gui/waitingspinnerwidget.py index 6967e6dea..0e3097b40 100644 --- a/artiq/gui/waitingspinnerwidget.py +++ b/artiq/gui/waitingspinnerwidget.py @@ -27,9 +27,9 @@ SOFTWARE. import math -from PyQt5.QtCore import * -from PyQt5.QtGui import * -from PyQt5.QtWidgets import * +from PyQt6.QtCore import * +from PyQt6.QtGui import * +from PyQt6.QtWidgets import * class QtWaitingSpinner(QWidget): @@ -37,7 +37,7 @@ class QtWaitingSpinner(QWidget): super().__init__() # WAS IN initialize() - self._color = QColor(Qt.black) + self._color = Qt.GlobalColor.black self._roundness = 100.0 self._minimumTrailOpacity = 3.14159265358979323846 self._trailFadePercentage = 80.0 @@ -54,17 +54,17 @@ class QtWaitingSpinner(QWidget): self.updateTimer() # END initialize() - self.setAttribute(Qt.WA_TranslucentBackground) + self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) def paintEvent(self, QPaintEvent): painter = QPainter(self) - painter.fillRect(self.rect(), Qt.transparent) - painter.setRenderHint(QPainter.Antialiasing, True) + painter.fillRect(self.rect(), Qt.GlobalColor.transparent) + painter.setRenderHint(QPainter.RenderHint.Antialiasing, True) if self._currentCounter >= self._numberOfLines: self._currentCounter = 0 - painter.setPen(Qt.NoPen) + painter.setPen(Qt.PenStyle.NoPen) for i in range(0, self._numberOfLines): painter.save() painter.translate(self._innerRadius + self._lineLength, self._innerRadius + self._lineLength) @@ -76,7 +76,7 @@ class QtWaitingSpinner(QWidget): self._minimumTrailOpacity, self._color) painter.setBrush(color) painter.drawRoundedRect(QRect(0, int(-self._lineWidth / 2), self._lineLength, self._lineWidth), self._roundness, - self._roundness, Qt.RelativeSize) + self._roundness, Qt.SizeMode.RelativeSize) painter.restore() def start(self): @@ -136,7 +136,7 @@ class QtWaitingSpinner(QWidget): def setRoundness(self, roundness): self._roundness = max(0.0, min(100.0, roundness)) - def setColor(self, color=Qt.black): + def setColor(self, color=Qt.GlobalColor.black): self._color = QColor(color) def setRevolutionsPerSecond(self, revolutionsPerSecond): diff --git a/doc/manual/conf.py b/doc/manual/conf.py index e25a3b927..50300b782 100644 --- a/doc/manual/conf.py +++ b/doc/manual/conf.py @@ -37,7 +37,7 @@ mock_modules = ["artiq.gui.waitingspinnerwidget", "artiq.dashboard.waveform", "artiq.dashboard.interactive_args", "qasync", "pyqtgraph", "matplotlib", "lmdb", - "numpy", "dateutil", "dateutil.parser", "prettytable", "PyQt5", + "numpy", "dateutil", "dateutil.parser", "prettytable", "PyQt6", "h5py", "serial", "scipy", "scipy.interpolate", "llvmlite", "Levenshtein", "pythonparser", "sipyco", "sipyco.pc_rpc", "sipyco.sync_struct", diff --git a/doc/manual/introduction.rst b/doc/manual/introduction.rst index a6983e74d..809b58daf 100644 --- a/doc/manual/introduction.rst +++ b/doc/manual/introduction.rst @@ -16,7 +16,7 @@ ARTIQ and its dependencies are available in the form of Nix packages (for Linux) ARTIQ is supported by M-Labs and developed openly. Components, features, fixes, improvements, and extensions are often `funded `_ by and developed for the partnering research groups. -Core technologies employed include `Python `_, `Migen `_, `Migen-AXI `_, `Rust `_, `MiSoC `_/`VexRiscv `_, `LLVM `_/`llvmlite `_, and `Qt5 `_. +Core technologies employed include `Python `_, `Migen `_, `Migen-AXI `_, `Rust `_, `MiSoC `_/`VexRiscv `_, `LLVM `_/`llvmlite `_, and `Qt6 `_. | Website: https://m-labs.hk/experiment-control/artiq | (US-hosted mirror: https://m-labs-intl.com/experiment-control/artiq) diff --git a/flake.nix b/flake.nix index f8c05604c..36ac02ace 100644 --- a/flake.nix +++ b/flake.nix @@ -76,7 +76,7 @@ rev = "v${version}"; sha256 = "sha256-DAzmobw+c29Pt/URGO3bWXHBxgu9bDHhdTUBE9QJDe4="; }; - propagatedBuildInputs = [ pkgs.python3Packages.pyqt5 ]; + propagatedBuildInputs = [ pkgs.python3Packages.pyqt6 ]; nativeCheckInputs = [ pkgs.python3Packages.pytest-runner pkgs.python3Packages.pytestCheckHook ]; disabledTestPaths = [ "tests/test_qeventloop.py" ]; }; @@ -132,10 +132,10 @@ export VERSIONEER_REV=${artiqRev} ''; - nativeBuildInputs = [ pkgs.qt5.wrapQtAppsHook ]; + nativeBuildInputs = [ pkgs.qt6.wrapQtAppsHook ]; # keep llvm_x and lld_x in sync with llvmlite - propagatedBuildInputs = [ pkgs.llvm_15 pkgs.lld_15 sipyco.packages.x86_64-linux.sipyco pythonparser llvmlite-new pkgs.qt5.qtsvg artiq-comtools.packages.x86_64-linux.artiq-comtools ] - ++ (with pkgs.python3Packages; [ pyqtgraph pygit2 numpy dateutil scipy prettytable pyserial levenshtein h5py pyqt5 qasync tqdm lmdb jsonschema ]); + propagatedBuildInputs = [ pkgs.llvm_15 pkgs.lld_15 sipyco.packages.x86_64-linux.sipyco pythonparser llvmlite-new pkgs.qt6.qtsvg artiq-comtools.packages.x86_64-linux.artiq-comtools ] + ++ (with pkgs.python3Packages; [ pyqtgraph pygit2 numpy dateutil scipy prettytable pyserial levenshtein h5py pyqt6 qasync tqdm lmdb jsonschema ]); dontWrapQtApps = true; postFixup = '' @@ -413,8 +413,8 @@ ]; shellHook = '' export LIBARTIQ_SUPPORT=`libartiq-support` - export QT_PLUGIN_PATH=${pkgs.qt5.qtbase}/${pkgs.qt5.qtbase.dev.qtPluginPrefix}:${pkgs.qt5.qtsvg.bin}/${pkgs.qt5.qtbase.dev.qtPluginPrefix} - export QML2_IMPORT_PATH=${pkgs.qt5.qtbase}/${pkgs.qt5.qtbase.dev.qtQmlPrefix} + export QT_PLUGIN_PATH=${pkgs.qt6.qtbase}/${pkgs.qt6.qtbase.dev.qtPluginPrefix}:${pkgs.qt6.qtsvg}/${pkgs.qt6.qtbase.dev.qtPluginPrefix} + export QML2_IMPORT_PATH=${pkgs.qt6.qtbase}/${pkgs.qt6.qtbase.dev.qtQmlPrefix} export PYTHONPATH=`git rev-parse --show-toplevel`:$PYTHONPATH ''; }; diff --git a/setup.py b/setup.py index f7436f582..78b0eb206 100755 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ if sys.version_info[:2] < (3, 7): raise Exception("You need Python 3.7+") -# Depends on PyQt5, but setuptools cannot check for it. +# Depends on PyQt6, but setuptools cannot check for it. requirements = [ "numpy", "scipy", "python-dateutil", "prettytable", "h5py", "lmdb",