基于QSimpleUpdater, 但是QSimpleUpdater无法在qml应用下使用,因此对其做了一定封装,,特点如下:
- 依赖QSimpleUpdater,但是没有修改其任何代码;
- 支持自定义下载文件名;
- 自定义下载路径;
- 灵活的嵌入到qml;
下面上代码
代码
qt.pro文件里面添加QSimpleUpdater依赖
include ($$PWD/QSimpleUpdater/QSimpleUpdater.pri)
C Class
qmlmqttclient.cpp
#pragma execution_character_set("utf-8")
#include "qmlUpdater.h"
#include <QDateTime>
#include <QDebug>
#include <QDesktopServices>
#include <QJsonDocument>
#include <QJsonObject>
QmlUpdater::QmlUpdater(QObject *parent) : QObject(parent) {
m_updater = QSimpleUpdater::getInstance();
m_downloader = new Downloader();
connect(m_updater, SIGNAL(appcastDownloaded(QString, QByteArray)), this,
SLOT(displayAppcast(QString, QByteArray)));
connect(m_downloader, SIGNAL(downloadFinished(QString, QString)), this,
SIGNAL(downloadFinished(QString, QString)));
DEFS_URL = DEFS_URL +
"?t=" + QString::number(QDateTime::currentDateTime().toTime_t());
checkForUpdates();
}
QmlUpdater::~QmlUpdater() {}
void QmlUpdater::checkForUpdates() {
/* Apply the settings */
// m_updater->setModuleVersion(DEFS_URL, "0.1");
m_updater->setNotifyOnFinish(DEFS_URL, true);
m_updater->setNotifyOnUpdate(DEFS_URL, true);
m_updater->setUseCustomAppcast(DEFS_URL, true);
m_updater->setDownloaderEnabled(DEFS_URL, true);
m_updater->setMandatoryUpdate(DEFS_URL, true);
/* Check for updates */
m_updater->checkForUpdates(DEFS_URL);
}
void QmlUpdater::updateChangelog(const QString &url) {
QString log = m_updater->getChangelog(url);
qDebug() << "updateChangelog " << log;
if (url == DEFS_URL) {
// setChangeLog(log);
}
}
void QmlUpdater::displayAppcast(const QString &url, const QByteArray &reply) {
if (url != DEFS_URL) {
return;
}
/* Try to create a JSON document from downloaded data */
QJsonDocument document = QJsonDocument::fromJson(reply);
/* JSON is invalid */
if (document.isNull()) {
qDebug() << " update json is error!!";
return;
}
/* Get the platform information */
QJsonObject updates = document.object().value("updates").toObject();
QJsonObject platform =
updates.value(m_updater->getPlatformKey(url)).toObject();
/* Get update information */
QString m_openUrl = platform.value("open-url").toString();
QString m_changelog = platform.value("changelog").toString();
m_downloadUrl = platform.value("download-url").toString();
QString m_latestVersion = platform.value("latest-version").toString();
if (platform.contains("mandatory-update")) {
bool m_mandatoryUpdate = platform.value("mandatory-update").toBool();
}
if (compare(m_latestVersion, m_updater->getModuleVersion(url))) {
emit notifyUpdate(m_latestVersion, m_updater->getModuleName(url),
m_changelog);
}
}
void QmlUpdater::finish(QString filepath) {
QDesktopServices::openUrl(QUrl::fromLocalFile(filepath));
}
void QmlUpdater::startDownload() {
QString path = QCoreApplication::applicationDirPath() + "/../"; //下载文件保存地址
QString filename = m_downloadUrl.split("/").last(); //文件名
qDebug() << "download path" << path;
qDebug() << "download url" << m_downloadUrl << " file name " << filename;
m_downloader->setUseCustomInstallProcedures(true);
m_downloader->setUrlId(DEFS_URL);
m_downloader->setDownloadDir(path);
m_downloader->setFileName(filename);
m_downloader->setMandatoryUpdate(true);
m_downloader->startDownload(QUrl(m_downloadUrl));
}
bool QmlUpdater::compare(const QString &x, const QString &y) {
QStringList versionsX = x.split(".");
QStringList versionsY = y.split(".");
int count = qMin(versionsX.count(), versionsY.count());
for (int i = 0; i < count; ++i) {
int a = QString(versionsX.at(i)).toInt();
int b = QString(versionsY.at(i)).toInt();
if (a > b)
return true;
else if (b > a)
return false;
}
return versionsY.count() < versionsX.count();
}
头文件qmlUpdater.h
#ifndef UPDATER_H
#define UPDATER_H
#include <QObject>
#include <QSimpleUpdater.h>
#include <QSimpleUpdater/src/Downloader.h>
namespace Ui {
class QmlUpdater;
}
class QSimpleUpdater;
class QmlUpdater : public QObject {
Q_OBJECT
public:
explicit QmlUpdater(QObject *parent = nullptr);
~QmlUpdater();
Q_INVOKABLE void checkForUpdates();
Q_INVOKABLE void startDownload();
public slots:
void finish(QString filepath);
private slots:
void updateChangelog(const QString &url);
void displayAppcast(const QString &url, const QByteArray &reply);
private:
bool compare(const QString &x, const QString &y);
signals:
void notifyUpdate(QString ver, QString name, QString log);
void downloadFinished(const QString &url, const QString &filepath);
private:
QString DEFS_URL = "http://wiki.developlink.cloud/vcom/updates.json"; //更新文件json地址
QString m_downloadUrl;
QSimpleUpdater *m_updater;
Downloader *m_downloader;
};
#endif // UPDATER_H
qml 文件 UpdatePage.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import QtQuick.Window 2.2
import QmlUpdater 1.0
Window {
id: root
property int space: 10
property real progressValue: 0
width: 400
height: 300
QmlUpdater {
id: updater
onNotifyUpdate: {
root.visible = true
infoLabel.text = "发现新版本: " + ver + " " + name
logText.text = log
}
onDownloadFinished: {
console.log("onDownloadFinished")
updater.finish(filepath)
Qt.quit()
}
}
Rectangle {
id: rectangle
ProgressBar {
id: progressBar
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: space
anchors.rightMargin: space
height: 30
from: 0
to: 100
value: progressValue
onValueChanged: {
//console.log("valueChanged:"+progressValue)
if (value > 0 && value < 100)
okBtn.enabled = false
else
okBtn.enabled = true
}
}
TextEdit {
id: logText
width: 341
height: 150
text: ""
wrapMode: Text.WrapAnywhere
anchors.top: tipLabel.bottom
readOnly: true
anchors.left: tipLabel.left
anchors.leftMargin: 0
anchors.topMargin: 0
}
Button {
id: cancleBtn
y: 243
width: 80
text: "取消"
anchors.bottom: parent.top
anchors.bottomMargin: -291
anchors.left: parent.left
anchors.leftMargin: 101
font.bold: true
font.pointSize: 12
onClicked: close()
}
Button {
id: okBtn
width: 80
text: "更新"
font.bold: true
font.pointSize: 12
anchors.left: cancleBtn.right
anchors.leftMargin: 45
anchors.top: cancleBtn.bottom
anchors.topMargin: -48
highlighted: true
onClicked: updater.startDownload()
}
Label {
id: infoLabel
text: "没有可用升级!"
font.pointSize: 10
anchors.left: parent.left
anchors.leftMargin: 27
anchors.top: parent.top
anchors.topMargin: 25
}
Label {
id: tipLabel
width: 129
height: 30
text: qsTr("更新内容:")
font.bold: true
anchors.left: infoLabel.left
anchors.leftMargin: 0
anchors.top: infoLabel.bottom
anchors.topMargin: 10
font.pointSize: 12
}
}
}
/*##^##
Designer {
D{i:4;anchors_x:27;anchors_y:81}D{i:5;anchors_x:98;anchors_y:298}D{i:6;anchors_x:235;anchors_y:298}
D{i:7;anchors_x:57;anchors_y:136}D{i:8;anchors_x:57;anchors_y:100}
}
##^##*/
使用
- main 里面注册qml类型
qmlRegisterType<QmlUpdater>("QmlUpdater", 1, 0, "QmlUpdater");
- qml main page 里面实例化
import QtQuick 2.12
import QtQuick.Controls 2.5
import Qt.labs.settings 1.0
ApplicationWindow {
visible: true
width: 800
height: 640
UpdatePage {
id: updatepage
visible: false
}
}
就这样,程序运行后自动检查更新服务器更新json文件;
- 服务器json文件,修改对应的verison,新程序下载链接,更新记录
{
"updates": {
"windows": {
"open-url": "",
"latest-version": "1.0",
"download-url": "https://raw.githubusercontent.com/alex-spataru/QSimpleUpdater/master/tutorial/download/YesItWorks.jpg",
"changelog": "This is an example changelog for Windows. Go on...",
"mandatory": true
},
"osx": {
"open-url": "",
"latest-version": "1.0",
"download-url": "https://raw.githubusercontent.com/alex-spataru/QSimpleUpdater/master/tutorial/download/YesItWorks.jpg",
"changelog": "This is an example changelog for Mac OS X. Go on...",
"mandatory": true
},
"linux": {
"open-url": "",
"latest-version": "1.0",
"download-url": "https://raw.githubusercontent.com/alex-spataru/QSimpleUpdater/master/tutorial/download/YesItWorks.jpg",
"changelog": "This is an example changelog for Linux. Go on...",
"mandatory": true
},
"ios": {
"open-url": "",
"latest-version": "1.0",
"download-url": "https://raw.githubusercontent.com/alex-spataru/QSimpleUpdater/master/tutorial/download/YesItWorks.jpg",
"changelog": "This is an example changelog for iOS. Go on...",
"mandatory": true
},
"android": {
"open-url": "",
"latest-version": "1.0",
"download-url": "https://raw.githubusercontent.com/alex-spataru/QSimpleUpdater/master/tutorial/download/YesItWorks.jpg",
"changelog": "This is an example changelog for Android. Go on...",
"mandatory": true
}
}
}