3#include <QStandardPaths>
4#include <QCoreApplication>
6#include <QLoggingCategory>
7#include <QRegularExpression>
8#include <QRegularExpressionMatch>
9#include "RabbitCommonDir.h"
10#include "RabbitCommonTools.h"
11#include "WorkerFileTransfer.h"
12#include "StatsAppUsage.h"
14static Q_LOGGING_CATEGORY(log,
"Stats.App")
16 const QString& szUrl, QObject *parent)
18 , m_szVersion(szVersion)
23 qDebug(log) << Q_FUNC_INFO;
24 if(m_szUrl.isEmpty()) {
25 m_szUrl =
"https://github.com/KangLin/"
26 + QCoreApplication::applicationName() +
"/releases/download";
28 bool check = connect(&m_Timer, &QTimer::timeout,
29 this, &CStatsAppUsage::slotTimeout);
31 check = connect(&m_ThreadPool, &CThreadPool::sigRunning,
32 this, &CStatsAppUsage::Start);
34 check = connect(&m_ThreadPool, &CThreadPool::sigFinished,
35 this, &CStatsAppUsage::sigFinished);
37 m_ThreadPool.Start(CreateWorkerFileTransfer);
40CStatsAppUsage::~CStatsAppUsage()
42 qDebug(log) << Q_FUNC_INFO;
45void CStatsAppUsage::SetUrl(
const QString &szUrl)
52 m_szVersion = szVersion;
55void CStatsAppUsage::Start()
57 Q_ASSERT_X(!m_szUrl.isEmpty(),
"Stats.App",
58 "Please call SetUrl() and SetVersion() first");
59 m_tmStart = QDateTime::currentDateTime();
63 m_Timer.start(24 * 3600 * 1000);
66void CStatsAppUsage::Stop()
75void CStatsAppUsage::slotTimeout()
85 QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
86 QSettings::IniFormat);
87 bool bOnce = set.value(
"Stats/App/Start/Once",
false).toBool();
90 Download(
"StartOnce");
91 set.setValue(
"Stats/App/Start/Once",
true);
94void CStatsAppUsage::StopOnce()
96 QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
97 QSettings::IniFormat);
98 bool bOnce = set.value(
"Stats/App/End/Once",
false).toBool();
102 set.setValue(
"Stats/App/End/Once",
true);
110 QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
111 QSettings::IniFormat);
112 QDateTime tm = set.value(
"Stats/App/Start/Day").toDateTime();
113 qDebug(log) <<
"daysTo:" << tm.daysTo(QDateTime::currentDateTime())
114 << tm.isValid() << tm.isNull() << tm;
115 if(tm.isValid() && !tm.isNull()
116 && tm.daysTo(QDateTime::currentDateTime()) < 1)
118 Download(
"StartDay");
119 set.setValue(
"Stats/App/Start/Day", QDateTime::currentDateTime());
122void CStatsAppUsage::StopDay()
124 QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
125 QSettings::IniFormat);
126 QDateTime tm = set.value(
"Stats/App/End/Day").toDateTime();
127 qDebug(log) <<
"daysTo:" << tm.daysTo(QDateTime::currentDateTime())
128 << tm.isValid() << tm.isNull() << tm;
129 if(tm.isValid() && !tm.isNull()
130 && tm.daysTo(QDateTime::currentDateTime()) < 1)
133 set.setValue(
"Stats/App/End/Day", QDateTime::currentDateTime());
141 qDebug(log) <<
"secsTo:" << m_tmStart.secsTo(QDateTime::currentDateTime());
142 if(m_tmStart.secsTo(QDateTime::currentDateTime()) >= 24 * 3600
145 Download(
"RunOneDay");
149void CStatsAppUsage::Download(
const QString &szFile)
151 QString file =
"Stats" + szFile;
152 if(m_szUrl.isEmpty())
return;
153 QString szUrl = m_szUrl +
"/";
154 QString szVersion = m_szVersion;
155 if(!szVersion.isEmpty()) {
156 if(RabbitCommon::CTools::VersionValid(szVersion)) {
157 auto map = RabbitCommon::CTools::GetVersion(szVersion);
158 if(!map.value(
"PreRelease").isEmpty()
159 || !map.value(
"Build").isEmpty()) {
161 static QRegularExpression regex(
"[-|+]");
162 szVersion = szVersion.left(szVersion.indexOf(regex));
163 qDebug(log) <<
"Version:" << szVersion;
166 szVersion = QString();
167 if(!szVersion.isEmpty())
168 szUrl += szVersion +
"/";
172 if(!m_szExt.isEmpty())
173 szUrl +=
"." + m_szExt;
174 qDebug(log) << Q_FUNC_INFO << szUrl;
177 CWorkerFileTransfer* pWorker =
178 qobject_cast<CWorkerFileTransfer*>(m_ThreadPool.ChooseWorker());
182 if(!url.fileName().isEmpty()) {
183 szDownload = QStandardPaths::writableLocation(
184 QStandardPaths::TempLocation);
185 if(szDownload.right(1) !=
"/" && szDownload.right(1) !=
"\\")
186 szDownload += QDir::separator();
187 szDownload += QString(
"Rabbit") + QDir::separator()
188 + QCoreApplication::applicationName()
190 szDownload += url.fileName();
192 CTaskFileTransfer* task =
new CTaskFileTransfer(szUrl, szDownload);
193 bool check = connect(task, &CTaskFileTransfer::sigFinished,
194 this, [task, pWorker]() {
195 qDebug(log) <<
"Download finished:" << task->Title();
198 check = connect(task, &CTaskFileTransfer::sigError,
199 this, [task, pWorker](
int nErr,
const QString& szError){
200 qDebug(log) <<
"Download fail:" << nErr << szError << task->Title();
202 pWorker->AddTask(task);
void RunOneDay()
运行超过一天的计为一次
void StartDay()
程序每天所有启动计为一次
void StartOnce()
程序安装后,同一用户所有启动计为一次
void SetVersion(const QString &szVersion)
Semantic Versioning: https://semver.org/