Commit 465e0613 authored by Elvis Angelaccio's avatar Elvis Angelaccio
Browse files

Add support for KUserFeedback

This commit introduces KUserFeedback in dolphin with some basic data
sources and with a settings page to configure the telemetry values.

There are also a couple custom data sources as proof of concept: a bunch
of settings and the count of available network shares as listed by Solid.

The settings page is shown only if the user feedback framework is
enabled, but currently in Plasma we don't have a global kill switch to
disable it.

At the moment we never show an encouragement message. We need to connect
to the `Provider::showEncouragementMessage()` signal, but first we
should agree to a common way to show a non-annoying message to the users.
parent 61bf84c1
......@@ -66,6 +66,17 @@ find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
Crash
WindowSystem
)
find_package(KUserFeedback 1.0.0)
set_package_properties(KUserFeedback
PROPERTIES TYPE OPTIONAL
PURPOSE "Used for submission of telemetry data"
)
if(KUserFeedback_FOUND)
set(HAVE_KUSERFEEDBACK TRUE)
endif()
find_package(KF5 ${KF5_MIN_VERSION} OPTIONAL_COMPONENTS
Activities
)
......
......@@ -8,6 +8,8 @@ configure_file(config-packagekit.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-pack
configure_file(config-terminal.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-terminal.h)
configure_file(config-kuserfeedback.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kuserfeedback.h)
add_definitions(
-DTRANSLATION_DOMAIN=\"dolphin\"
)
......@@ -261,6 +263,16 @@ if(HAVE_BALOO)
)
endif()
if(HAVE_KUSERFEEDBACK)
set(dolphinstatic_SRCS
${dolphinstatic_SRCS}
userfeedback/dolphinfeedbackprovider.cpp
userfeedback/settingsdatasource.cpp
userfeedback/placesdatasource.cpp
settings/userfeedback/userfeedbacksettingspage.cpp
)
endif()
kconfig_add_kcfg_files(dolphinstatic_SRCS GENERATE_MOC
panels/folders/dolphin_folderspanelsettings.kcfgc
panels/information/dolphin_informationpanelsettings.kcfgc
......@@ -299,6 +311,14 @@ if (HAVE_KACTIVITIES)
)
endif()
if (HAVE_KUSERFEEDBACK)
target_link_libraries(
dolphinstatic
KUserFeedbackCore
KUserFeedbackWidgets
)
endif()
set(dolphin_SRCS
dbusinterface.cpp
main.cpp
......
#cmakedefine HAVE_KUSERFEEDBACK
......@@ -245,6 +245,16 @@ void DolphinMainWindow::openFiles(const QList<QUrl>& files, bool splitView)
m_tabWidget->openFiles(files, splitView);
}
bool DolphinMainWindow::isFoldersPanelEnabled() const
{
return actionCollection()->action(QStringLiteral("show_folders_panel"))->isChecked();
}
bool DolphinMainWindow::isInformationPanelEnabled() const
{
return actionCollection()->action(QStringLiteral("show_information_panel"))->isChecked();
}
void DolphinMainWindow::openFiles(const QStringList& files, bool splitView)
{
openFiles(QUrl::fromStringList(files), splitView);
......
......@@ -108,6 +108,9 @@ public:
*/
void setViewsWithInvalidPathsToHome();
bool isFoldersPanelEnabled() const;
bool isInformationPanelEnabled() const;
public slots:
/**
* Opens each directory in \p dirs in a separate tab. If \a splitView is set,
......
......@@ -12,6 +12,10 @@
#include "dolphindebug.h"
#include "dolphinmainwindow.h"
#include "global.h"
#include "config-kuserfeedback.h"
#ifdef HAVE_KUSERFEEDBACK
#include "userfeedback/dolphinfeedbackprovider.h"
#endif
#include <KAboutData>
#include <KCrash>
......@@ -210,5 +214,10 @@ extern "C" Q_DECL_EXPORT int kdemain(int argc, char **argv)
}
}
#ifdef HAVE_KUSERFEEDBACK
auto feedbackProvider = DolphinFeedbackProvider::instance();
Q_UNUSED(feedbackProvider)
#endif
return app.exec(); // krazy:exclude=crash;
}
......@@ -14,6 +14,11 @@
#include "startup/startupsettingspage.h"
#include "trash/trashsettingspage.h"
#include "viewmodes/viewsettingspage.h"
#include "config-kuserfeedback.h"
#ifdef HAVE_KUSERFEEDBACK
#include "userfeedback/dolphinfeedbackprovider.h"
#include "userfeedback/userfeedbacksettingspage.h"
#endif
#include <KAuthorized>
#include <KLocalizedString>
......@@ -91,6 +96,17 @@ DolphinSettingsDialog::DolphinSettingsDialog(const QUrl& url, QWidget* parent) :
connect(trashSettingsPage, &TrashSettingsPage::changed, this, &DolphinSettingsDialog::enableApply);
}
#ifdef HAVE_KUSERFEEDBACK
// User Feedback
UserFeedbackSettingsPage* feedbackSettingsPage = nullptr;
if (DolphinFeedbackProvider::instance()->isEnabled()) {
feedbackSettingsPage = new UserFeedbackSettingsPage(this);
auto feedbackSettingsFrame = addPage(feedbackSettingsPage, i18nc("@title:group", "User Feedback"));
feedbackSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-locale")));
connect(feedbackSettingsPage, &UserFeedbackSettingsPage::changed, this, &DolphinSettingsDialog::enableApply);
}
#endif
m_pages.append(generalSettingsPage);
m_pages.append(startupSettingsPage);
m_pages.append(viewSettingsPage);
......@@ -99,6 +115,11 @@ DolphinSettingsDialog::DolphinSettingsDialog(const QUrl& url, QWidget* parent) :
if (trashSettingsPage) {
m_pages.append(trashSettingsPage);
}
#ifdef HAVE_KUSERFEEDBACK
if (feedbackSettingsPage) {
m_pages.append(feedbackSettingsPage);
}
#endif
const KConfigGroup dialogConfig(KSharedConfig::openConfig(QStringLiteral("dolphinrc")), "SettingsDialog");
KWindowConfig::restoreWindowSize(windowHandle(), dialogConfig);
......
/*
* SPDX-FileCopyrightText: 2020 Elvis Angelaccio <elvis.angelaccio@kde.org
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "userfeedbacksettingspage.h"
#include "userfeedback/dolphinfeedbackprovider.h"
#include <KUserFeedback/FeedbackConfigWidget>
#include <KUserFeedback/Provider>
#include <QVBoxLayout>
UserFeedbackSettingsPage::UserFeedbackSettingsPage(QWidget* parent) :
SettingsPageBase(parent)
{
auto layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
m_feedbackWidget = new KUserFeedback::FeedbackConfigWidget(this);
m_feedbackWidget->setFeedbackProvider(DolphinFeedbackProvider::instance());
layout->addWidget(m_feedbackWidget);
connect(m_feedbackWidget, &KUserFeedback::FeedbackConfigWidget::configurationChanged, this, &UserFeedbackSettingsPage::changed);
}
UserFeedbackSettingsPage::~UserFeedbackSettingsPage()
{
}
void UserFeedbackSettingsPage::applySettings()
{
auto feedbackProvider = DolphinFeedbackProvider::instance();
feedbackProvider->setTelemetryMode(m_feedbackWidget->telemetryMode());
feedbackProvider->setSurveyInterval(m_feedbackWidget->surveyInterval());
}
void UserFeedbackSettingsPage::restoreDefaults()
{
auto feedbackProvider = DolphinFeedbackProvider::instance();
feedbackProvider->setTelemetryMode(KUserFeedback::Provider::NoTelemetry);
feedbackProvider->setSurveyInterval(-1);
}
/*
* SPDX-FileCopyrightText: 2020 Elvis Angelaccio <elvis.angelaccio@kde.org
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef USERFEEDBACKSETTINGSPAGE_H
#define USERFEEDBACKSETTINGSPAGE_H
#include "settings/settingspagebase.h"
namespace KUserFeedback {
class FeedbackConfigWidget;
}
/**
* @brief Page for the 'User Feedback' settings of the Dolphin settings dialog.
*/
class UserFeedbackSettingsPage : public SettingsPageBase
{
Q_OBJECT
public:
explicit UserFeedbackSettingsPage(QWidget* parent);
~UserFeedbackSettingsPage() override;
/** @see SettingsPageBase::applySettings() */
void applySettings() override;
/** @see SettingsPageBase::restoreDefaults() */
void restoreDefaults() override;
private:
KUserFeedback::FeedbackConfigWidget *m_feedbackWidget = nullptr;
};
#endif // USERFEEDBACKSETTINGSPAGE_H
/*
* SPDX-FileCopyrightText: 2020 Elvis Angelaccio <elvis.angelaccio@kde.org
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "dolphinfeedbackprovider.h"
#include "placesdatasource.h"
#include "settingsdatasource.h"
#include <KUserFeedback/ApplicationVersionSource>
#include <KUserFeedback/LocaleInfoSource>
#include <KUserFeedback/PlatformInfoSource>
#include <KUserFeedback/QtVersionSource>
#include <KUserFeedback/ScreenInfoSource>
#include <KUserFeedback/StartCountSource>
#include <KUserFeedback/UsageTimeSource>
DolphinFeedbackProvider *DolphinFeedbackProvider::instance()
{
static DolphinFeedbackProvider s_self;
return &s_self;
}
DolphinFeedbackProvider::DolphinFeedbackProvider()
: KUserFeedback::Provider()
{
setProductIdentifier(QStringLiteral("org.kde.dolphin"));
setFeedbackServer(QUrl(QStringLiteral("https://telemetry.kde.org")));
setSubmissionInterval(7);
addDataSource(new KUserFeedback::ApplicationVersionSource);
addDataSource(new KUserFeedback::LocaleInfoSource);
addDataSource(new KUserFeedback::PlatformInfoSource);
addDataSource(new KUserFeedback::QtVersionSource);
addDataSource(new KUserFeedback::ScreenInfoSource);
addDataSource(new KUserFeedback::StartCountSource);
addDataSource(new KUserFeedback::UsageTimeSource);
addDataSource(new PlacesDataSource);
addDataSource(new SettingsDataSource);
}
/*
* SPDX-FileCopyrightText: 2020 Elvis Angelaccio <elvis.angelaccio@kde.org
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef DOLPHINFEEDBACKPROVIDER_H
#define DOLPHINFEEDBACKPROVIDER_H
#include <KUserFeedback/Provider>
class DolphinFeedbackProvider : public KUserFeedback::Provider
{
Q_OBJECT
public:
static DolphinFeedbackProvider *instance();
DolphinFeedbackProvider(const DolphinFeedbackProvider&) = delete;
DolphinFeedbackProvider(DolphinFeedbackProvider&&) = delete;
DolphinFeedbackProvider& operator=(const DolphinFeedbackProvider&) = delete;
DolphinFeedbackProvider& operator=(DolphinFeedbackProvider&&) = delete;
private:
DolphinFeedbackProvider();
};
#endif // DOLPHINFEEDBACKPROVIDER_H
/*
* SPDX-FileCopyrightText: 2020 Elvis Angelaccio <elvis.angelaccio@kde.org
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "placesdatasource.h"
#include <KLocalizedString>
#include <KMountPoint>
#include <KUserFeedback/Provider>
#include <Solid/Device>
#include <Solid/NetworkShare>
#include <Solid/StorageAccess>
#include <QVariant>
PlacesDataSource::PlacesDataSource()
: KUserFeedback::AbstractDataSource(QStringLiteral("places"), KUserFeedback::Provider::DetailedSystemInformation)
{}
QString PlacesDataSource::name() const
{
return i18nc("name of kuserfeedback data source provided by dolphin", "Places");
}
QString PlacesDataSource::description() const
{
// TODO: add count of remote places grouped by protocol type.
return i18nc("description of kuserfeedback data source provided by dolphin", "Count of available Network Shares");
}
QVariant PlacesDataSource::data()
{
QVariantMap map;
bool hasSSHFS = false;
bool hasSambaShare = false;
bool hasNfsShare = false;
const auto devices = Solid::Device::listFromType(Solid::DeviceInterface::NetworkShare);
for (const auto &device : devices) {
if (!hasSSHFS && device.vendor() == QLatin1String("fuse.sshfs")) {
// Ignore kdeconnect SSHFS mounts, we already know that people have those.
auto storageAccess = device.as<Solid::StorageAccess>();
if (storageAccess) {
auto mountPoint = KMountPoint::currentMountPoints().findByPath(storageAccess->filePath());
if (!mountPoint->mountedFrom().startsWith(QLatin1String("kdeconnect@"))) {
hasSSHFS = true;
continue;
}
}
}
if (!device.is<Solid::NetworkShare>()) {
continue;
}
switch (device.as<Solid::NetworkShare>()->type()) {
case Solid::NetworkShare::Cifs:
hasSambaShare = true;
continue;
case Solid::NetworkShare::Nfs:
hasNfsShare = true;
continue;
default:
continue;
}
}
map.insert(QStringLiteral("hasSSHFSMount"), hasSSHFS);
map.insert(QStringLiteral("hasSambaShare"), hasSambaShare);
map.insert(QStringLiteral("hasNfsShare"), hasNfsShare);
return map;
}
/*
* SPDX-FileCopyrightText: 2020 Elvis Angelaccio <elvis.angelaccio@kde.org
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef PLACESDATASOURCE_H
#define PLACESDATASOURCE_H
#include <KUserFeedback/AbstractDataSource>
class DolphinMainWindow;
class PlacesDataSource : public KUserFeedback::AbstractDataSource
{
public:
PlacesDataSource();
QString name() const override;
QString description() const override;
QVariant data() override;
};
#endif // PLACESDATASOURCE_H
/*
* SPDX-FileCopyrightText: 2020 Elvis Angelaccio <elvis.angelaccio@kde.org
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "settingsdatasource.h"
#include "dolphinmainwindow.h"
#include "dolphin_generalsettings.h"
#include <KLocalizedString>
#include <KUserFeedback/Provider>
#include <QApplication>
#include <QVariant>
SettingsDataSource::SettingsDataSource()
: KUserFeedback::AbstractDataSource(QStringLiteral("settings"), KUserFeedback::Provider::DetailedSystemInformation)
{}
QString SettingsDataSource::name() const
{
return i18nc("name of kuserfeedback data source provided by dolphin", "Settings");
}
QString SettingsDataSource::description() const
{
return i18nc("description of kuserfeedback data source provided by dolphin", "A subset of Dolphin settings.");
}
QVariant SettingsDataSource::data()
{
if (!m_mainWindow) {
// This assumes there is only one DolphinMainWindow per process.
const auto topLevelWidgets = QApplication::topLevelWidgets();
for (const auto widget : topLevelWidgets) {
if (qobject_cast<DolphinMainWindow *>(widget)) {
m_mainWindow = static_cast<DolphinMainWindow *>(widget);
break;
}
}
}
QVariantMap map;
if (m_mainWindow) {
map.insert(QStringLiteral("informationPanelEnabled"), m_mainWindow->isInformationPanelEnabled());
map.insert(QStringLiteral("foldersPanelEnabled"), m_mainWindow->isFoldersPanelEnabled());
}
map.insert(QStringLiteral("tooltipsEnabled"), GeneralSettings::showToolTips());
map.insert(QStringLiteral("browseArchivesEnable"), GeneralSettings::browseThroughArchives());
return map;
}
/*
* SPDX-FileCopyrightText: 2020 Elvis Angelaccio <elvis.angelaccio@kde.org
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef SETTINGSDATASOURCE_H
#define SETTINGSDATASOURCE_H
#include <KUserFeedback/AbstractDataSource>
class DolphinMainWindow;
class SettingsDataSource : public KUserFeedback::AbstractDataSource
{
public:
SettingsDataSource();
QString name() const override;
QString description() const override;
QVariant data() override;
private:
DolphinMainWindow *m_mainWindow = nullptr;
};
#endif // SETTINGSDATASOURCE_H
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