MauiKit Controls

AppViews.qml
1/*
2 * Copyright 2020 Camilo Higuita <milo.h@aol.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Library General Public License as
6 * published by the Free Software Foundation; either version 2, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20import QtQuick
21import QtQml
22
23import QtQuick.Controls
24import QtQuick.Layouts
25
26import org.mauikit.controls as Maui
27
28import "private" as Private
29
30/**
31 *
32 * @since org.mauikit.controls 1.2
33 *
34 * @brief Views switcher component.
35 *
36 * This controls inherits from MauiKit Page, to checkout its inherited properties refer to docs.
37 *
38 * The AppViews control presents a set of children items as views - into an horizontal swipe view, that does not jump around when resizing the application window and that takes care of different gestures and keyboard shortcuts for switching/navigating between the views.
39 *
40 * This component takes care of creating the button view-ports in its page header.
41 *
42 * Each child element represents a view - and each one should have the Controls metadata attached properties to give a title and icon to the view - so that it can be used as the text and icon for the view-port buttons. Some of the supported attached properties to be used are:
43 * - Controls.title
44 * - Controls.iconName
45 * - Controls.badgeText
46 *
47 * The badge item is handled by a MauiKit Badge control.
48 * @see Badge
49 *
50 * @see Controls
51 *
52 * @image html AppViews/viewports.png "The view ports as buttons in the header - the title is expanded for the current view on a wide mode, but compacted in a narrow space"
53 *
54 * @code
55 * AppViews
56 * {
57 * id: _page
58 * anchors.fill: parent
59 * Controls.showCSD: true
60 * headBar.forceCenterMiddleContent: true
61 *
62 * Rectangle
63 * {
64 * Controls.title: "View1"
65 * Controls.iconName: "love"
66 *
67 * color: "blue"
68 * }
69 *
70 * Rectangle
71 * {
72 * Controls.title: "View2"
73 * Controls.iconName: "folder"
74 * Controls.badgeText: "30"
75 * color: "pink"
76 * }
77 *
78 * Rectangle
79 * {
80 * Controls.title: "View3"
81 * Controls.iconName: "tag"
82 *
83 * color: "blue"
84 * }
85 * }
86 * @endcode
87 *
88 * @section notes Notes
89 *
90 * @subsection positioning Positioning & Behaviours
91 * There is not need to set the size or position of the child elements aka "views" - this component will take care of positioning them in the order they have been declared.
92 *
93 * If a child-item or a "view" is hidden via the visible property, then it is also hidden for the view port buttons.
94 *
95 * By default this component is not interactive with touch gestures, in order to not steal focus from other horizontal flickable elements - however you can enable it manually.
96 * @see interactive
97 *
98 * @subsection performance Performance
99 * Ideally do not add too many views, that are loaded simultaneously, since it will affect the application startup time. Instead you can load the views dinamically by using a Loader or the friend control AppViewLoader, which will take care of much of the loading task.
100 * @see AppViewLoader
101 *
102 * Besides taking longer to load - too many views - will also make the header bar too busy with the view-port buttons. This can also be tweaked by setting the maximum number of views visible - the other ones will be tucked away into an overflow menu.
103 * @see maxViews
104 *
105 * @subsection inheritance Inheritance & Shortcuts
106 * This component inherits for the MauiKit Page control, so you can customize it by using the same properties that can be applied to a Page, such as moving the header to the bottom, adding extra toolbars, enabling the pull-back behaviours, etc.
107 * @see Page
108 *
109 * The first four [4] views can be navigated by using keyboard shortcuts: [Ctrl + 1] [Ctrl + 2] [Ctrl + 3] [Ctrl + 4]
110 *
111 * <a href="https://invent.kde.org/maui/mauikit/-/blob/qt6-2/examples/AppViews.qml">You can find a more complete example at this link.</a>
112 * @inherit org::mauikit::controls::Page
113 */
114Maui.Page
115{
116 id: control
117
118 /**
119 * @brief All the child items declared will become part of the views. For each child element to be visible in the view port buttons, you need to use the Controls metadata attached properties.
120 * @see Controls
121 * The content layout is handled by a swipe view.
122 */
123 default property alias content: _swipeView.contentData
124
125 /**
126 * @brief The index number of the current view.
127 * @property int AppViews::currentIndex
128 */
129 property alias currentIndex : _swipeView.currentIndex
130
131 /**
132 * @brief The current item in the view.
133 * @property Item AppViews::currentItem
134 */
135 property alias currentItem : _swipeView.currentItem
137 /**
138 * @brief The total amount of items/views.
139 * @property int AppViews::count
140 */
141 property alias count : _swipeView.count
142
143 /**
144 * @brief Sets the views to be interactive by using touch gestures to flick between them.
145 * @property bool AppViews::interactive
146 */
147 property alias interactive : _swipeView.interactive
148
149 focus: true
150
151 /**
152 * @brief Maximum number of views to be shown in the view port buttons at the header bar.
153 * The rest of views buttons will be collapsed into a menu button.
154 * By default the maximum number is set to 4.
155 */
156 property int maxViews : 4
157
158 headBar.forceCenterMiddleContent: !isWide
159 headBar.middleContent: Loader
161 asynchronous: true
162 Layout.alignment: Qt.AlignCenter
163
164 sourceComponent: Private.ActionGroup
165 {
166 id: _actionGroup
167 currentIndex : _swipeView.currentIndex
168 display: ToolButton.TextUnderIcon
169 Binding on currentIndex
170 {
171 value: _swipeView.currentIndex
172 restoreMode: Binding.RestoreValue
173 }
174
175 onCurrentIndexChanged:
176 {
177 _swipeView.currentIndex = currentIndex
178 // _actionGroup.currentIndex = control.currentIndex
179 }
180
181 Component.onCompleted:
182 {
183 for(var i in _swipeView.contentChildren)
184 {
185 const obj = _swipeView.contentChildren[i]
186
187 if(obj.Maui.Controls.title || obj.Maui.Controls.iconName)
188 {
189 if(_actionGroup.items.length < control.maxViews)
190 {
191 _actionGroup.items.push(obj)
192 }else
193 {
194 _actionGroup.hiddenItems.push(obj)
195 }
196 }
197 }
198 }
199 }
200 }
201
202 SwipeView
203 {
204 id:_swipeView
205 anchors.fill: parent
206 interactive: false
207
208 onCurrentItemChanged:
209 {
210 currentItem.forceActiveFocus()
211 _listView.positionViewAtIndex(control.currentIndex , ListView.SnapPosition)
212 history.push(_swipeView.currentIndex)
213 }
214
215 Keys.onBackPressed:
216 {
217 control.goBack()
218 }
219
221 {
222 sequence: StandardKey.Back
223 onActivated: control.goBack()
224 }
225
226 background: null
227 padding: 0
228
229 contentItem: ListView
230 {
231 id: _listView
232 model: _swipeView.contentModel
233 interactive: _swipeView.interactive
234 currentIndex: _swipeView.currentIndex
235 spacing: _swipeView.spacing
236 orientation: _swipeView.orientation
237 snapMode: ListView.SnapOneItem
238 boundsBehavior: Flickable.StopAtBounds
239 clip: _swipeView.clip
240
241 preferredHighlightBegin: 0
242 preferredHighlightEnd: width
243
244 highlightRangeMode: ListView.StrictlyEnforceRange
245 highlightMoveDuration: 0
246 highlightFollowsCurrentItem: true
247 highlightResizeDuration: 0
248 highlightMoveVelocity: -1
249 highlightResizeVelocity: -1
250
251 maximumFlickVelocity: 4 * (_swipeView.orientation === Qt.Horizontal ? width : height)
252
253 property int lastPos: 0
254
255 onCurrentIndexChanged:
256 {
257 _listView.lastPos = _listView.contentX
258 }
259 }
260
261 Keys.enabled: true
262 // Keys.forwardTo:_listView
263 Keys.onPressed: (event) =>
264 {
265 if((event.key == Qt.Key_1) && (event.modifiers & Qt.ControlModifier))
266 {
267 if(_swipeView.count > -1 )
268 {
269 _swipeView.currentIndex = 0
270 }
271 }
272
273 if((event.key == Qt.Key_2) && (event.modifiers & Qt.ControlModifier))
274 {
275 if(_swipeView.count > 0 )
276 {
277 _swipeView.currentIndex = 1
278 }
279 }
280
281 if((event.key == Qt.Key_3) && (event.modifiers & Qt.ControlModifier))
282 {
283 if(_swipeView.count > 1 )
284 {
285 _swipeView.currentIndex = 2
286 }
287 }
288
289 if((event.key == Qt.Key_4) && (event.modifiers & Qt.ControlModifier))
290 {
291 if(_swipeView.count > 2 )
292 {
293 _swipeView.currentIndex = 3
294 }
295 }
296 }
297 }
298
299 /**
300 * @brief The private object that handles the history workflow
301 * @warning This is a private property and can not be accesed
302 */
303 property QtObject history : QtObject
304 {
305 property var historyIndexes : []
306
307 function pop()
308 {
309 historyIndexes.pop()
310 return historyIndexes.pop()
311 }
312
313 function push(index)
314 {
315 historyIndexes.push(index)
316 }
317
318 function indexes()
319 {
320 return historyIndexes
321 }
322 }
323
324 /**
325 * @brief A quick function to request the control to go back to the previously visited view.
326 * A history of visited views is kept, and invoking this method will pop the history one by one .
327 */
328 function goBack()
329 {
330 _swipeView.setCurrentIndex(history.pop())
331 }
332
333}
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Sep 6 2024 12:09:37 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.