Skip to content

Commit

Permalink
Merge pull request #492 from nucleic/qt6-flow
Browse files Browse the repository at this point in the history
qt: fix flow layout calculation on Qt6
  • Loading branch information
MatthieuDartiailh committed Jun 13, 2022
2 parents d719f11 + 1b99cca commit bf1e309
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 23 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
/build
/dist
/docs/build
/enaml/version.py
/tools/pygments/build
/tools/pygments/dist
/.mypy_cache
Expand Down
48 changes: 25 additions & 23 deletions enaml/qt/q_flow_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ def layout(self, x, y):
if align == QFlowLayout.AlignTrailing:
y += delta_h
elif align == QFlowLayout.AlignCenter:
y += delta_h / 2
y += delta_h // 2
item.setGeometry(QRect(x, int(round(y)),
int(round(w)), int(round(h))))
return
Expand Down Expand Up @@ -361,7 +361,7 @@ def layout(self, x, y):
for ignored, item in diffs:
item_stretch = item.data.stretch
max_width = item.maximumSize().width()
d = item_stretch * delta / items_stretch
d = item_stretch * delta // items_stretch
items_stretch -= item_stretch
item_width = widths[item]
if item_width + d > max_width:
Expand All @@ -384,9 +384,9 @@ def layout(self, x, y):
if opts.direction == QFlowLayout.LeftToRight:
start_x += delta
elif opts.alignment == QFlowLayout.AlignCenter:
start_x += delta / 2
start_x += delta // 2
else:
d = delta / (len(items) + 1)
d = delta // (len(items) + 1)
space += d
start_x += d

Expand All @@ -407,7 +407,7 @@ def layout(self, x, y):
if align == QFlowLayout.AlignTrailing:
this_y = y + delta
elif align == QFlowLayout.AlignCenter:
this_y = y + delta / 2
this_y = y + delta // 2
item.setGeometry(QRect(int(round(curr_x)), int(round(this_y)),
int(round(w)), int(round(h))))
curr_x += (w + space)
Expand All @@ -419,41 +419,41 @@ class _LayoutColumn(object):
This class accumulates information about a column of items as the
items are added to the column. Instances of the this class are
created by the QFlowLayout during a layout pass. For performance
reasons, there are several publically accesible attributes. See
reasons, there are several publically accessible attributes. See
their documentation for restrictions on their use.
"""
#: The width to use for laying out the column. This attribute is
#: modified directly by the layout as it distributes the horizontal
#: space amongst the columns.
layout_width = 0
layout_width: int = 0

#: The minimum height required for the column. This is automatically
#: updated as items are added to the column. It should be considered
#: read-only to external users.
min_height = 0
min_height: int = 0

#: The minimum width required for the column. This is automatically
#: updated as items are added to the column. It should be considered
#: read-only to external users.
min_width = 0
min_width: int = 0

#: The desired height for the column. This is automatically updated
#: as items are added to the column. It should be considered
#: read-only to external users.
hint_height = 0
hint_height: int = 0

#: The desired width for the column. This is automatically updated
#: as items are added to the column. It should be considered
#: read-only to external users.
hint_width = 0
hint_width: int = 0

#: The vertical stretch factor for the column. This is automatically
#: updated as items are added to the column. It should be considered
#: read-only by external users.
stretch = 0
stretch: int = 0

def __init__(self, height, options):
def __init__(self, height: int, options):
""" Initialize a layout column.
Parameters
Expand Down Expand Up @@ -513,7 +513,7 @@ def add_item(self, item):
self._items.append(item)
return True

def layout(self, x, y):
def layout(self, x: int, y: int) -> None:
""" Layout the row using the given starting coordinates.
Parameters
Expand Down Expand Up @@ -548,7 +548,7 @@ def layout(self, x, y):
if align == QFlowLayout.AlignTrailing:
x += delta_w
elif align == QFlowLayout.AlignCenter:
x += delta_w / 2
x += delta_w // 2
item.setGeometry(QRect(x, y, w, h))
return

Expand Down Expand Up @@ -577,7 +577,7 @@ def layout(self, x, y):
for ignored, item in diffs:
item_stretch = item.data.stretch
max_height = item.maximumSize().height()
d = item_stretch * delta / items_stretch
d = item_stretch * delta // items_stretch
items_stretch -= item_stretch
item_height = heights[item]
if item_height + d > max_height:
Expand All @@ -600,9 +600,9 @@ def layout(self, x, y):
if opts.direction == QFlowLayout.TopToBottom:
start_y += delta
elif opts.alignment == QFlowLayout.AlignCenter:
start_y += delta / 2
start_y += delta // 2
else:
d = delta / (len(items) + 1)
d = delta // (len(items) + 1)
space += d
start_y += d

Expand All @@ -623,7 +623,9 @@ def layout(self, x, y):
if align == QFlowLayout.AlignTrailing:
this_x = x + delta
elif align == QFlowLayout.AlignCenter:
this_x = x + delta / 2
this_x = x + delta // 2
if isinstance(w, float):
breakpoint()
item.setGeometry(QRect(this_x, curr_y, w, h))
curr_y += (h + space)

Expand Down Expand Up @@ -1004,7 +1006,7 @@ def _doHorizontalLayout(self, rect, test):
diff_space = max(total_diff, 1) # Guard against divide by zero
layout_height = 0
for row in rows:
d = play_space * row.diff_height / diff_space
d = play_space * row.diff_height // diff_space
row.layout_height = min(row.min_height + d, row.hint_height)
layout_height += row.layout_height
layout_height += space
Expand All @@ -1015,7 +1017,7 @@ def _doHorizontalLayout(self, rect, test):
if remaining > 0 and stretch > 0:
for row in rows:
if row.stretch > 0:
row.layout_height += remaining * row.stretch / stretch
row.layout_height += remaining * row.stretch // stretch

# Make a final pass to layout the rows, computing the overall
# final layout height along the way.
Expand Down Expand Up @@ -1076,7 +1078,7 @@ def _doVerticalLayout(self, rect, test):
diff_space = max(total_diff, 1) # Guard against divide by zero
layout_width = 0
for col in cols:
d = play_space * col.diff_width / diff_space
d = play_space * col.diff_width // diff_space
col.layout_width = min(col.min_width + d, col.hint_width)
layout_width += col.layout_width
layout_width += space
Expand All @@ -1087,7 +1089,7 @@ def _doVerticalLayout(self, rect, test):
if remaining > 0 and stretch > 0:
for col in cols:
if col.stretch > 0:
col.layout_width += remaining * col.stretch / stretch
col.layout_width += remaining * col.stretch // stretch

# Make a final pass to layout the columns, computing the overall
# final layout width along the way.
Expand Down
1 change: 1 addition & 0 deletions releasenotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Dates are written as DD/MM/YYYY
- fix drag and drop support under Qt6 PR #491
- fix date and time conversion under Qt6 PR #486
- fix handling of mouse press event by popup views PR #486
- fix flow widget size computation to only use integer (fixes Qt6) PR #492

0.15.0 - 31/03/2022
-------------------
Expand Down
64 changes: 64 additions & 0 deletions tests/widgets/test_flow_area.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# ------------------------------------------------------------------------------
# Copyright (c) 2022, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file LICENSE, distributed with this software.
# ------------------------------------------------------------------------------
"""Test flow area behavior.
With a particular focus on resizing.
"""
import pytest

from utils import compile_source, wait_for_window_displayed


SOURCE = """
from enaml.core.api import Looper
from enaml.widgets.api import Container, FlowArea, FlowItem, Label, Window
enamldef Main(Window): w:
alias horizontal_spacing: flow_area.horizontal_spacing
alias vertical_spacing: flow_area.vertical_spacing
alias direction: flow_area.direction
alias align: flow_area.align
initial_size = (800, 800)
Container:
FlowArea: flow_area:
Looper:
iterable = [1, 2, 3, 4, 5, 6]
FlowItem:
Container:
Label:
text = str(loop.item)
"""


@pytest.mark.parametrize("horizontal_spacing", [1, 2])
@pytest.mark.parametrize("vertical_spacing", [1, 2])
@pytest.mark.parametrize(
"direction", ["left_to_right", "right_to_left", "top_to_bottom", "bottom_to_top"]
)
@pytest.mark.parametrize("align", ["leading", "center", "justify", "trailing"])
def test_flow_area_sizing(
enaml_qtbot, horizontal_spacing, vertical_spacing, direction, align
):
"""Check we can click on a push button."""
win = compile_source(SOURCE, "Main")(
horizontal_spacing=horizontal_spacing,
vertical_spacing=vertical_spacing,
direction=direction,
align=align,
)
win.show()
wait_for_window_displayed(enaml_qtbot, win)

win.set_size((801, 801))
enaml_qtbot.wait(1)
win.set_size((802, 802))
enaml_qtbot.wait(1)

0 comments on commit bf1e309

Please sign in to comment.