Warning, /frameworks/kirigami/src/controls/GlobalDrawer.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 * SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 import QtQuick 2.12 0008 import QtQuick.Templates 2.3 as T2 0009 import QtQuick.Controls 2.2 as QQC2 0010 import QtQuick.Layouts 1.2 0011 import org.kde.kirigami 2.13 as Kirigami 0012 import "private" as P 0013 0014 /** 0015 * A specialized form of the QtQuick.Controls.Drawer intended for showing an application's 0016 * always-available global actions. Think of it like a mobile version of 0017 * a desktop application's menubar. 0018 * 0019 * Example usage: 0020 * @code{.qml} 0021 * import org.kde.kirigami 2.4 as Kirigami 0022 * 0023 * Kirigami.ApplicationWindow { 0024 * [...] 0025 * globalDrawer: Kirigami.GlobalDrawer { 0026 * actions: [ 0027 * Kirigami.Action { 0028 * text: "View" 0029 * icon.name: "view-list-icons" 0030 * Kirigami.Action { 0031 * text: "action 1" 0032 * } 0033 * Kirigami.Action { 0034 * text: "action 2" 0035 * } 0036 * Kirigami.Action { 0037 * text: "action 3" 0038 * } 0039 * }, 0040 * Kirigami.Action { 0041 * text: "Sync" 0042 * icon.name: "folder-sync" 0043 * } 0044 * ] 0045 * } 0046 * [...] 0047 * } 0048 * @endcode 0049 * @see <a href="https://develop.kde.org/docs/getting-started/kirigami/components-drawers/#global-drawer">Global Drawers in Kirigami</a> 0050 * @see <a href="https://develop.kde.org/hig/components/navigation/globaldrawer">Human Interface Guidelines on Global Drawers</a> 0051 * @see <a href="https://develop.kde.org/hig/patterns-command/drawer/#global-drawer">KDE Human Interface Guidelines' Short Introduction of Global Drawers</a> 0052 */ 0053 OverlayDrawer { 0054 id: root 0055 edge: Qt.application.layoutDirection === Qt.RightToLeft ? Qt.RightEdge : Qt.LeftEdge 0056 handleClosedIcon.source: null 0057 handleOpenIcon.source: null 0058 handleVisible: (modal || !drawerOpen) && (typeof(applicationWindow)===typeof(Function) && applicationWindow() ? applicationWindow().controlsVisible : true) && (!isMenu || Kirigami.Settings.isMobile) 0059 0060 enabled: !isMenu || Kirigami.Settings.isMobile 0061 0062 //BEGIN properties 0063 /** 0064 * @brief This property holds the title displayed at the top of the drawer. 0065 * @see kirigami::private::BannerImage::title 0066 * @property string title 0067 */ 0068 property alias title: bannerImage.title 0069 0070 /** 0071 * @brief This property holds an icon to be displayed alongside the title. 0072 * @see kirigami::private::BannerImage::titleIcon 0073 * @see Icon::source 0074 * @property var titleIcon 0075 */ 0076 property alias titleIcon: bannerImage.titleIcon 0077 0078 /** 0079 * @brief This property holds the banner image source. 0080 * @see kirigami::ShadowedImage::source 0081 * @property url bannerImageSource 0082 */ 0083 property alias bannerImageSource: bannerImage.source 0084 0085 /** 0086 * @brief This property holds the actions displayed in the drawer. 0087 * 0088 * The list of actions can be nested having a tree structure. 0089 * A tree depth bigger than 2 is discouraged. 0090 * 0091 * Example usage: 0092 * @code{.qml} 0093 * import org.kde.kirigami 2.4 as Kirigami 0094 * 0095 * Kirigami.ApplicationWindow { 0096 * [...] 0097 * globalDrawer: Kirigami.GlobalDrawer { 0098 * actions: [ 0099 * Kirigami.Action { 0100 * text: "View" 0101 * icon.name: "view-list-icons" 0102 * Kirigami.Action { 0103 * text: "action 1" 0104 * } 0105 * Kirigami.Action { 0106 * text: "action 2" 0107 * } 0108 * Kirigami.Action { 0109 * text: "action 3" 0110 * } 0111 * }, 0112 * Kirigami.Action { 0113 * text: "Sync" 0114 * icon.name: "folder-sync" 0115 * } 0116 * ] 0117 * } 0118 * [...] 0119 * } 0120 * @endcode 0121 * @property list<Action> actions 0122 */ 0123 property list<QtObject> actions 0124 0125 /** 0126 * @brief This property holds an item that will always be displayed at the top of the drawer. 0127 * 0128 * If the drawer contents can be scrolled, this item will stay still and won't scroll. 0129 * 0130 * @note This property is mainly intended for toolbars. 0131 * @since org.kde.kirigami 2.12 0132 */ 0133 property Item header 0134 0135 /** 0136 * @brief This property sets drawers banner visibility. 0137 * 0138 * If true, the banner area (which can contain an image, 0139 * an icon, and a title) will be visible. 0140 * 0141 * default: `the banner will be visible only on mobile platforms` 0142 * 0143 * @since org.kde.kirigami 2.12 0144 */ 0145 property bool bannerVisible: Kirigami.Settings.isMobile 0146 0147 /** 0148 * @brief This property holds items that are displayed above the actions. 0149 * 0150 * Example usage: 0151 * @code{.qml} 0152 * import org.kde.kirigami 2.4 as Kirigami 0153 * 0154 * Kirigami.ApplicationWindow { 0155 * [...] 0156 * globalDrawer: Kirigami.GlobalDrawer { 0157 * actions: [...] 0158 * topContent: [Button { 0159 * text: "Button" 0160 * onClicked: //do stuff 0161 * }] 0162 * } 0163 * [...] 0164 * } 0165 * @endcode 0166 * @property list<QtObject> topContent 0167 */ 0168 property alias topContent: topContent.data 0169 0170 /** 0171 * @brief This property holds items that are displayed under the actions. 0172 * 0173 * Example usage: 0174 * @code{.qml} 0175 * import org.kde.kirigami 2.4 as Kirigami 0176 * 0177 * Kirigami.ApplicationWindow { 0178 * [...] 0179 * globalDrawer: Kirigami.GlobalDrawer { 0180 * actions: [...] 0181 * Button { 0182 * text: "Button" 0183 * onClicked: //do stuff 0184 * } 0185 * } 0186 * [...] 0187 * } 0188 * @endcode 0189 * @note This is a `default` property. 0190 * @property list<QtObject> content 0191 */ 0192 default property alias content: mainContent.data 0193 0194 /** 0195 * @brief This property sets whether content items at the top should be shown. 0196 * when the drawer is collapsed as a sidebar. 0197 * 0198 * If you want to keep some items visible and some invisible, set this to 0199 * @c false and control the visibility/opacity of individual items, 0200 * binded to the OverlayDrawer.collapsed property. 0201 * 0202 * default: ``false`` 0203 * 0204 * @since org.kde.kirigami 2.5 0205 */ 0206 property bool showTopContentWhenCollapsed: false 0207 0208 /** 0209 * @brief This property sets whether content items at the bottom should be shown. 0210 * when the drawer is collapsed as a sidebar. 0211 * 0212 * If you want to keep some items visible and some invisible, set this to 0213 * @c false and control the visibility/opacity of individual items, 0214 * binded to the collapsed property 0215 * 0216 * default: ``false`` 0217 * 0218 * @see ::content 0219 * @since org.kde.kirigami 2.5 0220 */ 0221 property bool showContentWhenCollapsed: false 0222 0223 // TODO 0224 property bool showHeaderWhenCollapsed: false 0225 0226 /** 0227 * @brief This property sets whether activating a leaf action resets the 0228 * menu to show leaf's parent actions. 0229 * 0230 * A leaf action is an action without any child actions. 0231 * 0232 * default: ``true`` 0233 */ 0234 property bool resetMenuOnTriggered: true 0235 0236 /** 0237 * @brief This property points to the action acting as a submenu 0238 */ 0239 readonly property Action currentSubMenu: stackView.currentItem ? stackView.currentItem.current: null 0240 0241 /** 0242 * @brief This property sets whether the drawer becomes a menu on the desktop. 0243 * 0244 * default: ``false`` 0245 * 0246 * @since org.kde.kirigami 2.11 0247 */ 0248 property bool isMenu: false 0249 0250 /** 0251 * @brief This property sets the visibility of the collapse button 0252 * when the drawer collapsible. 0253 * 0254 * default: ``true`` 0255 * 0256 * @since org.kde.kirigami 2.12 0257 */ 0258 property bool collapseButtonVisible: true 0259 //END properties 0260 0261 /** 0262 * @brief This signal notifies that the banner has been clicked. 0263 */ 0264 signal bannerClicked() 0265 0266 /** 0267 * @brief This function reverts the menu back to its initial state 0268 */ 0269 function resetMenu() { 0270 stackView.pop(stackView.get(0, T2.StackView.DontLoad)); 0271 if (root.modal) { 0272 root.drawerOpen = false; 0273 } 0274 } 0275 0276 // rightPadding: !Kirigami.Settings.isMobile && mainFlickable.contentHeight > mainFlickable.height ? Kirigami.Units.gridUnit : Kirigami.Units.smallSpacing 0277 0278 Kirigami.Theme.colorSet: modal ? Kirigami.Theme.Window : Kirigami.Theme.View 0279 0280 onHeaderChanged: { 0281 if (header) { 0282 header.parent = headerContainer 0283 header.Layout.fillWidth = true; 0284 if (header.z === undefined) { 0285 header.z = 1; 0286 } 0287 if (header instanceof T2.ToolBar) { 0288 header.position = T2.ToolBar.Header 0289 } else if (header instanceof T2.TabBar) { 0290 header.position = T2.TabBar.Header 0291 } else if (header instanceof T2.DialogButtonBox) { 0292 header.position = T2.DialogButtonBox.Header 0293 } 0294 } 0295 } 0296 0297 contentItem: QQC2.ScrollView { 0298 id: scrollView 0299 //ensure the attached property exists 0300 Kirigami.Theme.inherit: true 0301 anchors.fill: parent 0302 implicitWidth: Math.min (Kirigami.Units.gridUnit * 20, root.parent.width * 0.8) 0303 QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff 0304 QQC2.ScrollBar.vertical.anchors { 0305 top: scrollView.top 0306 bottom: scrollView.bottom 0307 topMargin: headerParent.height + headerParent.y 0308 } 0309 0310 Flickable { 0311 id: mainFlickable 0312 contentWidth: width 0313 contentHeight: mainColumn.Layout.minimumHeight 0314 topMargin: headerParent.height 0315 0316 ColumnLayout { 0317 id: headerParent 0318 parent: mainFlickable 0319 anchors { 0320 left: parent.left 0321 right: parent.right 0322 rightMargin: Math.min(0, -scrollView.width + mainFlickable.width) 0323 } 0324 spacing: 0 0325 y: bannerImage.visible ? Math.max(headerContainer.height, -mainFlickable.contentY) - height : 0 0326 0327 Layout.fillWidth: true 0328 // visible: !bannerImage.empty || root.collapsible 0329 0330 P.BannerImage { 0331 id: bannerImage 0332 0333 0334 visible: !bannerImage.empty && opacity > 0 && root.bannerVisible 0335 opacity: !root.collapsed 0336 fillMode: Image.PreserveAspectCrop 0337 0338 Behavior on opacity { 0339 OpacityAnimator { 0340 duration: Kirigami.Units.longDuration 0341 easing.type: Easing.InOutQuad 0342 } 0343 } 0344 // leftPadding: root.collapsible ? collapseButton.width + Kirigami.Units.smallSpacing*2 : topPadding 0345 MouseArea { 0346 anchors.fill: parent 0347 onClicked: mouse => root.bannerClicked() 0348 } 0349 P.EdgeShadow { 0350 edge: Qt.BottomEdge 0351 visible: bannerImageSource != "" 0352 anchors { 0353 left: parent.left 0354 right: parent.right 0355 bottom: parent.top 0356 } 0357 } 0358 } 0359 RowLayout { 0360 id: headerContainer 0361 Kirigami.Theme.inherit: false 0362 Kirigami.Theme.colorSet: Kirigami.Theme.Window 0363 0364 Layout.fillWidth: true 0365 visible: opacity > 0 0366 // Workaround for https://bugreports.qt.io/browse/QTBUG-90034 0367 Layout.preferredHeight: { 0368 if (children.length > 0 && children[0].visible) { 0369 if (opacity === 1) { 0370 return -1; 0371 } else { 0372 return implicitHeight * opacity; 0373 } 0374 } else { 0375 return 0; 0376 } 0377 } 0378 opacity: !root.collapsed || showHeaderWhenCollapsed 0379 Behavior on opacity { 0380 // not an animator as is binded 0381 NumberAnimation { 0382 duration: Kirigami.Units.longDuration 0383 easing.type: Easing.InOutQuad 0384 } 0385 } 0386 } 0387 } 0388 0389 0390 ColumnLayout { 0391 id: mainColumn 0392 width: mainFlickable.width 0393 spacing: 0 0394 height: Math.max(root.height - headerParent.height, Layout.minimumHeight) 0395 0396 ColumnLayout { 0397 id: topContent 0398 spacing: 0 0399 Layout.alignment: Qt.AlignHCenter 0400 Layout.leftMargin: root.leftPadding 0401 Layout.rightMargin: root.rightPadding 0402 Layout.bottomMargin: Kirigami.Units.smallSpacing 0403 Layout.topMargin: root.topPadding 0404 Layout.fillWidth: true 0405 Layout.fillHeight: true 0406 Layout.preferredHeight: implicitHeight * opacity 0407 // NOTE: why this? just Layout.fillWidth: true doesn't seem sufficient 0408 // as items are added only after this column creation 0409 Layout.minimumWidth: parent.width - root.leftPadding - root.rightPadding 0410 visible: children.length > 0 && childrenRect.height > 0 && opacity > 0 0411 opacity: !root.collapsed || showTopContentWhenCollapsed 0412 Behavior on opacity { 0413 // not an animator as is binded 0414 NumberAnimation { 0415 duration: Kirigami.Units.longDuration 0416 easing.type: Easing.InOutQuad 0417 } 0418 } 0419 } 0420 0421 T2.StackView { 0422 id: stackView 0423 clip: true 0424 Layout.fillWidth: true 0425 Layout.minimumHeight: currentItem ? currentItem.implicitHeight : 0 0426 Layout.maximumHeight: Layout.minimumHeight 0427 property P.ActionsMenu openSubMenu 0428 initialItem: menuComponent 0429 // NOTE: it's important those are NumberAnimation and not XAnimators 0430 // as while the animation is running the drawer may close, and 0431 // the animator would stop when not drawing see BUG 381576 0432 popEnter: Transition { 0433 NumberAnimation { property: "x"; from: (stackView.mirrored ? -1 : 1) * -stackView.width; to: 0; duration: Kirigami.Units.veryLongDuration; easing.type: Easing.OutCubic } 0434 } 0435 0436 popExit: Transition { 0437 NumberAnimation { property: "x"; from: 0; to: (stackView.mirrored ? -1 : 1) * stackView.width; duration: Kirigami.Units.veryLongDuration; easing.type: Easing.OutCubic } 0438 } 0439 0440 pushEnter: Transition { 0441 NumberAnimation { property: "x"; from: (stackView.mirrored ? -1 : 1) * stackView.width; to: 0; duration: Kirigami.Units.veryLongDuration; easing.type: Easing.OutCubic } 0442 } 0443 0444 pushExit: Transition { 0445 NumberAnimation { property: "x"; from: 0; to: (stackView.mirrored ? -1 : 1) * -stackView.width; duration: Kirigami.Units.veryLongDuration; easing.type: Easing.OutCubic } 0446 } 0447 0448 replaceEnter: Transition { 0449 NumberAnimation { property: "x"; from: (stackView.mirrored ? -1 : 1) * stackView.width; to: 0; duration: Kirigami.Units.veryLongDuration; easing.type: Easing.OutCubic } 0450 } 0451 0452 replaceExit: Transition { 0453 NumberAnimation { property: "x"; from: 0; to: (stackView.mirrored ? -1 : 1) * -stackView.width; duration: Kirigami.Units.veryLongDuration; easing.type: Easing.OutCubic } 0454 } 0455 } 0456 Item { 0457 Layout.fillWidth: true 0458 Layout.fillHeight: root.actions.length>0 0459 Layout.minimumHeight: Kirigami.Units.smallSpacing 0460 } 0461 0462 ColumnLayout { 0463 id: mainContent 0464 Layout.alignment: Qt.AlignHCenter 0465 Layout.leftMargin: root.leftPadding 0466 Layout.rightMargin: root.rightPadding 0467 Layout.fillWidth: true 0468 Layout.fillHeight: true 0469 // NOTE: why this? just Layout.fillWidth: true doesn't seem sufficient 0470 // as items are added only after this column creation 0471 Layout.minimumWidth: parent.width - root.leftPadding - root.rightPadding 0472 visible: children.length > 0 && (opacity > 0 || mainContentAnimator.running) 0473 opacity: !root.collapsed || showContentWhenCollapsed 0474 Behavior on opacity { 0475 OpacityAnimator { 0476 id: mainContentAnimator 0477 duration: Kirigami.Units.longDuration 0478 easing.type: Easing.InOutQuad 0479 } 0480 } 0481 } 0482 Item { 0483 Layout.minimumWidth: Kirigami.Units.smallSpacing 0484 Layout.minimumHeight: root.bottomPadding 0485 } 0486 0487 Component { 0488 id: menuComponent 0489 0490 Column { 0491 spacing: 0 0492 property alias model: actionsRepeater.model 0493 property Action current 0494 0495 property int level: 0 0496 Layout.maximumHeight: Layout.minimumHeight 0497 0498 BasicListItem { 0499 id: backItem 0500 visible: level > 0 0501 icon: (LayoutMirroring.enabled ? "go-previous-symbolic-rtl" : "go-previous-symbolic") 0502 0503 label: Kirigami.MnemonicData.richTextLabel 0504 Kirigami.MnemonicData.enabled: backItem.enabled && backItem.visible 0505 Kirigami.MnemonicData.controlType: Kirigami.MnemonicData.MenuItem 0506 Kirigami.MnemonicData.label: qsTr("Back") 0507 0508 separatorVisible: false 0509 onClicked: stackView.pop() 0510 0511 Keys.onEnterPressed: stackView.pop() 0512 Keys.onReturnPressed: stackView.pop() 0513 0514 Keys.onDownPressed: nextItemInFocusChain().focus = true 0515 Keys.onUpPressed: nextItemInFocusChain(false).focus = true 0516 } 0517 Shortcut { 0518 sequence: backItem.Kirigami.MnemonicData.sequence 0519 onActivated: backItem.clicked() 0520 } 0521 0522 Repeater { 0523 id: actionsRepeater 0524 0525 readonly property bool withSections: { 0526 for (let i = 0; i < root.actions.length; i++) { 0527 const action = root.actions[i]; 0528 if (!(action.hasOwnProperty("expandible") && action.expandible)) { 0529 return false; 0530 } 0531 } 0532 return true; 0533 } 0534 0535 model: root.actions 0536 delegate: Column { 0537 width: parent.width 0538 P.GlobalDrawerActionItem { 0539 id: drawerItem 0540 visible: (modelData.hasOwnProperty("visible") && modelData.visible) && (root.collapsed || !(modelData.hasOwnProperty("expandible") && modelData.expandible)) 0541 width: parent.width 0542 onCheckedChanged: { 0543 // move every checked item into view 0544 if (checked && topContent.height + backItem.height + (model.index + 1) * height - mainFlickable.contentY > mainFlickable.height) { 0545 mainFlickable.contentY += height 0546 } 0547 } 0548 Kirigami.Theme.colorSet: drawerItem.visible && !root.modal && !root.collapsed && actionsRepeater.withSections ? Kirigami.Theme.Window : parent.Kirigami.Theme.colorSet 0549 backgroundColor: Kirigami.Theme.backgroundColor 0550 } 0551 Item { 0552 id: headerItem 0553 visible: !root.collapsed && (modelData.hasOwnProperty("expandible") && modelData.expandible && !!modelData.children && modelData.children.length > 0) 0554 height: sectionHeader.implicitHeight 0555 width: parent.width 0556 Kirigami.ListSectionHeader { 0557 id: sectionHeader 0558 anchors.fill: parent 0559 Kirigami.Theme.colorSet: root.modal ? Kirigami.Theme.View : Kirigami.Theme.Window 0560 contentItem: RowLayout { 0561 Kirigami.Icon { 0562 property int size: Kirigami.Units.iconSizes.smallMedium 0563 Layout.minimumHeight: size 0564 Layout.maximumHeight: size 0565 Layout.minimumWidth: size 0566 Layout.maximumWidth: size 0567 source: modelData.icon.name || modelData.icon.source 0568 } 0569 Heading { 0570 id: header 0571 level: 4 0572 text: modelData.text 0573 } 0574 Item { 0575 Layout.fillWidth: true 0576 } 0577 } 0578 } 0579 } 0580 Repeater { 0581 id: __repeater 0582 model: headerItem.visible ? modelData.children : null 0583 delegate: P.GlobalDrawerActionItem { 0584 width: parent.width 0585 opacity: !root.collapsed 0586 leftPadding: actionsRepeater.withSections && !root.collapsed && !root.modal ? padding * 2 : padding * 4 0587 } 0588 } 0589 } 0590 } 0591 } 0592 } 0593 0594 QQC2.ToolButton { 0595 icon.name: root.collapsed ? "view-right-new" : "view-right-close" 0596 Layout.fillWidth: root.collapsed 0597 onClicked: root.collapsed = !root.collapsed 0598 visible: root.collapsible && root.collapseButtonVisible 0599 text: root.collapsed ? "" : qsTr("Close Sidebar") 0600 0601 QQC2.ToolTip.visible: root.collapsed && hovered 0602 QQC2.ToolTip.text: qsTr("Open Sidebar") 0603 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay 0604 } 0605 } 0606 } 0607 } 0608 } 0609