From 0cd4f1225dcad3f73dfb679de7ed60302ce99047 Mon Sep 17 00:00:00 2001 From: Amar Takhar Date: Tue, 26 Jan 2010 13:14:05 +0000 Subject: [PATCH] Merge 3906,r3909,r3910,r3912,r3928,r3931,r3932,r3933,r3935,r3936: merge update checker from 2.1.8, this also needs to be documented for doxygen. closes #1084. Originally committed to SVN as r4042. --- aegisub/src/agi_pre.h | 2 + aegisub/src/dialog_version_check.cpp | 724 ++++++++++++++++++--------- aegisub/src/dialog_version_check.h | 88 +--- aegisub/src/frame_main.cpp | 14 +- aegisub/src/frame_main_events.cpp | 5 +- aegisub/src/options.cpp | 2 + 6 files changed, 499 insertions(+), 336 deletions(-) diff --git a/aegisub/src/agi_pre.h b/aegisub/src/agi_pre.h index b0f535704..a13c94bcf 100644 --- a/aegisub/src/agi_pre.h +++ b/aegisub/src/agi_pre.h @@ -173,6 +173,7 @@ #include #include #include +#include #include #include #include @@ -187,6 +188,7 @@ #include #include #include +#include #include #include #include diff --git a/aegisub/src/dialog_version_check.cpp b/aegisub/src/dialog_version_check.cpp index 242bdd12c..4835a078f 100644 --- a/aegisub/src/dialog_version_check.cpp +++ b/aegisub/src/dialog_version_check.cpp @@ -35,285 +35,519 @@ /// -/////////// -// Headers #include "config.h" #ifndef AGI_PRE -#include +#ifdef WIN32 +// Congratulation wx, you forgot to include a header somewhere +#include +#endif + +#include #include -#include -#include -#include +#include +#include #include +#include +#include +#include +#include +#include #endif #include "dialog_version_check.h" -#include "main.h" +#include "options.h" +#include "include/aegisub/exception.h" +#include "string_codec.h" #include "version.h" -/// DOCME -bool DialogVersionCheck::dialogRunning = false; +/* *** Public API is implemented here *** */ +// Allocate global lock mutex declared in header +wxMutex VersionCheckLock; -/// @brief Constructor -/// @param parent -/// @param hidden -/// @return -/// -DialogVersionCheck::DialogVersionCheck(wxWindow *parent,bool hidden) -: wxDialog(parent,-1,_("Version Checker"),wxDefaultPosition,wxDefaultSize,wxDEFAULT_DIALOG_STYLE) +class AegisubVersionCheckerThread : public wxThread { + bool interactive; + void DoCheck(); + void PostErrorEvent(const wxString &error_text); +public: + AegisubVersionCheckerThread(bool interactive); + virtual ExitCode Entry(); +}; + +// Public API for version checker +void PerformVersionCheck(bool interactive) { - // Is already running? - if (dialogRunning) { - Destroy(); - return; - } - dialogRunning = true; + new AegisubVersionCheckerThread(interactive); +} - // Controls - wxSizer *controlSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Log")); - logBox = new wxTextCtrl(this,Log_Box,_T(""),wxDefaultPosition,wxSize(400,150),wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH | wxTE_AUTO_URL); - controlSizer->Add(logBox,1,wxEXPAND,0); - // Buttons - wxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); - buttonSizer->AddStretchSpacer(1); - buttonSizer->Add(new wxButton(this,wxID_OK),0,0,0); - // Sizer - wxSizer *mainSizer = new wxBoxSizer(wxVERTICAL); - mainSizer->Add(controlSizer,1,wxEXPAND | wxALL,5); - mainSizer->Add(buttonSizer,0,wxEXPAND | wxALL,5); - mainSizer->SetSizeHints(this); - SetSizer(mainSizer); +/* *** The actual implementation begins here *** */ - // Show - visible = false; - if (!hidden) { - Show(); - CenterOnParent(); - visible = true; + + +// A new event class for reporting the result of checking + +DEFINE_EVENT_TYPE(AEGISUB_EVENT_VERSIONCHECK_RESULT) + +struct AegisubUpdateDescription { + wxString url; + wxString friendly_name; + wxString description; +}; + +class AegisubVersionCheckResultEvent : public wxEvent { + wxString main_text; + std::vector updates; + +public: + AegisubVersionCheckResultEvent() + : wxEvent(0, AEGISUB_EVENT_VERSIONCHECK_RESULT) + { } + + virtual wxEvent *Clone() const + { + return new AegisubVersionCheckResultEvent(*this); } - // Check version - CheckVersion(); -} + const wxString & GetMainText() const { return main_text; } + void SetMainText(const wxString &new_text) { main_text = new_text; } - - -/// @brief Destructor -/// -DialogVersionCheck::~DialogVersionCheck() { - dialogRunning = false; -} - - - -/// @brief Check Version -/// -void DialogVersionCheck::CheckVersion() { - if (!wxFileSystem::HasHandlerForPath(_T("http://www.aegisub.net/"))) wxFileSystem::AddHandler(new wxInternetFSHandler); - thread = new VersionCheckThread(this); - thread->Create(); - thread->Run(); -} - - -/////////////// -// Event table -BEGIN_EVENT_TABLE(DialogVersionCheck,wxDialog) - EVT_BUTTON (wxID_OK, DialogVersionCheck::OnOK) - EVT_CLOSE (DialogVersionCheck::OnClose) - EVT_TEXT_URL(Log_Box,DialogVersionCheck::OnURL) -END_EVENT_TABLE() - - - -/// @brief On close -/// @param event -/// -void DialogVersionCheck::OnClose(wxCloseEvent &event) { - dialogRunning = false; - if (thread) thread->alive = false; - Destroy(); -} - -/// @brief DOCME -/// @param event -/// -void DialogVersionCheck::OnOK(wxCommandEvent &event) { - dialogRunning = false; - if (thread) thread->alive = false; - Destroy(); -} - - - -/// @brief On Click URL -/// @param event -/// -void DialogVersionCheck::OnURL(wxTextUrlEvent &event) { - wxMouseEvent mEvent = event.GetMouseEvent(); - if (mEvent.LeftDown()) { - wxString url = logBox->GetValue().Mid(event.GetURLStart(),event.GetURLEnd()-event.GetURLStart()+1); - AegisubApp::OpenURL(url); + // If there are no updates in the list, either none were found or an error occurred, + // either way it means "failure" if it's empty + const std::vector & GetUpdates() const { return updates; } + void AddUpdate(const wxString &url, const wxString &friendly_name, const wxString &description) + { + updates.push_back(AegisubUpdateDescription()); + AegisubUpdateDescription &desc = updates.back(); + desc.url = url; + desc.friendly_name = friendly_name; + desc.description = description; } -} + +}; + +DEFINE_SIMPLE_EXCEPTION_NOINNER(VersionCheckError, Aegisub::Exception, "versioncheck") + + +class AegisubVersionCheckEventHandler : public wxEvtHandler { +public: + void OnUpdateResult(AegisubVersionCheckResultEvent &evt); + + static void EnsureHandlerIsRegistered(); +}; -/// @brief Worker thread constructor -/// @param par -/// -VersionCheckThread::VersionCheckThread(DialogVersionCheck *par) +AegisubVersionCheckerThread::AegisubVersionCheckerThread(bool interactive) : wxThread(wxTHREAD_DETACHED) +, interactive(interactive) { - parent = par; - alive = true; + AegisubVersionCheckEventHandler::EnsureHandlerIsRegistered(); + + if (!wxSocketBase::IsInitialized()) + wxSocketBase::Initialize(); + + Create(); + Run(); } +wxThread::ExitCode AegisubVersionCheckerThread::Entry() +{ + if (!interactive) + { + // Automatic checking enabled? + if (!Options.AsBool(_T("auto check for updates"))) + return 0; -/// @brief Worker thread -/// -wxThread::ExitCode VersionCheckThread::Entry() { - // List of paths - wxArrayString paths; - paths.Add(_T("http://updates.aegisub.org/latest.txt")); - paths.Add(_T("http://files.aegisub.net/latest.txt")); - wxFSFile *fp = NULL; - - // Try each path until it finds one that works - for (unsigned int i=0;ilogBox->AppendText(_("Could not open Internet File system. Aborting.\n")); - goto endThread; - } - wxMutexGuiLeave(); - - // Open file -#ifdef __WXDEBUG__ - wxMutexGuiEnter(); - if (!alive) goto endThread; - parent->logBox->AppendText(wxString::Format(_("Attempting to open \"%s\"..."), path.c_str())); - wxMutexGuiLeave(); -#endif - wxFileSystem fs; - fp = fs.OpenFile(path); - - // Failed? - if (!fp) { -#ifdef __WXDEBUG__ - wxMutexGuiEnter(); - if (!alive) goto endThread; - parent->logBox->AppendText(_("Failed.\n")); - wxMutexGuiLeave(); -#endif - continue; - } - - // OK -#ifdef __WXDEBUG__ - wxMutexGuiEnter(); - if (!alive) goto endThread; - parent->logBox->AppendText(_("OK.\n")); - wxMutexGuiLeave(); -#endif - - // Get text input stream - wxInputStream *fstream = fp->GetStream(); - wxTextInputStream text(*fstream); - wxString contents; - - // What kind of version is this? - wxString versionKind; - double versionN; - int svnRev = GetSVNRevision(); - wxString temp = GetVersionNumber(); - temp.ToDouble(&versionN); - if (GetIsOfficialRelease()) versionKind = _T("release"); - else versionKind = _T("svn"); - - // Read lines - while (!fstream->Eof()) { - // Parse - contents = text.ReadLine(); - wxStringTokenizer tkn(contents,_T(";"),wxTOKEN_RET_EMPTY_ALL); - wxArrayString parsed; - while (tkn.HasMoreTokens()) { - parsed.Add(tkn.GetNextToken()); - } - if (parsed.Count() != 4) continue; - - // See if it's interesting - if (parsed[0] == versionKind || parsed[0] == _T("release")) { - bool newer = false; - - // Check - if (parsed[0] == _T("svn")) { - long temp; - parsed[1].ToLong(&temp); - if (temp > svnRev) newer = true; - } - else { - int pos = parsed[1].Find(_T('-')); - wxString vName = parsed[1].Left(pos); - wxString svnName = parsed[1].Mid(pos+1); - if (versionKind == _T("svn")) { - long temp; - svnName.ToLong(&temp); - if (temp >= svnRev) newer = true; - } - else { - double temp; - vName.ToDouble(&temp); - if (temp > versionN) newer = true; - } - } - - // Is newer? - if (newer) { - wxMutexGuiEnter(); - if (!alive) goto endThread; - parent->logBox->AppendText(_("New version found!\n")); - parent->logBox->AppendText(parsed[3] + _T("\n")); - parent->logBox->AppendText(wxString::Format(_("Please go to the following URL to download it: %s\n"), parsed[2].c_str())); - if (!parent->visible) { - parent->Show(); - parent->Raise(); - parent->visible = true; - } - goto endThread; - } - } - } - - // No new updates - wxMutexGuiEnter(); - if (!alive) goto endThread; - parent->logBox->AppendText(_("No new version has been found.\n")); - wxMutexGuiLeave(); - - // Delete file - delete fp; - fp = NULL; - break; + // Is it actually time for a check? + time_t next_check = Options.AsInt(_T("Updates Next Check Time")); + if ((time_t)next_check > wxDateTime::GetTimeNow()) + return 0; } - // Finish thread - wxMutexGuiEnter(); -endThread: - if (alive && !parent->visible) parent->Destroy(); - wxMutexGuiLeave(); - delete fp; - fp = NULL; + if (VersionCheckLock.TryLock() != wxMUTEX_NO_ERROR) return 0; + + try { + DoCheck(); + } + catch (const Aegisub::Exception &e) { + PostErrorEvent(wxString::Format( + _("There was an error checking for updates to Aegisub:\n%s\n\nIf other applications can access the Internet fine, this is probably a temporary server problem on our end."), + e.GetMessage().c_str())); + } + catch (...) { + PostErrorEvent(_("An unknown error occurred while checking for updates to Aegisub.")); + } + + VersionCheckLock.Unlock(); + + // While Options isn't perfectly thread safe, this should still be okay. + // Traversing the std::map to find the key-value pair doesn't modify any data as long as + // the key already exists (which it does at this point), and modifying the value only + // touches that specific key-value pair and will never cause a rebalancing of the tree, + // because the tree only depends on the keys. + // Lastly, writing options to disk only happens when Options.Save() is called. + time_t new_next_check_time = wxDateTime::GetTimeNow() + 60*60; // in one hour + Options.SetInt(_T("Updates Next Check Time"), (int)new_next_check_time); + return 0; } +void AegisubVersionCheckerThread::PostErrorEvent(const wxString &error_text) +{ + if (!interactive) return; + + AegisubVersionCheckResultEvent evt; + evt.SetMainText(error_text); + wxTheApp->AddPendingEvent(evt); +} + + +static const wxChar * GetOSShortName() +{ + int osver_maj, osver_min; + wxOperatingSystemId osid = wxGetOsVersion(&osver_maj, &osver_min); + + if (osid & wxOS_WINDOWS_NT) + { + if (osver_maj == 5 && osver_min == 0) + return _T("win2k"); + else if (osver_maj == 5 && osver_min == 1) + return _T("winxp"); + else if (osver_maj == 5 && osver_min == 2) + return _T("win2k3"); // this is also xp64 + else if (osver_maj == 6 && osver_min == 0) + return _T("win60"); // vista and server 2008 + else if (osver_maj == 6 && osver_min == 1) + return _T("win61"); // 7 and server 2008r2 + else + return _T("windows"); // future proofing? I doubt we run on nt4 + } + else if (osid & wxOS_MAC_OSX_DARWIN && osver_maj == 0x10) // yes 0x10, not decimal 10, don't ask me + { + // ugliest hack in the world? nah. + static wxChar osxstring[] = _T("osx00"); + char minor = osver_min >> 4; + char patch = osver_min & 0x0F; + osxstring[3] = minor + ((minor<=9) ? '0' : ('a'-1)); + osxstring[4] = patch + ((patch<=9) ? '0' : ('a'-1)); + return osxstring; + } + else if (osid & wxOS_UNIX_LINUX) + return _T("linux"); + else if (osid & wxOS_UNIX_FREEBSD) + return _T("freebsd"); + else if (osid & wxOS_UNIX_OPENBSD) + return _T("openbsd"); + else if (osid & wxOS_UNIX_NETBSD) + return _T("netbsd"); + else if (osid & wxOS_UNIX_SOLARIS) + return _T("solaris"); + else if (osid & wxOS_UNIX_AIX) + return _T("aix"); + else if (osid & wxOS_UNIX_HPUX) + return _T("hpux"); + else if (osid & wxOS_UNIX) + return _T("unix"); + else if (osid & wxOS_OS2) + return _T("os2"); + else if (osid & wxOS_DOS) + return _T("dos"); + else + return _T("unknown"); +} + + +#ifdef WIN32 +typedef BOOL (WINAPI * PGetUserPreferredUILanguages)(DWORD dwFlags, PULONG pulNumLanguages, wchar_t *pwszLanguagesBuffer, PULONG pcchLanguagesBuffer); +static wxString GetSystemLanguage() +{ + wxString res; + + // Try using Win 6+ functions if available + HMODULE kernel32 = LoadLibraryW(L"kernel32.dll"); + PGetUserPreferredUILanguages gupuil = (PGetUserPreferredUILanguages)GetProcAddress(kernel32, "GetUserPreferredUILanguages"); + if (gupuil) + { + ULONG numlang = 0, output_len = 0; + if (gupuil(MUI_LANGUAGE_NAME, &numlang, 0, &output_len) != TRUE) + goto getsyslang_fallback; + wchar_t *output = new wchar_t[output_len]; + if (gupuil(MUI_LANGUAGE_NAME, &numlang, output, &output_len) && numlang >= 1) + { + // We got at least one language, just treat it as the only, and a null-terminated string + res = wxString(output); + delete[] output; + } + else + { + delete[] output; + goto getsyslang_fallback; + } + } + else + { +getsyslang_fallback: + // On an old version of Windows, let's just return the LANGID as a string + LANGID langid = GetUserDefaultUILanguage(); + res = wxString::Format(_T("x-win%04x"), langid); + + } + FreeModule(kernel32); + + return res; +} +#else +static wxString GetSystemLanguage() +{ + return wxLocale::GetLanguageInfo(wxLocale::GetSystemLanguage())->CanonicalName; +} +#endif + + +void AegisubVersionCheckerThread::DoCheck() +{ + const wxString servername = _T("updates.aegisub.org"); + const wxString base_updates_path = _T("/trunk"); + + wxString querystring = wxString::Format( + _T("?rev=%d&rel=%d&os=%s&lang=%s"), + GetSVNRevision(), + GetIsOfficialRelease()?1:0, + GetOSShortName(), + GetSystemLanguage().c_str()); + + wxString path = base_updates_path + querystring; + + wxHTTP http; + http.SetHeader(_T("Connection"), _T("Close")); + http.SetFlags(wxSOCKET_WAITALL|wxSOCKET_BLOCK); + + if (!http.Connect(servername)) + throw VersionCheckError(_("Could not connect to updates server.")); + + std::auto_ptr stream(http.GetInputStream(path)); + + if (http.GetResponse() < 200 || http.GetResponse() >= 300) + throw VersionCheckError(wxString::Format(_("HTTP request failed, got HTTP response %d."), http.GetResponse())); + + wxTextInputStream text(*stream); + + AegisubVersionCheckResultEvent result_event; + + while (!stream->Eof() && stream->GetSize() > 0) + { + wxString line = text.ReadLine(); + wxStringTokenizer tkn(line, _T("|"), wxTOKEN_RET_EMPTY_ALL); + wxArrayString parsed; + while (tkn.HasMoreTokens()) { + parsed.Add(tkn.GetNextToken()); + } + if (parsed.Count() != 6) continue; + + wxString line_type = parsed[0]; + wxString line_revision = parsed[1]; + wxString line_platform = parsed[2]; + wxString line_url = inline_string_decode(parsed[3]); + wxString line_friendlyname = inline_string_decode(parsed[4]); + wxString line_description = inline_string_decode(parsed[5]); + + if ((line_type == _T("branch") || line_type == _T("dev")) && GetIsOfficialRelease()) + { + // stable runners don't want unstable, not interesting, skip + continue; + } + + // check if the OS is right + wxOperatingSystemId osid = wxGetOsVersion(); + if (line_platform == _T("windows") && !(osid & wxOS_WINDOWS_NT)) + { + continue; + } + if (line_platform == _T("mac") && !(osid & wxOS_MAC_OSX_DARWIN)) + { + continue; + } + if (line_platform == _T("source") && (osid & wxOS_WINDOWS_NT || osid & wxOS_MAC_OSX_DARWIN)) + { + // TODO: support interested-in-source-releases flag + continue; + } + if (!(line_platform == _T("windows") || line_platform == _T("mac") || line_platform == _T("source") || line_platform == _T("all"))) + { + continue; + } + + if (line_type == _T("upgrade") || line_type == _T("bugfix")) + { + // de facto interesting + } + else + { + // maybe interesting, check revision + + long new_revision = 0; + if (!line_revision.ToLong(&new_revision)) continue; + if (new_revision <= GetSVNRevision()) + { + // too old, not interesting, skip + continue; + } + } + + // it's interesting! + result_event.AddUpdate(line_url, line_friendlyname, line_description); + } + + if (result_event.GetUpdates().size() == 1) + { + result_event.SetMainText(_("An update to Aegisub was found.")); + } + else if (result_event.GetUpdates().size() > 1) + { + result_event.SetMainText(_("Several possible updates to Aegisub were found.")); + } + else + { + result_event.SetMainText(_("There are no updates to Aegisub.")); + } + + if (result_event.GetUpdates().size() > 0 || interactive) + { + wxTheApp->AddPendingEvent(result_event); + } +} + + + +class VersionCheckerResultDialog : public wxDialog { + void OnCloseButton(wxCommandEvent &evt); + void OnRemindMeLater(wxCommandEvent &evt); + void OnClose(wxCloseEvent &evt); + + wxCheckBox *automatic_check_checkbox; + +public: + VersionCheckerResultDialog(const wxString &main_text, const std::vector &updates); + + bool ShouldPreventAppExit() const { return false; } + + DECLARE_EVENT_TABLE() +}; + +BEGIN_EVENT_TABLE(VersionCheckerResultDialog, wxDialog) + EVT_BUTTON(wxID_OK, VersionCheckerResultDialog::OnCloseButton) + EVT_BUTTON(wxID_NO, VersionCheckerResultDialog::OnRemindMeLater) + EVT_CLOSE(VersionCheckerResultDialog::OnClose) +END_EVENT_TABLE() + + +VersionCheckerResultDialog::VersionCheckerResultDialog(const wxString &main_text, const std::vector &updates) +: wxDialog(0, -1, _("Version Checker")) +{ + const int controls_width = 350; + + wxSizer *main_sizer = new wxBoxSizer(wxVERTICAL); + + wxStaticText *text = new wxStaticText(this, -1, main_text); + text->Wrap(controls_width); + main_sizer->Add(text, 0, wxBOTTOM|wxEXPAND, 6); + + std::vector::const_iterator upd_iterator = updates.begin(); + for (; upd_iterator != updates.end(); ++upd_iterator) + { + main_sizer->Add(new wxStaticLine(this), 0, wxEXPAND|wxALL, 6); + + text = new wxStaticText(this, -1, upd_iterator->friendly_name); + wxFont boldfont = text->GetFont(); + boldfont.SetWeight(wxFONTWEIGHT_BOLD); + text->SetFont(boldfont); + main_sizer->Add(text, 0, wxEXPAND|wxBOTTOM, 6); + + wxTextCtrl *descbox = new wxTextCtrl(this, -1, upd_iterator->description, wxDefaultPosition, wxSize(controls_width,60), wxTE_MULTILINE|wxTE_READONLY); + main_sizer->Add(descbox, 0, wxEXPAND|wxBOTTOM, 6); + + main_sizer->Add(new wxHyperlinkCtrl(this, -1, upd_iterator->url, upd_iterator->url), 0, wxALIGN_LEFT|wxBOTTOM, 6); + } + + automatic_check_checkbox = new wxCheckBox(this, -1, _("Auto Check for Updates")); + automatic_check_checkbox->SetValue(Options.AsBool(_T("Auto check for updates"))); + + wxButton *remind_later_button = 0; + if (updates.size() > 0) + remind_later_button = new wxButton(this, wxID_NO, _("Remind me again in a &week")); + + wxButton *close_button = new wxButton(this, wxID_OK, _("&Close")); + SetAffirmativeId(wxID_OK); + SetEscapeId(wxID_OK); + + main_sizer->Add(new wxStaticLine(this), 0, wxEXPAND|wxALL, 6); + main_sizer->Add(automatic_check_checkbox, 0, wxEXPAND|wxBOTTOM, 6); + + wxStdDialogButtonSizer *button_sizer = new wxStdDialogButtonSizer(); + button_sizer->AddButton(close_button); + if (remind_later_button) + button_sizer->AddButton(remind_later_button); + button_sizer->Realize(); + main_sizer->Add(button_sizer, 0, wxEXPAND, 0); + + wxSizer *outer_sizer = new wxBoxSizer(wxVERTICAL); + outer_sizer->Add(main_sizer, 0, wxALL|wxEXPAND, 12); + + SetSizerAndFit(outer_sizer); + Centre(); +} + + +void VersionCheckerResultDialog::OnCloseButton(wxCommandEvent &evt) +{ + Close(); +} + + +void VersionCheckerResultDialog::OnRemindMeLater(wxCommandEvent &evt) +{ + // In one week + time_t new_next_check_time = wxDateTime::Today().GetTicks() + 7*24*60*60; + Options.SetInt(_T("Updates Next Check Time"), (int)new_next_check_time); + + Close(); +} + + +void VersionCheckerResultDialog::OnClose(wxCloseEvent &evt) +{ + Options.SetBool(_T("Auto check for updates"), automatic_check_checkbox->GetValue()); + Destroy(); +} + + + +void AegisubVersionCheckEventHandler::OnUpdateResult(AegisubVersionCheckResultEvent &evt) +{ + VersionCheckerResultDialog *dlg = new VersionCheckerResultDialog(evt.GetMainText(), evt.GetUpdates()); + dlg->Show(); +} + +void AegisubVersionCheckEventHandler::EnsureHandlerIsRegistered() +{ + static bool is_registered = false; + static AegisubVersionCheckEventHandler evt_handler_object; + + if (is_registered) return; + + wxTheApp->Connect( + -1, -1, + AEGISUB_EVENT_VERSIONCHECK_RESULT, + (wxObjectEventFunction)&AegisubVersionCheckEventHandler::OnUpdateResult, + 0, + &evt_handler_object); + + is_registered = true; +} + diff --git a/aegisub/src/dialog_version_check.h b/aegisub/src/dialog_version_check.h index 6932f4230..537c8cb0d 100644 --- a/aegisub/src/dialog_version_check.h +++ b/aegisub/src/dialog_version_check.h @@ -35,87 +35,21 @@ /// - - -/////////// -// Headers #ifndef AGI_PRE -#include -#include -#include +#include #endif -////////////// -// Prototypes -class DialogVersionCheck; +/// @brief Check whether a newer version is available and report to the user if there is +/// @param interactive If true, always check and report all results, both success and failure. +/// If false, only check if auto-checking is enabled, and only report if a +/// new version actually exists. +void PerformVersionCheck(bool interactive); - -/// DOCME -/// @class VersionCheckThread -/// @brief DOCME +/// @brief Mutex that is taken while version checking is being performed. /// -/// DOCME -class VersionCheckThread : public wxThread { -private: - - /// DOCME - DialogVersionCheck *parent; - -public: - - /// DOCME - bool alive; - - VersionCheckThread(DialogVersionCheck *parent); - wxThread::ExitCode Entry(); -}; - - - -/// DOCME -/// @class DialogVersionCheck -/// @brief DOCME -/// -/// DOCME -class DialogVersionCheck : public wxDialog { - friend class VersionCheckThread; - -private: - - /// DOCME - static bool dialogRunning; - - - /// DOCME - wxTextCtrl *logBox; - - /// DOCME - VersionCheckThread *thread; - - /// DOCME - bool visible; - - void CheckVersion(); - void OnClose(wxCloseEvent &event); - void OnOK(wxCommandEvent &event); - void OnURL(wxTextUrlEvent &event); - -public: - DialogVersionCheck(wxWindow *parent,bool hidden); - ~DialogVersionCheck(); - - DECLARE_EVENT_TABLE() -}; - - -/////// -// IDs -enum { - - /// DOCME - Log_Box = 1000 -}; - - +/// A new version check can't be performed while this mutex is locked, checking whether +/// it is locked is a way to disable UI to invoke a version check while one is being +/// performed. +extern wxMutex VersionCheckLock; diff --git a/aegisub/src/frame_main.cpp b/aegisub/src/frame_main.cpp index c67484f57..198b22b46 100644 --- a/aegisub/src/frame_main.cpp +++ b/aegisub/src/frame_main.cpp @@ -213,22 +213,16 @@ FrameMain::FrameMain (wxArrayString args) LoadList(args); // Version checker - // Fails on non-Windows platforms with a crash -#ifdef __WXMSW__ StartupLog(_T("Possibly perform automatic updates check")); int option = Options.AsInt(_T("Auto check for updates")); if (option == -1) { int result = wxMessageBox(_("Do you want Aegisub to check for updates whenever it starts? You can still do it manually via the Help menu."),_("Check for updates?"),wxYES_NO); - option = 0; - if (result == wxYES) option = 1; + option = (result == wxYES); Options.SetInt(_T("Auto check for updates"),option); Options.Save(); } - if (option == 1) { - DialogVersionCheck *checker = new DialogVersionCheck (this,true); - (void)checker; - } -#endif + + PerformVersionCheck(false); //ShowFullScreen(true,wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION); StartupLog(_T("Leaving FrameMain constructor")); @@ -561,9 +555,7 @@ void FrameMain::InitMenu() { #ifndef __WXMAC__ helpMenu->AppendSeparator(); #endif -#ifdef __WXMSW__ AppendBitmapMenuItem(helpMenu,Menu_Help_Check_Updates, _("&Check for Updates..."), _("Check to see if there is a new version of Aegisub available"),GETIMAGE(blank_button_16)); -#endif AppendBitmapMenuItem(helpMenu,Menu_Help_About, _("&About..."), _("About Aegisub"),GETIMAGE(about_menu_16)); MenuBar->Append(helpMenu, _("&Help")); diff --git a/aegisub/src/frame_main_events.cpp b/aegisub/src/frame_main_events.cpp index 5147b1d63..a5818e0c9 100644 --- a/aegisub/src/frame_main_events.cpp +++ b/aegisub/src/frame_main_events.cpp @@ -601,12 +601,11 @@ void FrameMain::OnAbout(wxCommandEvent &event) { -/// @brief Open check updates +/// @brief Open check updates /// @param event /// void FrameMain::OnCheckUpdates(wxCommandEvent &event) { - DialogVersionCheck *check = new DialogVersionCheck(this,false); - (void)check; + PerformVersionCheck(true); } diff --git a/aegisub/src/options.cpp b/aegisub/src/options.cpp index a0cc882a9..f13e6e51f 100644 --- a/aegisub/src/options.cpp +++ b/aegisub/src/options.cpp @@ -419,6 +419,8 @@ void OptionsManager::LoadDefaults(bool onlyDefaults,bool doOverride) { previewText += 0x8a9e; // kanji "speak" SetText(_T("Style editor preview text"),previewText); SetColour(_T("Style editor preview background"),wxColour(125,153,176)); + + SetInt(_T("Updates Next Check Time"), 0); } lastVersion = -1;