Kirigami2

controls/templates/AbstractApplicationHeader.qml
1 /*
2  * SPDX-FileCopyrightText: 2015 Marco Martin <[email protected]>
3  *
4  * SPDX-License-Identifier: LGPL-2.0-or-later
5  */
6 
7 import QtQuick 2.7
8 import QtQuick.Layouts 1.2
9 import QtQuick.Controls 2.4 as QQC2
10 import org.kde.kirigami 2.14 as Kirigami
11 import "private"
12 
13 /**
14  * @brief An item that can be used as a title for the application.
15  *
16  * Scrolling the main page will make it taller or shorter (through the point of going away)
17  * It's a behavior similar to the typical mobile web browser addressbar
18  * the minimum, preferred and maximum heights of the item can be controlled with
19  * * minimumHeight: default is 0, i.e. hidden
20  * * preferredHeight: default is Units.gridUnit * 1.6
21  * * preferredHeight: default is Units.gridUnit * 3
22  *
23  * To achieve a titlebar that stays completely fixed just set the 3 sizes as the same
24  *
25  * @inherit QtQuick.Item
26  */
27 Item {
28  id: root
29  z: 90
30  property int minimumHeight: 0
31  property int preferredHeight: Math.max(...(Array.from(mainItem.children).map(elm => elm.implicitHeight))) + topPadding + bottomPadding
32  property int maximumHeight: Kirigami.Units.gridUnit * 3
33 
34  property int position: QQC2.ToolBar.Header
35 
36  property Kirigami.PageRow pageRow: __appWindow ? __appWindow.pageStack: null
37  property Kirigami.Page page: pageRow ? pageRow.currentItem : null
38 
39  default property alias contentItem: mainItem.data
40  readonly property int paintedHeight: headerItem.y + headerItem.height - 1
41 
42  property int leftPadding: 0
43  property int topPadding: 0
44  property int rightPadding: 0
45  property int bottomPadding: 0
46  property bool separatorVisible: true
47  // whether or not the header should be
48  // "pushed" back when scrolling using the
49  // touch screen
50  property bool hideWhenTouchScrolling: root.pageRow ? root.pageRow.globalToolBar.hideWhenTouchScrolling : false
51 
52  LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
53  LayoutMirroring.childrenInherit: true
54 
55  Kirigami.Theme.inherit: true
56 
57  // FIXME: remove
58  property QtObject __appWindow: typeof applicationWindow !== "undefined" ? applicationWindow() : null;
59  implicitHeight: preferredHeight
60  height: Layout.preferredHeight
61 
62  /**
63  * @brief This property holds the background item.
64  * @note the background will be automatically sized to fill the whole control
65  */
66  property Item background
67 
68  onBackgroundChanged: {
69  background.z = -1;
70  background.parent = headerItem;
71  background.anchors.fill = headerItem;
72  }
73 
74  Component.onCompleted: AppHeaderSizeGroup.items.push(this)
75 
76  onMinimumHeightChanged: implicitHeight = preferredHeight;
77  onPreferredHeightChanged: implicitHeight = preferredHeight;
78 
79  opacity: height > 0 ? 1 : 0
80 
81  onPageChanged: {
82  // NOTE: The Connections object doesn't work with attached properties signals, so we have to do this by hand
83  if (headerItem.oldPage) {
84  headerItem.oldPage.Kirigami.ColumnView.scrollIntention.disconnect(headerItem.scrollIntentHandler);
85  }
86  if (root.page) {
87  root.page.Kirigami.ColumnView.scrollIntention.connect(headerItem.scrollIntentHandler);
88  }
89  headerItem.oldPage = root.page;
90  }
91  Component.onDestruction: {
92  if (root.page) {
93  root.page.Kirigami.ColumnView.scrollIntention.disconnect(headerItem.scrollIntentHandler);
94  }
95  }
96 
97  NumberAnimation {
98  id: heightAnim
99  target: root
100  property: "implicitHeight"
101  duration: Kirigami.Units.longDuration
102  easing.type: Easing.InOutQuad
103  }
104  Connections {
105  target: __appWindow
106  function onControlsVisibleChanged() {
107  heightAnim.from = root.implicitHeight
108  heightAnim.to = __appWindow.controlsVisible ? root.preferredHeight : 0;
109  heightAnim.restart();
110  }
111  }
112 
113  Item {
114  id: headerItem
115  anchors {
116  left: parent.left
117  right: parent.right
118  bottom: !Kirigami.Settings.isMobile || root.position === QQC2.ToolBar.Header ? parent.bottom : undefined
119  top: !Kirigami.Settings.isMobile || root.position === QQC2.ToolBar.Footer ? parent.top : undefined
120  }
121 
122  height: __appWindow && __appWindow.reachableMode && __appWindow.reachableModeEnabled ? root.maximumHeight : (root.minimumHeight > 0 ? Math.max(root.height, root.minimumHeight) : Math.max(root.height, root.preferredHeight))
123 
124  function scrollIntentHandler(event) {
125  if (!root.hideWhenTouchScrolling) {
126  return
127  }
128 
129  if (root.pageRow
130  && root.pageRow.globalToolBar.actualStyle !== Kirigami.ApplicationHeaderStyle.TabBar
131  && root.pageRow.globalToolBar.actualStyle !== Kirigami.ApplicationHeaderStyle.Breadcrumb) {
132  return;
133  }
134  if (!root.page.flickable || (root.page.flickable.atYBeginning && root.page.flickable.atYEnd)) {
135  return;
136  }
137 
138  root.implicitHeight = Math.max(0, Math.min(root.preferredHeight, root.implicitHeight + event.delta.y))
139  event.accepted = root.implicitHeight > 0 && root.implicitHeight < root.preferredHeight;
140  slideResetTimer.restart();
141  if ((root.page.flickable instanceof ListView) && root.page.flickable.verticalLayoutDirection === ListView.BottomToTop) {
142  root.page.flickable.contentY -= event.delta.y;
143  }
144  }
145 
146  property Kirigami.Page oldPage
147 
148  Connections {
149  target: root.page ? root.page.globalToolBarItem : null
150  enabled: target
151  function onImplicitHeightChanged() {
152  root.implicitHeight = root.page.globalToolBarItem.implicitHeight;
153  }
154  }
155 
156  Timer {
157  id: slideResetTimer
158  interval: 500
159  onTriggered: {
160  if ((root.pageRow ? root.pageRow.wideMode : (__appWindow && __appWindow.wideScreen)) || !Kirigami.Settings.isMobile) {
161  return;
162  }
163  if (root.height > root.minimumHeight + (root.preferredHeight - root.minimumHeight)/2 ) {
164  heightAnim.to = root.preferredHeight;
165  } else {
166  heightAnim.to = root.minimumHeight;
167  }
168  heightAnim.from = root.implicitHeight
169  heightAnim.restart();
170  }
171  }
172 
173  Connections {
174  target: pageRow
175  function onCurrentItemChanged() {
176  if (!root.page) {
177  return;
178  }
179 
180  heightAnim.from = root.implicitHeight;
181  heightAnim.to = root.preferredHeight;
182 
183  heightAnim.restart();
184  }
185  }
186 
187  Item {
188  id: mainItem
189  clip: childrenRect.width > width
190  onChildrenChanged: {
191  Array.from(children).forEach(item => {
192  item.anchors.verticalCenter = this.verticalCenter;
193  })
194  }
195  anchors {
196  fill: parent
197  leftMargin: root.leftPadding
198  topMargin: root.topPadding
199  rightMargin: root.rightPadding
200  bottomMargin: root.bottomPadding
201  }
202  }
203  }
204 }
QTextStream & right(QTextStream &stream)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QTextStream & left(QTextStream &stream)
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
QTextStream & left(QTextStream &s)
QTextStream & right(QTextStream &s)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Jan 29 2023 04:11:03 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.