Commit bd920746 authored by Roman Gilg's avatar Roman Gilg

Add KCM for controlling KWin's Night Color module

Simple but powerful KCM utilizing LibColorCorrect from Plasma Workspace
to provide configuration of Night Color in KWin.

Reviewers: #plasma, davidedmundson

Reviewed By: #plasma, davidedmundson

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D5932
parent 81d7aedf
......@@ -56,6 +56,7 @@ find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
find_package(LibKWorkspace CONFIG REQUIRED)
find_package(LibTaskManager CONFIG REQUIRED)
find_package(LibColorCorrect CONFIG REQUIRED)
find_package(KWinDBusInterface CONFIG REQUIRED)
find_package(ScreenSaverDBusInterface CONFIG REQUIRED)
find_package(KRunnerAppDBusInterface CONFIG REQUIRED)
......
......@@ -32,6 +32,7 @@ add_subdirectory( standard_actions )
add_subdirectory( keys )
add_subdirectory( ksmserver )
add_subdirectory( lookandfeel )
add_subdirectory( nightcolor )
add_subdirectory( hardware )
add_subdirectory( desktoppaths )
......
# KI18N Translation Domain for this library
add_definitions(-DTRANSLATION_DOMAIN=\"kcm_nightcolor\")
set(kcm_nightcolor_SRCS
kcm.cpp
)
add_library(kcm_nightcolor MODULE ${kcm_nightcolor_SRCS})
target_link_libraries(kcm_nightcolor
KF5::QuickAddons
KF5::I18n
PW::LibColorCorrect
)
kcoreaddons_desktop_to_json(kcm_nightcolor "kcm_nightcolor.desktop" SERVICE_TYPES kcmodule.desktop)
#this desktop file is installed only for retrocompatibility with sycoca
install(FILES kcm_nightcolor.desktop DESTINATION ${SERVICES_INSTALL_DIR})
install(TARGETS kcm_nightcolor DESTINATION ${PLUGIN_INSTALL_DIR}/kcms)
kpackage_install_package(package kcm_nightcolor kcms)
#! /usr/bin/env bash
$XGETTEXT `find . -name "*.cpp" -o -name "*.qml"` -o $podir/kcm_nightcolor.pot
/********************************************************************
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "kcm.h"
#include <KPluginFactory>
#include <KPluginLoader>
#include <KAboutData>
#include <KLocalizedString>
K_PLUGIN_FACTORY_WITH_JSON(KCMNightColorFactory, "kcm_nightcolor.json", registerPlugin<ColorCorrect::KCMNightColor>();)
namespace ColorCorrect {
KCMNightColor::KCMNightColor(QObject *parent, const QVariantList& args)
: KQuickAddons::ConfigModule(parent, args)
{
KAboutData* about = new KAboutData(QStringLiteral("kcm_nightcolor"), i18n("Night Color"),
QStringLiteral("0.1"), QString(), KAboutLicense::LGPL);
about->addAuthor(i18n("Roman Gilg"), QString(), QStringLiteral("subdiff@gmail.com"));
setAboutData(about);
setButtons(Apply | Default);
}
void KCMNightColor::load()
{
emit loadRelay();
}
void KCMNightColor::defaults()
{
emit defaultsRelay();
}
void KCMNightColor::save()
{
emit saveRelay();
}
}
#include "kcm.moc"
/********************************************************************
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef _KCM_NIGHTCOLOR_H
#define _KCM_NIGHTCOLOR_H
#include <KQuickAddons/ConfigModule>
namespace ColorCorrect {
class KCMNightColor : public KQuickAddons::ConfigModule
{
Q_OBJECT
public:
KCMNightColor(QObject* parent, const QVariantList& args);
~KCMNightColor() {}
public Q_SLOTS:
void load();
void save();
void defaults();
Q_SIGNALS:
void loadRelay();
void saveRelay();
void defaultsRelay();
};
}
#endif // _KCM_NIGHTCOLOR_H
[Desktop Entry]
Icon=preferences-desktop-display-nightcolor
Exec=kcmshell5 kcm_nightcolor
Type=Service
X-KDE-ServiceTypes=KCModule
X-DocPath=https://userbase.kde.org/TODOX
X-KDE-Library=kcm_nightcolor
X-KDE-ParentApp=kcontrol
X-KDE-System-Settings-Parent-Category=display
X-KDE-Weight=120
Name=Night Color
Name[de]=Nachtfarbe
Comment=Adjust color temperatur at night to reduce eye strain
Comment[de]=Passe Farbtemperatur nachts an um Augen zu entlasten
X-KDE-Keywords=kwin,window,manager,night,colors,redshift,eyes
X-KDE-Keywords[de]=KWin,Fenster,Verwaltung,Nacht,Farben,Redshift,Augen
Categories=Qt;KDE;X-KDE-settings-nightcolor
/********************************************************************
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
import QtQuick 2.1
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4 as Controls
GridLayout {
columns: 2
rowSpacing: units.smallSpacing
columnSpacing: units.smallSpacing
enabled: activator.checked
Controls.Label {
text: i18n("Latitude")
Layout.alignment: Qt.AlignRight
enabled: false
}
NumberField {
id: latitudeField
backend: locator.latitude
enabled: false
}
Controls.Label {
text: i18n("Longitude")
Layout.alignment: Qt.AlignRight
enabled: false
}
NumberField {
id: longitudeField
backend: locator.longitude
enabled: false
}
}
/********************************************************************
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
import QtQuick 2.1
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4 as Controls
GridLayout {
columns: 2
rowSpacing: units.smallSpacing
columnSpacing: units.smallSpacing
enabled: activator.checked
Connections {
target: root
onReset: reset()
}
function reset() {
latitudeFixedField.backend = cA.latitudeFixed;
longitudeFixedField.backend = cA.longitudeFixed;
}
Controls.Label {
text: i18n("Latitude")
Layout.alignment: Qt.AlignRight
}
NumberField {
id: latitudeFixedField
backend: cA.latitudeFixedStaged
validator: DoubleValidator {bottom: -90; top: 90; decimals: 10}
onBackendChanged: {
cA.latitudeFixedStaged = backend;
manualLocationsViewRow.change();
calcNeedsSave();
}
}
Controls.Label {
text: i18n("Longitude")
Layout.alignment: Qt.AlignRight
}
NumberField {
id: longitudeFixedField
backend: cA.longitudeFixedStaged
validator: DoubleValidator {bottom: -180; top: 180; decimals: 10}
onBackendChanged: {
cA.longitudeFixedStaged = backend;
manualLocationsViewRow.change();
calcNeedsSave();
}
}
Controls.Button {
Layout.columnSpan: 2
Layout.alignment: Qt.AlignHCenter
text: i18n("Detect location")
onClicked: {
latitudeFixedField.backend = locator.latitude;
longitudeFixedField.backend = locator.longitude;
}
}
}
/********************************************************************
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
import QtQuick 2.1
import QtQuick.Controls 1.4 as Controls
Controls.TextField {
property double backend
maximumLength: 10
horizontalAlignment: TextInput.AlignHCenter
inputMethodHints: Qt.ImhFormattedNumbersOnly
text: backend
onBackendChanged: {
text = backend;
}
onTextChanged: {
var textFloat = parseFloat(text);
if (textFloat == undefined || isNaN(textFloat)) {
return;
}
backend = textFloat;
}
onFocusChanged: {
var textFloat = parseFloat(text);
if (!focus && (textFloat == undefined || isNaN(textFloat))) {
text = backend;
}
}
}
/********************************************************************
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
import QtQuick 2.1
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4 as Controls
Controls.TextField {
id: field
property date backend
horizontalAlignment: TextInput.AlignHCenter
onBackendChanged: readIn()
function getNormedDate() {
var nD = new Date();
nD.setHours(backend.getHours());
nD.setMinutes(backend.getMinutes());
return nD;
}
function readIn() {
if (!backend) {
return;
}
var hours = backend.getHours();
var minutes = backend.getMinutes();
if (hours < 10) {
hours = "0" + hours;
}
if (minutes < 10) {
minutes = "0" + minutes;
}
text = hours + ":" + minutes;
}
function submit() {
if (text.length != 5) {
return;
}
var hours = text.slice(0, 2);
var minutes = text.slice(3, 5);
var date = new Date();
date.setHours(hours);
date.setMinutes(minutes);
backend = date;
}
inputMethodHints: Qt.ImhPreferNumbers
validator: RegExpValidator { regExp: /^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/ }
onEditingFinished: submit()
}
/********************************************************************
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
import QtQuick 2.1
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4 as Controls
GridLayout {
columns: 2
rowSpacing: units.smallSpacing
columnSpacing: units.smallSpacing
enabled: activator.checked
property double latitude
property double longitude
property var morningTimings: sunCalc.getMorningTimings(latitude, longitude)
property var eveningTimings: sunCalc.getEveningTimings(latitude, longitude)
function reset() {
morningTimings = sunCalc.getMorningTimings(latitude, longitude);
eveningTimings = sunCalc.getEveningTimings(latitude, longitude);
}
Controls.Label {
text: i18n("Sunrise begins")
Layout.alignment: Qt.AlignRight
enabled: false
}
TimeField {
id: mornBeginField
backend: morningTimings.begin
enabled: false
}
Controls.Label {
text: i18n("and ends")
Layout.alignment: Qt.AlignRight
enabled: false
}
TimeField {
id: mornEndField
backend: morningTimings.end
enabled: false
}
Controls.Label {
text: i18n("Sunset begins")
Layout.alignment: Qt.AlignRight
enabled: false
}
TimeField {
id: evenBeginField
backend: eveningTimings.begin
enabled: false
}
Controls.Label {
text: i18n("and ends")
Layout.alignment: Qt.AlignRight
enabled: false
}
TimeField {
id: evenEndField
backend: eveningTimings.end
enabled: false
}
}
/********************************************************************
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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
import QtQuick 2.1
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4 as Controls
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.colorcorrect 0.1 as CC
Item {
id: root
implicitHeight: units.gridUnit * 20
property int error: cA.error
property bool defaultRequested: false
CC.CompositorAdaptor {
id: cA
}
CC.Geolocator {
id: locator
}
CC.SunCalc {
id: sunCalc
}
function calcNeedsSave() {
kcm.needsSave = cA.checkStaged();
// If the user changes something manually again after
// Default was triggered, only allow a normal
// configuration change again:
defaultRequested = false;
}
Connections {
target: kcm
onLoadRelay: cA.reloadData()
onSaveRelay: defaultRequested ? cA.sendConfigurationAll() : cA.sendConfiguration();
onDefaultsRelay: {
if (!cA.nightColorAvailable) {
return;
}
activator.checked = cA.activeDefault;
tempSlider.value = cA.nightTemperatureDefault;
modeSwitcher.currentIndex = cA.modeDefault;
// set everything else to default as well
cA.latitudeFixedStaged = cA.latitudeFixedDefault;
cA.longitudeFixedStaged = cA.longitudeFixedDefault;
cA.morningBeginFixedStaged = cA.morningBeginFixedDefault;
cA.eveningBeginFixedStaged = cA.eveningBeginFixedDefault;
cA.transitionTimeStaged = cA.transitionTimeDefault;
kcm.needsSave = cA.checkStagedAll();
defaultRequested = true;
}
}
Connections {
target: cA
onDataUpdated: calcNeedsSave()
onStagedDataReset: {
activator.checked = cA.active;
tempSlider.value = cA.nightTemperature;
modeSwitcher.currentIndex = cA.mode;
reset();
calcNeedsSave();
}
}
signal reset()
Item {
id: main
width: childrenRect.width
height: childrenRect.height
enabled: cA.nightColorAvailable
Controls.CheckBox {
id: activator
text: i18n("Activate Night Color")
checked: cA.active
onCheckedChanged: {
cA.activeStaged = checked;
calcNeedsSave();
}
}
ColumnLayout {
id: mainControls
anchors.top: activator.bottom