Skip to content

Commit 3bf3351

Browse files
committed
Allow the layout to be empty
1 parent 0710d94 commit 3bf3351

File tree

2 files changed

+43
-55
lines changed

2 files changed

+43
-55
lines changed

src/test.py

+21-34
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class SplitExceptionTestCase(unittest.TestCase):
4040
def setUp(self):
4141
self.app = QApplication([])
4242
self.ws = [Widget(i) for i in range(2)]
43-
self.layout = get_empty_tiling_layout(2)
43+
self.layout = QTilingLayout(max_span=2)
4444
self.layout.addWidget(self.ws[0], 0, 0, 2, 1)
4545
self.layout.addWidget(self.ws[1], 0, 1, 2, 1)
4646

@@ -145,8 +145,7 @@ def test(self):
145145

146146
def _perform_operation(self, max_span, positions, widget, operation):
147147
self.trace.append((positions[widget], operation))
148-
layout = QTilingLayout(self.widgets[0], max_span=max_span)
149-
layout.removeWidget(self.widgets[0])
148+
layout = QTilingLayout(max_span=max_span)
150149
for i in range(len(positions)):
151150
layout._add_widget(self.widgets[i], *positions[i], False)
152151
try:
@@ -171,13 +170,6 @@ def _perform_operation(self, max_span, positions, widget, operation):
171170
random.choice(new_operations))
172171

173172

174-
def get_empty_tiling_layout(max_span):
175-
mock_widget = QWidget()
176-
layout = QTilingLayout(mock_widget, max_span=max_span)
177-
layout.removeWidget(mock_widget)
178-
return layout
179-
180-
181173
class TransposedMethodsTestCase(unittest.TestCase):
182174

183175
# ┌───┬──────────┐
@@ -192,7 +184,7 @@ class TransposedMethodsTestCase(unittest.TestCase):
192184
def setUp(self):
193185
self.app = QApplication([])
194186
self.widgets = [Widget(i) for i in range(5)]
195-
self.layout = get_empty_tiling_layout(4)
187+
self.layout = QTilingLayout(max_span=4)
196188
self.layout.addWidget(self.widgets[0], 0, 0, 2, 1)
197189
self.layout.addWidget(self.widgets[1], 0, 1, 1, 3)
198190
self.layout.addWidget(self.widgets[2], 1, 1, 1, 1)
@@ -278,7 +270,7 @@ class StateTestCase(unittest.TestCase):
278270
def setUp(self):
279271
self.app = QApplication([])
280272
self.widgets = [Widget(i) for i in range(5)]
281-
self.layout = get_empty_tiling_layout(4)
273+
self.layout = QTilingLayout(max_span=4)
282274
self.layout.addWidget(self.widgets[0], 0, 0, 2, 1)
283275
self.layout.addWidget(self.widgets[1], 0, 1, 1, 3)
284276
self.layout.addWidget(self.widgets[2], 1, 1, 1, 1)
@@ -317,7 +309,7 @@ class SplitsTestCase(unittest.TestCase):
317309
def setUp(self):
318310
self.app = QApplication([])
319311
self.ws = [Widget(i) for i in range(2)]
320-
self.layout = get_empty_tiling_layout(2)
312+
self.layout = QTilingLayout(max_span=2)
321313
self.layout.addWidget(self.ws[0], 0, 0, 2, 2)
322314

323315
def test_hsplit_after(self):
@@ -368,7 +360,7 @@ class RemoveTestCase(unittest.TestCase):
368360
def setUp(self):
369361
self.app = QApplication([])
370362
self.widgets = [Widget(i) for i in range(5)]
371-
self.layout = get_empty_tiling_layout(4)
363+
self.layout = QTilingLayout(max_span=4)
372364
self.layout.addWidget(self.widgets[0], 0, 0, 2, 1)
373365
self.layout.addWidget(self.widgets[1], 0, 1, 1, 3)
374366
self.layout.addWidget(self.widgets[2], 1, 1, 1, 1)
@@ -415,11 +407,6 @@ def test_vertical_remove(self):
415407
(2, 3, 2, 1)
416408
)
417409

418-
def test_remove_last_widget(self):
419-
with self.assertRaises(SplitLimitException):
420-
for widget in self.widgets:
421-
self.layout.remove_widget(widget)
422-
423410

424411
class IndependentBlockTestCase(unittest.TestCase):
425412

@@ -438,7 +425,7 @@ class IndependentBlockTestCase(unittest.TestCase):
438425
# └───────────┴───────┴───┘
439426
def setUp(self):
440427
self.app = QApplication([])
441-
self.layout = get_empty_tiling_layout(6)
428+
self.layout = QTilingLayout(max_span=6)
442429
self.ws = [Widget(i) for i in range(11)]
443430
self.layout.addWidget(self.ws[0], 0, 0, 4, 1)
444431
self.layout.addWidget(self.ws[1], 0, 1, 2, 2)
@@ -491,7 +478,7 @@ def setUp(self):
491478
# │░░░│ 1 │
492479
# └───┴───────┘
493480
def test_right_space(self):
494-
layout = get_empty_tiling_layout(3)
481+
layout = QTilingLayout(max_span=3)
495482
widgets = [Widget(0), Widget(1)]
496483
layout.addWidget(widgets[0], 0, 0, 1, 1)
497484
layout.addWidget(widgets[1], 2, 1, 1, 2)
@@ -509,7 +496,7 @@ def test_right_space(self):
509496
# │ 1 │░░░│
510497
# └───────┴───┘
511498
def test_left_space(self):
512-
layout = get_empty_tiling_layout(3)
499+
layout = QTilingLayout(max_span=3)
513500
widgets = [Widget(0), Widget(1)]
514501
layout.addWidget(widgets[0], 0, 2, 1, 1)
515502
layout.addWidget(widgets[1], 2, 0, 1, 2)
@@ -527,7 +514,7 @@ def test_left_space(self):
527514
# │ 2 │░░░│
528515
# └───────┴───┘
529516
def test_not_enough_space(self):
530-
layout = get_empty_tiling_layout(3)
517+
layout = QTilingLayout(max_span=3)
531518
widgets = [Widget(0), Widget(1), Widget(2)]
532519
layout.addWidget(widgets[0], 0, 2, 1, 1)
533520
layout.addWidget(widgets[1], 1, 2, 1, 1)
@@ -548,7 +535,7 @@ def test_not_enough_space(self):
548535
# │░░░░░░░░░░░│
549536
# └───────────┘
550537
def test_move_supporters(self):
551-
layout = get_empty_tiling_layout(3)
538+
layout = QTilingLayout(max_span=3)
552539
widgets = [Widget(0), Widget(1), Widget(2)]
553540
layout.addWidget(widgets[0], 0, 0, 1, 1)
554541
layout.addWidget(widgets[1], 1, 0, 1, 1)
@@ -577,7 +564,7 @@ class SupportersTestCase(unittest.TestCase):
577564
# └───────────────────┘
578565
def setUp(self):
579566
self.app = QApplication([])
580-
self.layout = get_empty_tiling_layout(5)
567+
self.layout = QTilingLayout(max_span=5)
581568
self.ws = [Widget(i) for i in range(7)]
582569
self.layout.addWidget(self.ws[0], 0, 0, 1, 5)
583570
self.layout.addWidget(self.ws[1], 1, 0, 3, 3)
@@ -618,7 +605,7 @@ def setUp(self):
618605
# │░░░░░░░░░░░│
619606
# └───────────┘
620607
def test_top_block(self):
621-
layout = get_empty_tiling_layout(3)
608+
layout = QTilingLayout(max_span=3)
622609
widgets = [Widget(0), Widget(1), Widget(2)]
623610
layout.addWidget(widgets[0], 0, 0, 1, 1)
624611
layout.addWidget(widgets[1], 1, 0, 1, 1)
@@ -639,7 +626,7 @@ def test_top_block(self):
639626
# │░░░░░░░░░░░│
640627
# └───────────┘
641628
def test_left_block(self):
642-
layout = get_empty_tiling_layout(3)
629+
layout = QTilingLayout(max_span=3)
643630
widgets = [Widget(0), Widget(1), Widget(2)]
644631
layout.addWidget(widgets[0], 0, 0, 1, 3)
645632
layout.addWidget(widgets[1], 1, 0, 1, 1)
@@ -660,7 +647,7 @@ def test_left_block(self):
660647
# │░░░░░░░░░░░│
661648
# └───────────┘
662649
def test_right_block(self):
663-
layout = get_empty_tiling_layout(3)
650+
layout = QTilingLayout(max_span=3)
664651
widgets = [Widget(0), Widget(1), Widget(2)]
665652
layout.addWidget(widgets[0], 0, 0, 2, 1)
666653
layout.addWidget(widgets[1], 0, 1, 1, 2)
@@ -681,7 +668,7 @@ def test_right_block(self):
681668
# │ 3 │ 4 │ │
682669
# └───┴───┴───┘
683670
def test_no_suitable_block(self):
684-
layout = get_empty_tiling_layout(3)
671+
layout = QTilingLayout(max_span=3)
685672
widgets = [Widget(0), Widget(1), Widget(2), Widget(3), Widget(4)]
686673
layout.addWidget(widgets[0], 0, 0, 2, 1)
687674
layout.addWidget(widgets[1], 0, 1, 1, 2)
@@ -703,7 +690,7 @@ class BlockTestCase(unittest.TestCase):
703690
# └───┴───────┘
704691
def setUp(self):
705692
self.app = QApplication([])
706-
self.layout = get_empty_tiling_layout(3)
693+
self.layout = QTilingLayout(max_span=3)
707694
self.ws = [Widget(i) for i in range(2)]
708695
self.layout.addWidget(self.ws[0], 1, 3, 1, 1)
709696
self.layout.addWidget(self.ws[1], 2, 1, 1, 2)
@@ -755,7 +742,7 @@ class RecBlockTestCase(unittest.TestCase):
755742
# └───────────────┴───────────────┘
756743
def setUp(self):
757744
self.app = QApplication([])
758-
self.layout = get_empty_tiling_layout(8)
745+
self.layout = QTilingLayout(max_span=8)
759746
self.ws = [Widget(i) for i in range(6)]
760747
self.layout.addWidget(self.ws[0], 0, 0, 3, 2)
761748
self.layout.addWidget(self.ws[1], 0, 2, 2, 6)
@@ -897,7 +884,7 @@ class CriticalBlockTestCase(unittest.TestCase):
897884
# └───────┴───────┴───────┴───────┴───────┴───────┘
898885
def setUp(self):
899886
self.app = QApplication([])
900-
self.layout = get_empty_tiling_layout(12)
887+
self.layout = QTilingLayout(max_span=12)
901888
self.ws = [Widget(i) for i in range(29)]
902889
self.layout.addWidget(self.ws[0], 0, 0, 2, 2)
903890
self.layout.addWidget(self.ws[1], 0, 2, 3, 2)
@@ -1001,7 +988,7 @@ class EmptyBlockTestCase(unittest.TestCase):
1001988
# └───────────────────────┘
1002989
def setUp(self):
1003990
self.app = QApplication([])
1004-
self.layout = get_empty_tiling_layout(6)
991+
self.layout = QTilingLayout(max_span=6)
1005992
self.ws = [Widget(i) for i in range(8)]
1006993
self.layout.addWidget(self.ws[0], 0, 0, 1, 5)
1007994
self.layout.addWidget(self.ws[1], 1, 0, 4, 1)
@@ -1059,7 +1046,7 @@ class NeighbourTestCase(unittest.TestCase):
10591046
# └───────────────────────────────────┘
10601047
def setUp(self):
10611048
self.app = QApplication([])
1062-
self.layout = get_empty_tiling_layout(9)
1049+
self.layout = QTilingLayout(max_span=9)
10631050
self.ws = [Widget(i) for i in range(19)]
10641051
self.layout.addWidget(self.ws[0], 0, 0, 1, 2)
10651052
self.layout.addWidget(self.ws[1], 0, 2, 1, 3)

src/tilinglayout.py

+22-21
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@ def __init__(self, state, widget, operation):
5151

5252
class QTilingLayout(QGridLayout):
5353

54-
def __init__(self, widget, *args, max_span=12, **kwargs):
54+
def __init__(self, *args, initial_widget=None, max_span=12, **kwargs):
5555
super().__init__(*args, **kwargs)
5656
self.max_span = max_span
57-
self.addWidget(widget, 0, 0, self.max_span, self.max_span)
57+
if initial_widget:
58+
self.addWidget(initial_widget, 0, 0, self.max_span, self.max_span)
5859

5960
def _is_point_inside_grid(self, row, col):
6061
"""Determines if the point is inside the layout."""
@@ -131,26 +132,26 @@ def _restore_state(self, prev_state):
131132
def remove_widget(self, widget):
132133
"""Removes a widget from the layout and fills the remaining space"""
133134
if self.count() == 1:
134-
raise SplitLimitException
135-
136-
original_state = self._get_state()
137-
try:
138-
widget_pos = self._get_item_position(widget, False)
139-
transpose = widget_pos[3] < widget_pos[2]
140-
ib = self._get_independent_block(widget, transpose)
141135
self.removeWidget(widget)
142-
widget.hide()
143-
widgets = list(ib.get_widgets())
144-
self._rearrange_widgets(widgets, ib)
145-
# Rearrange widgets in the opposite direction as the resizing
146-
# results in some widgets sharing the space better with their
147-
# neighbours
148-
whole_block = CriticalBlock(self, not transpose, 0, 0,
149-
self.max_span, self.max_span)
150-
self._rearrange_widgets(list(whole_block.get_widgets()),
151-
whole_block)
152-
except Exception as e:
153-
raise SplitException(original_state, widget, 'remove') from e
136+
else:
137+
original_state = self._get_state()
138+
try:
139+
widget_pos = self._get_item_position(widget, False)
140+
transpose = widget_pos[3] < widget_pos[2]
141+
ib = self._get_independent_block(widget, transpose)
142+
self.removeWidget(widget)
143+
widget.hide()
144+
widgets = list(ib.get_widgets())
145+
self._rearrange_widgets(widgets, ib)
146+
# Rearrange widgets in the opposite direction as the resizing
147+
# results in some widgets sharing the space better with their
148+
# neighbours
149+
whole_block = CriticalBlock(self, not transpose, 0, 0,
150+
self.max_span, self.max_span)
151+
self._rearrange_widgets(list(whole_block.get_widgets()),
152+
whole_block)
153+
except Exception as e:
154+
raise SplitException(original_state, widget, 'remove') from e
154155

155156
def hsplit(self, old_widget, new_widget, put_before=False):
156157
"""Splits the specified widget horizontally.

0 commit comments

Comments
 (0)