Commit 15dd744a authored by Aleix Pol Gonzalez's avatar Aleix Pol Gonzalez 🐧
Browse files

Provide a telemetrics kcm module for Plasma

Summary:
It offers 2 main features:
- Configure the system-wide KUserFeedback kill-switch
- Provide a setting for how much information we want our Plasma to be sending

Test Plan:
Tested it together with Discover, works fine.

{F7497259}

Reviewers: #plasma, vkrause, ngraham

Reviewed By: ngraham

Subscribers: aspotashev, ngraham, bcooksley, davidedmundson, ognarb, broulik, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D24011
parent 625883de
......@@ -42,6 +42,7 @@ set_package_properties(KF5Kirigami2 PROPERTIES
)
# WARNING PlasmaQuick provides unversioned CMake config
find_package(KUserFeedback)
find_package(KF5 REQUIRED COMPONENTS PlasmaQuick)
find_package(KF5 REQUIRED COMPONENTS SysGuard)
find_package(KF5 REQUIRED COMPONENTS Package)
......
add_subdirectory(translations)
if(KUserFeedback_FOUND)
add_subdirectory(feedback)
endif()
add_definitions(-DTRANSLATION_DOMAIN=\"kcm_feedback\")
add_library(kcm_feedback MODULE feedback.cpp)
target_link_libraries(kcm_feedback
KF5::I18n
KF5::KCMUtils
KF5::QuickAddons
KUserFeedbackCore
)
kcoreaddons_desktop_to_json(kcm_feedback "kcm_feedback.desktop")
install(TARGETS kcm_feedback DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms)
install(FILES kcm_feedback.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
kpackage_install_package(package kcm_feedback kcms)
#! /usr/bin/env bash
$XGETTEXT `find . -name \*.cpp -o -name \*.qml` -o $podir/kcm_feedback.pot
/*
* Copyright (C) 2019 David Edmundson <davidedmundson@kde.org>
* Copyright (C) 2019 Aleix Pol Gonzalez <aleixpol@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "feedback.h"
#include <KSharedConfig>
#include <KConfigGroup>
#include <KPluginFactory>
#include <KAboutData>
#include <KLocalizedString>
#include <KUserFeedback/Provider>
K_PLUGIN_CLASS_WITH_JSON(Feedback, "kcm_feedback.json");
Feedback::Feedback(QObject *parent, const QVariantList &args)
: KQuickAddons::ConfigModule(parent)
//UserFeedback.conf is used by KUserFeedback which uses QSettings and won't go through globals
, m_globalConfig(KSharedConfig::openConfig(QStringLiteral("KDE/UserFeedback.conf"), KConfig::NoGlobals))
, m_plasmaConfig(KSharedConfig::openConfig(QStringLiteral("PlasmaUserFeedback")))
{
Q_UNUSED(args)
setAboutData(new KAboutData(QStringLiteral("kcm_feedback"),
i18n("User Feedback"),
QStringLiteral("1.0"), i18n("Configure user feedback settings"), KAboutLicense::LGPL));
connect(this, &Feedback::feedbackEnabledChanged, this, [this](){
setNeedsSave(true);
});
connect(this, &Feedback::plasmaFeedbackLevelChanged, this, [this](){
setNeedsSave(true);
});
}
Feedback::~Feedback() = default;
void Feedback::load()
{
KUserFeedback::Provider p;
setFeedbackEnabled(m_globalConfig->group("UserFeedback").readEntry("Enabled", p.isEnabled()));
setPlasmaFeedbackLevel(m_plasmaConfig->group("Global").readEntry("FeedbackLevel", int(KUserFeedback::Provider::BasicUsageStatistics)));
setNeedsSave(false);
}
void Feedback::save()
{
m_globalConfig->group("UserFeedback").writeEntry("Enabled", m_feedbackEnabled);
m_globalConfig->sync();
m_plasmaConfig->group("Global").writeEntry("FeedbackLevel", m_plasmaFeedbackLevel);
m_plasmaConfig->sync();
}
void Feedback::defaults()
{
setFeedbackEnabled(false);
setPlasmaFeedbackLevel(KUserFeedback::Provider::BasicUsageStatistics);
}
#include "feedback.moc"
/*
* Copyright (C) 2019 David Edmundson <davidedmundson@kde.org>
* Copyright (C) 2019 Aleix Pol Gonzalez <aleixpol@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#pragma once
#include <KQuickAddons/ConfigModule>
#include <KSharedConfig>
class Feedback : public KQuickAddons::ConfigModule
{
Q_OBJECT
Q_PROPERTY(bool feedbackEnabled READ feedbackEnabled WRITE setFeedbackEnabled NOTIFY feedbackEnabledChanged)
Q_PROPERTY(int plasmaFeedbackLevel READ plasmaFeedbackLevel WRITE setPlasmaFeedbackLevel NOTIFY plasmaFeedbackLevelChanged)
public:
explicit Feedback(QObject* parent = nullptr, const QVariantList &list = QVariantList());
~Feedback() override;
bool feedbackEnabled() const { return m_feedbackEnabled; }
int plasmaFeedbackLevel() const { return m_plasmaFeedbackLevel; }
void setFeedbackEnabled(bool feedbackEnabled) {
if (feedbackEnabled != m_feedbackEnabled) {
m_feedbackEnabled = feedbackEnabled;
Q_EMIT feedbackEnabledChanged(feedbackEnabled);
}
}
void setPlasmaFeedbackLevel(int plasmaFeedbackLevel) {
if (plasmaFeedbackLevel != m_plasmaFeedbackLevel) {
m_plasmaFeedbackLevel = plasmaFeedbackLevel;
Q_EMIT plasmaFeedbackLevelChanged(plasmaFeedbackLevel);
}
}
public Q_SLOTS:
void load() override;
void save() override;
void defaults() override;
Q_SIGNALS:
void feedbackEnabledChanged(bool feedbackEnabled) const;
void plasmaFeedbackLevelChanged(bool plasmaFeedbackLevel);
private:
KSharedConfig::Ptr m_globalConfig;
KSharedConfig::Ptr m_plasmaConfig;
bool m_feedbackEnabled = false;
int m_plasmaFeedbackLevel = 0;
};
[Desktop Entry]
Exec=kcmshell5 feedback
Icon=preferences-desktop-locale
Type=Service
X-KDE-ServiceTypes=KCModule
X-DocPath=kcontrol/feedback/index.html
X-KDE-Library=kcm_feedback
X-KDE-ParentApp=kcontrol
X-KDE-System-Settings-Parent-Category=personalization
Name=User Feedback
Comment=Configure user feedback settings
Categories=Qt;KDE;
/*
* Copyright (C) 2019 David Edmundson <davidedmundson@kde.org>
* Copyright (C) 2019 Aleix Pol Gonzalez <aleixpol@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
import QtQuick 2.1
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.3 as QQC2
import org.kde.kirigami 2.6 as Kirigami
import org.kde.userfeedback 1.0 as UserFeedback
import org.kde.kcm 1.2
SimpleKCM {
id: root
ConfigModule.buttons: ConfigModule.Defaults | ConfigModule.Apply
leftPadding: width * 0.1
rightPadding: leftPadding
Kirigami.FormLayout {
QQC2.CheckBox {
Kirigami.FormData.label: i18n("Feedback:")
checked: kcm.feedbackEnabled
onToggled: kcm.feedbackEnabled = checked
text: i18n("Allow KDE software to collect anomymous usage information")
}
Kirigami.Separator {
Layout.fillWidth: true
}
QQC2.Label {
Kirigami.FormData.label: i18n("Plasma:")
Layout.maximumWidth: root.width * 0.5
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
wrapMode: Text.WordWrap
text: xi18nc("@info", "We make Plasma for you. You can help us improve it by contributing information on how you use it. This allows us to focus on things that matter to you.<nl/><nl/>Contributing usage information is optional and entirely anonymous. It will not associate the data with any kind of unique identifier, and will never track the documents you open, the websites you visit, or any other kind of personal information.<nl/><nl/>You can read more about our policy in the following link.")
}
Kirigami.UrlButton {
Layout.leftMargin: Kirigami.Units.gridUnit
Layout.rightMargin: Kirigami.Units.gridUnit
url: "https://kde.org/privacypolicy-apps.php"
}
QQC2.ComboBox {
id: statisticsModeCombo
enabled: kcm.feedbackEnabled
Layout.fillWidth: true
textRole: "text"
model: ListModel { id: modeOptions }
Component.onCompleted: {
modeOptions.append({text: i18n("Basic System Information"), value: UserFeedback.Provider.BasicSystemInformation})
modeOptions.append({text: i18n("Basic Usage Information"), value: UserFeedback.Provider.BasicUsageStatistics})
modeOptions.append({text: i18n("Detailed System Information"), value: UserFeedback.Provider.DetailedSystemInformation})
modeOptions.append({text: i18n("Detailed Usage Information"), value: UserFeedback.Provider.DetailedUsageStatistics})
for(var i = 0, c=modeOptions.count; i<c; ++i) {
if (modeOptions.get(i).value === kcm.plasmaFeedbackLevel) {
currentIndex = i;
break;
}
}
if (currentIndex < 0)
currentIndex = 2
}
onActivated: {
kcm.plasmaFeedbackLevel = modeOptions.get(index).value;
}
}
UserFeedback.FeedbackConfigUiController {
id: feedbackController
}
QQC2.Label {
Layout.maximumWidth: root.width * 0.5
wrapMode: Text.WordWrap
text: feedbackController.telemetryDescription(modeOptions.get(statisticsModeCombo.currentIndex).value)
}
}
}
[Desktop Entry]
Name=Feedback
Icon=preferences-desktop-locale
Type=Service
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-Name=kcm_feedback
X-KDE-ServiceTypes=Plasma/Generic
X-Plasma-API=declarativeappletscript
X-Plasma-MainScript=ui/main.qml
......@@ -71,6 +71,7 @@ target_link_libraries(plasmashell
KF5::WaylandClient
KF5::Notifications
PW::KWorkspace
KUserFeedbackCore
)
target_include_directories(plasmashell PRIVATE "${CMAKE_BINARY_DIR}")
target_compile_definitions(plasmashell PRIVATE -DPROJECT_VERSION="${PROJECT_VERSION}")
......
/*
* Copyright 2019 Aleix Pol Gonzalez <aleixpol@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, 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 Library 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.
*/
#ifndef PANELCOUNTSOURCE_H
#define PANELCOUNTSOURCE_H
#include "shellcorona.h"
#include <KLocalizedString>
#include <KUserFeedback/AbstractDataSource>
class PanelCountSource : public KUserFeedback::AbstractDataSource
{
public:
/*! Create a new start count data source. */
PanelCountSource(ShellCorona* corona)
: AbstractDataSource(QStringLiteral("panelCount"), KUserFeedback::Provider::DetailedSystemInformation)
, corona(corona)
{}
QString name() const override { return i18n("Panel Count"); }
QString description() const override { return i18n("Counts the panels"); }
QVariant data() override { return corona->panelCount(); }
private:
ShellCorona* const corona;
};
#endif
......@@ -51,6 +51,14 @@
#include <kdeclarative/qmlobjectsharedengine.h>
#include <KMessageBox>
#include <kdirwatch.h>
#include <KUserFeedback/Provider>
#include <KUserFeedback/ApplicationVersionSource>
#include <KUserFeedback/CompilerInfoSource>
#include <KUserFeedback/PlatformInfoSource>
#include <KUserFeedback/QtVersionSource>
#include <KUserFeedback/UsageTimeSource>
#include <KUserFeedback/OpenGLInfoSource>
#include <KUserFeedback/ScreenInfoSource>
#include <KPackage/PackageLoader>
......@@ -70,6 +78,7 @@
#include "plasmashelladaptor.h"
#include "debug.h"
#include "futureutil.h"
#include "panelcountsource.h"
#ifndef NDEBUG
#define CHECK_SCREEN_INVARIANTS screenInvariants();
......@@ -83,7 +92,6 @@
#include <xcb/xcb.h>
#endif
static const int s_configSyncDelay = 10000; // 10 seconds
ShellCorona::ShellCorona(QObject *parent)
......@@ -273,6 +281,26 @@ void ShellCorona::setShell(const QString &shell)
t->setThemeName(themeName);
}
auto m_feedbackProvider = new KUserFeedback::Provider(this);
m_feedbackProvider->setProductIdentifier(QStringLiteral("org.kde.plasmashell"));
m_feedbackProvider->setFeedbackServer(QUrl(QStringLiteral("https://telemetry.kde.org/")));
m_feedbackProvider->setSubmissionInterval(7);
m_feedbackProvider->setApplicationStartsUntilEncouragement(5);
m_feedbackProvider->setEncouragementDelay(30);
m_feedbackProvider->addDataSource(new KUserFeedback::ApplicationVersionSource);
m_feedbackProvider->addDataSource(new KUserFeedback::CompilerInfoSource);
m_feedbackProvider->addDataSource(new KUserFeedback::PlatformInfoSource);
m_feedbackProvider->addDataSource(new KUserFeedback::QtVersionSource);
m_feedbackProvider->addDataSource(new KUserFeedback::UsageTimeSource);
m_feedbackProvider->addDataSource(new KUserFeedback::OpenGLInfoSource);
m_feedbackProvider->addDataSource(new KUserFeedback::ScreenInfoSource);
m_feedbackProvider->addDataSource(new PanelCountSource(this));
{
auto plasmaConfig = KSharedConfig::openConfig(QStringLiteral("PlasmaUserFeedback"));
m_feedbackProvider->setTelemetryMode(KUserFeedback::Provider::TelemetryMode(plasmaConfig->group("Global").readEntry("FeedbackLevel", int(KUserFeedback::Provider::BasicUsageStatistics))));
}
//FIXME: this would change the runtime platform to a fixed one if available
// but a different way to load platform specific components is needed beforehand
// because if we import and use two different components plugin, the second time
......@@ -309,7 +337,6 @@ void ShellCorona::setShell(const QString &shell)
load();
}
QJsonObject dumpconfigGroupJS(const KConfigGroup &rootGroup)
{
QJsonObject result;
......
......@@ -164,6 +164,8 @@ public Q_SLOTS:
void setTestModeLayout(const QString &layout) { m_testModeLayout = layout; }
int panelCount() const { return m_panelViews.count(); }
protected Q_SLOTS:
/**
* Loads the layout and performs the needed checks
......
Markdown is supported
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