aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/tests/QtWidgets/qlayout_test.py
blob: cc41f78b15c456059aefc74498b09c32fce0898f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

import gc
import os
import sys
import unittest

from pathlib import Path
sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from init_paths import init_test_paths
init_test_paths(False)

from helper.usesqapplication import UsesQApplication
from PySide6.QtCore import QTimer
from PySide6.QtWidgets import (QFormLayout, QHBoxLayout, QLayout, QPushButton,
                               QSpacerItem, QWidget, QWidgetItem)


class MyLayout(QLayout):
    def __init__(self, parent=None):
        QLayout.__init__(self, parent)
        self._list = []

    def addItem(self, item):
        self.add(item)

    def addWidget(self, widget):
        self.add(QWidgetItem(widget))

    def itemAt(self, index):
        if index < len(self._list):
            return self._list[index]

        return None

    def count(self):
        return len(self._list)

    def add(self, item):
        self._list.append(item)


class MissingItemAtLayout(QLayout):
    def __init__(self, parent=None):
        QLayout.__init__(self, parent)
        self._list = []

    def addItem(self, item):
        self.add(item)

    def addWidget(self, widget):
        self.add(QWidgetItem(widget))

    def count(self):
        return len(self._list)

    def add(self, item):
        self._list.append(item)

# Test if a layout implemented in python, the QWidget.setLayout works
# fine because this implement som layout functions used in glue code of
# QWidget, then in c++ when call a virtual function this need call the QLayout
# function implemented in python


class QLayoutTest(UsesQApplication):
    @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
    def testOwnershipTransfer(self):
        b = QPushButton("teste")
        l = MyLayout()

        l.addWidget(b)

        self.assertEqual(sys.getrefcount(b), 2)

        w = QWidget()

        # transfer ref
        w.setLayout(l)

        self.assertEqual(sys.getrefcount(b), 3)

    @unittest.skipUnless(hasattr(sys, "getrefcount"), f"{sys.implementation.name} has no refcount")
    def testReferenceTransfer(self):
        b = QPushButton("teste")
        l = QHBoxLayout()

        # keep ref
        l.addWidget(b)
        self.assertEqual(sys.getrefcount(b), 3)

        w = QWidget()

        # transfer ref
        w.setLayout(l)

        self.assertEqual(sys.getrefcount(b), 3)

        # release ref
        del w

        self.assertEqual(sys.getrefcount(b), 2)

    def testMissingFunctions(self):
        w = QWidget()
        b = QPushButton("test")
        l = MissingItemAtLayout()

        l.addWidget(b)

        self.assertRaises(RuntimeError, w.setLayout, l)

    def testQFormLayout(self):
        w = QWidget()
        formLayout = QFormLayout()
        spacer = QSpacerItem(100, 30)
        formLayout.setItem(0, QFormLayout.SpanningRole, spacer)
        w.setLayout(formLayout)
        w.show()
        QTimer.singleShot(10, w.close)
        self.app.exec()
        del w
        # PYSIDE-535: Need to collect garbage in PyPy to trigger deletion
        gc.collect()
        # PYSIDE-535: Why do I need to do it twice, here?
        gc.collect()
        self.assertRaises(RuntimeError, spacer.isEmpty)

    def testConstructorProperties(self):
        """PYSIDE-1986, test passing properties to the constructor of
           QHBoxLayout, which does not have default arguments."""
        layout = QHBoxLayout(objectName="layout", spacing=30)
        self.assertEqual(layout.spacing(), 30)
        self.assertEqual(layout.objectName(), "layout")


if __name__ == '__main__':
    unittest.main()