From f25a9bc103d101ea9d79fe159b83d88a4cc35f87 Mon Sep 17 00:00:00 2001 From: swirl Date: Wed, 29 Dec 2021 10:37:09 -0500 Subject: [PATCH] Completely remove Google Analytics library --- CMakeLists.txt | 6 +- buildconfig/BuildConfig.cpp.in | 1 - buildconfig/BuildConfig.h | 6 +- launcher/Application.cpp | 142 +--------- launcher/Application.h | 8 +- launcher/CMakeLists.txt | 3 - launcher/ui/pages/global/LauncherPage.cpp | 17 -- launcher/ui/pages/global/LauncherPage.ui | 63 ----- .../ui/setupwizard/AnalyticsWizardPage.cpp | 63 ----- launcher/ui/setupwizard/AnalyticsWizardPage.h | 25 -- launcher/ui/setupwizard/SetupWizard.cpp | 2 - libraries/README.md | 7 - libraries/ganalytics/CMakeLists.txt | 17 -- libraries/ganalytics/LICENSE.txt | 24 -- libraries/ganalytics/README.md | 34 --- libraries/ganalytics/include/ganalytics.h | 67 ----- libraries/ganalytics/src/ganalytics.cpp | 237 ---------------- .../ganalytics/src/ganalytics_worker.cpp | 254 ------------------ libraries/ganalytics/src/ganalytics_worker.h | 65 ----- 19 files changed, 5 insertions(+), 1036 deletions(-) delete mode 100644 launcher/ui/setupwizard/AnalyticsWizardPage.cpp delete mode 100644 launcher/ui/setupwizard/AnalyticsWizardPage.h delete mode 100644 libraries/ganalytics/CMakeLists.txt delete mode 100644 libraries/ganalytics/LICENSE.txt delete mode 100644 libraries/ganalytics/README.md delete mode 100644 libraries/ganalytics/include/ganalytics.h delete mode 100644 libraries/ganalytics/src/ganalytics.cpp delete mode 100644 libraries/ganalytics/src/ganalytics_worker.cpp delete mode 100644 libraries/ganalytics/src/ganalytics_worker.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b7018d1b6..ab7fc7bdc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,9 +78,6 @@ set(Launcher_PASTE_EE_API_KEY "utLvciUouSURFzfjPxLBf5W4ISsUX4pwBDF7N1AfZ" CACHE # Imgur API Client ID set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can get from Imgur when you register an application") -# Google analytics ID -set(Launcher_ANALYTICS_ID "" CACHE STRING "ID you can get from Google analytics") - # MSA Client ID set(Launcher_MSA_CLIENT_ID "17b47edd-c884-4997-926d-9e7f9a6b4647" CACHE STRING "Client ID you can get from Microsoft Identity Platform when you register an application") @@ -250,7 +247,6 @@ set(NBT_NAME Launcher_nbt++) set(NBT_DEST_DIR ${LIBRARY_DEST_DIR}) add_subdirectory(libraries/libnbtplusplus) -add_subdirectory(libraries/ganalytics) # google analytics library add_subdirectory(libraries/systeminfo) # system information library add_subdirectory(libraries/hoedown) # markdown parser add_subdirectory(libraries/launcher) # java based launcher part for Minecraft @@ -260,7 +256,7 @@ add_subdirectory(libraries/quazip) # zip manipulation library add_subdirectory(libraries/rainbow) # Qt extension for colors add_subdirectory(libraries/iconfix) # fork of Qt's QIcon loader add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions -add_subdirectory(libraries/classparser) # google analytics library +add_subdirectory(libraries/classparser) # class parser library add_subdirectory(libraries/optional-bare) add_subdirectory(libraries/tomlc99) # toml parser add_subdirectory(libraries/katabasis) # An OAuth2 library that tried to do too much diff --git a/buildconfig/BuildConfig.cpp.in b/buildconfig/BuildConfig.cpp.in index 66cb0f179..af8845dce 100644 --- a/buildconfig/BuildConfig.cpp.in +++ b/buildconfig/BuildConfig.cpp.in @@ -24,7 +24,6 @@ Config::Config() BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@"; UPDATER_BASE = "@Launcher_UPDATER_BASE@"; - ANALYTICS_ID = "@Launcher_ANALYTICS_ID@"; NOTIFICATION_URL = "@Launcher_NOTIFICATION_URL@"; FULL_VERSION_STR = "@Launcher_VERSION_MAJOR@.@Launcher_VERSION_MINOR@.@Launcher_VERSION_BUILD@"; diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index 2d847f944..009fb2bca 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -46,9 +46,6 @@ public: QString USER_AGENT_UNCACHED; - /// Google analytics ID - QString ANALYTICS_ID; - /// URL for notifications QString NOTIFICATION_URL; @@ -79,7 +76,7 @@ public: * Client ID you can get from Imgur when you register an application */ QString IMGUR_CLIENT_ID; - + /** * Client ID you can get from Microsoft Identity Platform when you register an application */ @@ -115,3 +112,4 @@ public: }; extern const Config BuildConfig; + diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 264bfff80..8e0d6c334 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -26,7 +26,6 @@ #include "ui/setupwizard/SetupWizard.h" #include "ui/setupwizard/LanguageWizardPage.h" #include "ui/setupwizard/JavaWizardPage.h" -#include "ui/setupwizard/AnalyticsWizardPage.h" #include "ui/dialogs/CustomMessageBox.h" @@ -73,7 +72,6 @@ #include #include -#include #include @@ -719,14 +717,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // paste.ee API key m_settings->registerSetting("PasteEEAPIKey", "multimc"); - if(!BuildConfig.ANALYTICS_ID.isEmpty()) - { - // Analytics - m_settings->registerSetting("Analytics", true); - m_settings->registerSetting("AnalyticsSeen", 0); - m_settings->registerSetting("AnalyticsClientID", QString()); - } - // Init page provider { m_globalSettingsProvider = std::make_shared(tr("Settings")); @@ -908,46 +898,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) qDebug() << "<> Application theme set."; } - // Initialize analytics - [this]() - { - const int analyticsVersion = 2; - if(BuildConfig.ANALYTICS_ID.isEmpty()) - { - return; - } - - auto analyticsSetting = m_settings->getSetting("Analytics"); - connect(analyticsSetting.get(), &Setting::SettingChanged, this, &Application::analyticsSettingChanged); - QString clientID = m_settings->get("AnalyticsClientID").toString(); - if(clientID.isEmpty()) - { - clientID = QUuid::createUuid().toString(); - clientID.remove(QLatin1Char('{')); - clientID.remove(QLatin1Char('}')); - m_settings->set("AnalyticsClientID", clientID); - } - m_analytics = new GAnalytics(BuildConfig.ANALYTICS_ID, clientID, analyticsVersion, this); - m_analytics->setLogLevel(GAnalytics::Debug); - m_analytics->setAnonymizeIPs(true); - // FIXME: the ganalytics library has no idea about our fancy shared pointers... - m_analytics->setNetworkAccessManager(network().get()); - - if(m_settings->get("AnalyticsSeen").toInt() < m_analytics->version()) - { - qDebug() << "Analytics info not seen by user yet (or old version)."; - return; - } - if(!m_settings->get("Analytics").toBool()) - { - qDebug() << "Analytics disabled by user."; - return; - } - - m_analytics->enable(); - qDebug() << "<> Initialized analytics with tid" << BuildConfig.ANALYTICS_ID; - }(); - if(createSetupWizard()) { return; @@ -974,29 +924,13 @@ bool Application::createSetupWizard() } return false; }(); - bool analyticsRequired = [&]() - { - if(BuildConfig.ANALYTICS_ID.isEmpty()) - { - return false; - } - if (!settings()->get("Analytics").toBool()) - { - return false; - } - if (settings()->get("AnalyticsSeen").toInt() < analytics()->version()) - { - return true; - } - return false; - }(); bool languageRequired = [&]() { if (settings()->get("Language").toString().isEmpty()) return true; return false; }(); - bool wizardRequired = javaRequired || analyticsRequired || languageRequired; + bool wizardRequired = javaRequired || languageRequired; if(wizardRequired) { @@ -1009,10 +943,6 @@ bool Application::createSetupWizard() { m_setupWizard->addPage(new JavaWizardPage(m_setupWizard)); } - if(analyticsRequired) - { - m_setupWizard->addPage(new AnalyticsWizardPage(m_setupWizard)); - } connect(m_setupWizard, &QDialog::finished, this, &Application::setupWizardFinished); m_setupWizard->show(); return true; @@ -1169,22 +1099,6 @@ void Application::messageReceived(const QByteArray& message) } } -void Application::analyticsSettingChanged(const Setting&, QVariant value) -{ - if(!m_analytics) - return; - bool enabled = value.toBool(); - if(enabled) - { - qDebug() << "Analytics enabled by user."; - } - else - { - qDebug() << "Analytics disabled by user."; - } - m_analytics->enable(enabled); -} - std::shared_ptr Application::translations() { return m_translations; @@ -1454,60 +1368,6 @@ MainWindow* Application::showMainWindow(bool minimized) connect(m_mainWindow, &MainWindow::isClosing, this, &Application::on_windowClose); m_openWindows++; } - // FIXME: move this somewhere else... - if(m_analytics) - { - auto windowSize = m_mainWindow->size(); - auto sizeString = QString("%1x%2").arg(windowSize.width()).arg(windowSize.height()); - qDebug() << "Viewport size" << sizeString; - m_analytics->setViewportSize(sizeString); - /* - * cm1 = java min heap [MB] - * cm2 = java max heap [MB] - * cm3 = system RAM [MB] - * - * cd1 = java version - * cd2 = java architecture - * cd3 = system architecture - * cd4 = CPU architecture - */ - QVariantMap customValues; - int min = m_settings->get("MinMemAlloc").toInt(); - int max = m_settings->get("MaxMemAlloc").toInt(); - if(min < max) - { - customValues["cm1"] = min; - customValues["cm2"] = max; - } - else - { - customValues["cm1"] = max; - customValues["cm2"] = min; - } - - constexpr uint64_t Mega = 1024ull * 1024ull; - int ramSize = int(Sys::getSystemRam() / Mega); - qDebug() << "RAM size is" << ramSize << "MB"; - customValues["cm3"] = ramSize; - - customValues["cd1"] = m_settings->get("JavaVersion"); - customValues["cd2"] = m_settings->get("JavaArchitecture"); - customValues["cd3"] = Sys::isSystem64bit() ? "64":"32"; - customValues["cd4"] = Sys::isCPU64bit() ? "64":"32"; - auto kernelInfo = Sys::getKernelInfo(); - customValues["cd5"] = kernelInfo.kernelName; - customValues["cd6"] = kernelInfo.kernelVersion; - auto distInfo = Sys::getDistributionInfo(); - if(!distInfo.distributionName.isEmpty()) - { - customValues["cd7"] = distInfo.distributionName; - } - if(!distInfo.distributionVersion.isEmpty()) - { - customValues["cd8"] = distInfo.distributionVersion; - } - m_analytics->sendScreenView("Main Window", customValues); - } return m_mainWindow; } diff --git a/launcher/Application.h b/launcher/Application.h index 982e22e32..c1cd82243 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -33,7 +33,6 @@ class BaseDetachedToolFactory; class TranslationsModel; class ITheme; class MCEditTool; -class GAnalytics; namespace Meta { class Index; @@ -60,10 +59,6 @@ public: Application(int &argc, char **argv); virtual ~Application(); - GAnalytics *analytics() const { - return m_analytics; - } - std::shared_ptr settings() const { return m_settings; } @@ -161,7 +156,6 @@ private slots: void messageReceived(const QByteArray & message); void controllerSucceeded(); void controllerFailed(const QString & error); - void analyticsSettingChanged(const Setting &setting, QVariant value); void setupWizardFinished(int status); private: @@ -226,7 +220,6 @@ private: // peer launcher instance connector - used to implement single instance launcher and signalling LocalPeer * m_peerInstance = nullptr; - GAnalytics * m_analytics = nullptr; SetupWizard * m_setupWizard = nullptr; public: QString m_instanceIdToLaunch; @@ -236,3 +229,4 @@ public: QUrl m_zipToImport; std::unique_ptr logFile; }; + diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index fceca8e23..b5c52afa2 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -627,8 +627,6 @@ SET(LAUNCHER_SOURCES # GUI - setup wizard ui/setupwizard/SetupWizard.h ui/setupwizard/SetupWizard.cpp - ui/setupwizard/AnalyticsWizardPage.cpp - ui/setupwizard/AnalyticsWizardPage.h ui/setupwizard/BaseWizardPage.h ui/setupwizard/JavaWizardPage.cpp ui/setupwizard/JavaWizardPage.h @@ -932,7 +930,6 @@ target_link_libraries(Launcher_logic hoedown Launcher_rainbow LocalPeer - ganalytics ) target_link_libraries(Launcher_logic) diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 2eb73e44d..4d4d4e896 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -73,11 +73,6 @@ LauncherPage::LauncherPage(QWidget *parent) : QWidget(parent), ui(new Ui::Launch { ui->updateSettingsBox->setHidden(true); } - // Analytics - if(BuildConfig.ANALYTICS_ID.isEmpty()) - { - ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->analyticsTab)); - } connect(ui->fontSizeBox, SIGNAL(valueChanged(int)), SLOT(refreshFontPreview())); connect(ui->consoleFont, SIGNAL(currentFontChanged(QFont)), SLOT(refreshFontPreview())); @@ -321,12 +316,6 @@ void LauncherPage::applySettings() s->set("InstSortMode", "Name"); break; } - - // Analytics - if(!BuildConfig.ANALYTICS_ID.isEmpty()) - { - s->set("Analytics", ui->analyticsCheck->isChecked()); - } } void LauncherPage::loadSettings() { @@ -422,12 +411,6 @@ void LauncherPage::loadSettings() { ui->sortByNameBtn->setChecked(true); } - - // Analytics - if(!BuildConfig.ANALYTICS_ID.isEmpty()) - { - ui->analyticsCheck->setChecked(s->get("Analytics").toBool()); - } } void LauncherPage::refreshFontPreview() diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index 62a66d73b..2b3729bcf 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -485,69 +485,6 @@ - - - Analytics - - - - - - Analytics Settings - - - - - - Send anonymous usage statistics? - - - - - - - Qt::Horizontal - - - - - - - <html><head/> -<body> -<p>The launcher sends anonymous usage statistics on every start of the application.</p><p>The following data is collected:</p> -<ul> -<li>Launcher version.</li> -<li>Operating system name, version and architecture.</li> -<li>CPU architecture (kernel architecture on linux).</li> -<li>Size of system memory.</li> -<li>Java version, architecture and memory settings.</li> -</ul> -</body></html> - - - true - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - diff --git a/launcher/ui/setupwizard/AnalyticsWizardPage.cpp b/launcher/ui/setupwizard/AnalyticsWizardPage.cpp deleted file mode 100644 index 3db2f6dcc..000000000 --- a/launcher/ui/setupwizard/AnalyticsWizardPage.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "AnalyticsWizardPage.h" -#include - -#include -#include -#include - -#include -#include - -AnalyticsWizardPage::AnalyticsWizardPage(QWidget *parent) - : BaseWizardPage(parent) -{ - setObjectName(QStringLiteral("analyticsPage")); - verticalLayout_3 = new QVBoxLayout(this); - verticalLayout_3->setObjectName(QStringLiteral("verticalLayout_3")); - textBrowser = new QTextBrowser(this); - textBrowser->setObjectName(QStringLiteral("textBrowser")); - textBrowser->setAcceptRichText(false); - textBrowser->setOpenExternalLinks(true); - verticalLayout_3->addWidget(textBrowser); - - checkBox = new QCheckBox(this); - checkBox->setObjectName(QStringLiteral("checkBox")); - checkBox->setChecked(true); - verticalLayout_3->addWidget(checkBox); - retranslate(); -} - -AnalyticsWizardPage::~AnalyticsWizardPage() -{ -} - -bool AnalyticsWizardPage::validatePage() -{ - auto settings = APPLICATION->settings(); - auto analytics = APPLICATION->analytics(); - auto status = checkBox->isChecked(); - settings->set("AnalyticsSeen", analytics->version()); - settings->set("Analytics", status); - return true; -} - -void AnalyticsWizardPage::retranslate() -{ - setTitle(tr("Analytics")); - setSubTitle(tr("We track some anonymous statistics about users.")); - textBrowser->setHtml(tr( - "" - "

The launcher sends anonymous usage statistics on every start of the application. This helps us decide what platforms and issues to focus on.

" - "

The data is processed by Google Analytics, see their article on the " - "matter.

" - "

The following data is collected:

" - "
  • A random unique ID of the installation.
    It is stored in the application settings file.
  • " - "
  • Anonymized (partial) IP address.
  • " - "
  • Launcher version.
  • " - "
  • Operating system name, version and architecture.
  • " - "
  • CPU architecture (kernel architecture on linux).
  • " - "
  • Size of system memory.
  • " - "
  • Java version, architecture and memory settings.
" - "

If we change the tracked information, you will see this page again.

")); - checkBox->setText(tr("Enable Analytics")); -} diff --git a/launcher/ui/setupwizard/AnalyticsWizardPage.h b/launcher/ui/setupwizard/AnalyticsWizardPage.h deleted file mode 100644 index c451db2c7..000000000 --- a/launcher/ui/setupwizard/AnalyticsWizardPage.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "BaseWizardPage.h" - -class QVBoxLayout; -class QTextBrowser; -class QCheckBox; - -class AnalyticsWizardPage : public BaseWizardPage -{ - Q_OBJECT -public: - explicit AnalyticsWizardPage(QWidget *parent = Q_NULLPTR); - virtual ~AnalyticsWizardPage(); - - bool validatePage() override; - -protected: - void retranslate() override; - -private: - QVBoxLayout *verticalLayout_3 = nullptr; - QTextBrowser *textBrowser = nullptr; - QCheckBox *checkBox = nullptr; -}; \ No newline at end of file diff --git a/launcher/ui/setupwizard/SetupWizard.cpp b/launcher/ui/setupwizard/SetupWizard.cpp index 5af5ba91f..22eab60e8 100644 --- a/launcher/ui/setupwizard/SetupWizard.cpp +++ b/launcher/ui/setupwizard/SetupWizard.cpp @@ -2,12 +2,10 @@ #include "LanguageWizardPage.h" #include "JavaWizardPage.h" -#include "AnalyticsWizardPage.h" #include "translations/TranslationsModel.h" #include #include -#include #include #include diff --git a/libraries/README.md b/libraries/README.md index 395058813..7e7e740d1 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -9,13 +9,6 @@ This library has served as a base for some (much more full-featured and advanced Copyright belongs to Petr Mrázek, unless explicitly stated otherwise in the source files. Available under the Apache 2.0 license. -## ganalytics -A Google Analytics library for Qt. - -BSD licensed, derived from [qt-google-analytics](https://github.com/HSAnet/qt-google-analytics). - -Modifications include better handling of IP anonymization (can be enabled) and general improvements of the API (application handles persistence and ID generation instead of the library). - ## hoedown Hoedown is a revived fork of Sundown, the Markdown parser based on the original code of the Upskirt library by Natacha Porté. diff --git a/libraries/ganalytics/CMakeLists.txt b/libraries/ganalytics/CMakeLists.txt deleted file mode 100644 index cf1cc5598..000000000 --- a/libraries/ganalytics/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -project(ganalytics) - -find_package(Qt5Core) -find_package(Qt5Gui) -find_package(Qt5Network) - -set(ganalytics_SOURCES -src/ganalytics.cpp -src/ganalytics_worker.cpp -src/ganalytics_worker.h -include/ganalytics.h -) - -add_library(ganalytics STATIC ${ganalytics_SOURCES}) -target_link_libraries(ganalytics Qt5::Core Qt5::Gui Qt5::Network) -target_include_directories(ganalytics PUBLIC include) -target_link_libraries(ganalytics systeminfo) diff --git a/libraries/ganalytics/LICENSE.txt b/libraries/ganalytics/LICENSE.txt deleted file mode 100644 index 795497ffe..000000000 --- a/libraries/ganalytics/LICENSE.txt +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2014-2015, University of Applied Sciences Augsburg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the University of Applied Sciences Augsburg nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -OODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -UT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libraries/ganalytics/README.md b/libraries/ganalytics/README.md deleted file mode 100644 index d7e1e33c7..000000000 --- a/libraries/ganalytics/README.md +++ /dev/null @@ -1,34 +0,0 @@ -qt-google-analytics -================ - -Qt5 classes for providing google analytics usage in a Qt/QML application. - -## Building -Include ```qt-google-analytics.pri``` in your .pro file. - -## Using -Please make sure you have set your application information using ```QApplication::setApplicationName``` and ```QApplication::setApplicationVersion```. - -### In C++: -``` -GAnalytics tracker("UA-my-id"); -tracker.sendScreenView("Main Screen"); -``` - -### In QtQuick: -Register the class on the C++ side using ```qmlRegisterType("analytics", 0, 1, "Tracker");``` -``` -Tracker { - id: tracker - trackingID: "UA-my-id" -} - -[...] -tracker.sendScreenView("Main Screen") -``` - -There is also an example application in the examples folder. - -## License -Copyright (c) 2014-2016, University of Applied Sciences Augsburg. -All rights reserved. Distributed under the terms and conditions of the BSD License. See separate LICENSE.txt. diff --git a/libraries/ganalytics/include/ganalytics.h b/libraries/ganalytics/include/ganalytics.h deleted file mode 100644 index ba4224572..000000000 --- a/libraries/ganalytics/include/ganalytics.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include -#include - -class QNetworkAccessManager; -class GAnalyticsWorker; - -class GAnalytics : public QObject -{ - Q_OBJECT - Q_ENUMS(LogLevel) - -public: - explicit GAnalytics(const QString &trackingID, const QString &clientID, const int version, QObject *parent = 0); - ~GAnalytics(); - -public: - enum LogLevel - { - Debug, - Info, - Error - }; - - int version(); - - void setLogLevel(LogLevel logLevel); - LogLevel logLevel() const; - - // Getter and Setters - void setViewportSize(const QString &viewportSize); - QString viewportSize() const; - - void setLanguage(const QString &language); - QString language() const; - - void setAnonymizeIPs(bool anonymize); - bool anonymizeIPs(); - - void setSendInterval(int milliseconds); - int sendInterval() const; - - void enable(bool state = true); - bool isEnabled(); - - /// Get or set the network access manager. If none is set, the class creates its own on the first request - void setNetworkAccessManager(QNetworkAccessManager *networkAccessManager); - QNetworkAccessManager *networkAccessManager() const; - -public slots: - void sendScreenView(const QString &screenName, const QVariantMap &customValues = QVariantMap()); - void sendEvent(const QString &category, const QString &action, const QString &label = QString(), const QVariant &value = QVariant(), - const QVariantMap &customValues = QVariantMap()); - void sendException(const QString &exceptionDescription, bool exceptionFatal = true, const QVariantMap &customValues = QVariantMap()); - void startSession(); - void endSession(); - -private: - GAnalyticsWorker *d; - - friend QDataStream &operator<<(QDataStream &outStream, const GAnalytics &analytics); - friend QDataStream &operator>>(QDataStream &inStream, GAnalytics &analytics); -}; - -QDataStream &operator<<(QDataStream &outStream, const GAnalytics &analytics); -QDataStream &operator>>(QDataStream &inStream, GAnalytics &analytics); diff --git a/libraries/ganalytics/src/ganalytics.cpp b/libraries/ganalytics/src/ganalytics.cpp deleted file mode 100644 index a4b7394f2..000000000 --- a/libraries/ganalytics/src/ganalytics.cpp +++ /dev/null @@ -1,237 +0,0 @@ -#include "ganalytics.h" -#include "ganalytics_worker.h" -#include "sys.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -GAnalytics::GAnalytics(const QString &trackingID, const QString &clientID, const int version, QObject *parent) : QObject(parent) -{ - d = new GAnalyticsWorker(this); - d->m_trackingID = trackingID; - d->m_clientID = clientID; - d->m_version = version; -} - -/** - * Destructor of class GAnalytics. - */ -GAnalytics::~GAnalytics() -{ - delete d; -} - -void GAnalytics::setLogLevel(GAnalytics::LogLevel logLevel) -{ - d->m_logLevel = logLevel; -} - -GAnalytics::LogLevel GAnalytics::logLevel() const -{ - return d->m_logLevel; -} - -// SETTER and GETTER -void GAnalytics::setViewportSize(const QString &viewportSize) -{ - d->m_viewportSize = viewportSize; -} - -QString GAnalytics::viewportSize() const -{ - return d->m_viewportSize; -} - -void GAnalytics::setLanguage(const QString &language) -{ - d->m_language = language; -} - -QString GAnalytics::language() const -{ - return d->m_language; -} - -void GAnalytics::setAnonymizeIPs(bool anonymize) -{ - d->m_anonymizeIPs = anonymize; -} - -bool GAnalytics::anonymizeIPs() -{ - return d->m_anonymizeIPs; -} - -void GAnalytics::setSendInterval(int milliseconds) -{ - d->m_timer.setInterval(milliseconds); -} - -int GAnalytics::sendInterval() const -{ - return (d->m_timer.interval()); -} - -bool GAnalytics::isEnabled() -{ - return d->m_isEnabled; -} - -void GAnalytics::enable(bool state) -{ - d->enable(state); -} - -int GAnalytics::version() -{ - return d->m_version; -} - -void GAnalytics::setNetworkAccessManager(QNetworkAccessManager *networkAccessManager) -{ - if (d->networkManager != networkAccessManager) - { - // Delete the old network manager if it was our child - if (d->networkManager && d->networkManager->parent() == this) - { - d->networkManager->deleteLater(); - } - - d->networkManager = networkAccessManager; - } -} - -QNetworkAccessManager *GAnalytics::networkAccessManager() const -{ - return d->networkManager; -} - -static void appendCustomValues(QUrlQuery &query, const QVariantMap &customValues) -{ - for (QVariantMap::const_iterator iter = customValues.begin(); iter != customValues.end(); ++iter) - { - query.addQueryItem(iter.key(), iter.value().toString()); - } -} - -/** - * Sent screen view is called when the user changed the applications view. - * These action of the user should be noticed and reported. Therefore - * a QUrlQuery is build in this method. It holts all the parameter for - * a http POST. The UrlQuery will be stored in a message Queue. - */ -void GAnalytics::sendScreenView(const QString &screenName, const QVariantMap &customValues) -{ - d->logMessage(Info, QString("ScreenView: %1").arg(screenName)); - - QUrlQuery query = d->buildStandardPostQuery("screenview"); - query.addQueryItem("cd", screenName); - query.addQueryItem("an", d->m_appName); - query.addQueryItem("av", d->m_appVersion); - appendCustomValues(query, customValues); - - d->enqueQueryWithCurrentTime(query); -} - -/** - * This method is called whenever a button was pressed in the application. - * A query for a POST message will be created to report this event. The - * created query will be stored in a message queue. - */ -void GAnalytics::sendEvent(const QString &category, const QString &action, const QString &label, const QVariant &value, const QVariantMap &customValues) -{ - QUrlQuery query = d->buildStandardPostQuery("event"); - query.addQueryItem("an", d->m_appName); - query.addQueryItem("av", d->m_appVersion); - query.addQueryItem("ec", category); - query.addQueryItem("ea", action); - if (!label.isEmpty()) - query.addQueryItem("el", label); - if (value.isValid()) - query.addQueryItem("ev", value.toString()); - - appendCustomValues(query, customValues); - - d->enqueQueryWithCurrentTime(query); -} - -/** - * Method is called after an exception was raised. It builds a - * query for a POST message. These query will be stored in a - * message queue. - */ -void GAnalytics::sendException(const QString &exceptionDescription, bool exceptionFatal, const QVariantMap &customValues) -{ - QUrlQuery query = d->buildStandardPostQuery("exception"); - query.addQueryItem("an", d->m_appName); - query.addQueryItem("av", d->m_appVersion); - - query.addQueryItem("exd", exceptionDescription); - - if (exceptionFatal) - { - query.addQueryItem("exf", "1"); - } - else - { - query.addQueryItem("exf", "0"); - } - appendCustomValues(query, customValues); - - d->enqueQueryWithCurrentTime(query); -} - -/** - * Session starts. This event will be sent by a POST message. - * Query is setup in this method and stored in the message - * queue. - */ -void GAnalytics::startSession() -{ - QVariantMap customValues; - customValues.insert("sc", "start"); - sendEvent("Session", "Start", QString(), QVariant(), customValues); -} - -/** - * Session ends. This event will be sent by a POST message. - * Query is setup in this method and stored in the message - * queue. - */ -void GAnalytics::endSession() -{ - QVariantMap customValues; - customValues.insert("sc", "end"); - sendEvent("Session", "End", QString(), QVariant(), customValues); -} - -/** - * Qut stream to persist class GAnalytics. - */ -QDataStream &operator<<(QDataStream &outStream, const GAnalytics &analytics) -{ - outStream << analytics.d->persistMessageQueue(); - - return outStream; -} - -/** - * In stream to read GAnalytics from file. - */ -QDataStream &operator>>(QDataStream &inStream, GAnalytics &analytics) -{ - QList dataList; - inStream >> dataList; - analytics.d->readMessagesFromFile(dataList); - - return inStream; -} diff --git a/libraries/ganalytics/src/ganalytics_worker.cpp b/libraries/ganalytics/src/ganalytics_worker.cpp deleted file mode 100644 index b0ae75a40..000000000 --- a/libraries/ganalytics/src/ganalytics_worker.cpp +++ /dev/null @@ -1,254 +0,0 @@ -#include "ganalytics.h" -#include "ganalytics_worker.h" -#include "sys.h" - -#include -#include -#include - -#include -#include - -const QLatin1String GAnalyticsWorker::dateTimeFormat("yyyy,MM,dd-hh:mm::ss:zzz"); - -GAnalyticsWorker::GAnalyticsWorker(GAnalytics *parent) - : QObject(parent), q(parent), m_logLevel(GAnalytics::Error) -{ - m_appName = QCoreApplication::instance()->applicationName(); - m_appVersion = QCoreApplication::instance()->applicationVersion(); - m_request.setUrl(QUrl("https://www.google-analytics.com/collect")); - m_request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); - m_request.setHeader(QNetworkRequest::UserAgentHeader, getUserAgent()); - - m_language = QLocale::system().name().toLower().replace("_", "-"); - m_screenResolution = getScreenResolution(); - - m_timer.setInterval(m_timerInterval); - connect(&m_timer, &QTimer::timeout, this, &GAnalyticsWorker::postMessage); -} - -void GAnalyticsWorker::enable(bool state) -{ - // state change to the same is not valid. - if(m_isEnabled == state) - { - return; - } - - m_isEnabled = state; - if(m_isEnabled) - { - // enable -> start doing things :) - m_timer.start(); - } - else - { - // disable -> stop the timer - m_timer.stop(); - } -} - -void GAnalyticsWorker::logMessage(GAnalytics::LogLevel level, const QString &message) -{ - if (m_logLevel > level) - { - return; - } - - qDebug() << "[Analytics]" << message; -} - -/** - * Build the POST query. Adds all parameter to the query - * which are used in every POST. - * @param type Type of POST message. The event which is to post. - * @return query Most used parameter in a query for a POST. - */ -QUrlQuery GAnalyticsWorker::buildStandardPostQuery(const QString &type) -{ - QUrlQuery query; - query.addQueryItem("v", "1"); - query.addQueryItem("tid", m_trackingID); - query.addQueryItem("cid", m_clientID); - if (!m_userID.isEmpty()) - { - query.addQueryItem("uid", m_userID); - } - query.addQueryItem("t", type); - query.addQueryItem("ul", m_language); - query.addQueryItem("vp", m_viewportSize); - query.addQueryItem("sr", m_screenResolution); - if(m_anonymizeIPs) - { - query.addQueryItem("aip", "1"); - } - return query; -} - -/** - * Get primary screen resolution. - * @return A QString like "800x600". - */ -QString GAnalyticsWorker::getScreenResolution() -{ - QScreen *screen = QGuiApplication::primaryScreen(); - QSize size = screen->size(); - - return QString("%1x%2").arg(size.width()).arg(size.height()); -} - -/** - * Try to gain information about the system where this application - * is running. It needs to get the name and version of the operating - * system, the language and screen resolution. - * All this information will be send in POST messages. - * @return agent A QString with all the information formatted for a POST message. - */ -QString GAnalyticsWorker::getUserAgent() -{ - return QString("%1/%2").arg(m_appName).arg(m_appVersion); -} - -/** - * The message queue contains a list of QueryBuffer object. - * QueryBuffer holds a QUrlQuery object and a QDateTime object. - * These both object are freed from the buffer object and - * inserted as QString objects in a QList. - * @return dataList The list with concartinated queue data. - */ -QList GAnalyticsWorker::persistMessageQueue() -{ - QList dataList; - foreach (QueryBuffer buffer, m_messageQueue) - { - dataList << buffer.postQuery.toString(); - dataList << buffer.time.toString(dateTimeFormat); - } - return dataList; -} - -/** - * Reads persistent messages from a file. - * Gets all message data as a QList. - * Two lines in the list build a QueryBuffer object. - */ -void GAnalyticsWorker::readMessagesFromFile(const QList &dataList) -{ - QListIterator iter(dataList); - while (iter.hasNext()) - { - QString queryString = iter.next(); - QString dateString = iter.next(); - QUrlQuery query; - query.setQuery(queryString); - QDateTime dateTime = QDateTime::fromString(dateString, dateTimeFormat); - QueryBuffer buffer; - buffer.postQuery = query; - buffer.time = dateTime; - m_messageQueue.enqueue(buffer); - } -} - -/** - * Takes a QUrlQuery object and wrapp it together with - * a QTime object into a QueryBuffer struct. These struct - * will be stored in the message queue. - */ -void GAnalyticsWorker::enqueQueryWithCurrentTime(const QUrlQuery &query) -{ - QueryBuffer buffer; - buffer.postQuery = query; - buffer.time = QDateTime::currentDateTime(); - - m_messageQueue.enqueue(buffer); -} - -/** - * This function is called by a timer interval. - * The function tries to send a messages from the queue. - * If message was successfully send then this function - * will be called back to send next message. - * If message queue contains more than one message then - * the connection will kept open. - * The message POST is asyncroniously when the server - * answered a signal will be emitted. - */ -void GAnalyticsWorker::postMessage() -{ - if (m_messageQueue.isEmpty()) - { - // queue empty -> try sending later - m_timer.start(); - return; - } - else - { - // queue has messages -> stop timer and start sending - m_timer.stop(); - } - - QString connection = "close"; - if (m_messageQueue.count() > 1) - { - connection = "keep-alive"; - } - - QueryBuffer buffer = m_messageQueue.head(); - QDateTime sendTime = QDateTime::currentDateTime(); - qint64 timeDiff = buffer.time.msecsTo(sendTime); - - if (timeDiff > fourHours) - { - // too old. - m_messageQueue.dequeue(); - emit postMessage(); - return; - } - - buffer.postQuery.addQueryItem("qt", QString::number(timeDiff)); - m_request.setRawHeader("Connection", connection.toUtf8()); - m_request.setHeader(QNetworkRequest::ContentLengthHeader, buffer.postQuery.toString().length()); - - logMessage(GAnalytics::Debug, "Query string = " + buffer.postQuery.toString()); - - // Create a new network access manager if we don't have one yet - if (networkManager == NULL) - { - networkManager = new QNetworkAccessManager(this); - } - - QNetworkReply *reply = networkManager->post(m_request, buffer.postQuery.query(QUrl::EncodeUnicode).toUtf8()); - connect(reply, SIGNAL(finished()), this, SLOT(postMessageFinished())); -} - -/** - * NetworkAccsessManager has finished to POST a message. - * If POST message was successfully send then the message - * query should be removed from queue. - * SIGNAL "postMessage" will be emitted to send next message - * if there is any. - * If message couldn't be send then next try is when the - * timer emits its signal. - */ -void GAnalyticsWorker::postMessageFinished() -{ - QNetworkReply *reply = qobject_cast(sender()); - - int httpStausCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - if (httpStausCode < 200 || httpStausCode > 299) - { - logMessage(GAnalytics::Error, QString("Error posting message: %1").arg(reply->errorString())); - - // An error ocurred. Try sending later. - m_timer.start(); - return; - } - else - { - logMessage(GAnalytics::Debug, "Message sent"); - } - - m_messageQueue.dequeue(); - postMessage(); - reply->deleteLater(); -} diff --git a/libraries/ganalytics/src/ganalytics_worker.h b/libraries/ganalytics/src/ganalytics_worker.h deleted file mode 100644 index 1962f7998..000000000 --- a/libraries/ganalytics/src/ganalytics_worker.h +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -struct QueryBuffer -{ - QUrlQuery postQuery; - QDateTime time; -}; - -class GAnalyticsWorker : public QObject -{ - Q_OBJECT - -public: - explicit GAnalyticsWorker(GAnalytics *parent = 0); - - GAnalytics *q; - - QNetworkAccessManager *networkManager = nullptr; - - QQueue m_messageQueue; - QTimer m_timer; - QNetworkRequest m_request; - GAnalytics::LogLevel m_logLevel; - - QString m_trackingID; - QString m_clientID; - QString m_userID; - QString m_appName; - QString m_appVersion; - QString m_language; - QString m_screenResolution; - QString m_viewportSize; - - bool m_anonymizeIPs = false; - bool m_isEnabled = false; - int m_timerInterval = 30000; - int m_version = 0; - - const static int fourHours = 4 * 60 * 60 * 1000; - const static QLatin1String dateTimeFormat; - -public: - void logMessage(GAnalytics::LogLevel level, const QString &message); - - QUrlQuery buildStandardPostQuery(const QString &type); - QString getScreenResolution(); - QString getUserAgent(); - QList persistMessageQueue(); - void readMessagesFromFile(const QList &dataList); - - void enqueQueryWithCurrentTime(const QUrlQuery &query); - void setIsSending(bool doSend); - void enable(bool state); - -public slots: - void postMessage(); - void postMessageFinished(); -}; -