MauiKit Controls

SplitViewItem.qml
1// Copyright 2018-2020 Camilo Higuita <milo.h@aol.com>
2// Copyright 2018-2020 Nitrux Latinoamericana S.C.
3//
4// SPDX-License-Identifier: GPL-3.0-or-later
5
6
7import QtQuick
8import QtQuick.Controls
9import QtQml.Models
10import QtQuick.Effects
11
12import org.mauikit.controls as Maui
13
14/**
15 * @inherit QtQuick.Controls.Pane
16 * @brief An item to be used as a view container for the MauiKit SplitView.
17 * <a href="https://doc.qt.io/qt-6/qml-qtquick-controls-pane.html">This controls inherits from QQC2 Pane, to checkout its inherited properties refer to the Qt Docs.</a>
18 * This is the preferred control to use when adding a new view into the SplitView, since it follows the Maui Style HIG.
19 * @see SplitView
20 *
21 * @note When this element is being resized by the SplitView handle, and reaches the minimum width, an action to close the view is then suggested and triggered if the pressed event of the handle is released at that minimum width.
22 */
23Pane
24{
25 id: control
26
27 Maui.Theme.colorSet: Maui.Theme.Window
28 Maui.Theme.inherit: false
29
30 /**
31 * @brief By default the children content of this item needs to be positioned manually.
32 * @property list<QtObject> SplitViewItem::content
33 */
34 default property alias content: _container.data
35
36 /**
37 * @brief The index of this view in the SplitView control.
38 */
39 readonly property int splitIndex : ObjectModel.index
40
41 /**
42 * @brief The minimum width of this view when resizing the SplitView.
43 * By default this is set to a fixed value of `200`.
44 */
45 property int minimumWidth : 200
46
47 /**
48 * @brief The minimum height of this view when resizing the SplitView.
49 * By default this is set to a fixed value of `100`.
50 */
51 property int minimumHeight : 100
52
53 /**
54 * @brief Whether the style of this view will be more compact. A compact style has not border corners or styling.
55 * While a non-compact mode means there is more than on view in the parent SplitView and the views will have rounded corners.
56 * This is `true` for mobile devices and one there is a single item in the SplitView.
57 */
58 readonly property bool compact : Maui.Handy.isMobile || (SplitView.view.count === 1 || SplitView.view.visibleChildren.length <= 1)
59
60 /**
61 * @brief Allow to close the split view item by resizing to the minimum size.
62 * @note A popup dialog will be display to confirm the action
63 * By default this is set to `!Maui.Handy.isMobile`
64 */
65 property bool autoClose : true
66
67 SplitView.fillHeight: true
68 SplitView.fillWidth: true
69
70 SplitView.preferredHeight: SplitView.view.orientation === Qt.Vertical ? SplitView.view.height / (SplitView.view.count) : SplitView.view.height
71 SplitView.minimumHeight: SplitView.view.orientation === Qt.Vertical ? minimumHeight : 0
72
73 SplitView.preferredWidth: SplitView.view.orientation === Qt.Horizontal ? SplitView.view.width / (SplitView.view.count) : SplitView.view.width
74 SplitView.minimumWidth: SplitView.view.orientation === Qt.Horizontal ? minimumWidth : 0
76 // clip: SplitView.view.orientation === Qt.Vertical && SplitView.view.count === 2 && splitIndex > 0
77
78 padding: compact ? 0 : Maui.Style.contentMargins
79 leftPadding: SplitView.view.orientation === Qt.Horizontal && splitIndex === 1 && SplitView.view.count > 1 ? padding/2 : padding
80 rightPadding: SplitView.view.orientation === Qt.Horizontal && splitIndex === 0 && SplitView.view.count > 1 ? padding/2 : padding
81
82 bottomPadding: SplitView.view.orientation === Qt.Vertical && splitIndex === 0 && SplitView.view.count > 1 ? padding/2 : padding
83
84 topPadding: SplitView.view.orientation === Qt.Vertical && splitIndex === 1 && SplitView.view.count > 1 ? padding/2 : padding
85
86 Behavior on padding
87 {
88 NumberAnimation
89 {
90 duration: Maui.Style.units.shortDuration
91 easing.type: Easing.InQuad
92 }
93 }
94
95 contentItem: Item
96 {
97 state: control.compact ? "compactBadge" : "uncompactBadge"
98
99 id: _parent
100 Item
101 {
102 id: _content
103 anchors.fill: parent
104
105 Item
106 {
107 id: _container
108 anchors.fill: parent
109 }
110
111 Loader
112 {
113 id: _closeLoader
114 asynchronous: true
115 anchors.fill: parent
116 active: (control.SplitView.view.resizing && control.autoClose)
117 visible: active
118 sourceComponent: Rectangle
119 {
120 color: Maui.Theme.backgroundColor
121 opacity: control.SplitView.view.orientation === Qt.Vertical ? (control.minimumHeight) / control.height : (control.minimumWidth) / control.width
122
123 Maui.Chip
124 {
125 anchors.centerIn: parent
126 opacity: control.SplitView.view.orientation === Qt.Vertical ? (control.minimumHeight) / control.height : (control.minimumWidth) / control.width
127 scale: opacity * 1
128
129 Maui.Theme.backgroundColor: Maui.Theme.negativeTextColor
130 label.text: i18nd("mauikit", "Close")
131 }
132 }
133
134 function reset()
135 {
136 active = false
137 active = Qt.binding(()=>{ return (control.SplitView.view.resizing && control.autoClose) })
138 }
139 }
140
141 Loader
142 {
143 asynchronous: true
144 anchors.bottom: parent.bottom
145 anchors.left: parent.left
146 anchors.right: parent.right
147 height: 2
148 active: control.SplitView.view.currentIndex === splitIndex && control.SplitView.view.count > 1
149 visible: active
150 sourceComponent: Rectangle
151 {
152 color: Maui.Theme.highlightColor
153 }
154 }
155
156 MouseArea
157 {
158 anchors.fill: parent
159 propagateComposedEvents: true
160 preventStealing: false
161 cursorShape: undefined
162
163 onPressed: (mouse) =>
164 {
165 control.SplitView.view.currentIndex = control.splitIndex
166 mouse.accepted = false
167 }
168 }
169
170 layer.enabled: !control.compact
171 layer.smooth: true
172 layer.effect: MultiEffect
173 {
174 maskEnabled: true
175 maskThresholdMin: 0.5
176 maskSpreadAtMin: 1.0
177 maskSpreadAtMax: 0.0
178 maskThresholdMax: 1.0
179 maskSource: ShaderEffectSource
180 {
181 sourceItem: Rectangle
182 {
183 width: _container.width
184 height: _container.height
185 radius: Maui.Style.radiusV
186 }
187 }
188 }
189
190 Loader
191 {
192 id: _dialogLoader
193 active: control.autoClose
194
195 sourceComponent: Maui.InfoDialog
196 {
197 message: i18n("Are you sure you want to close the split view: '%1'?", control.Maui.Controls.title)
198 template.iconSource: "dialog-warning"
199 onAccepted: control.SplitView.view.closeSplit(control.splitIndex)
200 onRejected:
201 {
202 _closeLoader.reset()
203 close()
204 }
205
206 standardButtons: Dialog.Ok | Dialog.Cancel
207 }
208 }
209 }
210
211 Loader
212 {
213 id: _badgeLoader
214 asynchronous: true
215
216 active: control.Maui.Controls.badgeText && control.Maui.Controls.badgeText.length > 0 && control.visible
217 visible: active
218
219 sourceComponent: Maui.Badge
220 {
221 text: control.Maui.Controls.badgeText
222
223 padding: 2
224 font.pointSize: Maui.Style.fontSizes.tiny
225
226 Maui.Theme.colorSet: Maui.Theme.View
227 Maui.Theme.backgroundColor: Maui.Theme.negativeBackgroundColor
228 Maui.Theme.textColor: Maui.Theme.negativeTextColor
229
230 OpacityAnimator on opacity
231 {
232 from: 0
233 to: 1
234 duration: Maui.Style.units.longDuration
235 running: parent.visible
236 }
237
238 ScaleAnimator on scale
239 {
240 from: 0.5
241 to: 1
242 duration: Maui.Style.units.longDuration
243 running: parent.visible
244 easing.type: Easing.OutInQuad
245 }
246 }
247
248 transitions: Transition {
249 // smoothly reanchor myRect and move into new position
250 AnchorAnimation { duration: Maui.Style.units.longDuration }
251 }
252 }
253
254 states:[
255
256 State {
257 name: "compactBadge"
258
259 AnchorChanges {
260 target: _badgeLoader
261 anchors.right: _parent.right
262 anchors.top: _parent.top
263
264 anchors.horizontalCenter: undefined
265 anchors.verticalCenter: undefined
266 }
267 PropertyChanges {
268 target: _badgeLoader
269 anchors.margins: 10
270 anchors.verticalCenterOffset: 0
271 anchors.horizontalCenterOffset: 0
272 }
273 },
274
275 State {
276 name: "uncompactBadge"
277
278 AnchorChanges {
279 target: _badgeLoader
280 anchors.horizontalCenter: _parent.right
281 anchors.verticalCenter: _parent.top
282
283 anchors.right: undefined
284 anchors.top: undefined
285 }
286 PropertyChanges {
287 target: _badgeLoader
288 anchors.verticalCenterOffset: 10
289 anchors.horizontalCenterOffset: -5
290 anchors.margins: 0
291 }
292 }
293 ]
294 }
295
296 Connections
297 {
298 target: control.SplitView.view
299 function onResizingChanged()
300 {
301 if(control.SplitView.view.resizing || !control.autoClose)
302 return
303
304 if(control.SplitView.view.orientation === Qt.Horizontal && control.width === control.minimumWidth)
305 {
306 _dialogLoader.item.open()
307 return
308 }
309
310 if(control.SplitView.view.orientation === Qt.Vertical && control.height === control.minimumHeight)
311 {
312 _dialogLoader.item.open()
313 return
314 }
315 }
316 }
317
318 /**
319 * @brief Forces to focus this item in the SplitView, and marks it as the current view.
320 */
321 function focusSplitItem()
322 {
323 control.SplitView.view.currentIndex = control.splitIndex
324 control.SplitView.view.itemAt(control.splitIndex).forceActiveFocus()
325 }
326}
bool compact
Whether the style of this view will be more compact.
int splitIndex
The index of this view in the SplitView control.
An extension to the QQC2 SplitView control, adding some extra functionality.
Definition SplitView.qml:44
QString i18nd(const char *domain, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QAction * close(const QObject *recvr, const char *slot, QObject *parent)
QString name(StandardAction id)
KGuiItem reset()
QString label(StandardShortcut id)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 31 2025 12:11:16 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.