System to collect usage statistic.
This commit is contained in:
parent
53dc4135e3
commit
eaf9d65339
|
@ -22,7 +22,8 @@ DEPENDPATH += \
|
|||
../../src/libs/vtools \
|
||||
../../src/libs/vformat \
|
||||
../../src/libs/fervor \
|
||||
../../src/libs/vwidgets
|
||||
../../src/libs/vwidgets \
|
||||
../../src/libs/vganalytics
|
||||
|
||||
include(../../src/app/valentina/valentina.pri)
|
||||
include(../../src/app/tape/tape.pri)
|
||||
|
@ -39,6 +40,7 @@ include(../../src/libs/vtools/vtools.pri)
|
|||
include(../../src/libs/vformat/vformat.pri)
|
||||
include(../../src/libs/fervor/fervor.pri)
|
||||
include(../../src/libs/vwidgets/vwidgets.pri)
|
||||
include(../../src/libs/vganalytics/vganalytics.pri)
|
||||
|
||||
# Add here path to new translation file with name "valentina_*_*.ts" if you want to add new language.
|
||||
# Same paths in variable INSTALL_TRANSLATIONS (translations.pri).
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include "../vmisc/backport/qoverload.h"
|
||||
#endif // QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
|
||||
|
||||
#include "../vganalytics/vganalytics.h"
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
PuzzlePreferencesConfigurationPage::PuzzlePreferencesConfigurationPage(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
|
@ -89,6 +91,9 @@ PuzzlePreferencesConfigurationPage::PuzzlePreferencesConfigurationPage(QWidget *
|
|||
ui->doubleSpinBoxAcceleration->setMinimum(VCommonSettings::scrollingAccelerationMin);
|
||||
ui->doubleSpinBoxAcceleration->setMaximum(VCommonSettings::scrollingAccelerationMax);
|
||||
ui->doubleSpinBoxAcceleration->setValue(settings->GetScrollingAcceleration());
|
||||
|
||||
// Tab Privacy
|
||||
ui->checkBoxSendUsageStatistics->setChecked(settings->IsCollectStatistic());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -166,6 +171,10 @@ auto PuzzlePreferencesConfigurationPage::Apply() -> QStringList
|
|||
settings->SetWheelMouseScale(ui->doubleSpinBoxWheel->value());
|
||||
settings->SetScrollingAcceleration(ui->doubleSpinBoxAcceleration->value());
|
||||
|
||||
// Tab Privacy
|
||||
settings->SetCollectStatistic(ui->checkBoxSendUsageStatistics->isChecked());
|
||||
VGAnalytics::Instance()->Enable(ui->checkBoxSendUsageStatistics->isChecked());
|
||||
|
||||
return preferences;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>545</width>
|
||||
<height>696</height>
|
||||
<width>539</width>
|
||||
<height>702</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -34,8 +34,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>503</width>
|
||||
<height>627</height>
|
||||
<width>497</width>
|
||||
<height>633</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
|
@ -424,6 +424,43 @@ This option will take an affect after restart.</string>
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabPrivacy">
|
||||
<attribute name="title">
|
||||
<string>Privacy</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxSendUsageStatistics">
|
||||
<property name="text">
|
||||
<string>Send usage statistics</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Please help to improve Valentina's quality by automatically sending usage statistics. Sent data contains <span style=" font-weight:700;">no potentially sensitive information</span> like user names, email addresses, file contents or file paths.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>540</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -282,6 +282,15 @@ DEPENDPATH += $$PWD/../../libs/vdxf
|
|||
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vdxf/$${DESTDIR}/vdxf.lib
|
||||
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vdxf/$${DESTDIR}/libvdxf.a
|
||||
|
||||
# VGAnalytics static library
|
||||
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vganalytics/$${DESTDIR}/ -lvganalytics
|
||||
|
||||
INCLUDEPATH += $$PWD/../../libs/vganalytics
|
||||
DEPENDPATH += $$PWD/../../libs/vganalytics
|
||||
|
||||
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vganalytics/$${DESTDIR}/vganalytics.lib
|
||||
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vganalytics/$${DESTDIR}/libvganalytics.a
|
||||
|
||||
# QMuParser library
|
||||
win32:CONFIG(release, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2
|
||||
|
|
|
@ -12,6 +12,7 @@ VToolApp {
|
|||
Depends { name: "VWidgetsLib" }
|
||||
Depends { name: "FervorLib" }
|
||||
Depends { name: "multibundle"; }
|
||||
Depends { name: "VGAnalyticsLib" }
|
||||
|
||||
name: "Puzzle"
|
||||
buildconfig.appTarget: qbs.targetOS.contains("macos") ? "Puzzle" : "puzzle"
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "../ifc/exception/vexceptionemptyparameter.h"
|
||||
#include "../ifc/exception/vexceptionobjecterror.h"
|
||||
#include "../ifc/exception/vexceptionwrongid.h"
|
||||
#include "../vganalytics/def.h"
|
||||
#include "../vganalytics/vganalytics.h"
|
||||
#include "../vmisc/vsysexits.h"
|
||||
#include "version.h"
|
||||
#include "vpmainwindow.h"
|
||||
|
@ -277,6 +279,17 @@ VPApplication::VPApplication(int &argc, char **argv)
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
VPApplication::~VPApplication()
|
||||
{
|
||||
if (settings->IsCollectStatistic())
|
||||
{
|
||||
auto *statistic = VGAnalytics::Instance();
|
||||
|
||||
QString clientID = settings->GetClientID();
|
||||
if (!clientID.isEmpty())
|
||||
{
|
||||
statistic->SendAppCloseEvent(m_uptimeTimer.elapsed());
|
||||
}
|
||||
}
|
||||
|
||||
qDeleteAll(m_mainWindows);
|
||||
}
|
||||
|
||||
|
@ -430,6 +443,19 @@ void VPApplication::InitOptions()
|
|||
QIcon::setThemeName(QStringLiteral("win.icon.theme"));
|
||||
}
|
||||
ActivateDarkMode();
|
||||
|
||||
auto *statistic = VGAnalytics::Instance();
|
||||
QString clientID = settings->GetClientID();
|
||||
if (clientID.isEmpty())
|
||||
{
|
||||
clientID = QUuid::createUuid().toString();
|
||||
settings->SetClientID(clientID);
|
||||
}
|
||||
statistic->SetClientID(clientID);
|
||||
statistic->SetGUILanguage(settings->GetLocale());
|
||||
statistic->SetMeasurementId(GA_MEASUREMENT_ID);
|
||||
statistic->SetApiSecret(GA_API_SECRET);
|
||||
statistic->Enable(settings->IsCollectStatistic());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "../vlayout/vlayoutexporter.h"
|
||||
#include "../vlayout/vprintlayout.h"
|
||||
#include "../vlayout/vrawlayout.h"
|
||||
#include "../vmisc/dialogs/dialogaskcollectstatistic.h"
|
||||
#include "../vmisc/dialogs/dialogselectlanguage.h"
|
||||
#include "../vmisc/lambdaconstants.h"
|
||||
#include "../vmisc/projectversion.h"
|
||||
|
@ -67,6 +68,7 @@
|
|||
#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
|
||||
#include "../vmisc/backport/qoverload.h"
|
||||
#endif // QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
|
||||
#include "../vganalytics/vganalytics.h"
|
||||
#include "layout/vppiece.h"
|
||||
#include "vptilefactory.h"
|
||||
|
||||
|
@ -389,7 +391,7 @@ VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent)
|
|||
|
||||
if (m_cmd->IsGuiEnabled())
|
||||
{
|
||||
QTimer::singleShot(V_SECONDS(1), this, &VPMainWindow::SetDefaultGUILanguage);
|
||||
QTimer::singleShot(V_SECONDS(1), this, &VPMainWindow::AskDefaultSettings);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4536,7 +4538,7 @@ void VPMainWindow::RemoveWatermark()
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPMainWindow::SetDefaultGUILanguage()
|
||||
void VPMainWindow::AskDefaultSettings()
|
||||
{
|
||||
if (m_cmd->IsGuiEnabled())
|
||||
{
|
||||
|
@ -4554,6 +4556,38 @@ void VPMainWindow::SetDefaultGUILanguage()
|
|||
VAbstractApplication::VApp()->LoadTranslation(locale);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings->IsAskCollectStatistic())
|
||||
{
|
||||
DialogAskCollectStatistic dialog(this);
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
settings->SetCollectStatistic(dialog.CollectStatistic());
|
||||
}
|
||||
|
||||
settings->SetAskCollectStatistic(false);
|
||||
}
|
||||
|
||||
if (settings->IsCollectStatistic())
|
||||
{
|
||||
auto *statistic = VGAnalytics::Instance();
|
||||
statistic->SetGUILanguage(settings->GetLocale());
|
||||
|
||||
QString clientID = settings->GetClientID();
|
||||
bool freshID = false;
|
||||
if (clientID.isEmpty())
|
||||
{
|
||||
clientID = QUuid::createUuid().toString();
|
||||
settings->SetClientID(clientID);
|
||||
statistic->SetClientID(clientID);
|
||||
freshID = true;
|
||||
}
|
||||
|
||||
statistic->Enable(true);
|
||||
|
||||
const qint64 uptime = VPApplication::VApp()->AppUptime();
|
||||
freshID ? statistic->SendAppFreshInstallEvent(uptime) : statistic->SendAppStartEvent(uptime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -286,7 +286,7 @@ private slots:
|
|||
void AboutToShowDockMenu();
|
||||
#endif //defined(Q_OS_MAC)
|
||||
|
||||
void SetDefaultGUILanguage();
|
||||
void AskDefaultSettings();
|
||||
|
||||
void HorizontalScaleChanged(double value);
|
||||
void VerticalScaleChanged(double value);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "../vmisc/backport/qoverload.h"
|
||||
#endif // QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
|
||||
#include "../qmuparser/qmudef.h"
|
||||
#include "../vganalytics/vganalytics.h"
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
TapePreferencesConfigurationPage::TapePreferencesConfigurationPage(QWidget *parent)
|
||||
|
@ -53,13 +54,13 @@ TapePreferencesConfigurationPage::TapePreferencesConfigurationPage(QWidget *pare
|
|||
VTapeSettings *settings = MApplication::VApp()->TapeSettings();
|
||||
|
||||
//-------------------- Decimal separator setup
|
||||
ui->osOptionCheck->setChecked(MApplication::VApp()->TapeSettings()->GetOsSeparator());
|
||||
ui->osOptionCheck->setChecked(settings->GetOsSeparator());
|
||||
|
||||
// Theme
|
||||
ui->darkModeCheck->setChecked(MApplication::VApp()->TapeSettings()->GetDarkMode());
|
||||
ui->darkModeCheck->setChecked(settings->GetDarkMode());
|
||||
|
||||
// Native dialogs
|
||||
ui->checkBoxDontUseNativeDialog->setChecked(MApplication::VApp()->TapeSettings()->IsDontUseNativeDialog());
|
||||
ui->checkBoxDontUseNativeDialog->setChecked(settings->IsDontUseNativeDialog());
|
||||
|
||||
//---------------------- Pattern making system
|
||||
ui->systemBookValueLabel->setFixedHeight(4 * QFontMetrics(ui->systemBookValueLabel->font()).lineSpacing());
|
||||
|
@ -77,7 +78,7 @@ TapePreferencesConfigurationPage::TapePreferencesConfigurationPage(QWidget *pare
|
|||
});
|
||||
|
||||
// set default pattern making system
|
||||
int index = ui->systemCombo->findData(MApplication::VApp()->TapeSettings()->GetPMSystemCode());
|
||||
int index = ui->systemCombo->findData(settings->GetPMSystemCode());
|
||||
if (index != -1)
|
||||
{
|
||||
ui->systemCombo->setCurrentIndex(index);
|
||||
|
@ -88,11 +89,13 @@ TapePreferencesConfigurationPage::TapePreferencesConfigurationPage(QWidget *pare
|
|||
[]() { MApplication::VApp()->TapeSettings()->SetConfirmFormatRewriting(true); });
|
||||
|
||||
//----------------------- Toolbar
|
||||
ui->toolBarStyleCheck->setChecked(MApplication::VApp()->TapeSettings()->GetToolBarStyle());
|
||||
ui->toolBarStyleCheck->setChecked(settings->GetToolBarStyle());
|
||||
|
||||
//----------------------- Update
|
||||
ui->checkBoxAutomaticallyCheckUpdates->setChecked(
|
||||
MApplication::VApp()->TapeSettings()->IsAutomaticallyCheckUpdates());
|
||||
ui->checkBoxAutomaticallyCheckUpdates->setChecked(settings->IsAutomaticallyCheckUpdates());
|
||||
|
||||
// Tab Privacy
|
||||
ui->checkBoxSendUsageStatistics->setChecked(settings->IsCollectStatistic());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -144,6 +147,10 @@ auto TapePreferencesConfigurationPage::Apply() -> QStringList
|
|||
settings->SetAutomaticallyCheckUpdates(ui->checkBoxAutomaticallyCheckUpdates->isChecked());
|
||||
}
|
||||
|
||||
// Tab Privacy
|
||||
settings->SetCollectStatistic(ui->checkBoxSendUsageStatistics->isChecked());
|
||||
VGAnalytics::Instance()->Enable(ui->checkBoxSendUsageStatistics->isChecked());
|
||||
|
||||
return preferences;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,209 +6,260 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>544</width>
|
||||
<height>636</height>
|
||||
<width>564</width>
|
||||
<height>686</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Configuration</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>524</width>
|
||||
<height>616</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<widget class="QWidget" name="tabGeneral">
|
||||
<attribute name="title">
|
||||
<string>General</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Language</string>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>522</width>
|
||||
<height>617</height>
|
||||
</rect>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>GUI language:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="langCombo"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Decimal separator parts:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="osOptionCheck">
|
||||
<property name="text">
|
||||
<string notr="true">< With OS options ></string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Language</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>GUI language:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="langCombo"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Decimal separator parts:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="osOptionCheck">
|
||||
<property name="text">
|
||||
<string notr="true">< With OS options ></string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Pattern making system</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Pattern making system:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="systemCombo"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Author:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="systemAuthorValueLabel">
|
||||
<property name="text">
|
||||
<string notr="true">author</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Book:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPlainTextEdit" name="systemBookValueLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Measurements editing</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="resetWarningsButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reset warnings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="title">
|
||||
<string>Toolbar</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="toolBarStyleCheck">
|
||||
<property name="text">
|
||||
<string>The text appears under the icon (recommended for beginners).</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>User Interface</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="darkModeCheck">
|
||||
<property name="text">
|
||||
<string>Activate dark mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxDontUseNativeDialog">
|
||||
<property name="text">
|
||||
<string>Don't use the native file dialog</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_9">
|
||||
<property name="title">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxAutomaticallyCheckUpdates">
|
||||
<property name="toolTip">
|
||||
<string>Automatically check for updates each time the application starts</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Automatically check for updates</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabPrivacy">
|
||||
<attribute name="title">
|
||||
<string>Privacy</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxSendUsageStatistics">
|
||||
<property name="text">
|
||||
<string>Send usage statistics</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Pattern making system</string>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Please help to improve Valentina's quality by automatically sending usage statistics. Sent data contains <span style=" font-weight:700;">no potentially sensitive information</span> like user names, email addresses, file contents or file paths.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Pattern making system:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="systemCombo"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Author:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="systemAuthorValueLabel">
|
||||
<property name="text">
|
||||
<string notr="true">author</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Book:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPlainTextEdit" name="systemBookValueLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Measurements editing</string>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="resetWarningsButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reset warnings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="title">
|
||||
<string>Toolbar</string>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>530</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="toolBarStyleCheck">
|
||||
<property name="text">
|
||||
<string>The text appears under the icon (recommended for beginners).</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>User Interface</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="darkModeCheck">
|
||||
<property name="text">
|
||||
<string>Activate dark mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxDontUseNativeDialog">
|
||||
<property name="text">
|
||||
<string>Don't use the native file dialog</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_9">
|
||||
<property name="title">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxAutomaticallyCheckUpdates">
|
||||
<property name="toolTip">
|
||||
<string>Automatically check for updates each time the application starts</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Automatically check for updates</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "../ifc/exception/vexceptionemptyparameter.h"
|
||||
#include "../ifc/exception/vexceptionobjecterror.h"
|
||||
#include "../ifc/exception/vexceptionwrongid.h"
|
||||
#include "../vganalytics/def.h"
|
||||
#include "../vganalytics/vganalytics.h"
|
||||
#include "../vmisc/projectversion.h"
|
||||
#include "../vmisc/vsysexits.h"
|
||||
#include "tmainwindow.h"
|
||||
|
@ -77,6 +79,7 @@ Q_LOGGING_CATEGORY(mApp, "m.application") // NOLINT
|
|||
QT_WARNING_POP
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QUuid>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -318,6 +321,17 @@ MApplication::MApplication(int &argc, char **argv)
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
MApplication::~MApplication()
|
||||
{
|
||||
if (settings->IsCollectStatistic())
|
||||
{
|
||||
auto *statistic = VGAnalytics::Instance();
|
||||
|
||||
QString clientID = settings->GetClientID();
|
||||
if (!clientID.isEmpty())
|
||||
{
|
||||
statistic->SendAppCloseEvent(m_uptimeTimer.elapsed());
|
||||
}
|
||||
}
|
||||
|
||||
qDeleteAll(m_mainWindows);
|
||||
|
||||
delete m_trVars;
|
||||
|
@ -473,6 +487,19 @@ void MApplication::InitOptions()
|
|||
}
|
||||
ActivateDarkMode();
|
||||
QResource::registerResource(diagramsPath());
|
||||
|
||||
auto *statistic = VGAnalytics::Instance();
|
||||
QString clientID = settings->GetClientID();
|
||||
if (clientID.isEmpty())
|
||||
{
|
||||
clientID = QUuid::createUuid().toString();
|
||||
settings->SetClientID(clientID);
|
||||
}
|
||||
statistic->SetClientID(clientID);
|
||||
statistic->SetGUILanguage(settings->GetLocale());
|
||||
statistic->SetMeasurementId(GA_MEASUREMENT_ID);
|
||||
statistic->SetApiSecret(GA_API_SECRET);
|
||||
statistic->Enable(settings->IsCollectStatistic());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -408,6 +408,15 @@ DEPENDPATH += $$PWD/../../libs/vmisc
|
|||
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vmisc/$${DESTDIR}/vmisc.lib
|
||||
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vmisc/$${DESTDIR}/libvmisc.a
|
||||
|
||||
# VGAnalytics static library
|
||||
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vganalytics/$${DESTDIR}/ -lvganalytics
|
||||
|
||||
INCLUDEPATH += $$PWD/../../libs/vganalytics
|
||||
DEPENDPATH += $$PWD/../../libs/vganalytics
|
||||
|
||||
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vganalytics/$${DESTDIR}/vganalytics.lib
|
||||
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vganalytics/$${DESTDIR}/libvganalytics.a
|
||||
|
||||
# QMuParser library
|
||||
win32:CONFIG(release, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2
|
||||
|
|
|
@ -14,6 +14,7 @@ VToolApp {
|
|||
Depends { name: "VToolsLib"; }
|
||||
Depends { name: "ebr" }
|
||||
Depends { name: "multibundle"; }
|
||||
Depends { name: "VGAnalyticsLib" }
|
||||
Depends { name: "conan.XercesC"; condition: buildconfig.useConanPackages }
|
||||
|
||||
name: "Tape"
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "../ifc/xml/vvitconverter.h"
|
||||
#include "../ifc/xml/vvstconverter.h"
|
||||
#include "../vmisc/compatibility.h"
|
||||
#include "../vmisc/dialogs/dialogaskcollectstatistic.h"
|
||||
#include "../vmisc/dialogs/dialogexporttocsv.h"
|
||||
#include "../vmisc/qxtcsvmodel.h"
|
||||
#include "../vmisc/vsysexits.h"
|
||||
|
@ -56,6 +57,7 @@
|
|||
#include "../vmisc/backport/qoverload.h"
|
||||
#endif // QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
|
||||
#include "../qmuparser/qmudef.h"
|
||||
#include "../vganalytics/vganalytics.h"
|
||||
#include "../vmisc/dialogs/dialogselectlanguage.h"
|
||||
#include "../vtools/dialogs/support/dialogeditwrongformula.h"
|
||||
#include "mapplication.h" // Should be last because of definning qApp
|
||||
|
@ -304,7 +306,7 @@ TMainWindow::TMainWindow(QWidget *parent)
|
|||
|
||||
if (MApplication::VApp()->IsAppInGUIMode())
|
||||
{
|
||||
QTimer::singleShot(V_SECONDS(1), this, &TMainWindow::SetDefaultGUILanguage);
|
||||
QTimer::singleShot(V_SECONDS(1), this, &TMainWindow::AskDefaultSettings);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2534,7 +2536,7 @@ void TMainWindow::DimensionCustomNames()
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void TMainWindow::SetDefaultGUILanguage()
|
||||
void TMainWindow::AskDefaultSettings()
|
||||
{
|
||||
if (MApplication::VApp()->IsAppInGUIMode())
|
||||
{
|
||||
|
@ -2552,6 +2554,38 @@ void TMainWindow::SetDefaultGUILanguage()
|
|||
VAbstractApplication::VApp()->LoadTranslation(locale);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings->IsAskCollectStatistic())
|
||||
{
|
||||
DialogAskCollectStatistic dialog(this);
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
settings->SetCollectStatistic(dialog.CollectStatistic());
|
||||
}
|
||||
|
||||
settings->SetAskCollectStatistic(false);
|
||||
}
|
||||
|
||||
if (settings->IsCollectStatistic())
|
||||
{
|
||||
auto *statistic = VGAnalytics::Instance();
|
||||
statistic->SetGUILanguage(settings->GetLocale());
|
||||
|
||||
QString clientID = settings->GetClientID();
|
||||
bool freshID = false;
|
||||
if (clientID.isEmpty())
|
||||
{
|
||||
clientID = QUuid::createUuid().toString();
|
||||
settings->SetClientID(clientID);
|
||||
statistic->SetClientID(clientID);
|
||||
freshID = true;
|
||||
}
|
||||
|
||||
statistic->Enable(true);
|
||||
|
||||
const qint64 uptime = MApplication::VApp()->AppUptime();
|
||||
freshID ? statistic->SendAppFreshInstallEvent(uptime) : statistic->SendAppStartEvent(uptime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ private slots:
|
|||
void EditDimensionLabels();
|
||||
void DimensionCustomNames();
|
||||
|
||||
void SetDefaultGUILanguage();
|
||||
void AskDefaultSettings();
|
||||
|
||||
private:
|
||||
// cppcheck-suppress unknownMacro
|
||||
|
|
|
@ -36,10 +36,11 @@
|
|||
#include "../mainwindow.h"
|
||||
#include "../qmuparser/qmuparsererror.h"
|
||||
#include "../version.h"
|
||||
#include "../vganalytics/def.h"
|
||||
#include "../vganalytics/vganalytics.h"
|
||||
#include "../vmisc/qt_dispatch/qt_dispatch.h"
|
||||
#include "../vmisc/vsysexits.h"
|
||||
#include "../vmisc/vvalentinasettings.h"
|
||||
#include <qstringliteral.h>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
#include "../vmisc/backport/text.h"
|
||||
|
@ -383,6 +384,18 @@ VApplication::VApplication(int &argc, char **argv)
|
|||
VApplication::~VApplication()
|
||||
{
|
||||
qCDebug(vApp, "Application closing.");
|
||||
|
||||
if (settings->IsCollectStatistic())
|
||||
{
|
||||
auto *statistic = VGAnalytics::Instance();
|
||||
|
||||
QString clientID = settings->GetClientID();
|
||||
if (!clientID.isEmpty())
|
||||
{
|
||||
statistic->SendAppCloseEvent(m_uptimeTimer.elapsed());
|
||||
}
|
||||
}
|
||||
|
||||
qInstallMessageHandler(nullptr); // Resore the message handler
|
||||
delete m_trVars;
|
||||
VCommandLine::Reset();
|
||||
|
@ -695,6 +708,19 @@ void VApplication::InitOptions()
|
|||
QIcon::setThemeName(QStringLiteral("win.icon.theme"));
|
||||
}
|
||||
ActivateDarkMode();
|
||||
|
||||
auto *statistic = VGAnalytics::Instance();
|
||||
QString clientID = settings->GetClientID();
|
||||
if (clientID.isEmpty())
|
||||
{
|
||||
clientID = QUuid::createUuid().toString();
|
||||
settings->SetClientID(clientID);
|
||||
}
|
||||
statistic->SetClientID(clientID);
|
||||
statistic->SetGUILanguage(settings->GetLocale());
|
||||
statistic->SetMeasurementId(GA_MEASUREMENT_ID);
|
||||
statistic->SetApiSecret(GA_API_SECRET);
|
||||
statistic->Enable(settings->IsCollectStatistic());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -31,12 +31,12 @@
|
|||
#include "../vmisc/literals.h"
|
||||
#include "../vmisc/vvalentinasettings.h"
|
||||
#include "../vpatterndb/pmsystems.h"
|
||||
#include "def.h"
|
||||
#include "ui_preferencesconfigurationpage.h"
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
|
||||
#include "../vmisc/backport/qoverload.h"
|
||||
#endif // QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
|
||||
#include "../qmuparser/qmudef.h"
|
||||
#include "../vganalytics/vganalytics.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
|
@ -162,6 +162,9 @@ PreferencesConfigurationPage::PreferencesConfigurationPage(QWidget *parent)
|
|||
ui->doubleSpinBoxAcceleration->setMinimum(VCommonSettings::scrollingAccelerationMin);
|
||||
ui->doubleSpinBoxAcceleration->setMaximum(VCommonSettings::scrollingAccelerationMax);
|
||||
ui->doubleSpinBoxAcceleration->setValue(settings->GetScrollingAcceleration());
|
||||
|
||||
// Tab Privacy
|
||||
ui->checkBoxSendUsageStatistics->setChecked(settings->IsCollectStatistic());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -254,6 +257,10 @@ auto PreferencesConfigurationPage::Apply() -> QStringList
|
|||
settings->SetWheelMouseScale(ui->doubleSpinBoxWheel->value());
|
||||
settings->SetScrollingAcceleration(ui->doubleSpinBoxAcceleration->value());
|
||||
|
||||
// Tab Privacy
|
||||
settings->SetCollectStatistic(ui->checkBoxSendUsageStatistics->isChecked());
|
||||
VGAnalytics::Instance()->Enable(ui->checkBoxSendUsageStatistics->isChecked());
|
||||
|
||||
return preferences;
|
||||
}
|
||||
|
||||
|
|
|
@ -527,6 +527,43 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabPrivacy">
|
||||
<attribute name="title">
|
||||
<string>Privacy</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxSendUsageStatistics">
|
||||
<property name="text">
|
||||
<string>Send usage statistics</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Please help to improve Valentina's quality by automatically sending usage statistics. Sent data contains <span style=" font-weight:700;">no potentially sensitive information</span> like user names, email addresses, file contents or file paths.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>716</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -38,9 +38,11 @@
|
|||
#include "../ifc/xml/vvstconverter.h"
|
||||
#include "../vformat/vmeasurements.h"
|
||||
#include "../vformat/vpatternrecipe.h"
|
||||
#include "../vganalytics/vganalytics.h"
|
||||
#include "../vlayout/dialogs/watermarkwindow.h"
|
||||
#include "../vmisc/customevents.h"
|
||||
#include "../vmisc/def.h"
|
||||
#include "../vmisc/dialogs/dialogaskcollectstatistic.h"
|
||||
#include "../vmisc/qxtcsvmodel.h"
|
||||
#include "../vmisc/vmodifierkey.h"
|
||||
#include "../vmisc/vsysexits.h"
|
||||
|
@ -505,7 +507,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
|
||||
if (VApplication::IsGUIMode())
|
||||
{
|
||||
QTimer::singleShot(V_SECONDS(1), this, &MainWindow::SetDefaultGUILanguage);
|
||||
QTimer::singleShot(V_SECONDS(1), this, &MainWindow::AskDefaultSettings);
|
||||
}
|
||||
|
||||
ui->actionExportFontCorrections->setEnabled(settings->GetSingleStrokeOutlineFont());
|
||||
|
@ -4548,7 +4550,7 @@ void MainWindow::ClearPatternMessages()
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void MainWindow::SetDefaultGUILanguage()
|
||||
void MainWindow::AskDefaultSettings()
|
||||
{
|
||||
if (VApplication::IsGUIMode())
|
||||
{
|
||||
|
@ -4565,6 +4567,38 @@ void MainWindow::SetDefaultGUILanguage()
|
|||
VAbstractApplication::VApp()->LoadTranslation(locale);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings->IsAskCollectStatistic())
|
||||
{
|
||||
DialogAskCollectStatistic dialog(this);
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
settings->SetCollectStatistic(dialog.CollectStatistic());
|
||||
}
|
||||
|
||||
settings->SetAskCollectStatistic(false);
|
||||
}
|
||||
|
||||
if (settings->IsCollectStatistic())
|
||||
{
|
||||
auto *statistic = VGAnalytics::Instance();
|
||||
statistic->SetGUILanguage(settings->GetLocale());
|
||||
|
||||
QString clientID = settings->GetClientID();
|
||||
bool freshID = false;
|
||||
if (clientID.isEmpty())
|
||||
{
|
||||
clientID = QUuid::createUuid().toString();
|
||||
settings->SetClientID(clientID);
|
||||
statistic->SetClientID(clientID);
|
||||
freshID = true;
|
||||
}
|
||||
|
||||
statistic->Enable(true);
|
||||
|
||||
const qint64 uptime = VAbstractValApplication::VApp()->AppUptime();
|
||||
freshID ? statistic->SendAppFreshInstallEvent(uptime) : statistic->SendAppStartEvent(uptime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ private slots:
|
|||
void ShowProgress();
|
||||
void ClearPatternMessages();
|
||||
|
||||
void SetDefaultGUILanguage();
|
||||
void AskDefaultSettings();
|
||||
|
||||
void AddBackgroundImageItem(const QUuid &id);
|
||||
void DeleteBackgroundImageItem(const QUuid &id);
|
||||
|
|
|
@ -698,6 +698,15 @@ DEPENDPATH += $$PWD/../../libs/vdxf
|
|||
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vdxf/$${DESTDIR}/vdxf.lib
|
||||
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vdxf/$${DESTDIR}/libvdxf.a
|
||||
|
||||
# VGAnalytics static library
|
||||
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vganalytics/$${DESTDIR}/ -lvganalytics
|
||||
|
||||
INCLUDEPATH += $$PWD/../../libs/vganalytics
|
||||
DEPENDPATH += $$PWD/../../libs/vganalytics
|
||||
|
||||
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vganalytics/$${DESTDIR}/vganalytics.lib
|
||||
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vganalytics/$${DESTDIR}/libvganalytics.a
|
||||
|
||||
# QMuParser library
|
||||
win32:CONFIG(release, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2
|
||||
|
|
|
@ -14,6 +14,7 @@ VToolApp {
|
|||
Depends { name: "VToolsLib"; }
|
||||
Depends { name: "VFormatLib"; }
|
||||
Depends { name: "VMiscLib"; }
|
||||
Depends { name: "VGAnalyticsLib" }
|
||||
|
||||
Depends {
|
||||
name: "Qt.xmlpatterns"
|
||||
|
|
|
@ -33,3 +33,6 @@ INCLUDEPATH += $${PWD}/vpropertyexplorer
|
|||
|
||||
#VTools static library
|
||||
INCLUDEPATH += $${PWD}/vtest
|
||||
|
||||
#VGAnalytics static library
|
||||
INCLUDEPATH += $${PWD}/vganalytics
|
||||
|
|
|
@ -13,4 +13,5 @@ SUBDIRS = \
|
|||
vtools \
|
||||
vformat \
|
||||
fervor \
|
||||
vtest
|
||||
vtest \
|
||||
vganalytics
|
||||
|
|
|
@ -14,5 +14,6 @@ Project {
|
|||
"vtest/vtest.qbs",
|
||||
"vtools/vtools.qbs",
|
||||
"vwidgets/vwidgets.qbs",
|
||||
"vganalytics/vganalytics.qbs",
|
||||
]
|
||||
}
|
||||
|
|
36
src/libs/vganalytics/def.h
Normal file
36
src/libs/vganalytics/def.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/************************************************************************
|
||||
**
|
||||
** @file def.h
|
||||
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
||||
** @date 26 6, 2023
|
||||
**
|
||||
** @brief
|
||||
** @copyright
|
||||
** This source code is part of the Valentina project, a pattern making
|
||||
** program, whose allow create and modeling patterns of clothing.
|
||||
** Copyright (C) 2023 Valentina project
|
||||
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
|
||||
**
|
||||
** Valentina is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** Valentina is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
*************************************************************************/
|
||||
#ifndef GADEF_H
|
||||
#define GADEF_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
const QString GA_MEASUREMENT_ID = QStringLiteral("G-KH8CCG06VJ"); // NOLINT(clazy-non-pod-global-static)
|
||||
const QString GA_API_SECRET = QStringLiteral("vnXM9BlCQXC9nvaXid_lAA"); // NOLINT(clazy-non-pod-global-static)
|
||||
|
||||
#endif // GADEF_H
|
306
src/libs/vganalytics/vganalytics.cpp
Normal file
306
src/libs/vganalytics/vganalytics.cpp
Normal file
|
@ -0,0 +1,306 @@
|
|||
/************************************************************************
|
||||
**
|
||||
** @file vganalytics.cpp
|
||||
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
||||
** @date 26 6, 2023
|
||||
**
|
||||
** @brief
|
||||
** @copyright
|
||||
** This source code is part of the Valentina project, a pattern making
|
||||
** program, whose allow create and modeling patterns of clothing.
|
||||
** Copyright (C) 2023 Valentina project
|
||||
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
|
||||
**
|
||||
** Valentina is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** Valentina is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
*************************************************************************/
|
||||
#include "vganalytics.h"
|
||||
#include "qguiapplication.h"
|
||||
#include "qstringliteral.h"
|
||||
#include "vganalyticsworker.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
#include <QGuiApplication>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QLocale>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QQueue>
|
||||
#include <QScreen>
|
||||
#include <QSettings>
|
||||
#include <QTimer>
|
||||
#include <QUrlQuery>
|
||||
#include <QUuid>
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
VGAnalytics::VGAnalytics(QObject *parent)
|
||||
: QObject{parent},
|
||||
d(new VGAnalyticsWorker(this))
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
VGAnalytics::~VGAnalytics()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VGAnalytics::Instance() -> VGAnalytics *
|
||||
{
|
||||
static VGAnalytics *instance = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
if (instance == nullptr)
|
||||
{
|
||||
instance = new VGAnalytics();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VGAnalytics::SetLogLevel(enum VGAnalytics::LogLevel logLevel)
|
||||
{
|
||||
d->m_logLevel = logLevel;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VGAnalytics::LogLevel() const -> enum VGAnalytics::LogLevel { return d->m_logLevel; }
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VGAnalytics::SetRepoRevision(const QString &rev)
|
||||
{
|
||||
d->m_repoRevision = rev;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VGAnalytics::RepoRevision() const -> QString
|
||||
{
|
||||
return d->m_repoRevision;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VGAnalytics::SetGUILanguage(const QString &language)
|
||||
{
|
||||
d->m_guiLanguage = language.toLower().replace(QChar('_'), QChar('-'));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VGAnalytics::GUILanguage() const -> QString
|
||||
{
|
||||
return d->m_guiLanguage;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VGAnalytics::SetSendInterval(int milliseconds)
|
||||
{
|
||||
d->m_timer.setInterval(milliseconds);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VGAnalytics::SendInterval() const -> int
|
||||
{
|
||||
return (d->m_timer.interval());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VGAnalytics::IsEnabled() -> bool
|
||||
{
|
||||
return d->m_isEnabled;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VGAnalytics::SetMeasurementId(const QString &measurementId)
|
||||
{
|
||||
d->m_measurementId = measurementId;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VGAnalytics::SetApiSecret(const QString &apiSecret)
|
||||
{
|
||||
d->m_apiSecret = apiSecret;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VGAnalytics::SetClientID(const QString &clientID)
|
||||
{
|
||||
d->m_clientID = clientID;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VGAnalytics::Enable(bool state)
|
||||
{
|
||||
d->Enable(state);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VGAnalytics::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;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VGAnalytics::NetworkAccessManager() const -> QNetworkAccessManager *
|
||||
{
|
||||
return d->networkManager;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VGAnalytics::SendAppFreshInstallEvent(qint64 engagementTimeMsec)
|
||||
{
|
||||
SendEvent(QStringLiteral("vapp_fresh_install"), InitAppStartEventParams(engagementTimeMsec));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VGAnalytics::SendAppStartEvent(qint64 engagementTimeMsec)
|
||||
{
|
||||
SendEvent(QStringLiteral("vapp_start"), InitAppStartEventParams(engagementTimeMsec));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VGAnalytics::SendAppCloseEvent(qint64 engagementTimeMsec)
|
||||
{
|
||||
QHash<QString, QJsonValue> params{
|
||||
// {QStringLiteral("category"), ""},
|
||||
// In order for user activity to display in standard reports like Realtime, engagement_time_msec and session_id
|
||||
// must be supplied as part of the params for an event.
|
||||
// https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#optional_parameters_for_reports
|
||||
{QStringLiteral("engagement_time_msec"), engagementTimeMsec},
|
||||
};
|
||||
|
||||
SendEvent(QStringLiteral("vapp_close"), params);
|
||||
QNetworkReply *reply = d->PostMessage();
|
||||
if (reply)
|
||||
{
|
||||
QTimer timer;
|
||||
const int timeoutSeconds = 3; // Wait for 3 seconds
|
||||
timer.setSingleShot(true);
|
||||
timer.start(timeoutSeconds * 1000);
|
||||
|
||||
QEventLoop loop;
|
||||
connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
|
||||
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||
loop.exec(); // wait for finished
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* A query for a POST message will be created to report this event. The
|
||||
* created query will be stored in a message queue.
|
||||
*/
|
||||
void VGAnalytics::SendEvent(const QString &eventName, const QHash<QString, QJsonValue> ¶ms)
|
||||
{
|
||||
/*
|
||||
// event body example
|
||||
{
|
||||
"client_id": "XXXXXXXXXX.YYYYYYYYYY",
|
||||
"events": [{
|
||||
"name": "refund",
|
||||
"params": {
|
||||
"currency": "USD",
|
||||
"value": "9.99",
|
||||
"transaction_id": "ABC-123"
|
||||
}
|
||||
}]
|
||||
}
|
||||
*/
|
||||
|
||||
QJsonObject root;
|
||||
root[QStringLiteral("client_id")] = d->m_clientID;
|
||||
|
||||
QJsonObject event;
|
||||
event[QStringLiteral("name")] = eventName;
|
||||
|
||||
QJsonObject eventParams;
|
||||
|
||||
auto i = params.constBegin();
|
||||
while (i != params.constEnd())
|
||||
{
|
||||
eventParams[i.key()] = i.value();
|
||||
++i;
|
||||
}
|
||||
|
||||
// In order for user activity to display in standard reports like Realtime, engagement_time_msec and session_id must
|
||||
// be supplied as part of the params for an event.
|
||||
// https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#optional_parameters_for_reports
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-static-cast-downcast)
|
||||
eventParams[QStringLiteral("session_id")] = qApp->sessionId();
|
||||
event[QStringLiteral("params")] = eventParams;
|
||||
|
||||
QJsonArray eventArray;
|
||||
eventArray.append(event);
|
||||
root[QStringLiteral("events")] = eventArray;
|
||||
|
||||
d->EnqueQueryWithCurrentTime(root);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VGAnalytics::InitAppStartEventParams(qint64 engagementTimeMsec) const -> QHash<QString, QJsonValue>
|
||||
{
|
||||
|
||||
QHash<QString, QJsonValue> params{
|
||||
// {QStringLiteral("category"), ""},
|
||||
{QStringLiteral("qt_version"), QT_VERSION_STR},
|
||||
{QStringLiteral("app_version"), d->m_appVersion},
|
||||
{QStringLiteral("word_size"), QStringLiteral("%1 bit").arg(QSysInfo::WordSize)},
|
||||
{QStringLiteral("cpu_architecture"), QSysInfo::currentCpuArchitecture()},
|
||||
{QStringLiteral("revision"), d->m_repoRevision},
|
||||
{QStringLiteral("os_version"), QSysInfo::prettyProductName()},
|
||||
{QStringLiteral("screen_size"), d->m_screenResolution},
|
||||
{QStringLiteral("screen_scale_factor"), d->m_screenScaleFactor},
|
||||
// In order for user activity to display in standard reports like Realtime, engagement_time_msec and session_id
|
||||
// must be supplied as part of the params for an event.
|
||||
// https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#optional_parameters_for_reports
|
||||
{QStringLiteral("engagement_time_msec"), engagementTimeMsec},
|
||||
{QStringLiteral("gui_language"), d->m_guiLanguage},
|
||||
};
|
||||
return params;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Qut stream to persist class GAnalytics.
|
||||
*/
|
||||
auto operator<<(QDataStream &outStream, const VGAnalytics &analytics) -> QDataStream &
|
||||
{
|
||||
outStream << analytics.d->PersistMessageQueue();
|
||||
|
||||
return outStream;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* In stream to read GAnalytics from file.
|
||||
*/
|
||||
auto operator>>(QDataStream &inStream, VGAnalytics &analytics) -> QDataStream &
|
||||
{
|
||||
QList<QString> dataList;
|
||||
inStream >> dataList;
|
||||
analytics.d->ReadMessagesFromFile(dataList);
|
||||
|
||||
return inStream;
|
||||
}
|
99
src/libs/vganalytics/vganalytics.h
Normal file
99
src/libs/vganalytics/vganalytics.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
/************************************************************************
|
||||
**
|
||||
** @file vganalytics.h
|
||||
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
||||
** @date 26 6, 2023
|
||||
**
|
||||
** @brief
|
||||
** @copyright
|
||||
** This source code is part of the Valentina project, a pattern making
|
||||
** program, whose allow create and modeling patterns of clothing.
|
||||
** Copyright (C) 2023 Valentina project
|
||||
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
|
||||
**
|
||||
** Valentina is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** Valentina is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
*************************************************************************/
|
||||
#ifndef VGANALYTICS_H
|
||||
#define VGANALYTICS_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class VGAnalyticsWorker;
|
||||
|
||||
// https://developers.google.com/analytics/devguides/collection/protocol/ga4/verify-implementation?client_type=gtag
|
||||
class VGAnalytics : public QObject
|
||||
{
|
||||
Q_OBJECT // NOLINT
|
||||
|
||||
public:
|
||||
~VGAnalytics() override;
|
||||
|
||||
static auto Instance() -> VGAnalytics *;
|
||||
|
||||
enum LogLevel
|
||||
{
|
||||
Debug,
|
||||
Info,
|
||||
Error
|
||||
};
|
||||
|
||||
Q_ENUM(LogLevel) // NOLINT
|
||||
|
||||
void SetMeasurementId(const QString &measurementId);
|
||||
void SetApiSecret(const QString &apiSecret);
|
||||
void SetClientID(const QString &clientID);
|
||||
|
||||
void SetLogLevel(LogLevel logLevel);
|
||||
auto LogLevel() const -> LogLevel;
|
||||
|
||||
void SetRepoRevision(const QString &rev);
|
||||
auto RepoRevision() const -> QString;
|
||||
|
||||
void SetGUILanguage(const QString &language);
|
||||
auto GUILanguage() const -> QString;
|
||||
|
||||
void SetSendInterval(int milliseconds);
|
||||
auto SendInterval() const -> int;
|
||||
|
||||
void Enable(bool state = true);
|
||||
auto IsEnabled() -> bool;
|
||||
|
||||
/// Get or set the network access manager. If none is set, the class creates its own on the first request
|
||||
void SetNetworkAccessManager(QNetworkAccessManager *networkAccessManager);
|
||||
auto NetworkAccessManager() const -> QNetworkAccessManager *;
|
||||
|
||||
public slots:
|
||||
void SendAppFreshInstallEvent(qint64 engagementTimeMsec);
|
||||
void SendAppStartEvent(qint64 engagementTimeMsec);
|
||||
void SendAppCloseEvent(qint64 engagementTimeMsec);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY_MOVE(VGAnalytics) // NOLINT
|
||||
|
||||
explicit VGAnalytics(QObject *parent = nullptr);
|
||||
|
||||
private:
|
||||
VGAnalyticsWorker *d;
|
||||
|
||||
void SendEvent(const QString &eventName, const QHash<QString, QJsonValue> ¶ms);
|
||||
|
||||
auto InitAppStartEventParams(qint64 engagementTimeMsec) const -> QHash<QString, QJsonValue>;
|
||||
|
||||
friend auto operator<<(QDataStream &outStream, const VGAnalytics &analytics) -> QDataStream &;
|
||||
friend auto operator>>(QDataStream &inStream, VGAnalytics &analytics) -> QDataStream &;
|
||||
};
|
||||
|
||||
#endif // VGANALYTICS_H
|
8
src/libs/vganalytics/vganalytics.pri
Normal file
8
src/libs/vganalytics/vganalytics.pri
Normal file
|
@ -0,0 +1,8 @@
|
|||
HEADERS += \
|
||||
$$PWD/def.h \
|
||||
$$PWD/vganalytics.h \
|
||||
$$PWD/vganalyticsworker.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/vganalytics.cpp \
|
||||
$$PWD/vganalyticsworker.cpp
|
80
src/libs/vganalytics/vganalytics.pro
Normal file
80
src/libs/vganalytics/vganalytics.pro
Normal file
|
@ -0,0 +1,80 @@
|
|||
# File with common stuff for whole project
|
||||
include(../../../common.pri)
|
||||
|
||||
QT += network gui
|
||||
|
||||
# Name of library
|
||||
TARGET = vganalytics
|
||||
|
||||
# We want to create a library
|
||||
TEMPLATE = lib
|
||||
|
||||
CONFIG += staticlib # Making static library
|
||||
|
||||
# Since Q5.12 available support for C++17
|
||||
equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 11) {
|
||||
CONFIG += c++17
|
||||
} else {
|
||||
CONFIG += c++14
|
||||
}
|
||||
|
||||
# Use out-of-source builds (shadow builds)
|
||||
CONFIG -= debug_and_release debug_and_release_target
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which has been marked as deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if you use deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
# Since Qt 5.4.0 the source code location is recorded only in debug builds.
|
||||
# We need this information also in release builds. For this need define QT_MESSAGELOGCONTEXT.
|
||||
DEFINES += QT_MESSAGELOGCONTEXT
|
||||
|
||||
include(vganalytics.pri)
|
||||
|
||||
# This is static library so no need in "make install"
|
||||
|
||||
# directory for executable file
|
||||
DESTDIR = bin
|
||||
|
||||
# files created moc
|
||||
MOC_DIR = moc
|
||||
|
||||
# objecs files
|
||||
OBJECTS_DIR = obj
|
||||
|
||||
# Set using ccache. Function enable_ccache() defined in common.pri.
|
||||
$$enable_ccache()
|
||||
|
||||
include(warnings.pri)
|
||||
|
||||
CONFIG(debug, debug|release){
|
||||
# Debug mode
|
||||
}else{
|
||||
# Release mode
|
||||
!*msvc*:CONFIG += silent
|
||||
DEFINES += V_NO_ASSERT
|
||||
!unix:*g++*{
|
||||
QMAKE_CXXFLAGS += -fno-omit-frame-pointer # Need for exchndl.dll
|
||||
}
|
||||
|
||||
noDebugSymbols{ # For enable run qmake with CONFIG+=noDebugSymbols
|
||||
# do nothing
|
||||
} else {
|
||||
!macx:!*msvc*{
|
||||
# Turn on debug symbols in release mode on Unix systems.
|
||||
# On Mac OS X temporarily disabled. TODO: find way how to strip binary file.
|
||||
QMAKE_CXXFLAGS_RELEASE += -g -gdwarf-3
|
||||
QMAKE_CFLAGS_RELEASE += -g -gdwarf-3
|
||||
QMAKE_LFLAGS_RELEASE =
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
include (../libs.pri)
|
16
src/libs/vganalytics/vganalytics.qbs
Normal file
16
src/libs/vganalytics/vganalytics.qbs
Normal file
|
@ -0,0 +1,16 @@
|
|||
VLib {
|
||||
name: "VGAnalyticsLib"
|
||||
files: [
|
||||
"def.h",
|
||||
"vganalytics.cpp",
|
||||
"vganalytics.h",
|
||||
"vganalyticsworker.cpp",
|
||||
"vganalyticsworker.h",
|
||||
]
|
||||
Depends { name: "Qt"; submodules: ["core", "network", "gui"] }
|
||||
|
||||
Export {
|
||||
Depends { name: "cpp" }
|
||||
cpp.includePaths: [exportingProduct.sourceDirectory]
|
||||
}
|
||||
}
|
281
src/libs/vganalytics/vganalyticsworker.cpp
Normal file
281
src/libs/vganalytics/vganalyticsworker.cpp
Normal file
|
@ -0,0 +1,281 @@
|
|||
/************************************************************************
|
||||
**
|
||||
** @file vganalyticsworker.cpp
|
||||
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
||||
** @date 26 6, 2023
|
||||
**
|
||||
** @brief
|
||||
** @copyright
|
||||
** This source code is part of the Valentina project, a pattern making
|
||||
** program, whose allow create and modeling patterns of clothing.
|
||||
** Copyright (C) 2023 Valentina project
|
||||
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
|
||||
**
|
||||
** Valentina is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** Valentina is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
*************************************************************************/
|
||||
#include "vganalyticsworker.h"
|
||||
#include "vganalytics.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
const QLatin1String VGAnalyticsWorker::dateTimeFormat("yyyy,MM,dd-hh:mm::ss:zzz");
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr int fourHours = 4 * 60 * 60 * 1000;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
VGAnalyticsWorker::VGAnalyticsWorker(QObject *parent)
|
||||
: QObject(parent),
|
||||
m_logLevel(VGAnalytics::Error)
|
||||
{
|
||||
m_appName = QCoreApplication::applicationName();
|
||||
m_appVersion = QCoreApplication::applicationVersion();
|
||||
m_request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=utf-8");
|
||||
m_request.setHeader(QNetworkRequest::UserAgentHeader, GetUserAgent());
|
||||
|
||||
m_guiLanguage = QLocale::system().name().toLower().replace(QChar('_'), QChar('-'));
|
||||
|
||||
QScreen *screen = QGuiApplication::primaryScreen();
|
||||
QSize size = screen->size();
|
||||
|
||||
m_screenResolution = QStringLiteral("%1x%2").arg(size.width()).arg(size.height());
|
||||
m_screenScaleFactor = screen->logicalDotsPerInchX() / 96.0;
|
||||
|
||||
m_timer.setInterval(m_timerInterval);
|
||||
connect(&m_timer, &QTimer::timeout, this, &VGAnalyticsWorker::PostMessage);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VGAnalyticsWorker::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 VGAnalyticsWorker::LogMessage(enum VGAnalytics::LogLevel level, const QString &message) const
|
||||
{
|
||||
if (m_logLevel > level)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "[Analytics]" << message;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
auto VGAnalyticsWorker::GetUserAgent() const -> QString
|
||||
{
|
||||
return QStringLiteral("%1/%2").arg(m_appName, 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.
|
||||
*/
|
||||
auto VGAnalyticsWorker::PersistMessageQueue() -> QList<QString>
|
||||
{
|
||||
QList<QString> dataList;
|
||||
dataList.reserve(m_messageQueue.size() * 2);
|
||||
|
||||
for (const auto &buffer : m_messageQueue)
|
||||
{
|
||||
dataList << QJsonDocument(buffer.postQuery).toJson();
|
||||
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 VGAnalyticsWorker::ReadMessagesFromFile(const QList<QString> &dataList)
|
||||
{
|
||||
QListIterator<QString> iter(dataList);
|
||||
while (iter.hasNext())
|
||||
{
|
||||
QString queryString = iter.next();
|
||||
QString dateString = iter.next();
|
||||
QDateTime dateTime = QDateTime::fromString(dateString, dateTimeFormat);
|
||||
QueryBuffer buffer;
|
||||
|
||||
QJsonDocument jsonDocument = QJsonDocument::fromJson(queryString.toUtf8());
|
||||
if (jsonDocument.isNull())
|
||||
{
|
||||
qDebug() << "===> please check the string " << queryString.toUtf8();
|
||||
}
|
||||
QJsonObject jsonObject = jsonDocument.object();
|
||||
|
||||
buffer.postQuery = jsonObject;
|
||||
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 VGAnalyticsWorker::EnqueQueryWithCurrentTime(const QJsonObject &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.
|
||||
*/
|
||||
auto VGAnalyticsWorker::PostMessage() -> QNetworkReply *
|
||||
{
|
||||
if (m_messageQueue.isEmpty())
|
||||
{
|
||||
// queue empty -> try sending later
|
||||
m_timer.start();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// queue has messages -> stop timer and start sending
|
||||
m_timer.stop();
|
||||
|
||||
QString connection = QStringLiteral("close");
|
||||
if (m_messageQueue.count() > 1)
|
||||
{
|
||||
connection = QLatin1String("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();
|
||||
return PostMessage();
|
||||
}
|
||||
|
||||
QByteArray requestJson = QJsonDocument(buffer.postQuery).toJson(QJsonDocument::Compact);
|
||||
m_request.setRawHeader("Connection", connection.toUtf8());
|
||||
m_request.setHeader(QNetworkRequest::ContentLengthHeader, requestJson.length());
|
||||
|
||||
if (m_measurementId.isEmpty())
|
||||
{
|
||||
LogMessage(VGAnalytics::Error, QStringLiteral("google analytics measurement id was not set!"));
|
||||
}
|
||||
if (m_apiSecret.isEmpty())
|
||||
{
|
||||
LogMessage(VGAnalytics::Error, QStringLiteral("google analytics api seceret was not set!"));
|
||||
}
|
||||
|
||||
QString requestUrl = QStringLiteral("https://www.google-analytics.com/mp/collect?measurement_id=%1&api_secret=%2");
|
||||
requestUrl = requestUrl.arg(m_measurementId, m_apiSecret);
|
||||
m_request.setUrl(QUrl(requestUrl));
|
||||
|
||||
LogMessage(VGAnalytics::Debug, "GA Query string = " + requestJson);
|
||||
|
||||
// Create a new network access manager if we don't have one yet
|
||||
if (networkManager == nullptr)
|
||||
{
|
||||
networkManager = new QNetworkAccessManager(this);
|
||||
}
|
||||
|
||||
QNetworkReply *reply = networkManager->post(m_request, requestJson);
|
||||
connect(reply, &QNetworkReply::finished, this, &VGAnalyticsWorker::PostMessageFinished);
|
||||
return reply;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* 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 VGAnalyticsWorker::PostMessageFinished()
|
||||
{
|
||||
auto *reply = qobject_cast<QNetworkReply *>(sender());
|
||||
|
||||
int httpStausCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (httpStausCode < 200 || httpStausCode > 299)
|
||||
{
|
||||
LogMessage(VGAnalytics::Error, QStringLiteral("Error posting message: %1").arg(reply->errorString()));
|
||||
|
||||
// An error ocurred. Try sending later.
|
||||
m_timer.start();
|
||||
return;
|
||||
}
|
||||
|
||||
LogMessage(VGAnalytics::Debug, QStringLiteral("Message sent"));
|
||||
|
||||
m_messageQueue.dequeue();
|
||||
PostMessage();
|
||||
reply->deleteLater();
|
||||
}
|
97
src/libs/vganalytics/vganalyticsworker.h
Normal file
97
src/libs/vganalytics/vganalyticsworker.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
/************************************************************************
|
||||
**
|
||||
** @file vganalyticsworker.h
|
||||
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
||||
** @date 26 6, 2023
|
||||
**
|
||||
** @brief
|
||||
** @copyright
|
||||
** This source code is part of the Valentina project, a pattern making
|
||||
** program, whose allow create and modeling patterns of clothing.
|
||||
** Copyright (C) 2023 Valentina project
|
||||
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
|
||||
**
|
||||
** Valentina is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** Valentina is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
*************************************************************************/
|
||||
#ifndef VGANALYTICSWORKER_H
|
||||
#define VGANALYTICSWORKER_H
|
||||
|
||||
#include "vganalytics.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QJsonObject>
|
||||
#include <QNetworkRequest>
|
||||
#include <QObject>
|
||||
#include <QQueue>
|
||||
#include <QTimer>
|
||||
#include <QUrlQuery>
|
||||
#include <qglobal.h>
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
struct QueryBuffer
|
||||
{
|
||||
QJsonObject postQuery{};
|
||||
QDateTime time{};
|
||||
};
|
||||
|
||||
class VGAnalyticsWorker : public QObject
|
||||
{
|
||||
Q_OBJECT // NOLINT
|
||||
|
||||
public:
|
||||
explicit VGAnalyticsWorker(QObject *parent = nullptr);
|
||||
|
||||
QNetworkAccessManager *networkManager{nullptr}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
|
||||
QQueue<QueryBuffer> m_messageQueue{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QTimer m_timer{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QNetworkRequest m_request{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
enum VGAnalytics::LogLevel m_logLevel{VGAnalytics::Debug}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
|
||||
QString m_measurementId{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString m_apiSecret{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString m_clientID{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString m_userID{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString m_appName{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString m_appVersion{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString m_guiLanguage{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString m_screenResolution{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString m_repoRevision{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
|
||||
bool m_isEnabled{false}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
int m_timerInterval{30000}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
qreal m_screenScaleFactor{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
|
||||
const static QLatin1String dateTimeFormat;
|
||||
|
||||
void LogMessage(enum VGAnalytics::LogLevel level, const QString &message) const;
|
||||
|
||||
auto GetUserAgent() const -> QString;
|
||||
auto PersistMessageQueue() -> QList<QString>;
|
||||
void ReadMessagesFromFile(const QList<QString> &dataList);
|
||||
|
||||
void EnqueQueryWithCurrentTime(const QJsonObject &query);
|
||||
void Enable(bool state);
|
||||
|
||||
public slots:
|
||||
QNetworkReply *PostMessage(); // NOLINT(modernize-use-trailing-return-type)
|
||||
void PostMessageFinished();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY_MOVE(VGAnalyticsWorker)
|
||||
};
|
||||
|
||||
#endif // VGANALYTICSWORKER_H
|
82
src/libs/vganalytics/warnings.pri
Normal file
82
src/libs/vganalytics/warnings.pri
Normal file
|
@ -0,0 +1,82 @@
|
|||
#Turn on compilers warnings.
|
||||
unix {
|
||||
*g++*{
|
||||
QMAKE_CXXFLAGS += \
|
||||
# Key -isystem disable checking errors in system headers.
|
||||
-isystem "$${OUT_PWD}/$${MOC_DIR}" \
|
||||
-isystem "$${OUT_PWD}/$${UI_DIR}" \
|
||||
$$GCC_DEBUG_CXXFLAGS # See common.pri for more details.
|
||||
|
||||
checkWarnings{ # For enable run qmake with CONFIG+=checkWarnings
|
||||
QMAKE_CXXFLAGS += -Werror
|
||||
}
|
||||
|
||||
noAddressSanitizer{ # For enable run qmake with CONFIG+=noAddressSanitizer
|
||||
# do nothing
|
||||
} else {
|
||||
CONFIG(debug, debug|release){
|
||||
# Debug mode
|
||||
#gcc’s 4.8.0 Address Sanitizer
|
||||
#http://blog.qt.digia.com/blog/2013/04/17/using-gccs-4-8-0-address-sanitizer-with-qt/
|
||||
QMAKE_CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer
|
||||
QMAKE_CFLAGS += -fsanitize=address -fno-omit-frame-pointer
|
||||
QMAKE_LFLAGS += -fsanitize=address
|
||||
}
|
||||
}
|
||||
|
||||
gccUbsan{ # For enable run qmake with CONFIG+=gccUbsan
|
||||
CONFIG(debug, debug|release){
|
||||
# Debug mode
|
||||
#gcc’s 4.9.0 Undefined Behavior Sanitizer (ubsan)
|
||||
QMAKE_CXXFLAGS += -fsanitize=undefined
|
||||
QMAKE_CFLAGS += -fsanitize=undefined
|
||||
QMAKE_LFLAGS += -fsanitize=undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*clang*{
|
||||
QMAKE_CXXFLAGS += \
|
||||
# Key -isystem disable checking errors in system headers.
|
||||
-isystem "$${OUT_PWD}/$${MOC_DIR}" \
|
||||
-isystem "$${OUT_PWD}/$${UI_DIR}" \
|
||||
$$CLANG_DEBUG_CXXFLAGS # See common.pri for more details.
|
||||
|
||||
checkWarnings{ # For enable run qmake with CONFIG+=checkWarnings
|
||||
QMAKE_CXXFLAGS += -Werror
|
||||
}
|
||||
|
||||
# -isystem key works only for headers. In some cases it's not enough. But we can't delete these warnings and
|
||||
# want them in global list. Compromise decision delete them from local list.
|
||||
QMAKE_CXXFLAGS -= \
|
||||
-Wmissing-prototypes \
|
||||
-Wundefined-reinterpret-cast
|
||||
}
|
||||
|
||||
*-icc-*{
|
||||
QMAKE_CXXFLAGS += \
|
||||
-isystem "$${OUT_PWD}/$${MOC_DIR}" \
|
||||
-isystem "$${OUT_PWD}/$${UI_DIR}" \
|
||||
$$ICC_DEBUG_CXXFLAGS
|
||||
|
||||
checkWarnings{ # For enable run qmake with CONFIG+=checkWarnings
|
||||
QMAKE_CXXFLAGS += -Werror
|
||||
}
|
||||
}
|
||||
} else { # Windows
|
||||
*g++*{
|
||||
QMAKE_CXXFLAGS += $$GCC_DEBUG_CXXFLAGS # See common.pri for more details.
|
||||
|
||||
checkWarnings{ # For enable run qmake with CONFIG+=checkWarnings
|
||||
QMAKE_CXXFLAGS += -Werror
|
||||
}
|
||||
}
|
||||
|
||||
*msvc*{
|
||||
QMAKE_CXXFLAGS += $$MSVC_DEBUG_CXXFLAGS # See common.pri for more details.
|
||||
|
||||
checkWarnings{ # For enable run qmake with CONFIG+=checkWarnings
|
||||
QMAKE_CXXFLAGS += -WX
|
||||
}
|
||||
}
|
||||
}
|
49
src/libs/vmisc/dialogs/dialogaskcollectstatistic.cpp
Normal file
49
src/libs/vmisc/dialogs/dialogaskcollectstatistic.cpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
/************************************************************************
|
||||
**
|
||||
** @file dialogaskcollectstatistic.cpp
|
||||
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
||||
** @date 26 6, 2023
|
||||
**
|
||||
** @brief
|
||||
** @copyright
|
||||
** This source code is part of the Valentina project, a pattern making
|
||||
** program, whose allow create and modeling patterns of clothing.
|
||||
** Copyright (C) 2023 Valentina project
|
||||
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
|
||||
**
|
||||
** Valentina is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** Valentina is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
*************************************************************************/
|
||||
#include "dialogaskcollectstatistic.h"
|
||||
#include "ui_dialogaskcollectstatistic.h"
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
DialogAskCollectStatistic::DialogAskCollectStatistic(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
ui(new Ui::DialogAskCollectStatistic)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
DialogAskCollectStatistic::~DialogAskCollectStatistic()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto DialogAskCollectStatistic::CollectStatistic() -> bool
|
||||
{
|
||||
return ui->checkBoxSendUsageStatistics->isChecked();
|
||||
}
|
57
src/libs/vmisc/dialogs/dialogaskcollectstatistic.h
Normal file
57
src/libs/vmisc/dialogs/dialogaskcollectstatistic.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/************************************************************************
|
||||
**
|
||||
** @file dialogaskcollectstatistic.h
|
||||
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
||||
** @date 26 6, 2023
|
||||
**
|
||||
** @brief
|
||||
** @copyright
|
||||
** This source code is part of the Valentina project, a pattern making
|
||||
** program, whose allow create and modeling patterns of clothing.
|
||||
** Copyright (C) 2023 Valentina project
|
||||
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
|
||||
**
|
||||
** Valentina is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** Valentina is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
*************************************************************************/
|
||||
#ifndef DIALOGASKCOLLECTSTATISTIC_H
|
||||
#define DIALOGASKCOLLECTSTATISTIC_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QtGlobal>
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
|
||||
#include "../defglobal.h"
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class DialogAskCollectStatistic;
|
||||
}
|
||||
|
||||
class DialogAskCollectStatistic : public QDialog
|
||||
{
|
||||
Q_OBJECT // NOLINT
|
||||
|
||||
public:
|
||||
explicit DialogAskCollectStatistic(QWidget *parent = nullptr);
|
||||
~DialogAskCollectStatistic() override;
|
||||
|
||||
auto CollectStatistic() -> bool;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY_MOVE(DialogAskCollectStatistic) // NOLINT
|
||||
Ui::DialogAskCollectStatistic *ui;
|
||||
};
|
||||
|
||||
#endif // DIALOGASKCOLLECTSTATISTIC_H
|
103
src/libs/vmisc/dialogs/dialogaskcollectstatistic.ui
Normal file
103
src/libs/vmisc/dialogs/dialogaskcollectstatistic.ui
Normal file
|
@ -0,0 +1,103 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DialogAskCollectStatistic</class>
|
||||
<widget class="QDialog" name="DialogAskCollectStatistic">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>376</width>
|
||||
<height>183</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Privacy</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../share/resources/icon.qrc">
|
||||
<normaloff>:/icon/64x64/icon64x64.png</normaloff>:/icon/64x64/icon64x64.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxSendUsageStatistics">
|
||||
<property name="text">
|
||||
<string>Send usage statistics</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Please help to improve Valentina's quality by automatically sending usage statistics. Sent data contains <span style=" font-weight:700;">no potentially sensitive information</span> like user names, email addresses, file contents or file paths.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</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>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../share/resources/icon.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DialogAskCollectStatistic</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DialogAskCollectStatistic</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -153,6 +153,8 @@ VAbstractApplication::VAbstractApplication(int &argc, char **argv)
|
|||
#endif
|
||||
|
||||
connect(this, &QApplication::aboutToQuit, this, &VAbstractApplication::AboutToQuit);
|
||||
|
||||
m_uptimeTimer.start();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -433,6 +435,12 @@ void VAbstractApplication::RestartSVGFontDatabaseWatcher()
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VAbstractApplication::AppUptime() const -> qint64
|
||||
{
|
||||
return m_uptimeTimer.elapsed();
|
||||
}
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VAbstractApplication::TextCodecCache(QStringConverter::Encoding encoding) const -> VTextCodec *
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include <QApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QElapsedTimer>
|
||||
#include <QFileDialog>
|
||||
#include <QLocale>
|
||||
#include <QMetaObject>
|
||||
|
@ -104,6 +105,8 @@ public:
|
|||
auto SVGFontDatabase() -> VSvgFontDatabase *;
|
||||
void RestartSVGFontDatabaseWatcher();
|
||||
|
||||
auto AppUptime() const -> qint64;
|
||||
|
||||
protected:
|
||||
QUndoStack *undoStack;
|
||||
|
||||
|
@ -120,6 +123,8 @@ protected:
|
|||
QPointer<QTranslator> appTranslator{nullptr};
|
||||
QPointer<QTranslator> pmsTranslator{nullptr};
|
||||
|
||||
QElapsedTimer m_uptimeTimer{};
|
||||
|
||||
virtual void InitTrVars() = 0;
|
||||
|
||||
static void CheckSystemLocale();
|
||||
|
|
|
@ -233,6 +233,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingWatermarkEditorSize, (QLatin1Str
|
|||
// NOLINTNEXTLINE
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingWatermarkCustomColors, (QLatin1String("watermarkCustomColors")))
|
||||
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingsStatistictAskCollect, (QLatin1String("askCollect"))) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingsStatistictCollect, (QLatin1String("collect"))) // NOLINT
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingsStatistictClientID, (QLatin1String("clientID"))) // NOLINT
|
||||
|
||||
// Reading settings file is very expensive, cache curve approximation to speed up getting value
|
||||
qreal curveApproximationCached = -1; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
Q_GLOBAL_STATIC(QString, localeCached) // NOLINT
|
||||
|
@ -1116,20 +1120,20 @@ auto VCommonSettings::GetCSVSeparator() const -> QChar
|
|||
switch (separator)
|
||||
{
|
||||
case 0:
|
||||
return QChar('\t');
|
||||
return QChar('\t'); // NOLINT(modernize-return-braced-init-list)
|
||||
case 1:
|
||||
return QChar(';');
|
||||
return QChar(';'); // NOLINT(modernize-return-braced-init-list)
|
||||
case 2:
|
||||
return QChar(' ');
|
||||
return QChar(' '); // NOLINT(modernize-return-braced-init-list)
|
||||
default:
|
||||
return QChar(',');
|
||||
return QChar(','); // NOLINT(modernize-return-braced-init-list)
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VCommonSettings::GetDefCSVSeparator() -> QChar
|
||||
{
|
||||
return QChar(',');
|
||||
return QChar(','); // NOLINT(modernize-return-braced-init-list)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -1751,6 +1755,51 @@ void VCommonSettings::SetWatermarkCustomColors(QVector<QColor> colors)
|
|||
settings.sync();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VCommonSettings::IsAskCollectStatistic() const -> bool
|
||||
{
|
||||
QSettings settings(this->format(), this->scope(), this->organizationName(), *commonIniFilename);
|
||||
return settings.value(*settingsStatistictAskCollect, 1).toBool();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VCommonSettings::SetAskCollectStatistic(bool value)
|
||||
{
|
||||
QSettings settings(this->format(), this->scope(), this->organizationName(), *commonIniFilename);
|
||||
settings.setValue(*settingsStatistictAskCollect, value);
|
||||
settings.sync();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VCommonSettings::IsCollectStatistic() const -> bool
|
||||
{
|
||||
QSettings settings(this->format(), this->scope(), this->organizationName(), *commonIniFilename);
|
||||
return settings.value(*settingsStatistictCollect, 1).toBool();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VCommonSettings::SetCollectStatistic(bool value)
|
||||
{
|
||||
QSettings settings(this->format(), this->scope(), this->organizationName(), *commonIniFilename);
|
||||
settings.setValue(*settingsStatistictCollect, value);
|
||||
settings.sync();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VCommonSettings::GetClientID() const -> QString
|
||||
{
|
||||
QSettings settings(this->format(), this->scope(), this->organizationName(), *commonIniFilename);
|
||||
return settings.value(*settingsStatistictClientID, QString()).toString();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VCommonSettings::SetClientID(const QString &clientID)
|
||||
{
|
||||
QSettings settings(this->format(), this->scope(), this->organizationName(), *commonIniFilename);
|
||||
settings.setValue(*settingsStatistictClientID, clientID);
|
||||
settings.sync();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VCommonSettings::PrepareStandardFiles(const QString ¤tPath, const QString &standardPath,
|
||||
const QString &defPath) -> QString
|
||||
|
|
|
@ -321,6 +321,15 @@ public:
|
|||
auto GetWatermarkCustomColors() const -> QVector<QColor>;
|
||||
void SetWatermarkCustomColors(QVector<QColor> colors);
|
||||
|
||||
auto IsAskCollectStatistic() const -> bool;
|
||||
void SetAskCollectStatistic(bool value);
|
||||
|
||||
auto IsCollectStatistic() const -> bool;
|
||||
void SetCollectStatistic(bool value);
|
||||
|
||||
auto GetClientID() const -> QString;
|
||||
void SetClientID(const QString &clientID);
|
||||
|
||||
signals:
|
||||
void SVGFontsPathChanged(const QString &oldPath, const QString &newPath);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
SOURCES += \
|
||||
$$PWD/def.cpp \
|
||||
$$PWD/dialogs/dialogaskcollectstatistic.cpp \
|
||||
$$PWD/svgfont/svgdef.cpp \
|
||||
$$PWD/svgfont/vsvgfont.cpp \
|
||||
$$PWD/svgfont/vsvgfontdatabase.cpp \
|
||||
|
@ -61,6 +62,7 @@ HEADERS += \
|
|||
$$PWD/bpstd/utility.hpp \
|
||||
$$PWD/bpstd/variant.hpp \
|
||||
$$PWD/compatibility.h \
|
||||
$$PWD/dialogs/dialogaskcollectstatistic.h \
|
||||
$$PWD/lambdaconstants.h \
|
||||
$$PWD/stable.h \
|
||||
$$PWD/def.h \
|
||||
|
@ -122,5 +124,6 @@ contains(QT_VERSION, ^5\\.[0-2]\\.[0-2]$) { # Since Qt 5.3.0
|
|||
}
|
||||
|
||||
FORMS += \
|
||||
$$PWD/dialogs/dialogaskcollectstatistic.ui \
|
||||
$$PWD/dialogs/dialogexporttocsv.ui \
|
||||
$$PWD/dialogs/dialogselectlanguage.ui
|
||||
|
|
|
@ -67,12 +67,15 @@ VLib {
|
|||
name: "dialogs"
|
||||
prefix: "dialogs/"
|
||||
files: [
|
||||
"dialogaskcollectstatistic.cpp",
|
||||
"dialogaskcollectstatistic.h",
|
||||
"dialogaskcollectstatistic.ui",
|
||||
"dialogexporttocsv.cpp",
|
||||
"dialogselectlanguage.cpp",
|
||||
"dialogexporttocsv.h",
|
||||
"dialogselectlanguage.h",
|
||||
"dialogexporttocsv.ui",
|
||||
"dialogselectlanguage.ui"
|
||||
"dialogselectlanguage.ui",
|
||||
]
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user