#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; }