3
* VBox frontends: Qt4 GUI ("VirtualBox"):
4
* VBoxUpdateDlg class implementation
8
* Copyright (C) 2006-2011 Oracle Corporation
10
* This file is part of VirtualBox Open Source Edition (OSE), as
11
* available from http://www.virtualbox.org. This file is free software;
12
* you can redistribute it and/or modify it under the terms of the GNU
13
* General Public License (GPL) as published by the Free Software
14
* Foundation, in version 2 as it comes in the "COPYING" file of the
15
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
#ifdef VBOX_WITH_PRECOMPILED_HEADERS
21
#else /* !VBOX_WITH_PRECOMPILED_HEADERS */
23
#include <QNetworkAccessManager>
24
#include <QNetworkReply>
26
#include "VBoxUpdateDlg.h"
27
#include "VBoxGlobal.h"
28
#include "UIMessageCenter.h"
29
#include "UIIconPool.h"
30
#include "VBoxUtils.h"
31
#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
34
* This class is used to store VBox version data.
40
VBoxVersion(const QString &strVersion)
43
QStringList versionStack = strVersion.split('.');
44
if (versionStack.size() > 0)
45
x = versionStack[0].toInt();
46
if (versionStack.size() > 1)
47
y = versionStack[1].toInt();
48
if (versionStack.size() > 2)
49
z = versionStack[2].toInt();
52
bool operator<(const VBoxVersion &other) const
54
return (x < other.x) ||
55
(x == other.x && y < other.y) ||
56
(x == other.x && y == other.y && z < other.z);
59
QString toString() const
61
return QString("%1.%2.%3").arg(x).arg(y).arg(z);
71
/* VBoxUpdateData stuff: */
72
QList<UpdateDay> VBoxUpdateData::m_dayList = QList<UpdateDay>();
74
void VBoxUpdateData::populate()
78
/* To avoid re-translation complexity all
79
* have to be retranslated separately: */
81
/* Separately retranslate each day: */
82
m_dayList << UpdateDay(VBoxUpdateDlg::tr("1 day"), "1 d");
83
m_dayList << UpdateDay(VBoxUpdateDlg::tr("2 days"), "2 d");
84
m_dayList << UpdateDay(VBoxUpdateDlg::tr("3 days"), "3 d");
85
m_dayList << UpdateDay(VBoxUpdateDlg::tr("4 days"), "4 d");
86
m_dayList << UpdateDay(VBoxUpdateDlg::tr("5 days"), "5 d");
87
m_dayList << UpdateDay(VBoxUpdateDlg::tr("6 days"), "6 d");
89
/* Separately retranslate each week */
90
m_dayList << UpdateDay(VBoxUpdateDlg::tr("1 week"), "1 w");
91
m_dayList << UpdateDay(VBoxUpdateDlg::tr("2 weeks"), "2 w");
92
m_dayList << UpdateDay(VBoxUpdateDlg::tr("3 weeks"), "3 w");
94
/* Separately retranslate each month */
95
m_dayList << UpdateDay(VBoxUpdateDlg::tr("1 month"), "1 m");
98
QStringList VBoxUpdateData::list()
101
for (int i = 0; i < m_dayList.size(); ++i)
102
result << m_dayList[i].val;
106
VBoxUpdateData::VBoxUpdateData(const QString &strData)
108
, m_periodIndex(Period1Day)
109
, m_branchIndex(BranchStable)
114
VBoxUpdateData::VBoxUpdateData(PeriodType periodIndex, BranchType branchIndex)
115
: m_strData(QString())
116
, m_periodIndex(periodIndex)
117
, m_branchIndex(branchIndex)
122
bool VBoxUpdateData::isNecessary()
124
return m_periodIndex != PeriodNever && QDate::currentDate() >= m_date;
127
bool VBoxUpdateData::isNoNeedToCheck()
129
return m_periodIndex == PeriodNever;
132
QString VBoxUpdateData::data() const
137
VBoxUpdateData::PeriodType VBoxUpdateData::periodIndex() const
139
return m_periodIndex;
142
QString VBoxUpdateData::date() const
144
return m_periodIndex == PeriodNever ? VBoxUpdateDlg::tr("Never")
145
: m_date.toString(Qt::LocaleDate);
148
VBoxUpdateData::BranchType VBoxUpdateData::branchIndex() const
150
return m_branchIndex;
153
QString VBoxUpdateData::branchName() const
155
switch (m_branchIndex)
159
case BranchAllRelease:
161
case BranchWithBetas:
167
void VBoxUpdateData::decode()
169
/* Parse standard values: */
170
if (m_strData == "never")
171
m_periodIndex = PeriodNever;
172
/* Parse other values: */
175
QStringList parser(m_strData.split(", ", QString::SkipEmptyParts));
177
/* Parse 'period' value: */
178
if (parser.size() > 0)
180
if (m_dayList.isEmpty())
182
PeriodType index = (PeriodType)m_dayList.indexOf(UpdateDay(QString(), parser[0]));
183
m_periodIndex = index == PeriodUndefined ? Period1Day : index;
186
/* Parse 'date' value: */
187
if (parser.size() > 1)
189
QDate date = QDate::fromString(parser[1], Qt::ISODate);
190
m_date = date.isValid() ? date : QDate::currentDate();
193
/* Parse 'branch' value: */
194
if (parser.size() > 2)
196
QString branch(parser[2]);
197
m_branchIndex = branch == "withbetas" ? BranchWithBetas :
198
branch == "allrelease" ? BranchAllRelease : BranchStable;
203
void VBoxUpdateData::encode()
205
/* Encode standard values: */
206
if (m_periodIndex == PeriodNever)
208
/* Encode other values: */
211
/* Encode 'period' value: */
212
if (m_dayList.isEmpty())
214
QString remindPeriod = m_dayList[m_periodIndex].key;
216
/* Encode 'date' value: */
217
m_date = QDate::currentDate();
218
QStringList parser(remindPeriod.split(' '));
219
if (parser[1] == "d")
220
m_date = m_date.addDays(parser[0].toInt());
221
else if (parser[1] == "w")
222
m_date = m_date.addDays(parser[0].toInt() * 7);
223
else if (parser[1] == "m")
224
m_date = m_date.addMonths(parser[0].toInt());
225
QString remindDate = m_date.toString(Qt::ISODate);
227
/* Encode 'branch' value: */
228
QString branchValue = m_branchIndex == BranchWithBetas ? "withbetas" :
229
m_branchIndex == BranchAllRelease ? "allrelease" : "stable";
231
/* Composite m_strData: */
232
m_strData = QString("%1, %2, %3").arg(remindPeriod, remindDate, branchValue);
236
/* VBoxUpdateDlg stuff: */
237
bool VBoxUpdateDlg::isNecessary()
239
VBoxUpdateData data(vboxGlobal().virtualBox().GetExtraData(VBoxDefs::GUI_UpdateDate));
240
return data.isNecessary();
243
VBoxUpdateDlg::VBoxUpdateDlg(VBoxUpdateDlg **ppSelf, bool fForceRun, QWidget *pParent)
244
: QIWithRetranslateUI<QDialog>(pParent)
246
, m_pNetworkManager(new QNetworkAccessManager(this))
247
, m_url("http://update.virtualbox.org/query.php")
248
, m_fForceRun(fForceRun)
250
/* Store external pointer to this dialog: */
253
/* Apply UI decorations: */
254
Ui::VBoxUpdateDlg::setupUi(this);
256
/* Apply window icons: */
257
setWindowIcon(UIIconPool::iconSetFull(QSize(32, 32), QSize(16, 16),
258
":/refresh_32px.png", ":/refresh_16px.png"));
260
/* Setup other connections: */
261
connect(mBtnCheck, SIGNAL(clicked()), this, SLOT(search()));
262
connect(mBtnFinish, SIGNAL(clicked()), this, SLOT(accept()));
263
connect(this, SIGNAL(sigDelayedAcception()), this, SLOT(accept()), Qt::QueuedConnection);
265
/* Setup initial condition: */
266
mPbCheck->setMinimumWidth(mLogoUpdate->width() + mLogoUpdate->frameWidth() * 2);
268
mTextSuccessInfo->hide();
269
mTextFailureInfo->hide();
270
mTextNotFoundInfo->hide();
272
/* Retranslate string constants: */
276
VBoxUpdateDlg::~VBoxUpdateDlg()
278
/* Erase dialog handle in config file: */
279
vboxGlobal().virtualBox().SetExtraData(VBoxDefs::GUI_UpdateDlgWinID, QString());
281
/* Erase external pointer to this dialog: */
285
void VBoxUpdateDlg::retranslateUi()
287
/* Translate uic generated strings: */
288
Ui::VBoxUpdateDlg::retranslateUi(this);
290
/* For wizard update: */
293
setWindowTitle(tr("VirtualBox Update Wizard"));
295
mPageUpdateHdr->setText(tr("Check for Updates"));
296
mBtnCheck->setText(tr("Chec&k"));
297
mBtnCancel->setText(tr("Cancel"));
299
mPageFinishHdr->setText(tr("Summary"));
300
mBtnFinish->setText(tr("&Close"));
302
mTextUpdateInfo->setText(tr("<p>This wizard will connect to the VirtualBox "
303
"web-site and check if a newer version of "
304
"VirtualBox is available.</p><p>Use the "
305
"<b>Check</b> button to check for a new version "
306
"now or the <b>Cancel</b> button if you do not "
307
"want to perform this check.</p><p>You can run "
308
"this wizard at any time by choosing <b>Check "
309
"for Updates...</b> from the <b>Help</b> menu.</p>"));
311
mTextSuccessInfo->setText(tr("<p>A new version of VirtualBox has been released! "
312
"Version <b>%1</b> is available at "
313
"<a href=\"http://www.virtualbox.org/\">virtualbox.org</a>.</p>"
314
"<p>You can download this version using the link:</p>"
315
"<p><a href=%2>%3</a></p>"));
317
mTextFailureInfo->setText(tr("<p>Unable to obtain the new version information "
318
"due to the following network error:</p><p><b>%1</b></p>"));
320
mTextNotFoundInfo->setText(tr("You are already running the most recent version of VirtualBox."));
324
void VBoxUpdateDlg::accept()
326
/* Recalculate new update data: */
327
VBoxUpdateData oldData(vboxGlobal().virtualBox().GetExtraData(VBoxDefs::GUI_UpdateDate));
328
VBoxUpdateData newData(oldData.periodIndex(), oldData.branchIndex());
329
vboxGlobal().virtualBox().SetExtraData(VBoxDefs::GUI_UpdateDate, newData.data());
330
/* Call to base-class: */
334
void VBoxUpdateDlg::search()
336
/* Calculate the count of checks left: */
338
QString strCount = vboxGlobal().virtualBox().GetExtraData(VBoxDefs::GUI_UpdateCheckCount);
339
if (!strCount.isEmpty())
342
int c = strCount.toLongLong(&ok);
348
url.addQueryItem("platform", vboxGlobal().virtualBox().GetPackageType());
349
/* Branding: Check whether we have a local branding file which tells us our version suffix "FOO"
350
(e.g. 3.06.54321_FOO) to identify this installation */
351
if (vboxGlobal().brandingIsActive())
353
url.addQueryItem("version", QString("%1_%2_%3").arg(vboxGlobal().virtualBox().GetVersion())
354
.arg(vboxGlobal().virtualBox().GetRevision())
355
.arg(vboxGlobal().brandingGetKey("VerSuffix")));
359
/* Use hard coded version set by VBOX_VERSION_STRING: */
360
url.addQueryItem("version", QString("%1_%2").arg(vboxGlobal().virtualBox().GetVersion())
361
.arg(vboxGlobal().virtualBox().GetRevision()));
363
url.addQueryItem("count", QString::number(cCount));
364
url.addQueryItem("branch", VBoxUpdateData(vboxGlobal().virtualBox().
365
GetExtraData(VBoxDefs::GUI_UpdateDate)).branchName());
366
QString strUserAgent(QString("VirtualBox %1 <%2>")
367
.arg(vboxGlobal().virtualBox().GetVersion())
368
.arg(vboxGlobal().platformInfo()));
370
/* Show progress bar: */
373
/* Setup GET request: */
374
QNetworkRequest request;
376
request.setRawHeader("User-Agent", strUserAgent.toAscii());
377
QNetworkReply *pReply = m_pNetworkManager->get(request);
378
connect(pReply, SIGNAL(finished()), this, SLOT(sltHandleReply()));
379
connect(pReply, SIGNAL(sslErrors(QList<QSslError>)), pReply, SLOT(ignoreSslErrors()));
382
void VBoxUpdateDlg::sltHandleReply()
384
/* Get corresponding network reply object: */
385
QNetworkReply *pReply = qobject_cast<QNetworkReply*>(sender());
386
/* And ask it for suicide: */
387
pReply->deleteLater();
389
/* Hide progress bar: */
392
/* Handle normal result: */
393
if (pReply->error() == QNetworkReply::NoError)
395
/* Deserialize incoming data: */
396
QString strResponseData(pReply->readAll());
398
/* Newer version of necessary package found: */
399
if (strResponseData.indexOf(QRegExp("^\\d+\\.\\d+\\.\\d+ \\S+$")) == 0)
401
QStringList response = strResponseData.split(" ", QString::SkipEmptyParts);
403
/* For background update: */
406
msgCenter().showUpdateSuccess(vboxGlobal().mainWindow(), response[0], response[1]);
409
/* For wizard update: */
412
mTextSuccessInfo->setText(mTextSuccessInfo->text().arg(response[0], response[1], response[1]));
413
mTextSuccessInfo->show();
414
mPageStack->setCurrentIndex(1);
417
/* No newer version of necessary package found: */
420
/* For background update: */
424
msgCenter().showUpdateNotFound(vboxGlobal().mainWindow());
427
/* For wizard update: */
430
mTextNotFoundInfo->show();
431
mPageStack->setCurrentIndex(1);
435
/* Save left count of checks: */
437
QString strCount = vboxGlobal().virtualBox().GetExtraData(VBoxDefs::GUI_UpdateCheckCount);
438
if (!strCount.isEmpty())
441
int c = strCount.toLongLong(&ok);
444
vboxGlobal().virtualBox().SetExtraData(VBoxDefs::GUI_UpdateCheckCount, QString("%1").arg((qulonglong)cCount + 1));
449
/* For background update: */
453
msgCenter().showUpdateFailure(vboxGlobal().mainWindow(), pReply->errorString());
456
/* For wizard update: */
459
mTextFailureInfo->setText(mTextFailureInfo->text().arg(pReply->errorString()));
460
mTextFailureInfo->show();
461
mPageStack->setCurrentIndex(1);