1 /* Copyright (C) 2007-2011 The SpringLobby Team. All rights reserved. */
2 //
3 // Class: Ui
4 //
5
6 #ifdef _MSC_VER
7 #ifndef NOMINMAX
8 #define NOMINMAX
9 #endif // NOMINMAX
10 #include <winsock2.h>
11 #endif // _MSC_VER
12
13
14 #include <wx/textdlg.h>
15 #include <stdexcept>
16 #include <wx/intl.h>
17 #include <wx/utils.h>
18 #include <wx/debugrpt.h>
19 #include <wx/filename.h>
20 #include <wx/app.h>
21
22 #include "ui.h"
23 #include "tasserver.h"
24 #include "settings.h"
25 #include "server.h"
26 #include "spring.h"
27 #include "channel/channel.h"
28 #include "connectwindow.h"
29 #include "mainwindow.h"
30 #include "user.h"
31 #include "utils/debug.h"
32 #include "utils/conversion.h"
33 #include "utils/uievents.h"
34 #include "updater/updatehelper.h"
35 #include "uiutils.h"
36 #include "chatpanel.h"
37 #include "battlelist/battlelisttab.h"
38 #include "hosting/battleroomtab.h"
39 #include "hosting/mainjoinbattletab.h"
40 #include "hosting/mainsingleplayertab.h"
41 #include "mainchattab.h"
42 #include "crashreport.h"
43 #include "maindownloadtab.h"
44 #include "downloader/prdownloader.h"
45
46 #include "agreementdialog.h"
47
48 #include "updater/updatehelper.h"
49 #include <wx/stdpaths.h>
50
51 #include "reconnectdialog.h"
52 #include "utils/customdialogs.h"
53 #include "utils/platform.h"
54 #include "updater/versionchecker.h"
55 #include "sound/alsound.h"
56 #include <lslutils/globalsmanager.h>
57 #include <lslunitsync/c_api.h>
58 #include "utils/misc.h"
59 #include "textentrydialog.h"
60
61 SLCONFIG("/General/AutoUpdate", true, "Determines if sprinlobby should check for updates on startup");
62 SLCONFIG("/GUI/StartTab", (long)MainWindow::PAGE_SINGLE, "which tab to show on startup");
63 SLCONFIG("/Chat/BroadcastEverywhere",true, "setting to spam the server messages in all channels");
64 SLCONFIG("/Server/Autoconnect", false, "Connect to server on startup");
65
66 static const unsigned int s_reconnect_delay_ms = 6000;
67
ui()68 Ui& ui()
69 {
70 assert(wxThread::IsMain());
71 static LSL::Util::LineInfo<Ui> m( AT );
72 static LSL::Util::GlobalObjectHolder<Ui, LSL::Util::LineInfo<Ui> > m_ui( m );
73 return m_ui;
74 }
75
Ui()76 Ui::Ui() :
77 wxEvtHandler(),
78 m_serv(0),
79 m_main_win(0),
80 m_con_win(0),
81 m_reconnect_dialog(0),
82 m_first_update_trigger(true),
83 m_recconecting_wait(false),
84 m_disable_autoconnect(false),
85 m_battle_info_updatedSink( this, &BattleEvents::GetBattleEventSender( ( BattleEvents::BattleInfoUpdate ) ) )
86 {
87 m_main_win = new MainWindow( );
88 CustomMessageBoxBase::setLobbypointer(m_main_win);
89 m_serv = new TASServer();
90 serverSelector().SetCurrentServer( m_serv );
91 ConnectGlobalEvent(this, GlobalEvent::OnSpringTerminated, wxObjectEventFunction(&Ui::OnSpringTerminated));
92 ConnectGlobalEvent(this, GlobalEvent::OnQuit, wxObjectEventFunction(&Ui::OnQuit));
93 }
94
~Ui()95 Ui::~Ui()
96 {
97 m_disable_autoconnect = true;
98 Disconnect();
99 delete m_serv;
100 }
101
GetActiveChatPanel()102 ChatPanel* Ui::GetActiveChatPanel()
103 {
104 return mw().GetActiveChatPanel();
105 }
106
107
mw()108 MainWindow& Ui::mw()
109 {
110 assert(wxThread::IsMain());
111 ASSERT_LOGIC( m_main_win != 0, _T("m_main_win = 0") );
112 return *m_main_win;
113 }
114
mw() const115 const MainWindow& Ui::mw() const
116 {
117 ASSERT_LOGIC( m_main_win != 0, _T("m_main_win = 0") );
118 return *m_main_win;
119 }
120
121
IsMainWindowCreated() const122 bool Ui::IsMainWindowCreated() const
123 {
124 if ( m_main_win == 0 ) return false;
125 else return true;
126 }
127
128
129 //! @brief Shows the main window on screen
ShowMainWindow()130 void Ui::ShowMainWindow()
131 {
132 ASSERT_LOGIC( m_main_win != 0, _T("m_main_win = 0") );
133 mw().Show(true);
134 }
135
136
137 //! @brief Show the connect window on screen
138 //!
139 //! @note It will create the ConnectWindow if not allready created
ShowConnectWindow()140 void Ui::ShowConnectWindow()
141 {
142 if ( IsConnecting() || IsConnected() || m_recconecting_wait )
143 return;
144 if ( m_con_win == 0 ) {
145 ASSERT_LOGIC( m_main_win != 0, _T("m_main_win = 0") );
146 m_con_win = new ConnectWindow( m_main_win, *this );
147 }
148 m_con_win->CenterOnParent();
149 m_con_win->Show(true);
150 m_con_win->Raise();
151 }
152
153
154 //! @brief Connects to default server or opens the ConnectWindow
155 //!
156 //! @todo Fix Auto Connect
157 //! @see DoConnect
Connect()158 void Ui::Connect()
159 {
160 wxString server_name = sett().GetDefaultServer();
161 wxString nick = sett().GetServerAccountNick( server_name );
162 bool autoconnect = cfg().ReadBool(_T( "/Server/Autoconnect" ));
163 if ( !autoconnect || server_name.IsEmpty() || nick.IsEmpty() ) {
164 ShowConnectWindow();
165 return;
166 }
167 if (m_disable_autoconnect)
168 return;
169 m_con_win = 0;
170 wxString pass = sett().GetServerAccountPass( server_name );
171 DoConnect( server_name, nick, pass);
172 }
173
174
Reconnect()175 void Ui::Reconnect()
176 {
177 wxString servname = sett().GetDefaultServer();
178
179 wxString pass = sett().GetServerAccountPass(servname);
180 if ( !sett().GetServerAccountSavePass(servname) ) {
181 if ( !AskPassword( _("Server password"), _("Password"), pass ) ) return;
182 }
183
184 Disconnect();
185 DoConnect( servname, sett().GetServerAccountNick(servname), pass );
186 }
187
188
Disconnect()189 void Ui::Disconnect()
190 {
191 if ( m_serv != 0 ) {
192 if ( IsConnected() ) {
193 serverSelector().GetServer().Disconnect();
194 }
195 }
196 }
197
198
199 //! @brief Opens the accutial connection to a server.
DoConnect(const wxString & servername,const wxString & username,const wxString & password)200 void Ui::DoConnect( const wxString& servername, const wxString& username, const wxString& password )
201 {
202 if ( m_reconnect_delay_timer.IsRunning() ) {
203 m_recconecting_wait = true;
204 AutocloseMessageBox m( &mw(), _("Waiting for reconnect"), wxMessageBoxCaptionStr, s_reconnect_delay_ms );
205 int res = m.ShowModal();
206 m_recconecting_wait = false;
207 if ( res == wxID_CANCEL ) {
208 m_reconnect_delay_timer.Stop();
209 return;
210 }
211 }
212
213 wxString host;
214 int port;
215
216 if ( servername != m_last_used_backup_server ) { // do not save the server as default if it's a backup one
217 sett().SetDefaultServer( servername );
218 } else {
219 m_last_used_backup_server = wxEmptyString;
220 }
221
222 if ( !sett().ServerExists( servername ) ) {
223 ASSERT_LOGIC( false, _T("Server does not exist in settings") );
224 return;
225 }
226
227 Disconnect();
228
229 serverSelector().GetServer().SetUsername( username );
230 serverSelector().GetServer().SetPassword( password );
231
232 if ( sett().GetServerAccountSavePass( servername ) ) {
233 if ( serverSelector().GetServer().IsPasswordHash(password) ) sett().SetServerAccountPass( servername, password );
234 else sett().SetServerAccountPass( servername, serverSelector().GetServer().GetPasswordHash( password ) );
235 } else {
236 sett().SetServerAccountPass( servername, wxEmptyString );
237 }
238
239 host = sett().GetServerHost( servername );
240 port = sett().GetServerPort( servername );
241
242 AddServerWindow( servername );
243 serverSelector().GetServer().uidata.panel->StatusMessage( _T("Connecting to server ") + servername + _T("...") );
244
245 // Connect
246 serverSelector().GetServer().Connect( servername, host, port );
247
248 }
249
AddServerWindow(const wxString & servername)250 void Ui::AddServerWindow( const wxString& servername )
251 {
252 if ( !serverSelector().GetServer().uidata.panel ) {
253 serverSelector().GetServer().uidata.panel = m_main_win->GetChatTab().AddChatPanel( *m_serv, servername );
254
255 }
256 }
257
258
ReopenServerTab()259 void Ui::ReopenServerTab()
260 {
261 if ( serverSelector().GetServer().IsOnline() ) {
262 AddServerWindow( serverSelector().GetServer().GetServerName() );
263 // re-add all users to the user list
264 const UserList& list = serverSelector().GetServer().GetUserList();
265 for ( unsigned int i = 0; i < list.GetNumUsers(); i++ ) {
266 serverSelector().GetServer().uidata.panel->OnChannelJoin( list.GetUser(i) );
267 }
268 }
269 }
270
DoRegister(const wxString & servername,const wxString & username,const wxString & password,wxString & reason)271 bool Ui::DoRegister( const wxString& servername, const wxString& username, const wxString& password,wxString& reason)
272 {
273 wxString host;
274 int port;
275
276 if ( !sett().ServerExists( servername ) ) {
277 ASSERT_LOGIC( false, _T("Server does not exist in settings") );
278 return false;
279 }
280
281 host = sett().GetServerHost( servername );
282 port = sett().GetServerPort( servername );
283 bool success = serverSelector().GetServer().Register( host, port, username, password,reason );
284 if ( success ) {
285 customMessageBox(SL_MAIN_ICON, _("Registration successful,\nyou should now be able to login."), _("Registration successful"), wxOK );
286 } else {
287 wxLogWarning( _T("registration failed, reason: %s"), reason.c_str() );
288 if ( reason == _("Connection timed out") || reason.IsEmpty() ) ConnectionFailurePrompt();
289 else customMessageBox(SL_MAIN_ICON,_("Registration failed, the reason was:\n")+ reason , _("Registration failed."), wxOK );
290 }
291 return success;
292
293 }
294
IsConnecting() const295 bool Ui::IsConnecting() const
296 {
297 if ( m_reconnect_dialog != 0 ) return m_reconnect_dialog->IsShown();
298 return false;
299 }
300
IsConnected() const301 bool Ui::IsConnected() const
302 {
303 if ( m_serv != 0 ) return m_serv->IsConnected();
304 return false;
305 }
306
JoinChannel(const wxString & name,const wxString & password)307 void Ui::JoinChannel( const wxString& name, const wxString& password )
308 {
309 if ( m_serv != 0 ) serverSelector().GetServer().JoinChannel( name, password );
310 }
311
312
IsSpringRunning() const313 bool Ui::IsSpringRunning() const
314 {
315 return spring().IsRunning();
316 }
317
318
319 //! @brief Quits the entire application
Quit()320 void Ui::Quit()
321 {
322 m_disable_autoconnect = true;
323 Disconnect();
324 if ( m_con_win != 0 )
325 m_con_win->Close();
326 }
327
Download(const wxString & category,const wxString & name,const wxString &)328 void Ui::Download( const wxString& category, const wxString& name, const wxString& /*hash */)
329 {
330 const std::string scat = STD_STRING(category);
331 const std::string sname = STD_STRING(name);
332 int count = prDownloader().GetDownload(scat, sname);
333 assert( count > 0 );
334 }
335
336 //void Ui::DownloadFileWebsite( const wxString& name )
337 //{
338 // wxString newname = name;
339 // newname.Replace( _T(" "), _T("+") );
340 // wxString url = _T("http://spring.jobjol.nl/search_result.php?search_cat=1&select_select=select_file_subject&Submit=Search&search=") + newname;
341 // OpenWebBrowser ( url );
342 //}
343
344 //! @brief Display a dialog asking a question with OK and Canel buttons
345 //!
346 //! @return true if OK button was pressed
347 //! @note this does not return until the user pressed any of the buttons or closed the dialog.
Ask(const wxString & heading,const wxString & question) const348 bool Ui::Ask( const wxString& heading, const wxString& question ) const
349 {
350 int answer = customMessageBox( SL_MAIN_ICON, question, heading, wxYES_NO );
351 return ( answer == wxYES );
352 }
353
354 //! cannot be const because parent window cannot be const
AskPassword(const wxString & heading,const wxString & message,wxString & password)355 bool Ui::AskPassword( const wxString& heading, const wxString& message, wxString& password )
356 {
357 wxPasswordEntryDialog pw_dlg( &mw(), message, heading, password );
358 int res = pw_dlg.ShowModal();
359 password = pw_dlg.GetValue();
360 return ( res == wxID_OK );
361 }
362
AskText(const wxString & heading,const wxString & question,wxString & answer,bool multiline)363 bool Ui::AskText( const wxString& heading, const wxString& question, wxString& answer, bool multiline )
364 {
365 TextEntryDialog name_dlg( &mw(), question, heading, answer, multiline );
366 int res = name_dlg.ShowModal();
367 answer = name_dlg.GetValue();
368 return ( res == wxID_OK );
369 }
370
371
ShowMessage(const wxString & heading,const wxString & message) const372 void Ui::ShowMessage( const wxString& heading, const wxString& message ) const
373 {
374 if ( m_main_win == 0 ) return;
375 serverMessageBox( SL_MAIN_ICON, message, heading, wxOK);
376 }
377
378
ExecuteSayCommand(const wxString & cmd)379 bool Ui::ExecuteSayCommand( const wxString& cmd )
380 {
381 if ( !IsConnected() ) return false;
382
383 if ( (cmd.BeforeFirst(' ').Lower() == _T("/join")) || (cmd.BeforeFirst(' ').Lower() == _T("/j")) ) {
384 wxString channel = cmd.AfterFirst(' ');
385 wxString pass = channel.AfterFirst(' ');
386 if ( !pass.IsEmpty() ) channel = channel.BeforeFirst(' ');
387 if ( channel.StartsWith(_T("#")) ) channel.Remove( 0, 1 );
388 serverSelector().GetServer().JoinChannel( channel, pass );
389 return true;
390 } else if ( cmd.BeforeFirst(' ').Lower() == _T("/away") ) {
391 serverSelector().GetServer().GetMe().Status().away = true;
392 serverSelector().GetServer().GetMe().SendMyUserStatus();
393 mw().GetJoinTab().GetBattleRoomTab().UpdateMyInfo();
394 return true;
395 } else if ( cmd.BeforeFirst(' ').Lower() == _T("/back") ) {
396 if ( IsConnected() ) {
397 serverSelector().GetServer().GetMe().Status().away = false;
398 serverSelector().GetServer().GetMe().SendMyUserStatus();
399 mw().GetJoinTab().GetBattleRoomTab().UpdateMyInfo();
400 return true;
401 }
402 } else if ( cmd.BeforeFirst(' ').Lower() == _T("/ingame") ) {
403 wxString nick = cmd.AfterFirst(' ');
404 serverSelector().GetServer().RequestInGameTime( nick );
405 return true;
406 } else if ( cmd.BeforeFirst(' ').Lower() == _T("/help") ) {
407 wxString topic = cmd.AfterFirst(' ');
408 ConsoleHelp( topic.Lower() );
409 return true;
410 } else if ( cmd.BeforeFirst(' ').Lower() == _T("/msg") ) {
411 wxString user = cmd.AfterFirst(' ').BeforeFirst(' ');
412 wxString msg = cmd.AfterFirst(' ').AfterFirst(' ');
413 serverSelector().GetServer().SayPrivate( user, msg );
414 return true;
415 } else if ( cmd.BeforeFirst(' ').Lower() == _T("/channels") ) {
416 mw().ShowChannelChooser();
417 return true;
418 }
419 return false;
420 }
421
422
ConsoleHelp(const wxString & topic)423 void Ui::ConsoleHelp( const wxString& topic )
424 {
425 ChatPanel* panel = GetActiveChatPanel();
426 if ( panel == 0 ) {
427 ShowMessage( _("Help error"), _("Type /help in a chat box. (A bug currently prevents this from working in battleroom") );
428 return;
429 }
430 if ( topic == wxEmptyString ) {
431 panel->ClientMessage( IdentityString( _("%s commands help.") ) );
432 panel->ClientMessage( wxEmptyString );
433 panel->ClientMessage( _("Global commands:") );
434 panel->ClientMessage( _(" \"/away\" - Sets your status to away.") );
435 panel->ClientMessage( _(" \"/back\" - Resets your away status.") );
436 panel->ClientMessage( _(" \"/changepassword2 newpassword\" - Changes the current active account's password, needs the old password saved in login box") );
437 panel->ClientMessage( _(" \"/changepassword oldpassword newpassword\" - Changes the current active account's password, password cannot contain spaces") );
438 panel->ClientMessage( _(" \"/channels\" - Lists currently active channels.") );
439 panel->ClientMessage( _(" \"/help [topic]\" - Put topic if you want to know more specific information about a command.") );
440 panel->ClientMessage( _(" \"/join channel [password]\" - Joins a channel.") );
441 panel->ClientMessage( _(" \"/j\" - Alias to /join.") );
442 panel->ClientMessage( _(" \"/ingame\" - Shows how much time you have in game.") );
443 panel->ClientMessage( _(" \"/msg username [text]\" - Sends a private message containing text to username.") );
444 panel->ClientMessage( _(" \"/part\" - Leaves current channel.") );
445 panel->ClientMessage( _(" \"/p\" - Alias to /part.") );
446 panel->ClientMessage( _(" \"/rename newalias\" - Changes your nickname to newalias.") );
447 panel->ClientMessage( IdentityString( _(" \"/sayver\" - Says what version of %s you have in chat.") ) );
448 panel->ClientMessage( _(" \"/testmd5 text\" - Returns md5-b64 hash of given text.") );
449 panel->ClientMessage( IdentityString( _(" \"/ver\" - Displays what version of %s you have.") ) );
450 panel->ClientMessage( _(" \"/clear\" - Clears all text from current chat panel") );
451 panel->ClientMessage( wxEmptyString );
452 panel->ClientMessage( _("Chat commands:") );
453 panel->ClientMessage( _(" \"/me action\" - Say IRC style action message.") );
454 panel->ClientMessage( wxEmptyString );
455 panel->ClientMessage( _("If you are missing any commands, go to #springlobby and try to type it there :)") );
456 // panel->ClientMessage( _(" \"/\" - .") );
457 } else if ( topic == _T("topics") ) {
458 panel->ClientMessage( _("No topics written yet.") );
459 } else {
460 panel->ClientMessage( _("The topic \"") + topic + _("\" was not found. Type \"/help topics\" only for available topics.") );
461 }
462 }
463
464
GetChannelChatPanel(const wxString & channel)465 ChatPanel* Ui::GetChannelChatPanel( const wxString& channel )
466 {
467 return mw().GetChannelChatPanel( channel );
468 }
469
470
471 ////////////////////////////////////////////////////////////////////////////////////////////
472 // EVENTS
473 ////////////////////////////////////////////////////////////////////////////////////////////
474
475 //! @brief Called when connected to a server
476 //!
477 //! @todo Display in servertab
OnConnected(Server & server,const wxString & server_name,const wxString &,bool)478 void Ui::OnConnected( Server& server, const wxString& server_name, const wxString& /*unused*/, bool /*supported*/ )
479 {
480 wxLogDebugFunc( wxEmptyString );
481
482 if ( server.uidata.panel ) server.uidata.panel->StatusMessage( _T("Connected to ") + server_name + _T(".") );
483 mw().GetBattleListTab().OnConnected();
484
485 delete m_con_win;
486 m_con_win = 0;
487
488 delete m_reconnect_dialog;
489 m_reconnect_dialog = 0;
490 }
491
492
VersionGetMajor(const std::string & version)493 std::string VersionGetMajor(const std::string& version)
494 {
495 const int pos = version.find(".");
496 if (pos>0) {
497 return version.substr(0, pos);
498 }
499 return version;
500 }
501
VersionIsRelease(const std::string & version)502 bool VersionIsRelease(const std::string& version) { //try to detect if a version is major
503 const std::string allowedChars = "01234567890.";
504 for(int i=0; i<version.length(); i++) {
505 if (allowedChars.find(version[i]) == std::string::npos) { //found invalid char -> not stable version
506 return false;
507 }
508 }
509 return true;
510 }
511
VersionSyncCompatible(const std::string & ver1,const std::string & ver2)512 bool VersionSyncCompatible(const std::string& ver1, const std::string& ver2)
513 {
514 if (ver1 == ver2) {
515 return true;
516 }
517 if ( (VersionIsRelease(ver1) && VersionIsRelease(ver2)) &&
518 (VersionGetMajor(ver1) == VersionGetMajor(ver2))) {
519 return true;
520 }
521 return false;
522 }
523
IsSpringCompatible(const wxString & engine,const wxString & version)524 bool Ui::IsSpringCompatible(const wxString& engine, const wxString& version)
525 {
526 assert(engine == _T("spring"));
527 if ( sett().GetDisableSpringVersionCheck() ) return true;
528 const std::string neededversion = STD_STRING(version);
529 const auto versionlist = sett().GetSpringVersionList();
530 for ( const auto pair : versionlist ) {
531 const wxString ver = pair.first;
532 const LSL::SpringBundle bundle = pair.second;
533 if ( VersionSyncCompatible(neededversion, STD_STRING(ver))) {
534 if ( sett().GetCurrentUsedSpringIndex() != ver ) {
535 wxLogMessage(_T("server enforce usage of version: %s, switching to profile: %s"), ver.c_str(), ver.c_str());
536 sett().SetUsedSpringIndex( ver );
537 LSL::usync().ReloadUnitSyncLib();
538 }
539 return true;
540 }
541 }
542 if ( wxYES == customMessageBox( SL_MAIN_ICON,
543 _("The selected preset requires the engine ") + engine + _(" ") + version+ _(". Should it be downloaded? \nPlease reselect the preset after download finished"),
544 _("Engine missing"),
545 wxYES_NO ) )
546
547 Download(TowxString(PrDownloader::GetEngineCat()), version, wxEmptyString);
548 return false; // no compatible version found
549 }
550
551
OnLoggedIn()552 void Ui::OnLoggedIn( )
553 {
554 if ( m_main_win == 0 ) return;
555 mw().GetChatTab().RejoinChannels();
556 // FIXME RejoinChannels changes active tab, we change back to
557 // default tab on auto connect
558 if ( cfg().ReadBool(_T( "/Server/Autoconnect" )) )
559 mw().ShowTab( cfg().ReadLong(_T( "/GUI/StartTab" )));
560 mw().GetBattleListTab().SortBattleList();
561 }
562
563
OnDisconnected(Server & server,bool wasonline)564 void Ui::OnDisconnected( Server& server, bool wasonline )
565 {
566 m_reconnect_delay_timer.Start( s_reconnect_delay_ms, true );
567 if ( m_main_win == 0 ) return;
568 wxLogDebugFunc( wxEmptyString );
569 if (!&server) {
570 wxLogError(_T("WTF got null reference!!!"));
571 return;
572 }
573
574 mw().GetJoinTab().LeaveCurrentBattle();
575 mw().GetBattleListTab().RemoveAllBattles();
576
577 mw().GetChatTab().LeaveChannels();
578
579 wxString disconnect_msg = wxFormat(_("disconnected from server: %s") ) % server.GetServerName();
580 UiEvents::GetStatusEventSender( UiEvents::addStatusMessage ).SendEvent(
581 UiEvents::StatusData( disconnect_msg, 1 ) );
582 if ( !wxTheApp->IsActive() ) {
583 UiEvents::GetNotificationEventSender().SendEvent(
584 UiEvents::NotficationData( UiEvents::ServerConnection, disconnect_msg ) );
585 }
586 if ( server.uidata.panel ) {
587 server.uidata.panel->StatusMessage( disconnect_msg );
588
589 server.uidata.panel->SetServer( 0 );
590 }
591 if ( (!m_disable_autoconnect) && (!wasonline)) {// couldn't even estabilish a socket, prompt the user to switch to another server
592 ConnectionFailurePrompt();
593 }
594 }
595
ConnectionFailurePrompt()596 void Ui::ConnectionFailurePrompt()
597 {
598 if ( m_reconnect_dialog != 0 ) {
599 return;
600 }
601 if ( m_recconecting_wait ) {
602 return;
603 }
604 // if connect window instance exists, delete it to avoid 2 windows which do the same task
605 delete m_con_win;
606 m_con_win = 0;
607 m_reconnect_dialog = new ReconnectDialog();
608 int returnval = m_reconnect_dialog->ShowModal();
609 delete m_reconnect_dialog;
610 m_reconnect_dialog = 0;
611 switch ( returnval ) {
612 case wxID_YES: { // try again with the same server/settings
613 Reconnect();
614 break;
615 }
616 case wxID_NO: { // switch to next server in the list
617 m_last_used_backup_server = GetNextServer();
618 wxString current_server = sett().GetDefaultServer();
619 sett().SetDefaultServer( m_last_used_backup_server );// temp set backup server as default
620 Connect();
621 sett().SetDefaultServer( current_server ); // restore original serv
622 break;
623 }
624 default:
625 case wxID_CANCEL: { // do nothing
626 return;
627 }
628 }
629 }
630
631
632
GetNextServer()633 wxString Ui::GetNextServer()
634 {
635 wxString previous_server = m_last_used_backup_server;
636 if ( previous_server.IsEmpty() ) previous_server = sett().GetDefaultServer();
637 wxArrayString serverlist = sett().GetServers();
638 int position = serverlist.Index( previous_server );
639 if ( position == wxNOT_FOUND ) position = -1;
640 position = ( position + 1) % serverlist.GetCount(); // switch to next in the list
641 return serverlist[position];
642 }
643
IsAutoJoinChannel(Channel & chan)644 static inline bool IsAutoJoinChannel( Channel& chan )
645 {
646 typedef std::vector<ChannelJoinInfo>
647 Vec;
648 typedef Vec::const_iterator
649 VecIt;
650 const Vec chans = sett().GetChannelsJoin();
651 for ( VecIt it = chans.begin(); it != chans.end(); ++it ) {
652 if ( it->name == chan.GetName() )
653 return true;
654 }
655 return false;
656 }
657 //! @brief Called when client has joined a channel
658 //!
659 //! @todo Check if a pannel allready exists for this channel
OnJoinedChannelSuccessful(Channel & chan)660 void Ui::OnJoinedChannelSuccessful( Channel& chan )
661 {
662 bool doFocus = !cfg().ReadBool(_T( "/Server/Autoconnect" )) || !IsAutoJoinChannel( chan );
663 bool panel_exists = mw().GetChannelChatPanel( chan.GetName() ) != NULL;
664 OnJoinedChannelSuccessful( chan, !panel_exists && doFocus );
665 }
666
OnJoinedChannelSuccessful(Channel & chan,bool focusTab)667 void Ui::OnJoinedChannelSuccessful( Channel& chan, bool focusTab )
668 {
669 if ( m_main_win == 0 ) return;
670 wxLogDebugFunc( wxEmptyString );
671
672 chan.uidata.panel = 0;
673
674 mw().OpenChannelChat( chan, focusTab );
675 }
676
677 //! @brief Called when something is said in a channel
OnChannelSaid(Channel & channel,User & user,const wxString & message)678 void Ui::OnChannelSaid( Channel& channel, User& user, const wxString& message )
679 {
680 wxLogDebugFunc( wxEmptyString );
681 if ( channel.uidata.panel == 0 ) {
682 wxLogError( _T("OnChannelSaid: ud->panel NULL") );
683 return;
684 }
685 channel.uidata.panel->Said( user.GetNick(), message );
686 }
687
688
OnChannelDidAction(Channel & channel,User & user,const wxString & action)689 void Ui::OnChannelDidAction( Channel& channel , User& user, const wxString& action )
690 {
691 wxLogDebugFunc( wxEmptyString );
692 if ( channel.uidata.panel == 0 ) {
693 wxLogError( _T("OnChannelDidAction: ud->panel NULL") );
694 return;
695 }
696 channel.uidata.panel->DidAction( user.GetNick(), action );
697 }
698
699
OnChannelMessage(const wxString & channel,const wxString & msg)700 void Ui::OnChannelMessage( const wxString& channel, const wxString& msg )
701 {
702 ChatPanel* panel = GetChannelChatPanel( channel );
703 if ( panel != 0 ) {
704 panel->StatusMessage( msg );
705 }
706 }
707
708
OnUserJoinedChannel(Channel & chan,User & user)709 void Ui::OnUserJoinedChannel( Channel& chan, User& user )
710 {
711 //wxLogDebugFunc( wxEmptyString );
712 if ( chan.uidata.panel == 0 ) {
713 wxLogError( _T("OnUserJoinedChannel: ud->panel NULL") );
714 return;
715 }
716 chan.uidata.panel->Joined( user );
717 }
718
719
OnChannelJoin(Channel & chan,User & user)720 void Ui::OnChannelJoin( Channel& chan, User& user )
721 {
722 //wxLogDebugFunc( wxEmptyString );
723 if ( chan.uidata.panel == 0 ) {
724 wxLogError( _T("OnChannelJoin: ud->panel NULL") );
725 return;
726 }
727 chan.uidata.panel->OnChannelJoin( user );
728 }
729
730
OnUserLeftChannel(Channel & chan,User & user,const wxString & reason)731 void Ui::OnUserLeftChannel( Channel& chan, User& user, const wxString& reason )
732 {
733 //wxLogDebugFunc( wxEmptyString );
734 if ( chan.uidata.panel == 0 ) {
735 wxLogError( _T("OnUserLeftChannel: ud->panel NULL") );
736 return;
737 }
738 chan.uidata.panel->Parted( user, reason );
739 }
740
741
OnChannelTopic(Channel & channel,const wxString & user,const wxString & topic)742 void Ui::OnChannelTopic( Channel& channel, const wxString& user, const wxString& topic )
743 {
744 wxLogDebugFunc( wxEmptyString );
745 if ( channel.uidata.panel == 0 ) {
746 wxLogError( _T("OnChannelTopic: ud->panel NULL") );
747 return;
748 }
749 channel.uidata.panel->SetTopic( user, topic );
750 }
751
752
OnChannelList(const wxString & channel,const int & numusers)753 void Ui::OnChannelList( const wxString& channel, const int& numusers )
754 {
755 ChatPanel* panel = GetActiveChatPanel();
756 if ( panel == 0 ) {
757 ShowMessage( _("error"), _("no active chat panels open.") );
758 return;
759 }
760 panel->StatusMessage( wxFormat( _("%s (%d users)") ) % channel % numusers );
761 }
762
763
OnUserOnline(User & user)764 void Ui::OnUserOnline( User& user )
765 {
766 if ( m_main_win == 0 ) return;
767 mw().GetChatTab().OnUserConnected( user );
768 }
769
770
OnUserOffline(User & user)771 void Ui::OnUserOffline( User& user )
772 {
773 if ( m_main_win == 0 ) return;
774 mw().GetChatTab().OnUserDisconnected( user );
775 if ( user.uidata.panel ) {
776 user.uidata.panel->SetUser( 0 );
777 user.uidata.panel = 0;
778 }
779 }
780
781
OnUserStatusChanged(User & user)782 void Ui::OnUserStatusChanged( User& user )
783 {
784 if ( m_main_win == 0 ) return;
785 for ( int i = 0; i < serverSelector().GetServer().GetNumChannels(); i++ ) {
786 Channel& chan = serverSelector().GetServer().GetChannel( i );
787 if ( ( chan.UserExists(user.GetNick()) ) && ( chan.uidata.panel != 0 ) ) {
788 chan.uidata.panel->UserStatusUpdated( user );
789 }
790 }
791 if ( user.uidata.panel ) {
792 user.uidata.panel->UserStatusUpdated( user );
793 }
794 if ( user.GetStatus().in_game ) mw().GetBattleListTab().UserUpdate( user );
795 try {
796 ChatPanel& server = mw().GetChatTab().ServerChat();
797 server.UserStatusUpdated( user );
798 } catch(...) {}
799 }
800
801
OnUnknownCommand(Server & server,const wxString & command,const wxString & params)802 void Ui::OnUnknownCommand( Server& server, const wxString& command, const wxString& params )
803 {
804 if ( server.uidata.panel != 0 ) server.uidata.panel->UnknownCommand( command, params );
805 }
806
807
OnMotd(Server & server,const wxString & message)808 void Ui::OnMotd( Server& server, const wxString& message )
809 {
810 if ( server.uidata.panel != 0 ) server.uidata.panel->Motd( message );
811 }
812
OnServerBroadcast(Server &,const wxString & message)813 void Ui::OnServerBroadcast( Server& /*server*/, const wxString& message )
814 {
815 if ( m_main_win == 0 ) return;
816 mw().GetChatTab().BroadcastMessage( message );
817 try { // send it to battleroom too
818 mw().GetJoinTab().GetBattleRoomTab().GetChatPanel().StatusMessage(message);
819 } catch(...) {}
820 }
821
822
OnServerMessage(Server & server,const wxString & message)823 void Ui::OnServerMessage( Server& server, const wxString& message )
824 {
825 if ( !cfg().ReadBool(_T("/Chat/BroadcastEverywhere")) ) {
826 if ( server.uidata.panel != 0 ) server.uidata.panel->StatusMessage( message );
827 } else {
828 if ( server.uidata.panel != 0 ) server.uidata.panel->StatusMessage( message );
829 if ( m_main_win == 0 ) return;
830 ChatPanel* activepanel = mw().GetChatTab().GetActiveChatPanel();
831 if ( activepanel != 0 ) {
832 if (activepanel != server.uidata.panel) activepanel->StatusMessage(message); // don't send it twice to the server tab
833 }
834 try { // send it to battleroom too
835 mw().GetJoinTab().GetBattleRoomTab().GetChatPanel().StatusMessage(message);
836 } catch(...) {}
837 }
838 }
839
840
OnUserSaid(User & user,const wxString & message,bool fromme)841 void Ui::OnUserSaid( User& user, const wxString& message, bool fromme )
842 {
843 if ( m_main_win == 0 ) return;
844 if ( user.uidata.panel == 0 ) {
845 mw().OpenPrivateChat( user );
846 }
847 if ( fromme ) user.uidata.panel->Said( serverSelector().GetServer().GetMe().GetNick(), message );
848 else user.uidata.panel->Said( user.GetNick(), message );
849 }
850
OnUserSaidEx(User & user,const wxString & action,bool fromme)851 void Ui::OnUserSaidEx( User& user, const wxString& action, bool fromme )
852 {
853 if ( m_main_win == 0 ) return;
854 if ( user.uidata.panel == 0 ) {
855 mw().OpenPrivateChat( user );
856 }
857 if ( fromme ) user.uidata.panel->DidAction ( serverSelector().GetServer().GetMe().GetNick(), action );
858 else user.uidata.panel->DidAction( user.GetNick(), action );
859 }
860
OnBattleOpened(IBattle & battle)861 void Ui::OnBattleOpened( IBattle& battle )
862 {
863 if ( m_main_win == 0 ) return;
864 mw().GetBattleListTab().AddBattle( battle );
865 try {
866 User& user = battle.GetFounder();
867 for ( int i = 0; i < serverSelector().GetServer().GetNumChannels(); i++ ) {
868 Channel& chan = serverSelector().GetServer().GetChannel( i );
869 if ( ( chan.UserExists(user.GetNick()) ) && ( chan.uidata.panel != 0 ) ) {
870 chan.uidata.panel->UserStatusUpdated( user );
871 }
872 }
873 } catch(...) {}
874 }
875
876
OnBattleClosed(IBattle & battle)877 void Ui::OnBattleClosed( IBattle& battle )
878 {
879 if ( m_main_win == 0 ) return;
880 mw().GetBattleListTab().RemoveBattle( battle );
881 try {
882 if ( mw().GetJoinTab().GetBattleRoomTab().GetBattle() == &battle ) {
883 if (!battle.IsFounderMe() )
884 customMessageBoxNoModal(SL_MAIN_ICON,_("The current battle was closed by the host."),_("Battle closed"));
885 mw().GetJoinTab().LeaveCurrentBattle();
886 }
887 } catch (...) {}
888 for ( unsigned int b = 0; b < battle.GetNumUsers(); b++ ) {
889 User& user = battle.GetUser( b );
890 user.SetBattle(0);
891 for ( int i = 0; i < serverSelector().GetServer().GetNumChannels(); i++ ) {
892 Channel& chan = serverSelector().GetServer().GetChannel( i );
893 if ( ( chan.UserExists(user.GetNick()) ) && ( chan.uidata.panel != 0 ) ) {
894 chan.uidata.panel->UserStatusUpdated( user );
895 }
896 }
897 }
898 }
899
900
OnUserJoinedBattle(IBattle & battle,User & user)901 void Ui::OnUserJoinedBattle( IBattle& battle, User& user )
902 {
903 if ( m_main_win == 0 ) return;
904 mw().GetBattleListTab().UpdateBattle( battle );
905
906 try {
907 if ( mw().GetJoinTab().GetBattleRoomTab().GetBattle() == &battle ) {
908 mw().GetJoinTab().GetBattleRoomTab().OnUserJoined( user );
909 OnBattleInfoUpdated( std::make_pair(&battle,wxString()) );
910 }
911 } catch (...) {}
912
913 for ( int i = 0; i < serverSelector().GetServer().GetNumChannels(); i++ ) {
914 Channel& chan = serverSelector().GetServer().GetChannel( i );
915 if ( ( chan.UserExists(user.GetNick()) ) && ( chan.uidata.panel != 0 ) ) {
916 chan.uidata.panel->UserStatusUpdated( user );
917 }
918 }
919 }
920
921
OnUserLeftBattle(IBattle & battle,User & user,bool isbot)922 void Ui::OnUserLeftBattle( IBattle& battle, User& user, bool isbot )
923 {
924 assert(wxThread::IsMain());
925 if ( m_main_win == 0 ) return;
926 user.SetSideiconIndex( -1 ); //just making sure he's not running around with some icon still set
927 user.BattleStatus().side = 0; // and reset side, so after rejoin we don't potentially stick with a num higher than avail
928 mw().GetBattleListTab().UpdateBattle( battle );
929 try {
930 if ( mw().GetJoinTab().GetBattleRoomTab().GetBattle() == &battle ) {
931 mw().GetJoinTab().GetBattleRoomTab().OnUserLeft( user );
932 OnBattleInfoUpdated( std::make_pair(&battle,wxString()) );
933 if ( &user == &serverSelector().GetServer().GetMe() ) {
934 mw().GetJoinTab().LeaveCurrentBattle();
935 mw().ShowTab(MainWindow::PAGE_LIST);
936 }
937 }
938 } catch (...) {}
939 if ( isbot ) return;
940 for ( int i = 0; i < serverSelector().GetServer().GetNumChannels(); i++ ) {
941 Channel& chan = serverSelector().GetServer().GetChannel( i );
942 if ( ( chan.UserExists(user.GetNick()) ) && ( chan.uidata.panel != 0 ) ) {
943 chan.uidata.panel->UserStatusUpdated( user );
944 }
945 }
946 }
947
OnBattleInfoUpdated(BattleEvents::BattleEventData data)948 void Ui::OnBattleInfoUpdated( BattleEvents::BattleEventData data )
949 {
950 IBattle& battle = *data.first;
951 const wxString& Tag = data.second;
952 if ( m_main_win == 0 ) return;
953 mw().GetBattleListTab().UpdateBattle( battle );
954 if ( mw().GetJoinTab().GetCurrentBattle() == &battle ) {
955 if ( Tag.IsEmpty() )
956 mw().GetJoinTab().UpdateCurrentBattle();
957 else
958 mw().GetJoinTab().UpdateCurrentBattle( Tag );
959 }
960 }
961
OnJoinedBattle(Battle & battle)962 void Ui::OnJoinedBattle( Battle& battle )
963 {
964 if ( m_main_win == 0 ) return;
965 mw().GetJoinTab().JoinBattle( battle );
966 mw().FocusBattleRoomTab();
967 if ( !LSL::usync().IsLoaded() ) {
968 customMessageBox(SL_MAIN_ICON, _("Your spring settings are probably not configured correctly,\nyou should take another look at your settings before trying\nto play online."), _("Spring settings error"), wxOK );
969 }
970 if ( battle.GetNatType() != NAT_None ) {
971 wxLogWarning( _T("joining game with NAT transversal") );
972 }
973 }
974
975
OnHostedBattle(Battle & battle)976 void Ui::OnHostedBattle( Battle& battle )
977 {
978 if ( m_main_win == 0 )
979 return;
980 mw().GetJoinTab().HostBattle( battle );
981 mw().FocusBattleRoomTab();
982 }
983
984
OnUserBattleStatus(IBattle & battle,User & user)985 void Ui::OnUserBattleStatus( IBattle& battle, User& user )
986 {
987 if ( m_main_win == 0 ) return;
988 mw().GetJoinTab().BattleUserUpdated( user );
989 OnBattleInfoUpdated( std::make_pair(&battle,wxString()) );
990 }
991
992
OnRequestBattleStatus(IBattle & battle)993 void Ui::OnRequestBattleStatus( IBattle& battle )
994 {
995 if ( m_main_win == 0 ) return;
996 try {
997 if ( mw().GetJoinTab().GetBattleRoomTab().GetBattle() == &battle ) {
998 mw().GetJoinTab().GetBattleRoomTab().GetBattle()->OnRequestBattleStatus();
999 }
1000 } catch (...) {}
1001 }
1002
1003
OnBattleStarted(Battle & battle)1004 void Ui::OnBattleStarted( Battle& battle )
1005 {
1006 if ( m_main_win == 0 ) return;
1007 wxLogDebugFunc( wxEmptyString );
1008 mw().GetBattleListTab().UpdateBattle( battle );
1009 }
1010
1011
OnSaidBattle(IBattle &,const wxString & nick,const wxString & msg)1012 void Ui::OnSaidBattle( IBattle& /*battle*/, const wxString& nick, const wxString& msg )
1013 {
1014 if ( m_main_win == 0 ) return;
1015 try {
1016 mw().GetJoinTab().GetBattleRoomTab().GetChatPanel().Said( nick, msg );
1017 } catch (...) {}
1018 }
1019
OnSpringTerminated(wxCommandEvent & data)1020 void Ui::OnSpringTerminated( wxCommandEvent& data )
1021 {
1022 const int exit_code = data.GetInt();
1023
1024 if ( !m_serv ) return;
1025
1026 try {
1027 serverSelector().GetServer().GetMe().Status().in_game = false;
1028 serverSelector().GetServer().GetMe().SendMyUserStatus();
1029 Battle *battle = serverSelector().GetServer().GetCurrentBattle();
1030 if ( !battle )
1031 return;
1032 if( battle->IsFounderMe() && battle->GetAutoLockOnStart() ) {
1033 battle->SetIsLocked( false );
1034 battle->SendHostInfo( IBattle::HI_Locked );
1035 }
1036 } catch ( assert_exception ) {}
1037
1038 if (exit_code != 0) {
1039 #if wxUSE_DEBUGREPORT && defined(ENABLE_DEBUG_REPORT)
1040 SpringDebugReport report;
1041 if ( wxDebugReportPreviewStd().Show( report ) )
1042 report.Process();
1043 #else
1044 if ( customMessageBox( SL_MAIN_ICON, _T("The game has crashed.\nOpen infolog.txt?"), _T("Crash"), wxYES_NO ) == wxYES )
1045 OpenFileInEditor( sett().GetCurrentUsedDataDir() + wxFileName::GetPathSeparator() + _T("infolog.txt") );
1046 #endif
1047 }
1048 }
1049
1050
OnAcceptAgreement(const wxString & agreement)1051 void Ui::OnAcceptAgreement( const wxString& agreement )
1052 {
1053 AgreementDialog dlg( m_main_win, agreement );
1054 if ( dlg.ShowModal() == 1 ) {
1055 serverSelector().GetServer().AcceptAgreement();
1056 serverSelector().GetServer().Login();
1057 }
1058 }
1059
1060
OnRing(const wxString & from)1061 void Ui::OnRing( const wxString& from )
1062 {
1063 if ( m_main_win == 0 ) return;
1064 m_main_win->RequestUserAttention();
1065
1066 if ( !wxTheApp->IsActive() ) {
1067 const wxString msg = wxFormat(_("%s:\nring!") ) % from;
1068 UiEvents::GetNotificationEventSender().SendEvent(
1069 UiEvents::NotficationData( UiEvents::ServerConnection, msg ) );
1070 }
1071
1072 #ifndef DISABLE_SOUND
1073 if ( sett().GetChatPMSoundNotificationEnabled() )
1074 sound().ring();
1075 #else
1076 wxBell();
1077 #endif
1078 }
1079
IsThisMe(User & other) const1080 bool Ui::IsThisMe(User& other) const
1081 {
1082 return IsThisMe( other.GetNick() );
1083 }
1084
IsThisMe(User * other) const1085 bool Ui::IsThisMe(User* other) const
1086 {
1087 return ( ( other != 0 ) && IsThisMe( other->GetNick() ) );
1088 }
1089
IsThisMe(const wxString & other) const1090 bool Ui::IsThisMe(const wxString& other) const
1091 {
1092 //if i'm not connected i have no identity
1093 if (!IsConnected() || m_serv==0)
1094 return false;
1095 else
1096 return ( other == serverSelector().GetServer().GetMe().GetNick() );
1097 }
1098
TestHostPort(unsigned int port) const1099 int Ui::TestHostPort( unsigned int port ) const
1100 {
1101 return serverSelector().GetServer().TestOpenPort( port );
1102 }
1103
ReloadPresetList()1104 void Ui::ReloadPresetList()
1105 {
1106 try {
1107 mw().GetSPTab().ReloadPresetList();
1108 } catch (...) {}
1109 try {
1110 mw().GetJoinTab().ReloadPresetList();
1111 } catch (...) {}
1112 }
1113
OnPresetRequiringMap(const wxString & mapname)1114 bool Ui::OnPresetRequiringMap( const wxString& mapname )
1115 {
1116 if ( wxYES == customMessageBox( SL_MAIN_ICON,
1117 _("The selected preset requires the map ") + mapname + _(". Should it be downloaded? \
1118 \n Selecting \"no\" will remove the missing map from the preset.\n\
1119 Please reselect the preset after download finished"),
1120 _("Map missing"),
1121 wxYES_NO ) ) {
1122 Download( _T("map") , mapname, wxEmptyString );
1123 return true;
1124 }
1125 return false;
1126 }
1127
OpenFileInEditor(const wxString & filepath)1128 void Ui::OpenFileInEditor( const wxString& filepath )
1129 {
1130 wxString editor_path = sett().GetEditorPath( );
1131 if ( editor_path == wxEmptyString ) {
1132 customMessageBoxNoModal( SL_MAIN_ICON, _T("You have not chosen an external text editor to open files with.\nPlease Select one now."), _T("No editor set") );
1133 mw().ShowConfigure( MainWindow::OPT_PAGE_GENERAL );
1134 return;
1135 }
1136 bool success = ( wxExecute( editor_path + _T(" \"") + filepath + _T("\""), wxEXEC_ASYNC ) != 0 );
1137 if ( !success ) {
1138 customMessageBoxNoModal( SL_MAIN_ICON, _T("There was a problem launching the editor.\nPlease make sure the path is correct and the binary executable for your user.\nNote it's currently not possible to use shell-only editors like ed, vi, etc."), _T("Problem launching editor") );
1139 mw().ShowConfigure( MainWindow::OPT_PAGE_GENERAL );
1140 }
1141 }
1142
OnInit()1143 void Ui::OnInit()
1144 {
1145 if (sett().IsFirstRun()) {
1146 FirstRunWelcome();
1147 } else {
1148 if (cfg().ReadBool(_T( "/Server/Autoconnect" ))) {
1149 Connect(); // OnConnect changes tab
1150 } else {
1151 mw().ShowTab(cfg().ReadLong(_T( "/GUI/StartTab" )));
1152 }
1153 //don't ask for updates on first run, that's a bit much for a newbie
1154 if (cfg().ReadBool(_T("/General/AutoUpdate"))) {
1155 CheckForUpdates();
1156 }
1157 }
1158 }
1159
1160
FirstRunWelcome()1161 void Ui::FirstRunWelcome()
1162 {
1163 #ifdef __WXMSW__
1164 sett().SetOldSpringLaunchMethod( true );
1165 #endif
1166
1167 wxLogMessage( _T("first time startup"));
1168 wxMessageBox( wxFormat( _("Hi %s,\nIt looks like this is your first time using %s. I have guessed a configuration that I think will work for you but you should review it, especially the Spring configuration.") )
1169 % wxGetUserName()
1170 % GetAppName(),
1171 _("Welcome"),
1172 wxOK | wxICON_INFORMATION, &mw() );
1173
1174 // copy uikeys.txt
1175 wxPathList pl;
1176 pl.AddEnvList( _T("%ProgramFiles%") );
1177 pl.AddEnvList( _T("XDG_DATA_DIRS") );
1178 pl = PathlistFactory::AdditionalSearchPaths( pl );
1179 wxString uikeyslocation = pl.FindValidPath( _T("uikeys.txt") );
1180 if ( !uikeyslocation.IsEmpty() ) {
1181 wxCopyFile( uikeyslocation, sett().GetCurrentUsedDataDir() + wxFileName::GetPathSeparator() + _T("uikeys.txt"), false );
1182 }
1183
1184 //this ensures that for new configs there's a default perspective to fall back on
1185 mw().SavePerspectives( _T("SpringLobby-default") );
1186 mw().ShowConfigure();
1187 }
1188
CheckForUpdates()1189 void Ui::CheckForUpdates()
1190 {
1191 wxString latestVersion = GetLatestVersion();
1192
1193 if (latestVersion == _T("-1")) {
1194 customMessageBoxNoModal(SL_MAIN_ICON, _("There was an error checking for the latest version.\nPlease try again later.\nIf the problem persists, please use Help->Report Bug to report this bug."), _("Error"));
1195 return;
1196 }
1197 //get current rev w/o AUX_VERSION added
1198 wxString myVersion = GetSpringLobbyVersion( false ) ;
1199
1200 wxString msg = _("Your Version: ") + myVersion + _T("\n") + _("Latest Version: ") + latestVersion;
1201 if ( !latestVersion.IsSameAs(myVersion, false) ) {
1202 #ifdef __WXMSW__
1203 int answer = customMessageBox(SL_MAIN_ICON,
1204 wxFormat( _("Your %s version is not up to date.\n\n%s\n\nWould you like for me to autodownload the new version? Changes will take effect next you launch the lobby again.") )
1205 % GetAppName()
1206 % msg,
1207 _("Not up to date"), wxYES_NO);
1208 if (answer == wxYES) {
1209 wxString command = _T("\"") + wxPathOnly( wxStandardPaths::Get().GetExecutablePath() ) + wxFileName::GetPathSeparator() + _T("springlobby_updater.exe\"");
1210 wxString params = _T("-f \"") + wxStandardPaths::Get().GetExecutablePath() + _T("\"") + _T(" -r ") + latestVersion ;
1211 if( WinExecute( command, params ) > 0 ) {
1212 //returned pid > 0 -> proc started successfully
1213 // now close this instance immeadiately
1214 wxCloseEvent dummy;
1215 ui().mw().OnClose( dummy );
1216 } else {
1217 //this will also happen if updater exe is not present so we don't really ne special check for existance of it
1218 customMessageBox(SL_MAIN_ICON, _("Automatic update failed\n\nyou will be redirected to a web page with instructions and the download link will be opened in your browser.") + msg, _("Updater error.") );
1219 OpenWebBrowser( _T("http://projects.springlobby.info/wiki/springlobby/Install#Windows-Binary") );
1220 OpenWebBrowser( GetDownloadUrl( latestVersion ) );
1221
1222 }
1223 }
1224 #else
1225 customMessageBoxNoModal(SL_MAIN_ICON, _("Your SpringLobby version is not up to date.\n\n") + msg, _("Not up to Date") );
1226 #endif
1227 }
1228 /* TODO currently not usable cause automatic update calls this function too and we don't want a msg box everytime the check succeeds
1229 else
1230 customMessageBoxNoModal(SL_MAIN_ICON, _("Your SpringLobby version is up to date.\n\n") + msg, _("Up to Date") );
1231 */
1232 }
1233
1234
OnQuit(wxCommandEvent &)1235 void Ui::OnQuit(wxCommandEvent& /*data*/)
1236 {
1237 m_disable_autoconnect = true;
1238 Disconnect();
1239 delete m_serv;
1240 m_serv = NULL;
1241 }
1242