SystemDialog: Move the different implementations into a LnF file

This way a LookAndFeel package can override the dialog and trim it to
its needs.
wilder-5.24
Aleix Pol 4 years ago committed by Aleix Pol Gonzalez
parent c531816078
commit 5291c77465
  1. 1
      components/CMakeLists.txt
  2. 325
      components/dialogs/MobileSystemDialog.qml
  3. 3
      components/dialogs/SystemDialog.qml
  4. 83
      components/dialogs/private/MobileSystemDialogButton.qml
  5. 162
      components/dialogs/private/ScrollView.qml
  6. 15
      components/lookandfeelqml/CMakeLists.txt
  7. 18
      components/lookandfeelqml/kpackageinterface.cpp
  8. 22
      components/lookandfeelqml/kpackageinterface.h
  9. 25
      components/lookandfeelqml/lookandfeelqmlplugin.cpp
  10. 18
      components/lookandfeelqml/lookandfeelqmlplugin.h
  11. 2
      components/lookandfeelqml/qmldir
  12. 1
      lookandfeel/contents/systemdialog/SystemDialog.qml
  13. 3
      shell/packageplugins/lookandfeel/lookandfeel.cpp

@ -6,3 +6,4 @@ add_subdirectory(containmentlayoutmanager)
add_subdirectory(shellprivate)
add_subdirectory(keyboardlayout)
add_subdirectory(sessionsprivate)
add_subdirectory(lookandfeelqml)

@ -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
}
}
}
}
}

@ -10,6 +10,7 @@ import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtGraphicalEffects 1.12
import org.kde.kirigami 2.18 as Kirigami
import org.kde.plasma.lookandfeel 1.0
/**
* Component to create CSD dialogs that come from the system.
@ -110,7 +111,7 @@ Kirigami.AbstractApplicationWindow {
id: contentDialog
anchors.fill: parent
Component.onCompleted: {
var component = !Kirigami.Settings.tabletMode ? "MobileSystemDialog.qml" : "DesktopSystemDialog.qml"
var component = LookAndFeel.fileUrl("systemdialogscript")
setSource(component, {
window: root,
mainText: root.mainText,

@ -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

@ -10,7 +10,6 @@ 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
/**
* Dialog used on desktop. Uses SSDs (as opposed to CSDs).

@ -70,6 +70,9 @@ void LookAndFeelPackage::initPackage(KPackage::Package *package)
package->addDirectoryDefinition("windowswitcher", QStringLiteral("windowswitcher"), i18n("Window Switcher"));
package->addFileDefinition("windowswitchermainscript", QStringLiteral("windowswitcher/WindowSwitcher.qml"), i18n("Main Script for Window Switcher"));
package->addDirectoryDefinition("systemdialog", QStringLiteral("systemdialog"), i18n("System Dialog"));
package->addFileDefinition("systemdialogscript", QStringLiteral("systemdialog/SystemDialog.qml"), i18n("The system dialog"));
package->addDirectoryDefinition("layouts", QStringLiteral("layouts"), i18n("Default layout scripts"));
package->setPath(DEFAULT_LOOKANDFEEL);

Loading…
Cancel
Save