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