Completely remove Google Analytics library
This commit is contained in:
parent
af76cf59b6
commit
f25a9bc103
@ -78,9 +78,6 @@ set(Launcher_PASTE_EE_API_KEY "utLvciUouSURFzfjPxLBf5W4ISsUX4pwBDF7N1AfZ" CACHE
|
|||||||
# Imgur API Client ID
|
# Imgur API Client ID
|
||||||
set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can get from Imgur when you register an application")
|
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
|
# 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")
|
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})
|
set(NBT_DEST_DIR ${LIBRARY_DEST_DIR})
|
||||||
add_subdirectory(libraries/libnbtplusplus)
|
add_subdirectory(libraries/libnbtplusplus)
|
||||||
|
|
||||||
add_subdirectory(libraries/ganalytics) # google analytics library
|
|
||||||
add_subdirectory(libraries/systeminfo) # system information library
|
add_subdirectory(libraries/systeminfo) # system information library
|
||||||
add_subdirectory(libraries/hoedown) # markdown parser
|
add_subdirectory(libraries/hoedown) # markdown parser
|
||||||
add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
|
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/rainbow) # Qt extension for colors
|
||||||
add_subdirectory(libraries/iconfix) # fork of Qt's QIcon loader
|
add_subdirectory(libraries/iconfix) # fork of Qt's QIcon loader
|
||||||
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions
|
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/optional-bare)
|
||||||
add_subdirectory(libraries/tomlc99) # toml parser
|
add_subdirectory(libraries/tomlc99) # toml parser
|
||||||
add_subdirectory(libraries/katabasis) # An OAuth2 library that tried to do too much
|
add_subdirectory(libraries/katabasis) # An OAuth2 library that tried to do too much
|
||||||
|
@ -24,7 +24,6 @@ Config::Config()
|
|||||||
|
|
||||||
BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@";
|
BUILD_PLATFORM = "@Launcher_BUILD_PLATFORM@";
|
||||||
UPDATER_BASE = "@Launcher_UPDATER_BASE@";
|
UPDATER_BASE = "@Launcher_UPDATER_BASE@";
|
||||||
ANALYTICS_ID = "@Launcher_ANALYTICS_ID@";
|
|
||||||
NOTIFICATION_URL = "@Launcher_NOTIFICATION_URL@";
|
NOTIFICATION_URL = "@Launcher_NOTIFICATION_URL@";
|
||||||
FULL_VERSION_STR = "@Launcher_VERSION_MAJOR@.@Launcher_VERSION_MINOR@.@Launcher_VERSION_BUILD@";
|
FULL_VERSION_STR = "@Launcher_VERSION_MAJOR@.@Launcher_VERSION_MINOR@.@Launcher_VERSION_BUILD@";
|
||||||
|
|
||||||
|
@ -46,9 +46,6 @@ public:
|
|||||||
QString USER_AGENT_UNCACHED;
|
QString USER_AGENT_UNCACHED;
|
||||||
|
|
||||||
|
|
||||||
/// Google analytics ID
|
|
||||||
QString ANALYTICS_ID;
|
|
||||||
|
|
||||||
/// URL for notifications
|
/// URL for notifications
|
||||||
QString NOTIFICATION_URL;
|
QString NOTIFICATION_URL;
|
||||||
|
|
||||||
@ -79,7 +76,7 @@ public:
|
|||||||
* Client ID you can get from Imgur when you register an application
|
* Client ID you can get from Imgur when you register an application
|
||||||
*/
|
*/
|
||||||
QString IMGUR_CLIENT_ID;
|
QString IMGUR_CLIENT_ID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client ID you can get from Microsoft Identity Platform when you register an application
|
* Client ID you can get from Microsoft Identity Platform when you register an application
|
||||||
*/
|
*/
|
||||||
@ -115,3 +112,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern const Config BuildConfig;
|
extern const Config BuildConfig;
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include "ui/setupwizard/SetupWizard.h"
|
#include "ui/setupwizard/SetupWizard.h"
|
||||||
#include "ui/setupwizard/LanguageWizardPage.h"
|
#include "ui/setupwizard/LanguageWizardPage.h"
|
||||||
#include "ui/setupwizard/JavaWizardPage.h"
|
#include "ui/setupwizard/JavaWizardPage.h"
|
||||||
#include "ui/setupwizard/AnalyticsWizardPage.h"
|
|
||||||
|
|
||||||
#include "ui/dialogs/CustomMessageBox.h"
|
#include "ui/dialogs/CustomMessageBox.h"
|
||||||
|
|
||||||
@ -73,7 +72,6 @@
|
|||||||
#include <DesktopServices.h>
|
#include <DesktopServices.h>
|
||||||
#include <LocalPeer.h>
|
#include <LocalPeer.h>
|
||||||
|
|
||||||
#include <ganalytics.h>
|
|
||||||
#include <sys.h>
|
#include <sys.h>
|
||||||
|
|
||||||
|
|
||||||
@ -719,14 +717,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
// paste.ee API key
|
// paste.ee API key
|
||||||
m_settings->registerSetting("PasteEEAPIKey", "multimc");
|
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
|
// Init page provider
|
||||||
{
|
{
|
||||||
m_globalSettingsProvider = std::make_shared<GenericPageProvider>(tr("Settings"));
|
m_globalSettingsProvider = std::make_shared<GenericPageProvider>(tr("Settings"));
|
||||||
@ -908,46 +898,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
|||||||
qDebug() << "<> Application theme set.";
|
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())
|
if(createSetupWizard())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -974,29 +924,13 @@ bool Application::createSetupWizard()
|
|||||||
}
|
}
|
||||||
return false;
|
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 = [&]()
|
bool languageRequired = [&]()
|
||||||
{
|
{
|
||||||
if (settings()->get("Language").toString().isEmpty())
|
if (settings()->get("Language").toString().isEmpty())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}();
|
}();
|
||||||
bool wizardRequired = javaRequired || analyticsRequired || languageRequired;
|
bool wizardRequired = javaRequired || languageRequired;
|
||||||
|
|
||||||
if(wizardRequired)
|
if(wizardRequired)
|
||||||
{
|
{
|
||||||
@ -1009,10 +943,6 @@ bool Application::createSetupWizard()
|
|||||||
{
|
{
|
||||||
m_setupWizard->addPage(new JavaWizardPage(m_setupWizard));
|
m_setupWizard->addPage(new JavaWizardPage(m_setupWizard));
|
||||||
}
|
}
|
||||||
if(analyticsRequired)
|
|
||||||
{
|
|
||||||
m_setupWizard->addPage(new AnalyticsWizardPage(m_setupWizard));
|
|
||||||
}
|
|
||||||
connect(m_setupWizard, &QDialog::finished, this, &Application::setupWizardFinished);
|
connect(m_setupWizard, &QDialog::finished, this, &Application::setupWizardFinished);
|
||||||
m_setupWizard->show();
|
m_setupWizard->show();
|
||||||
return true;
|
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<TranslationsModel> Application::translations()
|
std::shared_ptr<TranslationsModel> Application::translations()
|
||||||
{
|
{
|
||||||
return m_translations;
|
return m_translations;
|
||||||
@ -1454,60 +1368,6 @@ MainWindow* Application::showMainWindow(bool minimized)
|
|||||||
connect(m_mainWindow, &MainWindow::isClosing, this, &Application::on_windowClose);
|
connect(m_mainWindow, &MainWindow::isClosing, this, &Application::on_windowClose);
|
||||||
m_openWindows++;
|
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;
|
return m_mainWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ class BaseDetachedToolFactory;
|
|||||||
class TranslationsModel;
|
class TranslationsModel;
|
||||||
class ITheme;
|
class ITheme;
|
||||||
class MCEditTool;
|
class MCEditTool;
|
||||||
class GAnalytics;
|
|
||||||
|
|
||||||
namespace Meta {
|
namespace Meta {
|
||||||
class Index;
|
class Index;
|
||||||
@ -60,10 +59,6 @@ public:
|
|||||||
Application(int &argc, char **argv);
|
Application(int &argc, char **argv);
|
||||||
virtual ~Application();
|
virtual ~Application();
|
||||||
|
|
||||||
GAnalytics *analytics() const {
|
|
||||||
return m_analytics;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<SettingsObject> settings() const {
|
std::shared_ptr<SettingsObject> settings() const {
|
||||||
return m_settings;
|
return m_settings;
|
||||||
}
|
}
|
||||||
@ -161,7 +156,6 @@ private slots:
|
|||||||
void messageReceived(const QByteArray & message);
|
void messageReceived(const QByteArray & message);
|
||||||
void controllerSucceeded();
|
void controllerSucceeded();
|
||||||
void controllerFailed(const QString & error);
|
void controllerFailed(const QString & error);
|
||||||
void analyticsSettingChanged(const Setting &setting, QVariant value);
|
|
||||||
void setupWizardFinished(int status);
|
void setupWizardFinished(int status);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -226,7 +220,6 @@ private:
|
|||||||
// peer launcher instance connector - used to implement single instance launcher and signalling
|
// peer launcher instance connector - used to implement single instance launcher and signalling
|
||||||
LocalPeer * m_peerInstance = nullptr;
|
LocalPeer * m_peerInstance = nullptr;
|
||||||
|
|
||||||
GAnalytics * m_analytics = nullptr;
|
|
||||||
SetupWizard * m_setupWizard = nullptr;
|
SetupWizard * m_setupWizard = nullptr;
|
||||||
public:
|
public:
|
||||||
QString m_instanceIdToLaunch;
|
QString m_instanceIdToLaunch;
|
||||||
@ -236,3 +229,4 @@ public:
|
|||||||
QUrl m_zipToImport;
|
QUrl m_zipToImport;
|
||||||
std::unique_ptr<QFile> logFile;
|
std::unique_ptr<QFile> logFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -627,8 +627,6 @@ SET(LAUNCHER_SOURCES
|
|||||||
# GUI - setup wizard
|
# GUI - setup wizard
|
||||||
ui/setupwizard/SetupWizard.h
|
ui/setupwizard/SetupWizard.h
|
||||||
ui/setupwizard/SetupWizard.cpp
|
ui/setupwizard/SetupWizard.cpp
|
||||||
ui/setupwizard/AnalyticsWizardPage.cpp
|
|
||||||
ui/setupwizard/AnalyticsWizardPage.h
|
|
||||||
ui/setupwizard/BaseWizardPage.h
|
ui/setupwizard/BaseWizardPage.h
|
||||||
ui/setupwizard/JavaWizardPage.cpp
|
ui/setupwizard/JavaWizardPage.cpp
|
||||||
ui/setupwizard/JavaWizardPage.h
|
ui/setupwizard/JavaWizardPage.h
|
||||||
@ -932,7 +930,6 @@ target_link_libraries(Launcher_logic
|
|||||||
hoedown
|
hoedown
|
||||||
Launcher_rainbow
|
Launcher_rainbow
|
||||||
LocalPeer
|
LocalPeer
|
||||||
ganalytics
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(Launcher_logic)
|
target_link_libraries(Launcher_logic)
|
||||||
|
@ -73,11 +73,6 @@ LauncherPage::LauncherPage(QWidget *parent) : QWidget(parent), ui(new Ui::Launch
|
|||||||
{
|
{
|
||||||
ui->updateSettingsBox->setHidden(true);
|
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->fontSizeBox, SIGNAL(valueChanged(int)), SLOT(refreshFontPreview()));
|
||||||
connect(ui->consoleFont, SIGNAL(currentFontChanged(QFont)), SLOT(refreshFontPreview()));
|
connect(ui->consoleFont, SIGNAL(currentFontChanged(QFont)), SLOT(refreshFontPreview()));
|
||||||
|
|
||||||
@ -321,12 +316,6 @@ void LauncherPage::applySettings()
|
|||||||
s->set("InstSortMode", "Name");
|
s->set("InstSortMode", "Name");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analytics
|
|
||||||
if(!BuildConfig.ANALYTICS_ID.isEmpty())
|
|
||||||
{
|
|
||||||
s->set("Analytics", ui->analyticsCheck->isChecked());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void LauncherPage::loadSettings()
|
void LauncherPage::loadSettings()
|
||||||
{
|
{
|
||||||
@ -422,12 +411,6 @@ void LauncherPage::loadSettings()
|
|||||||
{
|
{
|
||||||
ui->sortByNameBtn->setChecked(true);
|
ui->sortByNameBtn->setChecked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analytics
|
|
||||||
if(!BuildConfig.ANALYTICS_ID.isEmpty())
|
|
||||||
{
|
|
||||||
ui->analyticsCheck->setChecked(s->get("Analytics").toBool());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherPage::refreshFontPreview()
|
void LauncherPage::refreshFontPreview()
|
||||||
|
@ -485,69 +485,6 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="analyticsTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Analytics</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="consoleSettingsBox_2">
|
|
||||||
<property name="title">
|
|
||||||
<string>Analytics Settings</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="analyticsCheck">
|
|
||||||
<property name="text">
|
|
||||||
<string>Send anonymous usage statistics?</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string><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></string>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</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>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
#include "AnalyticsWizardPage.h"
|
|
||||||
#include <Application.h>
|
|
||||||
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QTextBrowser>
|
|
||||||
#include <QCheckBox>
|
|
||||||
|
|
||||||
#include <ganalytics.h>
|
|
||||||
#include <BuildConfig.h>
|
|
||||||
|
|
||||||
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(
|
|
||||||
"<html><body>"
|
|
||||||
"<p>The launcher sends anonymous usage statistics on every start of the application. This helps us decide what platforms and issues to focus on.</p>"
|
|
||||||
"<p>The data is processed by Google Analytics, see their <a href=\"https://support.google.com/analytics/answer/6004245?hl=en\">article on the "
|
|
||||||
"matter</a>.</p>"
|
|
||||||
"<p>The following data is collected:</p>"
|
|
||||||
"<ul><li>A random unique ID of the installation.<br />It is stored in the application settings file.</li>"
|
|
||||||
"<li>Anonymized (partial) IP address.</li>"
|
|
||||||
"<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>"
|
|
||||||
"<p>If we change the tracked information, you will see this page again.</p></body></html>"));
|
|
||||||
checkBox->setText(tr("Enable Analytics"));
|
|
||||||
}
|
|
@ -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;
|
|
||||||
};
|
|
@ -2,12 +2,10 @@
|
|||||||
|
|
||||||
#include "LanguageWizardPage.h"
|
#include "LanguageWizardPage.h"
|
||||||
#include "JavaWizardPage.h"
|
#include "JavaWizardPage.h"
|
||||||
#include "AnalyticsWizardPage.h"
|
|
||||||
|
|
||||||
#include "translations/TranslationsModel.h"
|
#include "translations/TranslationsModel.h"
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <FileSystem.h>
|
#include <FileSystem.h>
|
||||||
#include <ganalytics.h>
|
|
||||||
|
|
||||||
#include <QAbstractButton>
|
#include <QAbstractButton>
|
||||||
#include <BuildConfig.h>
|
#include <BuildConfig.h>
|
||||||
|
@ -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.
|
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
|
||||||
Hoedown is a revived fork of Sundown, the Markdown parser based on the original code of the Upskirt library by Natacha Porté.
|
Hoedown is a revived fork of Sundown, the Markdown parser based on the original code of the Upskirt library by Natacha Porté.
|
||||||
|
|
||||||
|
@ -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)
|
|
@ -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.
|
|
@ -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<GAnalytics>("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.
|
|
@ -1,67 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QVariantMap>
|
|
||||||
|
|
||||||
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);
|
|
@ -1,237 +0,0 @@
|
|||||||
#include "ganalytics.h"
|
|
||||||
#include "ganalytics_worker.h"
|
|
||||||
#include "sys.h"
|
|
||||||
|
|
||||||
#include <QDataStream>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QLocale>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QNetworkRequest>
|
|
||||||
#include <QQueue>
|
|
||||||
#include <QSettings>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QUrlQuery>
|
|
||||||
#include <QUuid>
|
|
||||||
|
|
||||||
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<QString> dataList;
|
|
||||||
inStream >> dataList;
|
|
||||||
analytics.d->readMessagesFromFile(dataList);
|
|
||||||
|
|
||||||
return inStream;
|
|
||||||
}
|
|
@ -1,254 +0,0 @@
|
|||||||
#include "ganalytics.h"
|
|
||||||
#include "ganalytics_worker.h"
|
|
||||||
#include "sys.h"
|
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QNetworkReply>
|
|
||||||
|
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QScreen>
|
|
||||||
|
|
||||||
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<QString> GAnalyticsWorker::persistMessageQueue()
|
|
||||||
{
|
|
||||||
QList<QString> 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<QString>.
|
|
||||||
* Two lines in the list build a QueryBuffer object.
|
|
||||||
*/
|
|
||||||
void GAnalyticsWorker::readMessagesFromFile(const QList<QString> &dataList)
|
|
||||||
{
|
|
||||||
QListIterator<QString> 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<QNetworkReply *>(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();
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QUrlQuery>
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QNetworkRequest>
|
|
||||||
#include <QQueue>
|
|
||||||
|
|
||||||
struct QueryBuffer
|
|
||||||
{
|
|
||||||
QUrlQuery postQuery;
|
|
||||||
QDateTime time;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GAnalyticsWorker : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit GAnalyticsWorker(GAnalytics *parent = 0);
|
|
||||||
|
|
||||||
GAnalytics *q;
|
|
||||||
|
|
||||||
QNetworkAccessManager *networkManager = nullptr;
|
|
||||||
|
|
||||||
QQueue<QueryBuffer> 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<QString> persistMessageQueue();
|
|
||||||
void readMessagesFromFile(const QList<QString> &dataList);
|
|
||||||
|
|
||||||
void enqueQueryWithCurrentTime(const QUrlQuery &query);
|
|
||||||
void setIsSending(bool doSend);
|
|
||||||
void enable(bool state);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void postMessage();
|
|
||||||
void postMessageFinished();
|
|
||||||
};
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user