diff options
Diffstat (limited to 'src')
41 files changed, 3472 insertions, 0 deletions
diff --git a/src/UsageStatistic.json.in b/src/UsageStatistic.json.in new file mode 100644 index 0000000..0ed40e6 --- /dev/null +++ b/src/UsageStatistic.json.in @@ -0,0 +1,11 @@ +{ + \"Name\" : \"UsageStatistic\", + \"Version\" : \"$$QTCREATOR_VERSION\", + \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\", + \"Vendor\" : \"The Qt Company Ltd\", + \"Copyright\" : \"(C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\", + \"License\" : \"GNU GPL v3\", + \"Description\" : \"This plugin is used to collect usage statistic. All statistics are anonymous. You can switch off the plugin any time you want.\", + \"Url\" : \"https://www.qt.io/\", + $$dependencyList +} diff --git a/src/common/scopedsettingsgroupsetter.cpp b/src/common/scopedsettingsgroupsetter.cpp new file mode 100644 index 0000000..472b6fd --- /dev/null +++ b/src/common/scopedsettingsgroupsetter.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "scopedsettingsgroupsetter.h" + +#include <QSettings> + +#include <KUserFeedback/AbstractDataSource> + +#include "usagestatisticconstants.h" + +namespace UsageStatistic { +namespace Internal { + +ScopedSettingsGroupSetter::ScopedSettingsGroupSetter(QSettings &settings, + const std::initializer_list<QString> &prefixes) + : m_settings(settings) + , m_prefixesCount(int(prefixes.size())) +{ + for (auto &&prefix : prefixes) { + m_settings.beginGroup(prefix); + } +} + +ScopedSettingsGroupSetter::~ScopedSettingsGroupSetter() +{ + while (m_prefixesCount-- > 0) { + m_settings.endGroup(); + } +} + +ScopedSettingsGroupSetter ScopedSettingsGroupSetter::forDataSource( + const KUserFeedback::AbstractDataSource &ds, QSettings &settings) +{ + return ScopedSettingsGroupSetter(settings, {Constants::DATA_SOURCES_SETTINGS_GROUP, ds.id()}); +} + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/common/scopedsettingsgroupsetter.h b/src/common/scopedsettingsgroupsetter.h new file mode 100644 index 0000000..adcaa61 --- /dev/null +++ b/src/common/scopedsettingsgroupsetter.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <memory> + +#include <QtCore/QtGlobal> + +QT_BEGIN_NAMESPACE +class QSettings; +QT_END_NAMESPACE + +namespace KUserFeedback { class AbstractDataSource; } + +namespace UsageStatistic { +namespace Internal { + +//! Used to set the specific set of group prefixes. Everything will be unset in the destructor +class ScopedSettingsGroupSetter +{ +public: + ScopedSettingsGroupSetter(QSettings &settings, const std::initializer_list<QString> &prefixes); + + ~ScopedSettingsGroupSetter(); + + static ScopedSettingsGroupSetter forDataSource(const KUserFeedback::AbstractDataSource &ds, + QSettings &settings); + +private: + QSettings &m_settings; + int m_prefixesCount; +}; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/common/utils.h b/src/common/utils.h new file mode 100644 index 0000000..6bf5fd4 --- /dev/null +++ b/src/common/utils.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <QtCore/QString> + +namespace UsageStatistic { +namespace Internal { +namespace Utils { + +//! Secret key for authentication defined during building +constexpr auto secret() { return USP_AUTH_KEY; } + +//! Base server URL defined during building +constexpr auto serverUrl() { return USP_SERVER_URL; } + +} // namespace Utils +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/buildcountsource.cpp b/src/datasources/buildcountsource.cpp new file mode 100644 index 0000000..1a42305 --- /dev/null +++ b/src/datasources/buildcountsource.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "buildcountsource.h" + +#include <QtCore/QSettings> + +#include "common/scopedsettingsgroupsetter.h" + +#include <projectexplorer/buildmanager.h> + +#include <KUserFeedback/Provider> + +namespace UsageStatistic { +namespace Internal { + +using namespace KUserFeedback; + +BuildCountSource::BuildCountSource() + : AbstractDataSource(QStringLiteral("buildsCount"), Provider::DetailedUsageStatistics) +{ + QObject::connect(ProjectExplorer::BuildManager::instance(), + &ProjectExplorer::BuildManager::buildQueueFinished, + [&](bool success){ ++(success ? m_succeededBuildsCount : m_failedBuildsCount); }); +} + +QString BuildCountSource::name() const +{ + return tr("Builds count"); +} + +QString BuildCountSource::description() const +{ + return tr("Count of succeeded and failed builds."); +} + +static QString succeededKey() { return QStringLiteral("succeeded"); } +static QString failedKey() { return QStringLiteral("failed"); } +static QString totalKey() { return QStringLiteral("total"); } + +QVariant BuildCountSource::data() +{ + return QVariantMap{{succeededKey(), m_succeededBuildsCount}, + {failedKey(), m_failedBuildsCount}, + {totalKey(), m_succeededBuildsCount + m_failedBuildsCount}}; +} + +void BuildCountSource::loadImpl(QSettings *settings) +{ + auto setter = ScopedSettingsGroupSetter::forDataSource(*this, *settings); + m_succeededBuildsCount = qvariant_cast<quint64>(settings->value(succeededKey(), succeededCountDflt())); + m_failedBuildsCount = qvariant_cast<quint64>(settings->value(failedKey(), failedCountDflt())); +} + +void BuildCountSource::storeImpl(QSettings *settings) +{ + auto setter = ScopedSettingsGroupSetter::forDataSource(*this, *settings); + settings->setValue(succeededKey(), m_succeededBuildsCount); + settings->setValue(failedKey(), m_failedBuildsCount); +} + +void BuildCountSource::resetImpl(QSettings *settings) +{ + m_succeededBuildsCount = succeededCountDflt(); + m_failedBuildsCount = failedCountDflt(); + + storeImpl(settings); +} + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/buildcountsource.h b/src/datasources/buildcountsource.h new file mode 100644 index 0000000..0cee9c4 --- /dev/null +++ b/src/datasources/buildcountsource.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <QCoreApplication> + +#include <KUserFeedback/AbstractDataSource> + +namespace UsageStatistic { +namespace Internal { + +//! Tracks succeeded, failed, and total builds count +class BuildCountSource : public KUserFeedback::AbstractDataSource +{ + Q_DECLARE_TR_FUNCTIONS(BuildCountDataSource) + +public: + BuildCountSource(); + +public: // AbstractDataSource interface + QString name() const override; + QString description() const override; + + /*! The output data format is: + * { + * "succeeded": int, + * "failed" : int, + * "total" : int + * } + */ + QVariant data() override; + + void loadImpl(QSettings *settings) override; + void storeImpl(QSettings *settings) override; + void resetImpl(QSettings *settings) override; + +private: + static constexpr quint64 succeededCountDflt() { return 0; } + static constexpr quint64 failedCountDflt() { return 0; } + +private: + quint64 m_succeededBuildsCount = succeededCountDflt(); + quint64 m_failedBuildsCount = failedCountDflt(); +}; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/buildsystemsource.cpp b/src/datasources/buildsystemsource.cpp new file mode 100644 index 0000000..26433c0 --- /dev/null +++ b/src/datasources/buildsystemsource.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "buildsystemsource.h" + +#include <QtCore/QSettings> + +#include <projectexplorer/project.h> +#include <projectexplorer/session.h> + +#include <KUserFeedback/Provider> + +#include "common/scopedsettingsgroupsetter.h" + +namespace UsageStatistic { +namespace Internal { + +using namespace KUserFeedback; + +// Keep synchronized with BuildSystemSource::BuildSystem { +static const auto &buildSystemMarks() +{ + static const QString marks[] = {".qt4", ".cmake", ".qbs", ".autotools"}; + return marks; +} + +static const auto &buildSystemKeys() +{ + static const QString keys[] = {"qmake", "cmake", "qbs", "autotools", "other"}; + return keys; +} +// } + +static BuildSystemSource::BuildSystem extractBuildSystemType(const QString &name) +{ + auto begin = std::begin(buildSystemMarks()); + auto end = std::end(buildSystemMarks()); + + auto it = std::find_if(begin, end, [&](const QString &m){ return name.contains(m); }); + return it != end ? BuildSystemSource::BuildSystem(std::distance(begin, it)) + : BuildSystemSource::Other; +} + +BuildSystemSource::BuildSystemSource() + : AbstractDataSource(QStringLiteral("buildSystem"), Provider::DetailedUsageStatistics) +{ + connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::projectAdded, + this, &BuildSystemSource::updateProjects); + + connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::sessionLoaded, + this, &BuildSystemSource::updateProjects); +} + +BuildSystemSource::~BuildSystemSource() = default; + +QString BuildSystemSource::name() const +{ + return tr("Build system type"); +} + +QString BuildSystemSource::description() const +{ + return tr("Count of each used build systems"); +} + +QVariant BuildSystemSource::data() +{ + QVariantMap result; + for (int i = QMake; i < Count; ++i) { + result[buildSystemKeys()[i]] = m_projectsByBuildSystem[size_t(i)].count(); + } + + return result; +} + +void BuildSystemSource::loadImpl(QSettings *settings) +{ + auto setter = ScopedSettingsGroupSetter::forDataSource(*this, *settings); + for (int i = QMake; i < Count; ++i) { + m_projectsByBuildSystem[size_t(i)] = + settings->value(buildSystemKeys()[i]).toStringList().toSet(); + } +} + +void BuildSystemSource::storeImpl(QSettings *settings) +{ + auto setter = ScopedSettingsGroupSetter::forDataSource(*this, *settings); + for (int i = QMake; i < Count; ++i) { + settings->setValue( + buildSystemKeys()[i], QStringList(m_projectsByBuildSystem[size_t(i)].toList())); + } +} + +void BuildSystemSource::resetImpl(QSettings *settings) +{ + ProjectsByBuildSystem().swap(m_projectsByBuildSystem); + storeImpl(settings); +} + +void BuildSystemSource::updateProjects() +{ + for (auto project : ProjectExplorer::SessionManager::projects()) { + if (project) { + auto projectName = QString::fromUtf8(project->id().name()).toLower(); + auto projectPath = project->projectFilePath().toString(); + m_projectsByBuildSystem[extractBuildSystemType(projectName)] << projectPath; + } + } +} + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/buildsystemsource.h b/src/datasources/buildsystemsource.h new file mode 100644 index 0000000..d390c37 --- /dev/null +++ b/src/datasources/buildsystemsource.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <array> + +#include <QCoreApplication> +#include <QSet> + +#include <KUserFeedback/AbstractDataSource> + +namespace UsageStatistic { +namespace Internal { + +//! Tracks which build system is used for projects +class BuildSystemSource : public QObject, public KUserFeedback::AbstractDataSource +{ + Q_OBJECT + +public: // Types + enum BuildSystem { QMake, CMake, Qbs, Autotools, Other, Count }; + +public: + BuildSystemSource(); + ~BuildSystemSource() override; + +public: // AbstractDataSource interface + QString name() const override; + QString description() const override; + + /*! The output data format is (the value is projects count): + * { + * "autotools": int, + * "cmake" : int, + * "other" : int, + * "qbs" : int, + * "qmake" : int + * } + */ + QVariant data() override; + + void loadImpl(QSettings *settings) override; + void storeImpl(QSettings *settings) override; + void resetImpl(QSettings *settings) override; + +private: + void updateProjects(); + +private: + // Index is build system type + // Element is a set of full project paths. Full project path is used + // as a permanent unique identifier. This identifier is only for + // storing locally on user machine and should never be sent! + using ProjectsByBuildSystem = std::array<QSet<QString>, Count>; + ProjectsByBuildSystem m_projectsByBuildSystem; +}; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/examplesdatasource.cpp b/src/datasources/examplesdatasource.cpp new file mode 100644 index 0000000..8dc9b2d --- /dev/null +++ b/src/datasources/examplesdatasource.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "examplesdatasource.h" + +#include <QtCore/QSettings> +#include <QtCore/QRegularExpression> + +#include <projectexplorer/project.h> +#include <projectexplorer/session.h> + +#include <common/scopedsettingsgroupsetter.h> + +namespace UsageStatistic { +namespace Internal { + +using namespace KUserFeedback; + +ExamplesDataSource::ExamplesDataSource() + : AbstractDataSource(QStringLiteral("examplesData"), Provider::DetailedUsageStatistics) +{ + connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::startupProjectChanged, + this, &ExamplesDataSource::updateOpenedExamples); + + connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::projectAdded, + this, &ExamplesDataSource::updateOpenedExamples); + + connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::sessionLoaded, + this, &ExamplesDataSource::updateOpenedExamples); +} + +ExamplesDataSource::~ExamplesDataSource() = default; + +QString ExamplesDataSource::name() const +{ + return tr("Examples"); +} + +QString ExamplesDataSource::description() const +{ + return tr("The list of examples openned by the user. " + "Only example paths are collected and sent, for example: " + "widgets/mainwindows/application/application.pro"); +} + +static QString examplesKey() { return QStringLiteral("examples"); } + +QVariant ExamplesDataSource::data() +{ + return QVariantMap{{examplesKey(), QVariant(m_examplePaths.toList())}}; +} + +void ExamplesDataSource::loadImpl(QSettings *settings) +{ + auto setter = ScopedSettingsGroupSetter::forDataSource(*this, *settings); + m_examplePaths = settings->value(examplesKey()).toStringList().toSet(); +} + +void ExamplesDataSource::storeImpl(QSettings *settings) +{ + auto setter = ScopedSettingsGroupSetter::forDataSource(*this, *settings); + settings->setValue(examplesKey(), QStringList(m_examplePaths.toList())); +} + +void ExamplesDataSource::resetImpl(QSettings *settings) +{ + m_examplePaths.clear(); + storeImpl(settings); +} + +static QString examplePathGroupName() { return QStringLiteral("examplePathGroup"); } + +static QString examplePattern() +{ + return QStringLiteral("/Examples/Qt-(\\d+\\.*){1,3}/(?<%1>.*)$"); +} + +void ExamplesDataSource::updateOpenedExamples() +{ + QRegularExpression re(examplePattern().arg(examplePathGroupName())); + for (auto project : ProjectExplorer::SessionManager::projects()) { + if (project) { + auto projectPath = QDir::fromNativeSeparators(project->projectFilePath().toString()); + const auto match = re.match(projectPath); + if (match.hasMatch()) { + m_examplePaths << match.captured(examplePathGroupName()); + } + } + } +} + +} // namespace Internal +} // namespace UsageStatistic + + diff --git a/src/datasources/examplesdatasource.h b/src/datasources/examplesdatasource.h new file mode 100644 index 0000000..19b5779 --- /dev/null +++ b/src/datasources/examplesdatasource.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <QtCore/QSet> + +#include <KUserFeedback/AbstractDataSource> + +namespace UsageStatistic { +namespace Internal { + +//! Tracks which examples were opened by the user +class ExamplesDataSource : public QObject, public KUserFeedback::AbstractDataSource +{ + Q_OBJECT + +public: + ExamplesDataSource(); + ~ExamplesDataSource() override; + +public: // AbstractDataSource interface + QString name() const override; + QString description() const override; + + /*! The output data format is: + * { + * "examples": [] + * } + * + * The array contains paths like "widgets/mainwindows/application/application.pro". + * Full paths aren't collected. + */ + QVariant data() override; + + void loadImpl(QSettings *settings) override; + void storeImpl(QSettings *settings) override; + void resetImpl(QSettings *settings) override; + +private: // Methods + void updateOpenedExamples(); + +private: // Data + QSet<QString> m_examplePaths; +}; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/kitsource.cpp b/src/datasources/kitsource.cpp new file mode 100644 index 0000000..38d0ccc --- /dev/null +++ b/src/datasources/kitsource.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "kitsource.h" + +#include <QtCore/QSettings> + +#include <projectexplorer/kitinformation.h> +#include <projectexplorer/kitmanager.h> +#include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/gcctoolchain.h> +#include <qtsupport/qtkitinformation.h> +#include <debugger/debuggerkitinformation.h> +#include <debugger/debuggeritem.h> + +#include "common/scopedsettingsgroupsetter.h" + +namespace UsageStatistic { +namespace Internal { + +using namespace KUserFeedback; +using namespace ProjectExplorer; + +KitSource::KitSource() + : AbstractDataSource(QStringLiteral("kits"), Provider::DetailedUsageStatistics) +{ +} + +KitSource::~KitSource() = default; + +QString KitSource::name() const +{ + return tr("Kits"); +} + +QString KitSource::description() const +{ + return tr("Kits usage statistic: compilers, debuggers, target architecture etc."); +} + +static QString kitsInfoKey() { return QStringLiteral("kitsInfo"); } + +static QString extractToolChainVersion(const ToolChain &toolChain) +{ + try { + return dynamic_cast<const GccToolChain &>(toolChain).version(); + } catch (...) { + return {}; + } +} + +class KitInfo +{ +public: + KitInfo &withQtVersionInfo() + { + static const QString qtKey = QStringLiteral("qt"); + static const QString qtQmlDebuggingSupportKey = QStringLiteral("qmlDebugging"); + static const QString qtQmlCompilerSupportKey = QStringLiteral("qmlCompiler"); + static const QString qtAbisKey = QStringLiteral("abis"); + + if (auto qtVersion = QtSupport::QtKitAspect::qtVersion(&m_kit)) { + QVariantMap qtData; + qtData.insert(versionKey(), qtVersion->qtVersionString()); + qtData.insert(qtQmlDebuggingSupportKey, qtVersion->isQmlDebuggingSupported()); + qtData.insert(qtQmlCompilerSupportKey, qtVersion->isQtQuickCompilerSupported()); + qtData.insert(qtAbisKey, abisToVarinatList(qtVersion->qtAbis())); + + m_map.insert(qtKey, qtData); + } + + return *this; + } + + KitInfo &withCompilerInfo() + { + static const QString compilerKey = QStringLiteral("compiler"); + + if (auto toolChain = ToolChainKitAspect::toolChain(&m_kit, Constants::CXX_LANGUAGE_ID)) { + m_map.insert(compilerKey, + QVariantMap{{nameKey(), toolChain->typeDisplayName()}, + {versionKey(), extractToolChainVersion(*toolChain)}}); + } + + return *this; + } + + KitInfo &withDebuggerInfo() + { + static const QString debuggerKey = QStringLiteral("debugger"); + + if (auto debuggerInfo = Debugger::DebuggerKitAspect::debugger(&m_kit)) { + m_map.insert(debuggerKey, + QVariantMap{{nameKey(), debuggerInfo->engineTypeName()}, + {versionKey(), debuggerInfo->version()}}); + } + + return *this; + } + + QVariantMap extract() const { return m_map; } + + static KitInfo forKit(Kit &kit) { return KitInfo(kit); } + +private: // Methods + KitInfo(Kit &kit) : m_kit(kit) { addKitInfo(); } + + void addKitInfo() + { + static QString defaultKitKey = QStringLiteral("default"); + + m_map.insert(defaultKitKey, &m_kit == KitManager::defaultKit()); + } + + static QVariantMap abiToVariantMap(const Abi &abi) + { + static const QString archKey = QStringLiteral("arch"); + static const QString osKey = QStringLiteral("os"); + static const QString osFlavorKey = QStringLiteral("osFlavor"); + static const QString binaryFormatKey = QStringLiteral("binaryFormat"); + static const QString wordWidthKey = QStringLiteral("wordWidth"); + + return QVariantMap{{archKey , Abi::toString(abi.architecture())}, + {osKey , Abi::toString(abi.os()) }, + {osFlavorKey , Abi::toString(abi.osFlavor()) }, + {binaryFormatKey, Abi::toString(abi.binaryFormat())}, + {wordWidthKey , Abi::toString(abi.wordWidth()) }}; + } + + template <class Container> + QVariantList abisToVarinatList(const Container &abis) + { + QVariantList result; + for (auto &&abi : abis) { + result << abiToVariantMap(abi); + } + + return result; + } + + static QString versionKey() { return QStringLiteral("version"); } + static QString nameKey() { return QStringLiteral("name"); } + +private: // Data + Kit &m_kit; + QVariantMap m_map; +}; + +static QVariantList kitsInfo() +{ + QVariantList kitsInfoList; + for (auto &&kit : KitManager::instance()->kits()) { + if (kit && kit->isValid()) { + kitsInfoList << KitInfo::forKit(*kit) + .withCompilerInfo() + .withDebuggerInfo() + .withQtVersionInfo() + .extract(); + } + } + + return kitsInfoList; +} + +QVariant KitSource::data() +{ + return QVariantMap{{kitsInfoKey(), kitsInfo()}}; +} + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/kitsource.h b/src/datasources/kitsource.h new file mode 100644 index 0000000..4256c01 --- /dev/null +++ b/src/datasources/kitsource.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <QVariantMap> + +#include <KUserFeedback/AbstractDataSource> + +namespace UsageStatistic { +namespace Internal { + +//! Tracks which toolkits are used +class KitSource : public QObject, public KUserFeedback::AbstractDataSource +{ + Q_OBJECT + +public: + KitSource(); + ~KitSource() override; + +public: // AbstractDataSource interface + QString name() const override; + QString description() const override; + + /*! The output data format is: + * { + * "kitsInfo": [ + * { + * "compiler": { + * "name" : string, + * "version": int + * }, + * "debugger": { + * "name" : string, + * "version": string, + * }, + * "default": bool, + * "qt": { + * "abis": [ + * { + * "arch" : string, + * "binaryFormat": string, + * "os" : string, + * "osFlavor" : string, + * "wordWidth" : string + * } + * ], + * "qmlCompiler" : bool, + * "qmlDebugging": bool, + * "version" : string + * } + * }, + * ] + * } + * + * The version format if "\d+.\d+.\d+". + */ + QVariant data() override; +}; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/modeusagetimesource.cpp b/src/datasources/modeusagetimesource.cpp new file mode 100644 index 0000000..445e419 --- /dev/null +++ b/src/datasources/modeusagetimesource.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "modeusagetimesource.h" + +#include <QtCore/QSettings> + +#include <coreplugin/editormanager/editormanager.h> +#include <coreplugin/modemanager.h> + +#include <KUserFeedback/Provider> + +#include "common/scopedsettingsgroupsetter.h" + +namespace UsageStatistic { +namespace Internal { + +using namespace KUserFeedback; + +ModeUsageTimeSource::ModeUsageTimeSource() + : AbstractDataSource(QStringLiteral("modeUsageTime"), Provider::DetailedUsageStatistics) +{ + connect(Core::ModeManager::instance(), &Core::ModeManager::currentModeChanged, + this, &ModeUsageTimeSource::onCurrentModeIdChanged); + onCurrentModeIdChanged(Core::ModeManager::currentModeId()); +} + +ModeUsageTimeSource::~ModeUsageTimeSource() = default; + +QString ModeUsageTimeSource::name() const +{ + return tr("Modes usage time"); +} + +QString ModeUsageTimeSource::description() const +{ + return tr("How much time a user spent working in each mode (edit, debug, design, etc.)"); +} + +// Keep synced with ModeUsageTimeSource::Mode { +static const auto &modeMarks() +{ + static const QString marks[] = {"welcome", "edit", "design", "debug", "project", "help", "other"}; + return marks; +} +// } + +static ModeUsageTimeSource::Mode modeFromString(const QString &modeString) +{ + auto begin = std::begin(modeMarks()); + auto end = std::end(modeMarks()); + + auto it = std::find_if(begin, end, [&](const QString &mark) { return modeString.contains(mark); }); + + return it != end ? ModeUsageTimeSource::Mode(std::distance(begin, it)) + : ModeUsageTimeSource::Other; +} + +QVariant ModeUsageTimeSource::data() +{ + QVariantMap result; + + for (std::size_t i = Welcome; i < ModesCount; ++i) { + result[modeMarks()[i]] = m_timeByModes[i]; + } + + return result; +} + +void ModeUsageTimeSource::loadImpl(QSettings *settings) +{ + auto setter = ScopedSettingsGroupSetter::forDataSource(*this, *settings); + for (std::size_t i = Welcome; i < ModesCount; ++i) { + m_timeByModes[i] = qvariant_cast<qint64>(settings->value(modeMarks()[i], timeDflt())); + } +} + +void ModeUsageTimeSource::storeImpl(QSettings *settings) +{ + storeCurrentTimerValue(); + + auto setter = ScopedSettingsGroupSetter::forDataSource(*this, *settings); + for (std::size_t i = Welcome; i < ModesCount; ++i) { + settings->setValue(modeMarks()[i], m_timeByModes[i]); + } +} + +void ModeUsageTimeSource::resetImpl(QSettings *settings) +{ + std::fill(std::begin(m_timeByModes), std::end(m_timeByModes), timeDflt()); + storeImpl(settings); +} + +void ModeUsageTimeSource::setCurrentMode(ModeUsageTimeSource::Mode mode) +{ + m_currentMode = mode; +} + +ModeUsageTimeSource::Mode ModeUsageTimeSource::currentMode() const +{ + return m_currentMode; +} + +void ModeUsageTimeSource::onCurrentModeIdChanged(const Core::Id &modeId) +{ + auto mode = modeFromString(QString::fromUtf8(modeId.name().toLower().simplified())); + + if (m_currentMode == mode) { + return; + } + + if (m_currentTimer.isValid() && m_currentMode < ModesCount) { + m_timeByModes[m_currentMode] += m_currentTimer.elapsed(); + m_currentTimer.invalidate(); + } + + m_currentMode = mode; + + if (m_currentMode != ModesCount) { + m_currentTimer.start(); + } +} + +void ModeUsageTimeSource::storeCurrentTimerValue() +{ + if (m_currentTimer.isValid() && m_currentMode < ModesCount) { + m_timeByModes[m_currentMode] += m_currentTimer.restart(); + } +} + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/modeusagetimesource.h b/src/datasources/modeusagetimesource.h new file mode 100644 index 0000000..f1fbde1 --- /dev/null +++ b/src/datasources/modeusagetimesource.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <array> + +#include <QtCore/QElapsedTimer> + +#include <coreplugin/id.h> + +#include <KUserFeedback/AbstractDataSource> + +namespace UsageStatistic { +namespace Internal { + +//! Tracks which modes were used and for how long +class ModeUsageTimeSource : public QObject, public KUserFeedback::AbstractDataSource +{ + Q_OBJECT + +public: // Types + enum Mode {Welcome, Edit, Design, Debug, Projects, Help, Other, ModesCount}; + +public: + ModeUsageTimeSource(); + ~ModeUsageTimeSource() override; + +public: // AbstractDataSource interface + QString name() const override; + QString description() const override; + + /*! The output data format is: + * { + * "debug" : int, + * "design" : int, + * "edit" : int, + * "help" : int, + * "other" : int, + * "project": int, + * "welcome": int + * } + * + * The value is duration in milliseconds. + */ + QVariant data() override; + + void loadImpl(QSettings *settings) override; + void storeImpl(QSettings *settings) override; + void resetImpl(QSettings *settings) override; + +private: // Data + Mode m_currentMode = ModesCount; + QElapsedTimer m_currentTimer; + std::array<qint64, ModesCount> m_timeByModes{}; + +private: // Methods + void setCurrentMode(Mode mode); + Mode currentMode() const; + + void onCurrentModeIdChanged(const Core::Id &modeId); + + void storeCurrentTimerValue(); + + static constexpr qint64 timeDflt() { return 0; } +}; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/qmldesignerusagetimesource.cpp b/src/datasources/qmldesignerusagetimesource.cpp new file mode 100644 index 0000000..6bb4a32 --- /dev/null +++ b/src/datasources/qmldesignerusagetimesource.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "qmldesignerusagetimesource.h" + +#include <QtCore/QFileInfo> + +#include <coreplugin/editormanager/editormanager.h> +#include <coreplugin/editormanager/ieditor.h> +#include <coreplugin/modemanager.h> +#include <coreplugin/imode.h> + +namespace UsageStatistic { +namespace Internal { + +static QString currentModeName() +{ + if (auto modeManager = Core::ModeManager::instance()) { + if (auto mode = modeManager->currentMode()) { + return mode->displayName().toLower(); + } + } + + return {}; +} + +QmlDesignerUsageTimeSource::QmlDesignerUsageTimeSource() + : TimeUsageSourceBase(QStringLiteral("qmlDesignerUsageTime")) +{ + connect(Core::ModeManager::instance(), &Core::ModeManager::currentModeChanged, + this, [this](Core::Id modeId){ + updateTrackingState(QString::fromUtf8(modeId.name().toLower())); }); + + connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged, + this, [this](){ updateTrackingState(currentModeName()); }); +} + +QmlDesignerUsageTimeSource::~QmlDesignerUsageTimeSource() = default; + +QString QmlDesignerUsageTimeSource::name() const +{ + return tr("QmlDesigner usage time"); +} + +QString QmlDesignerUsageTimeSource::description() const +{ + return tr("How long a user spent editing QML files in designer mode"); +} + +static bool isDesignMode(const QString &modeName) +{ + static const QString designModeName = QStringLiteral("design"); + return modeName == designModeName; +} + +static bool editingQmlFile() +{ + static const QSet<QString> validExtentions = {"qml", "qml.ui"}; + static const QString validMimeType = "qml"; + + if (auto document = Core::EditorManager::currentDocument()) { + QString mimeType = document->mimeType().toLower(); + QString extension = document->filePath().toFileInfo().completeSuffix().toLower(); + + return validExtentions.contains(extension) || mimeType.contains(validMimeType); + } + + return false; +} + +void QmlDesignerUsageTimeSource::updateTrackingState(const QString &modeName) +{ + if (isDesignMode(modeName) && editingQmlFile() && !isTimeTrackingActive()) { + Q_EMIT start(); + } else { + Q_EMIT stop(); + } +} + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/qmldesignerusagetimesource.h b/src/datasources/qmldesignerusagetimesource.h new file mode 100644 index 0000000..3cadf57 --- /dev/null +++ b/src/datasources/qmldesignerusagetimesource.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include "timeusagesourcebase.h" + +namespace UsageStatistic { +namespace Internal { + +//! Tracks time spent using QML Designer +class QmlDesignerUsageTimeSource : public TimeUsageSourceBase +{ +public: + QmlDesignerUsageTimeSource(); + ~QmlDesignerUsageTimeSource() override; + +public: // AbstractDataSource interface + QString name() const override; + QString description() const override; + +private: // Methods + void updateTrackingState(const QString &modeName); +}; + +} // namespace Internal +} // namespace UsageStatistic + diff --git a/src/datasources/qtclicensesource.cpp b/src/datasources/qtclicensesource.cpp new file mode 100644 index 0000000..bee2c8c --- /dev/null +++ b/src/datasources/qtclicensesource.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "qtclicensesource.h" + +#include <coreplugin/icore.h> +#include <extensionsystem/iplugin.h> +#include <extensionsystem/pluginmanager.h> +#include <extensionsystem/pluginspec.h> + +#include <KUserFeedback/Provider> + +namespace UsageStatistic { +namespace Internal { + +using namespace KUserFeedback; + +QtcLicenseSource::QtcLicenseSource() + : AbstractDataSource(QStringLiteral("qtcLicense"), Provider::DetailedUsageStatistics) +{} + +QString QtcLicenseSource::description() const +{ + return tr("Qt Creator license type string: opensource, evaluation, commercial"); +} + +QString QtcLicenseSource::name() const +{ + return tr("Qt Creator license"); +} + +static const auto evaluationStr = QStringLiteral("evaluation"); +static const auto opensourceStr = QStringLiteral("opensource"); +static const auto commercialStr = QStringLiteral("commercial"); + +static bool isLicenseChecker(const ExtensionSystem::PluginSpec *spec) +{ + if (!spec) { + return false; + } + + static const auto pluginName = QStringLiteral("LicenseChecker"); + return spec->name().contains(pluginName); +} + +static bool hasEvaluationLicense(ExtensionSystem::IPlugin *plugin) +{ + if (!plugin) { + return false; + } + + bool isEvaluation = false; + + static const auto checkMethodName = "evaluationLicense"; + QMetaObject::invokeMethod(plugin, checkMethodName, Q_RETURN_ARG(bool, isEvaluation)); + + return isEvaluation; +} + +static QString licenseString() +{ + const auto plugins = ExtensionSystem::PluginManager::plugins(); + const auto it = std::find_if(plugins.begin(), plugins.end(), &isLicenseChecker); + if (it != plugins.end()) { + return hasEvaluationLicense((*it)->plugin()) ? evaluationStr: commercialStr; + } + + return opensourceStr; +} + +QVariant QtcLicenseSource::data() +{ + return QVariantMap{{"value", licenseString()}}; +} + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/qtclicensesource.h b/src/datasources/qtclicensesource.h new file mode 100644 index 0000000..80630d2 --- /dev/null +++ b/src/datasources/qtclicensesource.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <QCoreApplication> + +#include <KUserFeedback/AbstractDataSource> + +namespace UsageStatistic { +namespace Internal { + +//! Tracks whether commercial or open source version is used +class QtcLicenseSource : public KUserFeedback::AbstractDataSource +{ + Q_DECLARE_TR_FUNCTIONS(QtcLicenseSource) + +public: + QtcLicenseSource(); + +public: // AbstractDataSource interface + QString description() const override; + QString name() const override; + + /*! The output data format is: + * { + * "value": string + * } + */ + QVariant data() override; +}; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/timeusagesourcebase.cpp b/src/datasources/timeusagesourcebase.cpp new file mode 100644 index 0000000..ab4c1e1 --- /dev/null +++ b/src/datasources/timeusagesourcebase.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "timeusagesourcebase.h" + +#include <QtCore/QVariant> +#include <QtCore/QSettings> + +#include <KUserFeedback/Provider> + +#include <common/scopedsettingsgroupsetter.h> + +namespace UsageStatistic { +namespace Internal { + +using namespace KUserFeedback; + +TimeUsageSourceBase::TimeUsageSourceBase(const QString &id) + : AbstractDataSource(id, Provider::DetailedUsageStatistics) +{ + connect(this, &TimeUsageSourceBase::start, this, &TimeUsageSourceBase::onStarted); + connect(this, &TimeUsageSourceBase::stop, this, &TimeUsageSourceBase::onStopped); +} + +void TimeUsageSourceBase::onStarted() +{ + // Restart if required + if (m_timer.isValid()) { + onStopped(); + } + + ++m_startCount; + m_timer.start(); +} + +void TimeUsageSourceBase::onStopped() +{ + if (m_timer.isValid()) { + m_usageTime += m_timer.elapsed(); + } + + m_timer.invalidate(); +} + +bool TimeUsageSourceBase::isTimeTrackingActive() const +{ + return m_timer.isValid(); +} + +static QString usageTimeKey() { return QStringLiteral("usageTime"); } +static QString startCountKey() { return QStringLiteral("startCount"); } + +QVariant TimeUsageSourceBase::data() +{ + return QVariantMap{{usageTimeKey(), m_usageTime}, {startCountKey(), m_startCount}}; +} + +void TimeUsageSourceBase::loadImpl(QSettings *settings) +{ + auto setter = ScopedSettingsGroupSetter::forDataSource(*this, *settings); + m_usageTime = settings->value(usageTimeKey(), usageTimeDflt()).toLongLong(); + m_startCount = settings->value(startCountKey(), startCountDflt()).toLongLong(); +} + +void TimeUsageSourceBase::storeImpl(QSettings *settings) +{ + auto setter = ScopedSettingsGroupSetter::forDataSource(*this, *settings); + settings->setValue(usageTimeKey(), m_usageTime); + settings->setValue(startCountKey(), m_startCount); +} + +void TimeUsageSourceBase::resetImpl(QSettings *settings) +{ + m_usageTime = usageTimeDflt(); + m_startCount = startCountDflt(); + storeImpl(settings); +} + +TimeUsageSourceBase::~TimeUsageSourceBase() = default; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/datasources/timeusagesourcebase.h b/src/datasources/timeusagesourcebase.h new file mode 100644 index 0000000..e3d3730 --- /dev/null +++ b/src/datasources/timeusagesourcebase.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <QtCore/QObject> +#include <QtCore/QElapsedTimer> + +#include <KUserFeedback/AbstractDataSource> + +namespace UsageStatistic { +namespace Internal { + +//! Base class for all time trackers +class TimeUsageSourceBase : public QObject, public KUserFeedback::AbstractDataSource +{ + Q_OBJECT + +public: + ~TimeUsageSourceBase() override; + +public: // AbstractDataSource interface + /*! The output data format is: + * { + * "startCount": int, + * "usageTime" : int + * } + */ + QVariant data() override; + + void loadImpl(QSettings *settings) override; + void storeImpl(QSettings *settings) override; + void resetImpl(QSettings *settings) override; + +protected: + TimeUsageSourceBase(const QString &id); + + void onStarted(); + void onStopped(); + + bool isTimeTrackingActive() const; + +Q_SIGNALS: + void start(); + void stop(); + +private: + static constexpr qint64 usageTimeDflt() { return 0; } + static constexpr qint64 startCountDflt() { return 0; } + +private: + QElapsedTimer m_timer; + qint64 m_usageTime = usageTimeDflt(); + qint64 m_startCount = startCountDflt(); +}; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/images/settingscategory_usagestatistic.png b/src/images/settingscategory_usagestatistic.png Binary files differnew file mode 100644 index 0000000..e45c00b --- /dev/null +++ b/src/images/settingscategory_usagestatistic.png diff --git a/src/images/settingscategory_usagestatistic.svg b/src/images/settingscategory_usagestatistic.svg new file mode 100644 index 0000000..c4bd019 --- /dev/null +++ b/src/images/settingscategory_usagestatistic.svg @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="24" + height="24" + viewBox="0 0 6.35 6.35" + version="1.1" + id="svg2581" + inkscape:version="0.92.4 (5da689c313, 2019-01-14)" + sodipodi:docname="settingscategory_usagestatistic.svg"> + <defs + id="defs2575" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + units="px" + showguides="true" + inkscape:guide-bbox="true"> + <inkscape:grid + type="xygrid" + id="grid3287" + spacingx="0.13229167" + spacingy="0.13229167" + empspacing="2" + dotted="true" /> + <sodipodi:guide + position="0,5.2916667" + orientation="0,1" + id="guide6992" + inkscape:locked="false" + inkscape:label="" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="1.0583333,0" + orientation="1,0" + id="guide6994" + inkscape:locked="false" + inkscape:label="" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="0,1.0583333" + orientation="0,1" + id="guide6996" + inkscape:locked="false" + inkscape:label="" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="5.2916667,0" + orientation="1,0" + id="guide6998" + inkscape:locked="false" + inkscape:label="" + inkscape:color="rgb(0,0,255)" /> + </sodipodi:namedview> + <metadata + id="metadata2578"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-290.64998)"> + <g + transform="matrix(0.26458333,0,0,0.26458333,-310.09162,137.19165)" + id="settingscategory_usagestatistic" + style="display:inline"> + <rect + y="580" + x="1172" + height="24" + width="24" + id="use2493" + style="display:inline;fill:#ffffff;stroke-width:1.5" /> + <path + sodipodi:nodetypes="cc" + inkscape:connector-curvature="0" + id="path2521" + d="m 1176,589.5 h 16" + style="fill:none;stroke:#000000" /> + <path + sodipodi:nodetypes="csssc" + inkscape:connector-curvature="0" + id="path2523" + d="m 1180,589.5 c 0,-1 1,-5 1.5,-5 0.5,0 1,1.5 2.5,1.5 1.5,0 2,-1.5 2.5,-1.5 0.5,0 1.5,4 1.5,5" + style="fill:#000000;stroke:#000000" /> + <circle + r="5" + cy="592.5" + cx="1182.5" + id="path2525" + style="fill:#ffffff;stroke:#000000" /> + <path + sodipodi:nodetypes="cc" + inkscape:connector-curvature="0" + id="path2527" + d="M 1189.24,599.24 1186,596" + style="fill:none;stroke:#000000;stroke-width:2" /> + <path + sodipodi:nodetypes="cccccc" + inkscape:connector-curvature="0" + d="m 1184.5,595 v -5 m -2,5 v -3 m -2,1 v 2" + style="fill:none;stroke:#000000" + id="path2535" /> + </g> + </g> +</svg> diff --git a/src/images/settingscategory_usagestatistic@2x.png b/src/images/settingscategory_usagestatistic@2x.png Binary files differnew file mode 100644 index 0000000..136c67e --- /dev/null +++ b/src/images/settingscategory_usagestatistic@2x.png diff --git a/src/services/datasubmitter.cpp b/src/services/datasubmitter.cpp new file mode 100644 index 0000000..ea8d2c4 --- /dev/null +++ b/src/services/datasubmitter.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "datasubmitter.h" + +#include <QtCore/QCoreApplication> + +#include "common/utils.h" + +namespace UsageStatistic { +namespace Internal { + +using namespace KUserFeedback; + +DataSubmitter::DataSubmitter() = default; + +static QString makeVersionString() +{ + return qApp ? qApp->applicationName().append("/").append(qApp->applicationVersion()) : ""; +} + +static QByteArray authHeaderName() +{ + return QByteArrayLiteral("Authorization"); +} + +QNetworkRequest DataSubmitter::dataRequest() const +{ + QNetworkRequest request(serverUrl()); + + const auto versionString = makeVersionString(); + if (!versionString.isEmpty()) { + request.setHeader(QNetworkRequest::UserAgentHeader, versionString); + } + + request.setRawHeader(authHeaderName(), QByteArray(Utils::secret())); + + return request; +} + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/services/datasubmitter.h b/src/services/datasubmitter.h new file mode 100644 index 0000000..1ae66ac --- /dev/null +++ b/src/services/datasubmitter.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <KUserFeedback/AbstractJsonDataSubmitter> + +namespace UsageStatistic { +namespace Internal { + +//! Data submitter which also sets authorization and version headers +class DataSubmitter : public KUserFeedback::AbstractJsonDataSubmitter +{ +public: + DataSubmitter(); + +public: // AbstractDataSubmitter interface + QNetworkRequest dataRequest() const override; +}; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/src.pro b/src/src.pro new file mode 100644 index 0000000..f9fd69d --- /dev/null +++ b/src/src.pro @@ -0,0 +1,100 @@ +DEFINES += USAGESTATISTIC_LIBRARY + +INCLUDEPATH *= "$${PWD}" + +CONFIG += c++1z +QMAKE_CXXFLAGS *= -Wall +!msvc:QMAKE_CXXFLAGS *= -Wextra -pedantic + +DEFINES += $$shell_quote(USP_AUTH_KEY=\"$$(USP_AUTH_KEY)\") +DEFINES += $$shell_quote(USP_SERVER_URL=\"$$(USP_SERVER_URL)\") + +# UsageStatistic files +SOURCES += \ + usagestatisticplugin.cpp \ + datasources/qtclicensesource.cpp \ + datasources/buildcountsource.cpp \ + common/scopedsettingsgroupsetter.cpp \ + datasources/buildsystemsource.cpp \ + datasources/timeusagesourcebase.cpp \ + datasources/modeusagetimesource.cpp \ + datasources/examplesdatasource.cpp \ + datasources/kitsource.cpp \ + datasources/qmldesignerusagetimesource.cpp \ + ui/usagestatisticpage.cpp \ + ui/usagestatisticwidget.cpp \ + ui/outputpane.cpp \ + ui/encouragementwidget.cpp \ + services/datasubmitter.cpp + +HEADERS += \ + usagestatisticplugin.h \ + usagestatistic_global.h \ + usagestatisticconstants.h \ + datasources/qtclicensesource.h \ + datasources/buildcountsource.h \ + common/scopedsettingsgroupsetter.h \ + datasources/buildsystemsource.h \ + datasources/timeusagesourcebase.h \ + datasources/modeusagetimesource.h \ + datasources/examplesdatasource.h \ + datasources/kitsource.h \ + datasources/qmldesignerusagetimesource.h \ + ui/usagestatisticpage.h \ + ui/usagestatisticwidget.h \ + ui/outputpane.h \ + ui/encouragementwidget.h \ + services/datasubmitter.h \ + common/utils.h + +RESOURCES += \ + usagestatistic.qrc + +# Qt Creator linking + +## Either set the IDE_SOURCE_TREE when running qmake, +## or set the QTC_SOURCE environment variable, to override the default setting +isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE = $$(QTC_SOURCE) + +## Either set the IDE_BUILD_TREE when running qmake, +## or set the QTC_BUILD environment variable, to override the default setting +isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE = $$(QTC_BUILD) + +## uncomment to build plugin into user config directory +## <localappdata>/plugins/<ideversion> +## where <localappdata> is e.g. +## "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later +## "$XDG_DATA_HOME/data/QtProject/qtcreator" or "~/.local/share/data/QtProject/qtcreator" on Linux +## "~/Library/Application Support/QtProject/Qt Creator" on macOS +# USE_USER_DESTDIR = yes + +###### If the plugin can be depended upon by other plugins, this code needs to be outsourced to +###### <dirname>_dependencies.pri, where <dirname> is the name of the directory containing the +###### plugin's sources. + +QTC_PLUGIN_NAME = UsageStatistic +QTC_LIB_DEPENDS += \ + # nothing here at this time + +QTC_PLUGIN_DEPENDS += \ + coreplugin \ + debugger \ + projectexplorer \ + qtsupport + +QTC_PLUGIN_RECOMMENDS += \ + # optional plugin dependencies. nothing here at this time + +###### End _dependencies.pri contents ###### + +# KUserFeedback +include(3rdparty/kuserfeedback/kuserfeedback.pri) + +include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri) + +FORMS += \ + ui/usagestatisticwidget.ui \ + ui/encouragementwidget.ui + +QMAKE_EXTRA_TARGETS += docs install_docs # dummy targets for consistency + diff --git a/src/ui/encouragementwidget.cpp b/src/ui/encouragementwidget.cpp new file mode 100644 index 0000000..457422e --- /dev/null +++ b/src/ui/encouragementwidget.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "encouragementwidget.h" +#include "ui_encouragementwidget.h" + +#include "coreplugin/icore.h" + +#include <KUserFeedback/FeedbackConfigUiController> + +#include "usagestatisticconstants.h" + +namespace UsageStatistic { +namespace Internal { + +using namespace KUserFeedback; + +EncouragementWidget::EncouragementWidget(QWidget *parent) + : QWidget(parent) + , ui(new Ui::EncouragementWidget) + , m_controller(std::make_unique<FeedbackConfigUiController>()) +{ + ui->setupUi(this); + + connect(this, &EncouragementWidget::providerChanged, + this, &EncouragementWidget::onProviderChanged); + connect(ui->pbOptions, &QPushButton::clicked, + this, &EncouragementWidget::showSettingsDialog); +} + +std::shared_ptr<Provider> EncouragementWidget::provider() const +{ + return m_provider; +} + +void EncouragementWidget::setProvider(std::shared_ptr<Provider> provider) +{ + m_provider = std::move(provider); + + Q_EMIT providerChanged(m_provider); +} + +void EncouragementWidget::showEvent(QShowEvent *event) +{ + updateMessage(); + QWidget::showEvent(event); +} + +void EncouragementWidget::showSettingsDialog() +{ + Core::ICore::showOptionsDialog(Constants::USAGE_STATISTIC_PAGE_ID, this); +} + +void EncouragementWidget::updateMessage() +{ + if (m_provider) { + auto modeIndex = m_controller->telemetryModeToIndex(m_provider->telemetryMode()); + + auto description = m_controller->telemetryModeDescription(modeIndex); + + auto modeName = m_controller->telemetryModeName(modeIndex); + description.prepend(tr("Telemetry mode: %1.\n").arg(modeName)); + + ui->lblMsg->setText(description); + } +} + +void EncouragementWidget::onProviderChanged(const std::shared_ptr<Provider> &p) +{ + m_controller->setFeedbackProvider(p.get()); + + connect(m_provider.get(), &Provider::telemetryModeChanged, + this, &EncouragementWidget::updateMessage); + updateMessage(); +} + +EncouragementWidget::~EncouragementWidget() = default; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/ui/encouragementwidget.h b/src/ui/encouragementwidget.h new file mode 100644 index 0000000..6386a54 --- /dev/null +++ b/src/ui/encouragementwidget.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include <memory> + +#include <QWidget> + +namespace KUserFeedback { +class Provider; +class FeedbackConfigUiController; +} + +namespace UsageStatistic { +namespace Internal { + +namespace Ui { class EncouragementWidget; } + +//! Widget for displaying current telemetry level at the output pane +class EncouragementWidget : public QWidget +{ + Q_OBJECT + +public: + explicit EncouragementWidget(QWidget *parent = nullptr); + ~EncouragementWidget() override; + + std::shared_ptr<KUserFeedback::Provider> provider() const; + void setProvider(std::shared_ptr<KUserFeedback::Provider> provider); + +protected: // QWidget interface + void showEvent(QShowEvent *event) override; + +Q_SIGNALS: + void providerChanged(const std::shared_ptr<KUserFeedback::Provider> &); + +private Q_SLOTS: + void showSettingsDialog(); + void updateMessage(); + void onProviderChanged(const std::shared_ptr<KUserFeedback::Provider> &p); + +private: + QScopedPointer<Ui::EncouragementWidget> ui; + std::shared_ptr<KUserFeedback::Provider> m_provider; + std::unique_ptr<KUserFeedback::FeedbackConfigUiController> m_controller; +}; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/ui/encouragementwidget.ui b/src/ui/encouragementwidget.ui new file mode 100644 index 0000000..19f24a1 --- /dev/null +++ b/src/ui/encouragementwidget.ui @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UsageStatistic::Internal::EncouragementWidget</class> + <widget class="QWidget" name="UsageStatistic::Internal::EncouragementWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>572</width> + <height>70</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="lblMsg"> + <property name="text"> + <string>Message here...</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="pbOptions"> + <property name="text"> + <string>&Adjust telemetry settings</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/ui/outputpane.cpp b/src/ui/outputpane.cpp new file mode 100644 index 0000000..3529ca3 --- /dev/null +++ b/src/ui/outputpane.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "outputpane.h" + +#include <QtWidgets/QPushButton> +#include <QtWidgets/QHBoxLayout> +#include <QtCore/QDebug> + +#include "encouragementwidget.h" + +namespace UsageStatistic { +namespace Internal { + +OutputPane::OutputPane() = default; + +OutputPane::~OutputPane() = default; + +QWidget *OutputPane::outputWidget(QWidget *parent) +{ + if (!m_outputPaneWidget) { + createEncouragementWidget(parent); + } + + return m_outputPaneWidget; +} + +QList<QWidget *> OutputPane::toolBarWidgets() const +{ + return {}; +} + +QString OutputPane::displayName() const +{ + return tr("Feedback"); +} + +int OutputPane::priorityInStatusBar() const +{ + return 1; +} + +void OutputPane::clearContents() {} + +void OutputPane::visibilityChanged(bool /*visible*/) +{ +} + +void OutputPane::setFocus() {} + +bool OutputPane::hasFocus() const +{ + return false; +} + +bool OutputPane::canFocus() const +{ + return true; +} + +bool OutputPane::canNavigate() const +{ + return false; +} + +bool OutputPane::canNext() const +{ + return false; +} + +bool OutputPane::canPrevious() const +{ + return false; +} + +void OutputPane::goToNext() {} + +void OutputPane::goToPrev() {} + +void OutputPane::createEncouragementWidget(QWidget *parent) +{ + auto wgt = new EncouragementWidget(parent); + connect(this, &OutputPane::providerChanged, wgt, &EncouragementWidget::setProvider); + + m_outputPaneWidget = wgt; +} + +std::shared_ptr<KUserFeedback::Provider> OutputPane::provider() const +{ + return m_provider; +} + +void OutputPane::setProvider(std::shared_ptr<KUserFeedback::Provider> provider) +{ + m_provider = std::move(provider); + Q_EMIT providerChanged(m_provider); +} + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/ui/outputpane.h b/src/ui/outputpane.h new file mode 100644 index 0000000..039b3f2 --- /dev/null +++ b/src/ui/outputpane.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <memory> + +#include <QtCore/QPointer> +#include <QtWidgets/QWidget> + +#include <coreplugin/ioutputpane.h> + +QT_BEGIN_NAMESPACE +class QHBoxLayout; +QT_END_NAMESPACE + +namespace KUserFeedback { class Provider; } + +namespace UsageStatistic { +namespace Internal { + +class EncouragementWidget; + +//! Output pane for displayed different different information (telemetry level, surveys, etc.) +class OutputPane : public Core::IOutputPane +{ + Q_OBJECT + +public: + OutputPane(); + ~OutputPane() override; + +public: // IOutputPane interface + QWidget *outputWidget(QWidget *parent) override; + + QList<QWidget *> toolBarWidgets() const override; + + QString displayName() const override; + + int priorityInStatusBar() const override; + + void clearContents() override; + + void visibilityChanged(bool visible) override; + + void setFocus() override; + bool hasFocus() const override; + + bool canFocus() const override; + bool canNavigate() const override; + bool canNext() const override; + bool canPrevious() const override; + + void goToNext() override; + void goToPrev() override; + + std::shared_ptr<KUserFeedback::Provider> provider() const; + void setProvider(std::shared_ptr<KUserFeedback::Provider> provider); + +Q_SIGNALS: + void providerChanged(std::shared_ptr<KUserFeedback::Provider>); + +private: // Methods + void createEncouragementWidget(QWidget *parent); + +private: // Data + std::shared_ptr<KUserFeedback::Provider> m_provider; + QPointer<QWidget> m_outputPaneWidget; +}; + +} // namespace Internal +} // namespace UsageStatistic + +Q_DECLARE_METATYPE(std::shared_ptr<KUserFeedback::Provider>) diff --git a/src/ui/usagestatisticpage.cpp b/src/ui/usagestatisticpage.cpp new file mode 100644 index 0000000..a81fc87 --- /dev/null +++ b/src/ui/usagestatisticpage.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "usagestatisticpage.h" + +#include <KUserFeedback/AbstractDataSource> + +#include "usagestatisticwidget.h" +#include "usagestatisticconstants.h" + +namespace UsageStatistic { +namespace Internal { + +UsageStatisticPage::UsageStatisticPage(std::shared_ptr<KUserFeedback::Provider> provider) + : m_provider(std::move(provider)) +{ + configure(); +} + +UsageStatisticPage::~UsageStatisticPage() = default; + +QWidget *UsageStatisticPage::widget() +{ + if (!m_feedbackWidget) { + m_feedbackWidget = std::make_unique<UsageStatisticWidget>(m_provider); + m_feedbackWidget->updateSettings(); + } + + return m_feedbackWidget.get(); +} + +static void applyDataSourcesActiveStatuses(const QHash<QString, bool> &statuses, + const KUserFeedback::Provider &provider) +{ + for (auto &&ds : provider.dataSources()) { + if (ds) { + const auto it = statuses.find(ds->id()); + if (it != std::end(statuses)) { + ds->setActive(*it); + } + } + } +} + +void UsageStatisticPage::apply() +{ + auto settings = m_feedbackWidget->settings(); + + m_provider->setTelemetryMode(settings.telemetryMode); + applyDataSourcesActiveStatuses(settings.activeStatusesById, *m_provider); + + Q_EMIT settingsChanged(); +} + +void UsageStatisticPage::finish() +{ + m_feedbackWidget.reset(); +} + +void UsageStatisticPage::configure() +{ + setId(Constants::USAGE_STATISTIC_PAGE_ID); + setCategory(Constants::TELEMETRY_SETTINGS_CATEGORY_ID); + setCategoryIcon(Utils::Icon({{":/usagestatistic/images/settingscategory_usagestatistic.png", + Utils::Theme::PanelTextColorDark}}, Utils::Icon::Tint)); + + setDisplayName(tr("Usage Statistic")); + setDisplayCategory(tr("Telemetry")); +} + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/ui/usagestatisticpage.h b/src/ui/usagestatisticpage.h new file mode 100644 index 0000000..1052611 --- /dev/null +++ b/src/ui/usagestatisticpage.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <memory> + +#include <QtCore/QPointer> + +#include <coreplugin/dialogs/ioptionspage.h> + +namespace KUserFeedback { class Provider; } + +namespace UsageStatistic { +namespace Internal { + +class UsageStatisticWidget; + +//! Settings page +class UsageStatisticPage : public Core::IOptionsPage +{ + Q_OBJECT + +public: + UsageStatisticPage(std::shared_ptr<KUserFeedback::Provider> provider); + ~UsageStatisticPage() override; + +public: // IOptionsPage interface + QWidget *widget() override; + void apply() override; + void finish() override; + +Q_SIGNALS: + void settingsChanged(); + +private: // Data + std::unique_ptr<UsageStatisticWidget> m_feedbackWidget; + std::shared_ptr<KUserFeedback::Provider> m_provider; + +private: // Methods + void configure(); +}; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/ui/usagestatisticwidget.cpp b/src/ui/usagestatisticwidget.cpp new file mode 100644 index 0000000..b6f7a3b --- /dev/null +++ b/src/ui/usagestatisticwidget.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "usagestatisticwidget.h" +#include "ui_usagestatisticwidget.h" + +#include <QtCore/QJsonObject> +#include <QtCore/QJsonArray> +#include <QtCore/QJsonDocument> + +#include <KUserFeedback/FeedbackConfigUiController> +#include <KUserFeedback/AbstractDataSource> + +#include "usagestatisticconstants.h" + +namespace UsageStatistic { +namespace Internal { + +using namespace KUserFeedback; + +UsageStatisticWidget::UsageStatisticWidget(std::shared_ptr<KUserFeedback::Provider> provider) + : ui(std::make_unique<Ui::UsageStatisticWidget>()) + , m_provider(std::move(provider)) + , m_controller(std::make_unique<FeedbackConfigUiController>()) +{ + ui->setupUi(this); + + configure(); + + addPrivacyPolicyLink(); +} + +void UsageStatisticWidget::updateSettings() +{ + setupActiveStatuses(); + setupTelemetryModeUi(); +} + +UsageStatisticWidget::Settings UsageStatisticWidget::settings() const +{ + return {m_controller->telemetryIndexToMode(ui->cbMode->currentIndex()), m_activeStatusesById}; +} + +static constexpr int dataSourceIDRole = Qt::UserRole + 1; + +void UsageStatisticWidget::configure() +{ + m_controller->setFeedbackProvider(m_provider.get()); + + connect(ui->cbMode, QOverload<int>::of(&QComboBox::currentIndexChanged), + this, &UsageStatisticWidget::updateTelemetryModeDescription); + connect(ui->cbMode, QOverload<int>::of(&QComboBox::currentIndexChanged), + [this](int index) { preserveCurrentActiveStatuses(); updateDataSources(index); }); + + connect(ui->lvDataSources, &QListWidget::currentItemChanged, + this, &UsageStatisticWidget::updateDataSource); + connect(ui->lvDataSources, &QListWidget::itemChanged, + this, &UsageStatisticWidget::updateActiveStatus); +} + +void UsageStatisticWidget::setupTelemetryModeUi() +{ + ui->cbMode->clear(); + for (int i = 0; i < m_controller->telemetryModeCount(); ++i) { + ui->cbMode->addItem(QString("%1 - %2").arg(i).arg(m_controller->telemetryModeName(i))); + } + + ui->cbMode->setCurrentIndex(m_controller->telemetryModeToIndex(m_provider->telemetryMode())); +} + +void UsageStatisticWidget::updateTelemetryModeDescription(int modeIndex) +{ + ui->pteTelemetryLvlDescription->setPlainText(m_controller->telemetryModeDescription(modeIndex)); +} + +static auto dataSourceToItem(const AbstractDataSource &ds, + const UsageStatisticWidget::ActiveStatusesById &activeStatusesById) +{ + auto item = std::make_unique<QListWidgetItem>(ds.name()); + + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + const auto it = activeStatusesById.find(ds.id()); + if (it != std::end(activeStatusesById)) { + item->setCheckState(*it ? Qt::Checked : Qt::Unchecked); + } else { + item->setCheckState(Qt::Checked); + } + + item->setData(dataSourceIDRole, ds.id()); + + return item; +} + +void UsageStatisticWidget::updateDataSources(int modeIndex) +{ + ui->lvDataSources->clear(); + + for (auto &&ds : m_provider->dataSources()) { + if (ds && ds->telemetryMode() <= m_controller->telemetryIndexToMode(modeIndex)) { + auto item = dataSourceToItem(*ds, m_activeStatusesById).release(); + ui->lvDataSources->addItem(item); + + if (m_currentItemId == ds->id()) { + ui->lvDataSources->setCurrentItem(item); + } + } + } +} + +static QString collectedData(AbstractDataSource &ds) +{ + QByteArray result; + auto variantData = ds.data(); + + if (variantData.canConvert<QVariantMap>()) { + result = QJsonDocument(QJsonObject::fromVariantMap(variantData.toMap())).toJson(); + } + + if (variantData.canConvert<QVariantList>()) { + result = QJsonDocument(QJsonArray::fromVariantList(variantData.value<QVariantList>())).toJson(); + } + + return QString::fromUtf8(result); +} + +void UsageStatisticWidget::updateDataSource(QListWidgetItem *item) +{ + if (item) { + m_currentItemId = item->data(dataSourceIDRole).toString(); + + if (auto ds = m_provider->dataSource(m_currentItemId)) { + ui->pteDataSourceDescription->setPlainText(ds->description()); + ui->pteCollectedData->setPlainText(collectedData(*ds)); + } + } else { + ui->pteDataSourceDescription->clear(); + ui->pteCollectedData->clear(); + } +} + +void UsageStatisticWidget::updateActiveStatus(QListWidgetItem *item) +{ + if (item) { + auto id = item->data(dataSourceIDRole).toString(); + m_activeStatusesById[id] = item->checkState() == Qt::Checked; + } +} + +void UsageStatisticWidget::preserveCurrentActiveStatuses() +{ + for (int row = 0; row < ui->lvDataSources->count(); ++row) { + if (auto item = ui->lvDataSources->item(row)) { + auto id = item->data(dataSourceIDRole).toString(); + m_activeStatusesById[id] = item->checkState() == Qt::Checked; + } + } +} + +void UsageStatisticWidget::setupActiveStatuses() +{ + m_activeStatusesById.clear(); + + for (auto &&ds : m_provider->dataSources()) { + if (ds) { + m_activeStatusesById[ds->id()] = ds->isActive(); + } + } +} + +void UsageStatisticWidget::addPrivacyPolicyLink() +{ + const auto currentText = ui->lblPrivacyPolicy->text(); + const auto linkTemplate = QString("<a href=\"%1\">%2<\\a>"); + ui->lblPrivacyPolicy->setText(linkTemplate.arg(Constants::PRIVACY_POLICY_URL, currentText)); + + const auto tooltipTemplate = tr("Open %1"); + ui->lblPrivacyPolicy->setToolTip(tooltipTemplate.arg(Constants::PRIVACY_POLICY_URL)); +} + +UsageStatisticWidget::~UsageStatisticWidget() = default; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/ui/usagestatisticwidget.h b/src/ui/usagestatisticwidget.h new file mode 100644 index 0000000..fb3341a --- /dev/null +++ b/src/ui/usagestatisticwidget.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <memory> + +#include <QtWidgets/QWidget> +#include <QtCore/QHash> + +#include <KUserFeedback/Provider> + +namespace KUserFeedback { class FeedbackConfigUiController; } + +QT_BEGIN_NAMESPACE +class QListWidgetItem; +QT_END_NAMESPACE + +namespace UsageStatistic { +namespace Internal { + +namespace Ui { class UsageStatisticWidget; } + +//! Telemetry settings widget +class UsageStatisticWidget : public QWidget +{ + Q_OBJECT + +public: // Types + using ActiveStatusesById = QHash<QString, bool>; + + struct Settings + { + KUserFeedback::Provider::TelemetryMode telemetryMode; + ActiveStatusesById activeStatusesById; + }; + +public: + explicit UsageStatisticWidget(std::shared_ptr<KUserFeedback::Provider> provider); + ~UsageStatisticWidget() override; + + void updateSettings(); + + Settings settings() const; + +private: // Methods + void configure(); + + void setupTelemetryModeUi(); + void updateTelemetryModeDescription(int modeIndex); + + void updateDataSources(int modeIndex); + + void updateDataSource(QListWidgetItem *item); + void updateActiveStatus(QListWidgetItem *item); + + void preserveCurrentActiveStatuses(); + + void setupActiveStatuses(); + + void addPrivacyPolicyLink(); + +private: // Data + std::unique_ptr<Ui::UsageStatisticWidget> ui; + std::shared_ptr<KUserFeedback::Provider> m_provider; + std::unique_ptr<KUserFeedback::FeedbackConfigUiController> m_controller; + + QString m_currentItemId; + ActiveStatusesById m_activeStatusesById; +}; + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/ui/usagestatisticwidget.ui b/src/ui/usagestatisticwidget.ui new file mode 100644 index 0000000..484b69a --- /dev/null +++ b/src/ui/usagestatisticwidget.ui @@ -0,0 +1,161 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UsageStatistic::Internal::UsageStatisticWidget</class> + <widget class="QWidget" name="UsageStatistic::Internal::UsageStatisticWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>676</width> + <height>527</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <widget class="QGroupBox" name="gbTelemetryMode"> + <property name="title"> + <string>&Telemetry mode</string> + </property> + <property name="flat"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QComboBox" name="cbMode"> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToContents</enum> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QPlainTextEdit" name="pteTelemetryLvlDescription"> + <property name="undoRedoEnabled"> + <bool>false</bool> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="gbDataSources"> + <property name="title"> + <string>Data &sources</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="3,7"> + <item> + <widget class="QListWidget" name="lvDataSources"/> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_3" stretch="2,8"> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="lblDataSourceDescription"> + <property name="text"> + <string>&Description</string> + </property> + <property name="buddy"> + <cstring>pteDataSourceDescription</cstring> + </property> + </widget> + </item> + <item> + <widget class="QPlainTextEdit" name="pteDataSourceDescription"> + <property name="undoRedoEnabled"> + <bool>false</bool> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="textInteractionFlags"> + <set>Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QLabel" name="lblCollectedData"> + <property name="text"> + <string>&Collected Data</string> + </property> + <property name="buddy"> + <cstring>pteCollectedData</cstring> + </property> + </widget> + </item> + <item> + <widget class="QPlainTextEdit" name="pteCollectedData"> + <property name="undoRedoEnabled"> + <bool>false</bool> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="lblPrivacyPolicy"> + <property name="text"> + <string>Legal Notice and Privacy Policy</string> + </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/usagestatistic.qrc b/src/usagestatistic.qrc new file mode 100644 index 0000000..8ab02df --- /dev/null +++ b/src/usagestatistic.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/usagestatistic"> + <file>images/settingscategory_usagestatistic.png</file> + <file>images/settingscategory_usagestatistic@2x.png</file> + </qresource> +</RCC> diff --git a/src/usagestatistic_global.h b/src/usagestatistic_global.h new file mode 100644 index 0000000..094f51e --- /dev/null +++ b/src/usagestatistic_global.h @@ -0,0 +1,9 @@ +#pragma once + +#include <QtGlobal> + +#if defined(USAGESTATISTIC_LIBRARY) +# define USAGESTATISTICSHARED_EXPORT Q_DECL_EXPORT +#else +# define USAGESTATISTICSHARED_EXPORT Q_DECL_IMPORT +#endif diff --git a/src/usagestatisticconstants.h b/src/usagestatisticconstants.h new file mode 100644 index 0000000..0abde08 --- /dev/null +++ b/src/usagestatisticconstants.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <QString> + +namespace UsageStatistic { +namespace Constants { + +static const QString DATA_SOURCES_SETTINGS_GROUP = QStringLiteral("DataSources"); + +static constexpr char TELEMETRY_SETTINGS_CATEGORY_ID[] = "Telemetry"; + +static constexpr char USAGE_STATISTIC_PAGE_ID[] = "UsageStatistic"; + +static constexpr char PRIVACY_POLICY_URL[] = "https://www.qt.io/terms-conditions/#privacy"; + +} // namespace UsageStatistic +} // namespace Constants diff --git a/src/usagestatisticplugin.cpp b/src/usagestatisticplugin.cpp new file mode 100644 index 0000000..df09d74 --- /dev/null +++ b/src/usagestatisticplugin.cpp @@ -0,0 +1,195 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#include "usagestatisticplugin.h" +#include "usagestatisticconstants.h" + +#include <coreplugin/icore.h> +#include <coreplugin/icontext.h> +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/actionmanager/command.h> +#include <coreplugin/actionmanager/actioncontainer.h> +#include <coreplugin/coreconstants.h> + +#include <KUserFeedback/Provider> +#include <KUserFeedback/ApplicationVersionSource> +#include <KUserFeedback/CompilerInfoSource> +#include <KUserFeedback/CpuInfoSource> +#include <KUserFeedback/LocaleInfoSource> +#include <KUserFeedback/OpenGLInfoSource> +#include <KUserFeedback/PlatformInfoSource> +#include <KUserFeedback/QPAInfoSource> +#include <KUserFeedback/QtVersionSource> +#include <KUserFeedback/ScreenInfoSource> +#include <KUserFeedback/StartCountSource> +#include <KUserFeedback/UsageTimeSource> +#include <KUserFeedback/StyleInfoSource> + +#include "datasources/qtclicensesource.h" +#include "datasources/buildcountsource.h" +#include "datasources/buildsystemsource.h" +#include "datasources/modeusagetimesource.h" +#include "datasources/examplesdatasource.h" +#include "datasources/kitsource.h" +#include "datasources/qmldesignerusagetimesource.h" + +#include "services/datasubmitter.h" + +#include "ui/usagestatisticpage.h" +#include "ui/outputpane.h" + +#include "common/utils.h" + +namespace UsageStatistic { +namespace Internal { + +UsageStatisticPlugin::UsageStatisticPlugin() = default; + +UsageStatisticPlugin::~UsageStatisticPlugin() = default; + +bool UsageStatisticPlugin::initialize(const QStringList &arguments, QString *errorString) +{ + Q_UNUSED(arguments) + Q_UNUSED(errorString) + + // We have to create a pane here because of OutputPaneManager internal initialization order + createOutputPane(); + + return true; +} + +void UsageStatisticPlugin::extensionsInitialized() +{ +} + +static void addDefaultDataSources(KUserFeedback::Provider &provider) +{ + provider.addDataSource(new KUserFeedback::ApplicationVersionSource); + provider.addDataSource(new KUserFeedback::CompilerInfoSource); + provider.addDataSource(new KUserFeedback::CpuInfoSource); + provider.addDataSource(new KUserFeedback::LocaleInfoSource); + provider.addDataSource(new KUserFeedback::OpenGLInfoSource); + provider.addDataSource(new KUserFeedback::PlatformInfoSource); + provider.addDataSource(new KUserFeedback::QPAInfoSource); + provider.addDataSource(new KUserFeedback::QtVersionSource); + provider.addDataSource(new KUserFeedback::ScreenInfoSource); + provider.addDataSource(new KUserFeedback::StartCountSource); + provider.addDataSource(new KUserFeedback::UsageTimeSource); + provider.addDataSource(new KUserFeedback::StyleInfoSource); +} + +static void addQtCreatorDataSources(KUserFeedback::Provider &provider) +{ + provider.addDataSource(new QtcLicenseSource); + provider.addDataSource(new BuildCountSource); + provider.addDataSource(new BuildSystemSource); + provider.addDataSource(new ModeUsageTimeSource); + provider.addDataSource(new ExamplesDataSource); + provider.addDataSource(new KitSource); + provider.addDataSource(new QmlDesignerUsageTimeSource); +} + +bool UsageStatisticPlugin::delayedInitialize() +{ + // We should create the provider only after everything else + // is initialised (e.g., setting organization name) + createProvider(); + + addDefaultDataSources(*m_provider); + addQtCreatorDataSources(*m_provider); + + createUsageStatisticPage(); + + restoreSettings(); + + configureOutputPane(); + + return true; +} + +ExtensionSystem::IPlugin::ShutdownFlag UsageStatisticPlugin::aboutToShutdown() +{ + storeSettings(); + + return SynchronousShutdown; +} + +void UsageStatisticPlugin::createUsageStatisticPage() +{ + m_usageStatisticPage = std::make_unique<UsageStatisticPage>(m_provider); + + connect(m_usageStatisticPage.get(), &UsageStatisticPage::settingsChanged, + this, &UsageStatisticPlugin::storeSettings); +} + +void UsageStatisticPlugin::createOutputPane() +{ + m_outputPane = std::make_unique<OutputPane>(); +} + +void UsageStatisticPlugin::configureOutputPane() +{ + Q_ASSERT(m_outputPane); + + m_outputPane->setProvider(m_provider); + + connect(m_provider.get(), &KUserFeedback::Provider::showEncouragementMessage, + m_outputPane.get(), &OutputPane::flash); +} + +void UsageStatisticPlugin::storeSettings() +{ + if (m_provider) { + m_provider->store(); + } +} + +void UsageStatisticPlugin::restoreSettings() +{ + if (m_provider) { + m_provider->load(); + } +} + +static constexpr int encouragementTimeSec() { return 1800; } +static constexpr int encouragementIntervalDays() { return 1; } +static constexpr int submissionIntervalDays() { return 10; } + +void UsageStatisticPlugin::createProvider() +{ + Q_ASSERT(!m_provider); + m_provider = std::make_shared<KUserFeedback::Provider>(); + + m_provider->setFeedbackServer(QString::fromUtf8(Utils::serverUrl())); + m_provider->setDataSubmitter(new DataSubmitter); + + m_provider->setApplicationUsageTimeUntilEncouragement(encouragementTimeSec()); + m_provider->setEncouragementDelay(encouragementTimeSec()); + m_provider->setEncouragementInterval(encouragementIntervalDays()); + + m_provider->setSubmissionInterval(submissionIntervalDays()); +} + +} // namespace Internal +} // namespace UsageStatistic diff --git a/src/usagestatisticplugin.h b/src/usagestatisticplugin.h new file mode 100644 index 0000000..139acc3 --- /dev/null +++ b/src/usagestatisticplugin.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company +** Contact: https://www.qt.io/licensing/ +** +** This file is part of UsageStatistic plugin for Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <memory> + +#include "usagestatistic_global.h" + +#include <extensionsystem/iplugin.h> + +namespace KUserFeedback { class Provider; } + +namespace UsageStatistic { +namespace Internal { + +class UsageStatisticPage; +class OutputPane; + +//! Plugin for collecting and sending usage statistics +class UsageStatisticPlugin : public ExtensionSystem::IPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "UsageStatistic.json") + +public: + UsageStatisticPlugin(); + ~UsageStatisticPlugin() override; + + bool initialize(const QStringList &arguments, QString *errorString) override; + void extensionsInitialized() override; + bool delayedInitialize() override; + ShutdownFlag aboutToShutdown() override; + +private: + void createUsageStatisticPage(); + void createOutputPane(); + void configureOutputPane(); + void storeSettings(); + void restoreSettings(); + void createProvider(); + +private: + std::shared_ptr<KUserFeedback::Provider> m_provider; + std::unique_ptr<UsageStatisticPage> m_usageStatisticPage; + std::unique_ptr<OutputPane> m_outputPane; +}; + +} // namespace Internal +} // namespace UsageStatistic |