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
22import QtQuick.Controls
23import QtQuick.Layouts
24
25import org.mauikit.controls 1.3 as Maui
26
27import "private" as Private
28
29/**
30 *
31 * @since org.mauikit.controls 1.2
32 *
33 * @brief Views switcher component.
34 *
35 * This controls inherits from MauiKit Page, to checkout its inherited properties refer to docs.
36 *
37 * 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.
38 *
39 * This component takes care of creating the button view-ports in its page header.
40 *
41 * Each child element represents a view - and each one should have the AppView 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:
42 * - AppView.title
43 * - AppView.iconName
44 * - AppView.badgeText
45 *
46 * The badge item is handled by a MauiKit Badge control.
47 * @see Badge
48 *
49 * @see AppView
50 *
51 * @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"
52 *
53 * @code
54 * AppViews
55 * {
56 * id: _page
57 * anchors.fill: parent
58 * Controls.showCSD: true
59 * headBar.forceCenterMiddleContent: true
60 *
61 * Rectangle
62 * {
63 * AppView.title: "View1"
64 * AppView.iconName: "love"
65 *
66 * color: "blue"
67 * }
68 *
69 * Rectangle
70 * {
71 * AppView.title: "View2"
72 * AppView.iconName: "folder"
73 * AppView.badgeText: "30"
74 * color: "pink"
75 * }
76 *
77 * Rectangle
78 * {
79 * AppView.title: "View3"
80 * AppView.iconName: "tag"
81 *
82 * color: "blue"
83 * }
84 * }
85 * @endcode
86 *
87 * @section notes Notes
88 *
89 * @subsection positioning Positioning & Behaviours
90 * 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.
91 *
92 * If a child-item or a "view" is hidden via the visible property, then it is also hidden for the view port buttons.
93 *
94 * 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.
95 * @see interactive
96 *
97 * @subsection performance Performance
98 * 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.
99 * @see AppViewLoader
100 *
101 * 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.
102 * @see maxViews
103 *
104 * @subsection inheritance Inheritance & Shortcuts
105 * 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.
106 * @see Page
107 *
108 * The first four [4] views can be navigated by using keyboard shortcuts: [Ctrl + 1] [Ctrl + 2] [Ctrl + 3] [Ctrl + 4]
109 *
110 * <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>
111 * @inherit org::mauikit::controls::Page
112 */
113Maui.Page
114{
115 id: control
117 /**
118 * @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 AppView attached properties.
119 * @see AppView
120 * The content layout is handled by a swipe view.
121 */
122 default property alias content: _swipeView.contentData
123
124 /**
125 * @brief The index number of the current view.
126 * @property int AppViews::currentIndex
127 */
128 property alias currentIndex : _swipeView.currentIndex
129
130 /**
131 * @brief The current item in the view.
132 * @property Item AppViews::currentItem
133 */
134 property alias currentItem : _swipeView.currentItem
135
136 /**
137 * @brief The total amount of items/views.
138 * @property int AppViews::count
139 */
140 property alias count : _swipeView.count
141
142 /**
143 * @brief Sets the views to be interactive by using touch gestures to flick between them.
144 * @property bool AppViews::interactive
145 */
146 property alias interactive : _swipeView.interactive
147
148 focus: true
149
150 /**
151 * @brief Maximum number of views to be shown in the view port buttons at the header bar.
152 * The rest of views buttons will be collapsed into a menu button.
153 * By default the maximum number is set to 4.
154 */
155 property int maxViews : 4
156
157 headBar.forceCenterMiddleContent: !isWide
158 headBar.middleContent: Loader
159 {
160 asynchronous: true
161 Layout.alignment: Qt.AlignCenter
162
163 sourceComponent: Private.ActionGroup
164 {
165 id: _actionGroup
166 currentIndex : _swipeView.currentIndex
167 display: ToolButton.TextUnderIcon
168 Binding on currentIndex
169 {
170 value: _swipeView.currentIndex
171 restoreMode: Binding.RestoreValue
172 }
173
174 onCurrentIndexChanged:
175 {
176 _swipeView.currentIndex = currentIndex
177 // _actionGroup.currentIndex = control.currentIndex
178 }
179
180 Component.onCompleted:
181 {
182 for(var i in _swipeView.contentChildren)
183 {
184 const obj = _swipeView.contentChildren[i]
185
186 if(obj.Maui.AppView.title || obj.Maui.AppView.iconName)
187 {
188 if(_actionGroup.items.length < control.maxViews)
189 {
190 _actionGroup.items.push(obj)
191 }else
192 {
193 _actionGroup.hiddenItems.push(obj)
194 }
195 }
196 }
197 }
198 }
199 }
200
201 SwipeView
202 {
203 id:_swipeView
204 anchors.fill: parent
205 interactive: false
206
207 onCurrentItemChanged:
208 {
209 currentItem.forceActiveFocus()
210 _listView.positionViewAtIndex(control.currentIndex , ListView.SnapPosition)
211 history.push(_swipeView.currentIndex)
212 }
213
214 Keys.onBackPressed:
215 {
216 control.goBack()
217 }
218
220 {
221 sequence: StandardKey.Back
222 onActivated: control.goBack()
223 }
224
225 background: null
226 padding: 0
227
228 contentItem: ListView
229 {
230 id: _listView
231 model: _swipeView.contentModel
232 interactive: _swipeView.interactive
233 currentIndex: _swipeView.currentIndex
234 spacing: _swipeView.spacing
235 orientation: _swipeView.orientation
236 snapMode: ListView.SnapOneItem
237 boundsBehavior: Flickable.StopAtBounds
238 clip: _swipeView.clip
239
240 preferredHighlightBegin: 0
241 preferredHighlightEnd: width
242
243 highlightRangeMode: ListView.StrictlyEnforceRange
244 highlightMoveDuration: 0
245 highlightFollowsCurrentItem: true
246 highlightResizeDuration: 0
247 highlightMoveVelocity: -1
248 highlightResizeVelocity: -1
249
250 maximumFlickVelocity: 4 * (_swipeView.orientation === Qt.Horizontal ? width : height)
251
252 property int lastPos: 0
253
254 onCurrentIndexChanged:
255 {
256 _listView.lastPos = _listView.contentX
257 }
258 }
259
260 Keys.enabled: true
261 // Keys.forwardTo:_listView
262 Keys.onPressed:
263 {
264 if((event.key == Qt.Key_1) && (event.modifiers & Qt.ControlModifier))
265 {
266 if(_swipeView.count > -1 )
267 {
268 _swipeView.currentIndex = 0
269 }
270 }
271
272 if((event.key == Qt.Key_2) && (event.modifiers & Qt.ControlModifier))
273 {
274 if(_swipeView.count > 0 )
275 {
276 _swipeView.currentIndex = 1
277 }
278 }
279
280 if((event.key == Qt.Key_3) && (event.modifiers & Qt.ControlModifier))
281 {
282 if(_swipeView.count > 1 )
283 {
284 _swipeView.currentIndex = 2
285 }
286 }
287
288 if((event.key == Qt.Key_4) && (event.modifiers & Qt.ControlModifier))
289 {
290 if(_swipeView.count > 2 )
291 {
292 _swipeView.currentIndex = 3
293 }
294 }
295 }
296 }
297
298 /**
299 * @brief The private object that handles the history workflow
300 * @warning This is a private property and can not be accesed
301 */
302 property QtObject history : QtObject
303 {
304 property var historyIndexes : []
305
306 function pop()
307 {
308 historyIndexes.pop()
309 return historyIndexes.pop()
310 }
311
312 function push(index)
313 {
314 historyIndexes.push(index)
315 }
316
317 function indexes()
318 {
319 return historyIndexes
320 }
321 }
322
323 /**
324 * @brief A quick function to request the control to go back to the previously visited view.
325 * A history of visited views is kept, and invoking this method will pop the history one by one .
326 */
327 function goBack()
328 {
329 _swipeView.setCurrentIndex(history.pop())
330 }
331
332}
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 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.