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

Last change on this file since 503 was 500, checked in by iritscen, 15 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
RevLine 
[487]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
[358]11#include "boost/thread.hpp"
[487]12#include "boost/thread/mutex.hpp"
[379]13#include <fstream>
[487]14#include <string>
15#include "installer.h"
16#include "aeinstallerapp.h"
[356]17
18////@begin includes
19////@end includes
20
[500]21extern int updateStatus;
22extern bool installerJustUpdated;
[487]23Install_info_cfg currentAE, updateAE;
24MainWindow* TheWindow;
[356]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
[487]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. */
[356]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
[487]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
[500]115 if (updateStatus) // updateStatus was set when MainWindow::CreateControls() was called during initialization of the window
[487]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" +
[500]119 "(Current version is " + currentAE.AEVersion + ")\n"; // ...so we tack the rest on in a second command
[487]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";
[500]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();
[487]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{
[401]184#ifdef WIN32
[487]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)
[401]197 system("start http://www.microsoft.com/downloads/details.aspx?familyid=0856eacb-4362-4b0d-8edd-aab15c5e04f5");
198 RegCloseKey(hKey);
[487]199 return false;
[382]200 }
[487]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);
[379]210
[487]211 if (loc == string::npos) // this means that "which mono" did not return a path leading to the mono binary -- abort! abort! abort!
[379]212 {
[487]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);
[382]218 MonoDialogOfDeath->ShowModal();
[487]219 return false; // it's quittin' time, Joe
[379]220 }
221#endif
[487]222 return true;
223}
[379]224
[487]225bool CheckForGlobalization(bool justDoIt)
226{
227 if (!exists("../GameDataFolder"))
[382]228 {
[487]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
[382]235 if (YesNoDialog->ShowModal() == wxID_NO) // if the user said no...
[487]236 {
[356]237 TheWindow->Close();
[487]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
[358]244#ifdef WIN32
[487]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();
[358]252#endif
[487]253
[356]254 return true;
255}
256
[487]257void setStatusArea(string s)
258{
[356]259 wxString wxs(s.c_str(), wxConvUTF8);
260
[487]261 TheWindow->StatusArea->SetStatusText(wxs);
[356]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}
[487]275void doglobalizeData()
276{
[356]277 globalizeData();
278#ifdef WIN32
279 while(1) Sleep(-1);
280#endif
281}
Note: See TracBrowser for help on using the repository browser.