Skip to content

Commit 61c3d77

Browse files
committed
fix(dyngrid_layout): compute the number of rows with integer division
QwtDynGridLayout.setGeometry and QwtDynGridLayout.stretchGrid computed the number of rows with a true division (`/`) where the Qwt C++ code uses an integer division: numRows() returned a float (e.g. 2.5 for 3 items on 2 columns), and laying out the items with vertical expansion (setExpandingDirections(Qt.Vertical)) raised "TypeError: 'float' object cannot be interpreted as an integer". - Use an integer division (`//`) in both methods. The other row count computations already convert the quotient to an integer and are left unchanged. - Regression tests: integer number of rows for several item and column counts, rows stretched to the layout height with vertical expansion. - Changelog entry. Refs #115 Assisted-by: Claude Opus 5.5
1 parent 6d29a36 commit 61c3d77

3 files changed

Lines changed: 50 additions & 2 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- Fixed `QwtPlotDirectPainter.setAttribute`, which did not set or clear attributes as requested: enabling `AtomicPainter` twice disabled it, and `FullRepaint` or `CopyBackingStore` could not be disabled anymore once enabled ([Issue #115](https://github.com/PlotPyStack/PythonQwt/issues/115))
1717
- Fixed painting into a `QwtGraphic` with clipping enabled, which raised a `TypeError` on each paint operation (aborting the process with PyQt's default exception hook): clipped paint operations are now recorded, and the bounding rectangle of the graphic is clipped as in Qwt ([Issue #115](https://github.com/PlotPyStack/PythonQwt/issues/115))
1818
- Fixed the `QwtPainterCommand` copy constructor (`QwtPainterCommand(other)`), which raised an `AttributeError` for state commands and a `TypeError` (Qt objects cannot be pickled) for pixmap and image commands: commands of every type can now be copied, the copy being independent of the original ([Issue #115](https://github.com/PlotPyStack/PythonQwt/issues/115))
19+
- Fixed `QwtDynGridLayout` (used by `QwtLegend`), whose `numRows()` returned a float (e.g. `2.5` for 3 items on 2 columns) and which raised a `TypeError` when laying out its items with vertical expansion (`setExpandingDirections(Qt.Vertical)`) ([Issue #115](https://github.com/PlotPyStack/PythonQwt/issues/115))
1920

2021
## Version 0.16.3
2122

‎qwt/dyngrid_layout.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def setGeometry(self, rect):
159159
if self.isEmpty():
160160
return
161161
self.__data.numColumns = self.columnsForWidth(rect.width())
162-
self.__data.numRows = self.itemCount() / self.__data.numColumns
162+
self.__data.numRows = self.itemCount() // self.__data.numColumns
163163
if self.itemCount() % self.__data.numColumns:
164164
self.__data.numRows += 1
165165
itemGeometries = self.layoutItems(rect, self.__data.numColumns)
@@ -314,7 +314,7 @@ def stretchGrid(self, rect, numColumns, rowHeight, colWidth):
314314
colWidth[col] += space
315315
xDelta -= space
316316
if expandV:
317-
numRows = self.itemCount() / numColumns
317+
numRows = self.itemCount() // numColumns
318318
if self.itemCount() % numColumns:
319319
numRows += 1
320320
yDelta = rect.height() - hmargins - (numRows - 1) * self.spacing()

‎qwt/tests/test_issue115_porting_bugs.py‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
QwtScaleMap,
3535
QwtSymbol,
3636
)
37+
from qwt.dyngrid_layout import QwtDynGridLayout
3738
from qwt.graphic import QwtGraphic
3839
from qwt.painter_command import QwtPainterCommand
3940
from qwt.plot_curve import series_to_polyline
@@ -521,6 +522,51 @@ def test_painter_command_copy_replay():
521522
del app
522523

523524

525+
# ---------------------------------------------------------------------------
526+
# QwtDynGridLayout
527+
# ---------------------------------------------------------------------------
528+
529+
530+
def _make_grid_layout(count, max_columns):
531+
widget = QW.QWidget()
532+
layout = QwtDynGridLayout(widget)
533+
layout.setMaxColumns(max_columns)
534+
for index in range(count):
535+
layout.addWidget(QW.QLabel(f"Item {index}"))
536+
return widget, layout
537+
538+
539+
@pytest.mark.parametrize(
540+
"count, max_columns, rows",
541+
((1, 1, 1), (3, 2, 2), (4, 2, 2), (5, 3, 2), (6, 1, 6), (7, 3, 3)),
542+
)
543+
def test_dyngrid_layout_rows(count, max_columns, rows):
544+
"""The number of rows of the layout is an integer"""
545+
app = _ensure_app() # keep a reference alive for the duration of the test
546+
widget, layout = _make_grid_layout(count, max_columns)
547+
layout.setGeometry(QC.QRect(0, 0, 2000, 2000))
548+
assert layout.numColumns() == max_columns
549+
assert layout.numRows() == rows
550+
assert isinstance(layout.numRows(), int)
551+
widget.close()
552+
del app
553+
554+
555+
def test_dyngrid_layout_vertical_expanding():
556+
"""Rows are stretched to fill the layout height with vertical expansion"""
557+
app = _ensure_app() # keep a reference alive for the duration of the test
558+
widget, layout = _make_grid_layout(3, 2)
559+
layout.setExpandingDirections(QC.Qt.Vertical)
560+
layout.setGeometry(QC.QRect(0, 0, 400, 300))
561+
geometries = [layout.itemAt(index).geometry() for index in range(3)]
562+
assert geometries[0].top() == geometries[1].top()
563+
assert geometries[2].top() > geometries[0].bottom()
564+
margins = layout.contentsMargins()
565+
assert geometries[2].bottom() + 1 + margins.bottom() == 300
566+
widget.close()
567+
del app
568+
569+
524570
if __name__ == "__main__":
525571
for name in ("toPixmap", "toImage"):
526572
test_graphic_conversion_default_size(name)
@@ -539,4 +585,5 @@ def test_painter_command_copy_replay():
539585
test_painter_command_copy()
540586
test_painter_command_copy_is_independent()
541587
test_painter_command_copy_replay()
588+
test_dyngrid_layout_vertical_expanding()
542589
print("OK")

0 commit comments

Comments
 (0)