mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-26 14:23:09 +00:00
shell: Update configuration dialogs based on desktop, use new UI for wallpaper selector
This commit is contained in:
parent
dee476e773
commit
436b2660d2
7 changed files with 510 additions and 600 deletions
|
|
@ -1,43 +1,116 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
// SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
|
||||
// SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Controls 2.3 as QtControls
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Window 2.2
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Window 2.15
|
||||
|
||||
import org.kde.kirigami 2.5 as Kirigami
|
||||
import org.kde.plasma.core 2.1 as PlasmaCore
|
||||
import org.kde.kirigami 2.19 as Kirigami
|
||||
import org.kde.plasma.configuration 2.0
|
||||
import org.kde.kitemmodels 1.0 as KItemModels
|
||||
|
||||
|
||||
//TODO: all of this will be done with desktop components
|
||||
Rectangle {
|
||||
id: root
|
||||
// Layout.minimumWidth: plasmoid.availableScreenRect.width
|
||||
// Layout.minimumHeight: plasmoid.availableScreenRect.height
|
||||
|
||||
|
||||
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
|
||||
LayoutMirroring.childrenInherit: true
|
||||
|
||||
color: "transparent"
|
||||
|
||||
//BEGIN properties
|
||||
|
||||
property bool isContainment: false
|
||||
property alias internalDialog: dialogContents
|
||||
property alias appComponent: app
|
||||
|
||||
//END properties
|
||||
|
||||
//BEGIN model
|
||||
property ConfigModel globalConfigModel: globalAppletConfigModel
|
||||
|
||||
property ConfigModel globalConfigModel: globalAppletConfigModel
|
||||
|
||||
ConfigModel {
|
||||
id: globalAppletConfigModel
|
||||
}
|
||||
|
||||
KItemModels.KSortFilterProxyModel {
|
||||
id: configDialogFilterModel
|
||||
sourceModel: configDialog.configModel
|
||||
filterRowCallback: (row, parent) => {
|
||||
return sourceModel.data(sourceModel.index(row, 0), ConfigModel.VisibleRole);
|
||||
}
|
||||
}
|
||||
|
||||
//END model
|
||||
|
||||
//BEGIN functions
|
||||
|
||||
function saveConfig() {
|
||||
if (app.pageStack.currentItem.saveConfig) {
|
||||
app.pageStack.currentItem.saveConfig()
|
||||
}
|
||||
for (var key in plasmoid.configuration) {
|
||||
if (app.pageStack.currentItem["cfg_"+key] !== undefined) {
|
||||
plasmoid.configuration[key] = app.pageStack.currentItem["cfg_"+key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function configurationHasChanged() {
|
||||
for (var key in plasmoid.configuration) {
|
||||
if (app.pageStack.currentItem["cfg_"+key] !== undefined) {
|
||||
//for objects == doesn't work
|
||||
if (typeof plasmoid.configuration[key] == 'object') {
|
||||
for (var i in plasmoid.configuration[key]) {
|
||||
if (plasmoid.configuration[key][i] != app.pageStack.currentItem["cfg_"+key][i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (app.pageStack.currentItem["cfg_"+key] != plasmoid.configuration[key]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function settingValueChanged() {
|
||||
if (app.pageStack.currentItem.saveConfig !== undefined) {
|
||||
app.pageStack.currentItem.saveConfig();
|
||||
} else {
|
||||
root.saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
function pushReplace(item, config) {
|
||||
let page;
|
||||
if (app.pageStack.depth === 0) {
|
||||
page = app.pageStack.push(item, config);
|
||||
} else {
|
||||
page = app.pageStack.replace(item, config);
|
||||
}
|
||||
app.currentConfigPage = page;
|
||||
}
|
||||
|
||||
function open(item) {
|
||||
app.isAboutPage = false;
|
||||
if (item.source) {
|
||||
app.isAboutPage = item.source === "AboutPlugin.qml";
|
||||
pushReplace(Qt.resolvedUrl("ConfigurationAppletPage.qml"), {configItem: item, title: item.name});
|
||||
} else if (item.kcm) {
|
||||
pushReplace(configurationKcmPageComponent, {kcm: item.kcm, internalPage: item.kcm.mainUi});
|
||||
} else {
|
||||
app.pageStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
//END functions
|
||||
|
||||
|
||||
//BEGIN connections
|
||||
|
||||
Connections {
|
||||
target: root.Window.window
|
||||
function onVisibleChanged() {
|
||||
|
|
@ -47,334 +120,101 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
PlasmaCore.SortFilterModel {
|
||||
id: configDialogFilterModel
|
||||
sourceModel: configDialog.configModel
|
||||
filterRole: "visible"
|
||||
filterCallback: function(source_row, value) { return value; }
|
||||
}
|
||||
//END model
|
||||
|
||||
//BEGIN functions
|
||||
function saveConfig() {
|
||||
if (pageStack.currentItem.saveConfig) {
|
||||
pageStack.currentItem.saveConfig()
|
||||
}
|
||||
for (var key in plasmoid.configuration) {
|
||||
if (pageStack.currentItem["cfg_"+key] !== undefined) {
|
||||
plasmoid.configuration[key] = pageStack.currentItem["cfg_"+key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function configurationHasChanged() {
|
||||
for (var key in plasmoid.configuration) {
|
||||
if (pageStack.currentItem["cfg_"+key] !== undefined) {
|
||||
//for objects == doesn't work
|
||||
if (typeof plasmoid.configuration[key] == 'object') {
|
||||
for (var i in plasmoid.configuration[key]) {
|
||||
if (plasmoid.configuration[key][i] != pageStack.currentItem["cfg_"+key][i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (pageStack.currentItem["cfg_"+key] != plasmoid.configuration[key]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function settingValueChanged() {
|
||||
if (pageStack.currentItem.saveConfig !== undefined) {
|
||||
pageStack.currentItem.saveConfig();
|
||||
} else {
|
||||
root.saveConfig();
|
||||
}
|
||||
}
|
||||
//END functions
|
||||
|
||||
|
||||
//BEGIN connections
|
||||
Component.onCompleted: {
|
||||
if (!isContainment && configDialog.configModel && configDialog.configModel.count > 0) {
|
||||
if (configDialog.configModel.get(0).source) {
|
||||
pageStack.sourceFile = configDialog.configModel.get(0).source
|
||||
} else if (configDialog.configModel.get(0).kcm) {
|
||||
pageStack.sourceFile = Qt.resolvedUrl("ConfigurationKcmPage.qml");
|
||||
pageStack.currentItem.kcm = configDialog.configModel.get(0).kcm;
|
||||
} else {
|
||||
pageStack.sourceFile = "";
|
||||
}
|
||||
pageStack.title = configDialog.configModel.get(0).name
|
||||
// if we are a containment then the first item will be ConfigurationContainmentAppearance
|
||||
// if the applet does not have own configs then the first item will be Shortcuts
|
||||
if (isContainment || !configDialog.configModel || configDialog.configModel.count === 0) {
|
||||
open(root.globalConfigModel.get(0))
|
||||
} else {
|
||||
pageStack.sourceFile = globalConfigModel.get(0).source
|
||||
pageStack.title = globalConfigModel.get(0).name
|
||||
}
|
||||
// root.width = dialogRootItem.implicitWidth
|
||||
// root.height = dialogRootItem.implicitHeight
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
dialogContents.visible = true;
|
||||
open(configDialog.configModel.get(0))
|
||||
}
|
||||
}
|
||||
|
||||
//END connections
|
||||
|
||||
//BEGIN UI components
|
||||
|
||||
Rectangle {
|
||||
id: dialogContents
|
||||
visible: true
|
||||
Component {
|
||||
id: configurationKcmPageComponent
|
||||
ConfigurationKcmPage {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: configCategoryDelegate
|
||||
Kirigami.NavigationTabButton {
|
||||
icon.name: model.icon
|
||||
text: model.name
|
||||
// recolorIcon: false
|
||||
QQC2.ButtonGroup.group: footerBar.tabGroup
|
||||
|
||||
onClicked: {
|
||||
if (checked) {
|
||||
root.open(model);
|
||||
}
|
||||
}
|
||||
|
||||
checked: {
|
||||
if (app.pageStack.currentItem) {
|
||||
if (model.kcm && app.pageStack.currentItem.kcm) {
|
||||
return model.kcm == app.pageStack.currentItem.kcm;
|
||||
} else if (app.pageStack.currentItem.configItem) {
|
||||
return model.source == app.pageStack.currentItem.configItem.source;
|
||||
} else {
|
||||
return app.pageStack.currentItem.source == Qt.resolvedUrl(model.source);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.ApplicationItem {
|
||||
id: app
|
||||
anchors.fill: parent
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
|
||||
ColumnLayout {
|
||||
id: dialogRootItem
|
||||
anchors.fill: parent
|
||||
|
||||
spacing: 0
|
||||
implicitWidth: scroll.implicitWidth
|
||||
|
||||
QtControls.ScrollView {
|
||||
id: scroll
|
||||
|
||||
activeFocusOnTab: false
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
implicitWidth: pageColumn.implicitWidth
|
||||
implicitHeight: pageColumn.implicitHeight
|
||||
|
||||
property Item flickableItem: pageFlickable
|
||||
// this horrible code below ensures the control with active focus stays visible in the window
|
||||
// by scrolling the view up or down as needed when tabbing through the window
|
||||
Window.onActiveFocusItemChanged: {
|
||||
var flickable = scroll.flickableItem;
|
||||
|
||||
var item = Window.activeFocusItem;
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
// when an item within ScrollView has active focus the ScrollView,
|
||||
// as FocusScope, also has it, so we only scroll in this case
|
||||
if (!scroll.activeFocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
var padding = PlasmaCore.Units.gridUnit * 2 // some padding to the top/bottom when we scroll
|
||||
|
||||
var yPos = item.mapToItem(scroll.contentItem, 0, 0).y;
|
||||
if (yPos < flickable.contentY) {
|
||||
flickable.contentY = Math.max(0, yPos - padding);
|
||||
|
||||
// The "Math.min(padding, item.height)" ensures that we only scroll the item into view
|
||||
// when it's barely visible. The logic was mostly meant for keyboard navigating through
|
||||
// a list of CheckBoxes, so this check keeps us from trying to scroll an inner ScrollView
|
||||
// into view when it implicitly gains focus (like plasma-pa config dialog has).
|
||||
} else if (yPos + Math.min(padding, item.height) > flickable.contentY + flickable.height) {
|
||||
flickable.contentY = Math.min(flickable.contentHeight - flickable.height,
|
||||
yPos - flickable.height + item.height + padding);
|
||||
}
|
||||
}
|
||||
Flickable {
|
||||
id: pageFlickable
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: PlasmaCore.Units.smallSpacing
|
||||
}
|
||||
contentHeight: pageColumn.height
|
||||
contentWidth: width
|
||||
ColumnLayout {
|
||||
id: pageColumn
|
||||
spacing: PlasmaCore.Units.largeSpacing / 2
|
||||
width: pageFlickable.width
|
||||
height: Math.max(implicitHeight, pageFlickable.height)
|
||||
|
||||
Kirigami.Heading {
|
||||
id: pageTitle
|
||||
Layout.fillWidth: true
|
||||
level: 1
|
||||
text: pageStack.title
|
||||
}
|
||||
|
||||
QtControls.StackView {
|
||||
id: pageStack
|
||||
property string title: ""
|
||||
property bool invertAnimations: false
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
implicitWidth: Math.max(currentItem ? Math.max(currentItem.Layout.minimumWidth, currentItem.Layout.preferredWidth, currentItem.implicitWidth) : 0, PlasmaCore.Units.gridUnit * 15)
|
||||
implicitHeight: Math.max(currentItem ? Math.max(currentItem.Layout.minimumHeight, currentItem.Layout.preferredHeight, currentItem.implicitHeight) : 0, PlasmaCore.Units.gridUnit * 15)
|
||||
|
||||
property string sourceFile
|
||||
|
||||
onSourceFileChanged: {
|
||||
if (!sourceFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
//in a StackView pages need to be initialized with stackviews size, or have none
|
||||
var props = {"width": width, "height": height}
|
||||
|
||||
var plasmoidConfig = plasmoid.configuration
|
||||
for (var key in plasmoidConfig) {
|
||||
props["cfg_" + key] = plasmoid.configuration[key]
|
||||
}
|
||||
|
||||
var newItem = replace(Qt.resolvedUrl(sourceFile), props)
|
||||
|
||||
for (var key in plasmoidConfig) {
|
||||
var changedSignal = newItem["cfg_" + key + "Changed"]
|
||||
if (changedSignal) {
|
||||
changedSignal.connect(root.settingValueChanged)
|
||||
}
|
||||
}
|
||||
|
||||
var configurationChangedSignal = newItem.configurationChanged
|
||||
if (configurationChangedSignal) {
|
||||
configurationChangedSignal.connect(root.settingValueChanged)
|
||||
}
|
||||
|
||||
scroll.flickableItem.contentY = 0
|
||||
|
||||
/*
|
||||
for (var prop in currentItem) {
|
||||
if (prop.indexOf("cfg_") === 0) {
|
||||
currentItem[prop+"Changed"].connect(root.pageChanged)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
replaceEnter: Transition {
|
||||
ParallelAnimation {
|
||||
//OpacityAnimator when starting from 0 is buggy (it shows one frame with opacity 1)
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
from: 0
|
||||
to: 1
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
XAnimator {
|
||||
from: pageStack.invertAnimations ? -scroll.width/3: scroll.width/3
|
||||
to: 0
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
replaceExit: Transition {
|
||||
ParallelAnimation {
|
||||
OpacityAnimator {
|
||||
from: 1
|
||||
to: 0
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
XAnimator {
|
||||
from: 0
|
||||
to: pageStack.invertAnimations ? scroll.width/3 : -scroll.width/3
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pageStack.globalToolBar.canContainHandles: true
|
||||
pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.ToolBar
|
||||
pageStack.globalToolBar.showNavigationButtons: Kirigami.ApplicationHeaderStyle.ShowBackButton;
|
||||
|
||||
property var currentConfigPage: null
|
||||
property bool isAboutPage: false
|
||||
|
||||
// pop pages when not in use
|
||||
Connections {
|
||||
target: app.pageStack
|
||||
function onCurrentIndexChanged() {
|
||||
// wait for animation to finish before popping pages
|
||||
timer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 300
|
||||
onTriggered: {
|
||||
let currentIndex = app.pageStack.currentIndex;
|
||||
while (app.pageStack.depth > (currentIndex + 1) && currentIndex >= 0) {
|
||||
app.pageStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: separator
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 1
|
||||
color: Kirigami.Theme.highlightColor
|
||||
visible: categoriesScroll.visible
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
footer: Kirigami.NavigationTabBar {
|
||||
id: footerBar
|
||||
visible: count > 1
|
||||
height: visible ? implicitHeight : 0
|
||||
Repeater {
|
||||
model: root.isContainment ? globalConfigModel : undefined
|
||||
delegate: configCategoryDelegate
|
||||
}
|
||||
|
||||
QtControls.ScrollView {
|
||||
id: categoriesScroll
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: categories.implicitHeight
|
||||
|
||||
visible: (configDialog.configModel ? configDialog.configModel.count : 0) + globalConfigModel.count > 1
|
||||
|
||||
Keys.onLeftPressed: {
|
||||
var buttons = categories.children
|
||||
|
||||
var foundPrevious = false
|
||||
for (var i = buttons.length - 1; i >= 0; --i) {
|
||||
var button = buttons[i];
|
||||
if (!button.hasOwnProperty("current")) {
|
||||
// not a ConfigCategoryDelegate
|
||||
continue;
|
||||
}
|
||||
|
||||
if (foundPrevious) {
|
||||
button.openCategory()
|
||||
return
|
||||
} else if (button.current) {
|
||||
foundPrevious = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onRightPressed: {
|
||||
var buttons = categories.children
|
||||
|
||||
var foundNext = false
|
||||
for (var i = 0, length = buttons.length; i < length; ++i) {
|
||||
var button = buttons[i];
|
||||
console.log(button)
|
||||
if (!button.hasOwnProperty("current")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (foundNext) {
|
||||
button.openCategory()
|
||||
return
|
||||
} else if (button.current) {
|
||||
foundNext = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: categories
|
||||
spacing: 0
|
||||
width: categoriesScroll.width
|
||||
height: implicitHeight
|
||||
|
||||
property Item currentItem: children[1]
|
||||
|
||||
Repeater {
|
||||
model: root.isContainment ? globalConfigModel : undefined
|
||||
delegate: ConfigCategoryDelegate {}
|
||||
}
|
||||
Repeater {
|
||||
model: configDialogFilterModel
|
||||
delegate: ConfigCategoryDelegate {}
|
||||
}
|
||||
Repeater {
|
||||
model: !root.isContainment ? globalConfigModel : undefined
|
||||
delegate: ConfigCategoryDelegate {}
|
||||
}
|
||||
}
|
||||
Repeater {
|
||||
model: configDialogFilterModel
|
||||
delegate: configCategoryDelegate
|
||||
}
|
||||
Repeater {
|
||||
model: !root.isContainment ? globalConfigModel : undefined
|
||||
delegate: configCategoryDelegate
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//END UI components
|
||||
|
|
|
|||
|
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls 2.3 as QtControls
|
||||
import QtQuick.Window 2.2
|
||||
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.kquickcontrolsaddons 2.0
|
||||
import org.kde.kirigami 2.5 as Kirigami
|
||||
|
||||
MouseArea {
|
||||
id: delegate
|
||||
|
||||
//BEGIN properties
|
||||
implicitWidth: delegateContents.implicitWidth + 4 * PlasmaCore.Units.smallSpacing
|
||||
implicitHeight: delegateContents.height + PlasmaCore.Units.smallSpacing * 4
|
||||
Layout.fillWidth: true
|
||||
hoverEnabled: true
|
||||
|
||||
property bool current: (model.kcm && pageStack.currentItem.kcm && model.kcm == pageStack.currentItem.kcm) || (model.source == pageStack.sourceFile)
|
||||
//END properties
|
||||
|
||||
//BEGIN functions
|
||||
function openCategory() {
|
||||
if (current) {
|
||||
return;
|
||||
}
|
||||
if (typeof(categories.currentItem) !== "undefined") {
|
||||
pageStack.invertAnimations = (categories.currentItem.x > delegate.x);
|
||||
categories.currentItem = delegate;
|
||||
}
|
||||
|
||||
if (model.source) {
|
||||
pageStack.sourceFile = model.source;
|
||||
} else if (model.kcm) {
|
||||
pageStack.sourceFile = "";
|
||||
pageStack.sourceFile = Qt.resolvedUrl("ConfigurationKcmPage.qml");
|
||||
pageStack.currentItem.kcm = model.kcm;
|
||||
} else {
|
||||
pageStack.sourceFile = "";
|
||||
}
|
||||
pageStack.title = model.name
|
||||
}
|
||||
//END functions
|
||||
|
||||
//BEGIN connections
|
||||
onPressed: {
|
||||
categoriesScroll.forceActiveFocus()
|
||||
|
||||
if (current) {
|
||||
return;
|
||||
}
|
||||
|
||||
openCategory();
|
||||
}
|
||||
onCurrentChanged: {
|
||||
if (current) {
|
||||
categories.currentItem = delegate;
|
||||
}
|
||||
}
|
||||
//END connections
|
||||
|
||||
//BEGIN UI components
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Kirigami.Theme.highlightColor
|
||||
opacity: { // try to match Breeze style hover handling
|
||||
var active = categoriesScroll.activeFocus && Window.active
|
||||
if (current) {
|
||||
if (active) {
|
||||
return 1
|
||||
} else if (delegate.containsMouse) {
|
||||
return 0.6
|
||||
} else {
|
||||
return 0.3
|
||||
}
|
||||
} else if (delegate.containsMouse) {
|
||||
if (active) {
|
||||
return 0.3
|
||||
} else {
|
||||
return 0.1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: delegateContents
|
||||
spacing: PlasmaCore.Units.smallSpacing
|
||||
width: parent.width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
QIconItem {
|
||||
id: iconItem
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
width: PlasmaCore.Units.iconSizes.medium
|
||||
height: width
|
||||
icon: model.icon
|
||||
state: current && categoriesScroll.activeFocus ? QIconItem.SelectedState : QIconItem.DefaultState
|
||||
}
|
||||
|
||||
QtControls.Label {
|
||||
id: nameLabel
|
||||
Layout.fillWidth: true
|
||||
text: model.name
|
||||
wrapMode: Text.Wrap
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: current && categoriesScroll.activeFocus ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//END UI components
|
||||
}
|
||||
|
||||
72
shell/contents/configuration/ConfigurationAppletPage.qml
Normal file
72
shell/contents/configuration/ConfigurationAppletPage.qml
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
// SPDX-FileCopyrightText: 2020 Nicolas Fella <nicolas.fella@gmx.de>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick 2.0
|
||||
|
||||
import org.kde.kirigami 2.10 as Kirigami
|
||||
|
||||
Kirigami.ScrollablePage {
|
||||
id: root
|
||||
|
||||
title: configItem.name
|
||||
|
||||
required property var configItem
|
||||
|
||||
signal settingValueChanged()
|
||||
|
||||
function saveConfig() {
|
||||
for (let key in plasmoid.configuration) {
|
||||
if (loader.item["cfg_" + key] != undefined) {
|
||||
plasmoid.configuration[key] = loader.item["cfg_" + key]
|
||||
}
|
||||
}
|
||||
|
||||
// For ConfigurationContainmentActions.qml
|
||||
if (loader.item.hasOwnProperty("saveConfig")) {
|
||||
loader.item.saveConfig()
|
||||
}
|
||||
}
|
||||
|
||||
implicitHeight: loader.height
|
||||
|
||||
padding: Kirigami.Units.largeSpacing
|
||||
bottomPadding: 0
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
width: parent.width
|
||||
// HACK the height of the loader is based on the implicitHeight of the content.
|
||||
// Unfortunately not all content items have a sensible implicitHeight.
|
||||
// If it is zero fall back to the height of its children
|
||||
// Also make it at least as high as the page itself. Some existing configs assume they fill the whole space
|
||||
// TODO KF6 clean this up by making all configs based on SimpleKCM/ScrollViewKCM/GridViewKCM
|
||||
height: Math.max(root.availableHeight, item.implicitHeight ? item.implicitHeight : item.childrenRect.height)
|
||||
|
||||
Component.onCompleted: {
|
||||
const plasmoidConfig = plasmoid.configuration
|
||||
|
||||
const props = {}
|
||||
for (let key in plasmoidConfig) {
|
||||
props["cfg_" + key] = plasmoid.configuration[key]
|
||||
}
|
||||
|
||||
setSource(configItem.source, props)
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
const plasmoidConfig = plasmoid.configuration;
|
||||
|
||||
for (let key in plasmoidConfig) {
|
||||
const changedSignal = item["cfg_" + key + "Changed"]
|
||||
if (changedSignal) {
|
||||
changedSignal.connect(root.settingValueChanged)
|
||||
}
|
||||
}
|
||||
|
||||
const configurationChangedSignal = item.configurationChanged
|
||||
if (configurationChangedSignal) {
|
||||
configurationChangedSignal.connect(root.settingValueChanged)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -136,12 +136,6 @@ ColumnLayout {
|
|||
text: i18nd("plasma_shell_org.kde.plasma.desktop", "Apply now")
|
||||
onClicked: saveConfig()
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: categoriesScroll //from parent scope AppletConfiguration
|
||||
property: "enabled"
|
||||
value: !switchContainmentWarning.visible
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
|
|
|
|||
73
shell/contents/configuration/ConfigurationKcmPage.qml
Normal file
73
shell/contents/configuration/ConfigurationKcmPage.qml
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
|
||||
// SPDX-FileCopyrightText: 2020 Nicolas Fella <nicolas.fella@gmx.de>
|
||||
// SPDX-FileCopyrightText: 2020 Carl Schwan <carlschwan@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Controls 2.2 as QQC2
|
||||
import org.kde.kirigami 2.5 as Kirigami
|
||||
|
||||
Kirigami.Page {
|
||||
id: container
|
||||
|
||||
required property QtObject kcm
|
||||
required property Item internalPage
|
||||
|
||||
signal settingValueChanged()
|
||||
|
||||
title: kcm.name
|
||||
topPadding: 0
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
bottomPadding: 0
|
||||
flickable: internalPage.flickable
|
||||
actions.main: internalPage.actions.main
|
||||
actions.contextualActions: internalPage.contextualActions
|
||||
|
||||
onInternalPageChanged: {
|
||||
internalPage.parent = contentItem;
|
||||
internalPage.anchors.fill = contentItem;
|
||||
}
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
internalPage.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
kcm.load()
|
||||
}
|
||||
|
||||
function saveConfig() {
|
||||
kcm.save();
|
||||
}
|
||||
|
||||
data: [
|
||||
Connections {
|
||||
target: kcm
|
||||
onPagePushed: {
|
||||
app.pageStack.push(configurationKcmPageComponent.createObject(app.pageStack, {"kcm": kcm, "internalPage": page}));
|
||||
}
|
||||
onPageRemoved: app.pageStack.pop();
|
||||
},
|
||||
Connections {
|
||||
target: app.pageStack
|
||||
onPageRemoved: {
|
||||
if (kcm.needsSave) {
|
||||
kcm.save()
|
||||
}
|
||||
if (page == container) {
|
||||
page.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
Connections {
|
||||
target: kcm
|
||||
function onNeedsSaveChanged() {
|
||||
if (kcm.needsSave) {
|
||||
container.settingValueChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +1,23 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
// SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
|
||||
// SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Window 2.2
|
||||
import QtQuick.Controls 2.3 as Controls
|
||||
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||
import QtQuick.Controls 2.15 as Controls
|
||||
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents3
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.configuration 2.0
|
||||
|
||||
//for the "simple mode"
|
||||
import org.kde.plasma.wallpapers.image 2.0 as Wallpaper
|
||||
import org.kde.kquickcontrolsaddons 2.0 as Addons
|
||||
import org.kde.kcm 1.1 as KCM
|
||||
|
||||
AppletConfiguration {
|
||||
id: root
|
||||
isContainment: true
|
||||
|
||||
internalDialog.visible: false
|
||||
internalDialog.width: root.width < root.height ? root.width : Math.min(root.width, Math.max(internalDialog.implicitWidth, PlasmaCore.Units.gridUnit * 45))
|
||||
internalDialog.height: Math.min(root.height, Math.max(internalDialog.implicitHeight, PlasmaCore.Units.gridUnit * 29))
|
||||
appComponent.visible: false
|
||||
appComponent.width: root.width < root.height ? root.width : Math.min(root.width, Math.max(appComponent.implicitWidth, PlasmaCore.Units.gridUnit * 45))
|
||||
appComponent.height: Math.min(root.height, Math.max(appComponent.implicitHeight, PlasmaCore.Units.gridUnit * 29))
|
||||
|
||||
readonly property bool horizontal: root.width > root.height
|
||||
|
||||
|
|
@ -40,126 +34,74 @@ AppletConfiguration {
|
|||
}
|
||||
//END model
|
||||
|
||||
Controls.Drawer {
|
||||
id: imageWallpaperDrawer
|
||||
edge: root.horizontal ? Qt.LeftEdge : Qt.BottomEdge
|
||||
visible: true
|
||||
dragMargin: 0
|
||||
|
||||
onClosed: {
|
||||
if (!root.internalDialog.visible) {
|
||||
configDialog.close()
|
||||
Loader {
|
||||
id: wallpaperSelectorLoader
|
||||
asynchronous: true
|
||||
active: true
|
||||
|
||||
sourceComponent: WallpaperSelector {
|
||||
visible: false
|
||||
horizontal: root.horizontal
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
z: -1
|
||||
anchors.fill: parent
|
||||
onClicked: configDialog.close()
|
||||
|
||||
Controls.Control {
|
||||
anchors.centerIn: parent
|
||||
leftPadding: PlasmaCore.Units.largeSpacing
|
||||
rightPadding: PlasmaCore.Units.largeSpacing
|
||||
topPadding: PlasmaCore.Units.largeSpacing
|
||||
bottomPadding: PlasmaCore.Units.largeSpacing
|
||||
|
||||
NumberAnimation on opacity {
|
||||
id: opacityAnim
|
||||
running: true
|
||||
from: 0
|
||||
to: 1
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
}
|
||||
}
|
||||
onOpened: {
|
||||
wallpapersView.forceActiveFocus()
|
||||
}
|
||||
implicitWidth: PlasmaCore.Units.gridUnit * 10
|
||||
implicitHeight: PlasmaCore.Units.gridUnit * 8
|
||||
width: root.horizontal ? implicitWidth : root.width
|
||||
height: root.horizontal ? root.height : implicitHeight
|
||||
Wallpaper.ImageBackend {
|
||||
id: imageWallpaper
|
||||
}
|
||||
background: null
|
||||
|
||||
ListView {
|
||||
id: wallpapersView
|
||||
anchors.fill: parent
|
||||
orientation: root.horizontal ? ListView.Vertical : ListView.Horizontal
|
||||
keyNavigationEnabled: true
|
||||
highlightFollowsCurrentItem: true
|
||||
snapMode: ListView.SnapToItem
|
||||
model: imageWallpaper.wallpaperModel
|
||||
onCountChanged: currentIndex = Math.min(model.indexOf(configDialog.wallpaperConfiguration["Image"]), model.rowCount()-1)
|
||||
footer: Controls.Control {
|
||||
z: 999
|
||||
width: root.horizontal ? parent.width : implicitWidth
|
||||
height: root.horizontal ? implicitHeight : parent.height
|
||||
leftPadding: PlasmaCore.Units.gridUnit
|
||||
topPadding: PlasmaCore.Units.gridUnit
|
||||
rightPadding: PlasmaCore.Units.gridUnit
|
||||
bottomPadding: PlasmaCore.Units.gridUnit
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
Controls.Button {
|
||||
icon.name: "configure"
|
||||
text: i18nd("plasma_shell_org.kde.plasma.desktop", "Customize...")
|
||||
onClicked: {
|
||||
print(wallpapersView.currentIndex)
|
||||
internalDialog.visible = true;
|
||||
imageWallpaperDrawer.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
background: Rectangle {
|
||||
color: Qt.rgba (0, 0, 0, 0.3)
|
||||
}
|
||||
|
||||
background: PlasmaCore.FrameSvgItem {
|
||||
enabledBorders: PlasmaCore.FrameSvg.AllBorders
|
||||
imagePath: "widgets/background"
|
||||
}
|
||||
headerPositioning: ListView.PullBackHeader
|
||||
delegate: Controls.ItemDelegate {
|
||||
width: root.horizontal ? parent.width : height * (root.Screen.width / root.Screen.height)
|
||||
height: root.horizontal ? width / (root.Screen.width / root.Screen.height) : parent.height
|
||||
padding: wallpapersView.currentIndex === index ? PlasmaCore.Units.gridUnit / 4 : PlasmaCore.Units.gridUnit / 2
|
||||
leftPadding: padding
|
||||
topPadding: padding
|
||||
rightPadding: padding
|
||||
bottomPadding: padding
|
||||
Behavior on padding {
|
||||
NumberAnimation {
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
|
||||
property bool isCurrent: configDialog.wallpaperConfiguration["Image"] == model.path
|
||||
onIsCurrentChanged: {
|
||||
if (isCurrent) {
|
||||
wallpapersView.currentIndex = index;
|
||||
|
||||
contentItem: RowLayout {
|
||||
PlasmaComponents3.Button {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.preferredHeight: PlasmaCore.Units.gridUnit * 4
|
||||
Layout.preferredWidth: PlasmaCore.Units.gridUnit * 8
|
||||
|
||||
display: PlasmaComponents3.ToolButton.TextUnderIcon
|
||||
icon.name: "viewimage"
|
||||
icon.width: PlasmaCore.Units.iconSizes.medium
|
||||
icon.height: PlasmaCore.Units.iconSizes.medium
|
||||
text: i18n("Change Wallpaper")
|
||||
onClicked: {
|
||||
opacityAnim.from = 1;
|
||||
opacityAnim.to = 0;
|
||||
opacityAnim.restart();
|
||||
wallpaperSelectorLoader.item.open();
|
||||
}
|
||||
}
|
||||
|
||||
z: wallpapersView.currentIndex === index ? 2 : 0
|
||||
contentItem: Item {
|
||||
Addons.QIconItem {
|
||||
anchors.centerIn: parent
|
||||
width: PlasmaCore.Units.iconSizes.large
|
||||
height: width
|
||||
icon: "view-preview"
|
||||
visible: !walliePreview.visible
|
||||
}
|
||||
|
||||
Addons.QPixmapItem {
|
||||
id: walliePreview
|
||||
anchors.fill: parent
|
||||
visible: model.screenshot != null
|
||||
smooth: true
|
||||
pixmap: model.screenshot
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
configDialog.currentWallpaper = "org.kde.image";
|
||||
configDialog.wallpaperConfiguration["Image"] = model.path;
|
||||
configDialog.applyWallpaper()
|
||||
}
|
||||
Keys.onReturnPressed: {
|
||||
clicked();
|
||||
}
|
||||
background: Item {
|
||||
Rectangle {
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: wallpapersView.currentIndex === index ? 0 : PlasmaCore.Units.gridUnit / 4
|
||||
Behavior on margins {
|
||||
NumberAnimation {
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
radius: PlasmaCore.Units.gridUnit / 4
|
||||
PlasmaComponents3.Button {
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
Layout.preferredHeight: PlasmaCore.Units.gridUnit * 4
|
||||
Layout.preferredWidth: PlasmaCore.Units.gridUnit * 8
|
||||
|
||||
display: PlasmaComponents3.ToolButton.TextUnderIcon
|
||||
icon.name: "configure"
|
||||
icon.width: PlasmaCore.Units.iconSizes.medium
|
||||
icon.height: PlasmaCore.Units.iconSizes.medium
|
||||
text: i18n("Configure")
|
||||
onClicked: {
|
||||
appComponent.visible = true;
|
||||
wallpaperSelectorLoader.item.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
120
shell/contents/configuration/WallpaperSelector.qml
Normal file
120
shell/contents/configuration/WallpaperSelector.qml
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
// SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
|
||||
// SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Window 2.2
|
||||
import QtQuick.Controls 2.3 as Controls
|
||||
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.configuration 2.0
|
||||
|
||||
import org.kde.plasma.wallpapers.image 2.0 as Wallpaper
|
||||
import org.kde.kquickcontrolsaddons 2.0 as Addons
|
||||
import org.kde.kcm 1.1 as KCM
|
||||
|
||||
Controls.Drawer {
|
||||
id: imageWallpaperDrawer
|
||||
edge: root.horizontal ? Qt.LeftEdge : Qt.BottomEdge
|
||||
dragMargin: 0
|
||||
|
||||
required property bool horizontal
|
||||
|
||||
onClosed: {
|
||||
if (!root.appComponent.visible) {
|
||||
configDialog.close()
|
||||
}
|
||||
}
|
||||
onOpened: {
|
||||
wallpapersView.forceActiveFocus()
|
||||
}
|
||||
implicitWidth: PlasmaCore.Units.gridUnit * 10
|
||||
implicitHeight: PlasmaCore.Units.gridUnit * 8
|
||||
width: imageWallpaperDrawer.horizontal ? implicitWidth : root.width
|
||||
height: imageWallpaperDrawer.horizontal ? root.height : implicitHeight
|
||||
|
||||
Wallpaper.ImageBackend {
|
||||
id: imageWallpaper
|
||||
}
|
||||
|
||||
background: null
|
||||
|
||||
ListView {
|
||||
id: wallpapersView
|
||||
anchors.fill: parent
|
||||
orientation: imageWallpaperDrawer.horizontal ? ListView.Vertical : ListView.Horizontal
|
||||
keyNavigationEnabled: true
|
||||
highlightFollowsCurrentItem: true
|
||||
snapMode: ListView.SnapToItem
|
||||
model: imageWallpaper.wallpaperModel
|
||||
onCountChanged: currentIndex = Math.min(model.indexOf(configDialog.wallpaperConfiguration["Image"]), model.rowCount()-1)
|
||||
headerPositioning: ListView.PullBackHeader
|
||||
delegate: Controls.ItemDelegate {
|
||||
width: imageWallpaperDrawer.horizontal ? parent.width : height * (root.Screen.width / root.Screen.height)
|
||||
height: imageWallpaperDrawer.horizontal ? width / (root.Screen.width / root.Screen.height) : parent.height
|
||||
padding: wallpapersView.currentIndex === index ? PlasmaCore.Units.gridUnit / 4 : PlasmaCore.Units.gridUnit / 2
|
||||
leftPadding: padding
|
||||
topPadding: padding
|
||||
rightPadding: padding
|
||||
bottomPadding: padding
|
||||
Behavior on padding {
|
||||
NumberAnimation {
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
|
||||
property bool isCurrent: configDialog.wallpaperConfiguration["Image"] == model.path
|
||||
onIsCurrentChanged: {
|
||||
if (isCurrent) {
|
||||
wallpapersView.currentIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
z: wallpapersView.currentIndex === index ? 2 : 0
|
||||
contentItem: Item {
|
||||
Addons.QIconItem {
|
||||
anchors.centerIn: parent
|
||||
width: PlasmaCore.Units.iconSizes.large
|
||||
height: width
|
||||
icon: "view-preview"
|
||||
visible: !walliePreview.visible
|
||||
}
|
||||
|
||||
Addons.QPixmapItem {
|
||||
id: walliePreview
|
||||
anchors.fill: parent
|
||||
visible: model.screenshot != null
|
||||
smooth: true
|
||||
pixmap: model.screenshot
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
configDialog.currentWallpaper = "org.kde.image";
|
||||
configDialog.wallpaperConfiguration["Image"] = model.path;
|
||||
configDialog.applyWallpaper()
|
||||
}
|
||||
Keys.onReturnPressed: {
|
||||
clicked();
|
||||
}
|
||||
background: Item {
|
||||
Rectangle {
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: wallpapersView.currentIndex === index ? 0 : PlasmaCore.Units.gridUnit / 4
|
||||
Behavior on margins {
|
||||
NumberAnimation {
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
radius: PlasmaCore.Units.gridUnit / 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue