From: lordmulder Date: Wed, 11 Dec 2013 14:50:26 +0000 (+0100) Subject: Improved web-update to actually check for new versions and initiate a download. X-Git-Tag: v2.28~6 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=c78a3c49900b6cccd6516c7f8bee766f2c31f56c;p=x264-launcher%2Fx264-launcher.git Improved web-update to actually check for new versions and initiate a download. --- diff --git a/gui/win_updater.ui b/gui/win_updater.ui index db97974..391f33a 100644 --- a/gui/win_updater.ui +++ b/gui/win_updater.ui @@ -505,9 +505,15 @@ true + + PointingHandCursor + http://www.example.com/update_info.html + + Qt::LinksAccessibleByMouse + diff --git a/res/buttons/shield_grey.png b/res/buttons/shield_grey.png new file mode 100644 index 0000000..96e4b55 Binary files /dev/null and b/res/buttons/shield_grey.png differ diff --git a/res/resources.qrc b/res/resources.qrc index b66230e..c1335fb 100644 --- a/res/resources.qrc +++ b/res/resources.qrc @@ -39,6 +39,7 @@ buttons/shield_error.png buttons/shield_exclamation.png buttons/shield_green.png + buttons/shield_grey.png buttons/suspended.png buttons/transmit.png buttons/trash.png diff --git a/src/version.h b/src/version.h index c36c07c..0733844 100644 --- a/src/version.h +++ b/src/version.h @@ -26,7 +26,7 @@ #define VER_X264_MAJOR 2 #define VER_X264_MINOR 2 #define VER_X264_PATCH 7 -#define VER_X264_BUILD 686 +#define VER_X264_BUILD 691 #define VER_X264_MINIMUM_REV 2363 #define VER_X264_CURRENT_API 140 diff --git a/src/win_main.cpp b/src/win_main.cpp index 1f77a69..a03426d 100644 --- a/src/win_main.cpp +++ b/src/win_main.cpp @@ -978,7 +978,15 @@ void MainWindow::checkUpdates(void) } UpdaterDialog *updater = new UpdaterDialog(this, QString("%1/toolset").arg(m_appDir)); - updater->exec(); + const int ret = updater->exec(); + + if(ret == 42) + { + X264_DELETE(updater); + qWarning("Exitting to install update..."); + close(); + } + X264_DELETE(updater); } diff --git a/src/win_updater.cpp b/src/win_updater.cpp index f030b49..6e7d094 100644 --- a/src/win_updater.cpp +++ b/src/win_updater.cpp @@ -30,6 +30,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include /////////////////////////////////////////////////////////////////////////////// @@ -56,6 +62,7 @@ UpdaterDialog::UpdaterDialog(QWidget *parent, const QString &binDir) QDialog(parent), ui(new Ui::UpdaterDialog()), m_binDir(binDir), + m_status(UpdateCheckThread::UpdateStatus_NotStartedYet), m_thread(NULL), m_firstShow(true) { @@ -66,6 +73,14 @@ UpdaterDialog::UpdaterDialog(QWidget *parent, const QString &binDir) //Fix size setFixedSize(size()); + //Enable buttons + connect(ui->buttonCancel, SIGNAL(clicked()), this, SLOT(close())); + connect(ui->buttonDownload, SIGNAL(clicked()), this, SLOT(installUpdate())); + connect(ui->buttonRetry, SIGNAL(clicked()), this, SLOT(checkForUpdates())); + + //Enable info label + connect(ui->labelUrl, SIGNAL(linkActivated(QString)), this, SLOT(openUrl(QString))); + //Init animation m_animator = new QMovie(":/images/loading.gif"); ui->labelLoadingCenter->setMovie(m_animator); @@ -92,6 +107,13 @@ UpdaterDialog::~UpdaterDialog(void) } } + if((!m_keysFile.isEmpty()) && QFile::exists(m_keysFile)) + { + QFile::setPermissions(m_keysFile, QFile::ReadOwner | QFile::WriteOwner); + QFile::remove(m_keysFile); + m_keysFile.clear(); + } + X264_DELETE(m_thread); X264_DELETE(m_animator); @@ -125,21 +147,34 @@ void UpdaterDialog::closeEvent(QCloseEvent *e) } } +void UpdaterDialog::keyPressEvent(QKeyEvent *event) +{ + if(event->key() == Qt::Key_F11) + { + QFile logFile(QString("%1/%2.log").arg(x264_temp_directory(), x264_rand_str())); + if(logFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) + { + logFile.write("\xEF\xBB\xBF"); + for(QStringList::ConstIterator iter = m_logFile.constBegin(); iter != m_logFile.constEnd(); iter++) + { + logFile.write(iter->toUtf8()); + logFile.write("\r\n"); + } + logFile.close(); + QDesktopServices::openUrl(QUrl::fromLocalFile(logFile.fileName())); + } + } +} + /////////////////////////////////////////////////////////////////////////////// // Slots /////////////////////////////////////////////////////////////////////////////// void UpdaterDialog::initUpdate(void) { - - //Reset icons - - - //Show animation - //Check binary files - QStringList binaries; - if(!checkBinaries(binaries)) + QString wgetBin, gpgvBin; + if(!checkBinaries(wgetBin, gpgvBin)) { ui->buttonCancel->setEnabled(true); QMessageBox::critical(this, tr("File Error"), tr("At least one file required by web-update is missing or corrupted.
Please re-install this application and then try again!")); @@ -150,16 +185,15 @@ void UpdaterDialog::initUpdate(void) //Create and setup thread if(!m_thread) { - m_thread = new UpdateCheckThread(binaries[0], binaries[1], binaries[2], false); + m_thread = new UpdateCheckThread(wgetBin, gpgvBin, m_keysFile, false); connect(m_thread, SIGNAL(statusChanged(int)), this, SLOT(threadStatusChanged(int))); - connect(m_thread, SIGNAL(progressChanged(int)), this, SLOT(threadProgressChanged(int))); - connect(m_thread, SIGNAL(messageLogged(QString)), this, SLOT(threadMessageLogged(QString))); connect(m_thread, SIGNAL(finished()), this, SLOT(threadFinished())); connect(m_thread, SIGNAL(terminated()), this, SLOT(threadFinished())); + connect(m_thread, SIGNAL(messageLogged(QString)), this, SLOT(threadMessageLogged(QString))); } - //Begin updater test run - QTimer::singleShot(0, this, SLOT(checkForUpdates())); + //Begin updater run + QTimer::singleShot(125, this, SLOT(checkForUpdates())); } void UpdaterDialog::checkForUpdates(void) @@ -169,6 +203,9 @@ void UpdaterDialog::checkForUpdates(void) qWarning("Update in progress, cannot check for updates now!"); } + //Clear texts + ui->retranslateUi(this); + //Init buttons ui->buttonCancel->setEnabled(false); ui->buttonRetry->hide(); @@ -177,27 +214,33 @@ void UpdaterDialog::checkForUpdates(void) //Hide labels ui->labelInfo->hide(); ui->labelUrl->hide(); - + //Update status threadStatusChanged(UpdateCheckThread::UpdateStatus_NotStartedYet); + //Start animation + SHOW_ANIMATION(true); + m_animator->start(); + //Update cursor QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); QApplication::setOverrideCursor(Qt::WaitCursor); + //Clear log + m_logFile.clear(); + //Start the updater thread - m_thread->start(); + QTimer::singleShot(125, m_thread, SLOT(start())); } void UpdaterDialog::threadStatusChanged(int status) { - switch(status) + switch(m_status = status) { case UpdateCheckThread::UpdateStatus_NotStartedYet: UPDATE_ICON(1, "clock"); UPDATE_ICON(2, "clock"); UPDATE_ICON(3, "clock"); - ui->retranslateUi(this); break; case UpdateCheckThread::UpdateStatus_CheckingConnection: UPDATE_ICON(1, "play"); @@ -207,40 +250,153 @@ void UpdaterDialog::threadStatusChanged(int status) UPDATE_TEXT(1, tr("Internet connection is working.")); UPDATE_ICON(2, "play"); break; - case UpdateCheckThread::UpdateStatus_CompletedUpdateAvailable: - UPDATE_ICON(3, "shield_exclamation"); - UPDATE_TEXT(3, tr("A newer version is available!")); - break; case UpdateCheckThread::UpdateStatus_ErrorNoConnection: + UPDATE_ICON(1, "shield_error"); + UPDATE_TEXT(1, tr("Computer is currently offline!")); + UPDATE_ICON(2, "shield_grey"); + UPDATE_ICON(3, "shield_grey"); + break; case UpdateCheckThread::UpdateStatus_ErrorConnectionTestFailed: + UPDATE_ICON(1, "shield_error"); + UPDATE_TEXT(1, tr("Internet connectivity test failed!")); + UPDATE_ICON(2, "shield_grey"); + UPDATE_ICON(3, "shield_grey"); + break; case UpdateCheckThread::UpdateStatus_ErrorFetchUpdateInfo: + UPDATE_ICON(2, "shield_error"); + UPDATE_TEXT(2, tr("Failed to download the update information!")); + UPDATE_ICON(3, "shield_grey"); + break; + case UpdateCheckThread::UpdateStatus_CompletedUpdateAvailable: + case UpdateCheckThread::UpdateStatus_CompletedNoUpdates: + case UpdateCheckThread::UpdateStatus_CompletedNewVersionOlder: + UPDATE_ICON(2, "shield_green"); + UPDATE_TEXT(2, tr("Update information received successfully.")); + UPDATE_ICON(3, "play"); break; default: throw "Unknown status code!"; } +} + +void UpdaterDialog::threadFinished(void) +{ + //Restore cursor + QApplication::restoreOverrideCursor(); + + //Stop animation + m_animator->stop(); - switch(status) + //Process final updater state + switch(m_status) { case UpdateCheckThread::UpdateStatus_CompletedUpdateAvailable: + UPDATE_ICON(3, "shield_exclamation"); + UPDATE_TEXT(3, tr("A newer version is available!")); + ui->buttonDownload->show(); + break; case UpdateCheckThread::UpdateStatus_CompletedNoUpdates: + UPDATE_ICON(3, "shield_green"); + UPDATE_TEXT(3, tr("Your version is up-to-date.")); + break; case UpdateCheckThread::UpdateStatus_CompletedNewVersionOlder: - UPDATE_ICON(2, "shield_green"); - UPDATE_TEXT(2, tr("Update-information was received successfully.")); - ui->buttonDownload->show(); + UPDATE_ICON(3, "shield_error"); + UPDATE_TEXT(3, tr("Your are using a pre-release version!")); + break; + } + + //Show update info or retry button + switch(m_status) + { + case UpdateCheckThread::UpdateStatus_CompletedUpdateAvailable: + case UpdateCheckThread::UpdateStatus_CompletedNoUpdates: + case UpdateCheckThread::UpdateStatus_CompletedNewVersionOlder: + SHOW_ANIMATION(false); + ui->labelUrl->setText(QString("%1").arg(m_thread->getUpdateInfo()->m_downloadSite)); + break; case UpdateCheckThread::UpdateStatus_ErrorNoConnection: case UpdateCheckThread::UpdateStatus_ErrorConnectionTestFailed: case UpdateCheckThread::UpdateStatus_ErrorFetchUpdateInfo: - SHOW_ANIMATION(false); - ui->buttonCancel->setEnabled(true); + ui->buttonRetry->show(); break; } + + //Re-enbale cancel button + ui->buttonCancel->setEnabled(true); + +} + +void UpdaterDialog::threadMessageLogged(const QString &message) +{ + m_logFile << message; +} + +void UpdaterDialog::openUrl(const QString &url) +{ + qDebug("Open URL: %s", url.toLatin1().constData()); + QDesktopServices::openUrl(QUrl(url)); +} + +void UpdaterDialog::installUpdate(void) +{ + if(!((m_thread) && m_thread->getSuccess())) + { + qWarning("Cannot download/install update at this point!"); + return; + } + + const UpdateInfo *updateInfo = m_thread->getUpdateInfo(); + + QProcess process; + QStringList args; + QEventLoop loop; + + x264_init_process(process, x264_temp_directory(), false); + + connect(&process, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit())); + connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)), &loop, SLOT(quit())); + + args << QString("/Location=%1").arg(updateInfo->m_downloadAddress); + args << QString("/Filename=%1").arg(updateInfo->m_downloadFilename); + args << QString("/TicketID=%1").arg(updateInfo->m_downloadFilecode); + args << QString("/ToFolder=%1").arg(QDir::toNativeSeparators(QDir(QApplication::applicationDirPath()).canonicalPath())); + args << QString("/ToExFile=%1.exe").arg(QFileInfo(QFileInfo(QApplication::applicationFilePath()).canonicalFilePath()).completeBaseName()); + args << QString("/AppTitle=Simple x264 Launcher (Build #%1)").arg(QString::number(updateInfo->m_buildNo)); + + process.start(m_wupdFile, args); + if(!process.waitForStarted()) + { + QMessageBox::critical(this, tr("Update Failed"), tr("Sorry, failed to launch web-update program!")); + return; + } + + QApplication::setOverrideCursor(Qt::WaitCursor); + ui->buttonDownload->hide(); + ui->buttonCancel->setEnabled(false); + + loop.exec(QEventLoop::ExcludeUserInputEvents); + + if(!process.waitForFinished()) + { + process.kill(); + process.waitForFinished(); + } + + QApplication::restoreOverrideCursor(); + ui->buttonDownload->show(); + ui->buttonCancel->setEnabled(true); + + if(process.exitCode() == 0) + { + done(42); + } } /////////////////////////////////////////////////////////////////////////////// // Private Functions /////////////////////////////////////////////////////////////////////////////// -bool UpdaterDialog::checkBinaries(QStringList &binaries) +bool UpdaterDialog::checkBinaries(QString &wgetBin, QString &gpgvBin) { qDebug("[File Verification]"); @@ -254,24 +410,41 @@ bool UpdaterDialog::checkBinaries(QStringList &binaries) { "wget.exe", "7b522345239bcb95b5b0f7f50a883ba5957894a1feb769763e38ed789a8a0f63fead0155f54b9ffd0f1cdc5dfd855d207a6e7a8e4fd192589a8838ce646c504e" }, { "gpgv.exe", "e61d28e4c47b2422ceec7b8fc08f9c70f10a3056e3779a974026eb24fe09551eedc2e7f34fbe5ef8e844fab0dbe68b85c4ca69d63bf85d445f7cae152c17f589" }, { "gpgv.gpg", "58e0f0e462bbd0b5aa4f638801c1097da7da4b3eb38c8c88ad1db23705c0f11e174b083fa55fe76bd3ba196341c967833a6f3427d6f63ad8565900745535d8fa" }, + { "wupd.exe", "9dd0ae5f386aaf5df9e261a53b81569df51bccf2f9290ed42f04a5b52b4a4e1118f2c9ce3a9b2492fd5ae597600411dfa47bd7c96e2fd7bee205d603324452a2" }, { NULL, NULL } }; + QMap binaries; + + m_keysFile.clear(); + m_wupdFile.clear(); + wgetBin.clear(); + gpgvBin.clear(); + bool okay = true; - binaries.clear(); for(size_t i = 0; FILE_INFO[i].name; i++) { const QString binPath = QString("%1/common/%2").arg(m_binDir, QString::fromLatin1(FILE_INFO[i].name)); if(okay = okay && checkFileHash(binPath, FILE_INFO[i].hash)) { - binaries << binPath; + binaries.insert(FILE_INFO[i].name, binPath); } } if(okay) { - qDebug("Completed.\n"); + wgetBin = binaries.value("wget.exe"); + gpgvBin = binaries.value("gpgv.exe"); + + m_wupdFile = binaries.value("wupd.exe"); + m_keysFile = QString("%1/%2.gpg").arg(x264_temp_directory(), x264_rand_str()); + + if(okay = QFile::copy(binaries.value("gpgv.gpg"), m_keysFile)) + { + QFile::setPermissions(m_keysFile, QFile::ReadOwner); + } + qDebug("%s\n", okay ? "Completed." : "Failed to copy GPG file!"); } return okay; diff --git a/src/win_updater.h b/src/win_updater.h index bb3f62d..3afe5e4 100644 --- a/src/win_updater.h +++ b/src/win_updater.h @@ -42,20 +42,29 @@ public: protected: virtual void showEvent(QShowEvent *event); virtual void closeEvent(QCloseEvent *e); + virtual void keyPressEvent(QKeyEvent *event); private slots: void initUpdate(void); void checkForUpdates(void); void threadStatusChanged(int status); + void threadMessageLogged(const QString &message); + void threadFinished(void); + void openUrl(const QString &url); + void installUpdate(void); private: Ui::UpdaterDialog *const ui; - bool checkBinaries(QStringList &binaries); + bool checkBinaries(QString &wgetBin, QString &gpgvBin); bool checkFileHash(const QString &filePath, const char *expectedHash); bool m_firstShow; const QString m_binDir; - UpdateCheckThread *m_thread; QMovie *m_animator; + UpdateCheckThread *m_thread; + QStringList m_logFile; + QString m_keysFile; + QString m_wupdFile; + int m_status; };