Warning, /frameworks/kirigami/autotests/tst_actiontoolbar.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 import QtQuick 0008 import QtQuick.Controls 0009 import QtTest 0010 import org.kde.kirigami as Kirigami 0011 0012 // TODO: Find a nicer way to handle this 0013 import "../src/controls/private" as KirigamiPrivate 0014 0015 TestCase { 0016 id: testCase 0017 name: "ActionToolBarTest" 0018 0019 width: 800 0020 height: 400 0021 visible: true 0022 0023 when: windowShown 0024 0025 // These buttons are required for getting the right metrics. 0026 // Since ActionToolBar bases all sizing on button sizes, we need to be able 0027 // to verify that layouting does the right thing. 0028 property ToolButton iconButton: KirigamiPrivate.PrivateActionToolButton { 0029 display: Button.IconOnly 0030 action: Kirigami.Action { icon.name: "document-new"; text: "Test Action" } 0031 font.pointSize: 10 0032 } 0033 property ToolButton textButton: KirigamiPrivate.PrivateActionToolButton { 0034 display: Button.TextOnly 0035 action: Kirigami.Action { icon.name: "document-new"; text: "Test Action" } 0036 font.pointSize: 10 0037 } 0038 property ToolButton textIconButton: KirigamiPrivate.PrivateActionToolButton { 0039 action: Kirigami.Action { icon.name: "document-new"; text: "Test Action" } 0040 font.pointSize: 10 0041 } 0042 property TextField textField: TextField { font.pointSize: 10 } 0043 0044 Component { 0045 id: single; 0046 Kirigami.ActionToolBar { 0047 font.pointSize: 10 0048 actions: [ 0049 Kirigami.Action { icon.name: "document-new"; text: "Test Action" } 0050 ] 0051 } 0052 } 0053 0054 Component { 0055 id: multiple 0056 Kirigami.ActionToolBar { 0057 font.pointSize: 10 0058 actions: [ 0059 Kirigami.Action { icon.name: "document-new"; text: "Test Action" }, 0060 Kirigami.Action { icon.name: "document-new"; text: "Test Action" }, 0061 Kirigami.Action { icon.name: "document-new"; text: "Test Action" } 0062 ] 0063 } 0064 } 0065 0066 Component { 0067 id: iconOnly 0068 Kirigami.ActionToolBar { 0069 display: Button.IconOnly 0070 font.pointSize: 10 0071 actions: [ 0072 Kirigami.Action { icon.name: "document-new"; text: "Test Action" }, 0073 Kirigami.Action { icon.name: "document-new"; text: "Test Action" }, 0074 Kirigami.Action { icon.name: "document-new"; text: "Test Action" } 0075 ] 0076 } 0077 } 0078 0079 Component { 0080 id: qtActions 0081 Kirigami.ActionToolBar { 0082 font.pointSize: 10 0083 actions: [ 0084 Action { icon.name: "document-new"; text: "Test Action" }, 0085 Action { icon.name: "document-new"; text: "Test Action" }, 0086 Action { icon.name: "document-new"; text: "Test Action" } 0087 ] 0088 } 0089 } 0090 0091 Component { 0092 id: mixed 0093 Kirigami.ActionToolBar { 0094 font.pointSize: 10 0095 actions: [ 0096 Kirigami.Action { icon.name: "document-new"; text: "Test Action"; displayHint: Kirigami.DisplayHint.IconOnly }, 0097 Kirigami.Action { icon.name: "document-new"; text: "Test Action" }, 0098 Kirigami.Action { icon.name: "document-new"; text: "Test Action"; displayComponent: TextField { } }, 0099 Kirigami.Action { icon.name: "document-new"; text: "Test Action"; displayHint: Kirigami.DisplayHint.AlwaysHide }, 0100 Kirigami.Action { icon.name: "document-new"; text: "Test Action"; displayHint: Kirigami.DisplayHint.KeepVisible } 0101 ] 0102 } 0103 } 0104 0105 function test_layout_data() { 0106 return [ 0107 // One action 0108 // Full window width, should just display a toolbutton 0109 { tag: "single_full", component: single, width: testCase.width, expected: testCase.textIconButton.width }, 0110 // Small width, should display the overflow button 0111 { tag: "single_min", component: single, width: 50, expected: testCase.iconButton.width }, 0112 // Half window width, should display a single toolbutton 0113 { tag: "single_half", component: single, width: testCase.width / 2, expected: testCase.textIconButton.width }, 0114 // Multiple actions 0115 // Full window width, should display as many buttons as there are actions 0116 { tag: "multi_full", component: multiple, width: testCase.width, 0117 expected: testCase.textIconButton.width * 3 + Kirigami.Units.smallSpacing * 2 }, 0118 // Small width, should display just the overflow button 0119 { tag: "multi_min", component: multiple, width: 50, expected: testCase.iconButton.width }, 0120 // Half window width, should display one action and overflow button 0121 { tag: "multi_small", component: multiple, 0122 width: testCase.textIconButton.width * 2 + testCase.iconButton.width + Kirigami.Units.smallSpacing * 3, 0123 expected: testCase.textIconButton.width * 2 + testCase.iconButton.width + Kirigami.Units.smallSpacing * 2 }, 0124 // Multiple actions, display set to icon only 0125 // Full window width, should display as many icon-only buttons as there are actions 0126 { tag: "icon_full", component: iconOnly, width: testCase.width, 0127 expected: testCase.iconButton.width * 3 + Kirigami.Units.smallSpacing * 2 }, 0128 // Small width, should display just the overflow button 0129 { tag: "icon_min", component: iconOnly, width: 50, expected: testCase.iconButton.width }, 0130 // Quarter window width, should display one icon-only button and the overflow button 0131 { tag: "icon_small", component: iconOnly, width: testCase.iconButton.width * 4, 0132 expected: testCase.iconButton.width * 3 + Kirigami.Units.smallSpacing * 2 }, 0133 // QtQuick Controls actions 0134 // Full window width, should display as many buttons as there are actions 0135 { tag: "qt_full", component: qtActions, width: testCase.width, 0136 expected: testCase.textIconButton.width * 3 + Kirigami.Units.smallSpacing * 2 }, 0137 // Small width, should display just the overflow button 0138 { tag: "qt_min", component: qtActions, width: 50, expected: testCase.iconButton.width }, 0139 // Half window width, should display one action and overflow button 0140 { tag: "qt_small", component: qtActions, 0141 width: testCase.textIconButton.width * 2 + testCase.iconButton.width + Kirigami.Units.smallSpacing * 3, 0142 expected: testCase.textIconButton.width * 2 + testCase.iconButton.width + Kirigami.Units.smallSpacing * 2 }, 0143 // Mix of different display hints, displayComponent and normal actions. 0144 // Full window width, should display everything, but one action is collapsed to icon 0145 { tag: "mixed", component: mixed, width: testCase.width, 0146 expected: testCase.textIconButton.width * 2 + testCase.iconButton.width * 2 + testCase.textField.width + Kirigami.Units.smallSpacing * 4 } 0147 ] 0148 } 0149 0150 // Test layouting of ActionToolBar 0151 // 0152 // ActionToolBar has some pretty complex behaviour, which generally boils down to it trying 0153 // to fit as many visible actions as possible and placing the hidden ones in an overflow menu. 0154 // This test, along with the data above, verifies that that this behaviour is correct. 0155 function test_layout(data) { 0156 var toolbar = createTemporaryObject(data.component, testCase, {width: data.width}) 0157 0158 verify(toolbar) 0159 verify(waitForRendering(toolbar)) 0160 0161 while (toolbar.visibleWidth == 0) { 0162 // The toolbar creates its delegates asynchronously during "idle 0163 // time", this means we need to wait for a bit so the toolbar has 0164 // the time to do that. As long as it has not finished creation, the 0165 // toolbar will have a visibleWidth of 0, so we can use that to 0166 // determine when it is done. 0167 wait(50) 0168 } 0169 0170 compare(toolbar.visibleWidth, data.expected) 0171 } 0172 0173 Component { 0174 id: heightMode 0175 0176 Kirigami.ActionToolBar { 0177 id: heightModeToolBar 0178 font.pointSize: 10 0179 0180 property real customHeight: 50 0181 0182 actions: [ 0183 Kirigami.Action { 0184 displayComponent: Button { 0185 objectName: "tall" 0186 implicitHeight: heightModeToolBar.customHeight 0187 implicitWidth: 50 0188 } 0189 }, 0190 Kirigami.Action { 0191 displayComponent: Button { 0192 objectName: "short" 0193 implicitHeight: 25 0194 implicitWidth: 50 0195 } 0196 } 0197 ] 0198 } 0199 } 0200 0201 function getChild(toolbar, objectName) { 0202 let c = toolbar.children[0].children 0203 for (let i in c) { 0204 if (c[i].objectName === objectName) { 0205 return c[i] 0206 } 0207 } 0208 return -1 0209 } 0210 0211 function test_height() { 0212 var toolbar = createTemporaryObject(heightMode, testCase, {width: testCase.width}) 0213 0214 verify(toolbar) 0215 verify(waitForRendering(toolbar)) 0216 0217 while (toolbar.visibleWidth == 0) { 0218 // Same as above 0219 wait(50) 0220 } 0221 0222 compare(toolbar.implicitHeight, 50) 0223 compare(toolbar.height, 50) 0224 0225 toolbar.customHeight = 100 0226 0227 // Changing the delegate height will trigger the internal layout to 0228 // relayout, which is done in polish. This is not signaled to the 0229 // parent toolbar, so we need to wait on the contentItem here. 0230 verify(isPolishScheduled(toolbar.contentItem)) 0231 verify(waitForItemPolished(toolbar.contentItem)) 0232 0233 // Implicit height changes should propagate to the layout's height as 0234 // long as that doesn't have an explicit height set. 0235 compare(toolbar.implicitHeight, 100) 0236 compare(toolbar.height, 100) 0237 0238 // This should be the default, but make sure to set it regardless 0239 toolbar.heightMode = Kirigami.ToolBarLayout.ConstrainIfLarger 0240 toolbar.height = 50 0241 0242 // Find the actual child items so we can check their properties 0243 let t = getChild(toolbar, "tall"); 0244 let s = getChild(toolbar, "short"); 0245 0246 // waitForItemPolished doesn't wait long enough and waitForRendering 0247 // waits too long, so just wait an arbitrary amount of time... 0248 wait(50) 0249 0250 // ConstrainIfLarger should reduce the height of the first, but not touch the second 0251 compare(t.height, 50) 0252 compare(t.y, 0) 0253 compare(s.height, 25) 0254 compare(s.y, 13) // Should be centered and rounded 0255 0256 // AlwaysCenter should not touch any item's height, only make sure they are centered 0257 toolbar.heightMode = Kirigami.ToolBarLayout.AlwaysCenter 0258 0259 wait(50) 0260 0261 compare(t.height, 100) 0262 compare(t.y, -25) 0263 compare(s.height, 25) 0264 compare(s.y, 13) 0265 0266 // AlwaysFill should make sure each item has the same height as the toolbar 0267 toolbar.heightMode = Kirigami.ToolBarLayout.AlwaysFill 0268 0269 wait(50) 0270 0271 compare(t.height, 50) 0272 compare(t.y, 0) 0273 compare(s.height, 50) 0274 compare(s.y, 0) 0275 0276 // Unconstraining the toolbar should reset its height to the maximum 0277 // implicit height and set any children to that same value as heightMode 0278 // is still AlwaysFill. 0279 toolbar.height = undefined 0280 0281 wait(50) 0282 0283 compare(toolbar.height, 100) 0284 compare(t.height, 100) 0285 compare(s.height, 100) 0286 } 0287 }