Commit c2640f83 authored by Marco Martin's avatar Marco Martin

Port applet/containment configs to qqc2

Summary:
port the applet config dialogs and containments to
QtQuickControls2 and Kirigami modernizing it,
using form layouts, Headings and inline messages.
look is almost the same modulo fixing some misalignments and following
the hig more closely

BUG: 401472
FIXED-IN: 5.15.0

Test Plan:
looked at every wallpaper plugin and
loaded the config dialog of many applets

Reviewers: #plasma, #vdg, broulik, ngraham

Reviewed By: #vdg, ngraham

Subscribers: abetts, ngraham, apol, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D17211
parent 2460a8aa
......@@ -16,12 +16,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA.
*/
import QtQuick 2.0
import QtQuick 2.6
import QtQuick.Dialogs 1.1
import QtQuick.Controls 1.3 as QtControls
import QtQuick.Controls 2.3 as QtControls
import QtQuick.Layouts 1.0
import QtQuick.Window 2.2
import org.kde.kirigami 2.5 as Kirigami
import org.kde.plasma.core 2.1 as PlasmaCore
import org.kde.plasma.configuration 2.0
......@@ -36,7 +37,7 @@ Rectangle {
LayoutMirroring.childrenInherit: true
//BEGIN properties
color: syspal.window
color: Kirigami.Theme.backgroundColor
width: units.gridUnit * 40
height: units.gridUnit * 30
......@@ -65,12 +66,12 @@ Rectangle {
//BEGIN functions
function saveConfig() {
if (main.currentItem.saveConfig) {
main.currentItem.saveConfig()
if (pageStack.currentItem.saveConfig) {
pageStack.currentItem.saveConfig()
}
for (var key in plasmoid.configuration) {
if (main.currentItem["cfg_"+key] !== undefined) {
plasmoid.configuration[key] = main.currentItem["cfg_"+key]
if (pageStack.currentItem["cfg_"+key] !== undefined) {
plasmoid.configuration[key] = pageStack.currentItem["cfg_"+key]
}
}
}
......@@ -85,26 +86,24 @@ Rectangle {
Component.onCompleted: {
if (!isContainment && configDialog.configModel && configDialog.configModel.count > 0) {
if (configDialog.configModel.get(0).source) {
main.sourceFile = configDialog.configModel.get(0).source
pageStack.sourceFile = configDialog.configModel.get(0).source
} else if (configDialog.configModel.get(0).kcm) {
main.sourceFile = Qt.resolvedUrl("ConfigurationKcmPage.qml");
main.currentItem.kcm = configDialog.configModel.get(0).kcm;
pageStack.sourceFile = Qt.resolvedUrl("ConfigurationKcmPage.qml");
pageStack.currentItem.kcm = configDialog.configModel.get(0).kcm;
} else {
main.sourceFile = "";
pageStack.sourceFile = "";
}
main.title = configDialog.configModel.get(0).name
pageStack.title = configDialog.configModel.get(0).name
} else {
main.sourceFile = globalConfigModel.get(0).source
main.title = globalConfigModel.get(0).name
pageStack.sourceFile = globalConfigModel.get(0).source
pageStack.title = globalConfigModel.get(0).name
}
// root.width = mainColumn.implicitWidth
// root.height = mainColumn.implicitHeight
// root.width = pageStackColumn.implicitWidth
// root.height = pageStackColumn.implicitHeight
}
//END connections
//BEGIN UI components
SystemPalette {id: syspal}
MessageDialog {
id: messageDialog
icon: StandardIcon.Warning
......@@ -122,10 +121,10 @@ Rectangle {
}
ColumnLayout {
id: mainColumn
id: pageStackColumn
anchors {
fill: parent
margins: mainColumn.spacing * units.devicePixelRatio //margins are hardcoded in QStyle we should match that here
margins: pageStackColumn.spacing * units.devicePixelRatio //margins are hardcoded in QStyle we should match that here
}
property int implicitWidth: Math.max(contentRow.implicitWidth, buttonsRow.implicitWidth) + 8
property int implicitHeight: contentRow.implicitHeight + buttonsRow.implicitHeight + 8
......@@ -139,13 +138,11 @@ Rectangle {
QtControls.ScrollView {
id: categoriesScroll
frameVisible: false
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
QtControls.ScrollBar.horizontal.policy: QtControls.ScrollBar.AlwaysOff
Layout.fillHeight: true
visible: (configDialog.configModel ? configDialog.configModel.count : 0) + globalConfigModel.count > 1
Layout.maximumWidth: units.gridUnit * 7
Layout.preferredWidth: categories.implicitWidth
flickableItem.interactive: false
Keys.onUpPressed: {
var buttons = categories.children
......@@ -190,7 +187,7 @@ Rectangle {
ColumnLayout {
id: categories
spacing: 0
width: categoriesScroll.viewport.width
width: categoriesScroll.width
property Item currentItem: children[1]
......@@ -212,7 +209,7 @@ Rectangle {
Rectangle {
Layout.fillHeight: true
width: Math.round(units.devicePixelRatio)
color: syspal.highlight
color: Kirigami.Theme.highlightColor
visible: categoriesScroll.visible
opacity: categoriesScroll.activeFocus && Window.active ? 1 : 0.3
Behavior on color {
......@@ -235,6 +232,7 @@ Rectangle {
// we want to focus the controls in the settings page right away, don't focus the ScrollView
activeFocusOnTab: false
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: {
......@@ -266,109 +264,104 @@ Rectangle {
yPos - flickable.height + item.height + padding);
}
}
Flickable {
id: pageFlickable
anchors.fill: parent
contentHeight: pageColumn.height
contentWidth: width
Column {
id: pageColumn
spacing: units.largeSpacing / 2
Kirigami.Heading {
id: pageTitle
width: scroll.width
level: 1
text: pageStack.title
}
Column {
spacing: units.largeSpacing / 2
QtControls.Label {
id: pageTitle
width: scroll.viewport.width
font.pointSize: theme.defaultFont.pointSize*2
font.weight: Font.Light
text: main.title
}
QtControls.StackView {
id: main
property string title: ""
property bool invertAnimations: false
height: Math.max((scroll.viewport.height - pageTitle.height - parent.spacing), (main.currentItem ? (main.currentItem.implicitHeight ? main.currentItem.implicitHeight : main.currentItem.childrenRect.height) : 0))
width: scroll.viewport.width
property string sourceFile
QtControls.StackView {
id: pageStack
property string title: ""
property bool invertAnimations: false
onSourceFileChanged: {
if (!sourceFile) {
return;
}
height: Math.max((scroll.height - pageTitle.height - parent.spacing), (pageStack.currentItem ? (pageStack.currentItem.implicitHeight ? pageStack.currentItem.implicitHeight : pageStack.currentItem.childrenRect.height) : 0))
width: scroll.width
var props = {}
property string sourceFile
var plasmoidConfig = plasmoid.configuration
for (var key in plasmoidConfig) {
props["cfg_" + key] = plasmoid.configuration[key]
}
onSourceFileChanged: {
if (!sourceFile) {
return;
}
var newItem = push({
item: Qt.resolvedUrl(sourceFile),
replace: true,
properties: props
})
//in a StackView pages need to be initialized with stackviews size, or have none
var props = {"width": width, "height": height}
for (var key in plasmoidConfig) {
var changedSignal = newItem["cfg_" + key + "Changed"]
if (changedSignal) {
changedSignal.connect(root.settingValueChanged)
var plasmoidConfig = plasmoid.configuration
for (var key in plasmoidConfig) {
props["cfg_" + key] = plasmoid.configuration[key]
}
}
var configurationChangedSignal = newItem.configurationChanged
if (configurationChangedSignal) {
configurationChangedSignal.connect(root.settingValueChanged)
}
var newItem = replace(Qt.resolvedUrl(sourceFile), props)
applyButton.enabled = false;
scroll.flickableItem.contentY = 0
/*
* This is not needed on a desktop shell that has ok/apply/cancel buttons, i'll leave it here only for future reference until we have a prototype for the active shell.
* root.pageChanged will start a timer, that in turn will call saveConfig() when triggered
for (var key in plasmoidConfig) {
var changedSignal = newItem["cfg_" + key + "Changed"]
if (changedSignal) {
changedSignal.connect(root.settingValueChanged)
}
}
for (var prop in currentItem) {
if (prop.indexOf("cfg_") === 0) {
currentItem[prop+"Changed"].connect(root.pageChanged)
var configurationChangedSignal = newItem.configurationChanged
if (configurationChangedSignal) {
configurationChangedSignal.connect(root.settingValueChanged)
}
}*/
}
delegate: QtControls.StackViewDelegate {
function transitionFinished(properties)
{
properties.exitItem.opacity = 1
applyButton.enabled = false;
scroll.flickableItem.contentY = 0
/*
* This is not needed on a desktop shell that has ok/apply/cancel buttons, i'll leave it here only for future reference until we have a prototype for the active shell.
* root.pageChanged will start a timer, that in turn will call saveConfig() when triggered
for (var prop in currentItem) {
if (prop.indexOf("cfg_") === 0) {
currentItem[prop+"Changed"].connect(root.pageChanged)
}
}*/
}
pushTransition: QtControls.StackViewTransition {
PropertyAnimation {
target: enterItem
property: "opacity"
from: 0
to: 1
duration: units.longDuration
easing.type: Easing.InOutQuad
}
PropertyAnimation {
target: enterItem
property: "x"
from: main.invertAnimations ? -target.width/3: target.width/3
to: 0
duration: units.longDuration
easing.type: Easing.InOutQuad
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: units.longDuration
easing.type: Easing.InOutQuad
}
XAnimator {
from: pageStack.invertAnimations ? -scroll.width/3: scroll.width/3
to: 0
duration: units.longDuration
easing.type: Easing.InOutQuad
}
}
PropertyAnimation {
target: exitItem
property: "opacity"
from: 1
to: 0
duration: units.longDuration
easing.type: Easing.InOutQuad
}
PropertyAnimation {
target: exitItem
property: "x"
from: 0
to: main.invertAnimations ? target.width/3 : -target.width/3
duration: units.longDuration
easing.type: Easing.InOutQuad
}
replaceExit: Transition {
ParallelAnimation {
OpacityAnimator {
from: 1
to: 0
duration: units.longDuration
easing.type: Easing.InOutQuad
}
XAnimator {
from: 0
to: pageStack.invertAnimations ? scroll.width/3 : -scroll.width/3
duration: units.longDuration
easing.type: Easing.InOutQuad
}
}
}
}
......@@ -405,20 +398,20 @@ Rectangle {
id: buttonsRow
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
QtControls.Button {
iconName: "dialog-ok"
icon.name: "dialog-ok"
text: i18nd("plasma_shell_org.kde.plasma.desktop", "OK")
onClicked: acceptAction.trigger()
}
QtControls.Button {
id: applyButton
enabled: false
iconName: "dialog-ok-apply"
icon.name: "dialog-ok-apply"
text: i18nd("plasma_shell_org.kde.plasma.desktop", "Apply")
visible: main.currentItem && (!main.currentItem.kcm || main.currentItem.kcm.buttons & 4) // 4 = Apply button
visible: pageStack.currentItem && (!pageStack.currentItem.kcm || pageStack.currentItem.kcm.buttons & 4) // 4 = Apply button
onClicked: applyAction.trigger()
}
QtControls.Button {
iconName: "dialog-cancel"
icon.name: "dialog-cancel"
text: i18nd("plasma_shell_org.kde.plasma.desktop", "Cancel")
onClicked: cancelAction.trigger()
}
......
......@@ -18,10 +18,11 @@
import QtQuick 2.0
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.0 as QtControls
import QtQuick.Controls 2.3 as QtControls
import QtQuick.Window 2.2
import org.kde.kquickcontrolsaddons 2.0
import org.kde.kirigami 2.5 as Kirigami
MouseArea {
id: delegate
......@@ -32,7 +33,7 @@ MouseArea {
Layout.fillWidth: true
hoverEnabled: true
property bool current: (model.kcm && main.currentItem.kcm && model.kcm == main.currentItem.kcm) || (model.source == main.sourceFile)
property bool current: (model.kcm && pageStack.currentItem.kcm && model.kcm == pageStack.currentItem.kcm) || (model.source == pageStack.sourceFile)
//END properties
//BEGIN functions
......@@ -41,19 +42,19 @@ MouseArea {
return;
}
if (typeof(categories.currentItem) !== "undefined") {
main.invertAnimations = (categories.currentItem.y > delegate.y);
pageStack.invertAnimations = (categories.currentItem.y > delegate.y);
categories.currentItem = delegate;
}
if (model.source) {
main.sourceFile = model.source;
pageStack.sourceFile = model.source;
} else if (model.kcm) {
main.sourceFile = "";
main.sourceFile = Qt.resolvedUrl("ConfigurationKcmPage.qml");
main.currentItem.kcm = model.kcm;
pageStack.sourceFile = "";
pageStack.sourceFile = Qt.resolvedUrl("ConfigurationKcmPage.qml");
pageStack.currentItem.kcm = model.kcm;
} else {
main.sourceFile = "";
pageStack.sourceFile = "";
}
main.title = model.name
pageStack.title = model.name
}
//END functions
......@@ -65,7 +66,7 @@ MouseArea {
return;
}
//print("model source: " + model.source + " " + main.sourceFile);
//print("model source: " + model.source + " " + pageStack.sourceFile);
if (applyButton.enabled) {
messageDialog.delegate = delegate;
messageDialog.open();
......@@ -84,7 +85,7 @@ MouseArea {
//BEGIN UI components
Rectangle {
anchors.fill: parent
color: syspal.highlight
color: Kirigami.Theme.highlightColor
opacity: { // try to match Breeze style hover handling
var active = categoriesScroll.activeFocus && Window.active
if (current) {
......@@ -133,7 +134,7 @@ MouseArea {
text: model.name
wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter
color: current && categoriesScroll.activeFocus ? syspal.highlightedText : syspal.text
color: current && categoriesScroll.activeFocus ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor
Behavior on color {
ColorAnimation {
duration: units.longDuration
......
......@@ -17,7 +17,7 @@
*/
import QtQuick 2.0
import QtQuick.Controls 1.0 as QtControls
import QtQuick.Controls 2.3 as QtControls
import QtQuick.Layouts 1.0
Item {
......@@ -114,7 +114,7 @@ Item {
}
pluginsCombo.initialized = true;
}
onCurrentIndexChanged: {
onActivated: {
if (initialized && configDialog.containmentActionConfigModel.get(currentIndex).pluginName != pluginName) {
configDialog.currentContainmentActionsModel.update(index, action, configDialog.containmentActionConfigModel.get(currentIndex).pluginName);
}
......@@ -130,7 +130,7 @@ Item {
Layout.row: index
QtControls.Button {
iconName: "configure"
icon.name: "configure"
width: height
enabled: model.hasConfigurationInterface
onClicked: {
......@@ -138,14 +138,14 @@ Item {
}
}
QtControls.Button {
iconName: "dialog-information"
icon.name: "dialog-information"
width: height
onClicked: {
configDialog.currentContainmentActionsModel.showAbout(index, this);
}
}
QtControls.Button {
iconName: "list-remove"
icon.name: "list-remove"
width: height
onClicked: {
configDialog.currentContainmentActionsModel.remove(index);
......@@ -155,7 +155,6 @@ Item {
}
MouseEventInputButton {
anchors.left: parent.left
defaultText: i18nd("plasma_shell_org.kde.plasma.desktop", "Add Action");
onEventStringChanged: {
configDialog.currentContainmentActionsModel.append(eventString, "org.kde.contextmenu");
......
......@@ -18,16 +18,17 @@
import QtQuick 2.0
import org.kde.plasma.configuration 2.0
import QtQuick.Controls 1.0 as QtControls
import QtQuick.Controls 2.3 as QtControls
import QtQuick.Layouts 1.1
import org.kde.kconfig 1.0 // for KAuthorized
import org.kde.plasma.private.shell 2.0 as ShellPrivate // for WallpaperPlugin
import org.kde.kirigami 2.5 as Kirigami
ColumnLayout {
id: root
property int formAlignment: wallpaperComboBox.x + (units.largeSpacing/2)
property int formAlignment: wallpaperComboBox.Kirigami.ScenePosition.x - root.Kirigami.ScenePosition.x + (units.largeSpacing/2)
property string currentWallpaper: ""
property string containmentPlugin: ""
signal configurationChanged
......@@ -53,6 +54,7 @@ ColumnLayout {
var data = configDialog.containmentPluginsConfigModel.get(i);
if (configDialog.containmentPlugin == data.pluginName) {
pluginComboBox.currentIndex = i
pluginComboBox.activated(i);
break;
}
}
......@@ -61,32 +63,68 @@ ColumnLayout {
var data = configDialog.wallpaperConfigModel.get(i);
if (configDialog.currentWallpaper == data.pluginName) {
wallpaperComboBox.currentIndex = i
wallpaperComboBox.activated(i);
break;
}
}
}
Row {
spacing: units.largeSpacing / 2
visible: pluginComboBox.count > 1
QtControls.Label {
width: formAlignment - units.largeSpacing
anchors.verticalCenter: pluginComboBox.verticalCenter
text: i18nd("plasma_shell_org.kde.plasma.desktop", "Layout:")
horizontalAlignment: Text.AlignRight
}
Kirigami.InlineMessage {
visible: plasmoid.immutable || animating
text: i18nd("plasma_shell_org.kde.plasma.desktop", "Layout cannot be changed while widgets are locked")
showCloseButton: true
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.smallSpacing
Layout.rightMargin: Kirigami.Units.smallSpacing
}
Kirigami.FormLayout {
Layout.fillWidth: true
QtControls.ComboBox {
id: pluginComboBox
Layout.preferredWidth: Math.max(implicitWidth, wallpaperComboBox.implicitWidth)
Kirigami.FormData.label: i18nd("plasma_shell_org.kde.plasma.desktop", "Layout:")
enabled: !plasmoid.immutable
model: configDialog.containmentPluginsConfigModel
width: theme.mSize(theme.defaultFont).width * 24
textRole: "name"
onCurrentIndexChanged: {
onActivated: {
var model = configDialog.containmentPluginsConfigModel.get(currentIndex)
root.containmentPlugin = model.pluginName
root.configurationChanged()
}
}
RowLayout {
Layout.fillWidth: true
visible: !switchContainmentWarning.visible
Kirigami.FormData.label: i18nd("plasma_shell_org.kde.plasma.desktop", "Wallpaper Type:")
QtControls.ComboBox {
id: wallpaperComboBox
Layout.preferredWidth: Math.max(implicitWidth, pluginComboBox.implicitWidth)
model: configDialog.wallpaperConfigModel
width: theme.mSize(theme.defaultFont).width * 24
textRole: "name"
onActivated: {
var model = configDialog.wallpaperConfigModel.get(currentIndex)
root.currentWallpaper = model.pluginName
configDialog.currentWallpaper = model.pluginName
main.sourceFile = model.source
root.configurationChanged()
}
}
QtControls.Button {
icon.name: "get-hot-new-stuff"
text: i18nd("plasma_shell_org.kde.plasma.desktop", "Get New Plugins...")
visible: KAuthorized.authorize("ghns")
onClicked: wallpaperPlugin.getNewWallpaperPlugin(this)
Layout.preferredHeight: wallpaperComboBox.height
ShellPrivate.WallpaperPlugin {
id: wallpaperPlugin
}
}