1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: dlg_config.cpp 4474 2014-01-07 00:22:23Z russellrice $
5 //
6 // Copyright (C) 2006-2012 by The Odamex Team.
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; either version 2
11 // of the License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // DESCRIPTION:
19 //	Config dialog
20 //	AUTHOR:	Russell Rice, John D Corrado
21 //
22 //-----------------------------------------------------------------------------
23 
24 
25 #include "net_packet.h"
26 #include "dlg_config.h"
27 
28 #include <wx/settings.h>
29 #include <wx/menu.h>
30 #include <wx/statusbr.h>
31 #include <wx/msgdlg.h>
32 #include <wx/wfstream.h>
33 #include <wx/tokenzr.h>
34 #include <wx/recguard.h>
35 
36 #include "main.h"
37 
38 // Event table for widgets
BEGIN_EVENT_TABLE(dlgConfig,wxDialog)39 BEGIN_EVENT_TABLE(dlgConfig,wxDialog)
40 
41 	// Button events
42 	EVT_BUTTON(XRCID("Id_BtnCtrlAddDir"), dlgConfig::OnAddDir)
43 	EVT_BUTTON(XRCID("Id_BtnCtrlReplaceDir"), dlgConfig::OnReplaceDir)
44 	EVT_BUTTON(XRCID("Id_BtnCtrlDeleteDir"), dlgConfig::OnDeleteDir)
45     EVT_BUTTON(XRCID("Id_BtnCtrlMoveDirUp"), dlgConfig::OnUpClick)
46     EVT_BUTTON(XRCID("Id_BtnCtrlMoveDirDown"), dlgConfig::OnDownClick)
47 
48     EVT_BUTTON(XRCID("Id_BtnCtrlGetEnvironment"), dlgConfig::OnGetEnvClick)
49 
50 	EVT_BUTTON(wxID_OK, dlgConfig::OnOK)
51 
52     EVT_DIRPICKER_CHANGED(XRCID("Id_DirCtrlChooseOdamexPath"), dlgConfig::OnChooseOdamexPath)
53 
54 	// Misc events
55 	EVT_CHECKBOX(XRCID("Id_ChkCtrlGetListOnStart"), dlgConfig::OnCheckedBox)
56 	EVT_CHECKBOX(XRCID("Id_ChkCtrlShowBlockedServers"), dlgConfig::OnCheckedBox)
57 	EVT_CHECKBOX(XRCID("Id_ChkCtrlEnableBroadcasts"), dlgConfig::OnCheckedBox)
58 
59 	EVT_TEXT(XRCID("Id_SpnCtrlMasterTimeout"), dlgConfig::OnTextChange)
60 	EVT_TEXT(XRCID("Id_SpnCtrlServerTimeout"), dlgConfig::OnTextChange)
61 	EVT_TEXT(XRCID("Id_SpnCtrlRetry"), dlgConfig::OnTextChange)
62 	EVT_TEXT(XRCID("Id_TxtCtrlExtraCmdLineArgs"), dlgConfig::OnTextChange)
63 
64 	EVT_SPINCTRL(XRCID("Id_SpnCtrlPQGood"), dlgConfig::OnSpinValChange)
65 	EVT_SPINCTRL(XRCID("Id_SpnCtrlPQPlayable"), dlgConfig::OnSpinValChange)
66 	EVT_SPINCTRL(XRCID("Id_SpnCtrlPQLaggy"), dlgConfig::OnSpinValChange)
67 
68 	EVT_LISTBOX_DCLICK(XRCID("Id_LstCtrlWadDirectories"), dlgConfig::OnReplaceDir)
69 END_EVENT_TABLE()
70 
71 // Window constructor
72 dlgConfig::dlgConfig(launchercfg_t *cfg, wxWindow *parent, wxWindowID id)
73 {
74     // Set up the dialog and its widgets
75     wxXmlResource::Get()->LoadDialog(this, parent, _T("dlgConfig"));
76 
77     m_ChkCtrlGetListOnStart = XRCCTRL(*this, "Id_ChkCtrlGetListOnStart", wxCheckBox);
78     m_ChkCtrlShowBlockedServers = XRCCTRL(*this, "Id_ChkCtrlShowBlockedServers", wxCheckBox);
79     m_ChkCtrlEnableBroadcasts = XRCCTRL(*this, "Id_ChkCtrlEnableBroadcasts", wxCheckBox);
80 
81     m_LstCtrlWadDirectories = XRCCTRL(*this, "Id_LstCtrlWadDirectories", wxListBox);
82 
83     m_DirCtrlChooseOdamexPath = XRCCTRL(*this, "Id_DirCtrlChooseOdamexPath", wxDirPickerCtrl);
84 
85     m_SpnCtrlMasterTimeout = XRCCTRL(*this, "Id_SpnCtrlMasterTimeout", wxSpinCtrl);
86     m_SpnCtrlServerTimeout = XRCCTRL(*this, "Id_SpnCtrlServerTimeout", wxSpinCtrl);
87     m_SpnCtrlRetry = XRCCTRL(*this, "Id_SpnCtrlRetry", wxSpinCtrl);
88     m_TxtCtrlExtraCmdLineArgs = XRCCTRL(*this, "Id_TxtCtrlExtraCmdLineArgs", wxTextCtrl);
89 
90     m_SpnCtrlPQGood = XRCCTRL(*this, "Id_SpnCtrlPQGood", wxSpinCtrl);
91     m_SpnCtrlPQPlayable = XRCCTRL(*this, "Id_SpnCtrlPQPlayable", wxSpinCtrl);
92     m_SpnCtrlPQLaggy = XRCCTRL(*this, "Id_SpnCtrlPQLaggy", wxSpinCtrl);
93 
94     m_StcBmpPQGood = XRCCTRL(*this, "Id_StcBmpPQGood", wxStaticBitmap);
95     m_StcBmpPQPlayable = XRCCTRL(*this, "Id_StcBmpPQPlayable", wxStaticBitmap);
96     m_StcBmpPQLaggy = XRCCTRL(*this, "Id_StcBmpPQLaggy", wxStaticBitmap);
97     m_StcBmpPQBad = XRCCTRL(*this, "Id_StcBmpPQBad", wxStaticBitmap);
98 
99     // Ping quality icons
100     m_StcBmpPQGood->SetBitmap(wxXmlResource::Get()->LoadBitmap(wxT("bullet_green")));
101     m_StcBmpPQPlayable->SetBitmap(wxXmlResource::Get()->LoadBitmap(wxT("bullet_orange")));
102     m_StcBmpPQLaggy->SetBitmap(wxXmlResource::Get()->LoadBitmap(wxT("bullet_red")));
103     m_StcBmpPQBad->SetBitmap(wxXmlResource::Get()->LoadBitmap(wxT("bullet_gray")));
104 
105     // Load current configuration from global configuration structure
106     cfg_file = cfg;
107 
108     LoadSettings();
109 }
110 
111 // Window destructor
~dlgConfig()112 dlgConfig::~dlgConfig()
113 {
114 
115 }
116 
Show()117 void dlgConfig::Show()
118 {
119     m_ChkCtrlGetListOnStart->SetValue(cfg_file->get_list_on_start);
120     m_ChkCtrlShowBlockedServers->SetValue(cfg_file->show_blocked_servers);
121 
122     // Load wad path list
123     m_LstCtrlWadDirectories->Clear();
124 
125     wxStringTokenizer wadlist(cfg_file->wad_paths, _T(PATH_DELIMITER));
126 
127     while (wadlist.HasMoreTokens())
128     {
129         wxString path = wadlist.GetNextToken();
130 
131         #ifdef __WXMSW__
132         path.Replace(_T("\\\\"),_T("\\"), true);
133         #else
134         path.Replace(_T("////"),_T("//"), true);
135         #endif
136 
137         m_LstCtrlWadDirectories->AppendString(path);
138     }
139 
140     m_DirCtrlChooseOdamexPath->SetPath(cfg_file->odamex_directory);
141 
142     wxString MasterTimeout, ServerTimeout, RetryCount, ExtraCmdLineArgs;
143 
144     ConfigInfo.Read(wxT(MASTERTIMEOUT), &MasterTimeout, wxT("500"));
145     ConfigInfo.Read(wxT(SERVERTIMEOUT), &ServerTimeout, wxT("1000"));
146     ConfigInfo.Read(wxT(RETRYCOUNT), &RetryCount, wxT("2"));
147     ConfigInfo.Read(wxT(EXTRACMDLINEARGS), &ExtraCmdLineArgs, wxT(""));
148 
149     m_SpnCtrlMasterTimeout->SetValue(MasterTimeout);
150     m_SpnCtrlServerTimeout->SetValue(ServerTimeout);
151     m_SpnCtrlRetry->SetValue(RetryCount);
152     m_TxtCtrlExtraCmdLineArgs->SetValue(ExtraCmdLineArgs);
153 
154     wxInt32 PQGood, PQPlayable, PQLaggy;
155 
156     ConfigInfo.Read(wxT("IconPingQualityGood"), &PQGood, 150);
157     ConfigInfo.Read(wxT("IconPingQualityPlayable"), &PQPlayable, 300);
158     ConfigInfo.Read(wxT("IconPingQualityLaggy"), &PQLaggy, 350);
159 
160     m_SpnCtrlPQGood->SetValue(PQGood);
161     m_SpnCtrlPQPlayable->SetValue(PQPlayable);
162     m_SpnCtrlPQLaggy->SetValue(PQLaggy);
163 
164     UserChangedSetting = false;
165 
166     ShowModal();
167 }
168 
OnCheckedBox(wxCommandEvent & event)169 void dlgConfig::OnCheckedBox(wxCommandEvent &event)
170 {
171     UserChangedSetting = true;
172 }
173 
OnChooseOdamexPath(wxFileDirPickerEvent & event)174 void dlgConfig::OnChooseOdamexPath(wxFileDirPickerEvent &event)
175 {
176     UserChangedSetting = true;
177 }
178 
179 // Ping quality spin control changes
OnSpinValChange(wxSpinEvent & event)180 void dlgConfig::OnSpinValChange(wxSpinEvent &event)
181 {
182     wxInt32 PQGood, PQPlayable, PQLaggy;
183 
184     wxSpinCtrl *SpinControl = wxDynamicCast(event.GetEventObject(), wxSpinCtrl);
185 
186     if (!SpinControl)
187         return;
188 
189 
190     if (SpinControl == m_SpnCtrlPQGood)
191         PQGood = m_SpnCtrlPQGood->GetValue();
192 
193     if (SpinControl == m_SpnCtrlPQPlayable)
194         PQPlayable = m_SpnCtrlPQPlayable->GetValue();
195 
196     // Handle spin values that go beyond a certain range
197     // wxWidgets Bug: Double-clicking the down arrow on a spin control will go
198     // 1 more below even though we force it not to, we use an event so we
199     // counteract this with using +2 stepping
200     if (PQGood >= PQPlayable)
201     {
202         if (SpinControl == m_SpnCtrlPQPlayable)
203             m_SpnCtrlPQPlayable->SetValue(PQGood + 2);
204     }
205 
206     if (SpinControl == m_SpnCtrlPQPlayable)
207         PQPlayable = m_SpnCtrlPQPlayable->GetValue();
208     if (SpinControl == m_SpnCtrlPQLaggy)
209         PQLaggy = m_SpnCtrlPQLaggy->GetValue();
210 
211     if (PQPlayable >= PQLaggy)
212     {
213         if (SpinControl == m_SpnCtrlPQLaggy)
214             m_SpnCtrlPQLaggy->SetValue(PQPlayable + 2);
215     }
216 
217     UserChangedSetting = true;
218 }
219 
220 // User pressed ok button
OnOK(wxCommandEvent & event)221 void dlgConfig::OnOK(wxCommandEvent &event)
222 {
223     wxMessageDialog msgdlg(this, _T("Save settings?"), _T("Save settings?"),
224                            wxYES_NO | wxICON_QUESTION | wxSTAY_ON_TOP);
225 
226     if (UserChangedSetting == false)
227     {
228         Close();
229 
230         return;
231     }
232 
233     if (msgdlg.ShowModal() == wxID_YES)
234     {
235         // reset 'dirty' flag
236         UserChangedSetting = false;
237 
238         // Store data into global launcher configuration structure
239         cfg_file->get_list_on_start = m_ChkCtrlGetListOnStart->GetValue();
240         cfg_file->show_blocked_servers = m_ChkCtrlShowBlockedServers->GetValue();
241 
242         cfg_file->wad_paths = _T("");
243 
244         if (m_LstCtrlWadDirectories->GetCount() > 0)
245             for (wxUint32 i = 0; i < m_LstCtrlWadDirectories->GetCount(); i++)
246                 cfg_file->wad_paths.Append(m_LstCtrlWadDirectories->GetString(i) + _T(PATH_DELIMITER));
247 
248         cfg_file->odamex_directory = m_DirCtrlChooseOdamexPath->GetPath();
249 
250         // Save settings to configuration file
251         SaveSettings();
252     }
253     else
254         UserChangedSetting = false;
255 
256     // Close window
257     Close();
258 }
259 
OnTextChange(wxCommandEvent & event)260 void dlgConfig::OnTextChange(wxCommandEvent &event)
261 {
262     UserChangedSetting = true;
263 }
264 
265 /*
266     WAD Directory stuff
267 */
268 
269 // Add a directory to the listbox
OnAddDir(wxCommandEvent & event)270 void dlgConfig::OnAddDir(wxCommandEvent &event)
271 {
272     wxString WadDirectory;
273 
274     wxDirDialog ChooseWadDialog(this,
275         wxT("Select a directory containing WAD files"));
276 
277     if (ChooseWadDialog.ShowModal() != wxID_OK)
278         return;
279 
280     WadDirectory = ChooseWadDialog.GetPath();
281 
282     // Check to see if the path exists on the system
283     if (wxDirExists(WadDirectory))
284     {
285         // Check if path already exists in box
286         if (m_LstCtrlWadDirectories->FindString(WadDirectory) == wxNOT_FOUND)
287         {
288             m_LstCtrlWadDirectories->Append(WadDirectory);
289 
290             UserChangedSetting = true;
291         }
292     }
293     else
294         wxMessageBox(wxString::Format(_T("Directory %s not found"),
295                 WadDirectory.c_str()));
296 }
297 
298 // Replace a directory in the listbox
OnReplaceDir(wxCommandEvent & event)299 void dlgConfig::OnReplaceDir(wxCommandEvent &event)
300 {
301     wxInt32 i = m_LstCtrlWadDirectories->GetSelection();
302 
303     wxString WadDirectory;
304 
305     if (i == wxNOT_FOUND)
306     {
307         wxMessageBox(_T("Select a directory from the list to replace"));
308 
309         return;
310     }
311 
312     WadDirectory = m_LstCtrlWadDirectories->GetStringSelection();
313 
314     wxDirDialog ChooseWadDialog(this,
315                                 wxT("Replace selected directory with.."),
316                                 WadDirectory);
317 
318     if (ChooseWadDialog.ShowModal() != wxID_OK)
319         return;
320 
321     WadDirectory = ChooseWadDialog.GetPath();
322 
323     // Check to see if the path exists on the system
324     if (wxDirExists(WadDirectory))
325     {
326         // Get the selected item and replace it
327         m_LstCtrlWadDirectories->SetString(i, WadDirectory);
328 
329         UserChangedSetting = true;
330     }
331     else
332         wxMessageBox(wxString::Format(_T("Directory %s not found"),
333                 WadDirectory.c_str()));
334 }
335 
336 // Delete a directory from the listbox
OnDeleteDir(wxCommandEvent & event)337 void dlgConfig::OnDeleteDir(wxCommandEvent &event)
338 {
339     // Get the selected item and delete it, if
340     // it is selected.
341     wxInt32 i = m_LstCtrlWadDirectories->GetSelection();
342 
343     if (i != wxNOT_FOUND)
344     {
345         m_LstCtrlWadDirectories->Delete(i);
346 
347         UserChangedSetting = true;
348     }
349     else
350         wxMessageBox(_T("Select a directory from the list to delete"));
351 }
352 
353 // Move directory in list up 1 item
OnUpClick(wxCommandEvent & event)354 void dlgConfig::OnUpClick(wxCommandEvent &event)
355 {
356     // Get the selected item
357     wxInt32 i = m_LstCtrlWadDirectories->GetSelection();
358 
359     if ((i != wxNOT_FOUND) && (i > 0))
360     {
361         wxString str = m_LstCtrlWadDirectories->GetString(i);
362 
363         m_LstCtrlWadDirectories->Delete(i);
364 
365         m_LstCtrlWadDirectories->Insert(str, i - 1);
366 
367         m_LstCtrlWadDirectories->SetSelection(i - 1);
368 
369         UserChangedSetting = true;
370     }
371 }
372 
373 // Move directory in list down 1 item
OnDownClick(wxCommandEvent & event)374 void dlgConfig::OnDownClick(wxCommandEvent &event)
375 {
376     // Get the selected item
377     wxInt32 i = m_LstCtrlWadDirectories->GetSelection();
378 
379     if ((i != wxNOT_FOUND) && (i + 1 < m_LstCtrlWadDirectories->GetCount()))
380     {
381         wxString str = m_LstCtrlWadDirectories->GetString(i);
382 
383         m_LstCtrlWadDirectories->Delete(i);
384 
385         m_LstCtrlWadDirectories->Insert(str, i + 1);
386 
387         m_LstCtrlWadDirectories->SetSelection(i + 1);
388 
389         UserChangedSetting = true;
390     }
391 }
392 
393 // Get the environment variables
OnGetEnvClick(wxCommandEvent & event)394 void dlgConfig::OnGetEnvClick(wxCommandEvent &event)
395 {
396     wxString doomwaddir = _T("");
397     wxString env_paths[NUM_ENVVARS];
398     wxInt32 i = 0;
399 
400     // create a small list of paths
401     for (i = 0; i < NUM_ENVVARS; i++)
402     {
403         // only add paths if the variable exists and path isn't blank
404         if (wxGetEnv(env_vars[i], &env_paths[i]))
405             if (!env_paths[i].IsEmpty())
406                 doomwaddir += env_paths[i] + _T(PATH_DELIMITER);
407     }
408 
409     wxInt32 path_count = 0;
410 
411     wxStringTokenizer wadlist(doomwaddir, _T(PATH_DELIMITER));
412 
413     while (wadlist.HasMoreTokens())
414     {
415         wxString path = wadlist.GetNextToken();
416 
417         // make sure the path doesn't already exist in the list box
418         if (m_LstCtrlWadDirectories->FindString(path) == wxNOT_FOUND)
419         {
420                 m_LstCtrlWadDirectories->Append(path);
421 
422                 path_count++;
423         }
424     }
425 
426     if (path_count)
427     {
428         wxMessageBox(_T("Environment variables import successful"));
429 
430         UserChangedSetting = true;
431     }
432     else
433         wxMessageBox(_T("Environment variables contains paths that have been already imported."));
434 
435 }
436 
437 // Load settings from configuration file
LoadSettings()438 void dlgConfig::LoadSettings()
439 {
440     bool UseBroadcast;
441 
442     // Allow $ in directory names
443     ConfigInfo.SetExpandEnvVars(false);
444 
445     ConfigInfo.Read(wxT(USEBROADCAST), &UseBroadcast, false);
446 
447     m_ChkCtrlEnableBroadcasts->SetValue(UseBroadcast);
448 
449     ConfigInfo.Read(_T(GETLISTONSTART), &cfg_file->get_list_on_start, 1);
450     ConfigInfo.Read(_T(SHOWBLOCKEDSERVERS), &cfg_file->show_blocked_servers, cfg_file->show_blocked_servers);
451 	cfg_file->wad_paths = ConfigInfo.Read(_T(DELIMWADPATHS), cfg_file->wad_paths);
452 	cfg_file->odamex_directory = ConfigInfo.Read(_T(ODAMEX_DIRECTORY), cfg_file->odamex_directory);
453 }
454 
455 // Save settings to configuration file
SaveSettings()456 void dlgConfig::SaveSettings()
457 {
458     ConfigInfo.Write(wxT(MASTERTIMEOUT), m_SpnCtrlMasterTimeout->GetValue());
459     ConfigInfo.Write(wxT(SERVERTIMEOUT), m_SpnCtrlServerTimeout->GetValue());
460     ConfigInfo.Write(wxT(RETRYCOUNT), m_SpnCtrlRetry->GetValue());
461     ConfigInfo.Write(wxT(EXTRACMDLINEARGS), m_TxtCtrlExtraCmdLineArgs->GetValue());
462     ConfigInfo.Write(wxT(GETLISTONSTART), cfg_file->get_list_on_start);
463 	ConfigInfo.Write(wxT(SHOWBLOCKEDSERVERS), cfg_file->show_blocked_servers);
464 	ConfigInfo.Write(wxT(DELIMWADPATHS), cfg_file->wad_paths);
465     ConfigInfo.Write(wxT(ODAMEX_DIRECTORY), cfg_file->odamex_directory);
466     ConfigInfo.Write(wxT("IconPingQualityGood"), m_SpnCtrlPQGood->GetValue());
467     ConfigInfo.Write(wxT("IconPingQualityPlayable"), m_SpnCtrlPQPlayable->GetValue());
468     ConfigInfo.Write(wxT("IconPingQualityLaggy"), m_SpnCtrlPQLaggy->GetValue());
469     ConfigInfo.Write(wxT(USEBROADCAST), m_ChkCtrlEnableBroadcasts->GetValue());
470 
471 	ConfigInfo.Flush();
472 }
473