source: AE/Installer/trunk/source/aeinstallerapp.cpp @ 500

Last change on this file since 500 was 500, checked in by iritscen, 11 years ago

Changed 'Installer replacement failed' message so user can choose not to quit.
Fixed BSL mod package-detecting bug and other dubious flag-detecting code.
Added check for required Installer version when scanning package info files.

File size: 10.4 KB
Line 
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
21extern int updateStatus;
22extern bool installerJustUpdated;
23Install_info_cfg currentAE, updateAE;
24MainWindow* TheWindow;
25
26////@begin XPM images
27////@end XPM images
28
29
30/*
31 * Application instance implementation
32 */
33
34////@begin implement app
35IMPLEMENT_APP( AEInstallerApp )
36////@end implement app
37
38
39/*
40 * AEInstallerApp type definition
41 */
42
43IMPLEMENT_CLASS( AEInstallerApp, wxApp )
44
45
46/*
47 * AEInstallerApp event table definition
48 */
49
50BEGIN_EVENT_TABLE( AEInstallerApp, wxApp )
51
52////@begin AEInstallerApp event table entries
53////@end AEInstallerApp event table entries
54
55END_EVENT_TABLE()
56
57
58/*
59 * Constructor for AEInstallerApp
60 */
61
62AEInstallerApp::AEInstallerApp()
63{
64    Init();
65}
66
67
68/*
69 * Member initialisation
70 */
71
72void 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.                                  */
85bool 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"; // 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 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.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(&currentAE, &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(&currentAE, &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                                if (updateNotification->ShowModal() == wxID_YES)
156                                {
157                                        if (ProcessInstallerUpdate(&currentAE, &updateAE)) // there's an intentional logic gap here: if the user clicks "Yes"...
158                                        {                                                                                                  // ...and then ProcessInstallerUpdate has an error and returns false, the logic gap results...
159                                                TheWindow->Close();                                                        // ...in the code continuing to execute down through case UPDATE_INST_REPL_ERR
160                                                return true;
161                                        }
162                                }
163                                else
164                                        break;
165                        case UPDATE_INST_REPL_ERR: // the Installer replacement failed, user has to do it :-(
166                                updateMsg = "The Installer replacement process failed for some reason.\n";
167                                updateMsg = updateMsg + "In order for the update to continue, go into the folder Edition/updates/" + strEUFN + "/install/ and " + 
168                                                                                "drag the Installer to Edition/install/, replacing the current Installer application, then launch the " +
169                                                                                "new version. Click Yes to quit.";
170                                updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition);
171                                if (updateNotification->ShowModal() == wxID_YES)
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
182bool CheckForRequiredSoftware(void)
183{
184#ifdef WIN32
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");
198                RegCloseKey(hKey);
199                return false;
200        }
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 (loc == string::npos) // this means that "which mono" did not return a path leading to the mono binary -- abort! abort! abort!
212        {
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                return false; // it's quittin' time, Joe
220        }
221#endif
222        return true;
223}
224
225bool CheckForGlobalization(bool justDoIt)
226{
227        if (!exists("../GameDataFolder"))
228        {
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...
236                {
237                        TheWindow->Close();
238                        return true;
239                }
240        }
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
257void setStatusArea(string s)
258{
259        wxString wxs(s.c_str(), wxConvUTF8);
260       
261        TheWindow->StatusArea->SetStatusText(wxs);
262}
263
264
265/*
266 * Cleanup for AEInstallerApp
267 */
268
269int AEInstallerApp::OnExit()
270{   
271        ////@begin AEInstallerApp cleanup
272        return wxApp::OnExit();
273        ////@end AEInstallerApp cleanup
274}
275void doglobalizeData()
276{
277        globalizeData();
278#ifdef WIN32
279        while(1) Sleep(-1);
280#endif
281}
Note: See TracBrowser for help on using the repository browser.