MauiKit Controls

ToolActions.qml
1import QtQuick
2import QtQuick.Controls
3import QtQuick.Layouts
4import QtQml
5
6import org.mauikit.controls 1.3 as Maui
7
8/**
9 * @inherit QtQuick.Controls.Control
10 * @brief A set of grouped action visually joined together.
11 *
12 * <a href="https://doc.qt.io/qt-6/qml-qtquick-controls-control.html">This control inherits from QQC2 Control, to checkout its inherited properties refer to the Qt Docs.</a>
13 *
14 * The set actions can be checkable and auto-exclusive or not.
15 *
16 * @image html Misc/toolactions.png "[1] Non-checkable. [2] Checkable non-auto-exclusive. [3] Checkable and autoexclusive"
17 *
18 * @section features Features
19 * This control supports checkable and non-checkable actions. Also auto-exclusive and non-auto-exclusive actions.
20 *
21 * When enabling the `autoExclusive` property, then only one action in the group can be marked as checked at the time.
22 *
23 * There is also the option to collapse the actions into a single button with a popup menu where the actions are listed, this is useful when the available space changes and the control needs to be made more compact to save space.
24 *
25 * @image html Misc/toolactions2.png "The collapsed actions into a menu"
26 *
27 * If only two actions are added and marked as auto-exclusive, then this control has the option to enable a `cyclic` behavior, which means that toggling one button will activate the next action in line and cyclic around.
28 * @see canCyclic
29 * @see cyclic
30 *
31 * Heres a example of how to achieve such behavior:
32 * @code
33 * Maui.ToolActions
34 * {
35 * id: _actions
36 * checkable: true
37 * autoExclusive: true
38 * cyclic: true //enable the cyclic behavior
39 * expanded: false //the cyclic behavior needs to be in the collapsed mode
40 *
41 * property int currentAction: 0 //here we keep the state for the current action checked
42 *
43 * Action
44 * {
45 * id: _action1
46 * icon.name: "view-list-details"
47 * checked: _actions.currentAction === 0
48 * onTriggered:
49 * {
50 * _actions.currentAction = 0
51 * }
52 * }
53 *
54 * Action
55 * {
56 * id: _action2
57 * icon.name: "view-list-icons"
58 * checked: _actions.currentAction === 1
59 * onTriggered:
60 * {
61 * _actions.currentAction = 1
62 * }
63 * }
64 * }
65 * @endcode
66 *
67 * @code
68 * Maui.ToolActions
69 * {
70 * checkable: true
71 * autoExclusive: true
72 *
73 * Action
74 * {
75 * text: "Pick"
76 * }
77 *
78 * Action
79 * {
80 * text: "Only"
81 * }
82 *
83 * Action
84 * {
85 * text: "One"
86 * }
87 * }
88 * @endcode
89 *
90 * <a href="https://invent.kde.org/maui/mauikit/-/blob/qt6-2/examples/ToolActions.qml">You can find a more complete example at this link.</a>
91 */
92Control
93{
94 id: control
95
96 implicitWidth: implicitContentWidth + leftPadding + rightPadding
97 implicitHeight: implicitContentHeight + topPadding + bottomPadding
98
99 opacity: enabled ? 1 : 0.5
100
101 spacing: 2
102 padding: 0
104 Maui.Theme.colorSet: Maui.Theme.Button
105 Maui.Theme.inherit: false
106
107 /**
108 * @brief The list of QQC2 Action to be listed. These can be declared a children elements of this control.
109 */
110 default property list<Action> actions
111
112 /**
113 * @brief Whether this control should only allow one action to be checked at the time.
114 * By default this is set to `true`
115 */
116 property bool autoExclusive: true
117
118 /**
119 * @brief Whether the action button can be checked. If enabled, then the state will be styled accordingly.
120 * @By default this is set to `true`.
121 */
122 property bool checkable: true
124 /**
125 * @brief Options on how to display the button text and icon.
126 * Available options are:
127 * - ToolButton.IconOnly
128 * - ToolButton.TextBesideIcon
129 * - ToolButton.TextOnly
130 * - ToolButton.TextUnderIcon
131 * By default this is set to `ToolButton.TextBesideIcon`
132 */
133 property int display: ToolButton.TextBesideIcon
134
135 /**
136 * @brief Whether two action can be triggered in a cyclic manner. So one press will activate the next action and then cycle around again.
137 * @see canCyclic
138 * By default this is set to `false`
139 */
140 property bool cyclic: false
141
142 /**
143 * @brief Whether the `cyclic` behavior can be activated.
144 * For it to be possible, the conditions are: only two actions and those must be auto-exclusive.
145 * @see cyclic
146 * @see autoExclusive
147 * @see count
148 */
149 readonly property bool canCyclic : control.cyclic && control.count === 2 && control.autoExclusive
150
151 /**
152 * @brief Whether the style of this control should be styled as flat.
153 * By default this is set to `false`.
154 */
155 property bool flat : false
156
157 /**
158 * @brief The total amount of actions declared.
159 */
160 readonly property int count : actions.length
161
162
163 /**
164 * @brief Whether the control should display all the actions as buttons in a row, or to collapse them into a popup menu.
165 * By default this is set to `true`.
166 */
167 property bool expanded : true
168
169 /**
170 * @brief The icon name to be used in the button that opens the menu popup, when the view is collapsed.
171 * By default this is set to `application-menu`.
172 */
173 property string defaultIconName: "application-menu"
174
175 /**
176 * @brief Forces to uncheck all the actions except the one action sent as the argument.
177 * @param except the action that should not be unchecked.
178 */
179 function uncheck(except)
180 {
181 for(var i in control.actions)
182 {
183 if(control.actions[i] === except)
184 {
185 continue
186 }
187
188 control.actions[i].checked = false
189 }
190 }
191
192 contentItem: Loader
193 {
194 id: _loader
195 asynchronous: true
196 sourceComponent: control.expanded ? _rowComponent : _buttonComponent
197 }
198
199 background: null
200
201 Component
202 {
203 id: _rowComponent
204
205 Row
206 {
207 id: _row
208 property int biggerHeight : 0
209 spacing: control.spacing
210
211 Behavior on width
212 {
213 enabled: Maui.Style.enableEffects
214
215 NumberAnimation
216 {
217 duration: Maui.Style.units.shortDuration
218 easing.type: Easing.InOutQuad
219 }
220 }
221
222 function calculateBiggerHeight()
223 {
224 var value = 0
225 for(var i in _row.children)
226 {
227 const height = _row.children[i].implicitHeight
228 if(height > value)
229 {
230 value = height
231 }
232 }
233
234 return value
235 }
236
237 Repeater
238 {
239 id: _repeater
240 model: control.actions
241
242 ToolButton
243 {
244 id: _actionButton
245 action : modelData
246 checkable: control.checkable || action.checkable
247
248 height: Math.max(implicitHeight, _row.biggerHeight)
249
250 onImplicitHeightChanged: _row.biggerHeight = _row.calculateBiggerHeight()
251
252 autoExclusive: control.autoExclusive
253 enabled: action.enabled
254
255 display: control.display
256
257 background: Maui.ShadowedRectangle
258 {
259 color: (checked || down ? Maui.Theme.highlightColor : ( hovered ? Maui.Theme.hoverColor : Maui.Theme.backgroundColor))
260 corners
261 {
262 topLeftRadius: index === 0 ? Maui.Style.radiusV : 0
263 topRightRadius: index === _repeater.count - 1 ? Maui.Style.radiusV : 0
264 bottomLeftRadius: index === 0 ? Maui.Style.radiusV : 0
265 bottomRightRadius: index === _repeater.count - 1 ? Maui.Style.radiusV : 0
266 }
267
268 Behavior on color
269 {
270 Maui.ColorTransition{}
271 }
272 }
273 }
274 }
275 }
276 }
277
278 Component
279 {
280 id: _buttonComponent
281
282 ToolButton
283 {
284 id: _defaultButtonIcon
285
286 property Action m_action
287
288 Component.onCompleted: _defaultButtonIcon.m_action = _defaultButtonIcon.buttonAction()
289
290 function buttonAction()
291 {
292 if(control.autoExclusive)
293 {
294 var currentAction
295 var actionIndex = -1
296 for(var i in control.actions)
297 {
298 console.log("Checking current action", i)
299 if(control.actions[i].checked)
300 {
301 actionIndex = i
302 currentAction = control.actions[actionIndex]
303 console.log("Found current action", i, actionIndex)
304 }
305 }
306
307 if(control.canCyclic)
308 {
309 actionIndex++
310
311 let m_index = actionIndex >= control.actions.length ? 0 : actionIndex
312 //
313 console.log("Setting current action at", m_index)
314 if(control.actions[m_index].enabled)
315 {
316 return control.actions[m_index];
317 }
318 }
319
320 return currentAction
321 }
322
323 return null
324 }
325
326 Row
327 {
328 visible: false
329 Repeater
330 {
331 model: control.actions
332 delegate: Item
333 {
334 property bool checked : modelData.checked
335 onCheckedChanged: _defaultButtonIcon.m_action = _defaultButtonIcon.buttonAction()
336 }
337 }
338 }
339
340 data: Maui.ContextualMenu
341 {
342 id: _menu
343
344 Repeater
345 {
346 model: control.autoExclusive && control.canCyclic ? undefined : control.actions
347
348 delegate: MenuItem
349 {
350 action: modelData
351 enabled: modelData.enabled
352 autoExclusive: control.autoExclusive
353 checkable: control.checkable || action.checkable
354 }
355 }
356 }
357
358 onClicked:
359 {
360 if(_defaultButtonIcon.m_action && control.canCyclic && control.autoExclusive)
361 {
362 console.log("Trigger next cyclic action", _defaultButtonIcon.m_action.icon.name)
363 // var previousAction = _defaultButtonIcon.action
364 _defaultButtonIcon.m_action.triggered()
365 _defaultButtonIcon.m_action = _defaultButtonIcon.buttonAction()
366
367 }else
368 {
369 if(!_menu.visible)
370 {
371 _menu.show(0, control.height, control)
372
373 }else
374 {
375 _menu.close()
376 }
377 }
378 }
379
380 icon.width: Maui.Style.iconSize
381 icon.height: Maui.Style.iconSize
382 icon.color: m_action ? (m_action.icon.color && m_action.icon.color.length ? m_action.icon.color : (pressed ? control.Maui.Theme.highlightColor : control.Maui.Theme.textColor)) : control.Maui.Theme.textColor
383
384 icon.name: m_action ? m_action.icon.name : control.defaultIconName
385 text: m_action ? m_action.text: ""
386
387 enabled: m_action ? m_action.enabled : true
388
389 subMenu: !control.canCyclic
390
391 display: control.display
392
393 checkable: control.checkable && (action ? action.checkable : false)
394
395 background: Rectangle
396 {
397 color: Maui.Theme.backgroundColor
398 radius: Maui.Style.radiusV
399
400 Behavior on color
401 {
402 Maui.ColorTransition{}
403 }
404 }
405 }
406 }
407}
QString name(StandardAction id)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 17 2024 11:56:16 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.