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 @@
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.
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
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)