• Skip to content
  • Skip to link menu
Brand

API Documentation

  1. KDE API Reference
  2. Kirigami
  • KDE Home
  • Contact Us

Quick Links

Skip menu "Kirigami"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • File List
  • Related Pages

Class Picker

About

QtQuick plugins to build user interfaces based on the KDE UX guidelines

Maintainer
Marco Martin
Supported platforms
Android, Linux
Community
IRC: #plasma on Freenode
Mailing list: plasma-devel
Use with CMake
find_package(KF5Kirigami)
target_link_libraries(yourapp KF5::Kirigami)
Clone
git clone git://anongit.kde.org/kirigami1.git
Browse source
Kirigami on cgit.kde.org

Kirigami

  • src
  • controls
  • private
ActionButton.qml
1 /*
2  * Copyright 2015 Marco Martin <mart@kde.org>
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 Library 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 
20 import QtQuick 2.1
21 import QtQuick.Layouts 1.2
22 import QtGraphicalEffects 1.0
23 import org.kde.kirigami 1.0
24 
25 import "../templates/private"
26 
27 Item {
28  id: root
29  anchors {
30  left: parent.left
31  right: parent.right
32  bottom:parent.bottom
33  }
34  //smallSpacing for the shadow
35  height: button.height + Units.smallSpacing
36  clip: true
37 
38  //either Action or QAction should work here
39  property QtObject action: root.parent.parent ? root.parent.parent.mainAction : null
40  property QtObject leftAction: root.parent.parent ? root.parent.parent.leftAction : null
41  property QtObject rightAction: root.parent.parent ? root.parent.parent.rightAction : null
42 
43  onWidthChanged: button.x = root.width/2 - button.width/2
44 
45  transform: Translate {
46  id: translateTransform
47  }
48 
49  Item {
50  id: button
51 
52  anchors {
53  bottom: parent.bottom
54  bottomMargin: Units.smallSpacing
55  }
56  implicitWidth: implicitHeight + Units.iconSizes.smallMedium*3
57  implicitHeight: Units.iconSizes.large + Units.largeSpacing
58 
59 
60  onXChanged: {
61  if (mouseArea.pressed || edgeMouseArea.pressed || fakeContextMenuButton.pressed) {
62  if (globalDrawer && globalDrawer.enabled && globalDrawer.modal) {
63  globalDrawer.position = Math.min(1, Math.max(0, (x - root.width/2 + button.width/2)/globalDrawer.contentItem.width + mouseArea.drawerShowAdjust));
64  }
65  if (contextDrawer && contextDrawer.enabled && contextDrawer.modal) {
66  contextDrawer.position = Math.min(1, Math.max(0, (root.width/2 - button.width/2 - x)/contextDrawer.contentItem.width + mouseArea.drawerShowAdjust));
67  }
68  }
69  }
70 
71  MouseArea {
72  id: mouseArea
73  anchors.fill: parent
74 
75  visible: action != null || leftAction != null || rightAction != null
76  property bool internalVisibility: (applicationWindow === undefined || (applicationWindow().controlsVisible && applicationWindow().height > root.height*2)) && (root.action === null || root.action.visible === undefined || root.action.visible)
77  preventStealing: true
78  onInternalVisibilityChanged: {
79  showAnimation.running = false;
80  if (internalVisibility) {
81  showAnimation.to = 0;
82  } else {
83  showAnimation.to = button.height;
84  }
85  showAnimation.running = true;
86  }
87 
88  drag {
89  target: button
90  //filterChildren: true
91  axis: Drag.XAxis
92  minimumX: contextDrawer && contextDrawer.enabled && contextDrawer.modal ? 0 : root.width/2 - button.width/2
93  maximumX: globalDrawer && globalDrawer.enabled && globalDrawer.modal ? root.width : root.width/2 - button.width/2
94  }
95 
96  property var downTimestamp;
97  property int startX
98  property int startMouseY
99  property real drawerShowAdjust
100  property bool buttonPressedUnderMouse: false
101  property bool leftButtonPressedUnderMouse: false
102  property bool rightButtonPressedUnderMouse: false
103 
104  onPressed: {
105  //search if we have a page to set to current
106  if (applicationWindow !== undefined && applicationWindow().pageStack.currentIndex !== undefined) {
107  //search the button parent's parent, that is the page parent
108  //this will make the context drawer open for the proper page
109  applicationWindow().pageStack.currentIndex = root.parent.parent.parent.level;
110  }
111  downTimestamp = (new Date()).getTime();
112  startX = button.x + button.width/2;
113  startMouseY = mouse.y;
114  drawerShowAdjust = 0;
115  buttonPressedUnderMouse = mouse.x > buttonGraphics.x && mouse.x < buttonGraphics.x + buttonGraphics.width;
116  leftButtonPressedUnderMouse = !buttonPressedUnderMouse && leftAction && mouse.x < buttonGraphics.x;
117  rightButtonPressedUnderMouse = !buttonPressedUnderMouse && rightAction && mouse.x > buttonGraphics.x + buttonGraphics.width;
118  }
119  onReleased: {
120  //pixel/second
121  var x = button.x + button.width/2;
122  var speed = ((x - startX) / ((new Date()).getTime() - downTimestamp) * 1000);
123  drawerShowAdjust = 0;
124 
125  //project where it would be a full second in the future
126  if (globalDrawer && globalDrawer.modal && x + speed > Math.min(root.width/4*3, root.width/2 + globalDrawer.contentItem.width/2)) {
127  globalDrawer.open();
128  contextDrawer.close();
129  } else if (contextDrawer && x + speed < Math.max(root.width/4, root.width/2 - contextDrawer.contentItem.width/2)) {
130  if (contextDrawer && contextDrawer.modal) {
131  contextDrawer.open();
132  }
133  if (globalDrawer && globalDrawer.modal) {
134  globalDrawer.close();
135  }
136  } else {
137  if (globalDrawer && globalDrawer.modal) {
138  globalDrawer.close();
139  }
140  if (contextDrawer && contextDrawer.modal) {
141  contextDrawer.close();
142  }
143  }
144  //Don't rely on native onClicked, but fake it here:
145  //Qt.startDragDistance is not adapted to devices dpi in case
146  //of Android, so consider the button "clicked" when:
147  //*the button has been dragged less than a gridunit
148  //*the finger is still on the button
149  if (Math.abs((button.x + button.width/2) - startX) < Units.gridUnit &&
150  mouse.y > 0) {
151  var action;
152  if (buttonPressedUnderMouse) {
153  action = root.action;
154  } else if (leftButtonPressedUnderMouse) {
155  action = root.leftAction;
156  } else if (rightButtonPressedUnderMouse) {
157  action = root.rightAction;
158  }
159 
160  if (!action) {
161  return;
162  }
163 
164  //if an action has been assigned, trigger it
165  if (action && action.trigger) {
166  action.trigger();
167  }
168  }
169  }
170 
171  onPositionChanged: {
172  drawerShowAdjust = Math.min(0.3, Math.max(0, (startMouseY - mouse.y)/(Units.gridUnit*15)));
173  button.xChanged();
174  }
175  onPressAndHold: {
176  var action;
177  if (buttonPressedUnderMouse) {
178  action = root.action;
179  } else if (leftButtonPressedUnderMouse) {
180  action = root.leftAction;
181  } else if (rightButtonPressedUnderMouse) {
182  action = root.rightAction;
183  }
184 
185  if (!action) {
186  return;
187  }
188 
189  //if an action has been assigned, show a message like a tooltip
190  if (action && action.text) {
191  showPassiveNotification(action.text);
192  }
193  }
194  Connections {
195  target: globalDrawer
196  onPositionChanged: {
197  if ( globalDrawer && globalDrawer.modal && !mouseArea.pressed && !edgeMouseArea.pressed && !fakeContextMenuButton.pressed) {
198  button.x = globalDrawer.contentItem.width * globalDrawer.position + root.width/2 - button.width/2;
199  }
200  }
201  }
202  Connections {
203  target: contextDrawer
204  onPositionChanged: {
205  if (contextDrawer && contextDrawer.modal && !mouseArea.pressed && !edgeMouseArea.pressed && !fakeContextMenuButton.pressed) {
206  button.x = root.width/2 - button.width/2 - contextDrawer.contentItem.width * contextDrawer.position;
207  }
208  }
209  }
210 
211  NumberAnimation {
212  id: showAnimation
213  target: translateTransform
214  properties: "y"
215  duration: Units.longDuration
216  easing.type: mouseArea.internalVisibility == true ? Easing.InQuad : Easing.OutQuad
217  }
218  Item {
219  id: background
220  anchors {
221  fill: parent
222  }
223 
224  Rectangle {
225  id: buttonGraphics
226  radius: width/2
227  anchors.centerIn: parent
228  height: parent.height - Units.smallSpacing*2
229  width: height
230  visible: root.action
231  readonly property bool pressed: root.action && ((mouseArea.buttonPressedUnderMouse && mouseArea.pressed) || root.action.checked)
232  color: pressed ? Theme.highlightColor : Theme.backgroundColor
233 
234  Icon {
235  id: icon
236  source: root.action && root.action.iconName ? root.action.iconName : ""
237  selected: buttonGraphics.pressed
238  anchors {
239  fill: parent
240  margins: Units.smallSpacing
241  }
242  }
243  Behavior on color {
244  ColorAnimation {
245  duration: Units.longDuration
246  easing.type: Easing.InOutQuad
247  }
248  }
249  Behavior on x {
250  NumberAnimation {
251  duration: Units.longDuration
252  easing.type: Easing.InOutQuad
253  }
254  }
255  }
256  //left button
257  Rectangle {
258  id: leftButtonGraphics
259  z: -1
260  anchors {
261  left: parent.left
262  verticalCenter: parent.verticalCenter
263  }
264  radius: Units.smallSpacing
265  height: Units.iconSizes.medium + Units.smallSpacing * 2
266  width: height + (root.action ? Units.iconSizes.smallMedium : 0)
267  visible: root.leftAction
268 
269  readonly property bool pressed: root.leftAction && ((mouseArea.leftButtonPressedUnderMouse && mouseArea.pressed) || root.leftAction.checked)
270  color: pressed ? Theme.highlightColor : Theme.backgroundColor
271  Icon {
272  source: root.leftAction && root.leftAction.iconName ? root.leftAction.iconName : ""
273  width: height
274  selected: leftButtonGraphics.pressed
275  anchors {
276  left: parent.left
277  top: parent.top
278  bottom: parent.bottom
279  margins: Units.smallSpacing
280  }
281  }
282  }
283  //right button
284  Rectangle {
285  id: rightButtonGraphics
286  z: -1
287  anchors {
288  right: parent.right
289  verticalCenter: parent.verticalCenter
290  }
291  radius: Units.smallSpacing
292  height: Units.iconSizes.medium + Units.smallSpacing * 2
293  width: height + (root.action ? Units.iconSizes.smallMedium : 0)
294  visible: root.rightAction
295  readonly property bool pressed: root.rightAction && ((mouseArea.rightButtonPressedUnderMouse && mouseArea.pressed) || root.rightAction.checked)
296  color: pressed ? Theme.highlightColor : Theme.backgroundColor
297  Icon {
298  source: root.rightAction && root.rightAction.iconName ? root.rightAction.iconName : ""
299  width: height
300  selected: rightButtonGraphics.pressed
301  anchors {
302  right: parent.right
303  top: parent.top
304  bottom: parent.bottom
305  margins: Units.smallSpacing
306  }
307  }
308  }
309  }
310 
311  DropShadow {
312  anchors.fill: background
313  horizontalOffset: 0
314  verticalOffset: Units.smallSpacing/3
315  radius: Units.gridUnit / 3.5
316  samples: 16
317  color: Qt.rgba(0, 0, 0, 0.5)
318  source: background
319  }
320  }
321  }
322 
323  MouseArea {
324  id: fakeContextMenuButton
325  anchors {
326  right: edgeMouseArea.right
327  bottom: edgeMouseArea.bottom
328  margins: -1
329  }
330  drag {
331  target: button
332  //filterChildren: true
333  axis: Drag.XAxis
334  minimumX: contextDrawer && contextDrawer.enabled && contextDrawer.modal ? 0 : root.width/2 - button.width/2
335  maximumX: globalDrawer && globalDrawer.enabled && globalDrawer.modal ? root.width : root.width/2 - button.width/2
336  }
337  visible: root.parent.parent.actions.contextualActions.length > 0 && (applicationWindow === undefined || applicationWindow().wideScreen)
338 
339  width: Units.iconSizes.medium + Units.smallSpacing * 2
340  height: width
341 
342  Item {
343  opacity: 0.4
344  anchors {
345  fill:parent
346  margins: -Units.gridUnit
347  }
348  layer.enabled: true
349  Rectangle {
350  id: shadowRect
351  anchors {
352  fill: parent
353  margins: Units.gridUnit
354  }
355  color: "black"
356  }
357  FastBlur {
358  z: -1
359  anchors.fill: shadowRect
360  source: shadowRect
361  radius: Units.gridUnit
362  transparentBorder: true
363  }
364  Rectangle {
365  color: Theme.viewBackgroundColor
366  anchors {
367  fill:parent
368  margins: Units.gridUnit
369  }
370  }
371  }
372 
373  ContextIcon {
374  anchors.centerIn: parent
375  width: height
376  height: Units.iconSizes.smallMedium - Units.smallSpacing * 2
377  }
378 
379  onPressed: mouseArea.onPressed(mouse)
380  onReleased: {
381  var pos = root.mapFromItem(fakeContextMenuButton, mouse.x, mouse.y);
382  if (pos.x < root.width/2 || (!contextDrawer.opened && mouse.x > 0 && mouse.x < width)) {
383  contextDrawer.open();
384  } else if (contextDrawer.opened && mouse.x > 0 && mouse.x < width) {
385  contextDrawer.close();
386  }
387  if (globalDrawer.position > 0.5) {
388  globalDrawer.open();
389  } else {
390  globalDrawer.close();
391  }
392  }
393  }
394 
395  MouseArea {
396  id: edgeMouseArea
397  z:99
398  anchors {
399  left: parent.left
400  right: parent.right
401  bottom: parent.bottom
402  }
403  drag {
404  target: button
405  //filterChildren: true
406  axis: Drag.XAxis
407  minimumX: contextDrawer && contextDrawer.enabled && contextDrawer.modal ? 0 : root.width/2 - button.width/2
408  maximumX: globalDrawer && globalDrawer.enabled && globalDrawer.modal ? root.width : root.width/2 - button.width/2
409  }
410  height: Units.smallSpacing * 3
411 
412  onPressed: mouseArea.onPressed(mouse)
413  onPositionChanged: mouseArea.positionChanged(mouse)
414  onReleased: mouseArea.released(mouse)
415  }
416 }
org::kde::kirigami::Units::smallSpacing
int smallSpacing
units.smallSpacing is the amount of spacing that should be used around smaller UI elements...
Definition: controls/Units.qml:56
org::kde::kirigami::Units::longDuration
int longDuration
units.longDuration should be used for longer, screen-covering animations, for opening and closing of ...
Definition: controls/Units.qml:75
org::kde::kirigami::Units::largeSpacing
int largeSpacing
units.largeSpacing is the amount of spacing that should be used inside bigger UI elements, for example between an icon and the corresponding text.
Definition: controls/Units.qml:63
org::kde::kirigami::Theme
Definition: controls/Theme.qml:22
org::kde::kirigami::Units::gridUnit
int gridUnit
The fundamental unit of space that should be used for sizes, expressed in pixels. ...
Definition: controls/Units.qml:31
org::kde::kirigami::Units
Definition: controls/Units.qml:24
org::kde::kirigami::Units::iconSizes
QtObject iconSizes
units.iconSizes provides access to platform-dependent icon sizing
Definition: controls/Units.qml:49
This file is part of the KDE documentation.
Documentation copyright © 1996-2017 The KDE developers.
Generated on Fri Feb 17 2017 11:09:23 by doxygen 1.8.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal