#include "updaterdialog.h" #include "ui_updaterdialog.h" #include #include #include #include #include #include #include QString CHECK_URL = "http://www.tianzd.cn:1995/TianZD/deploy/raw/branch/master/"; QString ORIGIN_URL = "http://www.tianzd.cn:1995/TianZD/deploy/raw/branch/master/"; QString PLATFORM = "windows"; QString APPVERSION = ""; QString APPNAME = ""; QString APPDATE = "0"; QString MODIFYCNT = "0"; UpdaterDialog::UpdaterDialog(QWidget *parent) : QDialog(parent), ui(new Ui::UpdaterDialog) { ui->setupUi(this); this->setWindowTitle("Updater"); ui->btn_update->setEnabled(0); m_startTime = 0; m_version = APPVERSION; ui->versionInput->setText(m_version); ui->appNameInput->setText(APPNAME); ui->show->setEnabled(0); ui->label_2->setText(""); ui->label_3->setText(""); // ui->label_4->setText(APPNAME); // ui->versionInput->setEnabled(false); // ui->show->appendPlainText(APPNAME); // ui->show->appendPlainText(APPVERSION); // ui->show->appendPlainText(APPDATE); // ui->show->appendPlainText(MODIFYCNT); } UpdaterDialog::~UpdaterDialog() { delete ui; } void UpdaterDialog::showStatus(const QString &s) { // ui->show->clear(); ui->show->appendPlainText(s); } void UpdaterDialog::on_btn_check_clicked() { APPNAME = ui->appNameInput->text(); if(QString(APPNAME) == "") { ui->show->appendPlainText("Please input app name"); return; } ui->show->clear(); ui->btn_update->setEnabled(0); //version m_version = ui->versionInput->text(); if(!m_pManager) { m_pManager = new QNetworkAccessManager(this); connect(m_pManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(onCheckReply(QNetworkReply *))); } CHECK_URL = ORIGIN_URL + APPNAME + "/updates.json"; qDebug() << APPNAME << CHECK_URL; QNetworkRequest request(CHECK_URL); m_pManager->get(request); } bool UpdaterDialog::checkVersion(const QString &_localVersion, const QString &_remoteVersion) { //版本号分割,1.1.2分为1 1 2 QStringList _list_curr = _localVersion.split("."); QStringList _list_lastest = _remoteVersion.split("."); //检查是否需要更新 bool _isNotLatest = false; //版本号为空 if(_list_curr.count() == 0) { m_bDownloadFullExe = true; return true; } if(_list_curr.count() != _list_lastest.count()) _isNotLatest = true; for(int i = 0; i < _list_curr.count(); ++i) { if(_list_curr[i].toUInt() < _list_lastest[i].toUInt()) { _isNotLatest = true; } } //版本号一致,检查日期 if(!_isNotLatest) { if(m_lastChangeTime.toUInt() > APPDATE.toUInt()) { _isNotLatest = true; } //检查修改次数 if(m_modifyCnt != "" && m_modifyCnt != " " && MODIFYCNT != "" && MODIFYCNT != " ") { if(m_modifyCnt.toUInt() > MODIFYCNT.toUInt()) { _isNotLatest = true; } } } return _isNotLatest; } void UpdaterDialog::onCheckReply(QNetworkReply *reply) { /* There was a network error */ if (reply->error() != QNetworkReply::NoError) { showStatus("check error"); return; } /* Try to create a JSON document from downloaded data */ QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); /* JSON is invalid */ if (document.isNull()) { showStatus("reply doc is null"); return; } /* Get the platform information */ QJsonObject updates = document.object().value("updates").toObject(); QJsonObject platform = updates.value(PLATFORM).toObject(); /* Get update information */ m_changelog = platform.value("changelog").toString(); m_patchVersion = platform.value("patch-version").toString(); m_fullVersion = platform.value("full-version").toString(); m_lastChangeTime = platform.value("modify-time").toString(); m_modifyCnt = platform.value("modifyCnt").toString(); m_bDownloadFullExe = platform.value("download-full").toBool(); if(m_version == "" || m_version == "0") //当前版本号为空 { m_bDownloadFullExe = true; } m_fileName = APPNAME + "-patch-v" + m_patchVersion + ".zip"; m_patchUrl = platform.value("patch-url").toString() + APPNAME + "/" + APPNAME + "-patch-v" + m_patchVersion + ".zip"; m_fullUrl = platform.value("full-url").toString() + APPNAME + "/" + APPNAME + "-full-v" + m_fullVersion + ".exe"; QString _remoteVersion = m_bDownloadFullExe ? m_fullVersion : m_patchVersion; bool _isNotLatest = checkVersion(m_version, _remoteVersion); if(_isNotLatest) { showStatus("======================================" + tr("\ncurrent version: v") + m_version + tr("\nmodify time: ") + APPDATE + tr("\nmodify cnt: ") + MODIFYCNT + "\n ------------------------------" + tr("\nlatest version: v") + _remoteVersion + tr("\nmodify time: ") + m_lastChangeTime + tr("\nmodify cnt: ") + m_modifyCnt + tr("\nchange log: ") + m_changelog + "\n======================================" ); if(m_bDownloadFullExe) { showStatus("need download full exe"); m_fileName = APPNAME + "-full-v" + m_patchVersion + ".exe"; } showStatus(tr("click update button to update")); } else { showStatus("======================================" + tr("\ncurrent software is up-to-date") + tr("\nversion : v") + _remoteVersion + tr("\nmodify time: ") + m_lastChangeTime + tr("\nmodify cnt: ") + m_modifyCnt + "\n======================================" + tr("\nno need to update") + tr("\nclick cancel button to quit")); } ui->btn_update->setEnabled(1); } void UpdaterDialog::calculateSizes(qint64 received, qint64 total) { QString totalSize; QString receivedSize; if (total < 1024) totalSize = tr("%1 bytes").arg(total); else if (total < 1048576) totalSize = tr("%1 KB").arg(round(total / 1024)); else totalSize = tr("%1 MB").arg((total / 1048576.0)); if (received < 1024) receivedSize = tr("%1 bytes").arg(received); else if (received < 1048576) receivedSize = tr("%1 KB").arg(received / 1024); else receivedSize = tr("%1 MB").arg(received / 1048576.0); ui->label_2->setText(tr("Downloading updates") + " (" + receivedSize + " " + tr("of") + " " + totalSize + ")"); } /** * Uses two time samples (from the current time and a previous sample) to * calculate how many bytes have been downloaded. * * Then, this function proceeds to calculate the appropiate units of time * (hours, minutes or seconds) and constructs a user-friendly string, which * is displayed in the dialog. */ void UpdaterDialog::calculateTimeRemaining(qint64 received, qint64 total) { static quint64 lastRec = 0; static uint lastTime = 0; uint _time = QDateTime::currentDateTime().toMSecsSinceEpoch(); double _speed = (received - lastRec) / 1024.0 / (_time - lastTime) * 1000.0; lastTime = _time; lastRec = received; uint difference = QDateTime::currentDateTime().toSecsSinceEpoch() - m_startTime; if (difference > 0) { QString timeString; qreal timeRemaining = (total - received) / (received / difference); if (timeRemaining > 7200) { timeRemaining /= 3600; int hours = int(timeRemaining + 0.5); if (hours > 1) timeString = tr("about %1 hours").arg(hours); else timeString = tr("about one hour"); } else if (timeRemaining > 60) { timeRemaining /= 60; int minutes = int(timeRemaining + 0.5); if (minutes > 1) timeString = tr("%1 minutes").arg(minutes); else timeString = tr("1 minute"); } else if (timeRemaining <= 60) { int seconds = int(timeRemaining + 0.5); if (seconds > 1) timeString = tr("%1 seconds").arg(seconds); else timeString = tr("1 second"); } ui->label_3->setText(tr("speed: %1 kb/s ").arg(_speed) + tr("Time remaining") + ": " + timeString); } } void UpdaterDialog::on_btn_update_clicked() { if(!m_pDownloader) { m_pDownloader = new Downloader(this); connect(m_pDownloader, &Downloader::doShowInfo, this, [&](const QString & s) { showStatus(s); }); connect(m_pDownloader, &Downloader::onError, this, [&](QNetworkReply::NetworkError e) { QMetaEnum metaEnum = QMetaEnum::fromType(); QString str = QString(metaEnum.valueToKey(e)); ui->show->appendPlainText(str); }); connect(m_pDownloader, &Downloader::doFinished, this, [&]() { uint _end_time = QDateTime::currentSecsSinceEpoch(); uint _total_time = _end_time - m_startTime; ui->label_3->setText("total time: " + QString::number(_total_time, 'g', 3) + "s average speed: " + QString::number((m_totalSize / 1024.0 / _total_time), 'g', 3) + "kb/s"); ui->show->appendPlainText("download finished"); onDownloadFinished(); }); connect(m_pDownloader, &Downloader::doProgress, this, [&](quint64 received, quint64 total) { m_totalSize = total; if (total > 0) { ui->progressBar->setMinimum(0); ui->progressBar->setMaximum(100); ui->progressBar->setValue((received * 100) / total); calculateSizes(received, total); calculateTimeRemaining(received, total); } else { ui->progressBar->setMinimum(0); ui->progressBar->setMaximum(0); ui->progressBar->setValue(-1); ui->show->appendPlainText(tr("Downloading Updates") + "..."); } }); } m_pDownloader->setFileName(m_fileName); m_startTime = QDateTime::currentDateTime().toSecsSinceEpoch(); QString _url = m_bDownloadFullExe ? m_fullUrl : m_patchUrl; m_pDownloader->startDownload(_url); } void UpdaterDialog::on_btn_cancel_clicked() { if(!m_UpdateProc) { m_UpdateProc = new QProcess; } #if defined Q_OS_WIN m_UpdateProc->setProgram(APPNAME + ".exe"); #elif defined Q_OS_LINUX m_UpdateProc->setProgram("./" + APPNAME); #endif m_UpdateProc->start(); m_UpdateProc->waitForStarted(); QApplication::quit(); } void UpdaterDialog::onDownloadFinished() { // ui->show->appendPlainText(m_pDownloader->fileName()); // ui->show->appendPlainText("m_bDownloadFullExe"); auto localInformation = QMessageBox::question(this, "update", "download finished\nstart update?"); if(localInformation == QMessageBox::Yes) { QString _appName; if(!m_bDownloadFullExe) { //解压文件 QFileInfo f(m_pDownloader->getFile()); QString _path = f.fileName(); QZipReader * zipReader = new QZipReader(_path); zipReader->extractAll(f.path()); _appName = APPNAME + ".exe"; } else { _appName = m_pDownloader->fileName(); } QFileInfo f2(QCoreApplication::applicationDirPath() + "/" + _appName); if(f2.exists()) { QDesktopServices::openUrl(f2.absoluteFilePath()); } QApplication::quit(); } }