Commit 25c30932 authored by Eike Hein's avatar Eike Hein

Port launch feedback KCM to Qt Quick and implement VDG redesign

Summary:
* Implements VDG mockup M112/364
** But using "Task Manager" naming for consistency instead of "Taskbar"
** Additional UI tweak of using i18np for spinbox suffices
* Switched from generic name "launch" to "launchfeedback"
** This will require i18n pot and doc HTML renames to match
* Original business logic is preserved as-is, but code is simplified and cleaned-up (coding style, etc.)

Depends on D8641.

Reviewers: #plasma, mart, abetts

Reviewed By: #plasma, mart

Subscribers: anthonyfieroni, mmustac, ngraham, davidedmundson, broulik, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D8911
parent cd542ab3
# KI18N Translation Domain for this library
add_definitions(-DTRANSLATION_DOMAIN=\"kcmlaunch\")
# KI18N Translation Domain for this library.
add_definitions(-DTRANSLATION_DOMAIN=\"kcmlaunchfeedback\")
########### next target ###############
set(kcm_launch_PART_SRCS kcmlaunch.cpp )
set(kcm_launchfeedback_PART_SRCS launchfeedback.cpp)
set_source_files_properties(${KWIN_EFFECTS_INTERFACE} PROPERTIES INCLUDE "interface_util.h")
qt5_add_dbus_interface( kcm_launch_PART_SRCS ${KWIN_EFFECTS_INTERFACE} kwin_interface )
add_library(kcm_launch MODULE ${kcm_launch_PART_SRCS})
qt5_add_dbus_interface(kcm_launchfeedback_PART_SRCS ${KWIN_EFFECTS_INTERFACE} kwin_interface)
add_library(kcm_launchfeedback MODULE ${kcm_launchfeedback_PART_SRCS})
target_link_libraries(kcm_launch
target_link_libraries(kcm_launchfeedback
Qt5::DBus
KF5::KCMUtils
KF5::I18n
KF5::KCMUtils
KF5::QuickAddons
)
install(TARGETS kcm_launch DESTINATION ${PLUGIN_INSTALL_DIR} )
kcoreaddons_desktop_to_json(kcm_launchfeedback "kcm_launchfeedback.desktop")
########### install files ###############
install( FILES kcmlaunch.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
install(TARGETS kcm_launchfeedback DESTINATION ${PLUGIN_INSTALL_DIR}/kcms)
install(FILES kcm_launchfeedback.desktop DESTINATION ${SERVICES_INSTALL_DIR})
kpackage_install_package(package kcm_launchfeedback kcms)
#! /usr/bin/env bash
$XGETTEXT *.cpp -o $podir/kcmlaunch.pot
$XGETTEXT `find . -name \*.cpp -o -name \*.qml` -o $podir/kcmlaunchfeedback.pot
......@@ -2,10 +2,10 @@
Icon=preferences-desktop-launch-feedback
Type=Service
X-KDE-ServiceTypes=KCModule
X-DocPath=kcontrol/kcmlaunch/index.html
Exec=kcmshell5 kcmlaunch
X-DocPath=kcontrol/kcmlaunchfeedback/index.html
Exec=kcmshell5 launchfeedback
X-KDE-Library=kcm_launch
X-KDE-Library=kcm_launchfeedback
X-KDE-ParentApp=kcontrol
X-KDE-System-Settings-Parent-Category=applications
......@@ -163,7 +163,7 @@ X-KDE-Keywords[ga]=feidhmchlár,tosach,tosaigh,gafa,cúrsóir,aisfhotha,luch,luc
X-KDE-Keywords[gl]=aplicación,aplicativo,programa,inicio,iniciar,ocupado,cursor,indicador,rato, punteiro,rebotar,rodar,rotar,xirar,disco,informe,barra de tarefas
X-KDE-Keywords[hu]=alkalmazás,indítás,indítás,elfoglalt,kurzor,visszajelzés,egér,mutató,pattogás,forgatás,csavarás,lemez,indítás,program,jelentés,feladatsáv
X-KDE-Keywords[ia]=application,initio,lancea,occupate,cursor,retro information,mus,punctator,saltante,rotante,torneante,disco,initio,programma,reporto,barra de carga
X-KDE-Keywords[id]=aplikasi,start,jalankan,sibuk,kursor,umpan balik,mouse,penunjuk,memantul,rotasi,berputar,cakram,startup,program,laporan,bilah tugas
X-KDE-Keywords[id]=aplikasi,start,jalankan,sibuk,kursor,umpan balik,tetikus,penunjuk,memantul,rotasi,berputar,cakram,startup,program,laporan,batang tugas
X-KDE-Keywords[it]=applicazione,avvia,esegui,occupato,puntatore,segnale di avvio,mouse,puntatore,rimbalza,rotazione,disco,avvio,programma,resoconto,barra dei processi
X-KDE-Keywords[kk]=application,start,launch,busy,cursor,feedback,mouse,pointer,bouncing,rotating,spinning,disk,startup,program,report,taskbar
X-KDE-Keywords[km]=application,start,launch,busy,cursor,feedback,mouse,pointer,bouncing,rotating,spinning,disk,startup,program,report,taskbar
......
/*
* Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
*
* 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
*/
#include <QCheckBox>
#include <QComboBox>
#include <QLabel>
#include <QGroupBox>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QSpinBox>
#include <KConfigGroup>
#include <KLocalizedString>
#include <kconfig.h>
#include "kcmlaunch.h"
#include "kwin_interface.h"
#include <KPluginFactory>
K_PLUGIN_FACTORY(LaunchFactory,
registerPlugin<LaunchConfig>();
)
static const int s_startupDefaultTimeout = 5;
LaunchConfig::LaunchConfig(QWidget * parent, const QVariantList &)
: KCModule(parent)
{
QVBoxLayout* Form1Layout = new QVBoxLayout( this );
Form1Layout->setMargin( 0 );
setQuickHelp( i18n ( "<h1>Launch Feedback</h1>"
" You can configure the application-launch feedback here." ) );
QGroupBox* GroupBox1 = new QGroupBox(i18n( "Bus&y Cursor" ));
GroupBox1->setWhatsThis( i18n(
"<h1>Busy Cursor</h1>\n"
"KDE offers a busy cursor for application startup notification.\n"
"To enable the busy cursor, select one kind of visual feedback\n"
"from the combobox.\n"
"It may occur, that some applications are not aware of this startup\n"
"notification. In this case, the cursor stops blinking after the time\n"
"given in the section 'Startup indication timeout'"));
QGridLayout* GroupBox1Layout = new QGridLayout();
GroupBox1->setLayout( GroupBox1Layout );
Form1Layout->addWidget(GroupBox1);
GroupBox1Layout->setColumnStretch( 1, 1 );
cb_busyCursor = new QComboBox( GroupBox1);
cb_busyCursor->setObjectName( QStringLiteral("cb_busyCursor") );
cb_busyCursor->insertItem( 0, i18n( "No Busy Cursor" ) );
cb_busyCursor->insertItem( 1, i18n( "Passive Busy Cursor" ) );
cb_busyCursor->insertItem( 2, i18n( "Blinking Cursor" ) );
cb_busyCursor->insertItem( 3, i18n( "Bouncing Cursor" ) );
GroupBox1Layout->addWidget( cb_busyCursor, 0, 0 );
connect(cb_busyCursor, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &LaunchConfig::slotBusyCursor);
connect(cb_busyCursor, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &LaunchConfig::checkChanged);
lbl_cursorTimeout = new QLabel( GroupBox1 );
lbl_cursorTimeout->setObjectName( QStringLiteral("TextLabel1") );
lbl_cursorTimeout->setText( i18n( "&Startup indication timeout:" ) );
GroupBox1Layout->addWidget( lbl_cursorTimeout, 2, 0 );
sb_cursorTimeout = new QSpinBox( GroupBox1);
sb_cursorTimeout->setRange( 0, 99 );
sb_cursorTimeout->setSuffix( i18n(" sec") );
GroupBox1Layout->addWidget( sb_cursorTimeout, 2, 1 );
lbl_cursorTimeout->setBuddy( sb_cursorTimeout );
connect(sb_cursorTimeout, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &LaunchConfig::checkChanged);
QGroupBox* GroupBox2 = new QGroupBox( i18n( "Taskbar &Notification" ) );
GroupBox2->setWhatsThis( i18n("<H1>Taskbar Notification</H1>\n"
"You can enable a second method of startup notification which is\n"
"used by the taskbar where a button with a rotating hourglass appears,\n"
"symbolizing that your started application is loading.\n"
"It may occur, that some applications are not aware of this startup\n"
"notification. In this case, the button disappears after the time\n"
"given in the section 'Startup indication timeout'"));
QGridLayout* GroupBox2Layout = new QGridLayout();
GroupBox2->setLayout( GroupBox2Layout );
Form1Layout->addWidget( GroupBox2 );
GroupBox2Layout->setColumnStretch( 1, 1 );
cb_taskbarButton = new QCheckBox( GroupBox2 );
cb_taskbarButton->setObjectName( QStringLiteral("cb_taskbarButton") );
cb_taskbarButton->setText( i18n( "Enable &taskbar notification" ) );
GroupBox2Layout->addWidget( cb_taskbarButton, 0, 0, 1, 2 );
connect(cb_taskbarButton, &QCheckBox::toggled, this, &LaunchConfig::slotTaskbarButton);
connect(cb_taskbarButton, &QCheckBox::toggled, this, &LaunchConfig::checkChanged);
lbl_taskbarTimeout = new QLabel( GroupBox2 );
lbl_taskbarTimeout->setObjectName( QStringLiteral("TextLabel2") );
lbl_taskbarTimeout->setText( i18n( "Start&up indication timeout:" ) );
GroupBox2Layout->addWidget( lbl_taskbarTimeout, 1, 0 );
sb_taskbarTimeout = new QSpinBox( GroupBox2);
sb_taskbarTimeout->setRange( 0, 99 );
sb_taskbarTimeout->setSuffix( i18n(" sec") );
GroupBox2Layout->addWidget( sb_taskbarTimeout, 1, 1 );
lbl_taskbarTimeout->setBuddy( sb_taskbarTimeout );
connect(sb_taskbarTimeout, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &LaunchConfig::checkChanged);
Form1Layout->addStretch();
}
LaunchConfig::~LaunchConfig()
{
}
void
LaunchConfig::slotBusyCursor(int i)
{
lbl_cursorTimeout->setEnabled( i != 0 );
sb_cursorTimeout->setEnabled( i != 0 );
}
void
LaunchConfig::slotTaskbarButton(bool b)
{
lbl_taskbarTimeout->setEnabled( b );
sb_taskbarTimeout->setEnabled( b );
}
void
LaunchConfig::load()
{
KConfig conf(QStringLiteral("klaunchrc"), KConfig::NoGlobals);
KConfigGroup c = conf.group("FeedbackStyle");
bool busyCursor =
c.readEntry("BusyCursor", (bool)(Default & BusyCursor));
bool taskbarButton =
c.readEntry("TaskbarButton", (bool)(Default & TaskbarButton));
cb_taskbarButton->setChecked(taskbarButton);
c= conf.group( "BusyCursorSettings" );
sb_cursorTimeout->setValue( c.readEntry( "Timeout", s_startupDefaultTimeout ));
bool busyBlinking =c.readEntry("Blinking", false);
bool busyBouncing =c.readEntry("Bouncing", true);
if ( !busyCursor )
cb_busyCursor->setCurrentIndex(0);
else if ( busyBlinking )
cb_busyCursor->setCurrentIndex(2);
else if ( busyBouncing )
cb_busyCursor->setCurrentIndex(3);
else
cb_busyCursor->setCurrentIndex(1);
c= conf.group( "TaskbarButtonSettings" );
sb_taskbarTimeout->setValue( c.readEntry( "Timeout", s_startupDefaultTimeout ));
slotBusyCursor( cb_busyCursor->currentIndex() );
slotTaskbarButton( taskbarButton );
emit changed( false );
}
void
LaunchConfig::save()
{
KConfig conf(QStringLiteral("klaunchrc"), KConfig::NoGlobals);
KConfigGroup c = conf.group("FeedbackStyle");
c.writeEntry("BusyCursor", cb_busyCursor->currentIndex() != 0);
c.writeEntry("TaskbarButton", cb_taskbarButton->isChecked());
c = conf.group("BusyCursorSettings");
c.writeEntry( "Timeout", sb_cursorTimeout->value());
c.writeEntry("Blinking", cb_busyCursor->currentIndex() == 2);
c.writeEntry("Bouncing", cb_busyCursor->currentIndex() == 3);
c = conf.group("TaskbarButtonSettings");
c.writeEntry( "Timeout", sb_taskbarTimeout->value());
c.sync();
emit changed( false );
org::kde::kwin::Effects kwin(QStringLiteral("org.kde.KWin"), QStringLiteral("/Effects"), QDBusConnection::sessionBus());
kwin.reconfigureEffect(QStringLiteral("startupfeedback"));
}
void
LaunchConfig::defaults()
{
cb_busyCursor->setCurrentIndex(3); // bouncing cursor
cb_taskbarButton->setChecked( (bool)(Default & TaskbarButton) );
sb_cursorTimeout->setValue( s_startupDefaultTimeout );
sb_taskbarTimeout->setValue( s_startupDefaultTimeout );
slotBusyCursor(3);
slotTaskbarButton( (bool)(Default & TaskbarButton) );
checkChanged();
}
void
LaunchConfig::checkChanged()
{
KConfig conf(QStringLiteral("klaunchrc"), KConfig::NoGlobals);
KConfigGroup c = conf.group("FeedbackStyle");
bool savedBusyCursor =
c.readEntry("BusyCursor", (bool)(Default & BusyCursor));
bool savedTaskbarButton =
c.readEntry("TaskbarButton", (bool)(Default & TaskbarButton));
c = conf.group("BusyCursorSettings");
unsigned int savedCursorTimeout = c.readEntry( "Timeout", s_startupDefaultTimeout );
bool savedBusyBlinking =c.readEntry("Blinking", false);
bool savedBusyBouncing =c.readEntry("Bouncing", true);
c = conf.group("TaskbarButtonSettings");
unsigned int savedTaskbarTimeout = c.readEntry( "Timeout", s_startupDefaultTimeout );
bool newBusyCursor =cb_busyCursor->currentIndex()!=0;
bool newTaskbarButton =cb_taskbarButton->isChecked();
bool newBusyBlinking= cb_busyCursor->currentIndex()==2;
bool newBusyBouncing= cb_busyCursor->currentIndex()==3;
unsigned int newCursorTimeout = sb_cursorTimeout->value();
unsigned int newTaskbarTimeout = sb_taskbarTimeout->value();
emit changed(
savedBusyCursor != newBusyCursor
||
savedTaskbarButton != newTaskbarButton
||
savedCursorTimeout != newCursorTimeout
||
savedTaskbarTimeout != newTaskbarTimeout
||
savedBusyBlinking != newBusyBlinking
||
savedBusyBouncing != newBusyBouncing
);
}
#include "kcmlaunch.moc"
/*
* Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
* Copyright (C) 2017 Eike Hein <hein@kde.org>
*
* 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
*/
#include "launchfeedback.h"
#include <KAboutData>
#include <KConfig>
#include <KConfigGroup>
#include <KLocalizedString>
#include <KPluginFactory>
#include "kwin_interface.h"
#define STARTUP_DEFAULT_TIMEOUT 5
K_PLUGIN_FACTORY_WITH_JSON(LaunchFactory, "kcm_launchfeedback.json", registerPlugin<LaunchFeedback>();)
LaunchFeedback::LaunchFeedback(QObject *parent, const QVariantList &args)
: KQuickAddons::ConfigModule(parent, args)
, m_busyCursorCurrentIndex(3)
, m_taskManagerNotification(true)
, m_notificationTimeout(STARTUP_DEFAULT_TIMEOUT)
{
KAboutData *about = new KAboutData("kcm_launchfeedback",
i18n("Configure application launch feedback"),
"0.2", QString(), KAboutLicense::LGPL);
setAboutData(about);
setButtons(Apply | Default);
}
LaunchFeedback::~LaunchFeedback()
{
}
int LaunchFeedback::busyCursorCurrentIndex() const
{
return m_busyCursorCurrentIndex;
}
void LaunchFeedback::setBusyCursorCurrentIndex(int index)
{
if (m_busyCursorCurrentIndex != index) {
m_busyCursorCurrentIndex = index;
emit busyCursorCurrentIndexChanged();
updateNeedsSave();
}
}
bool LaunchFeedback::taskManagerNotification() const
{
return m_taskManagerNotification;
}
void LaunchFeedback::setTaskManagerNotification(bool enabled)
{
if (m_taskManagerNotification != enabled) {
m_taskManagerNotification = enabled;
emit taskManagerNotificationChanged();
updateNeedsSave();
}
}
int LaunchFeedback::notificationTimeout() const
{
return m_notificationTimeout;
}
void LaunchFeedback::setNotificationTimeout(int duration)
{
if (m_notificationTimeout != duration) {
m_notificationTimeout = duration;
emit notificationTimeoutChanged();
updateNeedsSave();
}
}
void LaunchFeedback::load()
{
KConfig conf(QStringLiteral("klaunchrc"), KConfig::NoGlobals);
KConfigGroup c = conf.group("FeedbackStyle");
const bool busyCursor = c.readEntry("BusyCursor", true);
setTaskManagerNotification(c.readEntry("TaskbarButton", true));
c = conf.group("BusyCursorSettings");
setNotificationTimeout(c.readEntry("Timeout", STARTUP_DEFAULT_TIMEOUT));
bool busyBlinking = c.readEntry("Blinking", false);
bool busyBouncing = c.readEntry("Bouncing", true);
if (!busyCursor) {
setBusyCursorCurrentIndex(0);
} else if (busyBlinking) {
setBusyCursorCurrentIndex(2);
} else if (busyBouncing) {
setBusyCursorCurrentIndex(3);
} else {
setBusyCursorCurrentIndex(1);
}
}
void LaunchFeedback::save()
{
KConfig conf(QStringLiteral("klaunchrc"), KConfig::NoGlobals);
KConfigGroup c = conf.group("FeedbackStyle");
c.writeEntry("BusyCursor", m_busyCursorCurrentIndex != 0);
c.writeEntry("TaskbarButton", m_taskManagerNotification);
c = conf.group("BusyCursorSettings");
c.writeEntry("Timeout", m_notificationTimeout);
c.writeEntry("Blinking", m_busyCursorCurrentIndex == 2);
c.writeEntry("Bouncing", m_busyCursorCurrentIndex == 3);
c = conf.group("TaskbarButtonSettings");
c.writeEntry( "Timeout", m_notificationTimeout);
c.sync();
setNeedsSave(false);
org::kde::kwin::Effects kwin(QStringLiteral("org.kde.KWin"),
QStringLiteral("/Effects"),
QDBusConnection::sessionBus());
kwin.reconfigureEffect(QStringLiteral("startupfeedback"));
}
void LaunchFeedback::defaults()
{
setBusyCursorCurrentIndex(3); // Bouncing cursor.
setTaskManagerNotification(true);
setNotificationTimeout(STARTUP_DEFAULT_TIMEOUT);
}
void LaunchFeedback::updateNeedsSave()
{
bool needsSave = false;
KConfig conf(QStringLiteral("klaunchrc"), KConfig::NoGlobals);
KConfigGroup c = conf.group("FeedbackStyle");
const bool savedBusyCursor = c.readEntry("BusyCursor", true);
if (m_taskManagerNotification != c.readEntry("TaskbarButton", true)) {
needsSave = true;
}
c = conf.group("BusyCursorSettings");
if (m_notificationTimeout != c.readEntry("Timeout", STARTUP_DEFAULT_TIMEOUT)) {
needsSave = true;
}
int savedBusyCursorIndex = 3; // Bouncing cursor (default);
bool savedBusyBlinking = c.readEntry("Blinking", false);
bool savedBusyBouncing = c.readEntry("Bouncing", true);
if (!savedBusyCursor) {
savedBusyCursorIndex = 0;
} else if (savedBusyBlinking) {
savedBusyCursorIndex = 2;
} else if (savedBusyBouncing) {
savedBusyCursorIndex = 3;
} else {
savedBusyCursorIndex = 1;
}
if (m_busyCursorCurrentIndex != savedBusyCursorIndex) {
needsSave = true;
}
setNeedsSave(needsSave);
}
#include "launchfeedback.moc"
/*
* Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
* Copyright (C) 2017 Eike Hein <hein@kde.org>
*
* 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
......@@ -15,57 +16,54 @@
* along with this program; if not, write to the Free Software
*/
#ifndef __kcmlaunch_h__
#define __kcmlaunch_h__
#ifndef LAUNCHFEEDBACK_H
#define LAUNCHFEEDBACK_H
#include <kcmodule.h>
#include <KQuickAddons/ConfigModule>
class QCheckBox;
class QComboBox;
class QLabel;
class LaunchFeedback : public KQuickAddons::ConfigModule
{
Q_OBJECT
class QSpinBox;
Q_PROPERTY(int busyCursorCurrentIndex READ busyCursorCurrentIndex WRITE setBusyCursorCurrentIndex NOTIFY busyCursorCurrentIndexChanged)
class LaunchConfig : public KCModule
{
Q_OBJECT
Q_PROPERTY(bool taskManagerNotification READ taskManagerNotification WRITE setTaskManagerNotification NOTIFY taskManagerNotificationChanged)
public:
Q_PROPERTY(int notificationTimeout READ notificationTimeout WRITE setNotificationTimeout NOTIFY notificationTimeoutChanged)
explicit LaunchConfig(QWidget * parent = 0, const QVariantList &list = QVariantList() );
public:
explicit LaunchFeedback(QObject* parent = 0, const QVariantList &list = QVariantList());
virtual ~LaunchFeedback();
virtual ~LaunchConfig();
int busyCursorCurrentIndex() const;
void setBusyCursorCurrentIndex(int index);
void load() override;
void save() override;
void defaults() override;
bool taskManagerNotification() const;
void setTaskManagerNotification(bool enabled);
protected Q_SLOTS:
int notificationTimeout() const;
void setNotificationTimeout(int duration);
void checkChanged();
void slotBusyCursor(int);
void slotTaskbarButton(bool);
public Q_SLOTS:
void load();
void save();
void defaults();
protected:
Q_SIGNALS:
void busyCursorCurrentIndexChanged() const;
enum FeedbackStyle
{
BusyCursor = 1 << 0,
TaskbarButton = 1 << 1,
void taskManagerNotificationChanged() const;
Default = BusyCursor | TaskbarButton
};
void notificationTimeoutChanged() const;
private:
void updateNeedsSave();