Skip to content

Commit a95ea4e

Browse files
committed
Added support for PyQt6
1 parent 0054756 commit a95ea4e

23 files changed

+241
-227
lines changed

CHANGELOG.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
# PythonQwt Releases
22

3+
## Version 0.10.1
4+
5+
- Added support for PyQt6.
6+
37
## Version 0.10.0
48

5-
- Added support for QtPy 2, PyQt6 and PySide6.
9+
- Added support for QtPy 2 and PySide6.
610
- Dropped support for Python 2.
711

812
## Version 0.9.2
@@ -12,18 +16,18 @@
1216
## Version 0.9.1
1317

1418
- Added load test showing a large number of plots (eventually highlights performance issues).
15-
- Fixed event management in `QwtPlot` and removed unnecessary `QEvent.LayoutRequest`
19+
- Fixed event management in `QwtPlot` and removed unnecessary `QEvent.LayoutRequest`
1620
emission in `QwtScaleWidget` (caused high CPU usage with `guiqwt.ImageWidget`).
1721
- `QwtScaleDiv`: fixed ticks initialization when passing all arguments to constructor.
1822
- tests/image.py: fixed overriden `updateLegend` signature.
1923

2024
## Version 0.9.0
2125

22-
- `QwtPlot`: set the `autoReplot` option at False by default, to avoid time consuming
26+
- `QwtPlot`: set the `autoReplot` option at False by default, to avoid time consuming
2327
implicit plot updates.
24-
- Added `QwtPlotItem.setIcon` and `QwtPlotItem.icon` method for setting and getting the
25-
icon associated to the plot item (as of today, this feature is not strictly needed in
26-
PythonQwt: this has been implemented for several use cases in higher level libraries
28+
- Added `QwtPlotItem.setIcon` and `QwtPlotItem.icon` method for setting and getting the
29+
icon associated to the plot item (as of today, this feature is not strictly needed in
30+
PythonQwt: this has been implemented for several use cases in higher level libraries
2731
(see PR #61).
2832
- Removed unused `QwtPlotItem.defaultIcon` method.
2933
- Added various minor optimizations for axes/ticks drawing features.
@@ -53,7 +57,7 @@
5357

5458
- Added PySide2 support: PythonQwt is now compatible with Python 2.7, Python 3.4+,
5559
PyQt4, PyQt5 and PySide2!
56-
60+
5761
## Version 0.7.1
5862

5963
- Changed QwtPlotItem.detachItems signature: removed unnecessary "autoDelete" argument,

doc/installation.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Dependencies
55
------------
66

77
Requirements:
8-
* Python 3.x (x>=4)
8+
* Python 3.x (x>=6)
99
* PyQt4 4.x (x>=4), PyQt5 5.x (x>=5), PyQt6 or PySide6
1010
* QtPy >= 1.3
1111
* NumPy 1.x (x>=5)

qwt/column_symbol.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88
from qwt.interval import QwtInterval
99

1010
from qtpy.QtGui import QPolygonF, QPalette
11-
from qtpy.QtCore import QRectF, Qt
11+
from qtpy.QtCore import QRectF, Qt, QLineF
1212

1313

1414
def qwtDrawBox(p, rect, pal, lw):
1515
if lw > 0.0:
1616
if rect.width() == 0.0:
1717
p.setPen(pal.dark().color())
18-
p.drawLine(rect.topLeft(), rect.bottomLeft())
18+
p.drawLine(QLineF(rect.topLeft(), rect.bottomLeft()))
1919
return
2020
if rect.height() == 0.0:
2121
p.setPen(pal.dark().color())
22-
p.drawLine(rect.topLeft(), rect.topRight())
22+
p.drawLine(QLineF(rect.topLeft(), rect.topRight()))
2323
return
2424
lw = min([lw, rect.height() / 2.0 - 1.0])
2525
lw = min([lw, rect.width() / 2.0 - 1.0])
@@ -40,11 +40,11 @@ def qwtDrawPanel(painter, rect, pal, lw):
4040
if lw > 0.0:
4141
if rect.width() == 0.0:
4242
painter.setPen(pal.window().color())
43-
painter.drawLine(rect.topLeft(), rect.bottomLeft())
43+
painter.drawLine(QLineF(rect.topLeft(), rect.bottomLeft()))
4444
return
4545
if rect.height() == 0.0:
4646
painter.setPen(pal.window().color())
47-
painter.drawLine(rect.topLeft(), rect.topRight())
47+
painter.drawLine(QLineF(rect.topLeft(), rect.topRight()))
4848
return
4949
lw = min([lw, rect.height() / 2.0 - 1.0])
5050
lw = min([lw, rect.width() / 2.0 - 1.0])

qwt/dyngrid_layout.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def __init__(self):
2525
self.maxColumns = 0
2626
self.numRows = 0
2727
self.numColumns = 0
28-
self.expanding = Qt.Orientations()
28+
self.expanding = Qt.Horizontal
2929
self.itemSizeHints = []
3030
self.itemList = []
3131

@@ -220,8 +220,8 @@ def layoutItems(self, rect, numColumns):
220220
rowHeight = [0] * numRows
221221
colWidth = [0] * numColumns
222222
self.layoutGrid(numColumns, rowHeight, colWidth)
223-
expandH = self.expandingDirections() & Qt.Horizontal
224-
expandV = self.expandingDirections() & Qt.Vertical
223+
expandH = self.expandingDirections() == Qt.Horizontal
224+
expandV = self.expandingDirections() == Qt.Vertical
225225
if expandH or expandV:
226226
self.stretchGrid(rect, numColumns, rowHeight, colWidth)
227227
maxColumns = self.__data.maxColumns
@@ -299,27 +299,26 @@ def stretchGrid(self, rect, numColumns, rowHeight, colWidth):
299299
return
300300
expandH = self.expandingDirections() & Qt.Horizontal
301301
expandV = self.expandingDirections() & Qt.Vertical
302+
mleft, mtop, mright, mbottom = self.getContentsMargins()
302303
if expandH:
303-
xDelta = (
304-
rect.width() - 2 * self.margin() - (numColumns - 1) * self.spacing()
305-
)
304+
xDelta = rect.width() - (mleft + mright) - (numColumns - 1) * self.spacing()
306305
for col in range(numColumns):
307306
xDelta -= colWidth[col]
308307
if xDelta > 0:
309308
for col in range(numColumns):
310-
space = xDelta / (numColumns - col)
309+
space = xDelta // (numColumns - col)
311310
colWidth[col] += space
312311
xDelta -= space
313312
if expandV:
314313
numRows = self.itemCount() / numColumns
315314
if self.itemCount() % numColumns:
316315
numRows += 1
317-
yDelta = rect.height() - 2 * self.margin() - (numRows - 1) * self.spacing()
316+
yDelta = rect.height() - (mtop + mbottom) - (numRows - 1) * self.spacing()
318317
for row in range(numRows):
319318
yDelta -= rowHeight[row]
320319
if yDelta > 0:
321320
for row in range(numRows):
322-
space = yDelta / (numRows - row)
321+
space = yDelta // (numRows - row)
323322
rowHeight[row] += space
324323
yDelta -= space
325324

qwt/graphic.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
:members:
1414
"""
1515

16+
import math
1617
from qwt.null_paintdevice import QwtNullPaintDevice
1718
from qwt.painter_command import QwtPainterCommand
1819

@@ -26,8 +27,6 @@
2627
)
2728
from qtpy.QtCore import Qt, QRectF, QSizeF, QSize, QPointF, QRect
2829

29-
import numpy as np
30-
3130

3231
def qwtHasScalablePen(painter):
3332
pen = painter.pen()
@@ -115,8 +114,6 @@ def qwtExecCommand(painter, cmd, renderHints, transform, initialTransform):
115114
QPainter.Antialiasing,
116115
QPainter.TextAntialiasing,
117116
QPainter.SmoothPixmapTransform,
118-
QPainter.HighQualityAntialiasing,
119-
QPainter.NonCosmeticDefaultPen,
120117
):
121118
painter.setRenderHint(hint, bool(data.renderHints & hint))
122119
if data.flags & QPaintEngine.DirtyCompositionMode:
@@ -383,7 +380,7 @@ def scaledBoundingRect(self, sx, sy):
383380
def sizeMetrics(self):
384381
"""Return Ceiled :py:meth:`defaultSize()`"""
385382
sz = self.defaultSize()
386-
return QSize(np.ceil(sz.width()), np.ceil(sz.height()))
383+
return QSize(math.ceil(sz.width()), math.ceil(sz.height()))
387384

388385
def setDefaultSize(self, size):
389386
"""
@@ -579,8 +576,8 @@ def toPixmap(self, *args):
579576
if self.isNull():
580577
return QPixmap()
581578
sz = self.defaultSize()
582-
w = np.ceil(sz.width())
583-
h = np.ceil(sz.height())
579+
w = math.ceil(sz.width())
580+
h = math.ceil(sz.height())
584581
pixmap = QPixmap(w, h)
585582
pixmap.fill(Qt.transparent)
586583
r = QRectF(0.0, 0.0, sz.width(), sz.height())
@@ -640,8 +637,8 @@ def toImage(self, *args):
640637
if self.isNull():
641638
return QImage()
642639
sz = self.defaultSize()
643-
w = np.ceil(sz.width())
644-
h = np.ceil(sz.height())
640+
w = math.ceil(sz.width())
641+
h = math.ceil(sz.height())
645642
image = QImage(w, h, QImage.Format_ARGB32)
646643
image.fill(0)
647644
r = QRect(0, 0, sz.width(), sz.height())

qwt/legend.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,8 @@ def setSpacing(self, spacing):
308308
spacing = max([spacing, 0])
309309
if spacing != self.__data.spacing:
310310
self.__data.spacing = spacing
311-
indent = self.margin() + self.__data.spacing
311+
margin = max(self.getContentsMargins())
312+
indent = margin + self.__data.spacing
312313
if self.__data.icon.width() > 0:
313314
indent += self.__data.icon.width() + self.__data.spacing
314315
self.setIndent(indent)
@@ -948,8 +949,9 @@ def renderItem(self, painter, widget, rect, fillBackground):
948949
if label is not None:
949950
icon = label.data().icon()
950951
sz = icon.defaultSize()
952+
margin = max(label.getContentsMargins())
951953
iconRect = QRectF(
952-
rect.x() + label.margin(),
954+
rect.x() + margin,
953955
rect.center().y() - 0.5 * sz.height(),
954956
sz.width(),
955957
sz.height(),

qwt/painter.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
QColor,
3030
)
3131
from qtpy.QtWidgets import QFrame, QStyle, QStyleOptionFocusRect, QStyleOption
32-
from qtpy.QtCore import Qt, QRect, QPoint, QRectF
32+
from qtpy.QtCore import Qt, QRect, QPoint, QRectF, QLineF
3333
from qtpy import QtCore as QC
3434

3535
QT_MAJOR_VERSION = int(QC.__version__.split(".")[0])
@@ -384,7 +384,7 @@ def drawColorBar(self, painter, colorMap, interval, scaleMap, orientation, rect)
384384
else:
385385
c = colorTable[colorMap.colorIndex(interval, value)]
386386
pmPainter.setPen(c)
387-
pmPainter.drawLine(x, devRect.top(), x, devRect.bottom())
387+
pmPainter.drawLine(QLineF(x, devRect.top(), x, devRect.bottom()))
388388
else:
389389
sMap = QwtScaleMap(scaleMap)
390390
sMap.setPaintInterval(rect.bottom(), rect.top())
@@ -395,7 +395,7 @@ def drawColorBar(self, painter, colorMap, interval, scaleMap, orientation, rect)
395395
else:
396396
c = colorTable[colorMap.colorIndex(interval, value)]
397397
pmPainter.setPen(c)
398-
pmPainter.drawLine(devRect.left(), y, devRect.right(), y)
398+
pmPainter.drawLine(QLineF(devRect.left(), y, devRect.right(), y))
399399
pmPainter.end()
400400
self.drawPixmap(painter, rect, pixmap)
401401

qwt/plot.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
:members:
2020
"""
2121

22+
import math
23+
2224
from qtpy.QtWidgets import (
2325
QWidget,
2426
QSizePolicy,
@@ -1388,7 +1390,7 @@ def updateCanvasMargins(self):
13881390

13891391
for axisId in self.AXES:
13901392
if margins[axisId] >= 0.0:
1391-
m = np.ceil(margins[axisId])
1393+
m = math.ceil(margins[axisId])
13921394
self.plotLayout().setCanvasMargin(m, axisId)
13931395
doUpdate = True
13941396

@@ -1520,7 +1522,7 @@ def canvasBackground(self):
15201522
15211523
:py:meth:`setCanvasBackground()`
15221524
"""
1523-
return self.canvas().palette().brush(QPalette.Normal, QPalette.Window)
1525+
return self.canvas().palette().brush(QPalette.Active, QPalette.Window)
15241526

15251527
def axisValid(self, axis_id):
15261528
"""

qwt/plot_canvas.py

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,6 @@ def alignCornerRects(self, rect):
133133
r.setBottom(rect.bottom())
134134

135135

136-
def _rects_conv_PyQt5(rects):
137-
# PyQt5 compatibility: the conversion from QRect to QRectF should not
138-
# be necessary but it seems to be anyway... PyQt5 bug?
139-
if QT_API == "pyqt5":
140-
return [QRectF(rect) for rect in rects]
141-
else:
142-
return rects
143-
144-
145136
def qwtDrawBackground(painter, canvas):
146137
painter.save()
147138
borderClip = canvas.borderPath(canvas.rect())
@@ -157,12 +148,7 @@ def qwtDrawBackground(painter, canvas):
157148
if brush.gradient().coordinateMode() == QGradient.ObjectBoundingMode:
158149
rects += [canvas.rect()]
159150
else:
160-
clipregion = painter.clipRegion()
161-
try:
162-
rects += [clipregion.rects()]
163-
except AttributeError:
164-
# Qt6: no equivalent to 'rects' method...
165-
rects += [clipregion.begin()]
151+
rects += [painter.clipRegion().boundingRect()]
166152
useRaster = False
167153
if painter.paintEngine().type() == QPaintEngine.X11:
168154
useRaster = True
@@ -174,26 +160,22 @@ def qwtDrawBackground(painter, canvas):
174160
format_ = QImage.Format_ARGB32
175161
break
176162
image = QImage(canvas.size(), format_)
177-
p = QPainter(image)
178-
p.setPen(Qt.NoPen)
179-
p.setBrush(brush)
180-
p.drawRects(_rects_conv_PyQt5(rects))
181-
p.end()
163+
pntr = QPainter(image)
164+
pntr.setPen(Qt.NoPen)
165+
pntr.setBrush(brush)
166+
for rect in rects:
167+
pntr.drawRect(rect)
168+
pntr.end()
182169
painter.drawImage(0, 0, image)
183170
else:
184171
painter.setPen(Qt.NoPen)
185172
painter.setBrush(brush)
186-
painter.drawRects(_rects_conv_PyQt5(rects))
173+
for rect in rects:
174+
painter.drawRect(rect)
187175
else:
188176
painter.setPen(Qt.NoPen)
189177
painter.setBrush(brush)
190-
clipregion = painter.clipRegion()
191-
try:
192-
rects = clipregion.rects()
193-
except AttributeError:
194-
# Qt6: no equivalent to 'rects' method...
195-
rects = [clipregion.begin()]
196-
painter.drawRects(_rects_conv_PyQt5(rects))
178+
painter.drawRect(painter.clipRegion().boundingRect())
197179

198180
painter.restore()
199181

@@ -754,8 +736,14 @@ def drawBorder(self, painter):
754736
else:
755737
opt = QStyleOptionFrame()
756738
opt.initFrom(self)
757-
frameShape = self.frameStyle() & QFrame.Shape_Mask
758-
frameShadow = self.frameStyle() & QFrame.Shadow_Mask
739+
try:
740+
shape_mask = QFrame.Shape_Mask.value
741+
shadow_mask = QFrame.Shadow_Mask.value
742+
except AttributeError:
743+
shape_mask = QFrame.Shape_Mask
744+
shadow_mask = QFrame.Shadow_Mask
745+
frameShape = self.frameStyle() & shape_mask
746+
frameShadow = self.frameStyle() & shadow_mask
759747
opt.frameShape = QFrame.Shape(int(opt.frameShape) | frameShape)
760748
if frameShape in (
761749
QFrame.Box,

0 commit comments

Comments
 (0)