diff --git a/fvupdater.cpp b/fvupdater.cpp index 77e2d91..487c69a 100644 --- a/fvupdater.cpp +++ b/fvupdater.cpp @@ -54,6 +54,7 @@ void FvUpdater::drop() FvUpdater::FvUpdater() : QObject(0) { + m_reply = 0; m_updaterWindow = 0; m_updateConfirmationDialog = 0; m_proposedUpdate = 0; @@ -114,6 +115,13 @@ void FvUpdater::hideUpdaterWindow() } } +void FvUpdater::updaterWindowWasClosed() +{ + // (Re-)nullify a pointer to a destroyed QWidget or you're going to have a bad time. + m_updaterWindow = 0; +} + + void FvUpdater::showUpdateConfirmationDialogUpdatedWithCurrentUpdateProposal() { // Destroy dialog if already exists @@ -138,6 +146,13 @@ void FvUpdater::hideUpdateConfirmationDialog() } } +void FvUpdater::updateConfirmationDialogWasClosed() +{ + // (Re-)nullify a pointer to a destroyed QWidget or you're going to have a bad time. + m_updateConfirmationDialog = 0; +} + + void FvUpdater::SetFeedURL(QUrl feedURL) { m_feedURL = feedURL; @@ -203,7 +218,7 @@ void FvUpdater::UpdateInstallationConfirmed() // Open a link if (! QDesktopServices::openUrl(proposedUpdate->GetEnclosureUrl())) { - showErrorDialog("Unable to open this link in a browser. Please do it manually."); + showErrorDialog(tr("Unable to open this link in a browser. Please do it manually."), true); return; } @@ -220,14 +235,14 @@ void FvUpdater::UpdateInstallationNotConfirmed() } -bool FvUpdater::CheckForUpdates(bool notifyAboutUpToDateApplication) +bool FvUpdater::CheckForUpdates(bool silentAsMuchAsItCouldGet) { if (m_feedURL.isEmpty()) { qCritical() << "Please set feed URL via setFeedURL() before calling CheckForUpdates()."; return false; } - m_showDialogEvenIfNoUpdatesWereFound = notifyAboutUpToDateApplication; + m_silentAsMuchAsItCouldGet = silentAsMuchAsItCouldGet; // Check if application's organization name and domain are set, fail otherwise // (nowhere to store QSettings to) @@ -252,12 +267,24 @@ bool FvUpdater::CheckForUpdates(bool notifyAboutUpToDateApplication) QApplication::setApplicationVersion(appVersion); } + cancelDownloadFeed(); m_httpRequestAborted = false; startDownloadFeed(m_feedURL); return true; } +bool FvUpdater::CheckForUpdatesSilent() +{ + return CheckForUpdates(true); +} + +bool FvUpdater::CheckForUpdatesNotSilent() +{ + return CheckForUpdates(false); +} + + void FvUpdater::startDownloadFeed(QUrl url) { m_xml.clear(); @@ -271,8 +298,10 @@ void FvUpdater::startDownloadFeed(QUrl url) void FvUpdater::cancelDownloadFeed() { - m_httpRequestAborted = true; - m_reply->abort(); + if (m_reply) { + m_httpRequestAborted = true; + m_reply->abort(); + } } void FvUpdater::httpFeedReadyRead() @@ -306,7 +335,7 @@ void FvUpdater::httpFeedDownloadFinished() if (m_reply->error()) { // Error. - showErrorDialog(tr("Feed download failed: %1.").arg(m_reply->errorString())); + showErrorDialog(tr("Feed download failed: %1.").arg(m_reply->errorString()), false); } else if (! redirectionTarget.isNull()) { QUrl newUrl = m_feedURL.resolved(redirectionTarget.toUrl()); @@ -439,7 +468,7 @@ bool FvUpdater::xmlParseFeed() if (m_xml.error() && m_xml.error() != QXmlStreamReader::PrematureEndOfDocumentError) { - showErrorDialog(tr("Feed parsing failed: %1 %2.").arg(QString::number(m_xml.lineNumber()), m_xml.errorString())); + showErrorDialog(tr("Feed parsing failed: %1 %2.").arg(QString::number(m_xml.lineNumber()), m_xml.errorString()), false); return false; } @@ -467,7 +496,7 @@ bool FvUpdater::searchDownloadedFeedForUpdates(QString xmlTitle, // Validate if (xmlReleaseNotesLink.isEmpty()) { if (xmlLink.isEmpty()) { - showErrorDialog("Feed error: \"release notes\" link is empty"); + showErrorDialog(tr("Feed error: \"release notes\" link is empty"), false); return false; } else { xmlReleaseNotesLink = xmlLink; @@ -476,11 +505,11 @@ bool FvUpdater::searchDownloadedFeedForUpdates(QString xmlTitle, xmlLink = xmlReleaseNotesLink; } if (! (xmlLink.startsWith("http://") || xmlLink.startsWith("https://"))) { - showErrorDialog("Feed error: invalid \"release notes\" link"); + showErrorDialog(tr("Feed error: invalid \"release notes\" link"), false); return false; } if (xmlEnclosureUrl.isEmpty() || xmlEnclosureVersion.isEmpty() || xmlEnclosurePlatform.isEmpty()) { - showErrorDialog("Feed error: invalid \"enclosure\" with the download link"); + showErrorDialog(tr("Feed error: invalid \"enclosure\" with the download link"), false); return false; } @@ -488,11 +517,7 @@ bool FvUpdater::searchDownloadedFeedForUpdates(QString xmlTitle, if (FVIgnoredVersions::VersionIsIgnored(xmlEnclosureVersion)) { qDebug() << "Version '" << xmlEnclosureVersion << "' is ignored, too old or something like that."; - if (m_showDialogEvenIfNoUpdatesWereFound) { - QMessageBox msgBox; - msgBox.setText(tr("No updates were found.")); - msgBox.exec(); - } + showInformationDialog(tr("No updates were found."), false); return true; // Things have succeeded when you think of it. } @@ -523,8 +548,15 @@ bool FvUpdater::searchDownloadedFeedForUpdates(QString xmlTitle, } -void FvUpdater::showErrorDialog(QString message) +void FvUpdater::showErrorDialog(QString message, bool showEvenInSilentMode) { + if (m_silentAsMuchAsItCouldGet) { + if (! showEvenInSilentMode) { + // Don't show errors in the silent mode + return; + } + } + QMessageBox dlFailedMsgBox; dlFailedMsgBox.setIcon(QMessageBox::Critical); dlFailedMsgBox.setText(tr("Error")); @@ -532,8 +564,15 @@ void FvUpdater::showErrorDialog(QString message) dlFailedMsgBox.exec(); } -void FvUpdater::showInformationDialog(QString message) +void FvUpdater::showInformationDialog(QString message, bool showEvenInSilentMode) { + if (m_silentAsMuchAsItCouldGet) { + if (! showEvenInSilentMode) { + // Don't show information dialogs in the silent mode + return; + } + } + QMessageBox dlInformationMsgBox; dlInformationMsgBox.setIcon(QMessageBox::Information); dlInformationMsgBox.setText(tr("Information")); diff --git a/fvupdater.h b/fvupdater.h index f70887e..04b69fa 100644 --- a/fvupdater.h +++ b/fvupdater.h @@ -29,7 +29,11 @@ class FvUpdater : public QObject public slots: // Check for updates - bool CheckForUpdates(bool notifyAboutUpToDateApplication = false); + bool CheckForUpdates(bool silentAsMuchAsItCouldGet = true); + + // Aliases + bool CheckForUpdatesSilent(); + bool CheckForUpdatesNotSilent(); // @@ -41,8 +45,8 @@ public slots: protected: - friend class FvUpdateWindow; // Uses GetProposedUpdate() - friend class FvUpdateConfirmDialog; // Uses GetProposedUpdate() + friend class FvUpdateWindow; // Uses GetProposedUpdate() and others + friend class FvUpdateConfirmDialog; // Uses GetProposedUpdate() and others FvAvailableUpdate* GetProposedUpdate(); @@ -75,24 +79,27 @@ protected slots: // // Windows / dialogs // - FvUpdateWindow* m_updaterWindow; // Updater window (NULL if not shown) - void showUpdaterWindowUpdatedWithCurrentUpdateProposal(); // Show updater window - void hideUpdaterWindow(); // Hide + destroy m_updaterWindow + FvUpdateWindow* m_updaterWindow; // Updater window (NULL if not shown) + void showUpdaterWindowUpdatedWithCurrentUpdateProposal(); // Show updater window + void hideUpdaterWindow(); // Hide + destroy m_updaterWindow + void updaterWindowWasClosed(); // Sent by the updater window when it gets closed FvUpdateConfirmDialog* m_updateConfirmationDialog; // Update confirmation dialog (NULL if not shown) void showUpdateConfirmationDialogUpdatedWithCurrentUpdateProposal(); // Show update confirmation dialog void hideUpdateConfirmationDialog(); // Hide + destroy m_updateConfirmationDialog + void updateConfirmationDialogWasClosed(); // Sent by the update confirmation dialog when it gets closed // Available update (NULL if not fetched) FvAvailableUpdate* m_proposedUpdate; - // "No updates" dialog was requested and should be shown even if no update was found - // (notifyAboutUpToDateApplication from CheckForUpdates() goes here) - bool m_showDialogEvenIfNoUpdatesWereFound; + // If true, don't show the error dialogs and the "no updates." dialog + // (silentAsMuchAsItCouldGet from CheckForUpdates() goes here) + // Useful for automatic update checking upon application startup. + bool m_silentAsMuchAsItCouldGet; // Dialogs (notifications) - void showErrorDialog(QString message); // Show an error message - void showInformationDialog(QString message); // Show an informational message + void showErrorDialog(QString message, bool showEvenInSilentMode = false); // Show an error message + void showInformationDialog(QString message, bool showEvenInSilentMode = false); // Show an informational message // diff --git a/sample/mainwindow.cpp b/sample/mainwindow.cpp index 98d4a2a..9dd3f9d 100644 --- a/sample/mainwindow.cpp +++ b/sample/mainwindow.cpp @@ -10,11 +10,9 @@ MainWindow::MainWindow(QWidget *parent) : { ui->setupUi(this); - // Set feed URL before doing anything else - FvUpdater::sharedUpdater()->SetFeedURL("https://raw.github.com/pypt/fervor/master/sample/Appcast.xml"); - // Connect the "check for updates" button with the autoupdater - connect(ui->updateButton, SIGNAL(clicked()), FvUpdater::sharedUpdater(), SLOT(CheckForUpdates())); + connect(ui->updateButton, SIGNAL(clicked()), + FvUpdater::sharedUpdater(), SLOT(CheckForUpdatesNotSilent())); } MainWindow::~MainWindow()