vnote/src/dialog/vupdater.cpp

184 lines
5.3 KiB
C++

#include "vupdater.h"
#include <QtWidgets>
#include <QJsonDocument>
#include <QJsonObject>
#include <QTimer>
#include <QWebEngineView>
#include "vconfigmanager.h"
#include "vdownloader.h"
#include "vmarkdownconverter.h"
#include "utils/vutils.h"
#include "vnote.h"
extern VConfigManager *g_config;
VUpdater::VUpdater(QWidget *p_parent)
: QDialog(p_parent)
{
setupUI();
}
void VUpdater::setupUI()
{
QImage img(":/resources/icons/vnote_update.svg");
QSize imgSize(128, 128);
QLabel *imgLabel = new QLabel();
imgLabel->setPixmap(QPixmap::fromImage(img.scaled(imgSize)));
m_versionLabel = new QLabel(tr("Current Version: v%1")
.arg(g_config->c_version));
m_proLabel = new QLabel(tr("Checking for updates..."));
m_proLabel->setOpenExternalLinks(true);
m_proBar = new QProgressBar();
m_proBar->setTextVisible(false);
m_descriptionWV = VUtils::getWebEngineView();
m_descriptionWV->setContextMenuPolicy(Qt::NoContextMenu);
m_descriptionWV->setHtml(VUtils::generateSimpleHtmlTemplate(VNote::s_sloganTemplate),
QUrl("qrc:/resources"));
m_btnBox = new QDialogButtonBox(QDialogButtonBox::Ok);
m_btnBox->button(QDialogButtonBox::Ok)->setProperty("SpecialBtn", true);
connect(m_btnBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
QVBoxLayout *verLayout = new QVBoxLayout();
verLayout->addStretch();
verLayout->addWidget(m_versionLabel);
verLayout->addStretch();
verLayout->addWidget(m_proLabel);
verLayout->addWidget(m_proBar);
QHBoxLayout *topLayout = new QHBoxLayout();
topLayout->addWidget(imgLabel);
topLayout->addLayout(verLayout);
topLayout->addStretch();
QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->addLayout(topLayout);
mainLayout->addWidget(m_descriptionWV, 1);
mainLayout->addWidget(m_btnBox);
m_proLabel->hide();
m_proBar->hide();
setLayout(mainLayout);
setWindowTitle(tr("VNote Update"));
}
void VUpdater::showEvent(QShowEvent *p_event)
{
QDialog::showEvent(p_event);
QTimer *timer = new QTimer(this);
timer->setSingleShot(true);
timer->setInterval(1000);
connect(timer, &QTimer::timeout,
this, [this]() {
this->checkUpdates();
});
timer->start();
}
void VUpdater::checkUpdates()
{
// Change UI.
m_proLabel->setText(tr("Checking for updates..."));
m_proLabel->show();
m_proBar->setEnabled(true);
m_proBar->setMinimum(0);
m_proBar->setMaximum(100);
m_proBar->reset();
m_proBar->show();
QString url("https://api.github.com/repos/tamlok/vnote/releases/latest");
VDownloader *downloader = new VDownloader(this);
connect(downloader, &VDownloader::downloadFinished,
this, &VUpdater::parseResult);
downloader->download(url);
m_proBar->setValue(20);
}
// Return if @p_latestVersion is newer than p_curVersion.
// They are both in format xx.xx.xx.xx
bool isNewerVersion(const QString &p_curVersion, const QString &p_latestVersion)
{
QStringList curList = p_curVersion.split('.', QString::SkipEmptyParts);
QStringList latestList = p_latestVersion.split('.', QString::SkipEmptyParts);
int i = 0;
for (; i < curList.size() && i < latestList.size(); ++i) {
int a = curList[i].toInt();
int b = latestList[i].toInt();
if (a > b) {
return false;
} else if (a < b) {
return true;
}
}
if (i < curList.size()) {
// 1.2.1 vs 1.2
return false;
} else if (i < latestList.size()) {
// 1.2 vs 1.2.1
return true;
} else {
// 1.2 vs 1.2
return false;
}
}
void VUpdater::parseResult(const QByteArray &p_data)
{
m_proBar->setValue(40);
QJsonDocument jsonDoc = QJsonDocument::fromJson(p_data);
QJsonObject json = jsonDoc.object();
if (jsonDoc.isNull() || json.empty()) {
m_proBar->setEnabled(false);
m_proLabel->setText(tr(":( Fail to check for updates.\n"
"Please try it later."));
return;
}
m_proBar->setValue(100);
QString tag = json["tag_name"].toString();
if (tag.startsWith('v') && tag.size() > 3) {
tag = tag.right(tag.size() - 1);
}
QString releaseName = json["name"].toString();
QString releaseUrl = json["html_url"].toString();
QString body = json["body"].toString();
m_versionLabel->setText(tr("Current Version: v%1\nLatest Version: v%2")
.arg(g_config->c_version).arg(tag));
if (isNewerVersion(g_config->c_version, tag)) {
m_proLabel->setText(tr("<span style=\"font-weight: bold;\">Updates Available!</span><br/>"
"Please visit <a href=\"%1\">Github Releases</a> to download the latest version.")
.arg(releaseUrl));
} else {
m_proLabel->setText(tr("VNote is already the latest version."));
}
QString mdText = "# " + releaseName + "\n" + body;
VMarkdownConverter mdConverter;
QString toc;
QString html = mdConverter.generateHtml(mdText,
g_config->getMarkdownExtensions(),
toc);
html = VUtils::generateSimpleHtmlTemplate(html);
m_descriptionWV->setHtml(html, QUrl("qrc:/resources"));
m_proBar->hide();
}