1 // This file is part of BOINC.
2 // http://boinc.berkeley.edu
3 // Copyright (C) 2015 University of California
4 //
5 // BOINC is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License
7 // as published by the Free Software Foundation,
8 // either version 3 of the License, or (at your option) any later version.
9 //
10 // BOINC is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with BOINC. If not, see <http://www.gnu.org/licenses/>.
17 //
18 #if defined(__GNUG__) && !defined(__APPLE__)
19 #pragma implementation "DlgAdvPreferences.h"
20 #endif
21
22 #include "stdwx.h"
23 #include "BOINCGUIApp.h"
24 #include "MainDocument.h"
25 #include "BOINCBaseFrame.h"
26 #include "SkinManager.h"
27 #include "Events.h"
28 #include "error_numbers.h"
29 #include "version.h"
30 #include "DlgAdvPreferences.h"
31
32 #include "res/usage.xpm"
33 #include "res/xfer.xpm"
34 #include "res/proj.xpm"
35 #include "res/clock.xpm"
36 #include "res/warning.xpm"
37
38
39 using std::string;
40
IMPLEMENT_DYNAMIC_CLASS(CDlgAdvPreferences,wxDialog)41 IMPLEMENT_DYNAMIC_CLASS(CDlgAdvPreferences, wxDialog)
42
43 BEGIN_EVENT_TABLE(CDlgAdvPreferences, wxDialog)
44 EVT_COMMAND_RANGE(ID_ADV_PREFS_START,ID_ADV_PREFS_LAST,wxEVT_COMMAND_CHECKBOX_CLICKED,CDlgAdvPreferences::OnHandleCommandEvent)
45 //buttons
46 EVT_BUTTON(wxID_OK,CDlgAdvPreferences::OnOK)
47 EVT_BUTTON(ID_HELPBOINC,CDlgAdvPreferences::OnHelp)
48 EVT_BUTTON(ID_BTN_CLEAR,CDlgAdvPreferences::OnClear)
49 END_EVENT_TABLE()
50
51 /* Constructor */
52 CDlgAdvPreferences::CDlgAdvPreferences(wxWindow* parent) : CDlgAdvPreferencesBase(parent,ID_ANYDIALOG) {
53 m_arrTabPageIds.Add(ID_TABPAGE_PROC);
54 m_arrTabPageIds.Add(ID_TABPAGE_NET);
55 m_arrTabPageIds.Add(ID_TABPAGE_DISK);
56 m_arrTabPageIds.Add(ID_TABPAGE_SCHED);
57
58 //setting tab page images (not handled by generated code)
59 int iImageIndex = 0;
60 wxImageList* pImageList = m_Notebook->GetImageList();
61 if (!pImageList) {
62 pImageList = new wxImageList(ADJUSTFORXDPI(16), ADJUSTFORYDPI(16), true, 0);
63 wxASSERT(pImageList != NULL);
64 m_Notebook->SetImageList(pImageList);
65 }
66 iImageIndex = pImageList->Add(GetScaledBitmapFromXPMData(proj_xpm));
67 m_Notebook->SetPageImage(0,iImageIndex);
68
69 iImageIndex = pImageList->Add(GetScaledBitmapFromXPMData(xfer_xpm));
70 m_Notebook->SetPageImage(1,iImageIndex);
71
72 iImageIndex = pImageList->Add(GetScaledBitmapFromXPMData(usage_xpm));
73 m_Notebook->SetPageImage(2,iImageIndex);
74
75 iImageIndex = pImageList->Add(GetScaledBitmapFromXPMData(clock_xpm));
76 m_Notebook->SetPageImage(3,iImageIndex);
77
78 //setting warning bitmap
79 if (m_bmpWarning) {
80 m_bmpWarning->SetBitmap(GetScaledBitmapFromXPMData(warning_xpm));
81 }
82
83 wxCheckBox* proc_cb[] = {m_chkProcSunday,m_chkProcMonday,m_chkProcTuesday,m_chkProcWednesday,m_chkProcThursday,m_chkProcFriday,m_chkProcSaturday};
84 wxTextCtrl* proc_tstarts[] = {m_txtProcSundayStart,m_txtProcMondayStart,m_txtProcTuesdayStart,m_txtProcWednesdayStart,m_txtProcThursdayStart,m_txtProcFridayStart,m_txtProcSaturdayStart};
85 wxTextCtrl* proc_tstops[] = {m_txtProcSundayStop,m_txtProcMondayStop,m_txtProcTuesdayStop,m_txtProcWednesdayStop,m_txtProcThursdayStop,m_txtProcFridayStop,m_txtProcSaturdayStop};
86 wxCheckBox* net_cb[] = {m_chkNetSunday,m_chkNetMonday,m_chkNetTuesday,m_chkNetWednesday,m_chkNetThursday,m_chkNetFriday,m_chkNetSaturday};
87 wxTextCtrl* net_tstarts[] = {m_txtNetSundayStart,m_txtNetMondayStart,m_txtNetTuesdayStart,m_txtNetWednesdayStart,m_txtNetThursdayStart,m_txtNetFridayStart,m_txtNetSaturdayStart};
88 wxTextCtrl* net_tstops[] = {m_txtNetSundayStop,m_txtNetMondayStop,m_txtNetTuesdayStop,m_txtNetWednesdayStop,m_txtNetThursdayStop,m_txtNetFridayStop,m_txtNetSaturdayStop};
89 for (int i=0; i<7; ++i) {
90 procDayChks[i] = proc_cb[i];
91 procDayStartTxts[i] = proc_tstarts[i];
92 procDayStopTxts[i] = proc_tstops[i];
93 netDayChks[i] = net_cb[i];
94 netDayStartTxts[i] = net_tstarts[i];
95 netDayStopTxts[i] = net_tstops[i];
96 }
97
98 // init special tooltips
99 SetSpecialTooltips();
100 //setting the validators for correct input handling
101 SetValidators();
102 //read in settings and initialize controls
103 ReadPreferenceSettings();
104
105 lastErrorCtrl = NULL;
106 stdTextBkgdColor = *wxWHITE;
107
108 if (! m_bOKToShow) return;
109
110 // Get default preference values
111 defaultPrefs.enabled_defaults();
112 //
113 RestoreState();
114
115 #ifdef __WXMSW__
116 int tabStart = 0, tabwidth = 0;
117 RECT r;
118 BOOL success = TabCtrl_GetItemRect(m_Notebook->GetHWND(), 0, &r);
119 if (success) {
120 tabStart = r.left;
121 }
122
123 success = TabCtrl_GetItemRect(m_Notebook->GetHWND(), m_Notebook->GetPageCount()-1, &r);
124 if (success) {
125 tabwidth = r.right - tabStart + ADJUSTFORXDPI(4);
126 }
127 wxSize sz = m_Notebook->GetBestSize();
128 if (sz.x < tabwidth) {
129 sz.x = tabwidth;
130 m_Notebook->SetMinSize(sz);
131 }
132 #endif
133 Layout();
134 Fit();
135 Centre();
136 }
137
138 /* destructor */
~CDlgAdvPreferences()139 CDlgAdvPreferences::~CDlgAdvPreferences() {
140 if (m_bOKToShow) {
141 SaveState();
142 }
143 delete m_vTimeValidator;
144 }
145
146 /* set validators for input filtering purposes only */
SetValidators()147 void CDlgAdvPreferences::SetValidators() {
148 m_vTimeValidator = new wxTextValidator(wxFILTER_INCLUDE_CHAR_LIST);
149 m_vTimeValidator->SetCharIncludes(wxT("0123456789:"));
150
151 // ######### proc usage page
152 m_txtProcUseProcessors->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
153 m_txtProcUseCPUTime->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
154
155 m_txtProcIdleFor->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
156 m_txtMaxLoad->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
157
158 m_txtNetConnectInterval->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
159 m_txtNetAdditionalDays->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
160 m_txtProcSwitchEvery->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
161 m_txtDiskWriteToDisk->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
162
163 // ######### net usage page
164 m_txtNetDownloadRate->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
165 m_txt_daily_xfer_limit_mb->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
166 m_txt_daily_xfer_period_days->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
167 m_txtNetUploadRate->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
168
169 // ######### disk and memory page
170 m_txtDiskMaxSpace->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
171 m_txtDiskLeastFree->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
172 m_txtDiskMaxOfTotal->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
173 m_txtMemoryMaxInUse->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
174 m_txtMemoryMaxOnIdle->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
175 m_txtDiskMaxSwap->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
176
177 // ######### daily schedules page
178 m_txtProcEveryDayStart->SetValidator(*m_vTimeValidator);
179 m_txtProcEveryDayStop->SetValidator(*m_vTimeValidator);
180
181 m_txtNetEveryDayStart->SetValidator(*m_vTimeValidator);
182 m_txtNetEveryDayStop->SetValidator(*m_vTimeValidator);
183
184 for (int i=0; i<7; ++i) {
185 procDayStartTxts[i]->SetValidator(*m_vTimeValidator);
186 procDayStopTxts[i]->SetValidator(*m_vTimeValidator);
187 netDayStartTxts[i]->SetValidator(*m_vTimeValidator);
188 netDayStopTxts[i]->SetValidator(*m_vTimeValidator);
189 }
190 }
191
192 /* some controls share the same tooltip, set them here */
SetSpecialTooltips()193 void CDlgAdvPreferences::SetSpecialTooltips() {
194 wxString procDaysTimeTT(PROC_DAY_OF_WEEK_TOOLTIP_TEXT);
195 wxString netDaysTimeTT(NET_DAY_OF_WEEK_TOOLTIP_TEXT);
196 for (int i=0; i<7; ++i) {
197 procDayChks[i]->SetToolTip(procDaysTimeTT);
198 procDayStartTxts[i]->SetToolTip(procDaysTimeTT);
199 procDayStopTxts[i]->SetToolTip(procDaysTimeTT);
200 netDayChks[i]->SetToolTip(netDaysTimeTT);
201 netDayStartTxts[i]->SetToolTip(netDaysTimeTT);
202 netDayStopTxts[i]->SetToolTip(netDaysTimeTT);
203 }
204 }
205
206 /* saves selected tab page */
SaveState()207 bool CDlgAdvPreferences::SaveState() {
208 wxString strBaseConfigLocation = wxString(wxT("/DlgAdvPreferences/"));
209 wxConfigBase* pConfig = wxConfigBase::Get(FALSE);
210
211 wxASSERT(pConfig);
212 if (!pConfig) return false;
213
214 pConfig->SetPath(strBaseConfigLocation);
215 pConfig->Write(wxT("CurrentPage"),m_Notebook->GetSelection());
216
217 pConfig->Flush();
218
219 return true;
220 }
221
222 /* restores former selected tab page */
RestoreState()223 bool CDlgAdvPreferences::RestoreState() {
224 wxString strBaseConfigLocation = wxString(wxT("/DlgAdvPreferences/"));
225 wxConfigBase* pConfig = wxConfigBase::Get(FALSE);
226 int p;
227
228 wxASSERT(pConfig);
229
230 if (!pConfig) return false;
231
232 pConfig->SetPath(strBaseConfigLocation);
233
234 pConfig->Read(wxT("CurrentPage"), &p,0);
235 m_Notebook->SetSelection(p);
236
237 return true;
238 }
239
240 // convert a Timestring HH:MM into a double
TimeStringToDouble(wxString timeStr)241 double CDlgAdvPreferences::TimeStringToDouble(wxString timeStr) {
242 double hour;
243 double minutes;
244 timeStr.SubString(0,timeStr.First(':')).ToDouble(&hour);
245 timeStr.SubString(timeStr.First(':')+1,timeStr.Length()).ToDouble(&minutes);
246 minutes = minutes/60.0;
247 return hour + minutes;
248 }
249
250 // convert a double into a timestring HH:MM
DoubleToTimeString(double dt)251 wxString CDlgAdvPreferences::DoubleToTimeString(double dt) {
252 int hour = (int)dt;
253 int minutes = (int)(60.0 * (dt - hour)+.5);
254 return wxString::Format(wxT("%02d:%02d"),hour,minutes);
255 }
256
257
258 // We only display 2 places past the decimal, so restrict the
259 // precision of saved values to .01. This prevents unexpected
260 // behavior when, for example, a zero value means no restriction
261 // and the value is displayed as 0.00 but is actually 0.001.
RoundToHundredths(double td)262 double CDlgAdvPreferences::RoundToHundredths(double td) {
263 int i = (int)((td + .005) * 100.);
264 return ((double)(i) / 100.);
265 }
266
DisplayValue(double value,wxTextCtrl * textCtrl,wxCheckBox * checkBox)267 void CDlgAdvPreferences::DisplayValue(double value, wxTextCtrl* textCtrl, wxCheckBox* checkBox) {
268 wxString buffer;
269
270 wxASSERT(textCtrl);
271
272 if (checkBox) {
273 if (! checkBox->IsChecked()) {
274 textCtrl->Clear();
275 textCtrl->Disable();
276 return;
277 }
278 }
279 buffer.Printf(wxT("%g"), value);
280 textCtrl->ChangeValue(buffer);
281 textCtrl->Enable();
282 }
283
284
285 /* read preferences from core client and initialize control values */
ReadPreferenceSettings()286 void CDlgAdvPreferences::ReadPreferenceSettings() {
287 CMainDocument* pDoc = wxGetApp().GetDocument();
288 int retval;
289
290 wxASSERT(pDoc);
291 wxASSERT(wxDynamicCast(pDoc, CMainDocument));
292
293 // Get current working preferences (including any overrides) from client
294 retval = pDoc->rpc.get_global_prefs_working_struct(prefs, mask);
295 if (retval == ERR_NOT_FOUND) {
296 // Older clients don't support get_global_prefs_working_struct RPC
297 prefs = pDoc->state.global_prefs;
298 retval = pDoc->rpc.get_global_prefs_override_struct(prefs, mask);
299 }
300 if (retval) {
301 m_bOKToShow = false;
302 return;
303 }
304
305 m_bOKToShow = true;
306
307 // ######### proc usage page
308 // max cpus
309 // 0 means "no retriction" but we don't use a checkbox here
310 if (prefs.max_ncpus_pct == 0.0) prefs.max_ncpus_pct = 100.0;
311 DisplayValue(prefs.max_ncpus_pct, m_txtProcUseProcessors);
312
313 //cpu limit
314 // 0 means "no retriction" but we don't use a checkbox here
315 if (prefs.cpu_usage_limit == 0.0) prefs.cpu_usage_limit = 100.0;
316 DisplayValue(prefs.cpu_usage_limit, m_txtProcUseCPUTime);
317
318 // on batteries
319 m_chkProcOnBatteries->SetValue(! prefs.run_on_batteries);
320
321 // in use
322 m_chkProcInUse->SetValue(! prefs.run_if_user_active);
323 m_chkGPUProcInUse->SetValue(! prefs.run_gpu_if_user_active);
324
325 //"Suspend while computer in use" implies "Suspend GPU while computer in use" so set
326 // and disable "Suspend GPU ..." checkbox, overriding its saved value if necessary.
327 if (m_chkProcInUse->IsChecked()) {
328 m_chkGPUProcInUse->SetValue(true);
329 m_chkGPUProcInUse->Disable();
330 }
331
332 // idle for X minutes
333 if (m_chkProcInUse->IsChecked() || m_chkGPUProcInUse->IsChecked()) {
334 m_txtProcIdleFor->Enable();
335 DisplayValue(prefs.idle_time_to_run, m_txtProcIdleFor);
336 } else {
337 m_txtProcIdleFor->Clear();
338 m_txtProcIdleFor->Disable();
339 }
340
341 m_chkMaxLoad->SetValue(prefs.suspend_cpu_usage > 0.0);
342 DisplayValue(prefs.suspend_cpu_usage, m_txtMaxLoad, m_chkMaxLoad);
343
344 // connection interval
345 DisplayValue(prefs.work_buf_min_days, m_txtNetConnectInterval);
346
347 DisplayValue(prefs.work_buf_additional_days, m_txtNetAdditionalDays);
348
349 // switch every X minutes
350 DisplayValue(prefs.cpu_scheduling_period_minutes, m_txtProcSwitchEvery);
351
352 // write to disk every X seconds
353 DisplayValue(prefs.disk_interval, m_txtDiskWriteToDisk);
354
355 // ######### net usage page
356
357 //download rate
358 m_chkNetDownloadRate->SetValue(prefs.max_bytes_sec_down > 0.0);
359 DisplayValue((prefs.max_bytes_sec_down / 1024), m_txtNetDownloadRate, m_chkNetDownloadRate);
360
361
362 // upload rate
363 m_chkNetUploadRate->SetValue(prefs.max_bytes_sec_up > 0.0);
364 DisplayValue((prefs.max_bytes_sec_up / 1024), m_txtNetUploadRate, m_chkNetUploadRate);
365
366 m_chk_daily_xfer_limit->SetValue((prefs.daily_xfer_limit_mb > 0.0) && (prefs.daily_xfer_period_days > 0.0));
367 DisplayValue(prefs.daily_xfer_limit_mb, m_txt_daily_xfer_limit_mb, m_chk_daily_xfer_limit);
368 DisplayValue(prefs.daily_xfer_period_days, m_txt_daily_xfer_period_days, m_chk_daily_xfer_limit);
369
370 //
371 // skip image verification
372 m_chkNetSkipImageVerification->SetValue(prefs.dont_verify_images);
373 // confirm before connect
374 m_chkNetConfirmBeforeConnect->SetValue(prefs.confirm_before_connecting);
375 // disconnect when done
376 m_chkNetDisconnectWhenDone->SetValue(prefs.hangup_if_dialed);
377
378 // ######### disk and memory usage page
379 //max space used
380 m_chkDiskMaxSpace->SetValue(prefs.disk_max_used_gb > 0.0);
381 DisplayValue(prefs.disk_max_used_gb, m_txtDiskMaxSpace, m_chkDiskMaxSpace);
382
383 // min free
384 m_chkDiskLeastFree->SetValue(prefs.disk_min_free_gb > 0.0);
385 DisplayValue(prefs.disk_min_free_gb, m_txtDiskLeastFree, m_chkDiskLeastFree);
386
387 // max used percentage
388 m_chkDiskMaxOfTotal->SetValue(prefs.disk_max_used_pct < 100.0);
389 DisplayValue(prefs.disk_max_used_pct, m_txtDiskMaxOfTotal, m_chkDiskMaxOfTotal);
390
391 // max VM used
392 DisplayValue((prefs.ram_max_used_busy_frac*100.0), m_txtMemoryMaxInUse);
393
394 // max VM idle
395 DisplayValue((prefs.ram_max_used_idle_frac*100.0), m_txtMemoryMaxOnIdle);
396
397 // suspend to memory
398 m_chkMemoryWhileSuspended->SetValue(prefs.leave_apps_in_memory);
399
400 // max swap space (virtual memory)
401 DisplayValue((prefs.vm_max_used_frac*100.0), m_txtDiskMaxSwap);
402
403 // ######### daily schedules page
404 // do work between
405 m_chkProcEveryDay->SetValue(prefs.cpu_times.start_hour != prefs.cpu_times.end_hour);
406 if (m_chkProcEveryDay->IsChecked()) {
407 m_txtProcEveryDayStart->ChangeValue(DoubleToTimeString(prefs.cpu_times.start_hour));
408 m_txtProcEveryDayStop->ChangeValue(DoubleToTimeString(prefs.cpu_times.end_hour));
409 }
410
411 //special day times
412 for(int i=0; i< 7;i++) {
413 TIME_SPAN& cpu = prefs.cpu_times.week.days[i];
414 if(cpu.present && (cpu.start_hour != cpu.end_hour)) {
415 procDayChks[i]->SetValue(true);
416 procDayStartTxts[i]->ChangeValue(DoubleToTimeString(cpu.start_hour));
417 procDayStopTxts[i]->ChangeValue(DoubleToTimeString(cpu.end_hour));
418 }
419 }
420
421 // use network between
422 m_chkNetEveryDay->SetValue(prefs.net_times.start_hour != prefs.net_times.end_hour);
423 if (m_chkNetEveryDay->IsChecked()) {
424 m_txtNetEveryDayStart->ChangeValue(DoubleToTimeString(prefs.net_times.start_hour));
425 m_txtNetEveryDayStop->ChangeValue(DoubleToTimeString(prefs.net_times.end_hour));
426 }
427
428 //special net times
429 for(int i=0; i< 7;i++) {
430 TIME_SPAN& net = prefs.net_times.week.days[i];
431 if(net.present && (net.start_hour != net.end_hour)) {
432 netDayChks[i]->SetValue(true);
433 netDayStartTxts[i]->ChangeValue(DoubleToTimeString(net.start_hour));
434 netDayStopTxts[i]->ChangeValue(DoubleToTimeString(net.end_hour));
435 }
436 }
437
438 //update control states
439 this->UpdateControlStates();
440 }
441
442 /* write overridden preferences to disk (global_prefs_override.xml) */
443 /* IMPORTANT: Any items added here must be checked in ValidateInput()! */
SavePreferencesSettings()444 bool CDlgAdvPreferences::SavePreferencesSettings() {
445 double td;
446
447 mask.clear();
448
449 // ######### proc usage page
450 m_txtProcUseProcessors->GetValue().ToDouble(&td);
451 prefs.max_ncpus_pct = RoundToHundredths(td);
452 mask.max_ncpus_pct=true;
453
454 //
455 m_txtProcUseCPUTime->GetValue().ToDouble(&td);
456 prefs.cpu_usage_limit=RoundToHundredths(td);
457 mask.cpu_usage_limit=true;
458
459 prefs.run_on_batteries = ! (m_chkProcOnBatteries->GetValue());
460 mask.run_on_batteries=true;
461 //
462 prefs.run_if_user_active = (! m_chkProcInUse->GetValue());
463 mask.run_if_user_active=true;
464
465 prefs.run_gpu_if_user_active = (! m_chkGPUProcInUse->GetValue());
466 mask.run_gpu_if_user_active=true;
467 //
468 if(m_txtProcIdleFor->IsEnabled()) {
469 m_txtProcIdleFor->GetValue().ToDouble(&td);
470 prefs.idle_time_to_run=RoundToHundredths(td);
471 mask.idle_time_to_run=true;
472 }
473
474 if (m_chkMaxLoad->IsChecked()) {
475 m_txtMaxLoad->GetValue().ToDouble(&td);
476 prefs.suspend_cpu_usage=RoundToHundredths(td);
477 } else {
478 prefs.suspend_cpu_usage = 0.0;
479 }
480 mask.suspend_cpu_usage=true;
481
482 m_txtNetConnectInterval->GetValue().ToDouble(&td);
483 prefs.work_buf_min_days=RoundToHundredths(td);
484 mask.work_buf_min_days=true;
485
486 //
487 m_txtNetAdditionalDays->GetValue().ToDouble(&td);
488 prefs.work_buf_additional_days = RoundToHundredths(td);
489 mask.work_buf_additional_days = true;
490
491 //
492 m_txtProcSwitchEvery->GetValue().ToDouble(&td);
493 prefs.cpu_scheduling_period_minutes=RoundToHundredths(td);
494 mask.cpu_scheduling_period_minutes=true;
495
496 //
497 m_txtDiskWriteToDisk->GetValue().ToDouble(&td);
498 prefs.disk_interval=RoundToHundredths(td);
499 mask.disk_interval=true;
500
501 // ######### net usage page
502 //
503 if (m_chkNetDownloadRate->IsChecked()) {
504 m_txtNetDownloadRate->GetValue().ToDouble(&td);
505 td = RoundToHundredths(td);
506 td = td * 1024;
507 prefs.max_bytes_sec_down=td;
508 } else {
509 prefs.max_bytes_sec_down = 0.0;
510 }
511 mask.max_bytes_sec_down=true;
512 //
513 if (m_chkNetUploadRate->IsChecked()) {
514 m_txtNetUploadRate->GetValue().ToDouble(&td);
515 td = RoundToHundredths(td);
516 td = td * 1024;
517 prefs.max_bytes_sec_up=td;
518 } else {
519 prefs.max_bytes_sec_up = 0.0;
520 }
521 mask.max_bytes_sec_up=true;
522
523 if (m_chk_daily_xfer_limit->IsChecked()) {
524 m_txt_daily_xfer_limit_mb->GetValue().ToDouble(&td);
525 prefs.daily_xfer_limit_mb=RoundToHundredths(td);
526 m_txt_daily_xfer_period_days->GetValue().ToDouble(&td);
527 prefs.daily_xfer_period_days=(int)td;
528 } else {
529 prefs.daily_xfer_limit_mb = 0.0;
530 prefs.daily_xfer_period_days = 0.0;
531 }
532 mask.daily_xfer_limit_mb=true;
533 mask.daily_xfer_period_days=true;
534 //
535 prefs.dont_verify_images=m_chkNetSkipImageVerification->GetValue();
536 mask.dont_verify_images=true;
537 //
538 prefs.confirm_before_connecting= m_chkNetConfirmBeforeConnect->GetValue();
539 mask.confirm_before_connecting=true;
540 //
541 prefs.hangup_if_dialed= m_chkNetDisconnectWhenDone->GetValue();
542 mask.hangup_if_dialed=true;
543
544 // ######### disk and memory page
545
546 if (m_chkDiskMaxSpace->IsChecked()) {
547 m_txtDiskMaxSpace->GetValue().ToDouble(&td);
548 prefs.disk_max_used_gb=RoundToHundredths(td);
549 } else {
550 prefs.disk_max_used_gb = 0.0;
551 }
552 mask.disk_max_used_gb=true;
553 //
554 if (m_chkDiskLeastFree->IsChecked()) {
555 m_txtDiskLeastFree->GetValue().ToDouble(&td);
556 prefs.disk_min_free_gb=RoundToHundredths(td);
557 } else {
558 prefs.disk_min_free_gb = 0.0;
559 }
560 mask.disk_min_free_gb=true;
561 //
562 if (m_chkDiskMaxOfTotal->IsChecked()) {
563 m_txtDiskMaxOfTotal->GetValue().ToDouble(&td);
564 prefs.disk_max_used_pct = RoundToHundredths(td);
565 } else {
566 prefs.disk_max_used_pct = 100.0;
567 }
568 mask.disk_max_used_pct=true;
569 //Memory
570 m_txtMemoryMaxInUse->GetValue().ToDouble(&td);
571 td = RoundToHundredths(td);
572 td = td / 100.0;
573 prefs.ram_max_used_busy_frac=td;
574 mask.ram_max_used_busy_frac=true;
575 //
576 m_txtMemoryMaxOnIdle->GetValue().ToDouble(&td);
577 td = RoundToHundredths(td);
578 td = td / 100.0;
579 prefs.ram_max_used_idle_frac=td;
580 mask.ram_max_used_idle_frac=true;
581 //
582 prefs.leave_apps_in_memory = m_chkMemoryWhileSuspended->GetValue();
583 mask.leave_apps_in_memory=true;
584 //
585 m_txtDiskMaxSwap->GetValue().ToDouble(&td);
586 td = RoundToHundredths(td);
587 td = td / 100.0 ;
588 prefs.vm_max_used_frac=td;
589 mask.vm_max_used_frac=true;
590
591 // ######### daily schedules page
592
593 if (m_chkProcEveryDay->IsChecked()) {
594 prefs.cpu_times.start_hour = TimeStringToDouble(m_txtProcEveryDayStart->GetValue());
595 prefs.cpu_times.end_hour = TimeStringToDouble(m_txtProcEveryDayStop->GetValue());
596 } else {
597 prefs.cpu_times.start_hour = prefs.cpu_times.end_hour = 0.0;
598 }
599 mask.start_hour = mask.end_hour = true;
600
601 //clear special day times settings
602 prefs.cpu_times.week.clear();
603 for(int i=0; i< 7;i++) {
604 if(procDayChks[i]->GetValue()) {
605 wxString startStr = procDayStartTxts[i]->GetValue();
606 wxString endStr = procDayStopTxts[i]->GetValue();
607 prefs.cpu_times.week.set(i,
608 TimeStringToDouble(startStr),
609 TimeStringToDouble(endStr)
610 );
611 }
612 }
613
614 if (m_chkNetEveryDay->IsChecked()) {
615 prefs.net_times.start_hour = TimeStringToDouble(m_txtNetEveryDayStart->GetValue());
616 prefs.net_times.end_hour = TimeStringToDouble(m_txtNetEveryDayStop->GetValue());
617 } else {
618 prefs.net_times.start_hour = prefs.net_times.end_hour = 0.0;
619 }
620 mask.net_start_hour = mask.net_end_hour = true;
621
622 //clear special net times settings
623 prefs.net_times.week.clear();
624 for(int i=0; i< 7;i++) {
625 if(netDayChks[i]->GetValue()) {
626 wxString startStr = netDayStartTxts[i]->GetValue();
627 wxString endStr = netDayStopTxts[i]->GetValue();
628 prefs.net_times.week.set(i,
629 TimeStringToDouble(startStr),
630 TimeStringToDouble(endStr)
631 );
632 }
633 }
634
635 return true;
636 }
637
638 /* set state of control depending on other control's state */
UpdateControlStates()639 void CDlgAdvPreferences::UpdateControlStates() {
640 // ######### proc usage page
641 // Disable idle timeout edit text item if we allow both CPU and GPU when idle.
642 bool wasEnabled = m_txtProcIdleFor->IsEnabled();
643 bool shouldEnable = m_chkProcInUse->IsChecked() || m_chkGPUProcInUse->IsChecked();
644 m_txtProcIdleFor->Enable(shouldEnable);
645 if (wasEnabled && !shouldEnable) m_txtProcIdleFor->Clear();
646 if (shouldEnable && !wasEnabled) {
647 DisplayValue(defaultPrefs.idle_time_to_run, m_txtProcIdleFor);
648 }
649
650 // If we suspend work when in use, disable and check "Use GPU when in use"
651 m_chkGPUProcInUse->Enable(! m_chkProcInUse->IsChecked());
652 if (m_chkProcInUse->IsChecked()) m_chkGPUProcInUse->SetValue(true);
653
654 m_txtMaxLoad->Enable(m_chkMaxLoad->IsChecked());
655
656 // ######### disk and memory usage page
657 m_txtDiskMaxSpace->Enable(m_chkDiskMaxSpace->IsChecked());
658 m_txtDiskLeastFree->Enable(m_chkDiskLeastFree->IsChecked());
659 m_txtDiskMaxOfTotal->Enable(m_chkDiskMaxOfTotal->IsChecked());
660
661 // ######### net usage page
662 m_txtNetDownloadRate->Enable(m_chkNetDownloadRate->IsChecked());
663 m_txtNetUploadRate->Enable(m_chkNetUploadRate->IsChecked());
664 m_txt_daily_xfer_limit_mb->Enable(m_chk_daily_xfer_limit->IsChecked());
665 m_txt_daily_xfer_period_days->Enable(m_chk_daily_xfer_limit->IsChecked());
666
667 // ######### daily schedules page
668 m_txtProcEveryDayStart->Enable(m_chkProcEveryDay->IsChecked());
669 m_txtProcEveryDayStop->Enable(m_chkProcEveryDay->IsChecked());
670
671 m_txtNetEveryDayStart->Enable(m_chkNetEveryDay->IsChecked());
672 m_txtNetEveryDayStop->Enable(m_chkNetEveryDay->IsChecked());
673
674 for (int i=0; i<7; ++i) {
675 procDayStartTxts[i]->Enable(procDayChks[i]->IsChecked());
676 procDayStopTxts[i]->Enable(procDayChks[i]->IsChecked());
677 netDayStartTxts[i]->Enable(netDayChks[i]->IsChecked());
678 netDayStopTxts[i]->Enable(netDayChks[i]->IsChecked());
679 }
680 }
681
682 /* validates the entered informations */
ValidateInput()683 bool CDlgAdvPreferences::ValidateInput() {
684 wxString invMsgFloat = _("Invalid number");
685 wxString invMsgTime = _("Invalid time, value must be between 0:00 and 24:00, format is HH:MM");
686 wxString invMsgTimeSpan = _("Start time must be different from end time");
687 wxString invMsgLimit10 = _("Number must be between 0 and 10");
688 wxString invMsgLimit100 = _("Number must be between 0 and 100");
689 wxString invMsgLimit1_100 = _("Number must be between 1 and 100");
690 wxString buffer;
691 double startTime, endTime;
692
693 // ######### proc usage page
694 buffer = m_txtProcUseProcessors->GetValue();
695 if(!IsValidFloatValueBetween(buffer, 0.0, 100.0)) {
696 ShowErrorMessage(invMsgLimit100, m_txtProcUseProcessors);
697 return false;
698 }
699
700 buffer = m_txtProcUseCPUTime->GetValue();
701 if(!IsValidFloatValueBetween(buffer, 0.0, 100.0)) {
702 ShowErrorMessage(invMsgLimit100, m_txtProcUseCPUTime);
703 return false;
704 }
705
706 if(m_txtProcIdleFor->IsEnabled()) {
707 buffer = m_txtProcIdleFor->GetValue();
708 if(!IsValidFloatValueBetween(buffer, 0, 10000)) {
709 ShowErrorMessage(invMsgFloat,m_txtProcIdleFor);
710 return false;
711 }
712 }
713
714 if (m_chkMaxLoad->IsChecked()) {
715 buffer = m_txtMaxLoad->GetValue();
716 if(!IsValidFloatValueBetween(buffer, 1.0, 100.0)) {
717 ShowErrorMessage(invMsgLimit1_100, m_txtMaxLoad);
718 return false;
719 }
720 }
721
722 //limit additional days from 0 to 10
723 buffer = m_txtNetConnectInterval->GetValue();
724 if(!IsValidFloatValueBetween(buffer, 0.0, 10.0)) {
725 ShowErrorMessage(invMsgLimit10,m_txtNetConnectInterval);
726 return false;
727 }
728
729 buffer = m_txtNetAdditionalDays->GetValue();
730 if(!IsValidFloatValueBetween(buffer, 0.0, 10.0)) {
731 ShowErrorMessage(invMsgLimit10,m_txtNetAdditionalDays);
732 return false;
733 }
734
735 buffer = m_txtProcSwitchEvery->GetValue();
736 if(!IsValidFloatValue(buffer)) {
737 ShowErrorMessage(invMsgFloat, m_txtProcSwitchEvery);
738 return false;
739 } else {
740 double td;
741 if((!buffer.ToDouble(&td)) || (td < 1.0)) {
742 ShowErrorMessage(invMsgFloat, m_txtProcSwitchEvery);
743 return false;
744 }
745 }
746
747 buffer = m_txtDiskWriteToDisk->GetValue();
748 if(!IsValidFloatValue(buffer)) {
749 ShowErrorMessage(invMsgFloat, m_txtDiskWriteToDisk);
750 return false;
751 }
752
753 // ######### net usage page
754
755 if (m_chkNetDownloadRate->IsChecked()) {
756 buffer = m_txtNetDownloadRate->GetValue();
757 if(!IsValidFloatValue(buffer)) {
758 ShowErrorMessage(invMsgFloat, m_txtNetDownloadRate);
759 return false;
760 }
761 }
762
763 if (m_chkNetUploadRate->IsChecked()) {
764 buffer = m_txtNetUploadRate->GetValue();
765 if(!IsValidFloatValue(buffer)) {
766 ShowErrorMessage(invMsgFloat, m_txtNetUploadRate);
767 return false;
768 }
769 }
770
771 if (m_chk_daily_xfer_limit->IsChecked()) {
772 buffer = m_txt_daily_xfer_limit_mb->GetValue();
773 if(!IsValidFloatValue(buffer)) {
774 ShowErrorMessage(invMsgFloat, m_txt_daily_xfer_limit_mb);
775 return false;
776 }
777
778 buffer = m_txt_daily_xfer_period_days->GetValue();
779 if(!IsValidFloatValue(buffer)) {
780 ShowErrorMessage(invMsgFloat, m_txt_daily_xfer_period_days);
781 return false;
782 }
783 }
784
785 // ######### disk and memory page
786 if (m_chkDiskMaxSpace->IsChecked()) {
787 buffer = m_txtDiskMaxSpace->GetValue();
788 if(!IsValidFloatValue(buffer)) {
789 ShowErrorMessage(invMsgFloat, m_txtDiskMaxSpace);
790 return false;
791 }
792 }
793
794 if (m_chkDiskLeastFree->IsChecked()) {
795 buffer = m_txtDiskLeastFree->GetValue();
796 if(!IsValidFloatValue(buffer)) {
797 ShowErrorMessage(invMsgFloat, m_txtDiskLeastFree);
798 return false;
799 }
800 }
801
802 if (m_chkDiskMaxOfTotal->IsChecked()) {
803 buffer = m_txtDiskMaxOfTotal->GetValue();
804 if(!IsValidFloatValueBetween(buffer, 0.0, 100.0)) {
805 ShowErrorMessage(invMsgLimit100, m_txtDiskMaxOfTotal);
806 return false;
807 }
808 }
809
810 buffer = m_txtMemoryMaxInUse->GetValue();
811 if(!IsValidFloatValueBetween(buffer, 1.0, 100.0)) {
812 ShowErrorMessage(invMsgLimit1_100, m_txtMemoryMaxInUse);
813 return false;
814 }
815
816 buffer = m_txtMemoryMaxOnIdle->GetValue();
817 if(!IsValidFloatValueBetween(buffer, 1.0, 100.0)) {
818 ShowErrorMessage(invMsgLimit1_100, m_txtMemoryMaxOnIdle);
819 return false;
820 }
821
822 buffer = m_txtDiskMaxSwap->GetValue();
823 if(!IsValidFloatValueBetween(buffer, 1.0, 100.0)) {
824 ShowErrorMessage(invMsgLimit1_100, m_txtDiskMaxSwap);
825 return false;
826 }
827
828 // ######### daily schedules page
829 if (m_chkProcEveryDay->IsChecked()) {
830 buffer = m_txtProcEveryDayStart->GetValue();
831 if(!IsValidTimeValue(buffer)) {
832 ShowErrorMessage(invMsgTime,m_txtProcEveryDayStart);
833 return false;
834 }
835 buffer = m_txtProcEveryDayStop->GetValue();
836 if(!IsValidTimeValue(buffer)) {
837 ShowErrorMessage(invMsgTime,m_txtProcEveryDayStop);
838 return false;
839 }
840 startTime = TimeStringToDouble(m_txtProcEveryDayStart->GetValue());
841 endTime = TimeStringToDouble(m_txtProcEveryDayStop->GetValue());
842 if (startTime == endTime) {
843 ShowErrorMessage(invMsgTimeSpan,m_txtProcEveryDayStop);
844 return false;
845 }
846 }
847
848 //all text ctrls in proc special time textBox
849 for(int i=0; i< 7;i++) {
850 if(procDayChks[i]->GetValue()) {
851 buffer = procDayStartTxts[i]->GetValue();
852 if(!IsValidTimeValue(buffer)) {
853 ShowErrorMessage(invMsgTime,procDayStartTxts[i]);
854 return false;
855 }
856 buffer = procDayStopTxts[i]->GetValue();
857 if(!IsValidTimeValue(buffer)) {
858 ShowErrorMessage(invMsgTime,procDayStopTxts[i]);
859 return false;
860 }
861 startTime = TimeStringToDouble(procDayStartTxts[i]->GetValue());
862 endTime = TimeStringToDouble(procDayStopTxts[i]->GetValue());
863 if (startTime == endTime) {
864 ShowErrorMessage(invMsgTimeSpan,procDayStopTxts[i]);
865 return false;
866 }
867 }
868 }
869
870 if (m_chkNetEveryDay->IsChecked()) {
871 buffer = m_txtNetEveryDayStart->GetValue();
872 if(!IsValidTimeValue(buffer)) {
873 ShowErrorMessage(invMsgTime,m_txtNetEveryDayStart);
874 return false;
875 }
876 buffer = m_txtNetEveryDayStop->GetValue();
877 if(!IsValidTimeValue(buffer)) {
878 ShowErrorMessage(invMsgTime,m_txtNetEveryDayStop);
879 return false;
880 }
881 startTime = TimeStringToDouble(m_txtNetEveryDayStart->GetValue());
882 endTime = TimeStringToDouble(m_txtNetEveryDayStop->GetValue());
883 if (startTime == endTime) {
884 ShowErrorMessage(invMsgTimeSpan,m_txtNetEveryDayStop);
885 return false;
886 }
887 }
888
889 //all text ctrls in net special time textBox
890 for(int i=0; i< 7;i++) {
891 if(netDayChks[i]->GetValue()) {
892 buffer = netDayStartTxts[i]->GetValue();
893 if(!IsValidTimeValue(buffer)) {
894 ShowErrorMessage(invMsgTime,netDayStartTxts[i]);
895 return false;
896 }
897 buffer = netDayStopTxts[i]->GetValue();
898 if(!IsValidTimeValue(buffer)) {
899 ShowErrorMessage(invMsgTime,netDayStopTxts[i]);
900 return false;
901 }
902 startTime = TimeStringToDouble(netDayStartTxts[i]->GetValue());
903 endTime = TimeStringToDouble(netDayStopTxts[i]->GetValue());
904 if (startTime == endTime) {
905 ShowErrorMessage(invMsgTimeSpan,netDayStopTxts[i]);
906 return false;
907 }
908 }
909 }
910 return true;
911 }
912
913 /* ensures that the page which contains txtCtrl is selected */
EnsureTabPageVisible(wxTextCtrl * txtCtrl)914 bool CDlgAdvPreferences::EnsureTabPageVisible(wxTextCtrl* txtCtrl) {
915 wxWindow* parent = txtCtrl->GetParent();
916 wxASSERT(parent);
917 int parentid = parent->GetId();
918 int index = m_arrTabPageIds.Index(parentid);
919 if(index == wxNOT_FOUND) {
920 //some controls are contained in an additional panel,
921 //so look at its parent and grandparent
922 for (int i=0; i<2; ++i) {
923 parent = parent->GetParent();
924 wxASSERT(parent);
925 parentid = parent->GetId();
926 index = m_arrTabPageIds.Index(parentid);
927 if(index != wxNOT_FOUND) break;
928 }
929 if(index == wxNOT_FOUND) {
930 //this should never happen
931 return false;
932 }
933 }
934 m_Notebook->SetSelection(index);
935 return true;
936 }
937
938 /* show an error message and set the focus to the control that caused the error */
ShowErrorMessage(wxString & message,wxTextCtrl * errorCtrl)939 void CDlgAdvPreferences::ShowErrorMessage(wxString& message,wxTextCtrl* errorCtrl) {
940 #if wxDEBUG_LEVEL // Prevent compiler warning (unused variable)
941 bool visibleOK =
942 #endif
943 this->EnsureTabPageVisible(errorCtrl);
944 wxASSERT(visibleOK);
945 //
946 if(message.IsEmpty()){
947 message = _("invalid input value detected");
948 }
949 if (lastErrorCtrl) {
950 lastErrorCtrl->SetBackgroundColour(stdTextBkgdColor);
951 lastErrorCtrl->Refresh();
952 }
953 if (lastErrorCtrl != errorCtrl) {
954 stdTextBkgdColor = errorCtrl->GetBackgroundColour();
955 }
956 errorCtrl->SetBackgroundColour(wxColour(255, 192, 192));
957 errorCtrl->Refresh();
958 lastErrorCtrl = errorCtrl;
959 wxGetApp().SafeMessageBox(message,_("Validation Error"),wxOK | wxCENTRE | wxICON_ERROR,this);
960 errorCtrl->SetFocus();
961 }
962
963 /* checks if ch is a valid character for float values */
IsValidFloatChar(const wxChar & ch)964 bool CDlgAdvPreferences::IsValidFloatChar(const wxChar& ch) {
965 //don't accept the e
966 return wxIsdigit(ch) || ch=='.' || ch==',' || ch=='+' || ch=='-';}
967
968 /* checks if ch is a valid character for time values */
IsValidTimeChar(const wxChar & ch)969 bool CDlgAdvPreferences::IsValidTimeChar(const wxChar& ch) {
970 return wxIsdigit(ch) || ch==':';
971 }
972
973 /* checks if the value contains a valid float */
IsValidFloatValue(const wxString & value,bool allowNegative)974 bool CDlgAdvPreferences::IsValidFloatValue(const wxString& value, bool allowNegative) {
975 for(unsigned int i=0; i < value.Length();i++) {
976 if(!IsValidFloatChar(value[i])) {
977 return false;
978 }
979 }
980 //all chars are valid, now what is with the value as a whole ?
981 double td;
982 if(!value.ToDouble(&td)) {
983 return false;
984 }
985 if (!allowNegative) {
986 if (td < 0.0) return false;
987 }
988 return true;
989 }
990
IsValidFloatValueBetween(const wxString & value,double minVal,double maxVal)991 bool CDlgAdvPreferences::IsValidFloatValueBetween(const wxString& value, double minVal, double maxVal){
992 for(unsigned int i=0; i < value.Length();i++) {
993 if(!IsValidFloatChar(value[i])) {
994 return false;
995 }
996 }
997 //all chars are valid, now what is with the value as a whole ?
998 double td;
999 if(!value.ToDouble(&td)) {
1000 return false;
1001 }
1002 if ((td < minVal) || (td > maxVal)) return false;
1003 return true;
1004 }
1005
1006
1007 /* checks if the value is a valid time */
IsValidTimeValue(const wxString & value)1008 bool CDlgAdvPreferences::IsValidTimeValue(const wxString& value) {
1009 for(unsigned int i=0; i < value.Length();i++) {
1010 if(!IsValidTimeChar(value[i])) {
1011 return false;
1012 }
1013 }
1014 //all chars are valid, now what is with the value as a whole ?
1015 wxDateTime dt;
1016 const wxChar* stopChar = dt.ParseFormat(value,wxT("%H:%M"));
1017 if(stopChar==NULL && value != wxT("24:00")) {
1018 // conversion failed
1019 return false;
1020 }
1021 return true;
1022 }
1023
1024
1025 // ------------ Event handlers starts here
1026 // -------- generic command handler
1027 // handles all control command events
OnHandleCommandEvent(wxCommandEvent & ev)1028 void CDlgAdvPreferences::OnHandleCommandEvent(wxCommandEvent& ev) {
1029 ev.Skip();
1030 // If user has just set the checkbox, set textedit field to default value.
1031 // Note: use ChangeValue() here to avoid generating extra events.
1032 // m_txtProcIdleFor depends on 2 checkboxes, set it in UpdateControlStates().
1033 switch (ev.GetId()) {
1034 // processor usage page
1035 case ID_CHKMAXLOAD:
1036 DisplayValue(defaultPrefs.suspend_cpu_usage, m_txtMaxLoad, m_chkMaxLoad);
1037 break;
1038
1039 // network usage page
1040 case ID_CHKNETDOWNLOADRATE:
1041 DisplayValue((defaultPrefs.max_bytes_sec_down / 1024), m_txtNetDownloadRate, m_chkNetDownloadRate);
1042 break;
1043 case ID_CHKNETUPLOADRATE:
1044 DisplayValue((defaultPrefs.max_bytes_sec_up / 1024), m_txtNetUploadRate, m_chkNetUploadRate);
1045 break;
1046 case ID_CHKDAILYXFERLIMIT:
1047 DisplayValue(defaultPrefs.daily_xfer_limit_mb, m_txt_daily_xfer_limit_mb, m_chk_daily_xfer_limit);
1048 DisplayValue(defaultPrefs.daily_xfer_period_days, m_txt_daily_xfer_period_days, m_chk_daily_xfer_limit);
1049 break;
1050
1051 // disk usage page
1052 case ID_CHKDISKMAXSPACE:
1053 DisplayValue(defaultPrefs.disk_max_used_gb, m_txtDiskMaxSpace, m_chkDiskMaxSpace);
1054 break;
1055 case ID_CHKDISKLEASTFREE:
1056 DisplayValue(defaultPrefs.disk_min_free_gb, m_txtDiskLeastFree, m_chkDiskLeastFree);
1057 break;
1058 case ID_CHKDISKMAXOFTOTAL:
1059 DisplayValue(defaultPrefs.disk_max_used_pct, m_txtDiskMaxOfTotal, m_chkDiskMaxOfTotal);
1060 break;
1061 case ID_CHKPROCEVERYDAY:
1062 if (ev.IsChecked()) {
1063 m_txtProcEveryDayStart->ChangeValue(DoubleToTimeString(defaultPrefs.cpu_times.start_hour));
1064 m_txtProcEveryDayStop->ChangeValue(DoubleToTimeString(defaultPrefs.cpu_times.end_hour));
1065 } else {
1066 m_txtProcEveryDayStart->Clear();
1067 m_txtProcEveryDayStop->Clear();
1068 }
1069 break;
1070 case ID_CHKPROCSUNDAY:
1071 case ID_CHKPROCMONDAY:
1072 case ID_CHKPROCTUESDAY:
1073 case ID_CHKPROCWEDNESDAY:
1074 case ID_CHKPROCTHURSDAY:
1075 case ID_CHKPROCFRIDAY:
1076 case ID_CHKPROCSATURDAY:
1077 if (ev.IsChecked()) {
1078 (procDayStartTxts[ev.GetId() - ID_CHKPROCSUNDAY])->ChangeValue(DoubleToTimeString(defaultPrefs.cpu_times.start_hour));
1079 (procDayStopTxts[ev.GetId() - ID_CHKPROCSUNDAY])->ChangeValue(DoubleToTimeString(defaultPrefs.cpu_times.end_hour));
1080 } else {
1081 (procDayStartTxts[ev.GetId() - ID_CHKPROCSUNDAY])->Clear();
1082 (procDayStopTxts[ev.GetId() - ID_CHKPROCSUNDAY])->Clear();
1083 }
1084 break;
1085 case ID_CHKNETEVERYDAY:
1086 if (ev.IsChecked()) {
1087 m_txtNetEveryDayStart->ChangeValue(DoubleToTimeString(defaultPrefs.net_times.start_hour));
1088 m_txtNetEveryDayStop->ChangeValue(DoubleToTimeString(defaultPrefs.net_times.end_hour));
1089 } else {
1090 m_txtNetEveryDayStart->Clear();
1091 m_txtNetEveryDayStop->Clear();
1092 }
1093 break;
1094 case ID_CHKNETSUNDAY:
1095 case ID_CHKNETMONDAY:
1096 case ID_CHKNETTUESDAY:
1097 case ID_CHKNETWEDNESDAY:
1098 case ID_CHKNETTHURSDAY:
1099 case ID_CHKNETFRIDAY:
1100 case ID_CHKNETSATURDAY:
1101 if (ev.IsChecked()) {
1102 (netDayStartTxts[ev.GetId() - ID_CHKNETSUNDAY])->ChangeValue(DoubleToTimeString(defaultPrefs.net_times.start_hour));
1103 (netDayStopTxts[ev.GetId() - ID_CHKNETSUNDAY])->ChangeValue(DoubleToTimeString(defaultPrefs.net_times.end_hour));
1104 } else {
1105 (netDayStartTxts[ev.GetId() - ID_CHKNETSUNDAY])->Clear();
1106 (netDayStopTxts[ev.GetId() - ID_CHKNETSUNDAY])->Clear();
1107 }
1108 break;
1109
1110 default:
1111 break;
1112 }
1113 // }
1114 UpdateControlStates();
1115 }
1116
1117 // ---- command buttons handlers
1118 // handles OK button clicked
OnOK(wxCommandEvent & ev)1119 void CDlgAdvPreferences::OnOK(wxCommandEvent& ev) {
1120 CMainDocument* pDoc = wxGetApp().GetDocument();
1121
1122 wxASSERT(pDoc);
1123 wxASSERT(wxDynamicCast(pDoc, CMainDocument));
1124
1125 if(!ValidateInput()) {
1126 return;
1127 }
1128 if(SavePreferencesSettings()) {
1129 pDoc->rpc.set_global_prefs_override_struct(prefs,mask);
1130 pDoc->rpc.read_global_prefs_override();
1131 }
1132
1133 ev.Skip();
1134 }
1135
1136 // handles Help button clicked
OnHelp(wxCommandEvent & ev)1137 void CDlgAdvPreferences::OnHelp(wxCommandEvent& ev) {
1138 if (IsShown()) {
1139
1140 wxString strURL = wxGetApp().GetSkinManager()->GetAdvanced()->GetOrganizationHelpUrl();
1141
1142 wxString wxurl;
1143 wxurl.Printf(
1144 wxT("%s?target=advanced_preferences&version=%s&controlid=%d"),
1145 strURL.c_str(),
1146 wxString(BOINC_VERSION_STRING, wxConvUTF8).c_str(),
1147 ev.GetId()
1148 );
1149 wxLaunchDefaultBrowser(wxurl);
1150 }
1151 }
1152
1153 // handles Clear button clicked
OnClear(wxCommandEvent & ev)1154 void CDlgAdvPreferences::OnClear(wxCommandEvent& ev) {
1155 if(this->ConfirmClear()) {
1156 CMainDocument* pDoc = wxGetApp().GetDocument();
1157
1158 wxASSERT(pDoc);
1159 wxASSERT(wxDynamicCast(pDoc, CMainDocument));
1160
1161 mask.clear();
1162 pDoc->rpc.set_global_prefs_override_struct(prefs,mask);
1163 pDoc->rpc.read_global_prefs_override();
1164 this->EndModal(wxID_CANCEL);
1165 }
1166 ev.Skip();
1167 }
1168
ConfirmClear()1169 bool CDlgAdvPreferences::ConfirmClear() {
1170 int res = wxGetApp().SafeMessageBox(_(
1171 "Discard local preferences and use web-based preferences?"),
1172 _("Confirmation"),wxCENTER | wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT,this);
1173
1174 return res==wxYES;
1175 }
1176
1177
1178
1179