Warning, /plasma/plasma-mobile/lookandfeel/contents/systemdialog/SystemDialog.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 * SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 import QtQuick 2.15 0008 import QtQuick.Controls 2.15 0009 import QtQuick.Layouts 1.15 0010 import QtQuick.Window 2.15 0011 import Qt5Compat.GraphicalEffects 0012 import org.kde.kirigami 2.18 as Kirigami 0013 import "private" as Private 0014 0015 Item { 0016 id: root 0017 0018 default property Item mainItem 0019 0020 /** 0021 * Title of the dialog. 0022 */ 0023 property string mainText: "" 0024 0025 /** 0026 * Subtitle of the dialog. 0027 */ 0028 property string subtitle: "" 0029 0030 /** 0031 * This property holds the default padding of the content. 0032 */ 0033 property real padding: Kirigami.Units.smallSpacing 0034 0035 /** 0036 * This property holds the left padding of the content. If not specified, it uses `padding`. 0037 */ 0038 property real leftPadding: padding 0039 0040 /** 0041 * This property holds the right padding of the content. If not specified, it uses `padding`. 0042 */ 0043 property real rightPadding: padding 0044 0045 /** 0046 * This property holds the top padding of the content. If not specified, it uses `padding`. 0047 */ 0048 property real topPadding: padding 0049 0050 /** 0051 * This property holds the bottom padding of the content. If not specified, it uses `padding`. 0052 */ 0053 property real bottomPadding: padding 0054 property alias standardButtons: footerButtonBox.standardButtons 0055 0056 readonly property int flags: Qt.FramelessWindowHint | Qt.Dialog 0057 readonly property real dialogCornerRadius: Kirigami.Units.smallSpacing * 2 0058 property list<Kirigami.Action> actions 0059 property string iconName 0060 0061 implicitWidth: loader.implicitWidth 0062 implicitHeight: loader.implicitHeight 0063 0064 readonly property real minimumHeight: implicitWidth 0065 readonly property real minimumWidth: implicitHeight 0066 0067 required property Kirigami.AbstractApplicationWindow window 0068 0069 function present() { 0070 root.window.showFullScreen() 0071 } 0072 0073 onWindowChanged: { 0074 window.color = Qt.binding(() => { 0075 return Qt.rgba(0, 0, 0, 0.5) 0076 }) 0077 } 0078 0079 // load in async to speed up load times (especially on embedded devices) 0080 Loader { 0081 id: loader 0082 anchors.centerIn: parent 0083 asynchronous: true 0084 0085 sourceComponent: Item { 0086 // margins for shadow 0087 implicitWidth: Math.min(Screen.width, control.implicitWidth + 2 * Kirigami.Units.gridUnit) 0088 implicitHeight: Math.min(Screen.height, control.implicitHeight + 2 * Kirigami.Units.gridUnit) 0089 0090 // shadow 0091 RectangularGlow { 0092 id: glow 0093 anchors.topMargin: 1 0094 anchors.fill: control 0095 cached: true 0096 glowRadius: 2 0097 cornerRadius: Kirigami.Units.gridUnit 0098 spread: 0.1 0099 color: Qt.rgba(0, 0, 0, 0.4) 0100 } 0101 0102 // actual window 0103 Control { 0104 id: control 0105 anchors.fill: parent 0106 anchors.margins: glow.cornerRadius 0107 topPadding: 0 0108 bottomPadding: 0 0109 rightPadding: 0 0110 leftPadding: 0 0111 0112 background: Item { 0113 Rectangle { // border 0114 anchors.fill: parent 0115 anchors.margins: -1 0116 radius: dialogCornerRadius + 1 0117 color: Qt.darker(Kirigami.Theme.backgroundColor, 1.5) 0118 } 0119 Rectangle { // background colour 0120 anchors.fill: parent 0121 radius: dialogCornerRadius 0122 color: Kirigami.Theme.backgroundColor 0123 } 0124 } 0125 0126 contentItem: column 0127 } 0128 } 0129 } 0130 0131 readonly property var contents: ColumnLayout { 0132 id: column 0133 spacing: 0 0134 0135 // header 0136 Control { 0137 id: headerControl 0138 0139 Layout.fillWidth: true 0140 Layout.maximumWidth: root.window.maximumWidth 0141 0142 topPadding: 0 0143 leftPadding: 0 0144 rightPadding: 0 0145 bottomPadding: 0 0146 0147 background: Item {} 0148 0149 contentItem: RowLayout { 0150 Kirigami.Heading { 0151 Layout.fillWidth: true 0152 Layout.topMargin: Kirigami.Units.largeSpacing 0153 Layout.bottomMargin: Kirigami.Units.largeSpacing 0154 Layout.leftMargin: Kirigami.Units.largeSpacing 0155 Layout.rightMargin: Kirigami.Units.largeSpacing 0156 Layout.alignment: Qt.AlignVCenter 0157 level: 2 0158 text: root.mainText 0159 wrapMode: Text.Wrap 0160 elide: Text.ElideRight 0161 horizontalAlignment: Text.AlignHCenter 0162 } 0163 } 0164 } 0165 0166 // content 0167 Control { 0168 id: content 0169 0170 Layout.fillHeight: true 0171 Layout.fillWidth: true 0172 Layout.maximumWidth: root.window.maximumWidth 0173 0174 leftPadding: 0 0175 rightPadding: 0 0176 topPadding: 0 0177 bottomPadding: 0 0178 0179 background: Item {} 0180 contentItem: ColumnLayout { 0181 spacing: 0 0182 clip: true 0183 0184 Label { 0185 id: subtitleLabel 0186 Layout.fillWidth: true 0187 Layout.topMargin: Kirigami.Units.largeSpacing 0188 Layout.bottomMargin: Kirigami.Units.largeSpacing 0189 Layout.leftMargin: Kirigami.Units.gridUnit * 3 0190 Layout.rightMargin: Kirigami.Units.gridUnit * 3 0191 visible: root.subtitle !== "" 0192 horizontalAlignment: Text.AlignHCenter 0193 text: root.subtitle 0194 wrapMode: Label.Wrap 0195 } 0196 0197 // separator when scrolling 0198 Kirigami.Separator { 0199 Layout.fillWidth: true 0200 opacity: root.mainItem && contentControl.flickableItem && contentControl.flickableItem.contentY !== 0 ? 1 : 0 // always maintain same height (as opposed to visible) 0201 } 0202 0203 // mainItem is in scrollview, in case of overflow 0204 Private.ScrollView { 0205 id: contentControl 0206 clip: true 0207 0208 // we cannot have contentItem inside a sub control (allowing for content padding within the scroll area), 0209 // because if the contentItem is a Flickable (ex. ListView), the ScrollView needs it to be top level in order 0210 // to decorate it 0211 contentItem: root.mainItem 0212 canFlickWithMouse: true 0213 0214 // ensure window colour scheme, and background color 0215 Kirigami.Theme.inherit: false 0216 Kirigami.Theme.colorSet: Kirigami.Theme.Window 0217 0218 // needs to explicitly be set for each side to work 0219 leftPadding: root.leftPadding; topPadding: root.topPadding 0220 rightPadding: root.rightPadding; bottomPadding: root.bottomPadding 0221 0222 // height of everything else in the dialog other than the content 0223 property real otherHeights: headerControl.height + subtitleLabel.height + footerButtonBox.height + root.topPadding + root.bottomPadding; 0224 0225 property real calculatedMaximumWidth: root.window.maximumWidth > root.absoluteMaximumWidth ? root.absoluteMaximumWidth : root.window.maximumWidth 0226 property real calculatedMaximumHeight: root.window.maximumHeight > root.absoluteMaximumHeight ? root.absoluteMaximumHeight : root.window.maximumHeight 0227 property real calculatedImplicitWidth: root.mainItem ? (root.mainItem.implicitWidth ? root.mainItem.implicitWidth : root.mainItem.width) + root.leftPadding + root.rightPadding : 0 0228 property real calculatedImplicitHeight: root.mainItem ? (root.mainItem.implicitHeight ? root.mainItem.implicitHeight : root.mainItem.height) + root.topPadding + root.bottomPadding : 0 0229 0230 // don't enforce preferred width and height if not set 0231 Layout.preferredWidth: root.preferredWidth >= 0 ? root.preferredWidth : calculatedImplicitWidth + contentControl.rightSpacing 0232 Layout.preferredHeight: root.preferredHeight >= 0 ? root.preferredHeight - otherHeights : calculatedImplicitHeight + contentControl.bottomSpacing 0233 0234 Layout.fillWidth: true 0235 Layout.fillHeight: true 0236 Layout.maximumWidth: calculatedMaximumWidth 0237 Layout.maximumHeight: calculatedMaximumHeight >= otherHeights ? calculatedMaximumHeight - otherHeights : 0 // we enforce maximum height solely from the content 0238 0239 // give an implied width and height to the contentItem so that features like word wrapping/eliding work 0240 // cannot placed directly in contentControl as a child, so we must use a property 0241 property var widthHint: Binding { 0242 target: root.mainItem 0243 property: "width" 0244 // we want to avoid horizontal scrolling, so we apply maximumWidth as a hint if necessary 0245 property real preferredWidthHint: contentControl.width - root.leftPadding - root.rightPadding - contentControl.rightSpacing 0246 property real maximumWidthHint: contentControl.calculatedMaximumWidth - root.leftPadding - root.rightPadding - contentControl.rightSpacing 0247 value: maximumWidthHint < preferredWidthHint ? maximumWidthHint : preferredWidthHint 0248 } 0249 property var heightHint: Binding { 0250 target: root.mainItem 0251 property: "height" 0252 // we are okay with overflow, if it exceeds maximumHeight we will allow scrolling 0253 value: contentControl.Layout.preferredHeight - root.topPadding - root.bottomPadding - contentControl.bottomSpacing 0254 } 0255 0256 // give explicit warnings since the maximumHeight is ignored when negative, so developers aren't confused 0257 Component.onCompleted: { 0258 if (contentControl.Layout.maximumHeight < 0 || contentControl.Layout.maximumHeight === Infinity) { 0259 console.log("Dialog Warning: the calculated maximumHeight for the content is " + contentControl.Layout.maximumHeight + ", ignoring..."); 0260 } 0261 } 0262 } 0263 } 0264 } 0265 Control { 0266 Layout.fillWidth: true 0267 0268 leftPadding: 0 0269 rightPadding: 0 0270 topPadding: 0 0271 bottomPadding: 0 0272 contentItem: footerButtonBox 0273 } 0274 } 0275 0276 readonly property DialogButtonBox dialogButtonBox: DialogButtonBox { 0277 //We want to report the same width on all so the button area is split equally 0278 id: footerButtonBox 0279 Layout.fillWidth: true 0280 onAccepted: root.window.accept() 0281 onRejected: root.window.reject() 0282 implicitHeight: contentItem.implicitHeight 0283 alignment: undefined 0284 0285 readonly property real sameWidth: 50 0286 delegate: Private.MobileSystemDialogButton { 0287 Layout.fillWidth: true 0288 Layout.preferredWidth: footerButtonBox.sameWidth 0289 0290 readonly property point globalPos: root.window.visible ? mapToItem(footerButtonBox, Qt.point(x, y)) : Qt.point(0, 0) 0291 verticalSeparator: globalPos.x > 0 && root.window.layout === Qt.Horizontal 0292 horizontalSeparator: true 0293 corners.bottomLeftRadius: verticalSeparator ? 0 : root.dialogCornerRadius 0294 corners.bottomRightRadius: globalPos.x >= footerButtonBox.width ? root.dialogCornerRadius : 0 0295 } 0296 0297 leftPadding: 0 0298 rightPadding: 0 0299 topPadding: 0 0300 bottomPadding: 0 0301 0302 contentItem: GridLayout { 0303 Layout.fillWidth: true 0304 0305 rowSpacing: 0 0306 columnSpacing: 0 0307 rows: root.window.layout === Qt.Vertical ? Number.MAX_VALUE : 1 0308 columns: root.window.layout !== Qt.Vertical ? Number.MAX_VALUE : 1 0309 0310 Repeater { 0311 model: root.actions 0312 delegate: Private.MobileSystemDialogButton { 0313 Layout.fillWidth: true 0314 Layout.preferredWidth: footerButtonBox.sameWidth 0315 readonly property point globalPos: root.window.visible ? mapToItem(footerButtonBox, Qt.point(x, y)) : Qt.point(0, 0) 0316 verticalSeparator: globalPos.x > 0 && root.window.layout === Qt.Horizontal 0317 horizontalSeparator: true 0318 corners.bottomLeftRadius: model.index === root.actions.length - 1 ? root.dialogCornerRadius : 0 0319 corners.bottomRightRadius: model.index === root.actions.length - 1 && footerButtonBox.standardButtons === 0 ? root.dialogCornerRadius : 0 0320 action: modelData 0321 } 0322 } 0323 } 0324 } 0325 }