Provide UI when waiting for host app

Now we continuously poll the host if it's ready to terminate (every .5
second) in a thread while displaying an indefinite progressbar to the
user and telling him that we are waiting for the host to terminate.
This commit is contained in:
Örn Guðjónsson
2013-09-25 17:27:18 +00:00
parent 1b35859e9c
commit ba556458e0
7 changed files with 148 additions and 13 deletions

View File

@@ -178,6 +178,7 @@
<ClCompile Include="src\dllmain.cpp" />
<ClCompile Include="src\download.cpp" />
<ClCompile Include="src\error.cpp" />
<ClCompile Include="src\hostpoller.cpp" />
<ClCompile Include="src\settings.cpp" />
<ClCompile Include="src\threads.cpp" />
<ClCompile Include="src\ui.cpp" />
@@ -190,6 +191,7 @@
<ClInclude Include="src\appcast.h" />
<ClInclude Include="src\download.h" />
<ClInclude Include="src\error.h" />
<ClInclude Include="src\hostpoller.h" />
<ClInclude Include="src\settings.h" />
<ClInclude Include="src\threads.h" />
<ClInclude Include="src\ui.h" />

View File

@@ -45,6 +45,9 @@
<ClCompile Include="src\updatedownloader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\hostpoller.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\winsparkle.h">
@@ -83,6 +86,9 @@
<ClInclude Include="src\winsparkletypes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\hostpoller.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="src\winsparkle.rc">

View File

@@ -109,8 +109,14 @@ int RegisterMainClass()
return RegisterClass(&wc) != 0;
}
int counter = 0;
int shutDownPollCallback()
{
if( counter < 5)
{
counter++;
return FALSE;
}
return TRUE;
}

25
src/hostpoller.cpp Normal file
View File

@@ -0,0 +1,25 @@
#include "hostpoller.h"
namespace winsparkle
{
HostPoller::HostPoller()
: Thread("WinSparkle HostPoller")
{
}
void HostPoller::Run()
{
SignalReady();
while(!UI::IsHostReadyToShutDown())
{
//sleep for half a second and try again until we are successful
Sleep(500);
}
//Now we are clear to run the installer and exit the app
UI::ExecuteInstaller();
}
} //namespace winsparkle

22
src/hostpoller.h Normal file
View File

@@ -0,0 +1,22 @@
#pragma once
#ifndef _hostpoller_h
#define _hostpoller_h
#include "threads.h"
#include "ui.h"
namespace winsparkle
{
class HostPoller : public Thread
{
public:
HostPoller();
protected:
virtual void Run();
virtual bool IsJoinable() const { return true; }
};
} //namespace winsparkle
#endif //_hostpoller_h

View File

@@ -31,6 +31,7 @@
#include "error.h"
#include "updatechecker.h"
#include "updatedownloader.h"
#include "hostpoller.h"
#define wxNO_NET_LIB
#define wxNO_XML_LIB
@@ -288,7 +289,11 @@ public:
void DownloadProgress(size_t downloaded, size_t total);
// change state into "update downloaded"
void StateUpdateDownloaded(const std::string& updateFile);
//change state into "waiting for host application to terminate"
void StateWaitForHostToTerminate();
//run the downloaded installer and tell the host to terminate
void ExecuteInstaller();
private:
void EnablePulsing(bool enable);
void OnTimer(wxTimerEvent& event);
@@ -328,6 +333,7 @@ private:
wxString m_updateFile;
// downloader (only valid between OnInstall and OnUpdateDownloaded)
UpdateDownloader* m_downloader;
HostPoller* m_hostpoller;
static const int RELNOTES_WIDTH = 460;
static const int RELNOTES_HEIGHT = 200;
@@ -460,6 +466,13 @@ void UpdateDialog::OnClose(wxCloseEvent&)
UpdateDownloader::CleanLeftovers();
}
if( m_hostpoller )
{
m_hostpoller->TerminateAndJoin();
delete m_hostpoller;
m_hostpoller = NULL;
}
// We need to override this, because by default, wxDialog doesn't
// destroy itself in Close().
Destroy();
@@ -490,6 +503,19 @@ void UpdateDialog::OnInstall(wxCommandEvent&)
m_downloader->Start();
}
void UpdateDialog::ExecuteInstaller()
{
if ( !wxLaunchDefaultApplication(m_updateFile) )
{
wxLogError(_("Failed to launch the installer."));
wxLog::FlushActive();
}
else
{
Close();
UI::RequestHostTermination();
}
}
void UpdateDialog::OnRunInstaller(wxCommandEvent&)
{
@@ -498,23 +524,18 @@ void UpdateDialog::OnRunInstaller(wxCommandEvent&)
m_message->SetLabel(_("Launching the installer..."));
m_runInstallerButton->Disable();
while(!UI::IsHostReadyToShutDown())
if(!UI::IsHostReadyToShutDown())
{
//FIXME: Do something proper instead of this loop.
Sleep(2000);
//Show UI stuff and wait
UpdateDialog::StateWaitForHostToTerminate();
m_hostpoller = new HostPoller();
m_hostpoller->Start();
}
if ( !wxLaunchDefaultApplication(m_updateFile) )
{
wxLogError(_("Failed to launch the installer."));
wxLog::FlushActive();
}
else
{
UI::RequestHostTermination();
ExecuteInstaller();
Close();
}
Close();
}
@@ -544,6 +565,25 @@ void UpdateDialog::StateCheckingUpdates()
MakeResizable(false);
}
void UpdateDialog::StateWaitForHostToTerminate()
{
LayoutChangesGuard guard(this);
SetMessage(_("Shutting down..."));
m_closeButton->SetLabel(_("Cancel"));
EnablePulsing(true);
HIDE(m_heading);
SHOW(m_progress);
HIDE(m_progressLabel);
SHOW(m_closeButtonSizer);
HIDE(m_runInstallerButtonSizer);
HIDE(m_releaseNotesSizer);
HIDE(m_updateButtonsSizer);
MakeResizable(false);
}
void UpdateDialog::StateNoUpdateFound()
{
@@ -912,6 +952,12 @@ const int MSG_UPDATE_DOWNLOADED = wxNewId();
// Tell the UI to ask for permission to check updates
const int MSG_ASK_FOR_PERMISSION = wxNewId();
//Tell the UI to tell the user we are waiting for the application to shut down
const int MSG_WAIT_FOR_HOST_TO_TERMINATE = wxNewId();
//Tell the UI to tell the application to Terminate
const int MSG_TELL_HOST_TO_TERMINATE = wxNewId();
/*--------------------------------------------------------------------------*
Application
@@ -938,6 +984,8 @@ private:
void OnDownloadProgress(wxThreadEvent& event);
void OnUpdateDownloaded(wxThreadEvent& event);
void OnAskForPermission(wxThreadEvent& event);
void OnWaitForHostToTerminate(wxThreadEvent& event);
void OnTellHostToTerminate(wxThreadEvent& event);
private:
UpdateDialog *m_win;
@@ -973,6 +1021,8 @@ App::App()
Bind(wxEVT_COMMAND_THREAD, &App::OnDownloadProgress, this, MSG_DOWNLOAD_PROGRESS);
Bind(wxEVT_COMMAND_THREAD, &App::OnUpdateDownloaded, this, MSG_UPDATE_DOWNLOADED);
Bind(wxEVT_COMMAND_THREAD, &App::OnAskForPermission, this, MSG_ASK_FOR_PERMISSION);
Bind(wxEVT_COMMAND_THREAD, &App::OnWaitForHostToTerminate, this, MSG_WAIT_FOR_HOST_TO_TERMINATE);
Bind(wxEVT_COMMAND_THREAD, &App::OnTellHostToTerminate, this, MSG_TELL_HOST_TO_TERMINATE);
}
@@ -1085,6 +1135,22 @@ void App::OnAskForPermission(wxThreadEvent& event)
}
}
void App::OnWaitForHostToTerminate(wxThreadEvent& event)
{
if( m_win )
{
m_win->StateWaitForHostToTerminate();
}
}
void App::OnTellHostToTerminate(wxThreadEvent& event)
{
if( m_win )
{
m_win->ExecuteInstaller();
}
}
/*--------------------------------------------------------------------------*
winsparkle::UI class
@@ -1288,4 +1354,11 @@ void UI::RequestHostTermination()
}
}
/*static*/
void UI::ExecuteInstaller()
{
UIThreadAccess uit;
uit.App().SendMsg(MSG_TELL_HOST_TO_TERMINATE);
}
} // namespace winsparkle

View File

@@ -127,6 +127,7 @@ public:
*/
static void RequestHostTermination();
static void ExecuteInstaller();
protected:
virtual void Run();
virtual bool IsJoinable() const { return true; }