mirror of
https://github.com/HackPlan/winsparkle.git
synced 2026-04-30 11:01:51 +08:00
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:
@@ -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" />
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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
25
src/hostpoller.cpp
Normal 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
22
src/hostpoller.h
Normal 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
|
||||
99
src/ui.cpp
99
src/ui.cpp
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user