| 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" | 
 
 
 
 
 | 13 | #include <fstream> | 
 
 
 
 
 | 14 | #include <string> | 
 
 
 
 
 | 15 | #include "installer.h" | 
 
 
 
 
 | 16 | #include "aeinstallerapp.h" | 
 
 
 
 
 | 17 |  | 
 
 
 
 
 | 18 | ////@begin includes | 
 
 
 
 
 | 19 | ////@end includes | 
 
 
 
 
 | 20 |  | 
 
 
 
 
 | 21 | extern int updateStatus; | 
 
 
 
 
 | 22 | extern bool installerJustUpdated; | 
 
 
 
 
 | 23 | Install_info_cfg currentAE, updateAE; | 
 
 
 
 
 | 24 | MainWindow* TheWindow; | 
 
 
 
 
 | 25 |  | 
 
 
 
 
 | 26 | ////@begin XPM images | 
 
 
 
 
 | 27 | ////@end XPM images | 
 
 
 
 
 | 28 |  | 
 
 
 
 
 | 29 |  | 
 
 
 
 
 | 30 | /* | 
 
 
 
 
 | 31 | * Application instance implementation | 
 
 
 
 
 | 32 | */ | 
 
 
 
 
 | 33 |  | 
 
 
 
 
 | 34 | ////@begin implement app | 
 
 
 
 
 | 35 | IMPLEMENT_APP( AEInstallerApp ) | 
 
 
 
 
 | 36 | ////@end implement app | 
 
 
 
 
 | 37 |  | 
 
 
 
 
 | 38 |  | 
 
 
 
 
 | 39 | /* | 
 
 
 
 
 | 40 | * AEInstallerApp type definition | 
 
 
 
 
 | 41 | */ | 
 
 
 
 
 | 42 |  | 
 
 
 
 
 | 43 | IMPLEMENT_CLASS( AEInstallerApp, wxApp ) | 
 
 
 
 
 | 44 |  | 
 
 
 
 
 | 45 |  | 
 
 
 
 
 | 46 | /* | 
 
 
 
 
 | 47 | * AEInstallerApp event table definition | 
 
 
 
 
 | 48 | */ | 
 
 
 
 
 | 49 |  | 
 
 
 
 
 | 50 | BEGIN_EVENT_TABLE( AEInstallerApp, wxApp ) | 
 
 
 
 
 | 51 |  | 
 
 
 
 
 | 52 | ////@begin AEInstallerApp event table entries | 
 
 
 
 
 | 53 | ////@end AEInstallerApp event table entries | 
 
 
 
 
 | 54 |  | 
 
 
 
 
 | 55 | END_EVENT_TABLE() | 
 
 
 
 
 | 56 |  | 
 
 
 
 
 | 57 |  | 
 
 
 
 
 | 58 | /* | 
 
 
 
 
 | 59 | * Constructor for AEInstallerApp | 
 
 
 
 
 | 60 | */ | 
 
 
 
 
 | 61 |  | 
 
 
 
 
 | 62 | AEInstallerApp::AEInstallerApp() | 
 
 
 
 
 | 63 | { | 
 
 
 
 
 | 64 | Init(); | 
 
 
 
 
 | 65 | } | 
 
 
 
 
 | 66 |  | 
 
 
 
 
 | 67 |  | 
 
 
 
 
 | 68 | /* | 
 
 
 
 
 | 69 | * Member initialisation | 
 
 
 
 
 | 70 | */ | 
 
 
 
 
 | 71 |  | 
 
 
 
 
 | 72 | void AEInstallerApp::Init() | 
 
 
 
 
 | 73 | { | 
 
 
 
 
 | 74 | ////@begin AEInstallerApp member initialisation | 
 
 
 
 
 | 75 | ////@end AEInstallerApp member initialisation | 
 
 
 
 
 | 76 | } | 
 
 
 
 
 | 77 |  | 
 
 
 
 
 | 78 | /* | 
 
 
 
 
 | 79 | * Initialisation for AEInstallerApp | 
 
 
 
 
 | 80 | */ | 
 
 
 
 
 | 81 |  | 
 
 
 
 
 | 82 | /* The OnInit() routine is used to check whether the Installer has the software *\ | 
 
 
 
 
 | 83 | |  it needs to install mods, whether there is an available update, and whether   | | 
 
 
 
 
 | 84 | \* the user has globalized yet, to allow mods to be installed.                                  */ | 
 
 
 
 
 | 85 | bool AEInstallerApp::OnInit() | 
 
 
 
 
 | 86 | { | 
 
 
 
 
 | 87 | ////@begin AEInstallerApp initialisation | 
 
 
 
 
 | 88 | // Remove the comment markers above and below this block | 
 
 
 
 
 | 89 | // to make permanent changes to the code. | 
 
 
 
 
 | 90 | #if wxUSE_XPM | 
 
 
 
 
 | 91 | wxImage::AddHandler(new wxXPMHandler); | 
 
 
 
 
 | 92 | #endif | 
 
 
 
 
 | 93 | #if wxUSE_LIBPNG | 
 
 
 
 
 | 94 | wxImage::AddHandler(new wxPNGHandler); | 
 
 
 
 
 | 95 | #endif | 
 
 
 
 
 | 96 | #if wxUSE_LIBJPEG | 
 
 
 
 
 | 97 | wxImage::AddHandler(new wxJPEGHandler); | 
 
 
 
 
 | 98 | #endif | 
 
 
 
 
 | 99 | #if wxUSE_GIF | 
 
 
 
 
 | 100 | wxImage::AddHandler(new wxGIFHandler); | 
 
 
 
 
 | 101 | #endif | 
 
 
 
 
 | 102 | MainWindow* mainWindow = new MainWindow( NULL ); | 
 
 
 
 
 | 103 | mainWindow->Show(true); | 
 
 
 
 
 | 104 | ////@end AEInstallerApp initialisation | 
 
 
 
 
 | 105 | TheWindow = mainWindow; | 
 
 
 
 
 | 106 |  | 
 
 
 
 
 | 107 | // Anything after this is done after the window appears... | 
 
 
 
 
 | 108 |  | 
 
 
 
 
 | 109 | if (!CheckForRequiredSoftware()) | 
 
 
 
 
 | 110 | { | 
 
 
 
 
 | 111 | TheWindow->Close(); // CheckForRequiredSoftware() will have notified the user of what they are missing, so we just quit now | 
 
 
 
 
 | 112 | return true; | 
 
 
 
 
 | 113 | } | 
 
 
 
 
 | 114 |  | 
 
 
 
 
 | 115 | if (updateStatus) // updateStatus was set when MainWindow::CreateControls() was called during initialization of the window | 
 
 
 
 
 | 116 | { | 
 
 
 
 
 | 117 | string updateMsg = "An update for the Anniversary Edition is available.\n" | 
 
 
 
 
 | 118 | "Do you wish to update to Edition version " + updateAE.AEVersion + "?\n" | 
 
 
 
 
 | 119 | "(Current version is " + currentAE.AEVersion + ")\n"; // ...so we 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 + " 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_PKG_AVAIL: // there's an update with no globalization or Installer strings attached | 
 
 
 
 
 | 143 | updateMsg = (string)"One or individual package updates for the Anniversary Edition is available.\n\n" + | 
 
 
 
 
 | 144 | (string)"Please note that the AE team assumes no responsibility for the content of third party mods " + | 
 
 
 
 
 | 145 | (string)"nor effects that a third party mod may have on your install.\n\n" + | 
 
 
 
 
 | 146 | (string)"Do you wish to install these update(s)?"; | 
 
 
 
 
 | 147 | updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition); | 
 
 
 
 
 | 148 | if (updateNotification->ShowModal() == wxID_YES) | 
 
 
 
 
 | 149 | ProcessPackageUpdates("../updates", "./packages"); | 
 
 
 
 
 | 150 | break; | 
 
 
 
 
 | 151 | case UPDATE_GLOB_AVAIL: // there's an update with globalization strings attached | 
 
 
 
 
 | 152 | updateMsg = updateMsg + "**Note that the update requires you to reglobalize, which will take 5-20 minutes.**\n" + | 
 
 
 
 
 | 153 | "Before clicking Yes, MAKE SURE you have backed up any mods not installed through\n " + | 
 
 
 
 
 | 154 | "the Installer, such as plug-ins or direct OniSplit imports."; | 
 
 
 
 
 | 155 | updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition); | 
 
 
 
 
 | 156 | if (updateNotification->ShowModal() == wxID_YES) | 
 
 
 
 
 | 157 | ProcessAEUpdate(¤tAE, &updateAE, &installerJustUpdated); | 
 
 
 
 
 | 158 | break; | 
 
 
 
 
 | 159 | case UPDATE_INST_AVAIL: // there's an update with Installer strings attached (globalization is irrelevant while the Installer is not yet updated) | 
 
 
 
 
 | 160 | updateMsg = updateMsg + "**Note that the update requires the Installer to update itself.**\n" + | 
 
 
 
 
 | 161 | "If you click Yes, the Installer will quit and re-launch itself, then\n" + | 
 
 
 
 
 | 162 | "you will be prompted to begin the installation."; | 
 
 
 
 
 | 163 | updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition); | 
 
 
 
 
 | 164 | if (updateNotification->ShowModal() == wxID_YES) | 
 
 
 
 
 | 165 | { | 
 
 
 
 
 | 166 | if (ProcessInstallerUpdate(¤tAE, &updateAE)) // there's an intentional logic gap here: if the user clicks "Yes"... | 
 
 
 
 
 | 167 | {                                                                                                  // ...and then ProcessInstallerUpdate has an error and returns false, the logic gap results... | 
 
 
 
 
 | 168 | TheWindow->Close();                                                        // ...in the code continuing to execute down through case UPDATE_INST_REPL_ERR | 
 
 
 
 
 | 169 | return true; | 
 
 
 
 
 | 170 | } | 
 
 
 
 
 | 171 | } | 
 
 
 
 
 | 172 | else | 
 
 
 
 
 | 173 | break; | 
 
 
 
 
 | 174 | case UPDATE_INST_REPL_ERR: // the Installer replacement failed, user has to do it :-( | 
 
 
 
 
 | 175 | updateMsg = "The Installer replacement process failed for some reason.\n"; | 
 
 
 
 
 | 176 | updateMsg = updateMsg + "In order for the update to continue, go into the folder Edition/updates/" + strEUFN + "/install/ and " + | 
 
 
 
 
 | 177 | "drag the Installer to Edition/install/, replacing the current Installer application, then launch the " + | 
 
 
 
 
 | 178 | "new version. Click Yes to quit."; | 
 
 
 
 
 | 179 | updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition); | 
 
 
 
 
 | 180 | if (updateNotification->ShowModal() == wxID_YES) | 
 
 
 
 
 | 181 | TheWindow->Close(); | 
 
 
 
 
 | 182 | return true; | 
 
 
 
 
 | 183 | } | 
 
 
 
 
 | 184 | } | 
 
 
 
 
 | 185 |  | 
 
 
 
 
 | 186 | CheckForGlobalization(false); // function will prompt user and initiate globalization if not done already | 
 
 
 
 
 | 187 |  | 
 
 
 
 
 | 188 | return true; | 
 
 
 
 
 | 189 | } | 
 
 
 
 
 | 190 |  | 
 
 
 
 
 | 191 | bool CheckForRequiredSoftware(void) | 
 
 
 
 
 | 192 | { | 
 
 
 
 
 | 193 | #ifdef WIN32 | 
 
 
 
 
 | 194 | // test for .NET 2.0 or higher | 
 
 
 
 
 | 195 | HKEY hKey; | 
 
 
 
 
 | 196 | if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\.NETFramework\\policy\\v2.0", 0L, KEY_READ , &hKey) == ERROR_SUCCESS) | 
 
 
 
 
 | 197 | { | 
 
 
 
 
 | 198 | string dotnetMsg = "You don't have .NET 2.0 installed! .NET is a framework required by the Edition.\n"; | 
 
 
 
 
 | 199 | dotnetMsg = dotnetMsg + "You can download it from:\n" + | 
 
 
 
 
 | 200 | "http://gumby.oni2.net/dotnet\n" + | 
 
 
 
 
 | 201 | "Please install .NET 2.0, then open this Installer again.\n\n" + | 
 
 
 
 
 | 202 | "Would you like to open the download webpage?"; | 
 
 
 
 
 | 203 | wxMessageDialog* DotNetDialogOfDeath = new wxMessageDialog(TheWindow, dotnetMsg.c_str(), "AE Installer Alert", | 
 
 
 
 
 | 204 | wxYES_NO | wxICON_EXCLAMATION  , wxDefaultPosition); | 
 
 
 
 
 | 205 | if (DotNetDialogOfDeath->ShowModal() == wxID_YES) | 
 
 
 
 
 | 206 | system("start http://www.microsoft.com/downloads/details.aspx?familyid=0856eacb-4362-4b0d-8edd-aab15c5e04f5"); | 
 
 
 
 
 | 207 | RegCloseKey(hKey); | 
 
 
 
 
 | 208 | return false; | 
 
 
 
 
 | 209 | } | 
 
 
 
 
 | 210 | #else // on Mac... | 
 
 
 
 
 | 211 | // test for the third-party "mono" framework, because without it, we are up a creek | 
 
 
 
 
 | 212 | FILE *fWhichMono = NULL; | 
 
 
 
 
 | 213 | char chrWhichMono[32]; | 
 
 
 
 
 | 214 | fWhichMono = popen("which mono", "r"); | 
 
 
 
 
 | 215 | fgets(chrWhichMono, sizeof(chrWhichMono), fWhichMono); | 
 
 
 
 
 | 216 | pclose(fWhichMono); | 
 
 
 
 
 | 217 | string strWhichMono = (string)chrWhichMono; | 
 
 
 
 
 | 218 | string::size_type loc = strWhichMono.find("mono", 0); | 
 
 
 
 
 | 219 |  | 
 
 
 
 
 | 220 | if (loc == string::npos) // this means that "which mono" did not return a path leading to the mono binary -- abort! abort! abort! | 
 
 
 
 
 | 221 | { | 
 
 
 
 
 | 222 | string monoMsg = "You don't have 'mono' installed! 'mono' is a command-line tool required by the Edition.\n"; | 
 
 
 
 
 | 223 | monoMsg = monoMsg + "You can download it from: http://www.go-mono.com/mono-downloads/download.html (OS X 10.4+)\n" + | 
 
 
 
 
 | 224 | "or http://edt.oni2.net/AE/MonoFramework10.3.dmg (OS X 10.3)\n\n" + | 
 
 
 
 
 | 225 | "Please install 'mono', then open this Installer again."; | 
 
 
 
 
 | 226 | wxMessageDialog* MonoDialogOfDeath = new wxMessageDialog(TheWindow, monoMsg.c_str(), "AE Installer Alert", wxOK | wxICON_EXCLAMATION, wxDefaultPosition); | 
 
 
 
 
 | 227 | MonoDialogOfDeath->ShowModal(); | 
 
 
 
 
 | 228 | return false; // it's quittin' time, Joe | 
 
 
 
 
 | 229 | } | 
 
 
 
 
 | 230 | #endif | 
 
 
 
 
 | 231 | return true; | 
 
 
 
 
 | 232 | } | 
 
 
 
 
 | 233 |  | 
 
 
 
 
 | 234 | bool CheckForGlobalization(bool justDoIt) | 
 
 
 
 
 | 235 | { | 
 
 
 
 
 | 236 | if (!exists("../GameDataFolder")) | 
 
 
 
 
 | 237 | { | 
 
 
 
 
 | 238 | string globMsg = "You haven't globalized yet!\n"; | 
 
 
 
 
 | 239 | globMsg = globMsg + "You must globalize to use the Anniversary Edition framework.\n" + | 
 
 
 
 
 | 240 | "Would you like to globalize now? (This could take a while...)\n" + | 
 
 
 
 
 | 241 | "(Selecting \"No\" will exit this program...)"; | 
 
 
 
 
 | 242 | wxMessageDialog* YesNoDialog = new wxMessageDialog(TheWindow, globMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition); | 
 
 
 
 
 | 243 |  | 
 
 
 
 
 | 244 | if (YesNoDialog->ShowModal() == wxID_NO) // if the user said no... | 
 
 
 
 
 | 245 | { | 
 
 
 
 
 | 246 | TheWindow->Close(); | 
 
 
 
 
 | 247 | return true; | 
 
 
 
 
 | 248 | } | 
 
 
 
 
 | 249 | } | 
 
 
 
 
 | 250 | else if (!justDoIt) | 
 
 
 
 
 | 251 | return false; | 
 
 
 
 
 | 252 | // Code below this point runs if user clicks "Yes" or if they are never asked but justDoIt is true | 
 
 
 
 
 | 253 | #ifdef WIN32 | 
 
 
 
 
 | 254 | boost::thread thrd3(globalize2); | 
 
 
 
 
 | 255 | #else // cannot use multi-threading in Mac build | 
 
 
 
 
 | 256 | TheWindow->InstallButton->Disable(); | 
 
 
 
 
 | 257 | TheWindow->ReglobalizeButton->Disable(); | 
 
 
 
 
 | 258 | globalizeData(); | 
 
 
 
 
 | 259 | TheWindow->InstallButton->Enable(); | 
 
 
 
 
 | 260 | TheWindow->ReglobalizeButton->Enable(); | 
 
 
 
 
 | 261 | #endif | 
 
 
 
 
 | 262 |  | 
 
 
 
 
 | 263 | return true; | 
 
 
 
 
 | 264 | } | 
 
 
 
 
 | 265 |  | 
 
 
 
 
 | 266 | void setStatusArea(string s) | 
 
 
 
 
 | 267 | { | 
 
 
 
 
 | 268 | wxString wxs(s.c_str(), wxConvUTF8); | 
 
 
 
 
 | 269 |  | 
 
 
 
 
 | 270 | TheWindow->StatusArea->SetStatusText(wxs); | 
 
 
 
 
 | 271 | } | 
 
 
 
 
 | 272 |  | 
 
 
 
 
 | 273 |  | 
 
 
 
 
 | 274 | /* | 
 
 
 
 
 | 275 | * Cleanup for AEInstallerApp | 
 
 
 
 
 | 276 | */ | 
 
 
 
 
 | 277 |  | 
 
 
 
 
 | 278 | int AEInstallerApp::OnExit() | 
 
 
 
 
 | 279 | { | 
 
 
 
 
 | 280 | ////@begin AEInstallerApp cleanup | 
 
 
 
 
 | 281 | return wxApp::OnExit(); | 
 
 
 
 
 | 282 | ////@end AEInstallerApp cleanup | 
 
 
 
 
 | 283 | } | 
 
 
 
 
 | 284 | void doglobalizeData() | 
 
 
 
 
 | 285 | { | 
 
 
 
 
 | 286 | globalizeData(); | 
 
 
 
 
 | 287 | #ifdef WIN32 | 
 
 
 
 
 | 288 | while(1) Sleep(-1); | 
 
 
 
 
 | 289 | #endif | 
 
 
 
 
 | 290 | } |