mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-29 15:03:09 +00:00
kcm: Add vibration intensity and duration
This commit is contained in:
parent
fc300d1a28
commit
9a575ad42e
6 changed files with 297 additions and 10 deletions
|
|
@ -27,6 +27,8 @@ MobileShellSettings::MobileShellSettings(QObject *parent)
|
||||||
connect(m_configWatcher.data(), &KConfigWatcher::configChanged, this, [this](const KConfigGroup &group, const QByteArrayList &names) -> void {
|
connect(m_configWatcher.data(), &KConfigWatcher::configChanged, this, [this](const KConfigGroup &group, const QByteArrayList &names) -> void {
|
||||||
if (group.name() == GENERAL_CONFIG_GROUP) {
|
if (group.name() == GENERAL_CONFIG_GROUP) {
|
||||||
Q_EMIT vibrationsEnabledChanged();
|
Q_EMIT vibrationsEnabledChanged();
|
||||||
|
Q_EMIT vibrationIntensityChanged();
|
||||||
|
Q_EMIT vibrationDurationChanged();
|
||||||
Q_EMIT animationsEnabledChanged();
|
Q_EMIT animationsEnabledChanged();
|
||||||
Q_EMIT navigationPanelEnabledChanged();
|
Q_EMIT navigationPanelEnabledChanged();
|
||||||
} else if (group.name() == QUICKSETTINGS_CONFIG_GROUP) {
|
} else if (group.name() == QUICKSETTINGS_CONFIG_GROUP) {
|
||||||
|
|
@ -49,6 +51,32 @@ void MobileShellSettings::setVibrationsEnabled(bool vibrationsEnabled)
|
||||||
m_config->sync();
|
m_config->sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MobileShellSettings::vibrationDuration() const
|
||||||
|
{
|
||||||
|
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
|
||||||
|
return group.readEntry("vibrationDuration", 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobileShellSettings::setVibrationDuration(int vibrationDuration)
|
||||||
|
{
|
||||||
|
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
|
||||||
|
group.writeEntry("vibrationDuration", vibrationDuration, KConfigGroup::Notify);
|
||||||
|
m_config->sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal MobileShellSettings::vibrationIntensity() const
|
||||||
|
{
|
||||||
|
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
|
||||||
|
return group.readEntry("vibrationDuration", 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MobileShellSettings::setVibrationIntensity(qreal vibrationIntensity)
|
||||||
|
{
|
||||||
|
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
|
||||||
|
group.writeEntry("vibrationDuration", vibrationIntensity, KConfigGroup::Notify);
|
||||||
|
m_config->sync();
|
||||||
|
}
|
||||||
|
|
||||||
bool MobileShellSettings::animationsEnabled() const
|
bool MobileShellSettings::animationsEnabled() const
|
||||||
{
|
{
|
||||||
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
|
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,17 @@
|
||||||
#include <KSharedConfig>
|
#include <KSharedConfig>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @short Wrapper class to access and control mobile shell specific settings.
|
||||||
|
*
|
||||||
|
* @author Devin Lin <devin@kde.org>
|
||||||
|
*/
|
||||||
class MobileShellSettings : public QObject
|
class MobileShellSettings : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool vibrationsEnabled READ vibrationsEnabled WRITE setVibrationsEnabled NOTIFY vibrationsEnabledChanged)
|
Q_PROPERTY(bool vibrationsEnabled READ vibrationsEnabled WRITE setVibrationsEnabled NOTIFY vibrationsEnabledChanged)
|
||||||
|
Q_PROPERTY(int vibrationDuration READ vibrationDuration WRITE setVibrationDuration NOTIFY vibrationDurationChanged)
|
||||||
|
Q_PROPERTY(qreal vibrationIntensity READ vibrationIntensity WRITE setVibrationIntensity NOTIFY vibrationIntensityChanged)
|
||||||
Q_PROPERTY(bool animationsEnabled READ animationsEnabled WRITE setAnimationsEnabled NOTIFY animationsEnabledChanged)
|
Q_PROPERTY(bool animationsEnabled READ animationsEnabled WRITE setAnimationsEnabled NOTIFY animationsEnabledChanged)
|
||||||
Q_PROPERTY(bool navigationPanelEnabled READ navigationPanelEnabled WRITE setNavigationPanelEnabled NOTIFY navigationPanelEnabledChanged)
|
Q_PROPERTY(bool navigationPanelEnabled READ navigationPanelEnabled WRITE setNavigationPanelEnabled NOTIFY navigationPanelEnabledChanged)
|
||||||
|
|
||||||
|
|
@ -23,23 +30,102 @@ public:
|
||||||
|
|
||||||
MobileShellSettings(QObject *parent = nullptr);
|
MobileShellSettings(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether shell vibrations are enabled.
|
||||||
|
*/
|
||||||
bool vibrationsEnabled() const;
|
bool vibrationsEnabled() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether shell vibrations should be enabled.
|
||||||
|
*
|
||||||
|
* @param vibrationsEnabled Whether vibrations are enabled.
|
||||||
|
*/
|
||||||
void setVibrationsEnabled(bool vibrationsEnabled);
|
void setVibrationsEnabled(bool vibrationsEnabled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the duration of a standard vibration event, in milliseconds.
|
||||||
|
* Different types of vibration events may be calculated off of this.
|
||||||
|
*/
|
||||||
|
int vibrationDuration() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the duration of a standard vibration event, in milliseconds.
|
||||||
|
*
|
||||||
|
* @param vibrationDuration The duration of a standard vibration event.
|
||||||
|
*/
|
||||||
|
void setVibrationDuration(int vibrationDuration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the intensity of a standard vibration event, which is a value between
|
||||||
|
* zero and one.
|
||||||
|
*/
|
||||||
|
qreal vibrationIntensity() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the intensity of a standard vibration event.
|
||||||
|
*
|
||||||
|
* @param vibrationIntensity The intensity of a standard vibration event, between zero and one.
|
||||||
|
*/
|
||||||
|
void setVibrationIntensity(qreal vibrationIntensity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether animations are enabled in the shell.
|
||||||
|
*
|
||||||
|
* If false, vibrations will either be disabled or minimized as much as possible.
|
||||||
|
* TODO: integrate with animation speed (in settings at "Workspace Behaviour->General Behaviour"),
|
||||||
|
* which affects applications as well.
|
||||||
|
*/
|
||||||
bool animationsEnabled() const;
|
bool animationsEnabled() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether animations are enabled in the shell.
|
||||||
|
*
|
||||||
|
* @param animationsEnabled Whether animations should be enabled in the shell.
|
||||||
|
*/
|
||||||
void setAnimationsEnabled(bool animationsEnabled);
|
void setAnimationsEnabled(bool animationsEnabled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the navigation panel is enabled.
|
||||||
|
*
|
||||||
|
* If this is false, then gesture based navigation is used.
|
||||||
|
*/
|
||||||
bool navigationPanelEnabled() const;
|
bool navigationPanelEnabled() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether the navigation panel is enabled.
|
||||||
|
*
|
||||||
|
* @param navigationPanelEnabled Whether the navigation panel should be enabled.
|
||||||
|
*/
|
||||||
void setNavigationPanelEnabled(bool navigationPanelEnabled);
|
void setNavigationPanelEnabled(bool navigationPanelEnabled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of IDs of quick settings that are enabled.
|
||||||
|
*/
|
||||||
QList<QString> enabledQuickSettings() const;
|
QList<QString> enabledQuickSettings() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the list of quick settings that are enabled.
|
||||||
|
*
|
||||||
|
* @param list A list of quick setting IDs.
|
||||||
|
*/
|
||||||
void setEnabledQuickSettings(QList<QString> &list);
|
void setEnabledQuickSettings(QList<QString> &list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of IDs of quick settings that are disabled.
|
||||||
|
*/
|
||||||
QList<QString> disabledQuickSettings() const;
|
QList<QString> disabledQuickSettings() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the list of quick settings that are disabled.
|
||||||
|
*
|
||||||
|
* @param list A list of quick setting IDs.
|
||||||
|
*/
|
||||||
void setDisabledQuickSettings(QList<QString> &list);
|
void setDisabledQuickSettings(QList<QString> &list);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void vibrationsEnabledChanged();
|
void vibrationsEnabledChanged();
|
||||||
|
void vibrationIntensityChanged();
|
||||||
|
void vibrationDurationChanged();
|
||||||
void navigationPanelEnabledChanged();
|
void navigationPanelEnabledChanged();
|
||||||
void animationsEnabledChanged();
|
void animationsEnabledChanged();
|
||||||
void enabledQuickSettingsChanged();
|
void enabledQuickSettingsChanged();
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ QtObject {
|
||||||
function buttonVibrate() {
|
function buttonVibrate() {
|
||||||
if (MobileShell.MobileShellSettings.vibrationsEnabled) {
|
if (MobileShell.MobileShellSettings.vibrationsEnabled) {
|
||||||
if (hapticsEffect.status == Loader.Ready) {
|
if (hapticsEffect.status == Loader.Ready) {
|
||||||
hapticsEffect.item.intensity = 0.5;
|
hapticsEffect.item.intensity = MobileShell.MobileShellSettings.vibrationIntensity;
|
||||||
hapticsEffect.item.duration = 100;
|
hapticsEffect.item.duration = MobileShell.MobileShellSettings.vibrationDuration;
|
||||||
hapticsEffect.item.start();
|
hapticsEffect.item.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
150
kcms/mobileshell/package/contents/ui/VibrationForm.qml
Normal file
150
kcms/mobileshell/package/contents/ui/VibrationForm.qml
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
import QtQuick.Controls 2.15 as QQC2
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.19 as Kirigami
|
||||||
|
import org.kde.kcm 1.3 as KCM
|
||||||
|
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||||
|
|
||||||
|
import "mobileform" as MobileForm
|
||||||
|
|
||||||
|
Kirigami.ScrollablePage {
|
||||||
|
id: root
|
||||||
|
title: i18n("Shell Vibrations")
|
||||||
|
leftPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
|
topPadding: Kirigami.Units.gridUnit
|
||||||
|
bottomPadding: Kirigami.Units.gridUnit
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
width: root.width
|
||||||
|
|
||||||
|
MobileForm.FormCard {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
MobileForm.FormSwitchDelegate {
|
||||||
|
id: shellVibrationsSwitch
|
||||||
|
text: i18n("Shell Vibrations")
|
||||||
|
description: i18n("Whether to have vibrations enabled in the shell.")
|
||||||
|
checked: MobileShell.MobileShellSettings.vibrationsEnabled
|
||||||
|
onCheckedChanged: {
|
||||||
|
if (checked != MobileShell.MobileShellSettings.vibrationsEnabled) {
|
||||||
|
MobileShell.MobileShellSettings.vibrationsEnabled = checked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Separator {
|
||||||
|
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||||
|
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||||
|
Layout.fillWidth: true
|
||||||
|
opacity: (!shellVibrationsSwitch.controlHovered && !vibrationIntensityDelegate.controlHovered) ? 0.5 : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
MobileForm.FormComboBoxDelegate {
|
||||||
|
id: vibrationIntensityDelegate
|
||||||
|
text: i18n("Vibration Intensity")
|
||||||
|
description: i18n("How intense shell vibrations should be.")
|
||||||
|
|
||||||
|
property string lowIntensityString: i18nc("Low intensity", "Low")
|
||||||
|
property string mediumIntensityString: i18nc("Medium intensity", "Medium")
|
||||||
|
property string highIntensityString: i18nc("High intensity", "High")
|
||||||
|
|
||||||
|
currentValue: {
|
||||||
|
let intensity = MobileShell.MobileShellSettings.vibrationIntensity;
|
||||||
|
if (intensity <= 0.2) {
|
||||||
|
return lowIntensityString;
|
||||||
|
} else if (intensity <= 0.5) {
|
||||||
|
return mediumIntensityString;
|
||||||
|
} else {
|
||||||
|
return highIntensityString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model: ListModel {
|
||||||
|
// we can't use i18n with ListElement
|
||||||
|
Component.onCompleted: {
|
||||||
|
append({"name": vibrationIntensityDelegate.highIntensityString, "value": 1.0});
|
||||||
|
append({"name": vibrationIntensityDelegate.mediumIntensityString, "value": 0.5});
|
||||||
|
append({"name": vibrationIntensityDelegate.lowIntensityString, "value": 0.2});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dialogDelegate: QQC2.RadioDelegate {
|
||||||
|
implicitWidth: Kirigami.Units.gridUnit * 16
|
||||||
|
topPadding: Kirigami.Units.smallSpacing * 2
|
||||||
|
bottomPadding: Kirigami.Units.smallSpacing * 2
|
||||||
|
|
||||||
|
text: name
|
||||||
|
checked: vibrationIntensityDelegate.currentValue === name
|
||||||
|
onCheckedChanged: {
|
||||||
|
if (checked) {
|
||||||
|
MobileShell.MobileShellSettings.vibrationIntensity = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Separator {
|
||||||
|
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||||
|
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||||
|
Layout.fillWidth: true
|
||||||
|
opacity: (!vibrationIntensityDelegate.controlHovered && !vibrationDurationDelegate.controlHovered) ? 0.5 : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
MobileForm.FormComboBoxDelegate {
|
||||||
|
id: vibrationDurationDelegate
|
||||||
|
text: i18n("Vibration Duration")
|
||||||
|
description: i18n("How long shell vibrations should be.")
|
||||||
|
|
||||||
|
property string longString: i18nc("Long duration", "Long")
|
||||||
|
property string mediumString: i18nc("Medium duration", "Medium")
|
||||||
|
property string shortString: i18nc("Short duration", "Short")
|
||||||
|
|
||||||
|
currentValue: {
|
||||||
|
let duration = MobileShell.MobileShellSettings.vibrationDuration;
|
||||||
|
if (duration >= 100) {
|
||||||
|
return longString;
|
||||||
|
} else if (duration >= 50) {
|
||||||
|
return mediumString;
|
||||||
|
} else {
|
||||||
|
return shortString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model: ListModel {
|
||||||
|
// we can't use i18n with ListElement
|
||||||
|
Component.onCompleted: {
|
||||||
|
append({"name": vibrationDurationDelegate.longString, "value": 100});
|
||||||
|
append({"name": vibrationDurationDelegate.mediumString, "value": 50});
|
||||||
|
append({"name": vibrationDurationDelegate.shortString, "value": 15});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dialogDelegate: QQC2.RadioDelegate {
|
||||||
|
implicitWidth: Kirigami.Units.gridUnit * 16
|
||||||
|
topPadding: Kirigami.Units.smallSpacing * 2
|
||||||
|
bottomPadding: Kirigami.Units.smallSpacing * 2
|
||||||
|
|
||||||
|
text: name
|
||||||
|
checked: vibrationDurationDelegate.currentValue === name
|
||||||
|
onCheckedChanged: {
|
||||||
|
if (checked) {
|
||||||
|
MobileShell.MobileShellSettings.vibrationDuration = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MobileForm.FormSectionText {
|
||||||
|
text: i18n("Keyboard vibrations are controlled separately in the keyboard settings module.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -37,18 +37,21 @@ KCM.SimpleKCM {
|
||||||
title: i18n("General")
|
title: i18n("General")
|
||||||
}
|
}
|
||||||
|
|
||||||
MobileForm.FormSwitchDelegate {
|
MobileForm.FormButtonDelegate {
|
||||||
|
id: shellVibrationsButton
|
||||||
text: i18n("Shell Vibrations")
|
text: i18n("Shell Vibrations")
|
||||||
description: i18n("Whether to have vibrations enabled in the shell.")
|
onClicked: kcm.push("VibrationForm.qml")
|
||||||
checked: MobileShell.MobileShellSettings.vibrationsEnabled
|
|
||||||
onCheckedChanged: {
|
|
||||||
if (checked != MobileShell.MobileShellSettings.vibrationsEnabled) {
|
|
||||||
MobileShell.MobileShellSettings.vibrationsEnabled = checked;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Kirigami.Separator {
|
||||||
|
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||||
|
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||||
|
Layout.fillWidth: true
|
||||||
|
opacity: (!shellVibrationsButton.controlHovered && !animationsSwitch.controlHovered) ? 0.5 : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
MobileForm.FormSwitchDelegate {
|
MobileForm.FormSwitchDelegate {
|
||||||
|
id: animationsSwitch
|
||||||
text: i18n("Animations")
|
text: i18n("Animations")
|
||||||
description: i18n("If this is off, animations will be reduced as much as possible.")
|
description: i18n("If this is off, animations will be reduced as much as possible.")
|
||||||
checked: MobileShell.MobileShellSettings.animationsEnabled
|
checked: MobileShell.MobileShellSettings.animationsEnabled
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,29 @@ AbstractFormDelegate {
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
property string currentValue: ""
|
property string currentValue: ""
|
||||||
|
property alias dialogDelegate: repeater.delegate
|
||||||
|
property alias model: repeater.model
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
onClicked: dialog.open()
|
||||||
|
|
||||||
|
Kirigami.Dialog {
|
||||||
|
id: dialog
|
||||||
|
showCloseButton: false
|
||||||
|
title: root.text
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Kirigami.Theme.inherit: false
|
||||||
|
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: repeater
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue