Improved web-update to actually check for new versions and initiate a download.
This commit is contained in:
parent
d51294e088
commit
c78a3c4990
@ -505,9 +505,15 @@
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>http://www.example.com/update_info.html</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
BIN
res/buttons/shield_grey.png
Normal file
BIN
res/buttons/shield_grey.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
@ -39,6 +39,7 @@
|
||||
<file>buttons/shield_error.png</file>
|
||||
<file>buttons/shield_exclamation.png</file>
|
||||
<file>buttons/shield_green.png</file>
|
||||
<file>buttons/shield_grey.png</file>
|
||||
<file>buttons/suspended.png</file>
|
||||
<file>buttons/transmit.png</file>
|
||||
<file>buttons/trash.png</file>
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,12 @@
|
||||
#include <QCloseEvent>
|
||||
#include <QTimer>
|
||||
#include <QMessageBox>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
#include <QProcess>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QMap>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -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.<br>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();
|
||||
@ -181,23 +218,29 @@ void UpdaterDialog::checkForUpdates(void)
|
||||
//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:
|
||||
case UpdateCheckThread::UpdateStatus_ErrorConnectionTestFailed:
|
||||
case UpdateCheckThread::UpdateStatus_ErrorFetchUpdateInfo:
|
||||
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;
|
||||
default:
|
||||
throw "Unknown status code!";
|
||||
}
|
||||
|
||||
switch(status)
|
||||
{
|
||||
case UpdateCheckThread::UpdateStatus_CompletedUpdateAvailable:
|
||||
case UpdateCheckThread::UpdateStatus_CompletedNoUpdates:
|
||||
case UpdateCheckThread::UpdateStatus_CompletedNewVersionOlder:
|
||||
UPDATE_ICON(2, "shield_green");
|
||||
UPDATE_TEXT(2, tr("Update-information was received successfully."));
|
||||
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();
|
||||
|
||||
//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(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("<a href=\"%1\">%1</a>").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<QString, QString> 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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user