Commit c38608bf authored by Nate Graham's avatar Nate Graham
Browse files

kcms/landingpage: Improve alignment, spacing, and clarity

This commit tweaks the landing page to make various interrelated
improvements:
- Improve alignment by moving the quick KCM link buttons into the
  FormLayout
- Use a 2x3 grid for the "Most Used" icons and improve the code quality
- Improve spacing by adding some vertical padding in relevant places
- Improve clarity by putting each radio button's explanatory text right
  below it

| Before | After |
| ------ | ----- |
| ![SySe_before](/uploads/4b554745da5ab3555ce233af8519ae7b/SySe_before.png) | ![SySe_after](/uploads/b3c8e7a43ea1d57135b58c7032212b7f/SySe_after.png) |

cc @teams/vdg
parent 6e8626f2
Pipeline #136095 passed with stage
in 2 minutes and 26 seconds
......@@ -76,7 +76,7 @@ void MostUsedModel::setResultModel(ResultModel *model)
}
auto updateModel = [this]() {
if (m_resultModel->rowCount() >= 5) {
if (m_resultModel->rowCount() >= 6) {
setSourceModel(m_resultModel);
} else {
setSourceModel(m_defaultModel);
......@@ -179,7 +179,7 @@ KCMLandingPage::KCMLandingPage(QObject *parent, const QVariantList &args)
setButtons(Apply | Help);
m_mostUsedModel = new MostUsedModel(this);
m_mostUsedModel->setResultModel(new ResultModel(AllResources | Agent(QStringLiteral("org.kde.systemsettings")) | HighScoredFirst | Limit(5), this));
m_mostUsedModel->setResultModel(new ResultModel(AllResources | Agent(QStringLiteral("org.kde.systemsettings")) | HighScoredFirst | Limit(6), this));
m_defaultLightLookAndFeel = new LookAndFeelGroup(this);
m_defaultDarkLookAndFeel = new LookAndFeelGroup(this);
......
/*
SPDX-FileCopyrightText: 2017 Marco Martin <mart@kde.org>
SPDX-FileCopyrightText: 2022 Nate Graham <nate@kde.org>
SPDX-License-Identifier: LGPL-2.0-only
*/
......@@ -10,53 +11,43 @@ import QtQuick.Layouts 1.1
import org.kde.kirigami 2.5 as Kirigami
MouseArea {
id: item
property alias icon: iconItem.source
property alias text: label.text
property string module
property int iconSize: Kirigami.Units.iconSizes.medium
implicitWidth: Kirigami.Units.gridUnit * 5
implicitHeight: Kirigami.Units.gridUnit * 4
cursorShape: Qt.PointingHandCursor
activeFocusOnTab: true
hoverEnabled: true
Accessible.role: Accessible.Button
Accessible.name: label.text
Accessible.description: i18n("Most used module number %1", index+1)
Accessible.onPressAction: { item.clicked(model.kcmPlugin); }
Keys.onReturnPressed: { item.clicked(model.kcmPlugin); }
Keys.onEnterPressed: { item.clicked(model.kcmPlugin); }
Keys.onSpacePressed: { item.clicked(model.kcmPlugin); }
Kirigami.Separator {
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
visible: item.activeFocus
color: Kirigami.Theme.highlightColor
}
ColumnLayout {
anchors.fill: parent
QQC2.ToolButton {
// We're using custom properties rather than plain old icon.name: and text:
// because this would cause the icon and text to be rendered twice with
// qqc2-desktop-style since it does all its rendering in the background item
// rather than the contentItem like it should, so overriding the contentItem
// as we're doing here doesn't completely replace those things as expected.
property alias kcmIcon: iconItem.source
property alias kcmName: label.text
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding)
onClicked: kcm.openKCM(model.kcmPlugin)
leftPadding: Kirigami.Units.smallSpacing
rightPadding: Kirigami.Units.smallSpacing
topPadding: Kirigami.Units.smallSpacing
bottomPadding: Kirigami.Units.smallSpacing
spacing: Kirigami.Units.smallSpacing
contentItem: RowLayout {
spacing: parent.spacing
Kirigami.Icon {
id: iconItem
active: item.containsMouse || item.activeFocus
Layout.alignment: Qt.AlignHCenter
implicitWidth: item.iconSize
implicitHeight: item.iconSize
Layout.alignment: Qt.AlignCenter
implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: Kirigami.Units.iconSizes.smallMedium
}
QQC2.Label {
id: label
Layout.fillWidth: true
Layout.fillHeight: true
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignTop
wrapMode: Text.Wrap
elide: Text.ElideRight
}
}
}
......
/*
SPDX-FileCopyrightText: 2021 Marco Martin <mart@kde.org>
SPDX-FileCopyrightText: 2018 Furkan Tokac <furkantokac34@gmail.com>
SPDX-FileCopyrightText: 2019 Nate Graham <nate@kde.org>
SPDX-FileCopyrightText: 2019-2022 Nate Graham <nate@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
......@@ -15,222 +15,233 @@ import org.kde.kcm 1.4 as KCM
KCM.SimpleKCM {
id: root
ColumnLayout {
Kirigami.FormLayout {
width: parent.width
Kirigami.FormLayout {
id: appearanceForm
twinFormLayouts: behaviorForm
anchors {
top: parent.top
topMargin: Kirigami.Units.largeSpacing
}
RowLayout {
Kirigami.FormData.label: i18n("Theme:")
RowLayout {
Kirigami.FormData.label: i18n("Theme:")
Layout.alignment: Qt.AlignCenter
spacing: Kirigami.Units.gridUnit * 2
Layout.alignment: Qt.AlignCenter
spacing: Kirigami.Units.gridUnit * 2
QQC2.ButtonGroup { id: themeGroup } // needed?
QQC2.ButtonGroup { id: themeGroup } // needed?
Thumbnail {
imageSource: kcm.defaultLightLookAndFeel.thumbnail
text: i18nc("Adjective; as in, 'light theme'", "Light")
checked: kcm.globalsSettings.lookAndFeelPackage === kcm.defaultLightLookAndFeel.id
QQC2.ButtonGroup.group: themeGroup
Thumbnail {
imageSource: kcm.defaultLightLookAndFeel.thumbnail
text: i18nc("Adjective; as in, 'light theme'", "Light")
checked: kcm.globalsSettings.lookAndFeelPackage === kcm.defaultLightLookAndFeel.id
QQC2.ButtonGroup.group: themeGroup
onToggled: kcm.globalsSettings.lookAndFeelPackage = kcm.defaultLightLookAndFeel.id
onToggled: kcm.globalsSettings.lookAndFeelPackage = kcm.defaultLightLookAndFeel.id
KCM.SettingStateBinding {
configObject: kcm.globalsSettings
settingName: "lookAndFeelPackage"
}
KCM.SettingStateBinding {
configObject: kcm.globalsSettings
settingName: "lookAndFeelPackage"
}
Thumbnail {
imageSource: kcm.defaultDarkLookAndFeel.thumbnail
text: i18nc("Adjective; as in, 'dark theme'", "Dark")
checked: kcm.globalsSettings.lookAndFeelPackage === kcm.defaultDarkLookAndFeel.id
QQC2.ButtonGroup.group: themeGroup
}
Thumbnail {
imageSource: kcm.defaultDarkLookAndFeel.thumbnail
text: i18nc("Adjective; as in, 'dark theme'", "Dark")
checked: kcm.globalsSettings.lookAndFeelPackage === kcm.defaultDarkLookAndFeel.id
QQC2.ButtonGroup.group: themeGroup
onToggled: kcm.globalsSettings.lookAndFeelPackage = kcm.defaultDarkLookAndFeel.id
onToggled: kcm.globalsSettings.lookAndFeelPackage = kcm.defaultDarkLookAndFeel.id
KCM.SettingStateBinding {
configObject: kcm.globalsSettings
settingName: "lookAndFeelPackage"
}
KCM.SettingStateBinding {
configObject: kcm.globalsSettings
settingName: "lookAndFeelPackage"
}
}
}
// We want to show the slider in a logarithmic way. ie
// move from 4x, 3x, 2x, 1x, 0.5x, 0.25x, 0.125x
// 0 is a special case
ColumnLayout {
Kirigami.FormData.label: i18n("Animation speed:")
Kirigami.FormData.buddyFor: slider
// We want to show the slider in a logarithmic way. ie
// move from 4x, 3x, 2x, 1x, 0.5x, 0.25x, 0.125x
// 0 is a special case
ColumnLayout {
Kirigami.FormData.label: i18n("Animation speed:")
Kirigami.FormData.buddyFor: slider
// Match width of feedback slider for aesthetics
Layout.minimumWidth: feedbackLoader.active ? feedbackLoader.item.sliderWidth : implicitWidth
Layout.maximumWidth: feedbackLoader.active ? feedbackLoader.item.sliderWidth : implicitWidth
// Match width of feedback slider for aesthetics
Layout.minimumWidth: feedbackLoader.active ? feedbackLoader.item.sliderWidth : implicitWidth
Layout.maximumWidth: feedbackLoader.active ? feedbackLoader.item.sliderWidth : implicitWidth
QQC2.Slider {
id: slider
Layout.fillWidth: true
from: -4
to: 4
stepSize: 0.5
snapMode: QQC2.Slider.SnapAlways
onMoved: {
if(value === to) {
kcm.globalsSettings.animationDurationFactor = 0;
} else {
kcm.globalsSettings.animationDurationFactor = 1.0 / Math.pow(2, value);
}
}
value: if (kcm.globalsSettings.animationDurationFactor === 0) {
return slider.to;
QQC2.Slider {
id: slider
Layout.fillWidth: true
from: -4
to: 4
stepSize: 0.5
snapMode: QQC2.Slider.SnapAlways
onMoved: {
if(value === to) {
kcm.globalsSettings.animationDurationFactor = 0;
} else {
return -(Math.log(kcm.globalsSettings.animationDurationFactor) / Math.log(2));
}
KCM.SettingStateBinding {
configObject: kcm.globalsSettings
settingName: "animationDurationFactor"
kcm.globalsSettings.animationDurationFactor = 1.0 / Math.pow(2, value);
}
}
RowLayout {
QQC2.Label {
text: i18nc("Animation speed", "Slow")
}
Item {
Layout.fillWidth: true
}
QQC2.Label {
text: i18nc("Animation speed", "Instant")
}
value: if (kcm.globalsSettings.animationDurationFactor === 0) {
return slider.to;
} else {
return -(Math.log(kcm.globalsSettings.animationDurationFactor) / Math.log(2));
}
}
KCM.SettingStateBinding {
configObject: kcm.globalsSettings
settingName: "animationDurationFactor"
}
}
RowLayout {
QQC2.Button {
icon.name: "preferences-desktop-wallpaper"
text: i18n("Change Wallpaper…")
onClicked: kcm.openWallpaperDialog()
QQC2.Label {
text: i18nc("Animation speed", "Slow")
}
QQC2.Button {
// This button deliberately does not start with a verb to save space
// so that translations don't overflow, as horizontal space is limited
text: i18n("More Appearance Settings…")
icon.name: "preferences-desktop-theme-global"
onClicked: kcm.openKCM("kcm_lookandfeel")
Item {
Layout.fillWidth: true
}
QQC2.Label {
text: i18nc("Animation speed", "Instant")
}
}
}
Kirigami.Separator {
Kirigami.FormData.isSection: true
}
Item {
Kirigami.FormData.isSection: false
}
Kirigami.FormLayout {
id: behaviorForm
RowLayout {
QQC2.Button {
icon.name: "preferences-desktop-wallpaper"
text: i18n("Change Wallpaper…")
onClicked: kcm.openWallpaperDialog()
}
twinFormLayouts: appearanceForm
QQC2.Button {
// This button deliberately does not start with a verb to save space
// so that translations don't overflow, as horizontal space is limited
text: i18n("More Appearance Settings…")
icon.name: "preferences-desktop-theme-global"
onClicked: kcm.openKCM("kcm_lookandfeel")
}
}
// Click behavior settings
Kirigami.Separator {
Kirigami.FormData.isSection: true
}
QQC2.ButtonGroup { id: singleClickGroup }
// Click behavior settings
QQC2.ButtonGroup { id: singleClickGroup }
QQC2.RadioButton {
id: singleClick
Kirigami.FormData.label: i18nc("part of a sentence: 'Clicking files or folders [opens them/selects them]'", "Clicking files or folders:")
text: i18nc("part of a sentence: 'Clicking files or folders opens them'", "Opens them")
checked: kcm.globalsSettings.singleClick
onToggled: kcm.globalsSettings.singleClick = true
QQC2.ButtonGroup.group: singleClickGroup
QQC2.RadioButton {
id: singleClick
Kirigami.FormData.label: i18nc("part of a sentence: 'Clicking files or folders [opens them/selects them]'", "Clicking files or folders:")
text: i18nc("part of a sentence: 'Clicking files or folders opens them'", "Opens them")
checked: kcm.globalsSettings.singleClick
onToggled: kcm.globalsSettings.singleClick = true
QQC2.ButtonGroup.group: singleClickGroup
KCM.SettingStateBinding {
configObject: kcm.globalsSettings
settingName: "singleClick"
}
KCM.SettingStateBinding {
configObject: kcm.globalsSettings
settingName: "singleClick"
}
}
QQC2.RadioButton {
id: doubleClick
text: i18nc("part of a sentence: 'Clicking files or folders selects them'", "Selects them")
checked: !kcm.globalsSettings.singleClick
onToggled: kcm.globalsSettings.singleClick = false
QQC2.ButtonGroup.group: singleClickGroup
QQC2.Label {
Layout.fillWidth: true
text: i18n("Select by clicking on item's selection marker")
elide: Text.ElideRight
font: Kirigami.Theme.smallFont
}
KCM.SettingStateBinding {
configObject: kcm.globalsSettings
settingName: "singleClick"
extraEnabledConditions: singleClick.enabled
}
}
Item {
Kirigami.FormData.isSection: false
}
QQC2.Label {
Layout.fillWidth: true
Layout.minimumWidth: Kirigami.Units.gridUnit * 15
text: singleClick.checked ? i18n("Select by clicking on item's selection marker") : i18n("Open by double-clicking instead")
elide: Text.ElideRight
font: Kirigami.Theme.smallFont
QQC2.RadioButton {
id: doubleClick
text: i18nc("part of a sentence: 'Clicking files or folders selects them'", "Selects them")
checked: !kcm.globalsSettings.singleClick
onToggled: kcm.globalsSettings.singleClick = false
QQC2.ButtonGroup.group: singleClickGroup
KCM.SettingStateBinding {
configObject: kcm.globalsSettings
settingName: "singleClick"
extraEnabledConditions: singleClick.enabled
}
}
Item {
// This is outside the loaded in order to have perfect label alignment
Layout.preferredHeight: Kirigami.Units.smallSpacing
visible: feedbackLoader.visible
}
// This is in a loader because the import FeedbackControls uses won't always exist being KUserFeedback optional
Loader {
id: feedbackLoader
visible: item !== null
active: kcm.hasOwnProperty("feedbackEnabled")
Kirigami.FormData.label: item ? i18n("Send User Feedback:") : ""
Kirigami.FormData.buddyFor: item ? item.slider : null
source: Qt.resolvedUrl("FeedbackControls.qml")
}
QQC2.Button {
// This button deliberately does not start with a verb to save space
// so that translations don't overflow, as horizontal space is limited
text: i18n("More Behavior Settings…")
icon.name: "preferences-desktop"
onClicked: kcm.openKCM("kcm_workspace")
}
QQC2.Label {
Layout.fillWidth: true
text: i18n("Open by double-clicking instead")
elide: Text.ElideRight
font: Kirigami.Theme.smallFont
}
Kirigami.Separator {
Kirigami.FormData.isSection: true
}
Item {
Kirigami.FormData.isSection: false
}
Kirigami.Heading {
level: 2
text: i18n("Most Used Settings")
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
// This is in a loader because the import FeedbackControls uses won't always exist being KUserFeedback optional
Loader {
id: feedbackLoader
visible: item !== null
active: kcm.hasOwnProperty("feedbackEnabled")
Kirigami.FormData.label: item ? i18n("Send User Feedback:") : ""
Kirigami.FormData.buddyFor: item ? item.slider : null
source: Qt.resolvedUrl("FeedbackControls.qml")
}
Item {
implicitHeight: Kirigami.Units.smallSpacing
Kirigami.FormData.isSection: false
}
RowLayout {
Layout.fillHeight: false
spacing: Kirigami.Units.largeSpacing
Item {
Layout.fillHeight: true
Layout.fillWidth: true
Layout.preferredWidth: Kirigami.Units.gridUnit * 2
}
QQC2.Button {
// This button deliberately does not start with a verb to save space
// so that translations don't overflow, as horizontal space is limited
text: i18n("More Behavior Settings…")
icon.name: "preferences-desktop"
onClicked: kcm.openKCM("kcm_workspace")
}
Kirigami.Separator {
Kirigami.FormData.isSection: true
}
GridLayout {
Kirigami.FormData.label: i18n("Most Used Pages:")
Kirigami.FormData.buddyFor: children[1] // 0 is the Repeater
Layout.fillWidth: true
rows: 3
columns: 2
rowSpacing: 0
columnSpacing: 0
Repeater {
id: recentlyUsedRepeater
readonly property int widestButton: {
let currentWidest = 0;
for (let i = 0; i < count; i++) {
if (itemAt(i).implicitWidth > currentWidest) {
currentWidest = itemAt(i).implicitWidth;
}
}
return currentWidest;
}
model: kcm.mostUsedModel
delegate: MostUsedIcon {
Layout.alignment: Qt.AlignTop
icon: model.decoration
text: model.display
Layout.preferredWidth: recentlyUsedRepeater.widestButton
kcmIcon: model.decoration
kcmName: model.display
onClicked: kcm.openKCM(model.kcmPlugin)
}
}
Item {
Layout.preferredWidth: Kirigami.Units.gridUnit * 2
Layout.fillHeight: true
Layout.fillWidth: true
}
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment