Replace UpdateObserver with UpdateController class which uses signal/slot notifications using the sigslot library.

This commit is contained in:
Robert Knight 2012-05-04 16:04:19 +01:00
parent 932cddfb77
commit d69b8288ee
15 changed files with 2608 additions and 48 deletions

View file

@ -12,6 +12,7 @@ option(SIGN_UPDATER OFF)
include_directories(external)
include_directories(external/TinyThread/source)
include_directories(external/sigslot/)
if (WIN32)
include_directories(external/zlib/)

2507
external/sigslot/sigslot.h vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -31,6 +31,7 @@ set (SOURCES
Log.cpp
ProcessUtils.cpp
StandardDirs.cpp
UpdateController.cpp
UpdateInstaller.cpp
UpdateScript.cpp
UpdaterOptions.cpp
@ -65,6 +66,7 @@ set (HEADERS
Log.h
ProcessUtils.h
StandardDirs.h
UpdateController.h
UpdateInstaller.h
UpdateScript.h
UpdaterOptions.h

6
src/UpdateController.cpp Normal file
View file

@ -0,0 +1,6 @@
#include "UpdateController.h"
UpdateController::UpdateController()
{
}

23
src/UpdateController.h Normal file
View file

@ -0,0 +1,23 @@
#pragma once
#include <sigslot.h>
/** Controller used by the UI to drive the installation
* and monitor the status of the install.
*/
class UpdateController
{
public:
UpdateController();
/** Emitted to indicate progress of update installation. */
sigslot::signal1<int> installProgress;
/** Emitted when installation fails for any reason. */
sigslot::signal1<const std::string&> installError;
/** Emitted when installation completes, whether successfully or
* following an unrecoverable error.
*/
sigslot::signal0<> finished;
};

View file

@ -1,22 +1,23 @@
#pragma once
#include "UpdateObserver.h"
#include <sigslot.h>
class UpdateDialogPrivate;
class UpdateController;
class UpdateDialogCocoa : public UpdateObserver
class UpdateDialogCocoa : public sigslot::has_slots<>
{
public:
UpdateDialogCocoa();
UpdateDialogCocoa(UpdateController* controller);
~UpdateDialogCocoa();
void init();
void exec();
// implements UpdateObserver
virtual void updateError(const std::string& errorMessage);
virtual void updateProgress(int percentage);
virtual void updateFinished();
// slots for update notifications
void updateError(const std::string& errorMessage);
void updateProgress(int percentage);
void updateFinished();
static void* createAutoreleasePool();
static void releaseAutoreleasePool(void* data);

View file

@ -6,6 +6,7 @@
#include "AppInfo.h"
#include "Log.h"
#include "StringUtils.h"
#include "UpdateController.h"
@interface UpdateDialogDelegate : NSObject
{
@ -78,9 +79,13 @@ class UpdateDialogPrivate
}
@end
UpdateDialogCocoa::UpdateDialogCocoa()
UpdateDialogCocoa::UpdateDialogCocoa(UpdateController* controller)
: d(new UpdateDialogPrivate)
{
controller->installProgress.connect(this, &UpdateDialogCocoa::updateProgress);
controller->installError.connect(this, &UpdateDialogCocoa::updateError);
controller->finished.connect(this, &UpdateDialogCocoa::updateFinished);
[NSApplication sharedApplication];
d->pool = [[NSAutoreleasePool alloc] init];
}

View file

@ -1,11 +1,10 @@
#pragma once
#include "UpdateMessage.h"
#include "UpdateObserver.h"
#include <gtk/gtk.h>
class UpdateDialogGtk : public UpdateObserver
class UpdateDialogGtk
{
public:
UpdateDialogGtk();
@ -15,9 +14,9 @@ class UpdateDialogGtk : public UpdateObserver
// observer callbacks - these may be called
// from a background thread
virtual void updateError(const std::string& errorMessage);
virtual void updateProgress(int percentage);
virtual void updateFinished();
void updateError(const std::string& errorMessage);
void updateProgress(int percentage);
void updateFinished();
private:
static void finish(GtkWidget* widget, gpointer dialog);

View file

@ -2,6 +2,7 @@
#include "Log.h"
#include "StringUtils.h"
#include "UpdateController.h"
#include <dlfcn.h>
#include <errno.h>
@ -41,9 +42,12 @@ bool extractFileFromBinary(const char* path, const void* buffer, size_t length)
return true;
}
UpdateDialogGtkWrapper::UpdateDialogGtkWrapper()
UpdateDialogGtkWrapper::UpdateDialogGtkWrapper(UpdateController* controller)
: m_dialog(0)
{
controller->installProgress.connect(this, &UpdateDialogGtkWrapper::updateProgress);
controller->installError.connect(this, &UpdateDialogGtkWrapper::updateError);
controller->finished.connect(this, &UpdateDialogGtkWrapper::updateFinished);
}
bool UpdateDialogGtkWrapper::init(int argc, char** argv)

View file

@ -1,14 +1,15 @@
#pragma once
#include "UpdateObserver.h"
#include <sigslot.h>
class UpdateDialogGtk;
class UpdateController;
/** A wrapper around UpdateDialogGtk which allows the GTK UI to
* be loaded dynamically at runtime if the GTK libraries are
* available.
*/
class UpdateDialogGtkWrapper : public UpdateObserver
class UpdateDialogGtkWrapper : public sigslot::has_slots<>
{
public:
UpdateDialogGtkWrapper();
@ -20,9 +21,9 @@ class UpdateDialogGtkWrapper : public UpdateObserver
bool init(int argc, char** argv);
void exec();
virtual void updateError(const std::string& errorMessage);
virtual void updateProgress(int percentage);
virtual void updateFinished();
void updateError(const std::string& errorMessage);
void updateProgress(int percentage);
void updateFinished();
private:
UpdateDialogGtk* m_dialog;

View file

@ -1,5 +1,6 @@
#include "UpdateDialogWin32.h"
#include "UpdateController.h"
#include "AppInfo.h"
#include "Log.h"
@ -58,9 +59,13 @@ void registerWindowClass()
RegisterClassEx(&wcex);
}
UpdateDialogWin32::UpdateDialogWin32()
UpdateDialogWin32::UpdateDialogWin32(UpdateController* controller)
: m_hadError(false)
{
controller->installProgress.connect(this, &UpdateDialogWin32::updateProgress);
controller->installError.connect(this, &UpdateDialogWin32::updateError);
controller->finished.connect(this, &UpdateDialogWin32::updateFinished);
registerWindowClass();
}

View file

@ -2,25 +2,28 @@
#include "Platform.h"
#include "UpdateMessage.h"
#include "UpdateObserver.h"
#include "wincore.h"
#include "controls.h"
#include "stdcontrols.h"
class UpdateDialogWin32 : public UpdateObserver
#include <sigslot.h>
class UpdateController;
class UpdateDialogWin32 : public has_slots<>
{
public:
UpdateDialogWin32();
UpdateDialogWin32(UpdateController* controller);
~UpdateDialogWin32();
void init();
void exec();
// implements UpdateObserver
virtual void updateError(const std::string& errorMessage);
virtual void updateProgress(int percentage);
virtual void updateFinished();
void updateError(const std::string& errorMessage);
void updateProgress(int percentage);
void updateFinished();
LRESULT WINAPI windowProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam);

View file

@ -4,13 +4,13 @@
#include "FileUtils.h"
#include "Log.h"
#include "ProcessUtils.h"
#include "UpdateObserver.h"
#include "UpdateController.h"
UpdateInstaller::UpdateInstaller()
: m_mode(Setup)
, m_waitPid(0)
, m_script(0)
, m_observer(0)
, m_controller(0)
, m_forceElevated(false)
{
}
@ -64,10 +64,10 @@ std::list<std::string> UpdateInstaller::updaterArgs() const
void UpdateInstaller::reportError(const std::string& error)
{
if (m_observer)
if (m_controller)
{
m_observer->updateError(error);
m_observer->updateFinished();
m_controller->installError.emit(error);
m_controller->finished.emit();
}
}
@ -213,19 +213,19 @@ void UpdateInstaller::run() throw ()
LOG(Error,"Error reverting partial update " + std::string(exception.what()));
}
if (m_observer)
if (m_controller)
{
if (friendlyError.empty())
{
friendlyError = error;
}
m_observer->updateError(friendlyError);
m_controller->installError.emit(friendlyError);
}
}
if (m_observer)
if (m_controller)
{
m_observer->updateFinished();
m_controller->finished.emit();
}
}
}
@ -319,11 +319,11 @@ void UpdateInstaller::installFiles()
{
installFile(*iter);
++filesInstalled;
if (m_observer)
if (m_controller)
{
int toInstallCount = static_cast<int>(m_script->filesToInstall().size());
double percentage = ((1.0 * filesInstalled) / toInstallCount) * 100.0;
m_observer->updateProgress(static_cast<int>(percentage));
m_controller->installProgress.emit(static_cast<int>(percentage));
}
}
}
@ -395,9 +395,9 @@ bool UpdateInstaller::checkAccess()
}
}
void UpdateInstaller::setObserver(UpdateObserver* observer)
void UpdateInstaller::setController(UpdateController* controller)
{
m_observer = observer;
m_controller = controller;
}
void UpdateInstaller::restartMainApp()

View file

@ -8,7 +8,7 @@
#include <string>
#include <map>
class UpdateObserver;
class UpdateController;
/** Central class responsible for installing updates,
* launching an elevated copy of the updater if required
@ -33,7 +33,7 @@ class UpdateInstaller
void setWaitPid(PLATFORM_PID pid);
void setForceElevated(bool elevated);
void setObserver(UpdateObserver* observer);
void setController(UpdateController* controller);
void run() throw ();
@ -61,7 +61,7 @@ class UpdateInstaller
std::string m_backupDir;
PLATFORM_PID m_waitPid;
UpdateScript* m_script;
UpdateObserver* m_observer;
UpdateController* m_controller;
std::map<std::string,std::string> m_backups;
bool m_forceElevated;
};

View file

@ -4,6 +4,7 @@
#include "Platform.h"
#include "ProcessUtils.h"
#include "StringUtils.h"
#include "UpdateController.h"
#include "UpdateScript.h"
#include "UpdaterOptions.h"
@ -164,17 +165,18 @@ int main(int argc, char** argv)
#ifdef PLATFORM_LINUX
void runWithUi(int argc, char** argv, UpdateInstaller* installer)
{
UpdateDialogAscii asciiDialog;
UpdateDialogGtkWrapper dialog;
UpdateController updateController;
UpdateDialogAscii asciiDialog(&updateController);
UpdateDialogGtkWrapper dialog(&updateController);
bool useGtk = dialog.init(argc,argv);
if (useGtk)
{
installer->setObserver(&dialog);
installer->setController(&dialog);
}
else
{
asciiDialog.init();
installer->setObserver(&asciiDialog);
installer->setController(&asciiDialog);
}
tthread::thread updaterThread(runUpdaterThread,installer);
if (useGtk)
@ -188,8 +190,9 @@ void runWithUi(int argc, char** argv, UpdateInstaller* installer)
#ifdef PLATFORM_MAC
void runWithUi(int argc, char** argv, UpdateInstaller* installer)
{
UpdateDialogCocoa dialog;
installer->setObserver(&dialog);
UpdateController updateController;
UpdateDialogCocoa dialog(&updateController);
installer->setController(&updateController);
dialog.init();
tthread::thread updaterThread(runUpdaterThread,installer);
dialog.exec();