This way a LookAndFeel package can override the dialog and trim it to its needs.wilder-5.24
parent
c531816078
commit
5291c77465
13 changed files with 106 additions and 572 deletions
@ -1,325 +0,0 @@ |
|||||||
/* |
|
||||||
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com> |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: LGPL-2.0-or-later |
|
||||||
*/ |
|
||||||
|
|
||||||
import QtQuick 2.15 |
|
||||||
import QtQuick.Controls 2.15 |
|
||||||
import QtQuick.Layouts 1.15 |
|
||||||
import QtQuick.Window 2.15 |
|
||||||
import QtGraphicalEffects 1.12 |
|
||||||
import org.kde.kirigami 2.18 as Kirigami |
|
||||||
import "private" as Private |
|
||||||
|
|
||||||
Item { |
|
||||||
id: root |
|
||||||
|
|
||||||
default property Item mainItem |
|
||||||
|
|
||||||
/** |
|
||||||
* Title of the dialog. |
|
||||||
*/ |
|
||||||
property string mainText: "" |
|
||||||
|
|
||||||
/** |
|
||||||
* Subtitle of the dialog. |
|
||||||
*/ |
|
||||||
property string subtitle: "" |
|
||||||
|
|
||||||
/** |
|
||||||
* This property holds the default padding of the content. |
|
||||||
*/ |
|
||||||
property real padding: Kirigami.Units.smallSpacing |
|
||||||
|
|
||||||
/** |
|
||||||
* This property holds the left padding of the content. If not specified, it uses `padding`. |
|
||||||
*/ |
|
||||||
property real leftPadding: padding |
|
||||||
|
|
||||||
/** |
|
||||||
* This property holds the right padding of the content. If not specified, it uses `padding`. |
|
||||||
*/ |
|
||||||
property real rightPadding: padding |
|
||||||
|
|
||||||
/** |
|
||||||
* This property holds the top padding of the content. If not specified, it uses `padding`. |
|
||||||
*/ |
|
||||||
property real topPadding: padding |
|
||||||
|
|
||||||
/** |
|
||||||
* This property holds the bottom padding of the content. If not specified, it uses `padding`. |
|
||||||
*/ |
|
||||||
property real bottomPadding: padding |
|
||||||
property alias standardButtons: footerButtonBox.standardButtons |
|
||||||
|
|
||||||
readonly property int flags: Qt.FramelessWindowHint | Qt.Dialog |
|
||||||
readonly property real dialogCornerRadius: Kirigami.Units.smallSpacing * 2 |
|
||||||
property list<Kirigami.Action> actions |
|
||||||
property string iconName |
|
||||||
|
|
||||||
implicitWidth: loader.implicitWidth |
|
||||||
implicitHeight: loader.implicitHeight |
|
||||||
|
|
||||||
readonly property real minimumHeight: implicitWidth |
|
||||||
readonly property real minimumWidth: implicitHeight |
|
||||||
|
|
||||||
required property Kirigami.AbstractApplicationWindow window |
|
||||||
|
|
||||||
function present() { |
|
||||||
root.window.showFullScreen() |
|
||||||
} |
|
||||||
|
|
||||||
onWindowChanged: { |
|
||||||
window.color = Qt.binding(() => { |
|
||||||
return Qt.rgba(0, 0, 0, 0.5) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
// load in async to speed up load times (especially on embedded devices) |
|
||||||
Loader { |
|
||||||
id: loader |
|
||||||
anchors.centerIn: parent |
|
||||||
asynchronous: true |
|
||||||
|
|
||||||
sourceComponent: Item { |
|
||||||
// margins for shadow |
|
||||||
implicitWidth: Math.min(Screen.width, control.implicitWidth + 2 * Kirigami.Units.gridUnit) |
|
||||||
implicitHeight: Math.min(Screen.height, control.implicitHeight + 2 * Kirigami.Units.gridUnit) |
|
||||||
|
|
||||||
// shadow |
|
||||||
RectangularGlow { |
|
||||||
id: glow |
|
||||||
anchors.topMargin: 1 |
|
||||||
anchors.fill: control |
|
||||||
cached: true |
|
||||||
glowRadius: 2 |
|
||||||
cornerRadius: Kirigami.Units.gridUnit |
|
||||||
spread: 0.1 |
|
||||||
color: Qt.rgba(0, 0, 0, 0.4) |
|
||||||
} |
|
||||||
|
|
||||||
// actual window |
|
||||||
Control { |
|
||||||
id: control |
|
||||||
anchors.fill: parent |
|
||||||
anchors.margins: glow.cornerRadius |
|
||||||
topPadding: 0 |
|
||||||
bottomPadding: 0 |
|
||||||
rightPadding: 0 |
|
||||||
leftPadding: 0 |
|
||||||
|
|
||||||
background: Item { |
|
||||||
Rectangle { // border |
|
||||||
anchors.fill: parent |
|
||||||
anchors.margins: -1 |
|
||||||
radius: dialogCornerRadius + 1 |
|
||||||
color: Qt.darker(Kirigami.Theme.backgroundColor, 1.5) |
|
||||||
} |
|
||||||
Rectangle { // background colour |
|
||||||
anchors.fill: parent |
|
||||||
radius: dialogCornerRadius |
|
||||||
color: Kirigami.Theme.backgroundColor |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
contentItem: column |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
readonly property var contents: ColumnLayout { |
|
||||||
id: column |
|
||||||
spacing: 0 |
|
||||||
|
|
||||||
// header |
|
||||||
Control { |
|
||||||
id: headerControl |
|
||||||
|
|
||||||
Layout.fillWidth: true |
|
||||||
Layout.maximumWidth: root.window.maximumWidth |
|
||||||
|
|
||||||
topPadding: 0 |
|
||||||
leftPadding: 0 |
|
||||||
rightPadding: 0 |
|
||||||
bottomPadding: 0 |
|
||||||
|
|
||||||
background: Item {} |
|
||||||
|
|
||||||
contentItem: RowLayout { |
|
||||||
Kirigami.Heading { |
|
||||||
Layout.fillWidth: true |
|
||||||
Layout.topMargin: Kirigami.Units.largeSpacing |
|
||||||
Layout.bottomMargin: Kirigami.Units.largeSpacing |
|
||||||
Layout.leftMargin: Kirigami.Units.largeSpacing |
|
||||||
Layout.rightMargin: Kirigami.Units.largeSpacing |
|
||||||
Layout.alignment: Qt.AlignVCenter |
|
||||||
level: 2 |
|
||||||
text: root.mainText |
|
||||||
wrapMode: Text.Wrap |
|
||||||
elide: Text.ElideRight |
|
||||||
horizontalAlignment: Text.AlignHCenter |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// content |
|
||||||
Control { |
|
||||||
id: content |
|
||||||
|
|
||||||
Layout.fillHeight: true |
|
||||||
Layout.fillWidth: true |
|
||||||
Layout.maximumWidth: root.window.maximumWidth |
|
||||||
|
|
||||||
leftPadding: 0 |
|
||||||
rightPadding: 0 |
|
||||||
topPadding: 0 |
|
||||||
bottomPadding: 0 |
|
||||||
|
|
||||||
background: Item {} |
|
||||||
contentItem: ColumnLayout { |
|
||||||
spacing: 0 |
|
||||||
clip: true |
|
||||||
|
|
||||||
Label { |
|
||||||
id: subtitleLabel |
|
||||||
Layout.fillWidth: true |
|
||||||
Layout.topMargin: Kirigami.Units.largeSpacing |
|
||||||
Layout.bottomMargin: Kirigami.Units.largeSpacing |
|
||||||
Layout.leftMargin: Kirigami.Units.gridUnit * 3 |
|
||||||
Layout.rightMargin: Kirigami.Units.gridUnit * 3 |
|
||||||
visible: root.subtitle !== "" |
|
||||||
horizontalAlignment: Text.AlignHCenter |
|
||||||
text: root.subtitle |
|
||||||
wrapMode: Label.Wrap |
|
||||||
} |
|
||||||
|
|
||||||
// separator when scrolling |
|
||||||
Kirigami.Separator { |
|
||||||
Layout.fillWidth: true |
|
||||||
opacity: root.mainItem && contentControl.flickableItem && contentControl.flickableItem.contentY !== 0 ? 1 : 0 // always maintain same height (as opposed to visible) |
|
||||||
} |
|
||||||
|
|
||||||
// mainItem is in scrollview, in case of overflow |
|
||||||
Private.ScrollView { |
|
||||||
id: contentControl |
|
||||||
clip: true |
|
||||||
|
|
||||||
// we cannot have contentItem inside a sub control (allowing for content padding within the scroll area), |
|
||||||
// because if the contentItem is a Flickable (ex. ListView), the ScrollView needs it to be top level in order |
|
||||||
// to decorate it |
|
||||||
contentItem: root.mainItem |
|
||||||
canFlickWithMouse: true |
|
||||||
|
|
||||||
// ensure window colour scheme, and background color |
|
||||||
Kirigami.Theme.inherit: false |
|
||||||
Kirigami.Theme.colorSet: Kirigami.Theme.Window |
|
||||||
|
|
||||||
// needs to explicitly be set for each side to work |
|
||||||
leftPadding: root.leftPadding; topPadding: root.topPadding |
|
||||||
rightPadding: root.rightPadding; bottomPadding: root.bottomPadding |
|
||||||
|
|
||||||
// height of everything else in the dialog other than the content |
|
||||||
property real otherHeights: headerControl.height + subtitleLabel.height + footerButtonBox.height + root.topPadding + root.bottomPadding; |
|
||||||
|
|
||||||
property real calculatedMaximumWidth: root.window.maximumWidth > root.absoluteMaximumWidth ? root.absoluteMaximumWidth : root.window.maximumWidth |
|
||||||
property real calculatedMaximumHeight: root.window.maximumHeight > root.absoluteMaximumHeight ? root.absoluteMaximumHeight : root.window.maximumHeight |
|
||||||
property real calculatedImplicitWidth: root.mainItem ? (root.mainItem.implicitWidth ? root.mainItem.implicitWidth : root.mainItem.width) + root.leftPadding + root.rightPadding : 0 |
|
||||||
property real calculatedImplicitHeight: root.mainItem ? (root.mainItem.implicitHeight ? root.mainItem.implicitHeight : root.mainItem.height) + root.topPadding + root.bottomPadding : 0 |
|
||||||
|
|
||||||
// don't enforce preferred width and height if not set |
|
||||||
Layout.preferredWidth: root.preferredWidth >= 0 ? root.preferredWidth : calculatedImplicitWidth + contentControl.rightSpacing |
|
||||||
Layout.preferredHeight: root.preferredHeight >= 0 ? root.preferredHeight - otherHeights : calculatedImplicitHeight + contentControl.bottomSpacing |
|
||||||
|
|
||||||
Layout.fillWidth: true |
|
||||||
Layout.fillHeight: true |
|
||||||
Layout.maximumWidth: calculatedMaximumWidth |
|
||||||
Layout.maximumHeight: calculatedMaximumHeight >= otherHeights ? calculatedMaximumHeight - otherHeights : 0 // we enforce maximum height solely from the content |
|
||||||
|
|
||||||
// give an implied width and height to the contentItem so that features like word wrapping/eliding work |
|
||||||
// cannot placed directly in contentControl as a child, so we must use a property |
|
||||||
property var widthHint: Binding { |
|
||||||
target: root.mainItem |
|
||||||
property: "width" |
|
||||||
// we want to avoid horizontal scrolling, so we apply maximumWidth as a hint if necessary |
|
||||||
property real preferredWidthHint: contentControl.width - root.leftPadding - root.rightPadding - contentControl.rightSpacing |
|
||||||
property real maximumWidthHint: contentControl.calculatedMaximumWidth - root.leftPadding - root.rightPadding - contentControl.rightSpacing |
|
||||||
value: maximumWidthHint < preferredWidthHint ? maximumWidthHint : preferredWidthHint |
|
||||||
} |
|
||||||
property var heightHint: Binding { |
|
||||||
target: root.mainItem |
|
||||||
property: "height" |
|
||||||
// we are okay with overflow, if it exceeds maximumHeight we will allow scrolling |
|
||||||
value: contentControl.Layout.preferredHeight - root.topPadding - root.bottomPadding - contentControl.bottomSpacing |
|
||||||
} |
|
||||||
|
|
||||||
// give explicit warnings since the maximumHeight is ignored when negative, so developers aren't confused |
|
||||||
Component.onCompleted: { |
|
||||||
if (contentControl.Layout.maximumHeight < 0 || contentControl.Layout.maximumHeight === Infinity) { |
|
||||||
console.log("Dialog Warning: the calculated maximumHeight for the content is " + contentControl.Layout.maximumHeight + ", ignoring..."); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
Control { |
|
||||||
Layout.fillWidth: true |
|
||||||
|
|
||||||
leftPadding: 0 |
|
||||||
rightPadding: 0 |
|
||||||
topPadding: 0 |
|
||||||
bottomPadding: 0 |
|
||||||
contentItem: footerButtonBox |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
readonly property DialogButtonBox dialogButtonBox: DialogButtonBox { |
|
||||||
//We want to report the same width on all so the button area is split equally |
|
||||||
id: footerButtonBox |
|
||||||
Layout.fillWidth: true |
|
||||||
onAccepted: root.window.accept() |
|
||||||
onRejected: root.window.reject() |
|
||||||
implicitHeight: contentItem.implicitHeight |
|
||||||
alignment: undefined |
|
||||||
|
|
||||||
readonly property real sameWidth: 50 |
|
||||||
delegate: Private.MobileSystemDialogButton { |
|
||||||
Layout.fillWidth: true |
|
||||||
Layout.preferredWidth: footerButtonBox.sameWidth |
|
||||||
|
|
||||||
readonly property point globalPos: root.window.visible ? mapToItem(footerButtonBox, Qt.point(x, y)) : Qt.point(0, 0) |
|
||||||
verticalSeparator: globalPos.x > 0 && root.window.layout === Qt.Horizontal |
|
||||||
horizontalSeparator: true |
|
||||||
corners.bottomLeftRadius: verticalSeparator ? 0 : root.dialogCornerRadius |
|
||||||
corners.bottomRightRadius: globalPos.x >= footerButtonBox.width ? root.dialogCornerRadius : 0 |
|
||||||
} |
|
||||||
|
|
||||||
leftPadding: 0 |
|
||||||
rightPadding: 0 |
|
||||||
topPadding: 0 |
|
||||||
bottomPadding: 0 |
|
||||||
|
|
||||||
contentItem: GridLayout { |
|
||||||
Layout.fillWidth: true |
|
||||||
|
|
||||||
rowSpacing: 0 |
|
||||||
columnSpacing: 0 |
|
||||||
rows: root.window.layout === Qt.Vertical ? Number.MAX_VALUE : 1 |
|
||||||
columns: root.window.layout !== Qt.Vertical ? Number.MAX_VALUE : 1 |
|
||||||
|
|
||||||
Repeater { |
|
||||||
model: root.actions |
|
||||||
delegate: Private.MobileSystemDialogButton { |
|
||||||
Layout.fillWidth: true |
|
||||||
Layout.preferredWidth: footerButtonBox.sameWidth |
|
||||||
readonly property point globalPos: root.window.visible ? mapToItem(footerButtonBox, Qt.point(x, y)) : Qt.point(0, 0) |
|
||||||
verticalSeparator: globalPos.x > 0 && root.window.layout === Qt.Horizontal |
|
||||||
horizontalSeparator: true |
|
||||||
corners.bottomLeftRadius: model.index === root.actions.length - 1 ? root.dialogCornerRadius : 0 |
|
||||||
corners.bottomRightRadius: model.index === root.actions.length - 1 && footerButtonBox.standardButtons === 0 ? root.dialogCornerRadius : 0 |
|
||||||
action: modelData |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,83 +0,0 @@ |
|||||||
/* |
|
||||||
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com> |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: LGPL-2.0-or-later |
|
||||||
*/ |
|
||||||
|
|
||||||
import QtQuick 2.15 |
|
||||||
import QtQuick.Controls 2.15 |
|
||||||
import QtQuick.Layouts 1.15 |
|
||||||
import QtQuick.Window 2.2 |
|
||||||
import QtGraphicalEffects 1.12 |
|
||||||
import org.kde.kirigami 2.18 as Kirigami |
|
||||||
|
|
||||||
AbstractButton { |
|
||||||
id: root |
|
||||||
|
|
||||||
property alias corners: background.corners |
|
||||||
|
|
||||||
property bool verticalSeparator: false |
|
||||||
property bool horizontalSeparator: false |
|
||||||
|
|
||||||
background: Kirigami.ShadowedRectangle { |
|
||||||
id: background |
|
||||||
Kirigami.Theme.colorSet: Kirigami.Theme.Button |
|
||||||
Kirigami.Theme.inherit: false |
|
||||||
color: { |
|
||||||
if (root.down) { |
|
||||||
let avg = (Kirigami.Theme.backgroundColor.r + Kirigami.Theme.backgroundColor.g + Kirigami.Theme.backgroundColor.b) / 3; |
|
||||||
// sample down |
|
||||||
avg = Math.max(0, (avg - 0.8) * 5); |
|
||||||
return Qt.darker(Kirigami.Theme.backgroundColor, 1.1 + 0.4 * (1 - avg)); |
|
||||||
} else if (hoverHandler.hovered) { |
|
||||||
return Qt.darker(Kirigami.Theme.backgroundColor, 1.05) |
|
||||||
} else { |
|
||||||
return Kirigami.Theme.backgroundColor |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
Kirigami.Separator { |
|
||||||
anchors.left: parent.left |
|
||||||
anchors.top: parent.top |
|
||||||
anchors.bottom: parent.bottom |
|
||||||
visible: root.verticalSeparator |
|
||||||
} |
|
||||||
Kirigami.Separator { |
|
||||||
anchors.left: parent.left |
|
||||||
anchors.right: parent.right |
|
||||||
anchors.top: parent.top |
|
||||||
visible: root.horizontalSeparator |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
leftPadding: Kirigami.Units.largeSpacing |
|
||||||
rightPadding: Kirigami.Units.largeSpacing |
|
||||||
topPadding: Kirigami.Units.largeSpacing |
|
||||||
bottomPadding: Kirigami.Units.largeSpacing |
|
||||||
|
|
||||||
contentItem: Item { |
|
||||||
implicitHeight: row.height + Kirigami.Units.smallSpacing |
|
||||||
implicitWidth: row.implicitWidth |
|
||||||
RowLayout { |
|
||||||
id: row |
|
||||||
anchors.centerIn: parent |
|
||||||
spacing: 0 |
|
||||||
|
|
||||||
Kirigami.Icon { |
|
||||||
Layout.preferredHeight: label.height |
|
||||||
Layout.preferredWidth: height |
|
||||||
Layout.rightMargin: Kirigami.Units.smallSpacing |
|
||||||
visible: root.icon.name |
|
||||||
source: root.icon.name |
|
||||||
} |
|
||||||
Label { |
|
||||||
id: label |
|
||||||
text: root.text |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
HoverHandler { |
|
||||||
id: hoverHandler |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,162 +0,0 @@ |
|||||||
/* |
|
||||||
* SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org> |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: LGPL-2.0-or-later |
|
||||||
*/ |
|
||||||
import QtQuick 2.7 |
|
||||||
import QtQuick.Controls 2.0 |
|
||||||
import QtQml 2.15 |
|
||||||
import org.kde.kirigami 2.9 as Kirigami |
|
||||||
|
|
||||||
// taken from Kirigami |
|
||||||
MouseArea { |
|
||||||
id: root |
|
||||||
default property Item contentItem |
|
||||||
property Flickable flickableItem |
|
||||||
clip: true |
|
||||||
|
|
||||||
property int horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff |
|
||||||
property int verticalScrollBarPolicy: Qt.ScrollBarAsNeeded |
|
||||||
property int topPadding: 0 |
|
||||||
property int leftPadding: 0 |
|
||||||
property int bottomPadding: 0 |
|
||||||
property int rightPadding: 0 |
|
||||||
property bool canFlickWithMouse: false |
|
||||||
|
|
||||||
// Note: These are used because RefreshableScrollView overrides right and |
|
||||||
// bottom padding properties. |
|
||||||
property int rightSpacing: !Kirigami.Settings.hasTransientTouchInput && flickableItem && flickableItem.ScrollBar.vertical && flickableItem.ScrollBar.vertical.visible ? flickableItem.ScrollBar.vertical.width : 0 |
|
||||||
property int bottomSpacing: !Kirigami.Settings.hasTransientTouchInput && flickableItem && flickableItem.ScrollBar.horizontal && flickableItem.ScrollBar.horizontal.visible ? flickableItem.ScrollBar.horizontal.height : 0 |
|
||||||
|
|
||||||
Accessible.onScrollDownAction: flickableItem.Accessible.onScrollDownAction |
|
||||||
Accessible.onScrollUpAction: flickableItem.Accessible.onScrollUpAction |
|
||||||
|
|
||||||
Keys.onUpPressed: scroll(Kirigami.Units.gridUnit * 2) |
|
||||||
Keys.onDownPressed: scroll(-Kirigami.Units.gridUnit * 2) |
|
||||||
|
|
||||||
function scroll(y) { |
|
||||||
// Don't scroll if the view isn't scrollable! |
|
||||||
if (flickableItem.contentHeight < flickableItem.height + flickableItem.contentY) { |
|
||||||
return; |
|
||||||
} |
|
||||||
const minYExtent = flickableItem.topMargin - flickableItem.originY; |
|
||||||
const maxYExtent = flickableItem.height - (flickableItem.contentHeight + flickableItem.bottomMargin + flickableItem.originY); |
|
||||||
|
|
||||||
flickableItem.contentY = Math.min(-maxYExtent, Math.max(-minYExtent, flickableItem.contentY - y)); |
|
||||||
} |
|
||||||
|
|
||||||
focus: true |
|
||||||
|
|
||||||
onPressed: mouse.accepted = mouse.source !== Qt.MouseEventNotSynthesized |
|
||||||
onVerticalScrollBarPolicyChanged: { |
|
||||||
scrollBarCreationTimer.restart(); |
|
||||||
} |
|
||||||
onHorizontalScrollBarPolicyChanged: { |
|
||||||
scrollBarCreationTimer.restart(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
onContentItemChanged: { |
|
||||||
if (contentItem.hasOwnProperty("contentY")) { |
|
||||||
flickableItem = contentItem; |
|
||||||
if (typeof(flickableItem.keyNavigationEnabled) != "undefined") { |
|
||||||
flickableItem.keyNavigationEnabled = true; |
|
||||||
flickableItem.keyNavigationWraps = false; |
|
||||||
} |
|
||||||
contentItem.parent = flickableParent; |
|
||||||
} else { |
|
||||||
flickableItem = flickableComponent.createObject(flickableParent); |
|
||||||
contentItem.parent = flickableItem.contentItem; |
|
||||||
} |
|
||||||
|
|
||||||
flickableItem.anchors.fill = flickableParent; |
|
||||||
|
|
||||||
scrollBarCreationTimer.restart(); |
|
||||||
} |
|
||||||
|
|
||||||
Binding { |
|
||||||
when: !root.canFlickWithMouse |
|
||||||
target: root.flickableItem |
|
||||||
property: "interactive" |
|
||||||
value: Kirigami.Settings.hasTransientTouchInput |
|
||||||
restoreMode: Binding.RestoreBinding |
|
||||||
} |
|
||||||
Timer { |
|
||||||
id: scrollBarCreationTimer |
|
||||||
interval: 0 |
|
||||||
onTriggered: { |
|
||||||
//create or destroy the vertical scrollbar |
|
||||||
if ((!flickableItem.ScrollBar.vertical) && |
|
||||||
verticalScrollBarPolicy != Qt.ScrollBarAlwaysOff) { |
|
||||||
flickableItem.ScrollBar.vertical = verticalScrollComponent.createObject(root); |
|
||||||
} else if (flickableItem.ScrollBar.vertical && |
|
||||||
verticalScrollBarPolicy == Qt.ScrollBarAlwaysOff) { |
|
||||||
flickableItem.ScrollBar.vertical.destroy(); |
|
||||||
} |
|
||||||
|
|
||||||
//create or destroy the horizontal scrollbar |
|
||||||
if ((!flickableItem.ScrollBar.horizontal) && |
|
||||||
horizontalScrollBarPolicy != Qt.ScrollBarAlwaysOff) { |
|
||||||
flickableItem.ScrollBar.horizontal = horizontalScrollComponent.createObject(root); |
|
||||||
} else if (flickableItem.ScrollBar.horizontal && |
|
||||||
horizontalScrollBarPolicy == Qt.ScrollBarAlwaysOff) { |
|
||||||
flickableItem.ScrollBar.horizontal.destroy(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
Kirigami.WheelHandler { |
|
||||||
id: wheelHandler |
|
||||||
target: root.flickableItem |
|
||||||
} |
|
||||||
Item { |
|
||||||
id: flickableParent |
|
||||||
clip: true |
|
||||||
anchors { |
|
||||||
fill: parent |
|
||||||
leftMargin: root.leftPadding |
|
||||||
topMargin: root.topPadding |
|
||||||
rightMargin: root.rightPadding + root.rightSpacing |
|
||||||
bottomMargin: root.bottomPadding + root.bottomSpacing |
|
||||||
} |
|
||||||
} |
|
||||||
Component { |
|
||||||
id: flickableComponent |
|
||||||
Flickable { |
|
||||||
anchors { |
|
||||||
fill: parent |
|
||||||
} |
|
||||||
contentWidth: root.contentItem ? root.contentItem.width : 0 |
|
||||||
contentHeight: root.contentItem ? root.contentItem.height : 0 |
|
||||||
} |
|
||||||
} |
|
||||||
Component { |
|
||||||
id: verticalScrollComponent |
|
||||||
ScrollBar { |
|
||||||
z: flickableParent.z + 1 |
|
||||||
visible: root.verticalScrollBarPolicy != Qt.ScrollBarAlwaysOff && root.contentItem.visible && size < 1 |
|
||||||
interactive: !Kirigami.Settings.hasTransientTouchInput |
|
||||||
|
|
||||||
anchors { |
|
||||||
right: parent.right |
|
||||||
top: parent.top |
|
||||||
bottom: parent.bottom |
|
||||||
bottomMargin: root.bottomSpacing |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
Component { |
|
||||||
id: horizontalScrollComponent |
|
||||||
ScrollBar { |
|
||||||
z: flickableParent.z + 1 |
|
||||||
visible: root.horizontalScrollBarPolicy != Qt.ScrollBarAlwaysOff && root.contentItem.visible && size < 1 |
|
||||||
interactive: !Kirigami.Settings.hasTransientTouchInput |
|
||||||
|
|
||||||
anchors { |
|
||||||
left: parent.left |
|
||||||
right: parent.right |
|
||||||
bottom: parent.bottom |
|
||||||
rightMargin: root.rightSpacing |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -0,0 +1,15 @@ |
|||||||
|
set(lookandfeelqmlplugin_SRCS |
||||||
|
lookandfeelqmlplugin.cpp |
||||||
|
kpackageinterface.cpp |
||||||
|
) |
||||||
|
|
||||||
|
add_library(lookandfeelqmlplugin SHARED ${lookandfeelqmlplugin_SRCS}) |
||||||
|
target_link_libraries(lookandfeelqmlplugin |
||||||
|
Qt::Qml |
||||||
|
KF5::ConfigCore |
||||||
|
KF5::Package |
||||||
|
) |
||||||
|
|
||||||
|
install(TARGETS lookandfeelqmlplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/lookandfeel) |
||||||
|
|
||||||
|
install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/lookandfeel) |
||||||
@ -0,0 +1,18 @@ |
|||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org> |
||||||
|
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "kpackageinterface.h" |
||||||
|
|
||||||
|
KPackageInterface::KPackageInterface(const KPackage::Package &package) |
||||||
|
: m_package(package) |
||||||
|
{ |
||||||
|
Q_ASSERT(m_package.isValid()); |
||||||
|
} |
||||||
|
|
||||||
|
QUrl KPackageInterface::fileUrl(const QByteArray &key) const |
||||||
|
{ |
||||||
|
return m_package.fileUrl(key); |
||||||
|
} |
||||||
@ -0,0 +1,22 @@ |
|||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org> |
||||||
|
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
||||||
|
*/ |
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <KPackage/Package> |
||||||
|
#include <QObject> |
||||||
|
|
||||||
|
class KPackageInterface : public QObject |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
public: |
||||||
|
KPackageInterface(const KPackage::Package &package); |
||||||
|
|
||||||
|
Q_INVOKABLE QUrl fileUrl(const QByteArray &key) const; |
||||||
|
|
||||||
|
private: |
||||||
|
const KPackage::Package m_package; |
||||||
|
}; |
||||||
@ -0,0 +1,25 @@ |
|||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org> |
||||||
|
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "lookandfeelqmlplugin.h" |
||||||
|
|
||||||
|
#include "kpackageinterface.h" |
||||||
|
#include <KConfigGroup> |
||||||
|
#include <KPackage/PackageLoader> |
||||||
|
#include <KSharedConfig> |
||||||
|
#include <QQmlEngine> |
||||||
|
|
||||||
|
void SessionsPrivatePlugin::registerTypes(const char *uri) |
||||||
|
{ |
||||||
|
Q_ASSERT(uri == QLatin1String("org.kde.plasma.lookandfeel")); |
||||||
|
|
||||||
|
qmlRegisterSingletonType<KPackageInterface>(uri, 1, 0, "LookAndFeel", [](QQmlEngine *, QJSEngine *) { |
||||||
|
KConfigGroup cg(KSharedConfig::openConfig(), "KDE"); |
||||||
|
const QString packageName = cg.readEntry("LookAndFeelPackage", QString()); |
||||||
|
const auto package = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/LookAndFeel"), packageName); |
||||||
|
return new KPackageInterface(package); |
||||||
|
}); |
||||||
|
} |
||||||
@ -0,0 +1,18 @@ |
|||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org> |
||||||
|
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
||||||
|
*/ |
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <QQmlExtensionPlugin> |
||||||
|
|
||||||
|
class SessionsPrivatePlugin : public QQmlExtensionPlugin |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") |
||||||
|
|
||||||
|
public: |
||||||
|
void registerTypes(const char *uri) override; |
||||||
|
}; |
||||||
@ -0,0 +1,2 @@ |
|||||||
|
module org.kde.plasma.lookandfeel |
||||||
|
plugin lookandfeelqmlplugin |
||||||
Loading…
Reference in new issue