diff --git a/CMakeLists.txt b/CMakeLists.txt index c1b1a7b846..49842bd4c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c74855df62..bff52cf0f1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/config-kuserfeedback.h.cmake b/src/config-kuserfeedback.h.cmake new file mode 100644 index 0000000000..1e79cc74bb --- /dev/null +++ b/src/config-kuserfeedback.h.cmake @@ -0,0 +1 @@ +#cmakedefine HAVE_KUSERFEEDBACK diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index e755e72817..97ced73b49 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -245,6 +245,16 @@ void DolphinMainWindow::openFiles(const QList& 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); diff --git a/src/dolphinmainwindow.h b/src/dolphinmainwindow.h index faf428c033..a56215fa7d 100644 --- a/src/dolphinmainwindow.h +++ b/src/dolphinmainwindow.h @@ -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, diff --git a/src/main.cpp b/src/main.cpp index d557f2ea03..ef2905d776 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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 #include @@ -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; } diff --git a/src/settings/dolphinsettingsdialog.cpp b/src/settings/dolphinsettingsdialog.cpp index 8e129e2419..9d8fb032a7 100644 --- a/src/settings/dolphinsettingsdialog.cpp +++ b/src/settings/dolphinsettingsdialog.cpp @@ -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 #include @@ -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); diff --git a/src/settings/userfeedback/userfeedbacksettingspage.cpp b/src/settings/userfeedback/userfeedbacksettingspage.cpp new file mode 100644 index 0000000000..479c462265 --- /dev/null +++ b/src/settings/userfeedback/userfeedbacksettingspage.cpp @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: 2020 Elvis Angelaccio +#include + +#include + +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); +} + + diff --git a/src/settings/userfeedback/userfeedbacksettingspage.h b/src/settings/userfeedback/userfeedbacksettingspage.h new file mode 100644 index 0000000000..d9b6086152 --- /dev/null +++ b/src/settings/userfeedback/userfeedbacksettingspage.h @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2020 Elvis Angelaccio +#include +#include +#include +#include +#include +#include + +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); +} diff --git a/src/userfeedback/dolphinfeedbackprovider.h b/src/userfeedback/dolphinfeedbackprovider.h new file mode 100644 index 0000000000..f6575d49fd --- /dev/null +++ b/src/userfeedback/dolphinfeedbackprovider.h @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2020 Elvis Angelaccio + +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 diff --git a/src/userfeedback/placesdatasource.cpp b/src/userfeedback/placesdatasource.cpp new file mode 100644 index 0000000000..6db89636d0 --- /dev/null +++ b/src/userfeedback/placesdatasource.cpp @@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: 2020 Elvis Angelaccio +#include +#include +#include +#include +#include + +#include + +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(); + if (storageAccess) { + auto mountPoint = KMountPoint::currentMountPoints().findByPath(storageAccess->filePath()); + if (!mountPoint->mountedFrom().startsWith(QLatin1String("kdeconnect@"))) { + hasSSHFS = true; + continue; + } + } + } + + if (!device.is()) { + continue; + } + + switch (device.as()->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; +} diff --git a/src/userfeedback/placesdatasource.h b/src/userfeedback/placesdatasource.h new file mode 100644 index 0000000000..f25f1067ca --- /dev/null +++ b/src/userfeedback/placesdatasource.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2020 Elvis Angelaccio + +class DolphinMainWindow; + +class PlacesDataSource : public KUserFeedback::AbstractDataSource +{ +public: + PlacesDataSource(); + + QString name() const override; + QString description() const override; + QVariant data() override; + +}; + +#endif // PLACESDATASOURCE_H diff --git a/src/userfeedback/settingsdatasource.cpp b/src/userfeedback/settingsdatasource.cpp new file mode 100644 index 0000000000..03a25ff750 --- /dev/null +++ b/src/userfeedback/settingsdatasource.cpp @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2020 Elvis Angelaccio +#include + +#include +#include + +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(widget)) { + m_mainWindow = static_cast(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; +} diff --git a/src/userfeedback/settingsdatasource.h b/src/userfeedback/settingsdatasource.h new file mode 100644 index 0000000000..9804c78a79 --- /dev/null +++ b/src/userfeedback/settingsdatasource.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2020 Elvis Angelaccio + +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