[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[vidalia-svn] r3413: Merge the auto-updates branch into trunk. It's still a compi (in vidalia/trunk: . src/vidalia src/vidalia/config src/vidalia/res src/vidalia/res/32x32 src/vidalia/res/48x48)
Author: edmanm
Date: 2009-01-03 15:10:16 -0500 (Sat, 03 Jan 2009)
New Revision: 3413
Added:
vidalia/trunk/src/vidalia/packageinfo.cpp
vidalia/trunk/src/vidalia/packageinfo.h
vidalia/trunk/src/vidalia/res/32x32/system-software-update.png
vidalia/trunk/src/vidalia/res/48x48/system-software-update.png
vidalia/trunk/src/vidalia/updateprocess.cpp
vidalia/trunk/src/vidalia/updateprocess.h
vidalia/trunk/src/vidalia/updateprogressdialog.cpp
vidalia/trunk/src/vidalia/updateprogressdialog.h
vidalia/trunk/src/vidalia/updateprogressdialog.ui
vidalia/trunk/src/vidalia/updatesavailabledialog.cpp
vidalia/trunk/src/vidalia/updatesavailabledialog.h
vidalia/trunk/src/vidalia/updatesavailabledialog.ui
Modified:
vidalia/trunk/CMakeLists.txt
vidalia/trunk/config.h.in
vidalia/trunk/src/vidalia/CMakeLists.txt
vidalia/trunk/src/vidalia/config/configdialog.cpp
vidalia/trunk/src/vidalia/config/configdialog.h
vidalia/trunk/src/vidalia/config/generalpage.cpp
vidalia/trunk/src/vidalia/config/generalpage.h
vidalia/trunk/src/vidalia/config/generalpage.ui
vidalia/trunk/src/vidalia/config/vidaliasettings.cpp
vidalia/trunk/src/vidalia/config/vidaliasettings.h
vidalia/trunk/src/vidalia/mainwindow.cpp
vidalia/trunk/src/vidalia/mainwindow.h
vidalia/trunk/src/vidalia/res/vidalia.qrc
Log:
Merge the auto-updates branch into trunk. It's still a compile-time option
and is disabled by default.
Modified: vidalia/trunk/CMakeLists.txt
===================================================================
--- vidalia/trunk/CMakeLists.txt 2009-01-03 14:05:46 UTC (rev 3412)
+++ vidalia/trunk/CMakeLists.txt 2009-01-03 20:10:16 UTC (rev 3413)
@@ -78,6 +78,11 @@
## UPnP support is currently optional (enabled by default)
option(USE_MINIUPNPC "Enable UPnP support using the MiniUPnPc library." ON)
+## Automatic osftware update is optional (disabled by default)
+if (WIN32)
+ option(USE_AUTOUPDATE "Enable automatic software update support." OFF)
+endif(WIN32)
+
## Check for system header files
check_include_file("limits.h" HAVE_LIMITS_H)
check_include_file("sys/limits.h" HAVE_SYS_LIMITS_H)
Modified: vidalia/trunk/config.h.in
===================================================================
--- vidalia/trunk/config.h.in 2009-01-03 14:05:46 UTC (rev 3412)
+++ vidalia/trunk/config.h.in 2009-01-03 20:10:16 UTC (rev 3413)
@@ -1,5 +1,5 @@
/*
-** $Id: $
+** $Id$
**
** This file is part of Vidalia, and is subject to the license terms in the
** LICENSE file, found in the top level directory of this distribution. If
@@ -28,5 +28,7 @@
#cmakedefine USE_MINIUPNPC
+#cmakedefine USE_AUTOUPDATE
+
#endif
Modified: vidalia/trunk/src/vidalia/CMakeLists.txt
===================================================================
--- vidalia/trunk/src/vidalia/CMakeLists.txt 2009-01-03 14:05:46 UTC (rev 3412)
+++ vidalia/trunk/src/vidalia/CMakeLists.txt 2009-01-03 20:10:16 UTC (rev 3413)
@@ -215,10 +215,29 @@
log/messagelog.ui
network/netviewer.ui
)
+
if (USE_MINIUPNPC)
qt4_wrap_ui(vidalia_SRCS config/upnptestdialog.ui)
endif(USE_MINIUPNPC)
+if (USE_AUTOUPDATE)
+ set(vidalia_SRCS ${vidalia_SRCS}
+ packageinfo.cpp
+ updateprocess.cpp
+ updateprogressdialog.cpp
+ updatesavailabledialog.cpp
+ )
+ qt4_wrap_cpp(vidalia_SRCS
+ updateprocess.h
+ updateprogressdialog.h
+ updatesavailabledialog.h
+ )
+ qt4_wrap_ui(vidalia_SRCS
+ updateprogressdialog.ui
+ updatesavailabledialog.ui
+ )
+endif(USE_AUTOUPDATE)
+
## Add the resource files (icons, etc.)
qt4_add_resources(vidalia_SRCS
res/vidalia.qrc
Modified: vidalia/trunk/src/vidalia/config/configdialog.cpp
===================================================================
--- vidalia/trunk/src/vidalia/config/configdialog.cpp 2009-01-03 14:05:46 UTC (rev 3412)
+++ vidalia/trunk/src/vidalia/config/configdialog.cpp 2009-01-03 20:10:16 UTC (rev 3413)
@@ -72,9 +72,12 @@
/* Create the config pages and actions */
QActionGroup *grp = new QActionGroup(this);
- ui.stackPages->add(new GeneralPage(ui.stackPages),
+ GeneralPage *generalPage = new GeneralPage(ui.stackPages);
+ ui.stackPages->add(generalPage,
createPageAction(QIcon(IMAGE_GENERAL),
tr("General"), "General", grp));
+ connect(generalPage, SIGNAL(checkForUpdates()),
+ this, SLOT(onCheckForUpdates()));
ui.stackPages->add(new NetworkPage(ui.stackPages),
createPageAction(QIcon(IMAGE_NETWORK),
@@ -282,6 +285,15 @@
}
}
+/** Stub method that relays the checkForUpdates() signal from the General
+ * settings page to the owner of the config dialog (MainWindow). */
+void
+ConfigDialog::onCheckForUpdates()
+{
+ emit checkForUpdates();
+}
+
+
/** Called when a ConfigPage in the dialog requests help on a specific
* <b>topic</b>. */
void
Modified: vidalia/trunk/src/vidalia/config/configdialog.h
===================================================================
--- vidalia/trunk/src/vidalia/config/configdialog.h 2009-01-03 14:05:46 UTC (rev 3412)
+++ vidalia/trunk/src/vidalia/config/configdialog.h 2009-01-03 20:10:16 UTC (rev 3413)
@@ -53,6 +53,11 @@
/** Shows the config dialog with focus set to the given page. */
void showWindow(Page page = General);
+signals:
+ /** Emitted when the user clicks "Check Now" to initiate a check
+ * for software updates. */
+ void checkForUpdates();
+
protected:
/** Called when the user changes the UI translation. */
virtual void retranslateUi();
@@ -74,6 +79,9 @@
/** Shows general help information for whichever settings page the user is
* currently viewing. */
void help();
+ /** Stub method that relays the checkForUpdates() signal from the General
+ * settings page to the owner of the config dialog (MainWindow). */
+ void onCheckForUpdates();
private:
/** Loads the current configuration settings */
Modified: vidalia/trunk/src/vidalia/config/generalpage.cpp
===================================================================
--- vidalia/trunk/src/vidalia/config/generalpage.cpp 2009-01-03 14:05:46 UTC (rev 3412)
+++ vidalia/trunk/src/vidalia/config/generalpage.cpp 2009-01-03 20:10:16 UTC (rev 3413)
@@ -16,6 +16,7 @@
#include <QDateTime>
#include <stringutil.h>
+#include <config.h>
#include "generalpage.h"
@@ -35,12 +36,16 @@
this, SLOT(browseTorExecutable()));
connect(ui.btnBrowseProxyExecutable, SIGNAL(clicked()),
this, SLOT(browseProxyExecutable()));
+ connect(ui.btnUpdateNow, SIGNAL(clicked()), this, SLOT(updateNow()));
#if !defined(Q_OS_WIN32)
/* Hide platform specific features */
ui.chkRunVidaliaAtSystemStartup->setVisible(false);
ui.lineHorizontalSeparator->setVisible(false);
#endif
+#if !defined(USE_AUTOUPDATE)
+ ui.grpSoftwareUpdates->setVisible(false);
+#endif
}
/** Destructor */
@@ -141,3 +146,9 @@
ui.chkRunProxyAtTorStartup->setChecked(_vidaliaSettings->runProxyAtStart());
}
+void
+GeneralPage::updateNow()
+{
+ emit checkForUpdates();
+}
+
Modified: vidalia/trunk/src/vidalia/config/generalpage.h
===================================================================
--- vidalia/trunk/src/vidalia/config/generalpage.h 2009-01-03 14:05:46 UTC (rev 3412)
+++ vidalia/trunk/src/vidalia/config/generalpage.h 2009-01-03 20:10:16 UTC (rev 3413)
@@ -40,11 +40,17 @@
/** Called when the user changes the UI translation. */
virtual void retranslateUi();
+signals:
+ /** Emitted when the user clicks the "Check Now" button. */
+ void checkForUpdates();
+
private slots:
/** Open a QFileDialog to browse for a Tor executable file. */
void browseTorExecutable();
/** Open a QFileDialog to browse for a proxy executable file. */
void browseProxyExecutable();
+ /** Initiate an immediate check for software updates. */
+ void updateNow();
private:
/** Displays a file dialog allowing the user to browse for an executable
Modified: vidalia/trunk/src/vidalia/config/generalpage.ui
===================================================================
--- vidalia/trunk/src/vidalia/config/generalpage.ui 2009-01-03 14:05:46 UTC (rev 3412)
+++ vidalia/trunk/src/vidalia/config/generalpage.ui 2009-01-03 20:10:16 UTC (rev 3413)
@@ -149,6 +149,55 @@
</widget>
</item>
<item>
+ <widget class="QGroupBox" name="grpSoftwareUpdates" >
+ <property name="title" >
+ <string>Software Updates</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout" >
+ <item>
+ <widget class="QCheckBox" name="chkAutoUpdates" >
+ <property name="text" >
+ <string>Check for new software updates automatically</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnUpdateNow" >
+ <property name="text" >
+ <string>Check Now</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<spacer name="verticalSpacer" >
<property name="orientation" >
<enum>Qt::Vertical</enum>
Modified: vidalia/trunk/src/vidalia/config/vidaliasettings.cpp
===================================================================
--- vidalia/trunk/src/vidalia/config/vidaliasettings.cpp 2009-01-03 14:05:46 UTC (rev 3412)
+++ vidalia/trunk/src/vidalia/config/vidaliasettings.cpp 2009-01-03 20:10:16 UTC (rev 3413)
@@ -254,3 +254,27 @@
setValue(SETTING_PROXY_EXECUTABLE_ARGUMENTS, proxyExecutableArguments);
}
+bool
+VidaliaSettings::isAutoUpdateEnabled() const
+{
+ return value(SETTING_CHECK_FOR_UPDATES).toBool();
+}
+
+void
+VidaliaSettings::setAutoUpdateEnabled(bool enabled)
+{
+ setValue(SETTING_CHECK_FOR_UPDATES, enabled);
+}
+
+QDateTime
+VidaliaSettings::lastCheckedForUpdates() const
+{
+ return value(SETTING_LAST_UPDATE_CHECK).toDateTime();
+}
+
+void
+VidaliaSettings::setLastCheckedForUpdates(const QDateTime &checkedAt)
+{
+ setValue(SETTING_LAST_UPDATE_CHECK, checkedAt);
+}
+
Modified: vidalia/trunk/src/vidalia/config/vidaliasettings.h
===================================================================
--- vidalia/trunk/src/vidalia/config/vidaliasettings.h 2009-01-03 14:05:46 UTC (rev 3412)
+++ vidalia/trunk/src/vidalia/config/vidaliasettings.h 2009-01-03 20:10:16 UTC (rev 3413)
@@ -17,6 +17,7 @@
#ifndef _VIDALIASETTINGS_H
#define _VIDALIASETTINGS_H
+#include <QDateTime>
#include "vsettings.h"
@@ -93,6 +94,19 @@
QStringList getProxyExecutableArguments() const;
/** Sets the additional arguments to be passed to Proxy Executable */
void setProxyExecutableArguments(const QStringList &proxyExecutableArguments);
+
+ /** Returns true if Vidalia should automatically check for software updates.
+ */
+ bool isAutoUpdateEnabled() const;
+ /** Sets to <b>enabled</b> whether Vidalia should automatically check for
+ * software updates or not. */
+ void setAutoUpdateEnabled(bool enabled);
+
+ /** Returns the time at which Vidalia last checked for software updates. */
+ QDateTime lastCheckedForUpdates() const;
+ /** Sets to <b>checkedAt</b> the time at which Vidalia last checked for
+ * available software updates. */
+ void setLastCheckedForUpdates(const QDateTime &checkedAt);
};
#endif
Modified: vidalia/trunk/src/vidalia/mainwindow.cpp
===================================================================
--- vidalia/trunk/src/vidalia/mainwindow.cpp 2009-01-03 14:05:46 UTC (rev 3412)
+++ vidalia/trunk/src/vidalia/mainwindow.cpp 2009-01-03 20:10:16 UTC (rev 3413)
@@ -34,6 +34,10 @@
#include "mainwindow.h"
#include "controlpasswordinputdialog.h"
+#ifdef USE_AUTOUPDATE
+#include "updatesavailabledialog.h"
+#endif
+
#define IMG_BWGRAPH ":/images/16x16/utilities-system-monitor.png"
#define IMG_CONTROL_PANEL ":/images/16x16/system-run.png"
#define IMG_MESSAGELOG ":/images/16x16/format-justify-fill.png"
@@ -120,6 +124,7 @@
createTrayIcon();
/* Start with Tor initially stopped */
_status = Unset;
+ _isVidaliaRunningTor = false;
updateTorStatus(Stopped);
/* Create a new TorControl object, used to communicate with Tor */
@@ -163,6 +168,28 @@
connect(vApp, SIGNAL(running()), this, SLOT(running()));
connect(vApp, SIGNAL(shutdown()), this, SLOT(shutdown()));
+#if defined(USE_AUTOUPDATE)
+ /* Create a timer used to remind us to check for software updates */
+ connect(&_updateTimer, SIGNAL(timeout()), this, SLOT(checkForUpdates()));
+
+ /* Also check for updates in the foreground when the user clicks the
+ * "Check Now" button in the config dialog. */
+ connect(_configDialog, SIGNAL(checkForUpdates()),
+ this, SLOT(checkForUpdatesWithUI()));
+
+ /* The rest of these slots are called as the update process executes. */
+ connect(&_updateProcess, SIGNAL(downloadProgress(QString,int,int)),
+ &_updateProgressDialog, SLOT(setDownloadProgress(QString,int,int)));
+ connect(&_updateProcess, SIGNAL(updatesAvailable(UpdateProcess::BundleInfo,PackageList)),
+ this, SLOT(updatesAvailable(UpdateProcess::BundleInfo,PackageList)));
+ connect(&_updateProcess, SIGNAL(updatesInstalled(int)),
+ this, SLOT(updatesInstalled(int)));
+ connect(&_updateProcess, SIGNAL(installUpdatesFailed(QString)),
+ this, SLOT(installUpdatesFailed(QString)));
+ connect(&_updateProgressDialog, SIGNAL(cancelUpdate()),
+ &_updateProcess, SLOT(cancel()));
+#endif
+
#if defined(USE_MINIUPNPC)
/* Catch UPnP-related signals */
connect(UPNPControl::instance(), SIGNAL(error(UPNPControl::UPNPError)),
@@ -280,6 +307,34 @@
/* Start the proxy server, if configured */
if (settings.runProxyAtStart())
startProxy();
+
+#if defined(USE_AUTOUPDATE)
+ if (settings.isAutoUpdateEnabled()) {
+ QDateTime lastCheckedAt = settings.lastCheckedForUpdates();
+ if (UpdateProcess::shouldCheckForUpdates(lastCheckedAt)) {
+ if (settings.runTorAtStart() && ! _torControl->circuitEstablished()) {
+ /* We started Tor but it hasn't bootstrapped yet, so give it a bit
+ * before we decide to check for updates. If Tor manages to build a
+ * circuit before this timer times out, we will stop the timer and
+ * launch a check for updates immediately. (see circuitEstablished()).
+ */
+ _updateTimer.start(5*60*1000);
+ } else {
+ /* Initiate a background check for updates now */
+ checkForUpdates();
+ }
+ } else {
+ /* Schedule the next time to check for updates */
+ QDateTime nextCheckAt = UpdateProcess::nextCheckForUpdates(lastCheckedAt);
+ QDateTime now = QDateTime::currentDateTime().toUTC();
+
+ vInfo("Last checked for software updates at %1. Will check again at %2.")
+ .arg(lastCheckedAt.toLocalTime().toString("dd-MM-yyyy hh:mm:ss"))
+ .arg(nextCheckAt.toLocalTime().toString("dd-MM-yyyy hh:mm:ss"));
+ _updateTimer.start((nextCheckAt.toTime_t() - now.toTime_t()) * 1000);
+ }
+ }
+#endif
}
/** Terminate the Tor process if it is being run under Vidalia, disconnect all
@@ -1307,6 +1362,18 @@
setStartupProgress(ui.progressBar->maximum(),
tr("Connected to the Tor network!"));
startSubprocesses();
+
+#if defined(USE_AUTOUPDATE)
+ VidaliaSettings settings;
+ if (settings.isAutoUpdateEnabled()) {
+ QDateTime lastCheckedAt = settings.lastCheckedForUpdates();
+ if (UpdateProcess::shouldCheckForUpdates(lastCheckedAt)) {
+ /* Initiate a background check for updates now */
+ _updateTimer.stop();
+ checkForUpdates();
+ }
+ }
+#endif
}
/** Checks the status of the current version of Tor to see if it's old,
@@ -1332,17 +1399,30 @@
static bool alreadyWarned = false;
if (!alreadyWarned) {
+#if !defined(USE_AUTOUPDATE)
QString website = "https://www.torproject.org/";
-#if QT_VERSION >= 0x040200
+# if QT_VERSION >= 0x040200
website = QString("<a href=\"%1\">%1</a>").arg(website);
-#endif
+# endif
- VMessageBox::information(this,
- tr("Tor Update Available"),
+ VMessageBox::information(this, tr("Tor Update Available"),
p(tr("The currently installed version of Tor is out of date or no longer "
"recommended. Please visit the Tor website to download the latest "
"version.")) + p(tr("Tor website: %1").arg(website)),
VMessageBox::Ok);
+#else
+ int ret = VMessageBox::information(this,
+ tr("Tor Update Available"),
+ p(tr("The currently installed version of Tor is out of date "
+ "or no longer recommended."))
+ + p(tr("Would you like to check if a newer package is "
+ "available for installation?")),
+ VMessageBox::Yes|VMessageBox::Default,
+ VMessageBox::No|VMessageBox::Escape);
+
+ if (ret == VMessageBox::Yes)
+ checkForUpdatesWithUI();
+#endif
alreadyWarned = true;
}
}
@@ -1474,3 +1554,141 @@
}
#endif
+#if defined(USE_AUTOUPDATE)
+/** Called when the user clicks the 'Check Now' button in the General
+ * settings page. */
+void
+MainWindow::checkForUpdatesWithUI()
+{
+ checkForUpdates(true);
+}
+
+/** Called when the update interval timer expires, notifying Vidalia that
+ * we should check for updates again. */
+void
+MainWindow::checkForUpdates(bool showProgress)
+{
+ VidaliaSettings settings;
+
+ if (_updateProcess.isRunning()) {
+ if (showProgress) {
+ /* A check for updates is already in progress, so just bring the update
+ * progress dialog into focus.
+ */
+ _updateProgressDialog.show();
+ }
+ } else {
+ /* If Tor is running and bootstrapped, then use Tor to check for updates */
+ if (_torControl->isRunning() && _torControl->circuitEstablished())
+ _updateProcess.setSocksPort(_torControl->getSocksPort());
+ else
+ _updateProcess.setSocksPort(0);
+
+ /* Initialize the UpdateProgressDialog and display it, if necessary. */
+ _updateProgressDialog.setStatus(UpdateProgressDialog::CheckingForUpdates);
+ if (showProgress)
+ _updateProgressDialog.show();
+
+ /* Initiate a check for available software updates. This check will
+ * be done in the background, notifying the user only if there are
+ * updates to be installed.
+ */
+ _updateProcess.checkForUpdates(UpdateProcess::TorBundleInfo);
+
+ /* Remember when we last checked for software updates */
+ settings.setLastCheckedForUpdates(QDateTime::currentDateTime().toUTC());
+
+ /* Restart the "Check for Updates" timer */
+ _updateTimer.start(UpdateProcess::checkForUpdatesInterval() * 1000);
+ }
+}
+
+/** Called when the check for software updates fails. */
+void
+MainWindow::checkForUpdatesFailed(const QString &errmsg)
+{
+ if (_updateProgressDialog.isVisible()) {
+ _updateProgressDialog.hide();
+ VMessageBox::warning(this, tr("Update Failed"), errmsg,
+ VMessageBox::Ok);
+ }
+}
+
+/** Called when there is an update available for installation. */
+void
+MainWindow::updatesAvailable(UpdateProcess::BundleInfo bi,
+ const PackageList &packageList)
+{
+ vInfo("%1 software update(s) available").arg(packageList.size());
+ if (packageList.size() > 0) {
+ UpdatesAvailableDialog dlg(packageList, &_updateProgressDialog);
+
+ switch (dlg.exec()) {
+ case UpdatesAvailableDialog::InstallUpdatesNow:
+ installUpdates(bi);
+ break;
+
+ default:
+ _updateProgressDialog.hide();
+ break;
+ }
+ } else {
+ if (_updateProgressDialog.isVisible()) {
+ _updateProgressDialog.hide();
+ VMessageBox::information(this, tr("No Updates Available"),
+ tr("You are currently running the most recent "
+ "Tor software available."),
+ VMessageBox::Ok);
+ }
+ }
+}
+
+/** Stops Tor (if necessary), installs any available for <b>bi</b>, and
+ * restarts Tor (if necessary). */
+void
+MainWindow::installUpdates(UpdateProcess::BundleInfo bi)
+{
+ _updateProgressDialog.setStatus(UpdateProgressDialog::InstallingUpdates);
+ _updateProgressDialog.show();
+
+ if (_isVidaliaRunningTor) {
+ _restartTorAfterUpgrade = true;
+ _isIntentionalExit = true;
+ _torControl->stop();
+ } else {
+ _restartTorAfterUpgrade = false;
+ }
+ _updateProcess.installUpdates(bi);
+}
+
+/** Called when all <b>numUpdates</b> software updates have been installed
+ * successfully. */
+void
+MainWindow::updatesInstalled(int numUpdates)
+{
+ _updateProgressDialog.setStatus(UpdateProgressDialog::UpdatesInstalled);
+ _updateProgressDialog.show();
+
+ if (_restartTorAfterUpgrade)
+ start();
+}
+
+/** Called when an update fails to install. <b>errmsg</b> contains details
+ * about the failure. */
+void
+MainWindow::installUpdatesFailed(const QString &errmsg)
+{
+ _updateProgressDialog.hide();
+
+ VMessageBox::warning(this, tr("Installation Failed"),
+ p(tr("Vidalia was unable to install your software updates."))
+ + p(tr("The following error occurred:"))
+ + p(errmsg),
+ VMessageBox::Ok);
+
+ if (_restartTorAfterUpgrade)
+ start();
+}
+
+#endif
+
Modified: vidalia/trunk/src/vidalia/mainwindow.h
===================================================================
--- vidalia/trunk/src/vidalia/mainwindow.h 2009-01-03 14:05:46 UTC (rev 3412)
+++ vidalia/trunk/src/vidalia/mainwindow.h 2009-01-03 20:10:16 UTC (rev 3413)
@@ -34,6 +34,10 @@
#include "helperprocess.h"
#include "config.h"
+#if defined(USE_AUTOUPDATE)
+#include "updateprocess.h"
+#include "updateprogressdialog.h"
+#endif
#if defined(USE_MINIUPNPC)
#include "config/upnpcontrol.h"
#endif
@@ -114,6 +118,28 @@
/** Called when the proxy server fails to start */
void onProxyFailed(QString errmsg);
+#if defined(USE_AUTOUPDATE)
+ /** Called when the user clicks the 'Check Now' button in the General
+ * settings page. */
+ void checkForUpdatesWithUI();
+ /** Called when the update interval timer expires, notifying Vidalia that
+ * we should check for updates again. */
+ void checkForUpdates(bool showProgress = false);
+ /** Called when the check for software updates fails. */
+ void checkForUpdatesFailed(const QString &errmsg);
+ /** Called when there is an update available for installation. */
+ void updatesAvailable(UpdateProcess::BundleInfo bi, const PackageList &packageList);
+ /** Stops Tor (if necessary), installs any available for <b>bi</b>, and
+ * restarts Tor (if necessary). */
+ void installUpdates(UpdateProcess::BundleInfo bi);
+ /** Called when all <b>numUpdates</b> software updates have been installed
+ * successfully. */
+ void updatesInstalled(int numUpdates);
+ /** Called when an update fails to install. <b>errmsg</b> contains details
+ * about the failure. */
+ void installUpdatesFailed(const QString &errmsg);
+#endif
+
#if defined(USE_MINIUPNPC)
/** Called when a UPnP error occurs. */
void upnpError(UPNPControl::UPNPError error);
@@ -206,6 +232,18 @@
bool _useSavedPassword;
/** The Vidalia icon that sits in the tray. */
TrayIcon _trayIcon;
+
+#if defined(USE_AUTOUPDATE)
+ /** Timer used to remind us to check for software updates. */
+ QTimer _updateTimer;
+ /** The auto-update process used to check for and download updates. */
+ UpdateProcess _updateProcess;
+ /** Dialog instance that is be used to show the progress of the auto-update
+ * executable. */
+ UpdateProgressDialog _updateProgressDialog;
+ /** Set to true if Vidalia should restart Tor after a software upgrade. */
+ bool _restartTorAfterUpgrade;
+#endif
/** The menubar (Mac OS X only). */
QMenuBar *_menuBar;
Copied: vidalia/trunk/src/vidalia/packageinfo.cpp (from rev 3409, vidalia/branches/auto-updates/src/vidalia/packageinfo.cpp)
===================================================================
--- vidalia/trunk/src/vidalia/packageinfo.cpp (rev 0)
+++ vidalia/trunk/src/vidalia/packageinfo.cpp 2009-01-03 20:10:16 UTC (rev 3413)
@@ -0,0 +1,92 @@
+/*
+** This file is part of Vidalia, and is subject to the license terms in the
+** LICENSE file, found in the top level directory of this distribution. If you
+** did not receive the LICENSE file with this file, you may obtain it from the
+** Vidalia source package distributed by the Vidalia Project at
+** http://www.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+/*
+** \file packageinfo.cpp
+** \version $Id$
+** \brief Contains information about a single available updated software
+** package.
+*/
+
+#include "packageinfo.h"
+
+
+PackageInfo::PackageInfo()
+{
+}
+
+bool
+PackageInfo::isValid() const
+{
+ return (! _name.isEmpty() && ! _version.isEmpty());
+}
+
+void
+PackageInfo::setName(const QString &name)
+{
+ _name = name;
+}
+
+QString
+PackageInfo::name() const
+{
+ return _name;
+}
+
+void
+PackageInfo::setVersion(const QString &version)
+{
+ _version = version;
+}
+
+QString
+PackageInfo::version() const
+{
+ return _version;
+}
+
+void
+PackageInfo::setLongDescription(const QString &lang, const QString &desc)
+{
+ _longDescription.insert(lang, desc);
+}
+
+QString
+PackageInfo::longDescription(const QString &lang) const
+{
+ return _longDescription.value(lang);
+}
+
+bool
+PackageInfo::hasLongDescription(const QString &lang) const
+{
+ return _longDescription.contains(lang);
+}
+
+void
+PackageInfo::setShortDescription(const QString &lang, const QString &desc)
+{
+ _shortDescription.insert(lang, desc);
+}
+
+
+QString
+PackageInfo::shortDescription(const QString &lang) const
+{
+ return _shortDescription.value(lang);
+}
+
+
+bool
+PackageInfo::hasShortDescription(const QString &lang) const
+{
+ return _shortDescription.contains(lang);
+}
+
Copied: vidalia/trunk/src/vidalia/packageinfo.h (from rev 3409, vidalia/branches/auto-updates/src/vidalia/packageinfo.h)
===================================================================
--- vidalia/trunk/src/vidalia/packageinfo.h (rev 0)
+++ vidalia/trunk/src/vidalia/packageinfo.h 2009-01-03 20:10:16 UTC (rev 3413)
@@ -0,0 +1,97 @@
+/*
+** This file is part of Vidalia, and is subject to the license terms in the
+** LICENSE file, found in the top level directory of this distribution. If you
+** did not receive the LICENSE file with this file, you may obtain it from the
+** Vidalia source package distributed by the Vidalia Project at
+** http://www.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+/*
+** \file packageinfo.h
+** \version $Id$
+** \brief Contains information about a single available updated software
+** package.
+*/
+
+#ifndef _PACKAGEINFO_H
+#define _PACKAGEINFO_H
+
+#include <QHash>
+#include <QList>
+#include <QString>
+
+
+class PackageInfo
+{
+public:
+ /** Default constructor. */
+ PackageInfo();
+
+ /** Returns true if this PackageInfo object is valid. A valid PackageInfo
+ * object must have a name and a version number set. All other fields are
+ * optional.
+ */
+ bool isValid() const;
+
+ /** Sets the name of this software package to <b>name</b>.
+ */
+ void setName(const QString &name);
+
+ /** Returns the name of this software package.
+ */
+ QString name() const;
+
+ /** Sets the version of this software package to <b>version</b>.
+ */
+ void setVersion(const QString &version);
+
+ /** Returns the version of this software package.
+ */
+ QString version() const;
+
+ /** Sets the long description of this software package to <b>desc</b> for
+ * the language <b>lang</b>.
+ */
+ void setLongDescription(const QString &lang, const QString &desc);
+
+ /** Returns true if there is a long description for this software package
+ * currently set for language <b>lang</b>.
+ */
+ bool hasLongDescription(const QString &lang) const;
+
+ /** Returns long description of this software package for language
+ * <b>lang</b>. If a description is not currently set for the specified
+ * language, a null QString object is returned.
+ */
+ QString longDescription(const QString &lang) const;
+
+ /** Sets the short description of this software package to <b>desc</b> for
+ * the language <b>lang</b>.
+ */
+ void setShortDescription(const QString &lang, const QString &desc);
+
+ /** Returns true if there is a short description of this software package
+ * currently set for language <b>lang</b>.
+ */
+ bool hasShortDescription(const QString &lang) const;
+
+ /** Returns the short description of this software package for language
+ * <b>lang</b>. If a description is not currently set for the specified
+ * language, a null QString object is returned.
+ */
+ QString shortDescription(const QString &lang) const;
+
+private:
+ QString _name;
+ QString _version;
+ QHash<QString,QString> _longDescription;
+ QHash<QString,QString> _shortDescription;
+};
+
+/** An unordered collection of PackageInfo objects. */
+typedef QList<PackageInfo> PackageList;
+
+#endif
+
Copied: vidalia/trunk/src/vidalia/res/32x32/system-software-update.png (from rev 3409, vidalia/branches/auto-updates/src/vidalia/res/32x32/system-software-update.png)
===================================================================
(Binary files differ)
Copied: vidalia/trunk/src/vidalia/res/48x48/system-software-update.png (from rev 3409, vidalia/branches/auto-updates/src/vidalia/res/48x48/system-software-update.png)
===================================================================
(Binary files differ)
Modified: vidalia/trunk/src/vidalia/res/vidalia.qrc
===================================================================
--- vidalia/trunk/src/vidalia/res/vidalia.qrc 2009-01-03 14:05:46 UTC (rev 3412)
+++ vidalia/trunk/src/vidalia/res/vidalia.qrc 2009-01-03 20:10:16 UTC (rev 3413)
@@ -72,6 +72,7 @@
<file>32x32/status-orange.png</file>
<file>32x32/status-red.png</file>
<file>32x32/system-help.png</file>
+ <file>32x32/system-software-update.png</file>
<file>32x32/utilities-log-viewer.png</file>
<file>32x32/utilities-system-monitor.png</file>
<file>32x32/view-refresh.png</file>
@@ -91,6 +92,7 @@
<file>48x48/status-green.png</file>
<file>48x48/status-orange.png</file>
<file>48x48/status-red.png</file>
+ <file>48x48/system-software-update.png</file>
<file>48x48/vidalia.png</file>
<file>48x48/view-media-artist.png</file>
</qresource>
Added: vidalia/trunk/src/vidalia/updateprocess.cpp
===================================================================
--- vidalia/trunk/src/vidalia/updateprocess.cpp (rev 0)
+++ vidalia/trunk/src/vidalia/updateprocess.cpp 2009-01-03 20:10:16 UTC (rev 3413)
@@ -0,0 +1,352 @@
+/*
+** This file is part of Vidalia, and is subject to the license terms in the
+** LICENSE file, found in the top level directory of this distribution. If you
+** did not receive the LICENSE file with this file, you may obtain it from the
+** Vidalia source package distributed by the Vidalia Project at
+** http://www.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+#include <QDir>
+#include <QDomDocument>
+#include <QDomElement>
+#include <QDomNodeList>
+#include <vidalia.h>
+#include <stringutil.h>
+
+#include "updateprocess.h"
+
+
+UpdateProcess::UpdateProcess(QObject *parent)
+ : QProcess(parent)
+{
+ _currentCommand = NoCommand;
+ _socksPort = 0;
+
+ connect(this, SIGNAL(readyReadStandardError()),
+ this, SLOT(readStandardError()));
+ connect(this, SIGNAL(readyReadStandardOutput()),
+ this, SLOT(readStandardOutput()));
+ connect(this, SIGNAL(finished(int, QProcess::ExitStatus)),
+ this, SLOT(onFinished(int, QProcess::ExitStatus)));
+
+ setEnvironment(systemEnvironment());
+}
+
+void
+UpdateProcess::checkForUpdates(BundleInfo bi)
+{
+ QStringList args;
+
+ args << "update" << "--controller-log-format"
+ << "--repo=" + updateRepositoryDir()
+ << "--debug";
+ if (_socksPort)
+ args << "--socks-port=" + QString::number(_socksPort);
+
+ args << bundleInfoToString(bi);
+
+ vNotice("updater: launching auto-update executable: %1 %2")
+ .arg(updateExecutable())
+ .arg(args.join(" "));
+ _currentBundle = bi;
+ _currentCommand = CheckForUpdates;
+ start(updateExecutable(), args);
+}
+
+void
+UpdateProcess::installUpdates(BundleInfo bi)
+{
+ QStringList args;
+
+ args << "update" << "--controller-log-format"
+ << "--repo=" + updateRepositoryDir()
+ << "--install";
+ if (_socksPort)
+ args << "--socks-port=" + QString::number(_socksPort);
+
+ args << bundleInfoToString(bi);
+
+ vNotice("updater: launching auto-update executable: %1 %2")
+ .arg(updateExecutable())
+ .arg(args.join(" "));
+ _currentBundle = bi;
+ _currentCommand = InstallUpdates;
+ start(updateExecutable(), args);
+}
+
+void
+UpdateProcess::setSocksPort(quint16 port)
+{
+ _socksPort = port;
+}
+
+bool
+UpdateProcess::isRunning() const
+{
+ return (state() != QProcess::NotRunning);
+}
+
+void
+UpdateProcess::cancel()
+{
+ if (_currentCommand == CheckForUpdates) {
+#if defined(Q_OS_WIN32)
+ kill();
+#else
+ terminate();
+#endif
+ }
+}
+
+void
+UpdateProcess::readStandardError()
+{
+ int idx;
+ bool ok;
+ QString line, type;
+ QHash<QString,QString> args;
+
+ setReadChannel(QProcess::StandardError);
+ while (canReadLine()) {
+ line = readLine().trimmed();
+ vInfo("updater (stderr): %1").arg(line);
+
+ idx = line.indexOf(" ");
+ if (idx < 0 || idx == line.length()-1)
+ continue;
+ type = line.mid(0, idx);
+ line = line.mid(idx + 1);
+
+ args = string_parse_keyvals(line, &ok);
+ if (! ok)
+ continue;
+ else if (line.startsWith("thandy.InstallFailed: ", Qt::CaseInsensitive)) {
+ /** XXX: This is a fucking kludge. If installation fails, Thandy just
+ * dumps a Python traceback that (for obvious reasons) doesn't
+ * follow the expected format. There isn't a defined control
+ * message type for this yet we'd really like the error, so treat
+ * this one specially.
+ */
+ emit installUpdatesFailed(line);
+ continue;
+ }
+
+ if (! type.compare("CAN_INSTALL", Qt::CaseInsensitive)) {
+ QString package = args.value("PKG");
+ if (! package.isEmpty()) {
+ PackageInfo pkgInfo = packageInfo(package);
+ if (pkgInfo.isValid())
+ _packageList << pkgInfo;
+ }
+ } else if (_currentCommand == CheckForUpdates
+ && ! type.compare("DEBUG")
+ && args.value("msg").startsWith("Got ")) {
+ /* XXX: This is an even worse fucking kludge. Thandy only reports
+ * download progress in a not-so-parser-friendly log message,
+ * though, so we must kludge again.
+ *
+ * Here's an example of what we're parsing:
+ * "Got 1666048/1666560 bytes from http://updates.torproject.org/thandy/data/win32/tor-0.2.1.9-alpha.msi"
+ *
+ * (Note that the kludge above would even match on "Got milk?".)
+ */
+ QStringList parts = args.value("msg").split(" ");
+ if (parts.size() == 5) {
+ QStringList progress = parts.at(1).split("/");
+ if (progress.size() == 2) {
+ int bytesReceived = progress.at(0).toUInt();
+ int bytesTotal = progress.at(1).toUInt();
+ vInfo("updater: Downloaded %1 of %2 bytes of file %3").arg(bytesReceived)
+ .arg(bytesTotal)
+ .arg(parts.at(4));
+ emit downloadProgress(parts.at(4), bytesReceived, bytesTotal);
+ }
+ }
+ }
+ }
+}
+
+void
+UpdateProcess::readStandardOutput()
+{
+ QString line;
+
+ setReadChannel(QProcess::StandardOutput);
+ while (canReadLine()) {
+ line = readLine().trimmed();
+ vInfo("updater (stdout): %1").arg(line);
+ }
+}
+
+void
+UpdateProcess::onFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ vInfo("updater: update process finished with exit code %1").arg(exitCode);
+
+ if (_currentCommand == CheckForUpdates) {
+ if (exitStatus == QProcess::NormalExit) {
+ emit updatesAvailable(_currentBundle, _packageList);
+ } else {
+ emit checkForUpdatesFailed(tr("Vidalia was unable to check for available "
+ "software updates because Tor's handy pocket "
+ "creature died. Sorry."));
+ }
+ } else if (_currentCommand == InstallUpdates) {
+ if (exitStatus == QProcess::NormalExit && exitCode == 0)
+ emit updatesInstalled(_packageList.size());
+ }
+ _packageList.clear();
+}
+
+void
+UpdateProcess::onError(QProcess::ProcessError error)
+{
+ if (error == QProcess::FailedToStart) {
+ vWarn("updater: failed to start");
+ emit checkForUpdatesFailed(tr("Vidalia was unable to check for available "
+ "software updates because it could not find "
+ "'%1'.").arg(updateExecutable()));
+ }
+}
+
+int
+UpdateProcess::checkForUpdatesInterval()
+{
+ /* XXX: Check twice a day. Why? Because arma said so. */
+ return 12*60*60;
+}
+
+QDateTime
+UpdateProcess::nextCheckForUpdates(const QDateTime &lastCheckedAt)
+{
+ return lastCheckedAt.addSecs(checkForUpdatesInterval()).toUTC();
+}
+
+bool
+UpdateProcess::shouldCheckForUpdates(const QDateTime &lastCheckedAt)
+{
+ QDateTime nextCheckAt = nextCheckForUpdates(lastCheckedAt);
+ return (QDateTime::currentDateTime().toUTC() >= nextCheckAt);
+}
+
+QString
+UpdateProcess::updateExecutable()
+{
+ return "thandy.exe";
+}
+
+QString
+UpdateProcess::updateRepositoryDir()
+{
+ return QDir::convertSeparators(Vidalia::dataDirectory() + "/updates");
+}
+
+QString
+UpdateProcess::bundleInfoToString(BundleInfo bi)
+{
+ switch (bi) {
+ case TorBundleInfo:
+ return "/bundleinfo/tor/win32/";
+ default:
+ return QString();
+ };
+}
+
+PackageInfo
+UpdateProcess::packageInfo(const QString &package)
+{
+ QProcess proc;
+ QStringList args;
+
+ args << "json2xml"
+ << QDir::convertSeparators(updateRepositoryDir() + "/" + package);
+
+ vNotice("updater: launching auto-update executable: %1 %2")
+ .arg(updateExecutable())
+ .arg(args.join(" "));
+
+ proc.setEnvironment(proc.systemEnvironment());
+ proc.start(updateExecutable(), args);
+ if (! proc.waitForStarted())
+ return PackageInfo();
+ if (! proc.waitForFinished())
+ return PackageInfo();
+ return packageInfoFromXml(proc.readAll());
+}
+
+PackageInfo
+UpdateProcess::packageInfoFromXml(const QByteArray &xml)
+{
+ QDomDocument doc;
+ QDomElement dict, elem;
+ QDomNodeList nodeList;
+ QString errmsg;
+ QStringList versionParts;
+ PackageInfo pkgInfo;
+
+ if (! doc.setContent(xml, false, &errmsg, 0, 0))
+ goto err;
+
+ /* XXX: Qt 4.4 introduced XPath support, which would make the following
+ * parsing much easier. Whenever we drop support for Qt < 4.4, this should
+ * be updated.
+ */
+ elem = doc.documentElement().firstChildElement("signed");
+ if (elem.isNull()) {
+ errmsg = "Signed element not found";
+ goto err;
+ }
+
+ dict = elem.firstChildElement("dict");
+ if (dict.isNull()) {
+ errmsg = "no Dict element as a child of Signed";
+ goto err;
+ }
+
+ elem = dict.firstChildElement("name");
+ if (elem.isNull()) {
+ errmsg = "Name element not found";
+ goto err;
+ }
+ pkgInfo.setName(elem.text());
+
+ elem = dict.firstChildElement("version").firstChildElement("list");
+ if (elem.isNull()) {
+ errmsg = "no valid Version element found";
+ goto err;
+ }
+ elem = elem.firstChildElement("item");
+ for ( ; ! elem.isNull(); elem = elem.nextSiblingElement("item")) {
+ versionParts << elem.text();
+ }
+ pkgInfo.setVersion(versionParts.join("."));
+
+ elem = dict.firstChildElement("shortdesc").firstChildElement("dict");
+ if (elem.isNull()) {
+ errmsg = "no valid Shortdesc element found";
+ goto err;
+ }
+ elem = elem.firstChildElement();
+ for ( ; ! elem.isNull(); elem = elem.nextSiblingElement()) {
+ pkgInfo.setShortDescription(elem.tagName(), elem.text());
+ }
+
+ elem = dict.firstChildElement("longdesc").firstChildElement("dict");
+ if (elem.isNull()) {
+ errmsg = "no valid Longdesc element found";
+ goto err;
+ }
+ elem = elem.firstChildElement();
+ for ( ; ! elem.isNull(); elem = elem.nextSiblingElement()) {
+ pkgInfo.setLongDescription(elem.tagName(), elem.text());
+ }
+
+ return pkgInfo;
+
+err:
+ vWarn("updater: invalid package info XML document: %1").arg(errmsg);
+ return PackageInfo();
+}
+
Added: vidalia/trunk/src/vidalia/updateprocess.h
===================================================================
--- vidalia/trunk/src/vidalia/updateprocess.h (rev 0)
+++ vidalia/trunk/src/vidalia/updateprocess.h 2009-01-03 20:10:16 UTC (rev 3413)
@@ -0,0 +1,170 @@
+/*
+** This file is part of Vidalia, and is subject to the license terms in the
+** LICENSE file, found in the top level directory of this distribution. If you
+** did not receive the LICENSE file with this file, you may obtain it from the
+** Vidalia source package distributed by the Vidalia Project at
+** http://www.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+#ifndef _UPDATEPROCESS_H
+#define _UPDATEPROCESS_H
+
+#include <QProcess>
+#include <QDateTime>
+#include <QStringList>
+#include <QUrl>
+
+#include "packageinfo.h"
+
+
+class UpdateProcess : public QProcess
+{
+ Q_OBJECT
+
+public:
+ enum BundleInfo {
+ TorBundleInfo,
+ };
+
+ /** Default constructor.
+ */
+ UpdateProcess(QObject *parent = 0);
+
+ /** Begin a check for software updates that may be available for the
+ * software package specified by <b>bi</b>.
+ */
+ void checkForUpdates(BundleInfo bi);
+
+ /** Instructs the software update process to install previously downloaded
+ * files for <b>bi</b>.
+ */
+ void installUpdates(BundleInfo bi);
+
+ /** Returns true if the update process is currently in the middle of an
+ * operation, such as checking for or installing updates.
+ */
+ bool isRunning() const;
+
+ /** Sets the port to use as a SOCKS proxy to <b>port</b>. If <b>port</b> is
+ * set to 0, then no SOCKS proxy will be used when checking for updates.
+ */
+ void setSocksPort(quint16 port);
+
+ /** Return the time at which we should next check for available updates,
+ * given the last we checked was at <b>lastCheckedAt</b>.
+ */
+ static QDateTime nextCheckForUpdates(const QDateTime &lastCheckedAt);
+
+ /** Return true if we should check for available software udpates, given
+ * the last time we checked was at <b>lastCheckedAt</b>. The returned
+ * QDateTime will be in UTC.
+ */
+ static bool shouldCheckForUpdates(const QDateTime &lastCheckedAt);
+
+ /** Returns the preferred interval (in seconds) between executions of the
+ * Glider process to check for available software updates.
+ */
+ static int checkForUpdatesInterval();
+
+ /** Returns the path and filename of the software update executable.
+ */
+ static QString updateExecutable();
+
+ /** Returns the path in which the software update executable should write
+ * all of its state information.
+ */
+ static QString updateRepositoryDir();
+
+signals:
+ /** Emitted when the check for available software updates failed.
+ * <b>errmsg</b> contains a human-readable description of the problem
+ * encountered.
+ */
+ void checkForUpdatesFailed(QString errmsg);
+
+ /** Emitted while an updated package download is in progress. <b>url</b> is
+ * location of the update, <b>bytesReceived</b> is how many bytes have been
+ * downloaded so far and <b>bytesTotal</b> is the total size of the package
+ * being downloaded. */
+ void downloadProgress(QString url, int bytesReceived, int bytesTotal);
+
+ /** Emitted when updated software packages in bundle <b>bi</b> are
+ * are available. <b>packages</b> contains a collection of PackageInfo objects
+ * describing the updates available for installation.
+ */
+ void updatesAvailable(UpdateProcess::BundleInfo bi, PackageList packages);
+
+ /** Emitted after all available updated packages have been successfully
+ * installed.
+ */
+ void updatesInstalled(int nPackagesInstalled);
+
+ /** Emitted when there is an error installing one or more updated software
+ * packages. <b>errmsg</b> might even contain a useful description of the
+ * error encountered (but don't bet the farm on it).
+ */
+ void installUpdatesFailed(QString errmsg);
+
+public slots:
+ /** Cancels the currently running software update operation immediately. */
+ void cancel();
+
+protected slots:
+ /** Called when there is data to be read from the update process's stdout.
+ * Reads and parses all available data.
+ */
+ void readStandardOutput();
+
+ /** Called when there is data to be read from the update process's stderr.
+ * Reads and parses all available data.
+ */
+ void readStandardError();
+
+ /** Called when the underlying QProcess encounters an error.
+ */
+ void onError(QProcess::ProcessError error);
+
+ /** Called when the auto-update process has terminated.
+ */
+ void onFinished(int exitCode, QProcess::ExitStatus exitStatus);
+
+protected:
+ enum UpdateCommand {
+ NoCommand,
+ CheckForUpdates,
+ InstallUpdates,
+ };
+
+ /** Converts a BundleInfo enum value to its proper Thandy-recognized URL
+ * for the current OS and architecture. */
+ QString bundleInfoToString(BundleInfo bundleInfo);
+
+ /** Returns a PackageInfo object containing information about the updated
+ * package specified by the /pkginfo/ URL in <b>package</b>.
+ */
+ static PackageInfo packageInfo(const QString &package);
+
+ /** Returns a PackageInfo object populated with information extracted
+ * from a Thandy-formatted XML document given by <b>xml</b>.
+ */
+ static PackageInfo packageInfoFromXml(const QByteArray &xml);
+
+private:
+ /** Enum value of the current auto-update operation. */
+ UpdateCommand _currentCommand;
+
+ /** Enum value of the last bundle for which we performed some action
+ * (e.g., check for updates, install an update, etc. */
+ BundleInfo _currentBundle;
+
+ /** List of packages that have available updates. */
+ PackageList _packageList;
+
+ /** Currently configured SOCKS port. */
+ quint16 _socksPort;
+};
+
+#endif
+
Copied: vidalia/trunk/src/vidalia/updateprogressdialog.cpp (from rev 3409, vidalia/branches/auto-updates/src/vidalia/updateprogressdialog.cpp)
===================================================================
--- vidalia/trunk/src/vidalia/updateprogressdialog.cpp (rev 0)
+++ vidalia/trunk/src/vidalia/updateprogressdialog.cpp 2009-01-03 20:10:16 UTC (rev 3413)
@@ -0,0 +1,92 @@
+/*
+** This file is part of Vidalia, and is subject to the license terms in the
+** LICENSE file, found in the top level directory of this distribution. If you
+** did not receive the LICENSE file with this file, you may obtain it from the
+** Vidalia source package distributed by the Vidalia Project at
+** http://www.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+#include "updateprogressdialog.h"
+
+
+UpdateProgressDialog::UpdateProgressDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ ui.setupUi(this);
+
+ connect(ui.btnHide, SIGNAL(clicked()), this, SLOT(onHide()));
+ connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(onCancel()));
+
+ setModal(true);
+}
+
+void
+UpdateProgressDialog::setStatus(UpdateProgressDialog::Status status)
+{
+ switch (status) {
+ case CheckingForUpdates:
+ ui.lblCurrentAction->setText(tr("Checking for available updates..."));
+
+ ui.progressBar->setMinimum(0);
+ ui.progressBar->setMaximum(0);
+
+ ui.btnHide->setText(tr("Hide"));
+ ui.btnCancel->setVisible(true);
+ ui.btnCancel->setEnabled(true);
+ break;
+
+ case DownloadingUpdates:
+ ui.lblCurrentAction->setText(tr("Downloading updates..."));
+ break;
+
+ case InstallingUpdates:
+ ui.lblCurrentAction->setText(tr("Installing updated software..."));
+
+ ui.progressBar->setMinimum(0);
+ ui.progressBar->setMaximum(0);
+
+ ui.btnCancel->setEnabled(false);
+ break;
+
+ case UpdatesInstalled:
+ ui.lblCurrentAction->setText(tr("Done! Your software is now up to date."));
+
+ ui.progressBar->setMinimum(0);
+ ui.progressBar->setMaximum(1);
+ ui.progressBar->setValue(1);
+
+ ui.btnHide->setText(tr("OK"));
+ ui.btnCancel->setVisible(false);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+UpdateProgressDialog::setDownloadProgress(const QString &url,
+ int bytesReceived, int bytesTotal)
+{
+ Q_UNUSED(url);
+
+ setStatus(DownloadingUpdates);
+ ui.progressBar->setMaximum(bytesTotal);
+ ui.progressBar->setValue(bytesReceived);
+}
+
+void
+UpdateProgressDialog::onHide()
+{
+ setVisible(false);
+}
+
+void
+UpdateProgressDialog::onCancel()
+{
+ emit cancelUpdate();
+ hide();
+}
+
Copied: vidalia/trunk/src/vidalia/updateprogressdialog.h (from rev 3409, vidalia/branches/auto-updates/src/vidalia/updateprogressdialog.h)
===================================================================
--- vidalia/trunk/src/vidalia/updateprogressdialog.h (rev 0)
+++ vidalia/trunk/src/vidalia/updateprogressdialog.h 2009-01-03 20:10:16 UTC (rev 3413)
@@ -0,0 +1,70 @@
+/*
+** This file is part of Vidalia, and is subject to the license terms in the
+** LICENSE file, found in the top level directory of this distribution. If you
+** did not receive the LICENSE file with this file, you may obtain it from the
+** Vidalia source package distributed by the Vidalia Project at
+** http://www.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+#ifndef _UPDATEPROGRESSDIALOG_H
+#define _UPDATEPROGRESSDIALOG_H
+
+#include <QDialog>
+
+#include "ui_updateprogressdialog.h"
+
+
+class UpdateProgressDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ enum Status {
+ CheckingForUpdates,
+ DownloadingUpdates,
+ InstallingUpdates,
+ UpdatesInstalled,
+ };
+
+ /** Default constructor.
+ */
+ UpdateProgressDialog(QWidget *parent = 0);
+
+ /** Updates the dialog's display to reflect the current action indicated
+ * by <b>status</b>.
+ */
+ void setStatus(UpdateProgressDialog::Status status);
+
+signals:
+ /** Emitted when the user clicks the "Cancel" button indicating they
+ * want to terminate the current check for available updates.
+ */
+ void cancelUpdate();
+
+public slots:
+ /** Called when more bytes of <b>url</b> have been received.
+ * <b>bytesReceived</b> indicates how many bytes have been downloaded so
+ * far and <b>bytesTotal</b> indicates the total size of the update to be
+ * downloaded.
+ */
+ void setDownloadProgress(const QString &url,
+ int bytesReceived, int bytesTotal);
+
+private slots:
+ /** Called when the user clicks the "Cancel" button. Emits the
+ * cancelUpdate() signal.
+ */
+ void onHide();
+
+ /** Called when the user clicks the "Hide" button. Hides the dialog
+ * box.
+ */
+ void onCancel();
+
+private:
+ Ui::UpdateProgressDialog ui; /**< Qt Designer generated object. */
+};
+
+#endif
Copied: vidalia/trunk/src/vidalia/updateprogressdialog.ui (from rev 3409, vidalia/branches/auto-updates/src/vidalia/updateprogressdialog.ui)
===================================================================
--- vidalia/trunk/src/vidalia/updateprogressdialog.ui (rev 0)
+++ vidalia/trunk/src/vidalia/updateprogressdialog.ui 2009-01-03 20:10:16 UTC (rev 3413)
@@ -0,0 +1,102 @@
+<ui version="4.0" >
+ <class>UpdateProgressDialog</class>
+ <widget class="QDialog" name="UpdateProgressDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>366</width>
+ <height>104</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Software Updates</string>
+ </property>
+ <property name="windowIcon" >
+ <iconset resource="res/vidalia.qrc" >
+ <normaloff>:/images/32x32/system-software-update.png</normaloff>:/images/32x32/system-software-update.png</iconset>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" >
+ <item rowspan="2" row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="pixmap" >
+ <pixmap resource="res/vidalia.qrc" >:/images/48x48/system-software-update.png</pixmap>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignBottom|Qt::AlignHCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLabel" name="lblCurrentAction" >
+ <property name="text" >
+ <string>Checking for updates...</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+ </property>
+ <property name="wordWrap" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QProgressBar" name="progressBar" >
+ <property name="maximum" >
+ <number>0</number>
+ </property>
+ <property name="value" >
+ <number>-1</number>
+ </property>
+ <property name="textVisible" >
+ <bool>false</bool>
+ </property>
+ <property name="format" >
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2" >
+ <layout class="QHBoxLayout" name="horizontalLayout" >
+ <item>
+ <spacer name="horizontalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnCancel" >
+ <property name="text" >
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnHide" >
+ <property name="text" >
+ <string>Hide</string>
+ </property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="res/vidalia.qrc" />
+ </resources>
+ <connections/>
+</ui>
Added: vidalia/trunk/src/vidalia/updatesavailabledialog.cpp
===================================================================
--- vidalia/trunk/src/vidalia/updatesavailabledialog.cpp (rev 0)
+++ vidalia/trunk/src/vidalia/updatesavailabledialog.cpp 2009-01-03 20:10:16 UTC (rev 3413)
@@ -0,0 +1,100 @@
+/*
+** This file is part of Vidalia, and is subject to the license terms in the
+** LICENSE file, found in the top level directory of this distribution. If you
+** did not receive the LICENSE file with this file, you may obtain it from the
+** Vidalia source package distributed by the Vidalia Project at
+** http://www.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+/*
+** \file InstallUpdatesAvailableDialog.cpp
+** \version $Id$
+** \brief Displays a list of available updates and details, such as release
+** notes. The user can choose to either install the updates now or later, or
+** skip the updates entirely.
+*/
+
+#include <vidalia.h>
+#include <QHeaderView>
+
+#include "updatesavailabledialog.h"
+
+
+UpdatesAvailableDialog::UpdatesAvailableDialog(const PackageList &packageList,
+ QWidget *parent)
+ : QDialog(parent)
+{
+ ui.setupUi(this);
+
+ connect(ui.btnInstall, SIGNAL(clicked()),
+ this, SLOT(installUpdatesNow()));
+ connect(ui.btnInstallLater, SIGNAL(clicked()),
+ this, SLOT(installUpdatesLater()));
+
+ connect(ui.treeUpdates,
+ SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
+ this, SLOT(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
+
+ loadPackagesTable(packageList);
+}
+
+void
+UpdatesAvailableDialog::showEvent(QShowEvent *e)
+{
+ ui.treeUpdates->header()->resizeSection(0, 240);
+ ui.treeUpdates->header()->setResizeMode(1, QHeaderView::ResizeToContents);
+ QDialog::showEvent(e);
+}
+
+void
+UpdatesAvailableDialog::loadPackagesTable(const PackageList &packageList)
+{
+ int row = 0;
+ QString language;
+ QTreeWidgetItem *item;
+
+ language = Vidalia::language();
+
+ foreach (PackageInfo package, packageList) {
+ item = new QTreeWidgetItem(ui.treeUpdates);
+
+ if (package.hasShortDescription(language))
+ item->setText(0, package.shortDescription(language));
+ else
+ item->setText(0, package.shortDescription("en"));
+
+ if (package.hasLongDescription(language))
+ item->setData(0, Qt::UserRole, package.longDescription(language));
+ else
+ item->setData(0, Qt::UserRole, package.longDescription("en"));
+
+ item->setText(1, package.version());
+ ui.treeUpdates->insertTopLevelItem(row++, item);
+ }
+}
+
+void
+UpdatesAvailableDialog::currentItemChanged(QTreeWidgetItem *current,
+ QTreeWidgetItem *previous)
+{
+ Q_UNUSED(previous);
+
+ ui.textDetails->clear();
+ if (current)
+ ui.textDetails->setText(current->data(0, Qt::UserRole).toString());
+}
+
+void
+UpdatesAvailableDialog::installUpdatesNow()
+{
+ done(InstallUpdatesNow);
+}
+
+void
+UpdatesAvailableDialog::installUpdatesLater()
+{
+ done(InstallUpdatesLater);
+}
+
Property changes on: vidalia/trunk/src/vidalia/updatesavailabledialog.cpp
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: vidalia/trunk/src/vidalia/updatesavailabledialog.h
===================================================================
--- vidalia/trunk/src/vidalia/updatesavailabledialog.h (rev 0)
+++ vidalia/trunk/src/vidalia/updatesavailabledialog.h 2009-01-03 20:10:16 UTC (rev 3413)
@@ -0,0 +1,76 @@
+/*
+** This file is part of Vidalia, and is subject to the license terms in the
+** LICENSE file, found in the top level directory of this distribution. If you
+** did not receive the LICENSE file with this file, you may obtain it from the
+** Vidalia source package distributed by the Vidalia Project at
+** http://www.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+/*
+** \file UpdatesAvailableDialog.h
+** \version $Id$
+** \brief Displays a list of available updates and details, such as release
+** notes. The user can choose to either install the updates now or later, or
+** skip the updates entirely.
+*/
+
+#ifndef _UpdatesAvailableDialog_H
+#define _UpdatesAvailableDialog_H
+
+#include <QDialog>
+#include <QShowEvent>
+#include <QTreeWidgetItem>
+
+#include "packageinfo.h"
+#include "ui_updatesavailabledialog.h"
+
+
+class UpdatesAvailableDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ enum UpdatesAvailableDialogExitCode {
+ InstallUpdatesNow = 100,
+ InstallUpdatesLater = 101,
+ };
+
+ /** Constructor. */
+ UpdatesAvailableDialog(const PackageList &packageList, QWidget *parent = 0);
+
+protected:
+ /** Called when the dialog receives a QShowEvent. This simply adjusts
+ * the column widths to something close to sane and forwards the event
+ * to the parent.
+ */
+ virtual void showEvent(QShowEvent *e);
+
+private slots:
+ /** Called when the user selects a different package in the list. The widget
+ * displaying details on the selected package will be updated.
+ */
+ void currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
+
+ /** Called when the user opts to install the displayed software updates
+ * immediately.
+ */
+ void installUpdatesNow();
+
+ /** Called when the user opts to install the display software updates at
+ * a later time.
+ */
+ void installUpdatesLater();
+
+private:
+ /** Populates the table of available updates with package information
+ * from <b>packageList</b>.
+ */
+ void loadPackagesTable(const PackageList &packageList);
+
+ Ui::UpdatesAvailableDialog ui; /**< Qt Designer generated object. */
+};
+
+#endif
+
Property changes on: vidalia/trunk/src/vidalia/updatesavailabledialog.h
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: vidalia/trunk/src/vidalia/updatesavailabledialog.ui
===================================================================
--- vidalia/trunk/src/vidalia/updatesavailabledialog.ui (rev 0)
+++ vidalia/trunk/src/vidalia/updatesavailabledialog.ui 2009-01-03 20:10:16 UTC (rev 3413)
@@ -0,0 +1,96 @@
+<ui version="4.0" >
+ <class>UpdatesAvailableDialog</class>
+ <widget class="QDialog" name="UpdatesAvailableDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>365</width>
+ <height>350</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Software Updates Available</string>
+ </property>
+ <property name="windowIcon" >
+ <iconset resource="res/vidalia.qrc" >
+ <normaloff>:/images/32x32/system-software-update.png</normaloff>:/images/32x32/system-software-update.png</iconset>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" >
+ <item row="2" column="0" colspan="2" >
+ <layout class="QHBoxLayout" name="horizontalLayout" >
+ <item>
+ <spacer name="horizontalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnInstallLater" >
+ <property name="text" >
+ <string>Remind Me Later</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnInstall" >
+ <property name="text" >
+ <string>Install</string>
+ </property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="0" colspan="2" >
+ <widget class="QLabel" name="lblUpdatesAvailable" >
+ <property name="text" >
+ <string>The following updated software packages are ready for installation:</string>
+ </property>
+ <property name="wordWrap" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2" >
+ <widget class="QSplitter" name="splitter" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <widget class="QTreeWidget" name="treeUpdates" >
+ <property name="rootIsDecorated" >
+ <bool>false</bool>
+ </property>
+ <property name="itemsExpandable" >
+ <bool>false</bool>
+ </property>
+ <column>
+ <property name="text" >
+ <string>Package</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Version</string>
+ </property>
+ </column>
+ </widget>
+ <widget class="QTextBrowser" name="textDetails" />
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="res/vidalia.qrc" />
+ </resources>
+ <connections/>
+</ui>