1 // This file is part of BOINC.
2 // http://boinc.berkeley.edu
3 // Copyright (C) 2008 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 "DlgDiagnosticLogFlags.cpp"
20 #endif
21 
22 #include "stdwx.h"
23 #include "util.h"
24 #include "DlgDiagnosticLogFlags.h"
25 #include "BOINCGUIApp.h"
26 #include "BOINCBaseFrame.h"
27 #include "Events.h"
28 #include "error_numbers.h"
29 #include "gui_rpc_client.h" // For SET_LOCALE
30 #include "SkinManager.h"
31 
32 
33 #define DLGDIAGNOSTICS_INITIAL_WIDTH ADJUSTFORXDPI(480)
34 #define DLGDIAGNOSTICS_INITIAL_HEIGHT ADJUSTFORYDPI(480)
35 #define DLGDIAGNOSTICS_MIN_WIDTH ADJUSTFORXDPI(400)
36 #define DLGDIAGNOSTICS_MIN_HEIGHT ADJUSTFORYDPI(400)
37 
IMPLEMENT_DYNAMIC_CLASS(CDlgDiagnosticLogFlags,wxDialog)38 IMPLEMENT_DYNAMIC_CLASS(CDlgDiagnosticLogFlags, wxDialog)
39 
40 BEGIN_EVENT_TABLE(CDlgDiagnosticLogFlags, wxDialog)
41     EVT_SIZE(CDlgDiagnosticLogFlags::OnSize)
42     EVT_BUTTON(wxID_OK,CDlgDiagnosticLogFlags::OnOK)
43     EVT_BUTTON(ID_DEFAULTSBTN,CDlgDiagnosticLogFlags::OnSetDefaults)
44     EVT_BUTTON(wxID_APPLY,CDlgDiagnosticLogFlags::OnApply)
45     EVT_CHECKBOX(wxID_ANY,CDlgDiagnosticLogFlags::OnCheckBox)
46 
47 END_EVENT_TABLE()
48 
49 /* Constructor */
50 CDlgDiagnosticLogFlags::CDlgDiagnosticLogFlags(wxWindow* parent) :
51     wxDialog( parent, ID_ANYDIALOG, wxEmptyString, wxDefaultPosition,
52                 wxSize( DLGDIAGNOSTICS_INITIAL_WIDTH,DLGDIAGNOSTICS_INITIAL_HEIGHT ),
53                 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER
54             ) {
55 
56     CSkinAdvanced*     pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
57     CMainDocument* pDoc = wxGetApp().GetDocument();
58 
59     wxASSERT(pDoc);
60     wxASSERT(wxDynamicCast(pDoc, CMainDocument));
61 
62     wxASSERT(pSkinAdvanced);
63     wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
64 
65     wxString title;
66     title.Printf(
67         _("%s Diagnostic Log Flags"),
68         pSkinAdvanced->GetApplicationShortName().c_str()
69     );
70 
71     SetTitle(title);
72 
73     // Get cc_config.xml file flags
74     log_flags.init();
75     m_cc_config.defaults();
76     pDoc->rpc.get_cc_config(m_cc_config, log_flags);
77 
78     SetSizeHints(DLGDIAGNOSTICS_MIN_WIDTH, DLGDIAGNOSTICS_MIN_HEIGHT);
79     SetExtraStyle( GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY );
80 
81     wxBoxSizer* bSizer1 = new wxBoxSizer( wxVERTICAL );
82     m_headingSizer = new wxFlexGridSizer( 1 );
83 
84     m_headingText.Printf(
85         _("These flags enable various types of diagnostic messages in the Event Log.")
86     );
87 
88     m_heading = new wxStaticText(this, wxID_ANY, m_headingText);
89 
90     m_headingSizer->Add(m_heading, 1, wxLEFT | wxRIGHT, 25);
91 
92     wxString strURL = pSkinAdvanced->GetOrganizationHelpUrl();
93     wxString helpURL;
94     helpURL.Printf(
95             wxT("%s?target=notice&controlid=log_flags"),
96             strURL.c_str()
97         );
98 
99      m_headingSizer->Add(
100         new wxHyperlinkCtrl(
101             this, wxID_ANY, _("More info ..."), helpURL,
102             wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE
103         ),
104         0, wxLEFT | wxRIGHT, 25
105     );
106 
107     bSizer1->AddSpacer(7);
108     bSizer1->Add( m_headingSizer, 0, wxEXPAND | wxALL, 5 );
109     bSizer1->AddSpacer(7);
110 
111     m_scrolledWindow = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL );
112     m_scrolledWindow->SetScrollRate( 5, 5 );
113 
114     m_checkboxSizer = new wxGridSizer(2, wxSize(0,3));
115     CreateCheckboxes();
116 
117     bSizer1->Add( m_scrolledWindow, 1, wxEXPAND | wxALL, 5 );
118 
119     wxBoxSizer* buttonSizer = new wxBoxSizer( wxHORIZONTAL );
120 
121     wxButton* btnOK = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 );
122     btnOK->SetToolTip( _("Save all values and close the dialog") );
123     buttonSizer->Add( btnOK, 0, wxALL, 5 );
124 
125     wxButton* btnDefaults = new wxButton( this, ID_DEFAULTSBTN, _("Defaults"), wxDefaultPosition, wxDefaultSize, 0 );
126     btnDefaults->SetToolTip( _("Restore default settings") );
127     buttonSizer->Add( btnDefaults, 0, wxALL, 5 );
128 
129     wxButton* btnCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
130     btnCancel->SetToolTip( _("Close the dialog without saving") );
131     buttonSizer->Add( btnCancel, 0, wxALL, 5 );
132 
133     m_btnApply = new wxButton( this, wxID_APPLY, _("Apply"), wxDefaultPosition, wxDefaultSize, 0 );
134     m_btnApply->SetToolTip( _("Save all values") );
135     m_btnApply->Enable(false);
136     buttonSizer->Add( m_btnApply, 0, wxALL, 5 );
137 
138     btnCancel->SetDefault();
139     bSizer1->Add( buttonSizer, 0, wxALIGN_RIGHT | wxALL, 15 );
140 
141     SetSizer( bSizer1 );
142 
143     RestoreState();
144     Layout();
145     Center( wxBOTH );
146 
147 #if defined(__WXMSW__) || defined(__WXGTK__)
148     SetDoubleBuffered(true);
149 #endif
150 }
151 
152 // destructor
~CDlgDiagnosticLogFlags()153 CDlgDiagnosticLogFlags::~CDlgDiagnosticLogFlags() {
154     SaveState();
155 }
156 
157 
CreateCheckboxes()158 void CDlgDiagnosticLogFlags::CreateCheckboxes() {
159     SET_LOCALE sl;
160     char buf[64000];
161     MIOFILE mf;
162     bool val;
163 
164     m_checkbox_list.clear();
165 
166     mf.init_buf_write(buf, sizeof(buf));
167     m_cc_config.write(mf, log_flags);
168 
169     mf.init_buf_read(buf);
170     XML_PARSER xp(&mf);
171 
172     while (!xp.get_tag()) {
173         if (!xp.is_tag) {
174             continue;
175         }
176         if (xp.match_tag("log_flags")) break;
177     }
178 
179     while (!xp.get_tag()) {
180         if (!xp.is_tag) {
181             continue;
182         }
183         if (xp.match_tag("/log_flags")) break;
184         wxString label = wxString(xp.parsed_tag);
185         xp.parse_bool(xp.parsed_tag, val);
186 
187         wxCheckBox* ckbox = new wxCheckBox(m_scrolledWindow, wxID_ANY, label);
188         m_checkboxSizer->Add(ckbox, 0, wxLEFT, 25);
189         m_checkbox_list.push_back(ckbox);
190         ckbox->SetValue(val);
191     }
192 
193     m_scrolledWindow->SetSizer( m_checkboxSizer );
194     m_scrolledWindow->Layout();
195     m_checkboxSizer->Fit( m_scrolledWindow );
196 }
197 
SaveFlags()198 void CDlgDiagnosticLogFlags::SaveFlags() {
199     SET_LOCALE sl;
200     char buf[64000];
201     MIOFILE mf;
202     bool val;
203     unsigned int i;
204     CMainDocument* pDoc = wxGetApp().GetDocument();
205 
206     wxASSERT(pDoc);
207     wxASSERT(wxDynamicCast(pDoc, CMainDocument));
208 
209     mf.init_buf_write(buf, sizeof(buf));
210     for (i = 0; i<m_checkbox_list.size(); ++i) {
211       wxCheckBox* ckbox = m_checkbox_list[i];
212       val = ckbox->GetValue();
213       mf.printf("        <%s>%d</%s>\n", (const char*)ckbox->GetLabel().ToAscii(), (int)val, (const char*)ckbox->GetLabel().ToAscii());
214     }
215     mf.printf("    </log_flags>\n");
216 
217     XML_PARSER xp(&mf);
218     mf.init_buf_read(buf);
219     log_flags.parse(xp);
220 
221     int retval = pDoc->rpc.set_cc_config(m_cc_config, log_flags);
222     if (!retval) {
223       pDoc->rpc.read_cc_config();
224     }
225 }
226 
227 
228 /* saves dialog size and (on Mac) position */
SaveState()229 bool CDlgDiagnosticLogFlags::SaveState() {
230     wxConfigBase*   pConfig = wxConfigBase::Get(FALSE);
231 
232     wxASSERT(pConfig);
233     if (!pConfig) return false;
234 
235     pConfig->SetPath("/DlgDiagnosticLogFlags/");
236     pConfig->Write(wxT("Width"), GetSize().GetWidth());
237     pConfig->Write(wxT("Height"), GetSize().GetHeight());
238 
239     pConfig->Flush();
240 
241     return true;
242 }
243 
244 /* restores former dialog size and (on Mac) position */
RestoreState()245 bool CDlgDiagnosticLogFlags::RestoreState() {
246     wxConfigBase*   pConfig = wxConfigBase::Get(FALSE);
247     int                iWidth, iHeight;
248 
249     wxASSERT(pConfig);
250     if (!pConfig) return false;
251 
252     pConfig->SetPath("/DlgDiagnosticLogFlags/");
253 
254     pConfig->Read(wxT("Width"), &iWidth, DLGDIAGNOSTICS_INITIAL_WIDTH);
255     pConfig->Read(wxT("Height"), &iHeight, DLGDIAGNOSTICS_INITIAL_HEIGHT);
256 
257     // Guard against a rare situation where registry values are zero
258     if ((iWidth < 50) && (iWidth != wxDefaultCoord)) iWidth = DLGDIAGNOSTICS_INITIAL_WIDTH;
259     if ((iHeight < 50) && (iHeight != wxDefaultCoord)) iHeight = DLGDIAGNOSTICS_INITIAL_HEIGHT;
260 
261     // Set size to saved values or defaults if no saved values
262     SetSize(std::max(iWidth, DLGDIAGNOSTICS_MIN_WIDTH), std::max(iHeight, DLGDIAGNOSTICS_MIN_HEIGHT));
263 
264     return true;
265 }
266 
267 
OnSize(wxSizeEvent & event)268 void CDlgDiagnosticLogFlags::OnSize(wxSizeEvent& event) {
269     m_heading->SetLabel(m_headingText);
270     m_heading->Wrap(m_headingSizer->GetSize().GetWidth()-50);
271     m_headingSizer->Fit(m_heading);
272     Layout();
273     SaveState();
274     Refresh();
275 
276     event.Skip();
277 }
278 
279 
OnOK(wxCommandEvent & event)280 void CDlgDiagnosticLogFlags::OnOK(wxCommandEvent& event) {
281     SaveFlags();
282 
283     event.Skip();
284 }
285 
286 
OnSetDefaults(wxCommandEvent &)287 void CDlgDiagnosticLogFlags::OnSetDefaults(wxCommandEvent& ) {
288     log_flags.init();
289 
290     m_checkboxSizer->Clear(true);
291     CreateCheckboxes();
292     m_btnApply->Enable();
293     Layout();
294 }
295 
OnApply(wxCommandEvent & event)296 void CDlgDiagnosticLogFlags::OnApply(wxCommandEvent & event) {
297     SaveFlags();
298     m_btnApply->Enable(false);
299 
300     event.Skip();
301 }
302 
OnCheckBox(wxCommandEvent & event)303 void CDlgDiagnosticLogFlags::OnCheckBox(wxCommandEvent & event) {
304     m_btnApply->Enable();
305 
306     event.Skip();
307 }
308