| 1 |
< |
///////////////////////////////////////////////////////////////////////////// |
| 2 |
< |
// Name: aeinstallerapp.cpp |
| 3 |
< |
// Purpose: |
| 4 |
< |
// Author: |
| 5 |
< |
// Modified by: |
| 6 |
< |
// Created: 07/05/2009 17:23:39 |
| 7 |
< |
// RCS-ID: |
| 8 |
< |
// Copyright: |
| 9 |
< |
// Licence: |
| 10 |
< |
///////////////////////////////////////////////////////////////////////////// |
| 1 |
> |
/***************************************************************************\ |
| 2 |
> |
| Project: AE Installer | |
| 3 |
> |
| By: Gumby & Iritscen | |
| 4 |
> |
| File: AEInstallerApp.cpp | |
| 5 |
> |
| Function: Sets up the main application window. | |
| 6 |
> |
| Created: 07/05/2009 17:23:39 | |
| 7 |
> |
\***************************************************************************/ |
| 8 |
> |
|
| 9 |
> |
#include "boost/filesystem.hpp" |
| 10 |
> |
#include "boost/lexical_cast.hpp" // int -> string |
| 11 |
|
#include "boost/thread.hpp" |
| 12 |
< |
#include <boost/thread/mutex.hpp> |
| 12 |
> |
#include "boost/thread/mutex.hpp" |
| 13 |
|
#include <fstream> |
| 14 |
< |
#include "boost/filesystem.hpp" // includes all needed Boost.Filesystem declarations |
| 15 |
< |
#include "boost/lexical_cast.hpp" //int -> string |
| 16 |
< |
using namespace boost::filesystem; |
| 17 |
< |
// For compilers that support precompilation, includes "wx/wx.h". |
| 18 |
< |
#include "wx/wxprec.h" |
| 19 |
< |
|
| 20 |
< |
#ifdef __BORLANDC__ |
| 21 |
< |
#pragma hdrstop |
| 22 |
< |
#endif |
| 23 |
< |
|
| 24 |
< |
#ifndef WX_PRECOMP |
| 25 |
< |
#include "wx/wx.h" |
| 26 |
< |
#endif |
| 14 |
> |
#include <string> |
| 15 |
> |
#include "installer.h" |
| 16 |
> |
#include "aeinstallerapp.h" |
| 17 |
|
|
| 18 |
|
////@begin includes |
| 19 |
|
////@end includes |
| 20 |
|
|
| 21 |
< |
#include "aeinstallerapp.h" |
| 22 |
< |
#include <string> |
| 21 |
> |
Install_info_cfg currentAE, updateAE; |
| 22 |
> |
MainWindow* TheWindow; |
| 23 |
|
|
| 24 |
|
////@begin XPM images |
| 25 |
|
////@end XPM images |
| 77 |
|
* Initialisation for AEInstallerApp |
| 78 |
|
*/ |
| 79 |
|
|
| 80 |
+ |
/* The OnInit() routine is used to check whether the Installer has the software *\ |
| 81 |
+ |
| it needs to install mods, whether there is an available update, and whether | |
| 82 |
+ |
\* the user has globalized yet, to allow mods to be installed. */ |
| 83 |
|
bool AEInstallerApp::OnInit() |
| 84 |
|
{ |
| 85 |
|
////@begin AEInstallerApp initialisation |
| 86 |
|
// Remove the comment markers above and below this block |
| 87 |
|
// to make permanent changes to the code. |
| 95 |
– |
|
| 88 |
|
#if wxUSE_XPM |
| 89 |
|
wxImage::AddHandler(new wxXPMHandler); |
| 90 |
|
#endif |
| 102 |
|
////@end AEInstallerApp initialisation |
| 103 |
|
TheWindow = mainWindow; |
| 104 |
|
|
| 105 |
+ |
// Anything after this is done after the window appears... |
| 106 |
+ |
|
| 107 |
+ |
if (!CheckForRequiredSoftware()) |
| 108 |
+ |
{ |
| 109 |
+ |
TheWindow->Close(); // CheckForRequiredSoftware() will have notified the user of what they are missing, so we just quit now |
| 110 |
+ |
return true; |
| 111 |
+ |
} |
| 112 |
+ |
|
| 113 |
+ |
bool installerJustUpdated = false; |
| 114 |
+ |
int updateStatus = GetUpdateStatus(¤tAE, &updateAE, &installerJustUpdated); |
| 115 |
+ |
if (updateStatus) // otherwise there's no update |
| 116 |
+ |
{ |
| 117 |
+ |
string updateMsg = "An update for the Anniversary Edition is available.\n"; // for some reason we can't set the initial value while using the '+' operator... |
| 118 |
+ |
updateMsg = updateMsg + "Do you wish to update to Edition version " + updateAE.AEVersion + "?\n" + |
| 119 |
+ |
"(Current version is " + currentAE.AEVersion + ")\n"; // ...so tack the rest on in a second command |
| 120 |
+ |
wxMessageDialog* updateNotification; |
| 121 |
+ |
|
| 122 |
+ |
switch (updateStatus) // for the meanings of these return values, see the comments preceding installer.cpp's GetUpdateStatus() |
| 123 |
+ |
{ |
| 124 |
+ |
case UPDATE_LOG_READ_ERR: |
| 125 |
+ |
{ |
| 126 |
+ |
if (exists("Update.log")) remove("Update.log"); |
| 127 |
+ |
ofstream logfile("Update.log"); |
| 128 |
+ |
logfile << "Error: A necessary .cfg file could not be read."; |
| 129 |
+ |
} // brackets are needed due to the initialization of the ofstream; silly C! |
| 130 |
+ |
break; |
| 131 |
+ |
case UPDATE_MNTH_REQD_ERR: |
| 132 |
+ |
updateMsg = "There is a patch in the updates/ folder, but it patches the\n"; |
| 133 |
+ |
updateMsg = updateMsg + updateAE.AEVersion.substr(0, updateAE.AEVersion.length() - 1) + " release; it cannot update this version of the Edition."; |
| 134 |
+ |
updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxOK | wxICON_EXCLAMATION, wxDefaultPosition); |
| 135 |
+ |
updateNotification->ShowModal(); |
| 136 |
+ |
break; |
| 137 |
+ |
case UPDATE_SIMP_AVAIL: // there's an update with no globalization or Installer strings attached |
| 138 |
+ |
updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition); |
| 139 |
+ |
if (updateNotification->ShowModal() == wxID_YES) |
| 140 |
+ |
ProcessAEUpdate(¤tAE, &updateAE, &installerJustUpdated); |
| 141 |
+ |
break; |
| 142 |
+ |
case UPDATE_GLOB_AVAIL: // there's an update with globalization strings attached |
| 143 |
+ |
updateMsg = updateMsg + "**Note that the update requires you to reglobalize, which will take 5-20 minutes.**\n" + |
| 144 |
+ |
"Before clicking Yes, MAKE SURE you have backed up any mods not installed through\n " + |
| 145 |
+ |
"the Installer, such as plug-ins or direct OniSplit imports."; |
| 146 |
+ |
updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition); |
| 147 |
+ |
if (updateNotification->ShowModal() == wxID_YES) |
| 148 |
+ |
ProcessAEUpdate(¤tAE, &updateAE, &installerJustUpdated); |
| 149 |
+ |
break; |
| 150 |
+ |
case UPDATE_INST_AVAIL: // there's an update with Installer strings attached (globalization is irrelevant while the Installer is not yet updated) |
| 151 |
+ |
updateMsg = updateMsg + "**Note that the update requires the Installer to update itself.**\n" + |
| 152 |
+ |
"If you click Yes, the Installer will quit and re-launch itself, then\n" + |
| 153 |
+ |
"you will be prompted to begin the installation."; |
| 154 |
+ |
updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition); |
| 155 |
+ |
updateNotification->ShowModal(); |
| 156 |
+ |
if (updateNotification->ShowModal() == wxID_YES) |
| 157 |
+ |
{ |
| 158 |
+ |
if (ProcessInstallerUpdate(¤tAE, &updateAE)) // there's an intentional logic gap here: if the user clicks "Yes"... |
| 159 |
+ |
{ // ...and then ProcessInstallerUpdate has an error and returns false, the logic gap results... |
| 160 |
+ |
TheWindow->Close(); // ...in the code continuing to execute down through case UPDATE_INST_REPL_ERR |
| 161 |
+ |
return true; |
| 162 |
+ |
} |
| 163 |
+ |
} |
| 164 |
+ |
else |
| 165 |
+ |
break; |
| 166 |
+ |
case UPDATE_INST_REPL_ERR: // the Installer replacement failed, user has to do it :-( |
| 167 |
+ |
updateMsg = "The Installer replacement process failed for some reason.\n"; |
| 168 |
+ |
updateMsg = updateMsg + "Please quit, go into the folder Edition/Updates/" + strEUFN + "/install/ and drag the Installer to Edition/install/, " + |
| 169 |
+ |
"replacing the current Installer application, then launch the new version."; |
| 170 |
+ |
updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxOK | wxICON_EXCLAMATION, wxDefaultPosition); |
| 171 |
+ |
updateNotification->ShowModal(); |
| 172 |
+ |
TheWindow->Close(); |
| 173 |
+ |
return true; |
| 174 |
+ |
} |
| 175 |
+ |
} |
| 176 |
+ |
|
| 177 |
+ |
CheckForGlobalization(false); // function will prompt user and initiate globalization if not done already |
| 178 |
+ |
|
| 179 |
+ |
return true; |
| 180 |
+ |
} |
| 181 |
+ |
|
| 182 |
+ |
bool CheckForRequiredSoftware(void) |
| 183 |
+ |
{ |
| 184 |
|
#ifdef WIN32 |
| 185 |
< |
HKEY hKey; |
| 186 |
< |
if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\.NETFramework\\policy\\v2.0", 0L, KEY_READ , &hKey) == ERROR_SUCCESS) { |
| 187 |
< |
wxMessageDialog* MonoDialogOfDeath = new wxMessageDialog(TheWindow, "You don't have .NET 2.0 installed! .NET is a framework required by the Edition. You can download it from:\nhttp://gumby.oni2.net/dotnet\nPlease install .NET 2.0, then open this Installer again. \n\nWould you like to open the download webpage?", "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION , wxDefaultPosition); |
| 188 |
< |
if(MonoDialogOfDeath->ShowModal() == wxID_YES) { |
| 185 |
> |
// test for .NET 2.0 or higher |
| 186 |
> |
HKEY hKey; |
| 187 |
> |
if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\.NETFramework\\policy\\v2.0", 0L, KEY_READ , &hKey) == ERROR_SUCCESS) |
| 188 |
> |
{ |
| 189 |
> |
string dotnetMsg = "You don't have .NET 2.0 installed! .NET is a framework required by the Edition.\n"; |
| 190 |
> |
dotnetMsg = dotnetMsg + "You can download it from:\n" + |
| 191 |
> |
"http://gumby.oni2.net/dotnet\n" + |
| 192 |
> |
"Please install .NET 2.0, then open this Installer again.\n\n" + |
| 193 |
> |
"Would you like to open the download webpage?"; |
| 194 |
> |
wxMessageDialog* DotNetDialogOfDeath = new wxMessageDialog(TheWindow, dotnetMsg.c_str(), "AE Installer Alert", |
| 195 |
> |
wxYES_NO | wxICON_EXCLAMATION , wxDefaultPosition); |
| 196 |
> |
if (DotNetDialogOfDeath->ShowModal() == wxID_YES) |
| 197 |
|
system("start http://www.microsoft.com/downloads/details.aspx?familyid=0856eacb-4362-4b0d-8edd-aab15c5e04f5"); |
| 119 |
– |
} |
| 198 |
|
RegCloseKey(hKey); |
| 199 |
< |
TheWindow->Close(); |
| 122 |
< |
} |
| 123 |
< |
#else |
| 124 |
< |
// test for the third-party mono framework, because without it, on Mac, we are up a creek |
| 125 |
< |
char monoCommand[300] = "which mono >> "; |
| 126 |
< |
strcat(monoCommand, escapePath(system_complete("mono_check.log").string()).c_str()); |
| 127 |
< |
system(monoCommand); |
| 128 |
< |
fstream file; |
| 129 |
< |
file.open("mono_check.log"); |
| 130 |
< |
string line; |
| 131 |
< |
int line_count = 0; |
| 132 |
< |
while (!file.eof()) |
| 133 |
< |
{ |
| 134 |
< |
line_count++; |
| 135 |
< |
getline(file, line); |
| 199 |
> |
return false; |
| 200 |
|
} |
| 201 |
< |
file.close(); |
| 202 |
< |
remove("mono_check.log"); |
| 201 |
> |
#else // on Mac... |
| 202 |
> |
// test for the third-party "mono" framework, because without it, we are up a creek |
| 203 |
> |
FILE *fWhichMono = NULL; |
| 204 |
> |
char chrWhichMono[32]; |
| 205 |
> |
fWhichMono = popen("which mono", "r"); |
| 206 |
> |
fgets(chrWhichMono, sizeof(chrWhichMono), fWhichMono); |
| 207 |
> |
pclose(fWhichMono); |
| 208 |
> |
string strWhichMono = (string)chrWhichMono; |
| 209 |
> |
string::size_type loc = strWhichMono.find("mono", 0); |
| 210 |
|
|
| 211 |
< |
if (line_count <= 1) // this means that "which mono" returned nothing -- abort! abort! abort! |
| 211 |
> |
if (loc == string::npos) // this means that "which mono" did not return a path leading to the mono binary -- abort! abort! abort! |
| 212 |
|
{ |
| 213 |
< |
wxMessageDialog* MonoDialogOfDeath = new wxMessageDialog(TheWindow, "You don't have 'mono' installed! 'mono' is a command-line tool required by the Edition. You can download it from:\nhttp://www.go-mono.com/mono-downloads/download.html (OS X 10.4+) or\nhttp://edt.oni2.net/AE/MonoFramework10.3.dmg (OS X 10.3)\n\nPlease install 'mono', then open this Installer again.", "AE Installer Alert", wxOK | wxICON_EXCLAMATION , wxDefaultPosition); |
| 213 |
> |
string monoMsg = "You don't have 'mono' installed! 'mono' is a command-line tool required by the Edition.\n"; |
| 214 |
> |
monoMsg = monoMsg + "You can download it from: http://www.go-mono.com/mono-downloads/download.html (OS X 10.4+)\n" + |
| 215 |
> |
"or http://edt.oni2.net/AE/MonoFramework10.3.dmg (OS X 10.3)\n\n" + |
| 216 |
> |
"Please install 'mono', then open this Installer again."; |
| 217 |
> |
wxMessageDialog* MonoDialogOfDeath = new wxMessageDialog(TheWindow, monoMsg.c_str(), "AE Installer Alert", wxOK | wxICON_EXCLAMATION, wxDefaultPosition); |
| 218 |
|
MonoDialogOfDeath->ShowModal(); |
| 219 |
< |
TheWindow->Close(); |
| 145 |
< |
return true; // it's quittin' time, Joe |
| 219 |
> |
return false; // it's quittin' time, Joe |
| 220 |
|
} |
| 221 |
|
#endif |
| 222 |
+ |
return true; |
| 223 |
+ |
} |
| 224 |
|
|
| 225 |
< |
//anything after this is done after the window appears... |
| 226 |
< |
|
| 227 |
< |
if ( !exists("../GameDataFolder") ) |
| 225 |
> |
bool CheckForGlobalization(bool justDoIt) |
| 226 |
> |
{ |
| 227 |
> |
if (!exists("../GameDataFolder")) |
| 228 |
|
{ |
| 229 |
< |
wxMessageDialog* YesNoDialog = new wxMessageDialog(TheWindow, "You haven't globalized yet! \nYou must globalize to use the Anniversary Edition framework. \nWould you like to globalize now? (This could take a while...)\n(Selecting \"No\" will exit this program...)", "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION , wxDefaultPosition); |
| 230 |
< |
|
| 229 |
> |
string globMsg = "You haven't globalized yet!\n"; |
| 230 |
> |
globMsg = globMsg + "You must globalize to use the Anniversary Edition framework.\n" + |
| 231 |
> |
"Would you like to globalize now? (This could take a while...)\n" + |
| 232 |
> |
"(Selecting \"No\" will exit this program...)"; |
| 233 |
> |
wxMessageDialog* YesNoDialog = new wxMessageDialog(TheWindow, globMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition); |
| 234 |
> |
|
| 235 |
|
if (YesNoDialog->ShowModal() == wxID_NO) // if the user said no... |
| 156 |
– |
TheWindow->Close(); |
| 157 |
– |
else |
| 236 |
|
{ |
| 237 |
< |
|
| 238 |
< |
|
| 161 |
< |
#ifdef WIN32 |
| 162 |
< |
boost::thread thrd3(globalize2); |
| 163 |
< |
//globalizeData(); |
| 164 |
< |
//boost::thread::create_thread(&globalizeData); |
| 165 |
< |
// boost::thread_group Tg; |
| 166 |
< |
// Tg.create_thread( &globalizeData(), this ); |
| 167 |
< |
#else |
| 168 |
< |
TheWindow->InstallButton->Disable(); |
| 169 |
< |
TheWindow->ReglobalizeButton->Disable(); |
| 170 |
< |
globalizeData(); |
| 171 |
< |
TheWindow->InstallButton->Enable(); |
| 172 |
< |
TheWindow->ReglobalizeButton->Enable(); |
| 173 |
< |
#endif |
| 174 |
< |
|
| 175 |
< |
|
| 237 |
> |
TheWindow->Close(); |
| 238 |
> |
return true; |
| 239 |
|
} |
| 240 |
|
} |
| 241 |
< |
|
| 241 |
> |
else if (!justDoIt) |
| 242 |
> |
return false; |
| 243 |
> |
// Code below this point runs if user clicks "Yes" or if they are never asked but justDoIt is true |
| 244 |
> |
#ifdef WIN32 |
| 245 |
> |
boost::thread thrd3(globalize2); |
| 246 |
> |
#else // cannot use multi-threading in Mac build |
| 247 |
> |
TheWindow->InstallButton->Disable(); |
| 248 |
> |
TheWindow->ReglobalizeButton->Disable(); |
| 249 |
> |
globalizeData(); |
| 250 |
> |
TheWindow->InstallButton->Enable(); |
| 251 |
> |
TheWindow->ReglobalizeButton->Enable(); |
| 252 |
> |
#endif |
| 253 |
> |
|
| 254 |
|
return true; |
| 255 |
|
} |
| 256 |
|
|
| 257 |
< |
|
| 258 |
< |
void setStatusArea( string s ) { |
| 257 |
> |
void setStatusArea(string s) |
| 258 |
> |
{ |
| 259 |
|
wxString wxs(s.c_str(), wxConvUTF8); |
| 260 |
|
|
| 261 |
< |
TheWindow->StatusArea->SetStatusText( wxs ); |
| 187 |
< |
//TheWindow->StatusArea->SetStatusText(s.c_str()); |
| 188 |
< |
//StatusArea->SetStatusText(_(s.c_str())); |
| 189 |
< |
//(*TheStatusBar)->SetStatusText(_(s.c_str())); |
| 190 |
< |
//AEInstallerApp:: |
| 191 |
< |
// TheWindow->StatusArea->SetStatusText("hi"); |
| 192 |
< |
//mainWindow |
| 193 |
< |
//itemFrame1->StatusArea->SetStatusText(_"lol"); |
| 194 |
< |
//MainWindow.StatusArea->SetStatusText("hi"); |
| 195 |
< |
// class AbstractStatusNotifier { public: virtual void NotifyStatus(const wxString &statusString) = 0; }; |
| 196 |
< |
//class StatusBarStatusNotifier : public AbstractStatusNotifier { wxStatusBar *statusbar; StatusBarStatusNotifier(wxStatusBar *bar) : statusbar(bar) { } ; |
| 197 |
< |
//void NotifyStatus(const wxString &status) { statusbar->SetStatus(status); } } |
| 198 |
< |
|
| 199 |
< |
|
| 200 |
< |
//MainWindow::StatusArea-> |
| 201 |
< |
//MainWindow::MainWindow().SetSize(MainWindow::MainWindow().GetRect().GetWidth(), MainWindow::MainWindow().GetRect().GetHeight()+1); |
| 202 |
< |
|
| 203 |
< |
//MainWindow::StatusBar->SetLabel("Importing Files..."); |
| 204 |
< |
//StatusBar->SetLabel(s); |
| 205 |
< |
//->SetLabel(s); |
| 206 |
< |
|
| 261 |
> |
TheWindow->StatusArea->SetStatusText(wxs); |
| 262 |
|
} |
| 263 |
|
|
| 264 |
|
|
| 272 |
|
return wxApp::OnExit(); |
| 273 |
|
////@end AEInstallerApp cleanup |
| 274 |
|
} |
| 275 |
< |
void doglobalizeData() { |
| 276 |
< |
//TheWindow->Disable(); |
| 275 |
> |
void doglobalizeData() |
| 276 |
> |
{ |
| 277 |
|
globalizeData(); |
| 278 |
|
#ifdef WIN32 |
| 279 |
|
while(1) Sleep(-1); |
| 280 |
|
#endif |
| 226 |
– |
//TheWindow->Enable(); |
| 227 |
– |
//setStatusArea((string)"Test1"); |
| 281 |
|
} |