Commit e4ce025a authored by Furkan Tokac's avatar Furkan Tokac 💬
Browse files

Mouse KCM Redesign Using Kirigami

Summary:
Mouse KCM is redesigned by using Kirigami. Tested on Xorg and Wayland. Functionality is same.

New design V0.5 (Xorg)
{F5909664}

New design V0.2 (Xorg)
{F5896659}

New design V0.1 (Wayland)
{F5892148}

Test Plan: V0.3 will be tested on Wayland. X is tested

Reviewers: ngraham, romangg, mart

Reviewed By: ngraham, romangg, mart

Subscribers: safaalfulaij, mart, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D13372
parent de78bcc4
/*
* Copyright 2017 Roman Gilg <subdiff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.7
import QtQuick.Controls 1.4 as Controls
import org.kde.plasma.core 2.0 as PlasmaCore
Column {
spacing: units.smallSpacing / 2
property alias label: textlabel.text
property alias model: repeater.model
property alias current: exlGroupbox.current
function itemAt(index) {
return repeater.itemAt(index)
}
Controls.Label {
id: textlabel
}
Controls.ExclusiveGroup { id: exlGroupbox }
Column {
leftPadding: units.smallSpacing
spacing: units.smallSpacing / 2
Repeater {
id: repeater
Controls.RadioButton {
text: modelData
exclusiveGroup: exlGroupbox
property alias tooltiptext: tooltip.text
ToolTip {
id: tooltip
}
}
}
}
}
/*
* Copyright 2018 Roman Gilg <subdiff@gmail.com>
* Copyright 2018 Furkan Tokac <furkantokac34@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -17,19 +18,24 @@
*/
import QtQuick 2.7
import QtQuick.Controls 1.4 as Controls
import QtQuick.Controls 2.0 as Controls
import QtQuick.Layouts 1.3 as Layouts
import QtQuick.Controls.Styles 1.4 as Styles
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.kcm 1.1 as KCM
import org.kde.kirigami 2.4 as Kirigami
import "components"
Item {
// TODO: Change ScrollablePage as KCM.SimpleKCM
// after rewrite the KCM in KConfigModule.
Kirigami.ScrollablePage {
id: root
spacing: Kirigami.Units.smallSpacing
property size sizeHint: Qt.size(formLayout.width, formLayout.height)
property size minimumSizeHint: Qt.size(formLayout.width/2, deviceSelector.height)
property size sizeHint: Qt.size(maincol.width, maincol.height)
property size minimumSizeHint: Qt.size(maincol.width/2, deviceSelector.height)
property alias deviceIndex: deviceSelector.currentIndex
signal changeSignal()
......@@ -40,7 +46,7 @@ Item {
function resetModel(index) {
deviceCount = backend.deviceCount
maincol.enabled = deviceCount
formLayout.enabled = deviceCount
deviceSelector.enabled = deviceCount > 1
loading = true
......@@ -64,259 +70,224 @@ Item {
leftHanded.load()
accelSpeed.load()
accelProfile.load()
naturalScroll.load()
loading = false
}
Controls.ScrollView {
anchors.fill: parent
Kirigami.FormLayout {
id: formLayout
enabled: deviceCount
// Device
Controls.ComboBox {
Kirigami.FormData.label: i18n("Device:")
id: deviceSelector
enabled: deviceCount > 1
Layouts.Layout.fillWidth: true
model: deviceModel
textRole: "name"
onCurrentIndexChanged: {
if (deviceCount) {
device = deviceModel[currentIndex]
if (!loading) {
changeSignal()
}
console.log("Configuration of device '" +
(currentIndex+1) + " : " + device.name + "' opened")
}
root.syncValuesFromBackend()
}
}
Layouts.ColumnLayout {
id: maincol
enabled: deviceCount
spacing: units.largeSpacing
Kirigami.Separator {
}
Layouts.RowLayout {
spacing: units.largeSpacing
// General
Controls.CheckBox {
Kirigami.FormData.label: i18n("General:")
id: deviceEnabled
text: i18n("Device enabled")
Controls.Label {
text: i18n("Device:")
function load() {
if (!formLayout.enabled) {
checked = false
return
}
enabled = device.supportsDisableEvents
checked = enabled && device.enabled
}
Controls.ComboBox {
id: deviceSelector
enabled: deviceCount > 1
Layouts.Layout.fillWidth: true
model: deviceModel
textRole: "name"
onCurrentIndexChanged: {
if (deviceCount) {
device = deviceModel[currentIndex]
if (!loading) {
changeSignal()
}
console.log("Configuration of device '" +
(currentIndex+1) + " : " + device.name + "' opened")
}
root.syncValuesFromBackend()
}
onCheckedChanged: {
if (enabled && !root.loading) {
device.enabled = checked
root.changeSignal()
}
}
Column {
spacing: units.smallSpacing * 2
Column {
leftPadding: units.smallSpacing
Column {
spacing: units.smallSpacing
Controls.Label {
text: i18n("General settings:")
}
Column {
leftPadding: units.smallSpacing
Column {
spacing: units.smallSpacing
Controls.CheckBox {
id: deviceEnabled
text: i18n("Device enabled")
function load() {
if (!maincol.enabled) {
checked = false
return
}
enabled = device.supportsDisableEvents
checked = enabled && device.enabled
}
onCheckedChanged: {
if (enabled && !root.loading) {
device.enabled = checked
root.changeSignal()
}
}
ToolTip {
text: i18n("Accept input through this device.")
}
}
Controls.CheckBox {
id: leftHanded
text: i18n("Left handed mode")
function load() {
if (!maincol.enabled) {
checked = false
return
}
enabled = device.supportsLeftHanded
checked = enabled && device.leftHanded
}
onCheckedChanged: {
if (enabled && !root.loading) {
device.leftHanded = checked
root.changeSignal()
}
}
ToolTip {
text: i18n("Swap left and right buttons.")
}
}
Controls.CheckBox {
id: middleEmulation
text: i18n("Emulate middle button")
function load() {
if (!maincol.enabled) {
checked = false
return
}
enabled = device.supportsMiddleEmulation
checked = enabled && device.middleEmulation
}
onCheckedChanged: {
if (enabled && !root.loading) {
device.middleEmulation = checked
root.changeSignal()
}
}
ToolTip {
text: i18n("Clicking left and right button simultaneously sends middle button click.")
}
}
}
}
}
ToolTip {
text: i18n("Accept input through this device.")
}
}
Controls.CheckBox {
id: leftHanded
text: i18n("Left handed mode")
function load() {
if (!formLayout.enabled) {
checked = false
return
}
enabled = device.supportsLeftHanded
checked = enabled && device.leftHanded
}
Column {
leftPadding: units.smallSpacing
Column {
spacing: units.smallSpacing
Controls.Label {
text: i18n("Acceleration:")
}
Column {
leftPadding: units.smallSpacing
Column {
spacing: units.smallSpacing * 2
Row {
Controls.Slider {
id: accelSpeed
anchors.verticalCenter: parent.verticalCenter
tickmarksEnabled: true
minimumValue: 1
maximumValue: 10
stepSize: 1
implicitWidth: units.gridUnit * 9
function load() {
enabled = device.supportsPointerAcceleration
if (!enabled) {
value = 0.1
return
}
// transform libinput's pointer acceleration range [-1, 1] to slider range [1, 10]
value = 4.5 * device.pointerAcceleration + 5.5
}
onValueChanged: {
if (device != undefined && enabled && !root.loading) {
// transform slider range [1, 10] to libinput's pointer acceleration range [-1, 1]
device.pointerAcceleration = Math.round( (value - 5.5) / 4.5 * 100 ) / 100
root.changeSignal()
}
}
}
}
ExclGroupBox {
id: accelProfile
label: i18n("Acceleration Profile:")
model: [i18n("Flat"), i18n("Adaptive")]
function load() {
enabled = device.supportsPointerAccelerationProfileAdaptive
if (!enabled) {
itemAt(0).checked = false
itemAt(1).checked = false
return
}
itemAt(0).tooltiptext = i18n("Cursor moves the same distance as finger.")
itemAt(1).tooltiptext = i18n("Cursor travel distance depends on movement speed of finger.")
var toCheck = device.pointerAccelerationProfileAdaptive ? 1 : 0
itemAt(toCheck).checked = true
}
onCurrentChanged: {
if (enabled && !root.loading) {
device.pointerAccelerationProfileFlat = itemAt(0).checked
device.pointerAccelerationProfileAdaptive = itemAt(1).checked
root.changeSignal()
}
}
}
}
}
}
onCheckedChanged: {
if (enabled && !root.loading) {
device.leftHanded = checked
root.changeSignal()
}
}
Column {
leftPadding: units.smallSpacing
Column {
spacing: units.smallSpacing
Controls.Label {
text: i18n("Scrolling:")
}
Column {
leftPadding: units.smallSpacing
Column {
spacing: units.smallSpacing
Controls.CheckBox {
id: naturalScroll
text: i18n("Invert scroll direction")
function load() {
enabled = device.supportsNaturalScroll
checked = enabled && device.naturalScroll
}
onCheckedChanged: {
if (enabled && !root.loading) {
device.naturalScroll = checked
root.changeSignal()
}
}
ToolTip {
text: i18n("Touchscreen like scrolling.")
}
}
}
}
}
ToolTip {
text: i18n("Swap left and right buttons.")
}
}
Controls.CheckBox {
id: middleEmulation
text: i18n("Press left and right buttons for middle-click")
function load() {
if (!formLayout.enabled) {
checked = false
return
}
enabled = device.supportsMiddleEmulation
checked = enabled && device.middleEmulation
}
onCheckedChanged: {
if (enabled && !root.loading) {
device.middleEmulation = checked
root.changeSignal()
}
}
ToolTip {
text: i18n("Clicking left and right button simultaneously sends middle button click.")
}
}
Kirigami.Separator {
}
// Acceleration
Controls.Slider {
Kirigami.FormData.label: i18n("Pointer speed:")
id: accelSpeed
from: 1
to: 10
stepSize: 1
function load() {
enabled = device.supportsPointerAcceleration
if (!enabled) {
value = 0.1
return
}
// transform libinput's pointer acceleration range [-1, 1] to slider range [1, 10]
value = 4.5 * device.pointerAcceleration + 5.5
}
onValueChanged: {
if (device != undefined && enabled && !root.loading) {
// transform slider range [1, 10] to libinput's pointer acceleration range [-1, 1]
device.pointerAcceleration = Math.round( (value - 5.5) / 4.5 * 100 ) / 100
root.changeSignal()
}
}
}
Layouts.ColumnLayout {
id: accelProfile
spacing: Kirigami.Units.smallSpacing
Kirigami.FormData.label: i18n("Acceleration profile:")
Kirigami.FormData.buddyFor: accelProfileFlat
function load() {
enabled = device.supportsPointerAccelerationProfileAdaptive
if (!enabled) {
accelProfileAdaptive.checked = false
accelProfileFlat.checked = false
return
}
if(device.pointerAccelerationProfileAdaptive) {
accelProfileAdaptive.checked = true
accelProfileFlat.checked = false
} else {
accelProfileAdaptive.checked = false
accelProfileFlat.checked = true
}
}
function syncCurrent() {
if (enabled && !root.loading) {
device.pointerAccelerationProfileFlat = accelProfileFlat.checked
device.pointerAccelerationProfileAdaptive = accelProfileAdaptive.checked
root.changeSignal()
}
}
Controls.RadioButton {
id: accelProfileFlat
text: i18n("Flat")
ToolTip {
text: i18n("Cursor moves the same distance as the mouse movement.")
}
onCheckedChanged: accelProfile.syncCurrent()
}
Controls.RadioButton {
id: accelProfileAdaptive
text: i18n("Adaptive")
ToolTip {
text: i18n("Cursor travel distance depends on the mouse movement speed.")
}
onCheckedChanged: accelProfile.syncCurrent()
}
}
Kirigami.Separator {
}
// Scrolling
Controls.CheckBox {
Kirigami.FormData.label: i18n("Scrolling:")
id: naturalScroll
text: i18n("Invert scroll direction")
function load() {
enabled = device.supportsNaturalScroll
checked = enabled && device.naturalScroll
}
onCheckedChanged: {
if (enabled && !root.loading) {
device.naturalScroll = checked
root.changeSignal()
}
}
ToolTip {
text: i18n("Touchscreen like scrolling.")
}
}
}
......
/*
* Copyright 2018 Roman Gilg <subdiff@gmail.com>
* Copyright 2018 Furkan Tokac <furkantokac34@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -17,19 +18,24 @@
*/
import QtQuick 2.7
import QtQuick.Controls 1.4 as Controls
import QtQuick.Controls 2.0 as Controls
import QtQuick.Layouts 1.3 as Layouts
import QtQuick.Controls.Styles 1.4 as Styles
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.kcm 1.1 as KCM
import org.kde.kirigami 2.4 as Kirigami
import "components"
Item {
// TODO: Change ScrollablePage as KCM.SimpleKCM
// after rewrite the KCM in KConfigModule.
Kirigami.ScrollablePage {
id: root
property size sizeHint: Qt.size(maincol.width, Math.round(1.1 * maincol.height))
property size minimumSizeHint: Qt.size(maincol.width, Math.round(1.1 * maincol.height))
spacing: Kirigami.Units.smallSpacing
property size sizeHint: Qt.size(formLayout.width, Math.round(1.1 * formLayout.height))
property size minimumSizeHint: Qt.size(formLayout.width, Math.round(1.1 * formLayout.height))
signal changeSignal()
property QtObject device: deviceModel[0]
......@@ -46,206 +52,174 @@ Item {
leftHanded.load()
accelSpeed.load()
accelProfile.load()
naturalScroll.load()
loading = false
}
Controls.ScrollView {
anchors.fill: parent