From 9ceaa8051e7258e3220b9972a98008503f54bee0 Mon Sep 17 00:00:00 2001 From: Andres Morfin Veytia <78442543+amorfinv@users.noreply.github.com> Date: Wed, 22 Dec 2021 19:45:19 +0100 Subject: [PATCH] start migration to pyqt6 --- bluesky/ui/loadvisuals_txt.py | 4 ++-- bluesky/ui/qtgl/aman.py | 6 +++--- bluesky/ui/qtgl/console.py | 13 +++++------ bluesky/ui/qtgl/customevents.py | 2 +- bluesky/ui/qtgl/docwindow.py | 12 ++++++----- bluesky/ui/qtgl/glhelpers.py | 36 +++++++++++++++++-------------- bluesky/ui/qtgl/gui.py | 23 ++++++++++---------- bluesky/ui/qtgl/guiclient.py | 2 +- bluesky/ui/qtgl/infowindow.py | 4 ++-- bluesky/ui/qtgl/mainwindow.py | 14 ++++++------ bluesky/ui/qtgl/nd.py | 4 ++-- bluesky/ui/qtgl/radarwidget.py | 34 ++++++++++++++--------------- bluesky/ui/qtgl/settingswindow.py | 8 +++---- bluesky/ui/qtgl/tiledtexture.py | 6 +++--- check.py | 12 +++++++---- data/html/Installation.html | 2 +- extra/blipdriver/blipdriver.py | 12 ++++++----- extra/blipdriver/glhelpers.py | 2 +- extra/textclient/textclient.py | 4 ++-- requirements.txt | 2 +- setup-python.bat | 2 +- utils/gltest.py | 10 +++++---- 22 files changed, 115 insertions(+), 99 deletions(-) diff --git a/bluesky/ui/loadvisuals_txt.py b/bluesky/ui/loadvisuals_txt.py index 6d99da94f6..36f9ddd6d5 100644 --- a/bluesky/ui/loadvisuals_txt.py +++ b/bluesky/ui/loadvisuals_txt.py @@ -82,8 +82,8 @@ def load_coastline_txt(): # Only try this if BlueSky is started in qtgl gui mode if bs.gui_type == 'qtgl': - from PyQt5.QtCore import Qt - from PyQt5.QtWidgets import QApplication, QProgressDialog + from PyQt6.QtCore import Qt + from PyQt6.QtWidgets import QApplication, QProgressDialog from bluesky.ui.polytools import PolygonSet, BoundingBox diff --git a/bluesky/ui/qtgl/aman.py b/bluesky/ui/qtgl/aman.py index 91d1512d79..73226f0716 100644 --- a/bluesky/ui/qtgl/aman.py +++ b/bluesky/ui/qtgl/aman.py @@ -1,6 +1,6 @@ -from PyQt5.QtCore import Qt -from PyQt5.QtGui import QPen, QBrush, QColor, QFont -from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsItemGroup +from PyQt6.QtCore import Qt +from PyQt6.QtGui import QPen, QBrush, QColor, QFont +from PyQt6.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsItemGroup class AMANDisplay(QGraphicsView): diff --git a/bluesky/ui/qtgl/console.py b/bluesky/ui/qtgl/console.py index 2eb72634d2..31b38057ea 100644 --- a/bluesky/ui/qtgl/console.py +++ b/bluesky/ui/qtgl/console.py @@ -1,7 +1,8 @@ """ Console interface for the QTGL implementation.""" -from PyQt5.QtCore import Qt -from PyQt5.Qt import QDesktopServices, QUrl, QApplication -from PyQt5.QtWidgets import QWidget, QTextEdit +from PyQt6.QtCore import Qt, QUrl +from PyQt6.QtGui import QDesktopServices +from PyQt6.QtWidgets import QApplication +from PyQt6.QtWidgets import QWidget, QTextEdit import bluesky as bs from bluesky.tools import cachefile @@ -255,15 +256,15 @@ class Stackwin(QTextEdit): def __init__(self, parent=None): super().__init__(parent) Console.stackText = self - self.setFocusPolicy(Qt.NoFocus) + self.setFocusPolicy(Qt.FocusPolicy.NoFocus) def mousePressEvent(self, e): self.anchor = self.anchorAt(e.pos()) if self.anchor: - QApplication.setOverrideCursor(Qt.PointingHandCursor) + QApplication.setOverrideCursor(Qt.CursorShape.PointingHandCursor) def mouseReleaseEvent(self, e): if self.anchor: QDesktopServices.openUrl(QUrl(self.anchor)) - QApplication.setOverrideCursor(Qt.ArrowCursor) + QApplication.setOverrideCursor(Qt.CursorShape.ArrowCursor) self.anchor = None diff --git a/bluesky/ui/qtgl/customevents.py b/bluesky/ui/qtgl/customevents.py index 6f435b9d3e..10dce5096a 100644 --- a/bluesky/ui/qtgl/customevents.py +++ b/bluesky/ui/qtgl/customevents.py @@ -1,5 +1,5 @@ """ Definition of custom QEvent objects for QtGL gui. """ -from PyQt5.QtCore import QEvent +from PyQt6.QtCore import QEvent NUMCUSTOMEVENTS = 2 diff --git a/bluesky/ui/qtgl/docwindow.py b/bluesky/ui/qtgl/docwindow.py index 0275f0b306..9a4e3ef68f 100644 --- a/bluesky/ui/qtgl/docwindow.py +++ b/bluesky/ui/qtgl/docwindow.py @@ -1,13 +1,15 @@ """ Documentation window for the QTGL version of BlueSky.""" -from PyQt5.QtCore import QUrl, QFileInfo -from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout, QWidget, QPushButton, QLabel +from PyQt6.QtCore import QUrl, QFileInfo +from PyQt6.QtWidgets import QVBoxLayout, QHBoxLayout, QWidget, QPushButton, QLabel try: try: - # Within PyQt5 there are different locations for QWebView and QWebPage, + # Within PyQt6 there are different locations for QWebView and QWebPage, # depending on release version. - from PyQt5.QtWebEngineWidgets import QWebEngineView as QWebView, QWebEnginePage as QWebPage + from PyQt6.QtWebEngineWidgets import QWebEngineView as QWebView + from PyQt6.QtWebEngineCore import QWebEnginePage as QWebPage except ImportError: - from PyQt5.QtWebKitWidgets import QWebView, QWebPage + from PyQt6.QtWebEngineWidgets import QWebView + from PyQt6.QtWebEngineCore import QWebPage class DocView(QWebView): def __init__(self, parent=None): diff --git a/bluesky/ui/qtgl/glhelpers.py b/bluesky/ui/qtgl/glhelpers.py index eb67add98c..1083d224c9 100644 --- a/bluesky/ui/qtgl/glhelpers.py +++ b/bluesky/ui/qtgl/glhelpers.py @@ -3,9 +3,10 @@ from os import path from collections import namedtuple from collections import OrderedDict -from PyQt5.QtCore import qCritical +import PyQt6 +from PyQt6.QtCore import qCritical -from PyQt5.QtWidgets import QOpenGLWidget +from PyQt6.QtOpenGLWidgets import QOpenGLWidget try: from collections.abc import Collection, MutableMapping @@ -15,10 +16,11 @@ import ctypes import numpy as np -from PyQt5.QtGui import (QSurfaceFormat, QOpenGLShader, QOpenGLShaderProgram, +from PyQt6.QtOpenGL import (QOpenGLShader, QOpenGLShaderProgram, QOpenGLVertexArrayObject, QOpenGLBuffer, - QOpenGLContext, QOpenGLVersionProfile, - QOpenGLTexture, QImage) + QOpenGLVersionProfile, QOpenGLTexture, QAbstractOpenGLFunctions) +from PyQt6.QtGui import QSurfaceFormat, QOpenGLContext, QImage + from bluesky import settings from bluesky.core import Entity from bluesky.stack import command @@ -35,12 +37,12 @@ def get_profile_settings(): - for version in ((4, 5), (4, 4), (4, 3), (4, 2), (4, 1), (4, 0), (3, 3)): + for version in ((4, 1), (2, 1), (2, 0)): for profile in ('Core', 'Compatibility'): try: - importlib.import_module(f'PyQt5._QOpenGLFunctions_{version[0]}_{version[1]}_{profile}') + importlib.import_module(f'PyQt6.QtOpenGL', package=f'QOpenGLFunctions_{version[0]}_{version[1]}_{profile}') print(f'Found Qt-provided OpenGL functions for OpenGL {version} {profile}') - return version, QSurfaceFormat.CoreProfile if profile == 'Core' else QSurfaceFormat.CompatibilityProfile + return version, QSurfaceFormat.OpenGLContextProfile.CoreProfile if profile == 'Core' else QSurfaceFormat.OpenGLContextProfile.CompatibilityProfile except: continue return (4, 1), None @@ -55,20 +57,22 @@ def init(): fmt.setVersion(*version) # profile = QSurfaceFormat.CoreProfile if sys.platform == 'darwin' else QSurfaceFormat.CompatibilityProfile - fmt.setProfile(profile or QSurfaceFormat.CompatibilityProfile) + fmt.setProfile(profile or QSurfaceFormat.OpenGLContextProfile.CompatibilityProfile) QSurfaceFormat.setDefaultFormat(fmt) if profile is not None: # Use a dummy context to get GL functions glprofile = QOpenGLVersionProfile(fmt) ctx = QOpenGLContext() - globals()['gl'] = ctx.versionFunctions(glprofile) + # globals()['gl'] = ctx.versionFunctions(glprofile) + globals()['gl'] = QAbstractOpenGLFunctions() + print(dir(gl)) # Check and set OpenGL capabilities if not glprofile.hasProfiles(): raise RuntimeError( 'No OpenGL version >= 3.3 support detected for this system!') else: - # If profile was none, PyQt5 is not shipped with any OpenGL function modules. Use PyOpenGL instead + # If profile was none, PyQt6 is not shipped with any OpenGL function modules. Use PyOpenGL instead print("Couldn't find OpenGL functions in Qt. Falling back to PyOpenGL") globals()['gl'] = importlib.import_module('OpenGL.GL') @@ -513,7 +517,7 @@ def create(self, texture=None, vertex_count=0, n_instances=0, **attribs): self.set_attribs(**attribs) - def set_attribs(self, usage=QOpenGLBuffer.StaticDraw, instance_divisor=0, + def set_attribs(self, usage=QOpenGLBuffer.UsagePattern.StaticDraw, instance_divisor=0, datatype=None, stride=0, offset=None, normalize=False, **attribs): ''' Set attributes for this VAO. ''' @@ -879,7 +883,7 @@ def create(self, w, h, fill=False): class GLBuffer(QOpenGLBuffer): ''' Wrapper class for vertex and index buffers. ''' - def create(self, size=None, usage=QOpenGLBuffer.StaticDraw, data=None): + def create(self, size=None, usage=QOpenGLBuffer.UsagePattern.StaticDraw, data=None): ''' Create the buffer. ''' if size is None and data is None: raise ValueError( @@ -918,7 +922,7 @@ def __init__(self): super().__init__(gl.GL_UNIFORM_BUFFER) self.binding = 0 - def create(self, size=None, usage=QOpenGLBuffer.StaticDraw, data=None): + def create(self, size=None, usage=QOpenGLBuffer.UsagePattern.StaticDraw, data=None): ''' Create this UBO. ''' super().create(size, usage, data) self.binding = UniformBufferObject.ufo_max_binding @@ -929,7 +933,7 @@ def create(self, size=None, usage=QOpenGLBuffer.StaticDraw, data=None): class Texture(QOpenGLTexture): ''' BlueSky OpenGL Texture class. ''' - def __init__(self, target=QOpenGLTexture.Target2D): + def __init__(self, target=QOpenGLTexture.Target.Target2D): super().__init__(target) def load(self, fname): @@ -966,7 +970,7 @@ class Font(Texture): _fonts = list() def __init__(self): - super().__init__(QOpenGLTexture.Target2DArray) + super().__init__(QOpenGLTexture.Target.Target2DArray) self.char_ar = 1.0 self.loc_char_size = 0 self.loc_block_size = 0 diff --git a/bluesky/ui/qtgl/gui.py b/bluesky/ui/qtgl/gui.py index a748dda107..d0e4397135 100644 --- a/bluesky/ui/qtgl/gui.py +++ b/bluesky/ui/qtgl/gui.py @@ -1,8 +1,9 @@ """ QTGL Gui for BlueSky.""" -from PyQt5.QtCore import Qt, QEvent, qInstallMessageHandler, \ - QtWarningMsg, QtCriticalMsg, QtFatalMsg, \ +from PyQt6.QtCore import Qt, QEvent, qInstallMessageHandler, \ QT_VERSION, QT_VERSION_STR -from PyQt5.QtWidgets import QApplication, QErrorMessage + +from PyQt6.QtCore import QtMsgType +from PyQt6.QtWidgets import QApplication, QErrorMessage import bluesky as bs from bluesky.ui.qtgl.guiclient import GuiClient @@ -12,13 +13,13 @@ print(('Using Qt ' + QT_VERSION_STR + ' for windows and widgets')) - +QtMsgType def gui_msg_handler(msgtype, context, msg): - if msgtype == QtWarningMsg: + if msgtype == QtMsgType.QtWarningMsg: print('Qt gui warning:', msg) - elif msgtype == QtCriticalMsg: + elif msgtype == QtMsgType.QtCriticalMsg: print('Qt gui critical error:', msg) - if msgtype == QtFatalMsg: + if msgtype == QtMsgType.QtFatalMsg: print('Qt gui fatal error:', msg) exit() @@ -33,9 +34,9 @@ def start(mode): # Start the bluesky network client client = GuiClient() - # Enable HiDPI support (Qt5 only) - if QT_VERSION >= 0x050000: - app.setAttribute(Qt.AA_UseHighDpiPixmaps) + # # Enable HiDPI support (Qt5 only) + # if QT_VERSION >= 0x050000: + # app.setAttribute(Qt.AA_UseHighDpiPixmaps) splash = Splash() @@ -49,7 +50,7 @@ def start(mode): # Install error message handler handler = QErrorMessage.qtHandler() - handler.setWindowFlags(Qt.WindowStaysOnTopHint) + handler.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint) splash.showMessage('Constructing main window') app.processEvents() diff --git a/bluesky/ui/qtgl/guiclient.py b/bluesky/ui/qtgl/guiclient.py index 2029ff9a88..745d8295fb 100644 --- a/bluesky/ui/qtgl/guiclient.py +++ b/bluesky/ui/qtgl/guiclient.py @@ -1,5 +1,5 @@ ''' I/O Client implementation for the QtGL gui. ''' -from PyQt5.QtCore import QTimer +from PyQt6.QtCore import QTimer import numpy as np from bluesky.ui import palette diff --git a/bluesky/ui/qtgl/infowindow.py b/bluesky/ui/qtgl/infowindow.py index 248e091736..1bb04917c7 100644 --- a/bluesky/ui/qtgl/infowindow.py +++ b/bluesky/ui/qtgl/infowindow.py @@ -11,8 +11,8 @@ from matplotlib.figure import Figure from matplotlib.backend_bases import key_press_handler import matplotlib.pyplot as plt -from PyQt5.QtCore import Qt -from PyQt5.QtWidgets import QTabWidget, QVBoxLayout, QScrollArea, QWidget +from PyQt6.QtCore import Qt +from PyQt6.QtWidgets import QTabWidget, QVBoxLayout, QScrollArea, QWidget from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas, \ NavigationToolbar2QT as NavigationToolbar diff --git a/bluesky/ui/qtgl/mainwindow.py b/bluesky/ui/qtgl/mainwindow.py index d4d38c7809..aa1b7ea23c 100644 --- a/bluesky/ui/qtgl/mainwindow.py +++ b/bluesky/ui/qtgl/mainwindow.py @@ -2,13 +2,13 @@ import platform import os -from PyQt5.QtWidgets import QApplication as app -from PyQt5.QtCore import Qt, pyqtSlot, QTimer, QItemSelectionModel, QSize -from PyQt5.QtGui import QPixmap, QIcon -from PyQt5.QtWidgets import QMainWindow, QSplashScreen, QTreeWidgetItem, \ +from PyQt6.QtWidgets import QApplication as app +from PyQt6.QtCore import Qt, pyqtSlot, QTimer, QItemSelectionModel, QSize +from PyQt6.QtGui import QPixmap, QIcon +from PyQt6.QtWidgets import QMainWindow, QSplashScreen, QTreeWidgetItem, \ QPushButton, QFileDialog, QDialog, QTreeWidget, QVBoxLayout, \ QDialogButtonBox -from PyQt5 import uic +from PyQt6 import uic # Local imports import bluesky as bs @@ -38,7 +38,7 @@ class Splash(QSplashScreen): """ Splash screen: BlueSky logo during start-up""" def __init__(self): - super().__init__(QPixmap(os.path.join(bs.settings.gfx_path, 'splash.gif')), Qt.WindowStaysOnTopHint) + super().__init__(QPixmap(os.path.join(bs.settings.gfx_path, 'splash.gif')), Qt.WindowType.WindowStaysOnTopHint) class DiscoveryDialog(QDialog): @@ -173,7 +173,7 @@ def __init__(self, mode): self.nodetree.setIndentation(0) self.nodetree.setColumnCount(2) self.nodetree.setStyleSheet('padding:0px') - self.nodetree.setAttribute(Qt.WA_MacShowFocusRect, False) + self.nodetree.setAttribute(Qt.WidgetAttribute.WA_MacShowFocusRect, False) self.nodetree.header().resizeSection(0, 130) self.nodetree.itemClicked.connect(self.nodetreeClicked) self.maxhostnum = 0 diff --git a/bluesky/ui/qtgl/nd.py b/bluesky/ui/qtgl/nd.py index f332dcf2f8..25b9439209 100644 --- a/bluesky/ui/qtgl/nd.py +++ b/bluesky/ui/qtgl/nd.py @@ -1,6 +1,6 @@ """ Navigation display for the QTGL gui.""" -from PyQt5.QtCore import qCritical, QTimer -from PyQt5.QtOpenGL import QGLWidget +from PyQt6.QtCore import qCritical, QTimer +from PyQt6.QtOpenGLWidgets import QOpenGLWidget as QGLWidget import OpenGL.GL as gl from math import sin, cos, radians import numpy as np diff --git a/bluesky/ui/qtgl/radarwidget.py b/bluesky/ui/qtgl/radarwidget.py index 096fdf8895..820a01199f 100644 --- a/bluesky/ui/qtgl/radarwidget.py +++ b/bluesky/ui/qtgl/radarwidget.py @@ -3,7 +3,7 @@ from ctypes import c_float, c_int, Structure import numpy as np -from PyQt5.QtCore import Qt, QEvent, QT_VERSION +from PyQt6.QtCore import Qt, QEvent, QT_VERSION import bluesky as bs from bluesky.core import Signal @@ -107,9 +107,9 @@ def __init__(self, parent=None): self.addobject(Navdata(parent=self)) self.addobject(Poly(parent=self)) - self.setAttribute(Qt.WA_AcceptTouchEvents, True) - self.grabGesture(Qt.PanGesture) - self.grabGesture(Qt.PinchGesture) + self.setAttribute(Qt.WidgetAttribute.WA_AcceptTouchEvents, True) + self.grabGesture(Qt.GestureType.PanGesture) + self.grabGesture(Qt.GestureType.PinchGesture) # self.grabGesture(Qt.SwipeGesture) self.setMouseTracking(True) @@ -267,9 +267,9 @@ def panzoom(self, pan=None, zoom=None, origin=None, absolute=False): def event(self, event): ''' Event handling for input events. ''' - if event.type() == QEvent.Wheel: + if event.type() == QEvent.Type.Wheel: # For mice we zoom with control/command and the scrolwheel - if event.modifiers() & Qt.ControlModifier: + if event.modifiers() & Qt.KeyboardModifier.ControlModifier: origin = (event.pos().x(), event.pos().y()) zoom = 1.0 try: @@ -295,16 +295,16 @@ def event(self, event): pass # For touchpad, pinch gesture is used for zoom - elif event.type() == QEvent.Gesture: + elif event.type() == QEvent.Type.Gesture: pan = zoom = None dlat = dlon = 0.0 for g in event.gestures(): - if g.gestureType() == Qt.PinchGesture: + if g.gestureType() == Qt.GestureType.PinchGesture: event.accept(g) zoom = g.scaleFactor() * (zoom or 1.0) if CORRECT_PINCH: zoom /= g.lastScaleFactor() - elif g.gestureType() == Qt.PanGesture: + elif g.gestureType() == Qt.GestureType.PanGesture: event.accept(g) if abs(g.delta().y() + g.delta().x()) > 1e-1: dlat += 0.005 * g.delta().y() / (self.zoom * self.ar) @@ -314,14 +314,14 @@ def event(self, event): self.panzoomchanged = True return self.panzoom(pan, zoom, self.mousepos) - elif event.type() == QEvent.MouseButtonPress and event.button() & Qt.LeftButton: + elif event.type() == QEvent.Type.MouseButtonPress and event.button() & Qt.MouseButton.LeftButton: self.mousedragged = False # For mice we pan with control/command and mouse movement. # Mouse button press marks the beginning of a pan self.prevmousepos = (event.x(), event.y()) - elif event.type() == QEvent.MouseButtonRelease and \ - event.button() & Qt.LeftButton and not self.mousedragged: + elif event.type() == QEvent.Type.MouseButtonRelease and \ + event.button() & Qt.MouseButton.LeftButton and not self.mousedragged: lat, lon = self.pixelCoordsToLatLon(event.x(), event.y()) actdata = bs.net.get_nodedata() tostack, tocmdline = radarclick(console.get_cmdline(), lat, lon, @@ -329,10 +329,10 @@ def event(self, event): console.process_cmdline((tostack + '\n' + tocmdline) if tostack else tocmdline) - elif event.type() == QEvent.MouseMove: + elif event.type() == QEvent.Type.MouseMove: self.mousedragged = True self.mousepos = (event.x(), event.y()) - if event.buttons() & Qt.LeftButton: + if event.buttons() & Qt.MouseButton.LeftButton: dlat = 0.003 * \ (event.y() - self.prevmousepos[1]) / (self.zoom * self.ar) dlon = 0.003 * \ @@ -342,13 +342,13 @@ def event(self, event): self.panzoomchanged = True return self.panzoom(pan=(dlat, dlon)) - elif event.type() == QEvent.TouchBegin: + elif event.type() == QEvent.Type.TouchBegin: # Accept touch start to enable reception of follow-on touch update and touch end events event.accept() # Update pan/zoom to simulation thread only when the pan/zoom gesture is finished - elif (event.type() == QEvent.MouseButtonRelease or - event.type() == QEvent.TouchEnd) and self.panzoomchanged: + elif (event.type() == QEvent.Type.MouseButtonRelease or + event.type() == QEvent.Type.TouchEnd) and self.panzoomchanged: self.panzoomchanged = False bs.net.send_event(b'PANZOOM', dict(pan=(self.panlat, self.panlon), zoom=self.zoom, ar=self.ar, absolute=True)) diff --git a/bluesky/ui/qtgl/settingswindow.py b/bluesky/ui/qtgl/settingswindow.py index b8a603c898..7f413d716b 100644 --- a/bluesky/ui/qtgl/settingswindow.py +++ b/bluesky/ui/qtgl/settingswindow.py @@ -1,8 +1,8 @@ from os import path from glob import glob from collections import defaultdict -from PyQt5.QtCore import Qt, pyqtSlot -from PyQt5.QtWidgets import QVBoxLayout, QScrollArea, QGroupBox, QWidget, \ +from PyQt6.QtCore import Qt, pyqtSlot +from PyQt6.QtWidgets import QVBoxLayout, QScrollArea, QGroupBox, QWidget, \ QFormLayout, QLabel, QSpinBox, QCheckBox, QLineEdit, QHBoxLayout, \ QTreeWidget, QTreeWidgetItem, QFrame, QPushButton, QLayout, QComboBox, \ QListWidget, QListWidgetItem @@ -88,7 +88,7 @@ def __init__(self): self.nodetree.setIndentation(0) self.nodetree.setColumnCount(2) self.nodetree.setStyleSheet('padding:0px') - self.nodetree.setAttribute(Qt.WA_MacShowFocusRect, False) + self.nodetree.setAttribute(Qt.WidgetAttribute.WA_MacShowFocusRect, False) self.nodetree.header().resizeSection(0, 130) self.nodetree.setHeaderHidden(True) self.nodetree.itemClicked.connect(self.nodetreeClicked) @@ -96,7 +96,7 @@ def __init__(self): self.nodesettings.setLayout(QVBoxLayout()) container = QWidget() container.setLayout(self.scrollarea.layout) - self.scrollarea.layout.setAlignment(Qt.AlignTop|Qt.AlignLeft) + self.scrollarea.layout.setAlignment(Qt.AlignmentFlag.AlignTop|Qt.AlignmentFlag.AlignLeft) self.scrollarea.setWidget(container) self.scrollarea.setWidgetResizable(True) diff --git a/bluesky/ui/qtgl/tiledtexture.py b/bluesky/ui/qtgl/tiledtexture.py index 0251ba3d5d..73cc24d89f 100644 --- a/bluesky/ui/qtgl/tiledtexture.py +++ b/bluesky/ui/qtgl/tiledtexture.py @@ -8,9 +8,9 @@ from urllib.error import URLError import numpy as np -from PyQt5.Qt import Qt -from PyQt5.QtCore import QObject, QRunnable, QThreadPool, pyqtSignal, pyqtSlot -from PyQt5.QtGui import QImage +from PyQt6.QtCore import Qt +from PyQt6.QtCore import QObject, QRunnable, QThreadPool, pyqtSignal, pyqtSlot +from PyQt6.QtGui import QImage import bluesky as bs from bluesky.core import Signal diff --git a/check.py b/check.py index da69744137..019e8e82c0 100644 --- a/check.py +++ b/check.py @@ -1,6 +1,8 @@ #!/usr/bin/python from __future__ import print_function import traceback + +import PyQt6 print("This script checks the availability of the libraries required by BlueSky, and the capabilities of your system.") print() np = sp = mpl = qt = gl = glhw = pg = False @@ -37,9 +39,11 @@ print("Checking for pyqt ", end=' ') try: - from PyQt5.QtCore import QT_VERSION_STR - from PyQt5.QtWidgets import QApplication - from PyQt5.QtOpenGL import QGLWidget, QGLFormat + from PyQt6.QtCore import QT_VERSION_STR + from PyQt6.QtWidgets import QApplication + from PyQt6.QtGui import QSurfaceFormat as QGLFormat + from PyQt6.QtOpenGLWidgets import QOpenGLWidget as QGLWidget + qt = True except ImportError: print("[FAIL]") @@ -74,7 +78,7 @@ try: f = QGLFormat() f.setVersion(3, 3) - f.setProfile(QGLFormat.CoreProfile) + f.setProfile(QGLFormat.OpenGLContextProfile.CoreProfile) f.setDoubleBuffer(True) QGLFormat.setDefaultFormat(f) diff --git a/data/html/Installation.html b/data/html/Installation.html index eb448ad66f..c9b8698151 100644 --- a/data/html/Installation.html +++ b/data/html/Installation.html @@ -28,7 +28,7 @@

Windows: Python(x,y)

For Windows, Python(x,y) is also a widely-used python distribution, especially in the scientific community. By default, Python(x,y) comes with PyQt4, but this is no problem for BlueSky. Also for this distribution, additional packages are required: pyopengl>=3.1.1 and pygame.

MacOS: MacPorts

If you prefer you can also install the required dependencies using MacPorts. Assuming you already have MacPorts installed, use port to install the following additional dependencies:

-
sudo port install py27-pyqt5 py27-opengl-accelerate py27-game
+
sudo port install py27-pyqt6 py27-opengl-accelerate py27-game

Linux: Your distribution's package manager

Each Linux distribution has its own package management software. You can use it to install the required dependencies for BlueSky. Typically python is already available by default on a Linux system. In addition, BlueSky relies on pyqt>=4.7, PyOpenGL>=3.1.1, numpy, scipy, matplotlib, and optionally pygame.

diff --git a/extra/blipdriver/blipdriver.py b/extra/blipdriver/blipdriver.py index 7db105d919..1422fb0e2e 100644 --- a/extra/blipdriver/blipdriver.py +++ b/extra/blipdriver/blipdriver.py @@ -1,7 +1,9 @@ -from PyQt5.QtCore import Qt, QEvent, QTimer, pyqtSlot -from PyQt5.QtGui import QImage -from PyQt5.QtWidgets import QApplication -from PyQt5.QtOpenGL import QGLWidget, QGLFormat +from PyQt6.QtCore import Qt, QEvent, QTimer, pyqtSlot +from PyQt6.QtGui import QImage +from PyQt6.QtWidgets import QApplication +from PyQt6.QtGui import QSurfaceFormat as QGLFormat +from PyQt6.QtOpenGLWidgets import QOpenGLWidget as QGLWidget + import OpenGL.GL as gl import numpy as np from glob import glob @@ -460,7 +462,7 @@ def updateAPValues(self): else: f = QGLFormat() f.setVersion(3, 3) - f.setProfile(QGLFormat.CoreProfile) + f.setProfile(QGLFormat.OpenGLContextProfile.CoreProfile) f.setDoubleBuffer(True) QGLFormat.setDefaultFormat(f) print(('QGLWidget initialized for OpenGL version %d.%d' % (f.majorVersion(), f.minorVersion()))) diff --git a/extra/blipdriver/glhelpers.py b/extra/blipdriver/glhelpers.py index a8e9192273..1da7260aad 100644 --- a/extra/blipdriver/glhelpers.py +++ b/extra/blipdriver/glhelpers.py @@ -20,7 +20,7 @@ Date : ------------------------------------------------------------------ """ -from PyQt5.QtGui import QImage +from PyQt6.QtGui import QImage import OpenGL.GL as gl import numpy as np from ctypes import c_void_p, pointer, sizeof diff --git a/extra/textclient/textclient.py b/extra/textclient/textclient.py index 387e715a72..9b474e04a6 100644 --- a/extra/textclient/textclient.py +++ b/extra/textclient/textclient.py @@ -5,8 +5,8 @@ PYTHONPATH=/path/to/your/bluesky python textclient.py ''' -from PyQt5.QtCore import Qt, QTimer -from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTextEdit +from PyQt6.QtCore import Qt, QTimer +from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QTextEdit from bluesky.network import Client diff --git a/requirements.txt b/requirements.txt index 80d40956f0..7b0d06d473 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -pyqt5 +pyqt6 pyqtwebengine diff --git a/setup-python.bat b/setup-python.bat index 65f4c458b1..732299da15 100644 --- a/setup-python.bat +++ b/setup-python.bat @@ -1,4 +1,4 @@ -pip install PyQt5 numpy scipy matplotlib pyopengl-accelerate +pip install PyQt6 numpy scipy matplotlib pyopengl-accelerate pip install pandas pyopengl pip install msgpack zmq pygame pyqtwebengine pause \ No newline at end of file diff --git a/utils/gltest.py b/utils/gltest.py index e0c1485580..4ce6fedff4 100644 --- a/utils/gltest.py +++ b/utils/gltest.py @@ -1,6 +1,8 @@ -from PyQt5.QtCore import QTimer -from PyQt5.QtWidgets import QApplication -from PyQt5.QtOpenGL import QGLWidget, QGLFormat, QGLContext +from PyQt6.QtCore import QTimer +from PyQt6.QtWidgets import QApplication +from PyQt6.QtGui import QSurfaceFormat as QGLFormat +from PyQt6.QtOpenGLWidgets import QOpenGLWidget as QGLWidget +from PyQt6.QtGui import QOpenGLContext as QGLContext import OpenGL.GL as gl @@ -9,7 +11,7 @@ def __init__(self, parent=None): self.first = True f = QGLFormat() f.setVersion(3, 3) - f.setProfile(QGLFormat.CoreProfile) + f.setProfile(QGLFormat.OpenGLContextProfile.CoreProfile) f.setDoubleBuffer(True) QGLWidget.__init__(self, QGLContext(f), parent)