ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/AE/Installer/trunk/source/aeinstallerapp.cpp
Revision: 500
Committed: Sun Mar 14 23:31:14 2010 UTC (15 years, 7 months ago) by iritscen
Content type: text/x-c++src
File size: 10692 byte(s)
Log Message:
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 Contents

# Content
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"; // 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
182 bool 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
225 bool 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
257 void 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
269 int AEInstallerApp::OnExit()
270 {
271 ////@begin AEInstallerApp cleanup
272 return wxApp::OnExit();
273 ////@end AEInstallerApp cleanup
274 }
275 void doglobalizeData()
276 {
277 globalizeData();
278 #ifdef WIN32
279 while(1) Sleep(-1);
280 #endif
281 }