diff --git a/PastorsSermonPro_Setup.exe b/PastorsSermonPro_Setup.exe index 33e8dcf..fa18713 100644 Binary files a/PastorsSermonPro_Setup.exe and b/PastorsSermonPro_Setup.exe differ diff --git a/src/UpdateManager.cpp b/src/UpdateManager.cpp new file mode 100644 index 0000000..8cd93fe --- /dev/null +++ b/src/UpdateManager.cpp @@ -0,0 +1,111 @@ +#include "UpdateManager.h" +#include +#include +#include +#include +#include +#include +#include +#include + +UpdateManager::UpdateManager(const QString& currentVersion, QObject *parent) + : QObject(parent), m_currentVersion(currentVersion), m_downloadFile(nullptr) +{ + m_network = new QNetworkAccessManager(this); +} + +void UpdateManager::checkForUpdates() { + emit checkStarted(); + // We check the raw version.txt on the master branch + QUrl url("https://git.linology.tech/michael/PastorsSermonPro/raw/branch/master/version.txt"); + QNetworkRequest request; + request.setUrl(url); + QNetworkReply* reply = m_network->get(request); + connect(reply, &QNetworkReply::finished, this, &UpdateManager::onVersionFetched); +} + +void UpdateManager::onVersionFetched() { + QNetworkReply* reply = qobject_cast(sender()); + if (!reply) return; + + if (reply->error() == QNetworkReply::NoError) { + m_latestVersion = QString::fromUtf8(reply->readAll()).trimmed(); + + // Smart semantic version comparison + if (!m_latestVersion.isEmpty() && isNewer(m_currentVersion, m_latestVersion)) { + // Construct the download URL for the Windows installer in the release + m_downloadUrl = QString("https://git.linology.tech/michael/PastorsSermonPro/releases/download/v%1/PastorsSermonPro_Setup.exe").arg(m_latestVersion); + emit updateAvailable(m_latestVersion, m_downloadUrl); + } else { + emit noUpdateFound(); + } + } else { + emit errorOccurred("Could not reach update server: " + reply->errorString()); + } + reply->deleteLater(); +} + +void UpdateManager::startDownload(const QString& url) { + m_downloadUrl = url; + QString tempPath = QStandardPaths::writableLocation(QStandardPaths::TempLocation); + QString fileName = tempPath + "/PastorsSermonPro_Update.exe"; + + m_downloadFile = new QFile(fileName, this); + if (!m_downloadFile->open(QIODevice::WriteOnly)) { + emit errorOccurred("Could not create temporary file for download."); + delete m_downloadFile; + m_downloadFile = nullptr; + return; + } + + QNetworkRequest request; + request.setUrl(QUrl(m_downloadUrl)); + QNetworkReply* reply = m_network->get(request); + + connect(reply, &QNetworkReply::downloadProgress, this, &UpdateManager::onDownloadProgress); + connect(reply, &QNetworkReply::finished, this, &UpdateManager::onDownloadFinished); +} + +void UpdateManager::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { + if (bytesTotal > 0) { + int percentage = static_cast((bytesReceived * 100) / bytesTotal); + emit progressUpdated(percentage); + } +} + +void UpdateManager::onDownloadFinished() { + QNetworkReply* reply = qobject_cast(sender()); + if (!reply) return; + + if (reply->error() == QNetworkReply::NoError) { + m_downloadFile->write(reply->readAll()); + m_downloadFile->flush(); + QString filePath = m_downloadFile->fileName(); + m_downloadFile->close(); + + emit downloadFinished(filePath); + + // Launch the installer + QProcess::startDetached(filePath); + } else { + emit errorOccurred("Download failed: " + reply->errorString()); + m_downloadFile->close(); + m_downloadFile->remove(); + } + + reply->deleteLater(); +} + +bool UpdateManager::isNewer(const QString& current, const QString& latest) { + QStringList curParts = current.split('.'); + QStringList latParts = latest.split('.'); + + int maxLen = std::max(curParts.size(), latParts.size()); + for (int i = 0; i < maxLen; ++i) { + int cur = (i < curParts.size()) ? curParts[i].toInt() : 0; + int lat = (i < latParts.size()) ? latParts[i].toInt() : 0; + if (lat > cur) return true; + if (lat < cur) return false; + } + return false; +}