diff --git a/CHANGELOG b/CHANGELOG index 921d0616..afba9d4a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ pyqtgraph-0.11.0 (in development) + New Features: + - PySide2 support + API / behavior changes: - ArrowItem's `angle` option now rotates the arrow without affecting its coordinate system. The result is visually the same, but children of ArrowItem are no longer rotated diff --git a/examples/ScatterPlotSpeedTest.py b/examples/ScatterPlotSpeedTest.py index 9cbf0c63..2c64173a 100644 --- a/examples/ScatterPlotSpeedTest.py +++ b/examples/ScatterPlotSpeedTest.py @@ -12,7 +12,7 @@ For testing rapid updates of ScatterPlotItem under various conditions. import initExample -from pyqtgraph.Qt import QtGui, QtCore, USE_PYSIDE, USE_PYQT5 +from pyqtgraph.Qt import QtGui, QtCore, QT_LIB import numpy as np import pyqtgraph as pg from pyqtgraph.ptime import time @@ -20,9 +20,11 @@ from pyqtgraph.ptime import time app = QtGui.QApplication([]) #mw = QtGui.QMainWindow() #mw.resize(800,800) -if USE_PYSIDE: +if QT_LIB == 'PySide': from ScatterPlotSpeedTestTemplate_pyside import Ui_Form -elif USE_PYQT5: +elif QT_LIB == 'PySide2': + from ScatterPlotSpeedTestTemplate_pyside2 import Ui_Form +elif QT_LIB == 'PyQt5': from ScatterPlotSpeedTestTemplate_pyqt5 import Ui_Form else: from ScatterPlotSpeedTestTemplate_pyqt import Ui_Form diff --git a/examples/ScatterPlotSpeedTestTemplate_pyqt5.py b/examples/ScatterPlotSpeedTestTemplate_pyqt5.py new file mode 100644 index 00000000..66254a5a --- /dev/null +++ b/examples/ScatterPlotSpeedTestTemplate_pyqt5.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ScatterPlotSpeedTestTemplate.ui' +# +# Created: Sun Sep 18 19:21:36 2016 +# by: pyside2-uic running on PySide2 2.0.0~alpha0 +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore, QtGui, QtWidgets + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(400, 300) + self.gridLayout = QtWidgets.QGridLayout(Form) + self.gridLayout.setObjectName("gridLayout") + self.sizeSpin = QtWidgets.QSpinBox(Form) + self.sizeSpin.setProperty("value", 10) + self.sizeSpin.setObjectName("sizeSpin") + self.gridLayout.addWidget(self.sizeSpin, 1, 1, 1, 1) + self.pixelModeCheck = QtWidgets.QCheckBox(Form) + self.pixelModeCheck.setObjectName("pixelModeCheck") + self.gridLayout.addWidget(self.pixelModeCheck, 1, 3, 1, 1) + self.label = QtWidgets.QLabel(Form) + self.label.setObjectName("label") + self.gridLayout.addWidget(self.label, 1, 0, 1, 1) + self.plot = PlotWidget(Form) + self.plot.setObjectName("plot") + self.gridLayout.addWidget(self.plot, 0, 0, 1, 4) + self.randCheck = QtWidgets.QCheckBox(Form) + self.randCheck.setObjectName("randCheck") + self.gridLayout.addWidget(self.randCheck, 1, 2, 1, 1) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1)) + self.pixelModeCheck.setText(QtWidgets.QApplication.translate("Form", "pixel mode", None, -1)) + self.label.setText(QtWidgets.QApplication.translate("Form", "Size", None, -1)) + self.randCheck.setText(QtWidgets.QApplication.translate("Form", "Randomize", None, -1)) + +from pyqtgraph import PlotWidget diff --git a/examples/ScatterPlotSpeedTestTemplate_pyside2.py b/examples/ScatterPlotSpeedTestTemplate_pyside2.py new file mode 100644 index 00000000..b0e62814 --- /dev/null +++ b/examples/ScatterPlotSpeedTestTemplate_pyside2.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ScatterPlotSpeedTestTemplate.ui' +# +# Created: Sun Sep 18 19:21:36 2016 +# by: pyside2-uic running on PySide2 2.0.0~alpha0 +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore, QtGui, QtWidgets + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(400, 300) + self.gridLayout = QtWidgets.QGridLayout(Form) + self.gridLayout.setObjectName("gridLayout") + self.sizeSpin = QtWidgets.QSpinBox(Form) + self.sizeSpin.setProperty("value", 10) + self.sizeSpin.setObjectName("sizeSpin") + self.gridLayout.addWidget(self.sizeSpin, 1, 1, 1, 1) + self.pixelModeCheck = QtWidgets.QCheckBox(Form) + self.pixelModeCheck.setObjectName("pixelModeCheck") + self.gridLayout.addWidget(self.pixelModeCheck, 1, 3, 1, 1) + self.label = QtWidgets.QLabel(Form) + self.label.setObjectName("label") + self.gridLayout.addWidget(self.label, 1, 0, 1, 1) + self.plot = PlotWidget(Form) + self.plot.setObjectName("plot") + self.gridLayout.addWidget(self.plot, 0, 0, 1, 4) + self.randCheck = QtWidgets.QCheckBox(Form) + self.randCheck.setObjectName("randCheck") + self.gridLayout.addWidget(self.randCheck, 1, 2, 1, 1) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1)) + self.pixelModeCheck.setText(QtWidgets.QApplication.translate("Form", "pixel mode", None, -1)) + self.label.setText(QtWidgets.QApplication.translate("Form", "Size", None, -1)) + self.randCheck.setText(QtWidgets.QApplication.translate("Form", "Randomize", None, -1)) + +from pyqtgraph import PlotWidget diff --git a/examples/VideoSpeedTest.py b/examples/VideoSpeedTest.py index e7189bf5..f123ccc3 100644 --- a/examples/VideoSpeedTest.py +++ b/examples/VideoSpeedTest.py @@ -10,14 +10,16 @@ is used by the view widget import initExample ## Add path to library (just for examples; you do not need this) -from pyqtgraph.Qt import QtGui, QtCore, USE_PYSIDE, USE_PYQT5 +from pyqtgraph.Qt import QtGui, QtCore, QT_LIB import numpy as np import pyqtgraph as pg import pyqtgraph.ptime as ptime -if USE_PYSIDE: +if QT_LIB == 'PySide': import VideoTemplate_pyside as VideoTemplate -elif USE_PYQT5: +elif QT_LIB == 'PySide2': + import VideoTemplate_pyside2 as VideoTemplate +elif QT_LIB == 'PyQt5': import VideoTemplate_pyqt5 as VideoTemplate else: import VideoTemplate_pyqt as VideoTemplate diff --git a/examples/VideoTemplate_pyside2.py b/examples/VideoTemplate_pyside2.py new file mode 100644 index 00000000..37b7d2e8 --- /dev/null +++ b/examples/VideoTemplate_pyside2.py @@ -0,0 +1,207 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'VideoTemplate.ui' +# +# Created: Sun Sep 18 19:22:41 2016 +# by: pyside2-uic running on PySide2 2.0.0~alpha0 +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore, QtGui, QtWidgets + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName("MainWindow") + MainWindow.resize(695, 798) + self.centralwidget = QtWidgets.QWidget(MainWindow) + self.centralwidget.setObjectName("centralwidget") + self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget) + self.gridLayout_2.setObjectName("gridLayout_2") + self.downsampleCheck = QtWidgets.QCheckBox(self.centralwidget) + self.downsampleCheck.setObjectName("downsampleCheck") + self.gridLayout_2.addWidget(self.downsampleCheck, 8, 0, 1, 2) + self.scaleCheck = QtWidgets.QCheckBox(self.centralwidget) + self.scaleCheck.setObjectName("scaleCheck") + self.gridLayout_2.addWidget(self.scaleCheck, 4, 0, 1, 1) + self.gridLayout = QtWidgets.QGridLayout() + self.gridLayout.setObjectName("gridLayout") + self.rawRadio = QtWidgets.QRadioButton(self.centralwidget) + self.rawRadio.setObjectName("rawRadio") + self.gridLayout.addWidget(self.rawRadio, 3, 0, 1, 1) + self.gfxRadio = QtWidgets.QRadioButton(self.centralwidget) + self.gfxRadio.setChecked(True) + self.gfxRadio.setObjectName("gfxRadio") + self.gridLayout.addWidget(self.gfxRadio, 2, 0, 1, 1) + self.stack = QtWidgets.QStackedWidget(self.centralwidget) + self.stack.setObjectName("stack") + self.page = QtWidgets.QWidget() + self.page.setObjectName("page") + self.gridLayout_3 = QtWidgets.QGridLayout(self.page) + self.gridLayout_3.setObjectName("gridLayout_3") + self.graphicsView = GraphicsView(self.page) + self.graphicsView.setObjectName("graphicsView") + self.gridLayout_3.addWidget(self.graphicsView, 0, 0, 1, 1) + self.stack.addWidget(self.page) + self.page_2 = QtWidgets.QWidget() + self.page_2.setObjectName("page_2") + self.gridLayout_4 = QtWidgets.QGridLayout(self.page_2) + self.gridLayout_4.setObjectName("gridLayout_4") + self.rawImg = RawImageWidget(self.page_2) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.rawImg.sizePolicy().hasHeightForWidth()) + self.rawImg.setSizePolicy(sizePolicy) + self.rawImg.setObjectName("rawImg") + self.gridLayout_4.addWidget(self.rawImg, 0, 0, 1, 1) + self.stack.addWidget(self.page_2) + self.page_3 = QtWidgets.QWidget() + self.page_3.setObjectName("page_3") + self.gridLayout_5 = QtWidgets.QGridLayout(self.page_3) + self.gridLayout_5.setObjectName("gridLayout_5") + self.rawGLImg = RawImageGLWidget(self.page_3) + self.rawGLImg.setObjectName("rawGLImg") + self.gridLayout_5.addWidget(self.rawGLImg, 0, 0, 1, 1) + self.stack.addWidget(self.page_3) + self.gridLayout.addWidget(self.stack, 0, 0, 1, 1) + self.rawGLRadio = QtWidgets.QRadioButton(self.centralwidget) + self.rawGLRadio.setObjectName("rawGLRadio") + self.gridLayout.addWidget(self.rawGLRadio, 4, 0, 1, 1) + self.gridLayout_2.addLayout(self.gridLayout, 1, 0, 1, 4) + self.dtypeCombo = QtWidgets.QComboBox(self.centralwidget) + self.dtypeCombo.setObjectName("dtypeCombo") + self.dtypeCombo.addItem("") + self.dtypeCombo.addItem("") + self.dtypeCombo.addItem("") + self.gridLayout_2.addWidget(self.dtypeCombo, 3, 2, 1, 1) + self.label = QtWidgets.QLabel(self.centralwidget) + self.label.setObjectName("label") + self.gridLayout_2.addWidget(self.label, 3, 0, 1, 1) + self.rgbLevelsCheck = QtWidgets.QCheckBox(self.centralwidget) + self.rgbLevelsCheck.setObjectName("rgbLevelsCheck") + self.gridLayout_2.addWidget(self.rgbLevelsCheck, 4, 1, 1, 1) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.minSpin2 = SpinBox(self.centralwidget) + self.minSpin2.setEnabled(False) + self.minSpin2.setObjectName("minSpin2") + self.horizontalLayout_2.addWidget(self.minSpin2) + self.label_3 = QtWidgets.QLabel(self.centralwidget) + self.label_3.setAlignment(QtCore.Qt.AlignCenter) + self.label_3.setObjectName("label_3") + self.horizontalLayout_2.addWidget(self.label_3) + self.maxSpin2 = SpinBox(self.centralwidget) + self.maxSpin2.setEnabled(False) + self.maxSpin2.setObjectName("maxSpin2") + self.horizontalLayout_2.addWidget(self.maxSpin2) + self.gridLayout_2.addLayout(self.horizontalLayout_2, 5, 2, 1, 1) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.minSpin1 = SpinBox(self.centralwidget) + self.minSpin1.setObjectName("minSpin1") + self.horizontalLayout.addWidget(self.minSpin1) + self.label_2 = QtWidgets.QLabel(self.centralwidget) + self.label_2.setAlignment(QtCore.Qt.AlignCenter) + self.label_2.setObjectName("label_2") + self.horizontalLayout.addWidget(self.label_2) + self.maxSpin1 = SpinBox(self.centralwidget) + self.maxSpin1.setObjectName("maxSpin1") + self.horizontalLayout.addWidget(self.maxSpin1) + self.gridLayout_2.addLayout(self.horizontalLayout, 4, 2, 1, 1) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.minSpin3 = SpinBox(self.centralwidget) + self.minSpin3.setEnabled(False) + self.minSpin3.setObjectName("minSpin3") + self.horizontalLayout_3.addWidget(self.minSpin3) + self.label_4 = QtWidgets.QLabel(self.centralwidget) + self.label_4.setAlignment(QtCore.Qt.AlignCenter) + self.label_4.setObjectName("label_4") + self.horizontalLayout_3.addWidget(self.label_4) + self.maxSpin3 = SpinBox(self.centralwidget) + self.maxSpin3.setEnabled(False) + self.maxSpin3.setObjectName("maxSpin3") + self.horizontalLayout_3.addWidget(self.maxSpin3) + self.gridLayout_2.addLayout(self.horizontalLayout_3, 6, 2, 1, 1) + self.lutCheck = QtWidgets.QCheckBox(self.centralwidget) + self.lutCheck.setObjectName("lutCheck") + self.gridLayout_2.addWidget(self.lutCheck, 7, 0, 1, 1) + self.alphaCheck = QtWidgets.QCheckBox(self.centralwidget) + self.alphaCheck.setObjectName("alphaCheck") + self.gridLayout_2.addWidget(self.alphaCheck, 7, 1, 1, 1) + self.gradient = GradientWidget(self.centralwidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.gradient.sizePolicy().hasHeightForWidth()) + self.gradient.setSizePolicy(sizePolicy) + self.gradient.setObjectName("gradient") + self.gridLayout_2.addWidget(self.gradient, 7, 2, 1, 2) + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.gridLayout_2.addItem(spacerItem, 3, 3, 1, 1) + self.fpsLabel = QtWidgets.QLabel(self.centralwidget) + font = QtGui.QFont() + font.setPointSize(12) + self.fpsLabel.setFont(font) + self.fpsLabel.setAlignment(QtCore.Qt.AlignCenter) + self.fpsLabel.setObjectName("fpsLabel") + self.gridLayout_2.addWidget(self.fpsLabel, 0, 0, 1, 4) + self.rgbCheck = QtWidgets.QCheckBox(self.centralwidget) + self.rgbCheck.setObjectName("rgbCheck") + self.gridLayout_2.addWidget(self.rgbCheck, 3, 1, 1, 1) + self.label_5 = QtWidgets.QLabel(self.centralwidget) + self.label_5.setObjectName("label_5") + self.gridLayout_2.addWidget(self.label_5, 2, 0, 1, 1) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.framesSpin = QtWidgets.QSpinBox(self.centralwidget) + self.framesSpin.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) + self.framesSpin.setProperty("value", 10) + self.framesSpin.setObjectName("framesSpin") + self.horizontalLayout_4.addWidget(self.framesSpin) + self.widthSpin = QtWidgets.QSpinBox(self.centralwidget) + self.widthSpin.setButtonSymbols(QtWidgets.QAbstractSpinBox.PlusMinus) + self.widthSpin.setMaximum(10000) + self.widthSpin.setProperty("value", 512) + self.widthSpin.setObjectName("widthSpin") + self.horizontalLayout_4.addWidget(self.widthSpin) + self.heightSpin = QtWidgets.QSpinBox(self.centralwidget) + self.heightSpin.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) + self.heightSpin.setMaximum(10000) + self.heightSpin.setProperty("value", 512) + self.heightSpin.setObjectName("heightSpin") + self.horizontalLayout_4.addWidget(self.heightSpin) + self.gridLayout_2.addLayout(self.horizontalLayout_4, 2, 1, 1, 2) + self.sizeLabel = QtWidgets.QLabel(self.centralwidget) + self.sizeLabel.setText("") + self.sizeLabel.setObjectName("sizeLabel") + self.gridLayout_2.addWidget(self.sizeLabel, 2, 3, 1, 1) + MainWindow.setCentralWidget(self.centralwidget) + + self.retranslateUi(MainWindow) + self.stack.setCurrentIndex(2) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(QtWidgets.QApplication.translate("MainWindow", "MainWindow", None, -1)) + self.downsampleCheck.setText(QtWidgets.QApplication.translate("MainWindow", "Auto downsample", None, -1)) + self.scaleCheck.setText(QtWidgets.QApplication.translate("MainWindow", "Scale Data", None, -1)) + self.rawRadio.setText(QtWidgets.QApplication.translate("MainWindow", "RawImageWidget", None, -1)) + self.gfxRadio.setText(QtWidgets.QApplication.translate("MainWindow", "GraphicsView + ImageItem", None, -1)) + self.rawGLRadio.setText(QtWidgets.QApplication.translate("MainWindow", "RawGLImageWidget", None, -1)) + self.dtypeCombo.setItemText(0, QtWidgets.QApplication.translate("MainWindow", "uint8", None, -1)) + self.dtypeCombo.setItemText(1, QtWidgets.QApplication.translate("MainWindow", "uint16", None, -1)) + self.dtypeCombo.setItemText(2, QtWidgets.QApplication.translate("MainWindow", "float", None, -1)) + self.label.setText(QtWidgets.QApplication.translate("MainWindow", "Data type", None, -1)) + self.rgbLevelsCheck.setText(QtWidgets.QApplication.translate("MainWindow", "RGB", None, -1)) + self.label_3.setText(QtWidgets.QApplication.translate("MainWindow", "<--->", None, -1)) + self.label_2.setText(QtWidgets.QApplication.translate("MainWindow", "<--->", None, -1)) + self.label_4.setText(QtWidgets.QApplication.translate("MainWindow", "<--->", None, -1)) + self.lutCheck.setText(QtWidgets.QApplication.translate("MainWindow", "Use Lookup Table", None, -1)) + self.alphaCheck.setText(QtWidgets.QApplication.translate("MainWindow", "alpha", None, -1)) + self.fpsLabel.setText(QtWidgets.QApplication.translate("MainWindow", "FPS", None, -1)) + self.rgbCheck.setText(QtWidgets.QApplication.translate("MainWindow", "RGB", None, -1)) + self.label_5.setText(QtWidgets.QApplication.translate("MainWindow", "Image size", None, -1)) + +from pyqtgraph.widgets.RawImageWidget import RawImageGLWidget, RawImageWidget +from pyqtgraph import GradientWidget, SpinBox, GraphicsView diff --git a/examples/__main__.py b/examples/__main__.py index 084fe2c3..9c49bb3b 100644 --- a/examples/__main__.py +++ b/examples/__main__.py @@ -7,14 +7,16 @@ if __name__ == "__main__" and (__package__ is None or __package__==''): import pyqtgraph as pg import subprocess from pyqtgraph.python2_3 import basestring -from pyqtgraph.Qt import QtGui, USE_PYSIDE, USE_PYQT5 +from pyqtgraph.Qt import QtGui, QT_LIB from .utils import buildFileList, testFile, path, examples -if USE_PYSIDE: +if QT_LIB == 'PySide': from .exampleLoaderTemplate_pyside import Ui_Form -elif USE_PYQT5: +elif QT_LIB == 'PySide2': + from .exampleLoaderTemplate_pyside2 import Ui_Form +elif QT_LIB == 'PyQt5': from .exampleLoaderTemplate_pyqt5 import Ui_Form else: from .exampleLoaderTemplate_pyqt import Ui_Form diff --git a/examples/designerExample_pyside2.py b/examples/designerExample_pyside2.py new file mode 100644 index 00000000..1e04c1ac --- /dev/null +++ b/examples/designerExample_pyside2.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'examples/designerExample.ui' +# +# Created: Fri Feb 16 20:31:04 2018 +# by: pyside2-uic 2.0.0 running on PySide2 2.0.0~alpha0 +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore, QtGui, QtWidgets + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(400, 300) + self.gridLayout = QtWidgets.QGridLayout(Form) + self.gridLayout.setObjectName("gridLayout") + self.plotBtn = QtWidgets.QPushButton(Form) + self.plotBtn.setObjectName("plotBtn") + self.gridLayout.addWidget(self.plotBtn, 0, 0, 1, 1) + self.plot = PlotWidget(Form) + self.plot.setObjectName("plot") + self.gridLayout.addWidget(self.plot, 1, 0, 1, 1) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1)) + self.plotBtn.setText(QtWidgets.QApplication.translate("Form", "Plot!", None, -1)) + +from pyqtgraph import PlotWidget diff --git a/examples/exampleLoaderTemplate.ui b/examples/exampleLoaderTemplate.ui index a1d6bc19..f12459ba 100644 --- a/examples/exampleLoaderTemplate.ui +++ b/examples/exampleLoaderTemplate.ui @@ -79,6 +79,11 @@ PyQt5 + + + PySide2 + + diff --git a/examples/exampleLoaderTemplate_pyqt.py b/examples/exampleLoaderTemplate_pyqt.py index 708839f5..732a3ea1 100644 --- a/examples/exampleLoaderTemplate_pyqt.py +++ b/examples/exampleLoaderTemplate_pyqt.py @@ -1,9 +1,8 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file 'exampleLoaderTemplate.ui' +# Form implementation generated from reading ui file 'examples/exampleLoaderTemplate.ui' # -# Created: Sat Feb 28 10:30:29 2015 -# by: PyQt4 UI code generator 4.10.4 +# Created by: PyQt4 UI code generator 4.11.4 # # WARNING! All changes made in this file will be lost! @@ -35,7 +34,6 @@ class Ui_Form(object): self.widget = QtGui.QWidget(self.splitter) self.widget.setObjectName(_fromUtf8("widget")) self.gridLayout = QtGui.QGridLayout(self.widget) - self.gridLayout.setMargin(0) self.gridLayout.setObjectName(_fromUtf8("gridLayout")) self.exampleTree = QtGui.QTreeWidget(self.widget) self.exampleTree.setObjectName(_fromUtf8("exampleTree")) @@ -55,6 +53,7 @@ class Ui_Form(object): self.qtLibCombo.addItem(_fromUtf8("")) self.qtLibCombo.addItem(_fromUtf8("")) self.qtLibCombo.addItem(_fromUtf8("")) + self.qtLibCombo.addItem(_fromUtf8("")) self.gridLayout.addWidget(self.qtLibCombo, 1, 1, 1, 1) self.label_2 = QtGui.QLabel(self.widget) self.label_2.setObjectName(_fromUtf8("label_2")) @@ -68,7 +67,6 @@ class Ui_Form(object): self.widget1 = QtGui.QWidget(self.splitter) self.widget1.setObjectName(_fromUtf8("widget1")) self.verticalLayout = QtGui.QVBoxLayout(self.widget1) - self.verticalLayout.setMargin(0) self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) self.loadedFileLabel = QtGui.QLabel(self.widget1) font = QtGui.QFont() @@ -100,6 +98,7 @@ class Ui_Form(object): self.qtLibCombo.setItemText(1, _translate("Form", "PyQt4", None)) self.qtLibCombo.setItemText(2, _translate("Form", "PySide", None)) self.qtLibCombo.setItemText(3, _translate("Form", "PyQt5", None)) + self.qtLibCombo.setItemText(4, _translate("Form", "PySide2", None)) self.label_2.setText(_translate("Form", "Graphics System:", None)) self.label.setText(_translate("Form", "Qt Library:", None)) self.loadBtn.setText(_translate("Form", "Run Example", None)) diff --git a/examples/exampleLoaderTemplate_pyqt5.py b/examples/exampleLoaderTemplate_pyqt5.py index 29c00325..14ded4d9 100644 --- a/examples/exampleLoaderTemplate_pyqt5.py +++ b/examples/exampleLoaderTemplate_pyqt5.py @@ -1,9 +1,8 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file 'exampleLoaderTemplate.ui' +# Form implementation generated from reading ui file 'examples/exampleLoaderTemplate.ui' # -# Created: Sat Feb 28 10:28:50 2015 -# by: PyQt5 UI code generator 5.2.1 +# Created by: PyQt5 UI code generator 5.6 # # WARNING! All changes made in this file will be lost! @@ -41,6 +40,7 @@ class Ui_Form(object): self.qtLibCombo.addItem("") self.qtLibCombo.addItem("") self.qtLibCombo.addItem("") + self.qtLibCombo.addItem("") self.gridLayout.addWidget(self.qtLibCombo, 1, 1, 1, 1) self.label_2 = QtWidgets.QLabel(self.widget) self.label_2.setObjectName("label_2") @@ -87,6 +87,7 @@ class Ui_Form(object): self.qtLibCombo.setItemText(1, _translate("Form", "PyQt4")) self.qtLibCombo.setItemText(2, _translate("Form", "PySide")) self.qtLibCombo.setItemText(3, _translate("Form", "PyQt5")) + self.qtLibCombo.setItemText(4, _translate("Form", "PySide2")) self.label_2.setText(_translate("Form", "Graphics System:")) self.label.setText(_translate("Form", "Qt Library:")) self.loadBtn.setText(_translate("Form", "Run Example")) diff --git a/examples/exampleLoaderTemplate_pyside.py b/examples/exampleLoaderTemplate_pyside.py index 61f1d09f..62296827 100644 --- a/examples/exampleLoaderTemplate_pyside.py +++ b/examples/exampleLoaderTemplate_pyside.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file 'exampleLoaderTemplate.ui' +# Form implementation generated from reading ui file 'examples/exampleLoaderTemplate.ui' # -# Created: Sat Feb 28 10:31:57 2015 -# by: pyside-uic 0.2.15 running on PySide 1.2.1 +# Created: Fri Feb 16 20:29:46 2018 +# by: pyside-uic 0.2.15 running on PySide 1.2.4 # # WARNING! All changes made in this file will be lost! @@ -41,6 +41,7 @@ class Ui_Form(object): self.qtLibCombo.addItem("") self.qtLibCombo.addItem("") self.qtLibCombo.addItem("") + self.qtLibCombo.addItem("") self.gridLayout.addWidget(self.qtLibCombo, 1, 1, 1, 1) self.label_2 = QtGui.QLabel(self.widget) self.label_2.setObjectName("label_2") @@ -86,6 +87,7 @@ class Ui_Form(object): self.qtLibCombo.setItemText(1, QtGui.QApplication.translate("Form", "PyQt4", None, QtGui.QApplication.UnicodeUTF8)) self.qtLibCombo.setItemText(2, QtGui.QApplication.translate("Form", "PySide", None, QtGui.QApplication.UnicodeUTF8)) self.qtLibCombo.setItemText(3, QtGui.QApplication.translate("Form", "PyQt5", None, QtGui.QApplication.UnicodeUTF8)) + self.qtLibCombo.setItemText(4, QtGui.QApplication.translate("Form", "PySide2", None, QtGui.QApplication.UnicodeUTF8)) self.label_2.setText(QtGui.QApplication.translate("Form", "Graphics System:", None, QtGui.QApplication.UnicodeUTF8)) self.label.setText(QtGui.QApplication.translate("Form", "Qt Library:", None, QtGui.QApplication.UnicodeUTF8)) self.loadBtn.setText(QtGui.QApplication.translate("Form", "Run Example", None, QtGui.QApplication.UnicodeUTF8)) diff --git a/examples/exampleLoaderTemplate_pyside2.py b/examples/exampleLoaderTemplate_pyside2.py new file mode 100644 index 00000000..6bef728b --- /dev/null +++ b/examples/exampleLoaderTemplate_pyside2.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'examples/exampleLoaderTemplate.ui' +# +# Created: Fri Feb 16 20:30:37 2018 +# by: pyside2-uic 2.0.0 running on PySide2 2.0.0~alpha0 +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore, QtGui, QtWidgets + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(846, 552) + self.gridLayout_2 = QtWidgets.QGridLayout(Form) + self.gridLayout_2.setObjectName("gridLayout_2") + self.splitter = QtWidgets.QSplitter(Form) + self.splitter.setOrientation(QtCore.Qt.Horizontal) + self.splitter.setObjectName("splitter") + self.widget = QtWidgets.QWidget(self.splitter) + self.widget.setObjectName("widget") + self.gridLayout = QtWidgets.QGridLayout(self.widget) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.exampleTree = QtWidgets.QTreeWidget(self.widget) + self.exampleTree.setObjectName("exampleTree") + self.exampleTree.headerItem().setText(0, "1") + self.exampleTree.header().setVisible(False) + self.gridLayout.addWidget(self.exampleTree, 0, 0, 1, 2) + self.graphicsSystemCombo = QtWidgets.QComboBox(self.widget) + self.graphicsSystemCombo.setObjectName("graphicsSystemCombo") + self.graphicsSystemCombo.addItem("") + self.graphicsSystemCombo.addItem("") + self.graphicsSystemCombo.addItem("") + self.graphicsSystemCombo.addItem("") + self.gridLayout.addWidget(self.graphicsSystemCombo, 2, 1, 1, 1) + self.qtLibCombo = QtWidgets.QComboBox(self.widget) + self.qtLibCombo.setObjectName("qtLibCombo") + self.qtLibCombo.addItem("") + self.qtLibCombo.addItem("") + self.qtLibCombo.addItem("") + self.qtLibCombo.addItem("") + self.qtLibCombo.addItem("") + self.gridLayout.addWidget(self.qtLibCombo, 1, 1, 1, 1) + self.label_2 = QtWidgets.QLabel(self.widget) + self.label_2.setObjectName("label_2") + self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1) + self.label = QtWidgets.QLabel(self.widget) + self.label.setObjectName("label") + self.gridLayout.addWidget(self.label, 1, 0, 1, 1) + self.loadBtn = QtWidgets.QPushButton(self.widget) + self.loadBtn.setObjectName("loadBtn") + self.gridLayout.addWidget(self.loadBtn, 3, 1, 1, 1) + self.widget1 = QtWidgets.QWidget(self.splitter) + self.widget1.setObjectName("widget1") + self.verticalLayout = QtWidgets.QVBoxLayout(self.widget1) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setObjectName("verticalLayout") + self.loadedFileLabel = QtWidgets.QLabel(self.widget1) + font = QtGui.QFont() + font.setWeight(75) + font.setBold(True) + self.loadedFileLabel.setFont(font) + self.loadedFileLabel.setText("") + self.loadedFileLabel.setAlignment(QtCore.Qt.AlignCenter) + self.loadedFileLabel.setObjectName("loadedFileLabel") + self.verticalLayout.addWidget(self.loadedFileLabel) + self.codeView = QtWidgets.QPlainTextEdit(self.widget1) + font = QtGui.QFont() + font.setFamily("FreeMono") + self.codeView.setFont(font) + self.codeView.setObjectName("codeView") + self.verticalLayout.addWidget(self.codeView) + self.gridLayout_2.addWidget(self.splitter, 0, 0, 1, 1) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1)) + self.graphicsSystemCombo.setItemText(0, QtWidgets.QApplication.translate("Form", "default", None, -1)) + self.graphicsSystemCombo.setItemText(1, QtWidgets.QApplication.translate("Form", "native", None, -1)) + self.graphicsSystemCombo.setItemText(2, QtWidgets.QApplication.translate("Form", "raster", None, -1)) + self.graphicsSystemCombo.setItemText(3, QtWidgets.QApplication.translate("Form", "opengl", None, -1)) + self.qtLibCombo.setItemText(0, QtWidgets.QApplication.translate("Form", "default", None, -1)) + self.qtLibCombo.setItemText(1, QtWidgets.QApplication.translate("Form", "PyQt4", None, -1)) + self.qtLibCombo.setItemText(2, QtWidgets.QApplication.translate("Form", "PySide", None, -1)) + self.qtLibCombo.setItemText(3, QtWidgets.QApplication.translate("Form", "PyQt5", None, -1)) + self.qtLibCombo.setItemText(4, QtWidgets.QApplication.translate("Form", "PySide2", None, -1)) + self.label_2.setText(QtWidgets.QApplication.translate("Form", "Graphics System:", None, -1)) + self.label.setText(QtWidgets.QApplication.translate("Form", "Qt Library:", None, -1)) + self.loadBtn.setText(QtWidgets.QApplication.translate("Form", "Run Example", None, -1)) + diff --git a/examples/initExample.py b/examples/initExample.py index c10de84e..8bce7441 100644 --- a/examples/initExample.py +++ b/examples/initExample.py @@ -26,6 +26,8 @@ elif 'pyqt' in sys.argv: from PyQt4 import QtGui elif 'pyqt5' in sys.argv: from PyQt5 import QtGui +elif 'pyside2' in sys.argv: + from PySide2 import QtGui else: from pyqtgraph.Qt import QtGui diff --git a/examples/optics/pyoptic.py b/examples/optics/pyoptic.py index c2cb2ba2..f59f3bac 100644 --- a/examples/optics/pyoptic.py +++ b/examples/optics/pyoptic.py @@ -110,7 +110,11 @@ class ParamObj(object): def __getitem__(self, item): # bug in pyside 1.2.2 causes getitem to be called inside QGraphicsObject.parentItem: - return self.getParam(item) # PySide bug: https://bugreports.qt.io/browse/PYSIDE-441 + return self.getParam(item) # PySide bug: https://bugreports.qt.io/browse/PYSIDE-671 + + def __len__(self): + # Workaround for PySide bug: https://bugreports.qt.io/browse/PYSIDE-671 + return 0 def getParam(self, param): return self.__params[param] @@ -235,35 +239,21 @@ class Lens(Optic): N must already be normalized in order to achieve the desired result. """ - - - iors = [self.ior(ray['wl']), 1.0] for i in [0,1]: surface = self.surfaces[i] ior = iors[i] p1, ai = surface.intersectRay(ray) - #print "surface intersection:", p1, ai*180/3.14159 - #trans = self.sceneTransform().inverted()[0] * surface.sceneTransform() - #p1 = trans.map(p1) if p1 is None: ray.setEnd(None) break p1 = surface.mapToItem(ray, p1) - #print "adjusted position:", p1 - #ior = self.ior(ray['wl']) rd = ray['dir'] a1 = np.arctan2(rd[1], rd[0]) ar = a1 - ai + np.arcsin((np.sin(ai) * ray['ior'] / ior)) - #print [x for x in [a1, ai, (np.sin(ai) * ray['ior'] / ior), ar]] - #print ai, np.sin(ai), ray['ior'], ior ray.setEnd(p1) dp = Point(np.cos(ar), np.sin(ar)) - #p2 = p1+dp - #p1p = self.mapToScene(p1) - #p2p = self.mapToScene(p2) - #dpp = Point(p2p-p1p) ray = Ray(parent=ray, ior=ior, dir=dp) return [ray] @@ -384,20 +374,12 @@ class CircleSurface(pg.GraphicsObject): else: ## half-height of surface can't be larger than radius h2 = min(h2, abs(r)) - - #dx = abs(r) - (abs(r)**2 - abs(h2)**2)**0.5 - #p.moveTo(-d*w/2.+ d*dx, d*h2) arc = QtCore.QRectF(0, -r, r*2, r*2) - #self.surfaces.append((arc.center(), r, h2)) a1 = np.arcsin(h2/r) * 180. / np.pi a2 = -2*a1 a1 += 180. self.path.arcMoveTo(arc, a1) self.path.arcTo(arc, a1, a2) - #if d == -1: - #p1 = QtGui.QPainterPath() - #p1.addRect(arc) - #self.paths.append(p1) self.h2 = h2 def boundingRect(self): @@ -405,8 +387,6 @@ class CircleSurface(pg.GraphicsObject): def paint(self, p, *args): return ## usually we let the optic draw. - #p.setPen(pg.mkPen('r')) - #p.drawPath(self.path) def intersectRay(self, ray): ## return the point of intersection and the angle of incidence @@ -527,7 +507,6 @@ class Ray(pg.GraphicsObject, ParamObj): p2 = trans.map(pos + dir) return Point(p1), Point(p2-p1) - def setEnd(self, end): self['end'] = end self.mkPath() @@ -561,6 +540,7 @@ def trace(rays, optics): r2 = o.propagateRay(r) trace(r2, optics[1:]) + class Tracer(QtCore.QObject): """ Simple ray tracer. diff --git a/pyqtgraph/GraphicsScene/exportDialog.py b/pyqtgraph/GraphicsScene/exportDialog.py index 2676a3b4..8085c5bf 100644 --- a/pyqtgraph/GraphicsScene/exportDialog.py +++ b/pyqtgraph/GraphicsScene/exportDialog.py @@ -1,12 +1,14 @@ -from ..Qt import QtCore, QtGui, USE_PYSIDE, USE_PYQT5 +from ..Qt import QtCore, QtGui, QT_LIB from .. import exporters as exporters from .. import functions as fn from ..graphicsItems.ViewBox import ViewBox from ..graphicsItems.PlotItem import PlotItem -if USE_PYSIDE: +if QT_LIB == 'PySide': from . import exportDialogTemplate_pyside as exportDialogTemplate -elif USE_PYQT5: +elif QT_LIB == 'PySide2': + from . import exportDialogTemplate_pyside2 as exportDialogTemplate +elif QT_LIB == 'PyQt5': from . import exportDialogTemplate_pyqt5 as exportDialogTemplate else: from . import exportDialogTemplate_pyqt as exportDialogTemplate diff --git a/pyqtgraph/GraphicsScene/exportDialogTemplate_pyside2.py b/pyqtgraph/GraphicsScene/exportDialogTemplate_pyside2.py new file mode 100644 index 00000000..6c0fec47 --- /dev/null +++ b/pyqtgraph/GraphicsScene/exportDialogTemplate_pyside2.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'exportDialogTemplate.ui' +# +# Created: Sun Sep 18 19:19:58 2016 +# by: pyside2-uic running on PySide2 2.0.0~alpha0 +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore, QtGui, QtWidgets + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(241, 367) + self.gridLayout = QtWidgets.QGridLayout(Form) + self.gridLayout.setSpacing(0) + self.gridLayout.setObjectName("gridLayout") + self.label = QtWidgets.QLabel(Form) + self.label.setObjectName("label") + self.gridLayout.addWidget(self.label, 0, 0, 1, 3) + self.itemTree = QtWidgets.QTreeWidget(Form) + self.itemTree.setObjectName("itemTree") + self.itemTree.headerItem().setText(0, "1") + self.itemTree.header().setVisible(False) + self.gridLayout.addWidget(self.itemTree, 1, 0, 1, 3) + self.label_2 = QtWidgets.QLabel(Form) + self.label_2.setObjectName("label_2") + self.gridLayout.addWidget(self.label_2, 2, 0, 1, 3) + self.formatList = QtWidgets.QListWidget(Form) + self.formatList.setObjectName("formatList") + self.gridLayout.addWidget(self.formatList, 3, 0, 1, 3) + self.exportBtn = QtWidgets.QPushButton(Form) + self.exportBtn.setObjectName("exportBtn") + self.gridLayout.addWidget(self.exportBtn, 6, 1, 1, 1) + self.closeBtn = QtWidgets.QPushButton(Form) + self.closeBtn.setObjectName("closeBtn") + self.gridLayout.addWidget(self.closeBtn, 6, 2, 1, 1) + self.paramTree = ParameterTree(Form) + self.paramTree.setObjectName("paramTree") + self.paramTree.headerItem().setText(0, "1") + self.paramTree.header().setVisible(False) + self.gridLayout.addWidget(self.paramTree, 5, 0, 1, 3) + self.label_3 = QtWidgets.QLabel(Form) + self.label_3.setObjectName("label_3") + self.gridLayout.addWidget(self.label_3, 4, 0, 1, 3) + self.copyBtn = QtWidgets.QPushButton(Form) + self.copyBtn.setObjectName("copyBtn") + self.gridLayout.addWidget(self.copyBtn, 6, 0, 1, 1) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Export", None, -1)) + self.label.setText(QtWidgets.QApplication.translate("Form", "Item to export:", None, -1)) + self.label_2.setText(QtWidgets.QApplication.translate("Form", "Export format", None, -1)) + self.exportBtn.setText(QtWidgets.QApplication.translate("Form", "Export", None, -1)) + self.closeBtn.setText(QtWidgets.QApplication.translate("Form", "Close", None, -1)) + self.label_3.setText(QtWidgets.QApplication.translate("Form", "Export options", None, -1)) + self.copyBtn.setText(QtWidgets.QApplication.translate("Form", "Copy", None, -1)) + +from ..parametertree import ParameterTree diff --git a/pyqtgraph/Qt.py b/pyqtgraph/Qt.py index 4ce571cc..88c27e27 100644 --- a/pyqtgraph/Qt.py +++ b/pyqtgraph/Qt.py @@ -14,17 +14,18 @@ import os, sys, re, time from .python2_3 import asUnicode PYSIDE = 'PySide' +PYSIDE2 = 'PySide2' PYQT4 = 'PyQt4' PYQT5 = 'PyQt5' QT_LIB = os.getenv('PYQTGRAPH_QT_LIB') -## Automatically determine whether to use PyQt or PySide (unless specified by +## Automatically determine which Qt package to use (unless specified by ## environment variable). ## This is done by first checking to see whether one of the libraries ## is already imported. If not, then attempt to import PyQt4, then PySide. if QT_LIB is None: - libOrder = [PYQT4, PYSIDE, PYQT5] + libOrder = [PYQT4, PYSIDE, PYQT5, PYSIDE2] for lib in libOrder: if lib in sys.modules: @@ -41,7 +42,7 @@ if QT_LIB is None: pass if QT_LIB is None: - raise Exception("PyQtGraph requires one of PyQt4, PyQt5 or PySide; none of these packages could be imported.") + raise Exception("PyQtGraph requires one of PyQt4, PyQt5, PySide or PySide2; none of these packages could be imported.") class FailedImport(object): @@ -54,6 +55,74 @@ class FailedImport(object): raise self.err +def _isQObjectAlive(obj): + """An approximation of PyQt's isQObjectAlive(). + """ + try: + if hasattr(obj, 'parent'): + obj.parent() + elif hasattr(obj, 'parentItem'): + obj.parentItem() + else: + raise Exception("Cannot determine whether Qt object %s is still alive." % obj) + except RuntimeError: + return False + else: + return True + + +# Make a loadUiType function like PyQt has + +# Credit: +# http://stackoverflow.com/questions/4442286/python-code-genration-with-pyside-uic/14195313#14195313 + +class _StringIO(object): + """Alternative to built-in StringIO needed to circumvent unicode/ascii issues""" + def __init__(self): + self.data = [] + + def write(self, data): + self.data.append(data) + + def getvalue(self): + return ''.join(map(asUnicode, self.data)).encode('utf8') + + +def _loadUiType(uiFile): + """ + PySide lacks a "loadUiType" command like PyQt4's, so we have to convert + the ui file to py code in-memory first and then execute it in a + special frame to retrieve the form_class. + + from stackoverflow: http://stackoverflow.com/a/14195313/3781327 + + seems like this might also be a legitimate solution, but I'm not sure + how to make PyQt4 and pyside look the same... + http://stackoverflow.com/a/8717832 + """ + import pysideuic + import xml.etree.ElementTree as xml + #from io import StringIO + + parsed = xml.parse(uiFile) + widget_class = parsed.find('widget').get('class') + form_class = parsed.find('class').text + + with open(uiFile, 'r') as f: + o = _StringIO() + frame = {} + + pysideuic.compileUi(f, o, indent=0) + pyc = compile(o.getvalue(), '', 'exec') + exec(pyc, frame) + + #Fetch the base_class and form class based on their type in the xml from designer + form_class = frame['Ui_%s'%form_class] + base_class = eval('QtGui.%s'%widget_class) + + return form_class, base_class + + if QT_LIB == PYSIDE: from PySide import QtGui, QtCore @@ -68,89 +137,20 @@ if QT_LIB == PYSIDE: try: from PySide import QtTest - if not hasattr(QtTest.QTest, 'qWait'): - @staticmethod - def qWait(msec): - start = time.time() - QtGui.QApplication.processEvents() - while time.time() < start + msec * 0.001: - QtGui.QApplication.processEvents() - QtTest.QTest.qWait = qWait except ImportError as err: QtTest = FailedImport(err) - - import PySide + try: from PySide import shiboken isQObjectAlive = shiboken.isValid except ImportError: - def isQObjectAlive(obj): - try: - if hasattr(obj, 'parent'): - obj.parent() - elif hasattr(obj, 'parentItem'): - obj.parentItem() - else: - raise Exception("Cannot determine whether Qt object %s is still alive." % obj) - except RuntimeError: - return False - else: - return True + # use approximate version + isQObjectAlive = _isQObjectAlive - VERSION_INFO = 'PySide ' + PySide.__version__ + import PySide + VERSION_INFO = 'PySide ' + PySide.__version__ + ' Qt ' + QtCore.__version__ - # Make a loadUiType function like PyQt has - - # Credit: - # http://stackoverflow.com/questions/4442286/python-code-genration-with-pyside-uic/14195313#14195313 - - class StringIO(object): - """Alternative to built-in StringIO needed to circumvent unicode/ascii issues""" - def __init__(self): - self.data = [] - - def write(self, data): - self.data.append(data) - - def getvalue(self): - return ''.join(map(asUnicode, self.data)).encode('utf8') - - def loadUiType(uiFile): - """ - Pyside "loadUiType" command like PyQt4 has one, so we have to convert - the ui file to py code in-memory first and then execute it in a - special frame to retrieve the form_class. - - from stackoverflow: http://stackoverflow.com/a/14195313/3781327 - - seems like this might also be a legitimate solution, but I'm not sure - how to make PyQt4 and pyside look the same... - http://stackoverflow.com/a/8717832 - """ - import pysideuic - import xml.etree.ElementTree as xml - #from io import StringIO - - parsed = xml.parse(uiFile) - widget_class = parsed.find('widget').get('class') - form_class = parsed.find('class').text - - with open(uiFile, 'r') as f: - o = StringIO() - frame = {} - - pysideuic.compileUi(f, o, indent=0) - pyc = compile(o.getvalue(), '', 'exec') - exec(pyc, frame) - - #Fetch the base_class and form class based on their type in the xml from designer - form_class = frame['Ui_%s'%form_class] - base_class = eval('QtGui.%s'%widget_class) - - return form_class, base_class - elif QT_LIB == PYQT4: - from PyQt4 import QtGui, QtCore, uic try: from PyQt4 import QtSvg @@ -168,7 +168,6 @@ elif QT_LIB == PYQT4: VERSION_INFO = 'PyQt4 ' + QtCore.PYQT_VERSION_STR + ' Qt ' + QtCore.QT_VERSION_STR elif QT_LIB == PYQT5: - # We're using PyQt5 which has a different structure so we're going to use a shim to # recreate the Qt4 structure for Qt5 from PyQt5 import QtGui, QtCore, QtWidgets, uic @@ -198,8 +197,39 @@ elif QT_LIB == PYQT5: except ImportError as err: QtTest = FailedImport(err) - # Re-implement deprecated APIs + VERSION_INFO = 'PyQt5 ' + QtCore.PYQT_VERSION_STR + ' Qt ' + QtCore.QT_VERSION_STR +elif QT_LIB == PYSIDE2: + from PySide2 import QtGui, QtCore, QtWidgets + + try: + from PySide2 import QtSvg + except ImportError as err: + QtSvg = FailedImport(err) + try: + from PySide2 import QtOpenGL + except ImportError as err: + QtOpenGL = FailedImport(err) + try: + from PySide2 import QtTest + QtTest.QTest.qWaitForWindowShown = QtTest.QTest.qWaitForWindowExposed + except ImportError as err: + QtTest = FailedImport(err) + + isQObjectAlive = _isQObjectAlive + + import PySide2 + VERSION_INFO = 'PySide2 ' + PySide2.__version__ + ' Qt ' + QtCore.__version__ + +else: + raise ValueError("Invalid Qt lib '%s'" % QT_LIB) + + +# common to PyQt5 and PySide2 +if QT_LIB in [PYQT5, PYSIDE2]: + # We're using Qt5 which has a different structure so we're going to use a shim to + # recreate the Qt4 structure + __QGraphicsItem_scale = QtWidgets.QGraphicsItem.scale def scale(self, *args): @@ -246,28 +276,45 @@ elif QT_LIB == PYQT5: if o.startswith('Q'): setattr(QtGui, o, getattr(QtWidgets,o) ) - VERSION_INFO = 'PyQt5 ' + QtCore.PYQT_VERSION_STR + ' Qt ' + QtCore.QT_VERSION_STR -else: - raise ValueError("Invalid Qt lib '%s'" % QT_LIB) +# Common to PySide and PySide2 +if QT_LIB in [PYSIDE, PYSIDE2]: + QtVersion = QtCore.__version__ + loadUiType = _loadUiType + + # PySide does not implement qWait + if not isinstance(QtTest, FailedImport): + if not hasattr(QtTest.QTest, 'qWait'): + @staticmethod + def qWait(msec): + start = time.time() + QtGui.QApplication.processEvents() + while time.time() < start + msec * 0.001: + QtGui.QApplication.processEvents() + QtTest.QTest.qWait = qWait + # Common to PyQt4 and 5 -if QT_LIB.startswith('PyQt'): +if QT_LIB in [PYQT4, PYQT5]: + QtVersion = QtCore.QT_VERSION_STR + import sip def isQObjectAlive(obj): return not sip.isdeleted(obj) + loadUiType = uic.loadUiType QtCore.Signal = QtCore.pyqtSignal - -## Make sure we have Qt >= 4.7 -versionReq = [4, 7] +# USE_XXX variables are deprecated USE_PYSIDE = QT_LIB == PYSIDE USE_PYQT4 = QT_LIB == PYQT4 USE_PYQT5 = QT_LIB == PYQT5 -QtVersion = PySide.QtCore.__version__ if QT_LIB == PYSIDE else QtCore.QT_VERSION_STR + + +## Make sure we have Qt >= 4.7 +versionReq = [4, 7] m = re.match(r'(\d+)\.(\d+).*', QtVersion) if m is not None and list(map(int, m.groups())) < versionReq: print(list(map(int, m.groups()))) diff --git a/pyqtgraph/Transform3D.py b/pyqtgraph/Transform3D.py index 56283351..b5a41bc2 100644 --- a/pyqtgraph/Transform3D.py +++ b/pyqtgraph/Transform3D.py @@ -10,10 +10,14 @@ class Transform3D(QtGui.QMatrix4x4): Extension of QMatrix4x4 with some helpful methods added. """ def __init__(self, *args): - if len(args) == 1 and isinstance(args[0], (list, tuple, np.ndarray)): - args = [x for y in args[0] for x in y] - if len(args) != 16: - raise TypeError("Single argument to Transform3D must have 16 elements.") + if len(args) == 1: + if isinstance(args[0], (list, tuple, np.ndarray)): + args = [x for y in args[0] for x in y] + if len(args) != 16: + raise TypeError("Single argument to Transform3D must have 16 elements.") + elif isinstance(args[0], QtGui.QMatrix4x4): + args = list(args[0].copyDataTo()) + QtGui.QMatrix4x4.__init__(self, *args) def matrix(self, nd=3): @@ -45,4 +49,4 @@ class Transform3D(QtGui.QMatrix4x4): def inverted(self): inv, b = QtGui.QMatrix4x4.inverted(self) - return Transform3D(inv), b \ No newline at end of file + return Transform3D(inv), b diff --git a/pyqtgraph/Vector.py b/pyqtgraph/Vector.py index f2898e80..0c980a61 100644 --- a/pyqtgraph/Vector.py +++ b/pyqtgraph/Vector.py @@ -5,7 +5,7 @@ Copyright 2010 Luke Campagnola Distributed under MIT/X11 license. See license.txt for more infomation. """ -from .Qt import QtGui, QtCore, USE_PYSIDE +from .Qt import QtGui, QtCore, QT_LIB import numpy as np class Vector(QtGui.QVector3D): @@ -36,7 +36,7 @@ class Vector(QtGui.QVector3D): def __add__(self, b): # workaround for pyside bug. see https://bugs.launchpad.net/pyqtgraph/+bug/1223173 - if USE_PYSIDE and isinstance(b, QtGui.QVector3D): + if QT_LIB == 'PySide' and isinstance(b, QtGui.QVector3D): b = Vector(b) return QtGui.QVector3D.__add__(self, b) diff --git a/pyqtgraph/WidgetGroup.py b/pyqtgraph/WidgetGroup.py index d7e265c5..09c30854 100644 --- a/pyqtgraph/WidgetGroup.py +++ b/pyqtgraph/WidgetGroup.py @@ -8,7 +8,7 @@ This class addresses the problem of having to save and restore the state of a large group of widgets. """ -from .Qt import QtCore, QtGui, USE_PYQT5 +from .Qt import QtCore, QtGui, QT_LIB import weakref, inspect from .python2_3 import asUnicode @@ -218,7 +218,7 @@ class WidgetGroup(QtCore.QObject): v1 = self.cache[n] v2 = self.readWidget(w) if v1 != v2: - if not USE_PYQT5: + if QT_LIB != 'PyQt5': # Old signal kept for backward compatibility. self.emit(QtCore.SIGNAL('changed'), self.widgetList[w], v2) self.sigChanged.emit(self.widgetList[w], v2) diff --git a/pyqtgraph/canvas/Canvas.py b/pyqtgraph/canvas/Canvas.py index 2ebc2ba1..72d70d7e 100644 --- a/pyqtgraph/canvas/Canvas.py +++ b/pyqtgraph/canvas/Canvas.py @@ -13,6 +13,8 @@ if QT_LIB == 'PySide': from .CanvasTemplate_pyside import * elif QT_LIB == 'PyQt4': from .CanvasTemplate_pyqt import * +elif QT_LIB == 'PySide2': + from .CanvasTemplate_pyside2 import * elif QT_LIB == 'PyQt5': from .CanvasTemplate_pyqt5 import * diff --git a/pyqtgraph/canvas/CanvasItem.py b/pyqtgraph/canvas/CanvasItem.py index c406256c..57174b5f 100644 --- a/pyqtgraph/canvas/CanvasItem.py +++ b/pyqtgraph/canvas/CanvasItem.py @@ -7,6 +7,8 @@ if QT_LIB == 'PySide': from . import TransformGuiTemplate_pyside as TransformGuiTemplate elif QT_LIB == 'PyQt4': from . import TransformGuiTemplate_pyqt as TransformGuiTemplate +elif QT_LIB == 'PySide2': + from . import TransformGuiTemplate_pyside2 as TransformGuiTemplate elif QT_LIB == 'PyQt5': from . import TransformGuiTemplate_pyqt5 as TransformGuiTemplate diff --git a/pyqtgraph/canvas/CanvasTemplate_pyside2.py b/pyqtgraph/canvas/CanvasTemplate_pyside2.py new file mode 100644 index 00000000..de9c6322 --- /dev/null +++ b/pyqtgraph/canvas/CanvasTemplate_pyside2.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'CanvasTemplate.ui' +# +# Created: Sun Sep 18 19:18:22 2016 +# by: pyside2-uic running on PySide2 2.0.0~alpha0 +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore, QtGui, QtWidgets + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(490, 414) + self.gridLayout = QtWidgets.QGridLayout(Form) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setSpacing(0) + self.gridLayout.setObjectName("gridLayout") + self.splitter = QtWidgets.QSplitter(Form) + self.splitter.setOrientation(QtCore.Qt.Horizontal) + self.splitter.setObjectName("splitter") + self.view = GraphicsView(self.splitter) + self.view.setObjectName("view") + self.layoutWidget = QtWidgets.QWidget(self.splitter) + self.layoutWidget.setObjectName("layoutWidget") + self.gridLayout_2 = QtWidgets.QGridLayout(self.layoutWidget) + self.gridLayout_2.setContentsMargins(0, 0, 0, 0) + self.gridLayout_2.setObjectName("gridLayout_2") + self.autoRangeBtn = QtWidgets.QPushButton(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(1) + sizePolicy.setHeightForWidth(self.autoRangeBtn.sizePolicy().hasHeightForWidth()) + self.autoRangeBtn.setSizePolicy(sizePolicy) + self.autoRangeBtn.setObjectName("autoRangeBtn") + self.gridLayout_2.addWidget(self.autoRangeBtn, 2, 0, 1, 2) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setSpacing(0) + self.horizontalLayout.setObjectName("horizontalLayout") + self.redirectCheck = QtWidgets.QCheckBox(self.layoutWidget) + self.redirectCheck.setObjectName("redirectCheck") + self.horizontalLayout.addWidget(self.redirectCheck) + self.redirectCombo = CanvasCombo(self.layoutWidget) + self.redirectCombo.setObjectName("redirectCombo") + self.horizontalLayout.addWidget(self.redirectCombo) + self.gridLayout_2.addLayout(self.horizontalLayout, 5, 0, 1, 2) + self.itemList = TreeWidget(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(100) + sizePolicy.setHeightForWidth(self.itemList.sizePolicy().hasHeightForWidth()) + self.itemList.setSizePolicy(sizePolicy) + self.itemList.setHeaderHidden(True) + self.itemList.setObjectName("itemList") + self.itemList.headerItem().setText(0, "1") + self.gridLayout_2.addWidget(self.itemList, 6, 0, 1, 2) + self.ctrlLayout = QtWidgets.QGridLayout() + self.ctrlLayout.setSpacing(0) + self.ctrlLayout.setObjectName("ctrlLayout") + self.gridLayout_2.addLayout(self.ctrlLayout, 10, 0, 1, 2) + self.resetTransformsBtn = QtWidgets.QPushButton(self.layoutWidget) + self.resetTransformsBtn.setObjectName("resetTransformsBtn") + self.gridLayout_2.addWidget(self.resetTransformsBtn, 7, 0, 1, 1) + self.mirrorSelectionBtn = QtWidgets.QPushButton(self.layoutWidget) + self.mirrorSelectionBtn.setObjectName("mirrorSelectionBtn") + self.gridLayout_2.addWidget(self.mirrorSelectionBtn, 3, 0, 1, 1) + self.reflectSelectionBtn = QtWidgets.QPushButton(self.layoutWidget) + self.reflectSelectionBtn.setObjectName("reflectSelectionBtn") + self.gridLayout_2.addWidget(self.reflectSelectionBtn, 3, 1, 1, 1) + self.gridLayout.addWidget(self.splitter, 0, 0, 1, 1) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1)) + self.autoRangeBtn.setText(QtWidgets.QApplication.translate("Form", "Auto Range", None, -1)) + self.redirectCheck.setToolTip(QtWidgets.QApplication.translate("Form", "Check to display all local items in a remote canvas.", None, -1)) + self.redirectCheck.setText(QtWidgets.QApplication.translate("Form", "Redirect", None, -1)) + self.resetTransformsBtn.setText(QtWidgets.QApplication.translate("Form", "Reset Transforms", None, -1)) + self.mirrorSelectionBtn.setText(QtWidgets.QApplication.translate("Form", "Mirror Selection", None, -1)) + self.reflectSelectionBtn.setText(QtWidgets.QApplication.translate("Form", "MirrorXY", None, -1)) + +from ..widgets.TreeWidget import TreeWidget +from CanvasManager import CanvasCombo +from ..widgets.GraphicsView import GraphicsView diff --git a/pyqtgraph/canvas/TransformGuiTemplate_pyside2.py b/pyqtgraph/canvas/TransformGuiTemplate_pyside2.py new file mode 100644 index 00000000..e05ceb14 --- /dev/null +++ b/pyqtgraph/canvas/TransformGuiTemplate_pyside2.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'TransformGuiTemplate.ui' +# +# Created: Sun Sep 18 19:18:41 2016 +# by: pyside2-uic running on PySide2 2.0.0~alpha0 +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore, QtGui, QtWidgets + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(224, 117) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth()) + Form.setSizePolicy(sizePolicy) + self.verticalLayout = QtWidgets.QVBoxLayout(Form) + self.verticalLayout.setSpacing(1) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setObjectName("verticalLayout") + self.translateLabel = QtWidgets.QLabel(Form) + self.translateLabel.setObjectName("translateLabel") + self.verticalLayout.addWidget(self.translateLabel) + self.rotateLabel = QtWidgets.QLabel(Form) + self.rotateLabel.setObjectName("rotateLabel") + self.verticalLayout.addWidget(self.rotateLabel) + self.scaleLabel = QtWidgets.QLabel(Form) + self.scaleLabel.setObjectName("scaleLabel") + self.verticalLayout.addWidget(self.scaleLabel) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.mirrorImageBtn = QtWidgets.QPushButton(Form) + self.mirrorImageBtn.setToolTip("") + self.mirrorImageBtn.setObjectName("mirrorImageBtn") + self.horizontalLayout.addWidget(self.mirrorImageBtn) + self.reflectImageBtn = QtWidgets.QPushButton(Form) + self.reflectImageBtn.setObjectName("reflectImageBtn") + self.horizontalLayout.addWidget(self.reflectImageBtn) + self.verticalLayout.addLayout(self.horizontalLayout) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1)) + self.translateLabel.setText(QtWidgets.QApplication.translate("Form", "Translate:", None, -1)) + self.rotateLabel.setText(QtWidgets.QApplication.translate("Form", "Rotate:", None, -1)) + self.scaleLabel.setText(QtWidgets.QApplication.translate("Form", "Scale:", None, -1)) + self.mirrorImageBtn.setText(QtWidgets.QApplication.translate("Form", "Mirror", None, -1)) + self.reflectImageBtn.setText(QtWidgets.QApplication.translate("Form", "Reflect", None, -1)) + diff --git a/pyqtgraph/console/Console.py b/pyqtgraph/console/Console.py index 02f00c44..c30a392c 100644 --- a/pyqtgraph/console/Console.py +++ b/pyqtgraph/console/Console.py @@ -1,13 +1,15 @@ import sys, re, os, time, traceback, subprocess import pickle -from ..Qt import QtCore, QtGui, USE_PYSIDE, USE_PYQT5 +from ..Qt import QtCore, QtGui, QT_LIB from ..python2_3 import basestring from .. import exceptionHandling as exceptionHandling from .. import getConfigOption -if USE_PYSIDE: +if QT_LIB == 'PySide': from . import template_pyside as template -elif USE_PYQT5: +elif QT_LIB == 'PySide2': + from . import template_pyside2 as template +elif QT_LIB == 'PyQt5': from . import template_pyqt5 as template else: from . import template_pyqt as template diff --git a/pyqtgraph/console/template_pyside2.py b/pyqtgraph/console/template_pyside2.py new file mode 100644 index 00000000..c8662c74 --- /dev/null +++ b/pyqtgraph/console/template_pyside2.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'template.ui' +# +# Created: Sun Sep 18 19:19:10 2016 +# by: pyside2-uic running on PySide2 2.0.0~alpha0 +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore, QtGui, QtWidgets + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(694, 497) + self.gridLayout = QtWidgets.QGridLayout(Form) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setSpacing(0) + self.gridLayout.setObjectName("gridLayout") + self.splitter = QtWidgets.QSplitter(Form) + self.splitter.setOrientation(QtCore.Qt.Vertical) + self.splitter.setObjectName("splitter") + self.layoutWidget = QtWidgets.QWidget(self.splitter) + self.layoutWidget.setObjectName("layoutWidget") + self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setObjectName("verticalLayout") + self.output = QtWidgets.QPlainTextEdit(self.layoutWidget) + font = QtGui.QFont() + font.setFamily("Monospace") + self.output.setFont(font) + self.output.setReadOnly(True) + self.output.setObjectName("output") + self.verticalLayout.addWidget(self.output) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.input = CmdInput(self.layoutWidget) + self.input.setObjectName("input") + self.horizontalLayout.addWidget(self.input) + self.historyBtn = QtWidgets.QPushButton(self.layoutWidget) + self.historyBtn.setCheckable(True) + self.historyBtn.setObjectName("historyBtn") + self.horizontalLayout.addWidget(self.historyBtn) + self.exceptionBtn = QtWidgets.QPushButton(self.layoutWidget) + self.exceptionBtn.setCheckable(True) + self.exceptionBtn.setObjectName("exceptionBtn") + self.horizontalLayout.addWidget(self.exceptionBtn) + self.verticalLayout.addLayout(self.horizontalLayout) + self.historyList = QtWidgets.QListWidget(self.splitter) + font = QtGui.QFont() + font.setFamily("Monospace") + self.historyList.setFont(font) + self.historyList.setObjectName("historyList") + self.exceptionGroup = QtWidgets.QGroupBox(self.splitter) + self.exceptionGroup.setObjectName("exceptionGroup") + self.gridLayout_2 = QtWidgets.QGridLayout(self.exceptionGroup) + self.gridLayout_2.setSpacing(0) + self.gridLayout_2.setContentsMargins(-1, 0, -1, 0) + self.gridLayout_2.setObjectName("gridLayout_2") + self.clearExceptionBtn = QtWidgets.QPushButton(self.exceptionGroup) + self.clearExceptionBtn.setEnabled(False) + self.clearExceptionBtn.setObjectName("clearExceptionBtn") + self.gridLayout_2.addWidget(self.clearExceptionBtn, 0, 6, 1, 1) + self.catchAllExceptionsBtn = QtWidgets.QPushButton(self.exceptionGroup) + self.catchAllExceptionsBtn.setCheckable(True) + self.catchAllExceptionsBtn.setObjectName("catchAllExceptionsBtn") + self.gridLayout_2.addWidget(self.catchAllExceptionsBtn, 0, 1, 1, 1) + self.catchNextExceptionBtn = QtWidgets.QPushButton(self.exceptionGroup) + self.catchNextExceptionBtn.setCheckable(True) + self.catchNextExceptionBtn.setObjectName("catchNextExceptionBtn") + self.gridLayout_2.addWidget(self.catchNextExceptionBtn, 0, 0, 1, 1) + self.onlyUncaughtCheck = QtWidgets.QCheckBox(self.exceptionGroup) + self.onlyUncaughtCheck.setChecked(True) + self.onlyUncaughtCheck.setObjectName("onlyUncaughtCheck") + self.gridLayout_2.addWidget(self.onlyUncaughtCheck, 0, 4, 1, 1) + self.exceptionStackList = QtWidgets.QListWidget(self.exceptionGroup) + self.exceptionStackList.setAlternatingRowColors(True) + self.exceptionStackList.setObjectName("exceptionStackList") + self.gridLayout_2.addWidget(self.exceptionStackList, 2, 0, 1, 7) + self.runSelectedFrameCheck = QtWidgets.QCheckBox(self.exceptionGroup) + self.runSelectedFrameCheck.setChecked(True) + self.runSelectedFrameCheck.setObjectName("runSelectedFrameCheck") + self.gridLayout_2.addWidget(self.runSelectedFrameCheck, 3, 0, 1, 7) + self.exceptionInfoLabel = QtWidgets.QLabel(self.exceptionGroup) + self.exceptionInfoLabel.setObjectName("exceptionInfoLabel") + self.gridLayout_2.addWidget(self.exceptionInfoLabel, 1, 0, 1, 7) + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.gridLayout_2.addItem(spacerItem, 0, 5, 1, 1) + self.label = QtWidgets.QLabel(self.exceptionGroup) + self.label.setObjectName("label") + self.gridLayout_2.addWidget(self.label, 0, 2, 1, 1) + self.filterText = QtWidgets.QLineEdit(self.exceptionGroup) + self.filterText.setObjectName("filterText") + self.gridLayout_2.addWidget(self.filterText, 0, 3, 1, 1) + self.gridLayout.addWidget(self.splitter, 0, 0, 1, 1) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Console", None, -1)) + self.historyBtn.setText(QtWidgets.QApplication.translate("Form", "History..", None, -1)) + self.exceptionBtn.setText(QtWidgets.QApplication.translate("Form", "Exceptions..", None, -1)) + self.exceptionGroup.setTitle(QtWidgets.QApplication.translate("Form", "Exception Handling", None, -1)) + self.clearExceptionBtn.setText(QtWidgets.QApplication.translate("Form", "Clear Exception", None, -1)) + self.catchAllExceptionsBtn.setText(QtWidgets.QApplication.translate("Form", "Show All Exceptions", None, -1)) + self.catchNextExceptionBtn.setText(QtWidgets.QApplication.translate("Form", "Show Next Exception", None, -1)) + self.onlyUncaughtCheck.setText(QtWidgets.QApplication.translate("Form", "Only Uncaught Exceptions", None, -1)) + self.runSelectedFrameCheck.setText(QtWidgets.QApplication.translate("Form", "Run commands in selected stack frame", None, -1)) + self.exceptionInfoLabel.setText(QtWidgets.QApplication.translate("Form", "Exception Info", None, -1)) + self.label.setText(QtWidgets.QApplication.translate("Form", "Filter (regex):", None, -1)) + +from .CmdInput import CmdInput diff --git a/pyqtgraph/exporters/ImageExporter.py b/pyqtgraph/exporters/ImageExporter.py index ffa59091..a43a3d88 100644 --- a/pyqtgraph/exporters/ImageExporter.py +++ b/pyqtgraph/exporters/ImageExporter.py @@ -1,6 +1,6 @@ from .Exporter import Exporter from ..parametertree import Parameter -from ..Qt import QtGui, QtCore, QtSvg, USE_PYSIDE +from ..Qt import QtGui, QtCore, QtSvg, QT_LIB from .. import functions as fn import numpy as np @@ -47,7 +47,7 @@ class ImageExporter(Exporter): def export(self, fileName=None, toBytes=False, copy=False): if fileName is None and not toBytes and not copy: - if USE_PYSIDE: + if QT_LIB in ['PySide', 'PySide2']: filter = ["*."+str(f) for f in QtGui.QImageWriter.supportedImageFormats()] else: filter = ["*."+bytes(f).decode('utf-8') for f in QtGui.QImageWriter.supportedImageFormats()] diff --git a/pyqtgraph/exporters/SVGExporter.py b/pyqtgraph/exporters/SVGExporter.py index ce2a90c0..b1569b74 100644 --- a/pyqtgraph/exporters/SVGExporter.py +++ b/pyqtgraph/exporters/SVGExporter.py @@ -1,7 +1,7 @@ from .Exporter import Exporter from ..python2_3 import asUnicode from ..parametertree import Parameter -from ..Qt import QtGui, QtCore, QtSvg, USE_PYSIDE +from ..Qt import QtGui, QtCore, QtSvg, QT_LIB from .. import debug from .. import functions as fn import re @@ -188,7 +188,7 @@ def _generateItemSvg(item, nodes=None, root=None, options={}): #if hasattr(item, 'setExportMode'): #item.setExportMode(False) - if USE_PYSIDE: + if QT_LIB in ['PySide', 'PySide2']: xmlStr = str(arr) else: xmlStr = bytes(arr).decode('utf-8') diff --git a/pyqtgraph/flowchart/Flowchart.py b/pyqtgraph/flowchart/Flowchart.py index cbfd084e..4edea91b 100644 --- a/pyqtgraph/flowchart/Flowchart.py +++ b/pyqtgraph/flowchart/Flowchart.py @@ -1,15 +1,18 @@ # -*- coding: utf-8 -*- -from ..Qt import QtCore, QtGui, USE_PYSIDE, USE_PYQT5 +from ..Qt import QtCore, QtGui, QT_LIB from .Node import * from ..pgcollections import OrderedDict from ..widgets.TreeWidget import * from .. import FileDialog, DataTreeWidget ## pyside and pyqt use incompatible ui files. -if USE_PYSIDE: +if QT_LIB == 'PySide': from . import FlowchartTemplate_pyside as FlowchartTemplate from . import FlowchartCtrlTemplate_pyside as FlowchartCtrlTemplate -elif USE_PYQT5: +elif QT_LIB == 'PySide2': + from . import FlowchartTemplate_pyside2 as FlowchartTemplate + from . import FlowchartCtrlTemplate_pyside2 as FlowchartCtrlTemplate +elif QT_LIB == 'PyQt5': from . import FlowchartTemplate_pyqt5 as FlowchartTemplate from . import FlowchartCtrlTemplate_pyqt5 as FlowchartCtrlTemplate else: @@ -619,7 +622,7 @@ class FlowchartCtrlWidget(QtGui.QWidget): self.cwWin.resize(1000,800) h = self.ui.ctrlList.header() - if not USE_PYQT5: + if QT_LIB in ['PyQt4', 'PySide']: h.setResizeMode(0, h.Stretch) else: h.setSectionResizeMode(0, h.Stretch) diff --git a/pyqtgraph/flowchart/FlowchartCtrlTemplate_pyside2.py b/pyqtgraph/flowchart/FlowchartCtrlTemplate_pyside2.py new file mode 100644 index 00000000..2e7a7a0b --- /dev/null +++ b/pyqtgraph/flowchart/FlowchartCtrlTemplate_pyside2.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'FlowchartCtrlTemplate.ui' +# +# Created: Sun Sep 18 19:16:46 2016 +# by: pyside2-uic running on PySide2 2.0.0~alpha0 +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore, QtGui, QtWidgets + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(217, 499) + self.gridLayout = QtWidgets.QGridLayout(Form) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setVerticalSpacing(0) + self.gridLayout.setObjectName("gridLayout") + self.loadBtn = QtWidgets.QPushButton(Form) + self.loadBtn.setObjectName("loadBtn") + self.gridLayout.addWidget(self.loadBtn, 1, 0, 1, 1) + self.saveBtn = FeedbackButton(Form) + self.saveBtn.setObjectName("saveBtn") + self.gridLayout.addWidget(self.saveBtn, 1, 1, 1, 2) + self.saveAsBtn = FeedbackButton(Form) + self.saveAsBtn.setObjectName("saveAsBtn") + self.gridLayout.addWidget(self.saveAsBtn, 1, 3, 1, 1) + self.reloadBtn = FeedbackButton(Form) + self.reloadBtn.setCheckable(False) + self.reloadBtn.setFlat(False) + self.reloadBtn.setObjectName("reloadBtn") + self.gridLayout.addWidget(self.reloadBtn, 4, 0, 1, 2) + self.showChartBtn = QtWidgets.QPushButton(Form) + self.showChartBtn.setCheckable(True) + self.showChartBtn.setObjectName("showChartBtn") + self.gridLayout.addWidget(self.showChartBtn, 4, 2, 1, 2) + self.ctrlList = TreeWidget(Form) + self.ctrlList.setObjectName("ctrlList") + self.ctrlList.headerItem().setText(0, "1") + self.ctrlList.header().setVisible(False) + self.ctrlList.header().setStretchLastSection(False) + self.gridLayout.addWidget(self.ctrlList, 3, 0, 1, 4) + self.fileNameLabel = QtWidgets.QLabel(Form) + font = QtGui.QFont() + font.setWeight(75) + font.setBold(True) + self.fileNameLabel.setFont(font) + self.fileNameLabel.setText("") + self.fileNameLabel.setAlignment(QtCore.Qt.AlignCenter) + self.fileNameLabel.setObjectName("fileNameLabel") + self.gridLayout.addWidget(self.fileNameLabel, 0, 1, 1, 1) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1)) + self.loadBtn.setText(QtWidgets.QApplication.translate("Form", "Load..", None, -1)) + self.saveBtn.setText(QtWidgets.QApplication.translate("Form", "Save", None, -1)) + self.saveAsBtn.setText(QtWidgets.QApplication.translate("Form", "As..", None, -1)) + self.reloadBtn.setText(QtWidgets.QApplication.translate("Form", "Reload Libs", None, -1)) + self.showChartBtn.setText(QtWidgets.QApplication.translate("Form", "Flowchart", None, -1)) + +from ..widgets.FeedbackButton import FeedbackButton +from ..widgets.TreeWidget import TreeWidget diff --git a/pyqtgraph/flowchart/FlowchartTemplate_pyside2.py b/pyqtgraph/flowchart/FlowchartTemplate_pyside2.py new file mode 100644 index 00000000..2bca5f82 --- /dev/null +++ b/pyqtgraph/flowchart/FlowchartTemplate_pyside2.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'FlowchartTemplate.ui' +# +# Created: Sun Sep 18 19:16:03 2016 +# by: pyside2-uic running on PySide2 2.0.0~alpha0 +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore, QtGui, QtWidgets + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(529, 329) + self.selInfoWidget = QtWidgets.QWidget(Form) + self.selInfoWidget.setGeometry(QtCore.QRect(260, 10, 264, 222)) + self.selInfoWidget.setObjectName("selInfoWidget") + self.gridLayout = QtWidgets.QGridLayout(self.selInfoWidget) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.selDescLabel = QtWidgets.QLabel(self.selInfoWidget) + self.selDescLabel.setText("") + self.selDescLabel.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) + self.selDescLabel.setWordWrap(True) + self.selDescLabel.setObjectName("selDescLabel") + self.gridLayout.addWidget(self.selDescLabel, 0, 0, 1, 1) + self.selNameLabel = QtWidgets.QLabel(self.selInfoWidget) + font = QtGui.QFont() + font.setWeight(75) + font.setBold(True) + self.selNameLabel.setFont(font) + self.selNameLabel.setText("") + self.selNameLabel.setObjectName("selNameLabel") + self.gridLayout.addWidget(self.selNameLabel, 0, 1, 1, 1) + self.selectedTree = DataTreeWidget(self.selInfoWidget) + self.selectedTree.setObjectName("selectedTree") + self.selectedTree.headerItem().setText(0, "1") + self.gridLayout.addWidget(self.selectedTree, 1, 0, 1, 2) + self.hoverText = QtWidgets.QTextEdit(Form) + self.hoverText.setGeometry(QtCore.QRect(0, 240, 521, 81)) + self.hoverText.setObjectName("hoverText") + self.view = FlowchartGraphicsView(Form) + self.view.setGeometry(QtCore.QRect(0, 0, 256, 192)) + self.view.setObjectName("view") + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1)) + +from ..flowchart.FlowchartGraphicsView import FlowchartGraphicsView +from ..widgets.DataTreeWidget import DataTreeWidget diff --git a/pyqtgraph/functions.py b/pyqtgraph/functions.py index 8857c052..fe3f9910 100644 --- a/pyqtgraph/functions.py +++ b/pyqtgraph/functions.py @@ -12,7 +12,7 @@ import decimal, re import ctypes import sys, struct from .python2_3 import asUnicode, basestring -from .Qt import QtGui, QtCore, USE_PYSIDE +from .Qt import QtGui, QtCore, QT_LIB from . import getConfigOption, setConfigOptions from . import debug, reload from .reload import getPreviousVersion @@ -1220,7 +1220,7 @@ def makeQImage(imgData, alpha=None, copy=True, transpose=True): if copy is True and copied is False: imgData = imgData.copy() - if USE_PYSIDE: + if QT_LIB in ['PySide', 'PySide2']: ch = ctypes.c_char.from_buffer(imgData, 0) # Bug in PySide + Python 3 causes refcount for image data to be improperly @@ -1278,7 +1278,7 @@ def imageToArray(img, copy=False, transpose=True): """ fmt = img.format() ptr = img.bits() - if USE_PYSIDE: + if QT_LIB in ['PySide', 'PySide2']: arr = np.frombuffer(ptr, dtype=np.ubyte) else: ptr.setsize(img.byteCount()) diff --git a/pyqtgraph/graphicsItems/FillBetweenItem.py b/pyqtgraph/graphicsItems/FillBetweenItem.py index 0efb11dd..b16be853 100644 --- a/pyqtgraph/graphicsItems/FillBetweenItem.py +++ b/pyqtgraph/graphicsItems/FillBetweenItem.py @@ -1,4 +1,4 @@ -from ..Qt import QtGui, USE_PYQT5, USE_PYQT4, USE_PYSIDE +from ..Qt import QtGui from .. import functions as fn from .PlotDataItem import PlotDataItem from .PlotCurveItem import PlotCurveItem diff --git a/pyqtgraph/graphicsItems/GraphicsObject.py b/pyqtgraph/graphicsItems/GraphicsObject.py index 015a78c6..2493fe76 100644 --- a/pyqtgraph/graphicsItems/GraphicsObject.py +++ b/pyqtgraph/graphicsItems/GraphicsObject.py @@ -1,5 +1,5 @@ -from ..Qt import QtGui, QtCore, USE_PYSIDE -if not USE_PYSIDE: +from ..Qt import QtGui, QtCore, QT_LIB +if QT_LIB in ['PyQt4', 'PyQt5']: import sip from .GraphicsItem import GraphicsItem @@ -33,7 +33,7 @@ class GraphicsObject(GraphicsItem, QtGui.QGraphicsObject): ## workaround for pyqt bug: ## http://www.riverbankcomputing.com/pipermail/pyqt/2012-August/031818.html - if not USE_PYSIDE and change == self.ItemParentChange and isinstance(ret, QtGui.QGraphicsItem): + if QT_LIB in ['PyQt4', 'PyQt5'] and change == self.ItemParentChange and isinstance(ret, QtGui.QGraphicsItem): ret = sip.cast(ret, QtGui.QGraphicsItem) return ret diff --git a/pyqtgraph/graphicsItems/PlotItem/PlotItem.py b/pyqtgraph/graphicsItems/PlotItem/PlotItem.py index 7321702c..506122a7 100644 --- a/pyqtgraph/graphicsItems/PlotItem/PlotItem.py +++ b/pyqtgraph/graphicsItems/PlotItem/PlotItem.py @@ -41,6 +41,8 @@ elif QT_LIB == 'PySide': from .plotConfigTemplate_pyside import * elif QT_LIB == 'PyQt5': from .plotConfigTemplate_pyqt5 import * +elif QT_LIB == 'PySide2': + from .plotConfigTemplate_pyside2 import * __all__ = ['PlotItem'] diff --git a/pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate_pyside2.py b/pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate_pyside2.py new file mode 100644 index 00000000..d801f298 --- /dev/null +++ b/pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate_pyside2.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file './pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate.ui' +# +# Created: Wed Mar 26 15:09:28 2014 +# by: PyQt5 UI code generator 5.0.1 +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore, QtGui, QtWidgets + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(481, 840) + self.averageGroup = QtWidgets.QGroupBox(Form) + self.averageGroup.setGeometry(QtCore.QRect(0, 640, 242, 182)) + self.averageGroup.setCheckable(True) + self.averageGroup.setChecked(False) + self.averageGroup.setObjectName("averageGroup") + self.gridLayout_5 = QtWidgets.QGridLayout(self.averageGroup) + self.gridLayout_5.setContentsMargins(0, 0, 0, 0) + self.gridLayout_5.setSpacing(0) + self.gridLayout_5.setObjectName("gridLayout_5") + self.avgParamList = QtWidgets.QListWidget(self.averageGroup) + self.avgParamList.setObjectName("avgParamList") + self.gridLayout_5.addWidget(self.avgParamList, 0, 0, 1, 1) + self.decimateGroup = QtWidgets.QFrame(Form) + self.decimateGroup.setGeometry(QtCore.QRect(10, 140, 191, 171)) + self.decimateGroup.setObjectName("decimateGroup") + self.gridLayout_4 = QtWidgets.QGridLayout(self.decimateGroup) + self.gridLayout_4.setContentsMargins(0, 0, 0, 0) + self.gridLayout_4.setSpacing(0) + self.gridLayout_4.setObjectName("gridLayout_4") + self.clipToViewCheck = QtWidgets.QCheckBox(self.decimateGroup) + self.clipToViewCheck.setObjectName("clipToViewCheck") + self.gridLayout_4.addWidget(self.clipToViewCheck, 7, 0, 1, 3) + self.maxTracesCheck = QtWidgets.QCheckBox(self.decimateGroup) + self.maxTracesCheck.setObjectName("maxTracesCheck") + self.gridLayout_4.addWidget(self.maxTracesCheck, 8, 0, 1, 2) + self.downsampleCheck = QtWidgets.QCheckBox(self.decimateGroup) + self.downsampleCheck.setObjectName("downsampleCheck") + self.gridLayout_4.addWidget(self.downsampleCheck, 0, 0, 1, 3) + self.peakRadio = QtWidgets.QRadioButton(self.decimateGroup) + self.peakRadio.setChecked(True) + self.peakRadio.setObjectName("peakRadio") + self.gridLayout_4.addWidget(self.peakRadio, 6, 1, 1, 2) + self.maxTracesSpin = QtWidgets.QSpinBox(self.decimateGroup) + self.maxTracesSpin.setObjectName("maxTracesSpin") + self.gridLayout_4.addWidget(self.maxTracesSpin, 8, 2, 1, 1) + self.forgetTracesCheck = QtWidgets.QCheckBox(self.decimateGroup) + self.forgetTracesCheck.setObjectName("forgetTracesCheck") + self.gridLayout_4.addWidget(self.forgetTracesCheck, 9, 0, 1, 3) + self.meanRadio = QtWidgets.QRadioButton(self.decimateGroup) + self.meanRadio.setObjectName("meanRadio") + self.gridLayout_4.addWidget(self.meanRadio, 3, 1, 1, 2) + self.subsampleRadio = QtWidgets.QRadioButton(self.decimateGroup) + self.subsampleRadio.setObjectName("subsampleRadio") + self.gridLayout_4.addWidget(self.subsampleRadio, 2, 1, 1, 2) + self.autoDownsampleCheck = QtWidgets.QCheckBox(self.decimateGroup) + self.autoDownsampleCheck.setChecked(True) + self.autoDownsampleCheck.setObjectName("autoDownsampleCheck") + self.gridLayout_4.addWidget(self.autoDownsampleCheck, 1, 2, 1, 1) + spacerItem = QtWidgets.QSpacerItem(30, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum) + self.gridLayout_4.addItem(spacerItem, 2, 0, 1, 1) + self.downsampleSpin = QtWidgets.QSpinBox(self.decimateGroup) + self.downsampleSpin.setMinimum(1) + self.downsampleSpin.setMaximum(100000) + self.downsampleSpin.setProperty("value", 1) + self.downsampleSpin.setObjectName("downsampleSpin") + self.gridLayout_4.addWidget(self.downsampleSpin, 1, 1, 1, 1) + self.transformGroup = QtWidgets.QFrame(Form) + self.transformGroup.setGeometry(QtCore.QRect(0, 0, 154, 79)) + self.transformGroup.setObjectName("transformGroup") + self.gridLayout = QtWidgets.QGridLayout(self.transformGroup) + self.gridLayout.setObjectName("gridLayout") + self.fftCheck = QtWidgets.QCheckBox(self.transformGroup) + self.fftCheck.setObjectName("fftCheck") + self.gridLayout.addWidget(self.fftCheck, 0, 0, 1, 1) + self.logXCheck = QtWidgets.QCheckBox(self.transformGroup) + self.logXCheck.setObjectName("logXCheck") + self.gridLayout.addWidget(self.logXCheck, 1, 0, 1, 1) + self.logYCheck = QtWidgets.QCheckBox(self.transformGroup) + self.logYCheck.setObjectName("logYCheck") + self.gridLayout.addWidget(self.logYCheck, 2, 0, 1, 1) + self.pointsGroup = QtWidgets.QGroupBox(Form) + self.pointsGroup.setGeometry(QtCore.QRect(10, 550, 234, 58)) + self.pointsGroup.setCheckable(True) + self.pointsGroup.setObjectName("pointsGroup") + self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.pointsGroup) + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.autoPointsCheck = QtWidgets.QCheckBox(self.pointsGroup) + self.autoPointsCheck.setChecked(True) + self.autoPointsCheck.setObjectName("autoPointsCheck") + self.verticalLayout_5.addWidget(self.autoPointsCheck) + self.gridGroup = QtWidgets.QFrame(Form) + self.gridGroup.setGeometry(QtCore.QRect(10, 460, 221, 81)) + self.gridGroup.setObjectName("gridGroup") + self.gridLayout_2 = QtWidgets.QGridLayout(self.gridGroup) + self.gridLayout_2.setObjectName("gridLayout_2") + self.xGridCheck = QtWidgets.QCheckBox(self.gridGroup) + self.xGridCheck.setObjectName("xGridCheck") + self.gridLayout_2.addWidget(self.xGridCheck, 0, 0, 1, 2) + self.yGridCheck = QtWidgets.QCheckBox(self.gridGroup) + self.yGridCheck.setObjectName("yGridCheck") + self.gridLayout_2.addWidget(self.yGridCheck, 1, 0, 1, 2) + self.gridAlphaSlider = QtWidgets.QSlider(self.gridGroup) + self.gridAlphaSlider.setMaximum(255) + self.gridAlphaSlider.setProperty("value", 128) + self.gridAlphaSlider.setOrientation(QtCore.Qt.Horizontal) + self.gridAlphaSlider.setObjectName("gridAlphaSlider") + self.gridLayout_2.addWidget(self.gridAlphaSlider, 2, 1, 1, 1) + self.label = QtWidgets.QLabel(self.gridGroup) + self.label.setObjectName("label") + self.gridLayout_2.addWidget(self.label, 2, 0, 1, 1) + self.alphaGroup = QtWidgets.QGroupBox(Form) + self.alphaGroup.setGeometry(QtCore.QRect(10, 390, 234, 60)) + self.alphaGroup.setCheckable(True) + self.alphaGroup.setObjectName("alphaGroup") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.alphaGroup) + self.horizontalLayout.setObjectName("horizontalLayout") + self.autoAlphaCheck = QtWidgets.QCheckBox(self.alphaGroup) + self.autoAlphaCheck.setChecked(False) + self.autoAlphaCheck.setObjectName("autoAlphaCheck") + self.horizontalLayout.addWidget(self.autoAlphaCheck) + self.alphaSlider = QtWidgets.QSlider(self.alphaGroup) + self.alphaSlider.setMaximum(1000) + self.alphaSlider.setProperty("value", 1000) + self.alphaSlider.setOrientation(QtCore.Qt.Horizontal) + self.alphaSlider.setObjectName("alphaSlider") + self.horizontalLayout.addWidget(self.alphaSlider) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + _translate = QtCore.QCoreApplication.translate + Form.setWindowTitle(_translate("Form", "Form")) + self.averageGroup.setToolTip(_translate("Form", "Display averages of the curves displayed in this plot. The parameter list allows you to choose parameters to average over (if any are available).")) + self.averageGroup.setTitle(_translate("Form", "Average")) + self.clipToViewCheck.setToolTip(_translate("Form", "Plot only the portion of each curve that is visible. This assumes X values are uniformly spaced.")) + self.clipToViewCheck.setText(_translate("Form", "Clip to View")) + self.maxTracesCheck.setToolTip(_translate("Form", "If multiple curves are displayed in this plot, check this box to limit the number of traces that are displayed.")) + self.maxTracesCheck.setText(_translate("Form", "Max Traces:")) + self.downsampleCheck.setText(_translate("Form", "Downsample")) + self.peakRadio.setToolTip(_translate("Form", "Downsample by drawing a saw wave that follows the min and max of the original data. This method produces the best visual representation of the data but is slower.")) + self.peakRadio.setText(_translate("Form", "Peak")) + self.maxTracesSpin.setToolTip(_translate("Form", "If multiple curves are displayed in this plot, check \"Max Traces\" and set this value to limit the number of traces that are displayed.")) + self.forgetTracesCheck.setToolTip(_translate("Form", "If MaxTraces is checked, remove curves from memory after they are hidden (saves memory, but traces can not be un-hidden).")) + self.forgetTracesCheck.setText(_translate("Form", "Forget hidden traces")) + self.meanRadio.setToolTip(_translate("Form", "Downsample by taking the mean of N samples.")) + self.meanRadio.setText(_translate("Form", "Mean")) + self.subsampleRadio.setToolTip(_translate("Form", "Downsample by taking the first of N samples. This method is fastest and least accurate.")) + self.subsampleRadio.setText(_translate("Form", "Subsample")) + self.autoDownsampleCheck.setToolTip(_translate("Form", "Automatically downsample data based on the visible range. This assumes X values are uniformly spaced.")) + self.autoDownsampleCheck.setText(_translate("Form", "Auto")) + self.downsampleSpin.setToolTip(_translate("Form", "Downsample data before plotting. (plot every Nth sample)")) + self.downsampleSpin.setSuffix(_translate("Form", "x")) + self.fftCheck.setText(_translate("Form", "Power Spectrum (FFT)")) + self.logXCheck.setText(_translate("Form", "Log X")) + self.logYCheck.setText(_translate("Form", "Log Y")) + self.pointsGroup.setTitle(_translate("Form", "Points")) + self.autoPointsCheck.setText(_translate("Form", "Auto")) + self.xGridCheck.setText(_translate("Form", "Show X Grid")) + self.yGridCheck.setText(_translate("Form", "Show Y Grid")) + self.label.setText(_translate("Form", "Opacity")) + self.alphaGroup.setTitle(_translate("Form", "Alpha")) + self.autoAlphaCheck.setText(_translate("Form", "Auto")) + diff --git a/pyqtgraph/graphicsItems/ScatterPlotItem.py b/pyqtgraph/graphicsItems/ScatterPlotItem.py index 9759e3ae..89bb5b98 100644 --- a/pyqtgraph/graphicsItems/ScatterPlotItem.py +++ b/pyqtgraph/graphicsItems/ScatterPlotItem.py @@ -5,7 +5,7 @@ except ImportError: imap = map import numpy as np import weakref -from ..Qt import QtGui, QtCore, USE_PYSIDE, USE_PYQT5 +from ..Qt import QtGui, QtCore, QT_LIB from ..Point import Point from .. import functions as fn from .GraphicsItem import GraphicsItem @@ -769,10 +769,10 @@ class ScatterPlotItem(GraphicsObject): self.data['targetRect'][updateMask] = list(imap(QtCore.QRectF, updatePts[0,:], updatePts[1,:], width, width)) data = self.data[viewMask] - if USE_PYSIDE or USE_PYQT5: - list(imap(p.drawPixmap, data['targetRect'], repeat(atlas), data['sourceRect'])) - else: + if QT_LIB == 'PyQt4': p.drawPixmapFragments(data['targetRect'].tolist(), data['sourceRect'].tolist(), atlas) + else: + list(imap(p.drawPixmap, data['targetRect'], repeat(atlas), data['sourceRect'])) else: # render each symbol individually p.setRenderHint(p.Antialiasing, aa) diff --git a/pyqtgraph/graphicsItems/UIGraphicsItem.py b/pyqtgraph/graphicsItems/UIGraphicsItem.py index 6f756334..2074a2e9 100644 --- a/pyqtgraph/graphicsItems/UIGraphicsItem.py +++ b/pyqtgraph/graphicsItems/UIGraphicsItem.py @@ -1,7 +1,7 @@ -from ..Qt import QtGui, QtCore, USE_PYSIDE +from ..Qt import QtGui, QtCore, QT_LIB import weakref from .GraphicsObject import GraphicsObject -if not USE_PYSIDE: +if QT_LIB in ['PyQt4', 'PyQt5']: import sip __all__ = ['UIGraphicsItem'] @@ -49,7 +49,7 @@ class UIGraphicsItem(GraphicsObject): ## workaround for pyqt bug: ## http://www.riverbankcomputing.com/pipermail/pyqt/2012-August/031818.html - if not USE_PYSIDE and change == self.ItemParentChange and isinstance(ret, QtGui.QGraphicsItem): + if QT_LIB in ['PyQt4', 'PyQt5'] and change == self.ItemParentChange and isinstance(ret, QtGui.QGraphicsItem): ret = sip.cast(ret, QtGui.QGraphicsItem) if change == self.ItemScenePositionHasChanged: diff --git a/pyqtgraph/graphicsItems/ViewBox/ViewBoxMenu.py b/pyqtgraph/graphicsItems/ViewBox/ViewBoxMenu.py index 10392d7e..74a861d0 100644 --- a/pyqtgraph/graphicsItems/ViewBox/ViewBoxMenu.py +++ b/pyqtgraph/graphicsItems/ViewBox/ViewBoxMenu.py @@ -8,7 +8,9 @@ elif QT_LIB == 'PySide': from .axisCtrlTemplate_pyside import Ui_Form as AxisCtrlTemplate elif QT_LIB == 'PyQt5': from .axisCtrlTemplate_pyqt5 import Ui_Form as AxisCtrlTemplate - +elif QT_LIB == 'PySide2': + from .axisCtrlTemplate_pyside2 import Ui_Form as AxisCtrlTemplate + import weakref class ViewBoxMenu(QtGui.QMenu): diff --git a/pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate_pyside2.py b/pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate_pyside2.py new file mode 100644 index 00000000..401c52fc --- /dev/null +++ b/pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate_pyside2.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file './pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate.ui' +# +# Created: Wed Mar 26 15:09:28 2014 +# by: PyQt5 UI code generator 5.0.1 +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore, QtGui, QtWidgets + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(186, 154) + Form.setMaximumSize(QtCore.QSize(200, 16777215)) + self.gridLayout = QtWidgets.QGridLayout(Form) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setSpacing(0) + self.gridLayout.setObjectName("gridLayout") + self.label = QtWidgets.QLabel(Form) + self.label.setObjectName("label") + self.gridLayout.addWidget(self.label, 7, 0, 1, 2) + self.linkCombo = QtWidgets.QComboBox(Form) + self.linkCombo.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents) + self.linkCombo.setObjectName("linkCombo") + self.gridLayout.addWidget(self.linkCombo, 7, 2, 1, 2) + self.autoPercentSpin = QtWidgets.QSpinBox(Form) + self.autoPercentSpin.setEnabled(True) + self.autoPercentSpin.setMinimum(1) + self.autoPercentSpin.setMaximum(100) + self.autoPercentSpin.setSingleStep(1) + self.autoPercentSpin.setProperty("value", 100) + self.autoPercentSpin.setObjectName("autoPercentSpin") + self.gridLayout.addWidget(self.autoPercentSpin, 2, 2, 1, 2) + self.autoRadio = QtWidgets.QRadioButton(Form) + self.autoRadio.setChecked(True) + self.autoRadio.setObjectName("autoRadio") + self.gridLayout.addWidget(self.autoRadio, 2, 0, 1, 2) + self.manualRadio = QtWidgets.QRadioButton(Form) + self.manualRadio.setObjectName("manualRadio") + self.gridLayout.addWidget(self.manualRadio, 1, 0, 1, 2) + self.minText = QtWidgets.QLineEdit(Form) + self.minText.setObjectName("minText") + self.gridLayout.addWidget(self.minText, 1, 2, 1, 1) + self.maxText = QtWidgets.QLineEdit(Form) + self.maxText.setObjectName("maxText") + self.gridLayout.addWidget(self.maxText, 1, 3, 1, 1) + self.invertCheck = QtWidgets.QCheckBox(Form) + self.invertCheck.setObjectName("invertCheck") + self.gridLayout.addWidget(self.invertCheck, 5, 0, 1, 4) + self.mouseCheck = QtWidgets.QCheckBox(Form) + self.mouseCheck.setChecked(True) + self.mouseCheck.setObjectName("mouseCheck") + self.gridLayout.addWidget(self.mouseCheck, 6, 0, 1, 4) + self.visibleOnlyCheck = QtWidgets.QCheckBox(Form) + self.visibleOnlyCheck.setObjectName("visibleOnlyCheck") + self.gridLayout.addWidget(self.visibleOnlyCheck, 3, 2, 1, 2) + self.autoPanCheck = QtWidgets.QCheckBox(Form) + self.autoPanCheck.setObjectName("autoPanCheck") + self.gridLayout.addWidget(self.autoPanCheck, 4, 2, 1, 2) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + _translate = QtCore.QCoreApplication.translate + Form.setWindowTitle(_translate("Form", "Form")) + self.label.setText(_translate("Form", "Link Axis:")) + self.linkCombo.setToolTip(_translate("Form", "

Links this axis with another view. When linked, both views will display the same data range.

")) + self.autoPercentSpin.setToolTip(_translate("Form", "

Percent of data to be visible when auto-scaling. It may be useful to decrease this value for data with spiky noise.

")) + self.autoPercentSpin.setSuffix(_translate("Form", "%")) + self.autoRadio.setToolTip(_translate("Form", "

Automatically resize this axis whenever the displayed data is changed.

")) + self.autoRadio.setText(_translate("Form", "Auto")) + self.manualRadio.setToolTip(_translate("Form", "

Set the range for this axis manually. This disables automatic scaling.

")) + self.manualRadio.setText(_translate("Form", "Manual")) + self.minText.setToolTip(_translate("Form", "

Minimum value to display for this axis.

")) + self.minText.setText(_translate("Form", "0")) + self.maxText.setToolTip(_translate("Form", "

Maximum value to display for this axis.

")) + self.maxText.setText(_translate("Form", "0")) + self.invertCheck.setToolTip(_translate("Form", "

Inverts the display of this axis. (+y points downward instead of upward)

")) + self.invertCheck.setText(_translate("Form", "Invert Axis")) + self.mouseCheck.setToolTip(_translate("Form", "

Enables mouse interaction (panning, scaling) for this axis.

")) + self.mouseCheck.setText(_translate("Form", "Mouse Enabled")) + self.visibleOnlyCheck.setToolTip(_translate("Form", "

When checked, the axis will only auto-scale to data that is visible along the orthogonal axis.

")) + self.visibleOnlyCheck.setText(_translate("Form", "Visible Data Only")) + self.autoPanCheck.setToolTip(_translate("Form", "

When checked, the axis will automatically pan to center on the current data, but the scale along this axis will not change.

")) + self.autoPanCheck.setText(_translate("Form", "Auto Pan Only")) + diff --git a/pyqtgraph/graphicsItems/tests/test_ImageItem.py b/pyqtgraph/graphicsItems/tests/test_ImageItem.py index 4f310bc3..ca197c6e 100644 --- a/pyqtgraph/graphicsItems/tests/test_ImageItem.py +++ b/pyqtgraph/graphicsItems/tests/test_ImageItem.py @@ -134,7 +134,7 @@ def test_ImageItem_axisorder(): pg.setConfigOptions(imageAxisOrder=origMode) -@pytest.mark.skipif(pg.Qt.USE_PYSIDE, reason="pyside does not have qWait") +@pytest.mark.skipif(pg.Qt.QT_LIB=='PySide', reason="pyside does not have qWait") def test_dividebyzero(): import pyqtgraph as pg im = pg.image(pg.np.random.normal(size=(100,100))) diff --git a/pyqtgraph/imageview/ImageView.py b/pyqtgraph/imageview/ImageView.py index 1d38a6c3..40a3987a 100644 --- a/pyqtgraph/imageview/ImageView.py +++ b/pyqtgraph/imageview/ImageView.py @@ -15,9 +15,13 @@ Widget used for displaying 2D or 3D data. Features: import os, sys import numpy as np -from ..Qt import QtCore, QtGui, USE_PYSIDE -if USE_PYSIDE: +from ..Qt import QtCore, QtGui, QT_LIB +if QT_LIB == 'PySide': from .ImageViewTemplate_pyside import * +elif QT_LIB == 'PySide2': + from .ImageViewTemplate_pyside2 import * +elif QT_LIB == 'PyQt5': + from .ImageViewTemplate_pyqt5 import * else: from .ImageViewTemplate_pyqt import * diff --git a/pyqtgraph/imageview/ImageViewTemplate_pyqt5.py b/pyqtgraph/imageview/ImageViewTemplate_pyqt5.py index 4b4009b6..1d076a9e 100644 --- a/pyqtgraph/imageview/ImageViewTemplate_pyqt5.py +++ b/pyqtgraph/imageview/ImageViewTemplate_pyqt5.py @@ -41,15 +41,15 @@ class Ui_Form(object): self.roiBtn.setCheckable(True) self.roiBtn.setObjectName("roiBtn") self.gridLayout.addWidget(self.roiBtn, 1, 1, 1, 1) - self.normBtn = QtWidgets.QPushButton(self.layoutWidget) + self.menuBtn = QtWidgets.QPushButton(self.layoutWidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(1) - sizePolicy.setHeightForWidth(self.normBtn.sizePolicy().hasHeightForWidth()) - self.normBtn.setSizePolicy(sizePolicy) - self.normBtn.setCheckable(True) - self.normBtn.setObjectName("normBtn") - self.gridLayout.addWidget(self.normBtn, 1, 2, 1, 1) + sizePolicy.setHeightForWidth(self.menuBtn.sizePolicy().hasHeightForWidth()) + self.menuBtn.setSizePolicy(sizePolicy) + self.menuBtn.setCheckable(True) + self.menuBtn.setObjectName("menuBtn") + self.gridLayout.addWidget(self.menuBtn, 1, 2, 1, 1) self.roiPlot = PlotWidget(self.splitter) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -136,7 +136,7 @@ class Ui_Form(object): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Form", "Form")) self.roiBtn.setText(_translate("Form", "ROI")) - self.normBtn.setText(_translate("Form", "Norm")) + self.menuBtn.setText(_translate("Form", "Norm")) self.normGroup.setTitle(_translate("Form", "Normalization")) self.normSubtractRadio.setText(_translate("Form", "Subtract")) self.normDivideRadio.setText(_translate("Form", "Divide")) diff --git a/pyqtgraph/imageview/ImageViewTemplate_pyside2.py b/pyqtgraph/imageview/ImageViewTemplate_pyside2.py new file mode 100644 index 00000000..cfe400c1 --- /dev/null +++ b/pyqtgraph/imageview/ImageViewTemplate_pyside2.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ImageViewTemplate.ui' +# +# Created: Sun Sep 18 19:17:41 2016 +# by: pyside2-uic running on PySide2 2.0.0~alpha0 +# +# WARNING! All changes made in this file will be lost! + +from PySide2 import QtCore, QtGui, QtWidgets + +class Ui_Form(object): + def setupUi(self, Form): + Form.setObjectName("Form") + Form.resize(726, 588) + self.gridLayout_3 = QtWidgets.QGridLayout(Form) + self.gridLayout_3.setContentsMargins(0, 0, 0, 0) + self.gridLayout_3.setSpacing(0) + self.gridLayout_3.setObjectName("gridLayout_3") + self.splitter = QtWidgets.QSplitter(Form) + self.splitter.setOrientation(QtCore.Qt.Vertical) + self.splitter.setObjectName("splitter") + self.layoutWidget = QtWidgets.QWidget(self.splitter) + self.layoutWidget.setObjectName("layoutWidget") + self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget) + self.gridLayout.setSpacing(0) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.graphicsView = GraphicsView(self.layoutWidget) + self.graphicsView.setObjectName("graphicsView") + self.gridLayout.addWidget(self.graphicsView, 0, 0, 2, 1) + self.histogram = HistogramLUTWidget(self.layoutWidget) + self.histogram.setObjectName("histogram") + self.gridLayout.addWidget(self.histogram, 0, 1, 1, 2) + self.roiBtn = QtWidgets.QPushButton(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(1) + sizePolicy.setHeightForWidth(self.roiBtn.sizePolicy().hasHeightForWidth()) + self.roiBtn.setSizePolicy(sizePolicy) + self.roiBtn.setCheckable(True) + self.roiBtn.setObjectName("roiBtn") + self.gridLayout.addWidget(self.roiBtn, 1, 1, 1, 1) + self.menuBtn = QtWidgets.QPushButton(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(1) + sizePolicy.setHeightForWidth(self.menuBtn.sizePolicy().hasHeightForWidth()) + self.menuBtn.setSizePolicy(sizePolicy) + self.menuBtn.setObjectName("menuBtn") + self.gridLayout.addWidget(self.menuBtn, 1, 2, 1, 1) + self.roiPlot = PlotWidget(self.splitter) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.roiPlot.sizePolicy().hasHeightForWidth()) + self.roiPlot.setSizePolicy(sizePolicy) + self.roiPlot.setMinimumSize(QtCore.QSize(0, 40)) + self.roiPlot.setObjectName("roiPlot") + self.gridLayout_3.addWidget(self.splitter, 0, 0, 1, 1) + self.normGroup = QtWidgets.QGroupBox(Form) + self.normGroup.setObjectName("normGroup") + self.gridLayout_2 = QtWidgets.QGridLayout(self.normGroup) + self.gridLayout_2.setContentsMargins(0, 0, 0, 0) + self.gridLayout_2.setSpacing(0) + self.gridLayout_2.setObjectName("gridLayout_2") + self.normSubtractRadio = QtWidgets.QRadioButton(self.normGroup) + self.normSubtractRadio.setObjectName("normSubtractRadio") + self.gridLayout_2.addWidget(self.normSubtractRadio, 0, 2, 1, 1) + self.normDivideRadio = QtWidgets.QRadioButton(self.normGroup) + self.normDivideRadio.setChecked(False) + self.normDivideRadio.setObjectName("normDivideRadio") + self.gridLayout_2.addWidget(self.normDivideRadio, 0, 1, 1, 1) + self.label_5 = QtWidgets.QLabel(self.normGroup) + font = QtGui.QFont() + font.setWeight(75) + font.setBold(True) + self.label_5.setFont(font) + self.label_5.setObjectName("label_5") + self.gridLayout_2.addWidget(self.label_5, 0, 0, 1, 1) + self.label_3 = QtWidgets.QLabel(self.normGroup) + font = QtGui.QFont() + font.setWeight(75) + font.setBold(True) + self.label_3.setFont(font) + self.label_3.setObjectName("label_3") + self.gridLayout_2.addWidget(self.label_3, 1, 0, 1, 1) + self.label_4 = QtWidgets.QLabel(self.normGroup) + font = QtGui.QFont() + font.setWeight(75) + font.setBold(True) + self.label_4.setFont(font) + self.label_4.setObjectName("label_4") + self.gridLayout_2.addWidget(self.label_4, 2, 0, 1, 1) + self.normROICheck = QtWidgets.QCheckBox(self.normGroup) + self.normROICheck.setObjectName("normROICheck") + self.gridLayout_2.addWidget(self.normROICheck, 1, 1, 1, 1) + self.normXBlurSpin = QtWidgets.QDoubleSpinBox(self.normGroup) + self.normXBlurSpin.setObjectName("normXBlurSpin") + self.gridLayout_2.addWidget(self.normXBlurSpin, 2, 2, 1, 1) + self.label_8 = QtWidgets.QLabel(self.normGroup) + self.label_8.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_8.setObjectName("label_8") + self.gridLayout_2.addWidget(self.label_8, 2, 1, 1, 1) + self.label_9 = QtWidgets.QLabel(self.normGroup) + self.label_9.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_9.setObjectName("label_9") + self.gridLayout_2.addWidget(self.label_9, 2, 3, 1, 1) + self.normYBlurSpin = QtWidgets.QDoubleSpinBox(self.normGroup) + self.normYBlurSpin.setObjectName("normYBlurSpin") + self.gridLayout_2.addWidget(self.normYBlurSpin, 2, 4, 1, 1) + self.label_10 = QtWidgets.QLabel(self.normGroup) + self.label_10.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_10.setObjectName("label_10") + self.gridLayout_2.addWidget(self.label_10, 2, 5, 1, 1) + self.normOffRadio = QtWidgets.QRadioButton(self.normGroup) + self.normOffRadio.setChecked(True) + self.normOffRadio.setObjectName("normOffRadio") + self.gridLayout_2.addWidget(self.normOffRadio, 0, 3, 1, 1) + self.normTimeRangeCheck = QtWidgets.QCheckBox(self.normGroup) + self.normTimeRangeCheck.setObjectName("normTimeRangeCheck") + self.gridLayout_2.addWidget(self.normTimeRangeCheck, 1, 3, 1, 1) + self.normFrameCheck = QtWidgets.QCheckBox(self.normGroup) + self.normFrameCheck.setObjectName("normFrameCheck") + self.gridLayout_2.addWidget(self.normFrameCheck, 1, 2, 1, 1) + self.normTBlurSpin = QtWidgets.QDoubleSpinBox(self.normGroup) + self.normTBlurSpin.setObjectName("normTBlurSpin") + self.gridLayout_2.addWidget(self.normTBlurSpin, 2, 6, 1, 1) + self.gridLayout_3.addWidget(self.normGroup, 1, 0, 1, 1) + + self.retranslateUi(Form) + QtCore.QMetaObject.connectSlotsByName(Form) + + def retranslateUi(self, Form): + Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1)) + self.roiBtn.setText(QtWidgets.QApplication.translate("Form", "ROI", None, -1)) + self.menuBtn.setText(QtWidgets.QApplication.translate("Form", "Menu", None, -1)) + self.normGroup.setTitle(QtWidgets.QApplication.translate("Form", "Normalization", None, -1)) + self.normSubtractRadio.setText(QtWidgets.QApplication.translate("Form", "Subtract", None, -1)) + self.normDivideRadio.setText(QtWidgets.QApplication.translate("Form", "Divide", None, -1)) + self.label_5.setText(QtWidgets.QApplication.translate("Form", "Operation:", None, -1)) + self.label_3.setText(QtWidgets.QApplication.translate("Form", "Mean:", None, -1)) + self.label_4.setText(QtWidgets.QApplication.translate("Form", "Blur:", None, -1)) + self.normROICheck.setText(QtWidgets.QApplication.translate("Form", "ROI", None, -1)) + self.label_8.setText(QtWidgets.QApplication.translate("Form", "X", None, -1)) + self.label_9.setText(QtWidgets.QApplication.translate("Form", "Y", None, -1)) + self.label_10.setText(QtWidgets.QApplication.translate("Form", "T", None, -1)) + self.normOffRadio.setText(QtWidgets.QApplication.translate("Form", "Off", None, -1)) + self.normTimeRangeCheck.setText(QtWidgets.QApplication.translate("Form", "Time range", None, -1)) + self.normFrameCheck.setText(QtWidgets.QApplication.translate("Form", "Frame", None, -1)) + +from ..widgets.HistogramLUTWidget import HistogramLUTWidget +from ..widgets.PlotWidget import PlotWidget +from ..widgets.GraphicsView import GraphicsView diff --git a/pyqtgraph/multiprocess/bootstrap.py b/pyqtgraph/multiprocess/bootstrap.py index a8a03d41..b9868367 100644 --- a/pyqtgraph/multiprocess/bootstrap.py +++ b/pyqtgraph/multiprocess/bootstrap.py @@ -29,9 +29,13 @@ if __name__ == '__main__': for k,v in pyqtapis.items(): sip.setapi(k, v) - if opts.pop('pyside', False): + qt_lib = opts.pop('qt_lib', None) + if qt_lib == 'PySide': import PySide - + elif qt_lib == 'PySide2': + import PySide2 + elif qt_lib == 'PyQt5': + import PyQt5 targetStr = opts.pop('targetStr') try: diff --git a/pyqtgraph/multiprocess/processes.py b/pyqtgraph/multiprocess/processes.py index 4cf2ab70..d841ea40 100644 --- a/pyqtgraph/multiprocess/processes.py +++ b/pyqtgraph/multiprocess/processes.py @@ -6,7 +6,7 @@ except ImportError: import pickle from .remoteproxy import RemoteEventHandler, ClosedError, NoResultError, LocalObjectProxy, ObjectProxy -from ..Qt import USE_PYSIDE +from ..Qt import QT_LIB from ..util import cprint # color printing for debugging @@ -131,7 +131,7 @@ class Process(RemoteEventHandler): ppid=pid, targetStr=targetStr, path=sysPath, - pyside=USE_PYSIDE, + qt_lib=QT_LIB, debug=procDebug, pyqtapis=pyqtapis, ) diff --git a/pyqtgraph/opengl/GLViewWidget.py b/pyqtgraph/opengl/GLViewWidget.py index 540fce7d..17c0833d 100644 --- a/pyqtgraph/opengl/GLViewWidget.py +++ b/pyqtgraph/opengl/GLViewWidget.py @@ -1,4 +1,4 @@ -from ..Qt import QtCore, QtGui, QtOpenGL, USE_PYQT5 +from ..Qt import QtCore, QtGui, QtOpenGL, QT_LIB from OpenGL.GL import * import OpenGL.GL.framebufferobjects as glfbo import numpy as np @@ -342,7 +342,7 @@ class GLViewWidget(QtOpenGL.QGLWidget): def wheelEvent(self, ev): delta = 0 - if not USE_PYQT5: + if QT_LIB in ['PyQt4', 'PySide']: delta = ev.delta() else: delta = ev.angleDelta().x() diff --git a/pyqtgraph/tests/test_qt.py b/pyqtgraph/tests/test_qt.py index 5c8800dd..bfb98631 100644 --- a/pyqtgraph/tests/test_qt.py +++ b/pyqtgraph/tests/test_qt.py @@ -13,8 +13,8 @@ def test_isQObjectAlive(): gc.collect() assert not pg.Qt.isQObjectAlive(o2) -@pytest.mark.skipif(pg.Qt.USE_PYSIDE, reason='pysideuic does not appear to be ' - 'packaged with conda') +@pytest.mark.skipif(pg.Qt.QT_LIB == 'PySide', reason='pysideuic does not appear to be ' + 'packaged with conda') def test_loadUiType(): path = os.path.dirname(__file__) formClass, baseClass = pg.Qt.loadUiType(os.path.join(path, 'uictest.ui')) diff --git a/pyqtgraph/tests/test_ref_cycles.py b/pyqtgraph/tests/test_ref_cycles.py index dec95ef7..e05c4ef1 100644 --- a/pyqtgraph/tests/test_ref_cycles.py +++ b/pyqtgraph/tests/test_ref_cycles.py @@ -40,7 +40,7 @@ def mkrefs(*objs): return map(weakref.ref, allObjs.values()) -@pytest.mark.skipif(six.PY3 or pg.Qt.USE_PYSIDE, reason=skipreason) +@pytest.mark.skipif(six.PY3 or pg.Qt.QT_LIB == 'PySide', reason=skipreason) def test_PlotWidget(): def mkobjs(*args, **kwds): w = pg.PlotWidget(*args, **kwds) @@ -58,7 +58,7 @@ def test_PlotWidget(): for i in range(5): assert_alldead(mkobjs()) -@pytest.mark.skipif(six.PY3 or pg.Qt.USE_PYSIDE, reason=skipreason) +@pytest.mark.skipif(six.PY3 or pg.Qt.QT_LIB == 'PySide', reason=skipreason) def test_ImageView(): def mkobjs(): iv = pg.ImageView() @@ -71,7 +71,7 @@ def test_ImageView(): assert_alldead(mkobjs()) -@pytest.mark.skipif(six.PY3 or pg.Qt.USE_PYSIDE, reason=skipreason) +@pytest.mark.skipif(six.PY3 or pg.Qt.QT_LIB == 'PySide', reason=skipreason) def test_GraphicsWindow(): def mkobjs(): w = pg.GraphicsWindow() diff --git a/pyqtgraph/widgets/GraphicsView.py b/pyqtgraph/widgets/GraphicsView.py index f3f8cbb5..e1a7327e 100644 --- a/pyqtgraph/widgets/GraphicsView.py +++ b/pyqtgraph/widgets/GraphicsView.py @@ -5,7 +5,7 @@ Copyright 2010 Luke Campagnola Distributed under MIT/X11 license. See license.txt for more infomation. """ -from ..Qt import QtCore, QtGui, USE_PYSIDE +from ..Qt import QtCore, QtGui, QT_LIB try: from ..Qt import QtOpenGL @@ -115,7 +115,7 @@ class GraphicsView(QtGui.QGraphicsView): ## Workaround for PySide crash ## This ensures that the scene will outlive the view. - if USE_PYSIDE: + if QT_LIB == 'PySide': self.sceneObj._view_ref_workaround = self ## by default we set up a central widget with a grid layout. diff --git a/pyqtgraph/widgets/MatplotlibWidget.py b/pyqtgraph/widgets/MatplotlibWidget.py index 30496839..c5b6c980 100644 --- a/pyqtgraph/widgets/MatplotlibWidget.py +++ b/pyqtgraph/widgets/MatplotlibWidget.py @@ -1,8 +1,8 @@ -from ..Qt import QtGui, QtCore, USE_PYSIDE, USE_PYQT5 +from ..Qt import QtGui, QtCore, QT_LIB import matplotlib -if not USE_PYQT5: - if USE_PYSIDE: +if QT_LIB != 'PyQt5': + if QT_LIB == 'PySide': matplotlib.rcParams['backend.qt4']='PySide' from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas diff --git a/pyqtgraph/widgets/RemoteGraphicsView.py b/pyqtgraph/widgets/RemoteGraphicsView.py index 85f5556a..a1674cc2 100644 --- a/pyqtgraph/widgets/RemoteGraphicsView.py +++ b/pyqtgraph/widgets/RemoteGraphicsView.py @@ -1,5 +1,5 @@ -from ..Qt import QtGui, QtCore, USE_PYSIDE -if not USE_PYSIDE: +from ..Qt import QtGui, QtCore, QT_LIB +if QT_LIB in ['PyQt4', 'PyQt5']: import sip from .. import multiprocess as mp from .GraphicsView import GraphicsView @@ -208,7 +208,7 @@ class Renderer(GraphicsView): self.shm.resize(size) ## render the scene directly to shared memory - if USE_PYSIDE: + if QT_LIB in ['PySide', 'PySide2']: ch = ctypes.c_char.from_buffer(self.shm, 0) #ch = ctypes.c_char_p(address) self.img = QtGui.QImage(ch, self.width(), self.height(), QtGui.QImage.Format_ARGB32) diff --git a/tools/rebuildUi.py b/tools/rebuildUi.py index bdacda81..18de45d6 100644 --- a/tools/rebuildUi.py +++ b/tools/rebuildUi.py @@ -10,6 +10,7 @@ import os, sys, subprocess, tempfile pyqtuic = 'pyuic4' pysideuic = 'pyside-uic' pyqt5uic = 'pyuic5' +pyside2uic = 'pyside2-uic' usage = """Compile .ui files to .py for all supported pyqt/pyside versions. @@ -49,7 +50,7 @@ for arg in args: # rebuild all requested ui files for ui in uifiles: base, _ = os.path.splitext(ui) - for compiler, ext in [(pyqtuic, '_pyqt.py'), (pysideuic, '_pyside.py'), (pyqt5uic, '_pyqt5.py')]: + for compiler, ext in [(pyqtuic, '_pyqt.py'), (pysideuic, '_pyside.py'), (pyqt5uic, '_pyqt5.py'), (pyside2uic, '_pyside2.py')]: py = base + ext if not force and os.path.exists(py) and os.stat(ui).st_mtime <= os.stat(py).st_mtime: print("Skipping %s; already compiled." % py)