1 /*
2 * This file is part of lib_finder plugin for Code::Blocks Studio
3 * Copyright (C) 2007  Bartlomiej Swiecki
4 *
5 * wxSmith is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * wxSmith 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. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with wxSmith; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18 *
19 * $Revision: 10771 $
20 * $Id: projectconfigurationpanel.cpp 10771 2016-02-06 14:29:31Z mortenmacfly $
21 * $HeadURL: svn://svn.code.sf.net/p/codeblocks/code/branches/release-20.xx/src/plugins/contrib/lib_finder/projectconfigurationpanel.cpp $
22 */
23 
24 #include "projectconfigurationpanel.h"
25 
26 //(*InternalHeaders(ProjectConfigurationPanel)
27 #include <wx/checkbox.h>
28 #include <wx/sizer.h>
29 #include <wx/button.h>
30 #include <wx/string.h>
31 #include <wx/intl.h>
32 #include <wx/stattext.h>
33 #include <wx/textctrl.h>
34 #include <wx/treectrl.h>
35 #include <wx/listbox.h>
36 //*)
37 
38 #include <wx/tokenzr.h>
39 #include <wx/choicdlg.h>
40 
41 #include "lib_finder.h"
42 #include "headersdetectordlg.h"
43 
44 //(*IdInit(ProjectConfigurationPanel)
45 const long ProjectConfigurationPanel::ID_LISTBOX1 = wxNewId();
46 const long ProjectConfigurationPanel::ID_BUTTON6 = wxNewId();
47 const long ProjectConfigurationPanel::ID_CHECKBOX2 = wxNewId();
48 const long ProjectConfigurationPanel::ID_BUTTON4 = wxNewId();
49 const long ProjectConfigurationPanel::ID_BUTTON1 = wxNewId();
50 const long ProjectConfigurationPanel::ID_BUTTON2 = wxNewId();
51 const long ProjectConfigurationPanel::ID_TREECTRL1 = wxNewId();
52 const long ProjectConfigurationPanel::ID_STATICTEXT1 = wxNewId();
53 const long ProjectConfigurationPanel::ID_TEXTCTRL2 = wxNewId();
54 const long ProjectConfigurationPanel::ID_CHECKBOX1 = wxNewId();
55 const long ProjectConfigurationPanel::ID_BUTTON5 = wxNewId();
56 const long ProjectConfigurationPanel::ID_TEXTCTRL1 = wxNewId();
57 const long ProjectConfigurationPanel::ID_BUTTON3 = wxNewId();
58 const long ProjectConfigurationPanel::ID_STATICTEXT2 = wxNewId();
59 const long ProjectConfigurationPanel::ID_TIMER1 = wxNewId();
60 //*)
61 
62 BEGIN_EVENT_TABLE(ProjectConfigurationPanel,cbConfigurationPanel)
63 	//(*EventTable(ProjectConfigurationPanel)
64 	//*)
65 END_EVENT_TABLE()
66 
67 namespace
68 {
69     class TreeItemData: public wxTreeItemData
70     {
71         // Warning: since we use reference to string instead of string itself,
72         // the base string must exist as long as this item data exists
73         public:
TreeItemData(const wxString & ShortCode)74             TreeItemData(const wxString& ShortCode): m_ShortCode(ShortCode) {}
~TreeItemData()75             ~TreeItemData() {}
76 
77             const wxString& m_ShortCode;
78     };
79 
80     class ListItemData: public wxClientData
81     {
82         // We don't use string's reference here since project's libraries set
83         // should be much smaller than list of known libraries
84         public:
ListItemData(const wxString & ShortCode)85             ListItemData(const wxString& ShortCode): m_ShortCode(ShortCode) {}
~ListItemData()86             ~ListItemData() {}
87 
88             const wxString m_ShortCode;
89     };
90 }
91 
ProjectConfigurationPanel(wxWindow * parent,ProjectConfiguration * Configuration,cbProject * Project,TypedResults & KnownLibs)92 ProjectConfigurationPanel::ProjectConfigurationPanel(wxWindow* parent,ProjectConfiguration* Configuration,cbProject* Project,TypedResults& KnownLibs):
93     m_Configuration(Configuration),
94     m_Project(Project),
95     m_KnownLibs(KnownLibs)
96 {
97 	//(*Initialize(ProjectConfigurationPanel)
98 	wxStaticBoxSizer* StaticBoxSizer2;
99 	wxBoxSizer* BoxSizer3;
100 	wxBoxSizer* BoxSizer7;
101 	wxBoxSizer* BoxSizer2;
102 	wxStaticBoxSizer* StaticBoxSizer3;
103 	wxBoxSizer* BoxSizer4;
104 	wxBoxSizer* BoxSizer1;
105 	wxStaticBoxSizer* m_DisableAuto;
106 	wxBoxSizer* BoxSizer6;
107 	wxBoxSizer* BoxSizer5;
108 	wxStaticBoxSizer* StaticBoxSizer1;
109 
110 	Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("wxID_ANY"));
111 	BoxSizer1 = new wxBoxSizer(wxVERTICAL);
112 	BoxSizer6 = new wxBoxSizer(wxHORIZONTAL);
113 	BoxSizer5 = new wxBoxSizer(wxVERTICAL);
114 	StaticBoxSizer1 = new wxStaticBoxSizer(wxVERTICAL, this, _("Libraries used in project"));
115 	m_UsedLibraries = new wxListBox(this, ID_LISTBOX1, wxDefaultPosition, wxSize(147,123), 0, 0, 0, wxDefaultValidator, _T("ID_LISTBOX1"));
116 	StaticBoxSizer1->Add(m_UsedLibraries, 1, wxALL|wxEXPAND, 5);
117 	Button2 = new wxButton(this, ID_BUTTON6, _("Try to detect missing ones"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON6"));
118 	StaticBoxSizer1->Add(Button2, 0, wxLEFT|wxRIGHT|wxEXPAND, 5);
119 	BoxSizer5->Add(StaticBoxSizer1, 1, wxALL|wxEXPAND, 5);
120 	m_DisableAuto = new wxStaticBoxSizer(wxVERTICAL, this, _("Extra settings"));
121 	m_NoAuto = new wxCheckBox(this, ID_CHECKBOX2, _("Don\'t setup automatically"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX2"));
122 	m_NoAuto->SetValue(false);
123 	m_NoAuto->SetToolTip(_("If you check this option, lib_finder won\'t add settings of libraries automatically.\nNote that automatic setup is available only after applying extra patch to code::blocks available at forums."));
124 	m_DisableAuto->Add(m_NoAuto, 0, wxEXPAND, 5);
125 	m_AddScript = new wxButton(this, ID_BUTTON4, _("Add manual build script"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON4"));
126 	m_AddScript->SetToolTip(_("When you use this option, extra script will be added to the project.\nThis script does invoke lib_finder and will add settings of libraries\njust as in case of automatic setup.\nIt may be usefull when no extra-event patch has been applied."));
127 	m_DisableAuto->Add(m_AddScript, 0, wxEXPAND, 5);
128 	BoxSizer5->Add(m_DisableAuto, 0, wxALL|wxEXPAND, 5);
129 	BoxSizer6->Add(BoxSizer5, 3, wxEXPAND, 5);
130 	BoxSizer2 = new wxBoxSizer(wxVERTICAL);
131 	m_Add = new wxButton(this, ID_BUTTON1, _("<"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON1"));
132 	m_Add->Disable();
133 	m_Add->SetToolTip(_("Add selected library to project"));
134 	BoxSizer2->Add(m_Add, 1, wxEXPAND, 5);
135 	m_Remove = new wxButton(this, ID_BUTTON2, _(">"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON2"));
136 	m_Remove->Disable();
137 	m_Remove->SetToolTip(_("Remove selected library from project"));
138 	BoxSizer2->Add(m_Remove, 1, wxEXPAND, 5);
139 	BoxSizer6->Add(BoxSizer2, 0, wxALIGN_CENTER_VERTICAL, 5);
140 	BoxSizer3 = new wxBoxSizer(wxVERTICAL);
141 	StaticBoxSizer2 = new wxStaticBoxSizer(wxVERTICAL, this, _("Known libraries"));
142 	m_KnownLibrariesTree = new wxTreeCtrl(this, ID_TREECTRL1, wxDefaultPosition, wxDefaultSize, wxTR_HIDE_ROOT|wxTR_SINGLE|wxTR_DEFAULT_STYLE|wxSUNKEN_BORDER, wxDefaultValidator, _T("ID_TREECTRL1"));
143 	StaticBoxSizer2->Add(m_KnownLibrariesTree, 1, wxALL|wxEXPAND, 5);
144 	BoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
145 	StaticText1 = new wxStaticText(this, ID_STATICTEXT1, _("Filter:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT1"));
146 	BoxSizer4->Add(StaticText1, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5);
147 	m_Filter = new wxTextCtrl(this, ID_TEXTCTRL2, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL2"));
148 	BoxSizer4->Add(m_Filter, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5);
149 	StaticBoxSizer2->Add(BoxSizer4, 0, wxEXPAND, 5);
150 	BoxSizer7 = new wxBoxSizer(wxHORIZONTAL);
151 	m_Tree = new wxCheckBox(this, ID_CHECKBOX1, _("Show as tree"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX1"));
152 	m_Tree->SetValue(true);
153 	BoxSizer7->Add(m_Tree, 1, wxLEFT|wxRIGHT|wxEXPAND, 5);
154 	Button1 = new wxButton(this, ID_BUTTON5, _("Edit"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON5"));
155 	Button1->Hide();
156 	BoxSizer7->Add(Button1, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5);
157 	StaticBoxSizer2->Add(BoxSizer7, 0, wxEXPAND, 5);
158 	BoxSizer3->Add(StaticBoxSizer2, 1, wxBOTTOM|wxEXPAND, 5);
159 	StaticBoxSizer3 = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Unknown library"));
160 	m_UnknownLibrary = new wxTextCtrl(this, ID_TEXTCTRL1, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL1"));
161 	StaticBoxSizer3->Add(m_UnknownLibrary, 1, wxTOP|wxBOTTOM|wxLEFT|wxEXPAND, 5);
162 	m_AddUnknown = new wxButton(this, ID_BUTTON3, _("Add"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON3"));
163 	m_AddUnknown->Disable();
164 	StaticBoxSizer3->Add(m_AddUnknown, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
165 	BoxSizer3->Add(StaticBoxSizer3, 0, wxTOP|wxEXPAND, 5);
166 	BoxSizer6->Add(BoxSizer3, 4, wxALL|wxEXPAND, 5);
167 	BoxSizer1->Add(BoxSizer6, 1, wxEXPAND, 5);
168 	m_EventText = new wxStaticText(this, ID_STATICTEXT2, _("Note: Because there\'s not yet ability to update project\'s build options\nfrom plugin, the only way to automatically add library configurations\nis to use build script"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE, _T("ID_STATICTEXT2"));
169 	m_EventText->Hide();
170 	BoxSizer1->Add(m_EventText, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5);
171 	SetSizer(BoxSizer1);
172 	Timer1.SetOwner(this, ID_TIMER1);
173 	BoxSizer1->Fit(this);
174 	BoxSizer1->SetSizeHints(this);
175 
176 	Connect(ID_LISTBOX1,wxEVT_COMMAND_LISTBOX_SELECTED,(wxObjectEventFunction)&ProjectConfigurationPanel::Onm_UsedLibrariesSelect);
177 	Connect(ID_BUTTON6,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&ProjectConfigurationPanel::OnButton2Click);
178 	Connect(ID_BUTTON4,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&ProjectConfigurationPanel::Onm_AddScriptClick);
179 	Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&ProjectConfigurationPanel::Onm_AddClick);
180 	Connect(ID_BUTTON2,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&ProjectConfigurationPanel::Onm_RemoveClick);
181 	Connect(ID_TREECTRL1,wxEVT_COMMAND_TREE_SEL_CHANGED,(wxObjectEventFunction)&ProjectConfigurationPanel::Onm_KnownLibrariesTreeSelectionChanged);
182 	Connect(ID_TEXTCTRL2,wxEVT_COMMAND_TEXT_UPDATED,(wxObjectEventFunction)&ProjectConfigurationPanel::Onm_FilterText);
183 	Connect(ID_TEXTCTRL2,wxEVT_COMMAND_TEXT_ENTER,(wxObjectEventFunction)&ProjectConfigurationPanel::Onm_FilterTextEnter);
184 	Connect(ID_CHECKBOX1,wxEVT_COMMAND_CHECKBOX_CLICKED,(wxObjectEventFunction)&ProjectConfigurationPanel::Onm_TreeClick);
185 	Connect(ID_TEXTCTRL1,wxEVT_COMMAND_TEXT_UPDATED,(wxObjectEventFunction)&ProjectConfigurationPanel::Onm_UnknownLibraryText);
186 	Connect(ID_BUTTON3,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&ProjectConfigurationPanel::Onm_AddUnknownClick);
187 	Connect(ID_TIMER1,wxEVT_TIMER,(wxObjectEventFunction)&ProjectConfigurationPanel::OnTimer1Trigger);
188 	//*)
189 
190 	m_EventText->Show(!lib_finder::IsExtraEvent());
191 
192 	if ( m_Project->GetBuildScripts().Index(_T("lib_finder.script")) != wxNOT_FOUND )
193 	    m_AddScript->Disable(); // There's a build script yet
194 
195 	m_ConfCopy = *m_Configuration;
196 	FillKnownLibraries();
197 	LoadData();
198 }
199 
~ProjectConfigurationPanel()200 ProjectConfigurationPanel::~ProjectConfigurationPanel()
201 {
202 	//(*Destroy(ProjectConfigurationPanel)
203 	//*)
204 }
205 
GetTitle() const206 wxString ProjectConfigurationPanel::GetTitle() const
207 {
208     return _("Libraries");
209 }
210 
GetBitmapBaseName() const211 wxString ProjectConfigurationPanel::GetBitmapBaseName() const
212 {
213     return _T("");
214 }
215 
OnApply()216 void ProjectConfigurationPanel::OnApply()
217 {
218     StoreData();
219     *m_Configuration = m_ConfCopy;
220 }
221 
OnCancel()222 void ProjectConfigurationPanel::OnCancel()
223 {
224 }
225 
LoadData()226 void ProjectConfigurationPanel::LoadData()
227 {
228     m_UsedLibraries->Freeze();
229     for ( size_t i=0; i<m_ConfCopy.m_GlobalUsedLibs.Count(); i++ )
230     {
231         wxString Name = m_ConfCopy.m_GlobalUsedLibs[i];
232         m_UsedLibraries->Append(GetUserListName(Name),new ListItemData(Name));
233     }
234     m_UsedLibraries->Thaw();
235     m_NoAuto->SetValue(m_ConfCopy.m_DisableAuto);
236 }
237 
GetUserListName(const wxString & Name)238 wxString ProjectConfigurationPanel::GetUserListName(const wxString& Name)
239 {
240     for ( int i=0; i<rtCount; i++ )
241     {
242         if ( m_KnownLibs[i].IsShortCode(Name) )
243         {
244             switch ( i )
245             {
246                 case rtPkgConfig:
247                     return Name + _T(" (pkg-config)");
248 
249                 default:
250                     return Name + _T(": ") + m_KnownLibs[i].GetShortCode(Name)[0]->LibraryName;
251             }
252         }
253     }
254 
255     return Name + _T(" (Unknown library)");
256 }
257 
StoreData()258 void ProjectConfigurationPanel::StoreData()
259 {
260     m_ConfCopy.m_DisableAuto = m_NoAuto->GetValue();
261 }
262 
FillKnownLibraries()263 void ProjectConfigurationPanel::FillKnownLibraries()
264 {
265     Timer1.Stop();
266     m_KnownLibrariesTree->Freeze();
267     m_KnownLibrariesTree->DeleteAllItems();
268     m_KnownLibrariesTree->AddRoot(_("Known libraries"));
269 
270     m_CategoryMap.clear();
271     m_IsOtherCategory = false;
272     m_IsPkgConfig = false;
273 
274     wxString Filter = m_Filter->GetValue().Upper();
275     bool Tree = m_Tree->GetValue();
276 
277     // Collecting list of all global variable names,
278     // currently without pkg-config entries (will be used later)
279     wxArrayString Vars;
280     for ( int i = 0; i < rtCount; ++i )
281     {
282         if ( i==rtPkgConfig ) continue;
283         m_KnownLibs[i].GetShortCodes(Vars);
284     }
285 
286     for ( size_t i = 0; i < Vars.Count(); ++i )
287     {
288         ResultArray* Array = 0;
289         for ( int j = 0; j < rtCount; ++j )
290         {
291             if ( j!=rtPkgConfig )
292             {
293                 if ( m_KnownLibs[j].IsShortCode(Vars[i]) )
294                     Array = &m_KnownLibs[j].GetShortCode(Vars[i]);
295             }
296         }
297 
298         if ( !Array || Array->IsEmpty() ) continue;
299 
300         if ( !Filter.IsEmpty() )
301         {
302             if ( (*Array)[0]->LibraryName.Upper().Find(Filter) == wxNOT_FOUND &&
303                  (*Array)[0]->ShortCode.Upper().Find(Filter)   == wxNOT_FOUND )
304             {
305                 // This result has been filtered
306                 continue;
307             }
308         }
309 
310         if ( Tree )
311         {
312             wxArrayString& Categories = (*Array)[0]->Categories;
313             if ( Categories.IsEmpty() )
314                 BuildEntry(OtherCategoryId(),*Array);
315             else
316             {
317                 for ( size_t cat = 0; cat < Categories.Count(); ++cat )
318                     BuildEntry(CategoryId(Categories[cat]), *Array);
319             }
320         }
321         else
322             BuildEntry(m_KnownLibrariesTree->GetRootItem(), *Array);
323     }
324 
325     // Now add pkg-config entries in separate category at the end
326     Vars.Clear();
327     m_KnownLibs[rtPkgConfig].GetShortCodes(Vars);
328 
329     if ( !Vars.IsEmpty() )
330     {
331         for ( size_t i=0; i<Vars.Count(); i++ )
332         {
333             ResultArray& Array = m_KnownLibs[rtPkgConfig].GetShortCode(Vars[i]);
334             if ( Array.IsEmpty() ) continue;
335 
336             if ( !Filter.IsEmpty() )
337             {
338                 if ( Array[0]->LibraryName.Upper().Find(Filter) == wxNOT_FOUND &&
339                      Array[0]->ShortCode.Upper().Find(Filter)   == wxNOT_FOUND )
340                 {
341                     // This result has been filtered
342                     continue;
343                 }
344             }
345 
346             BuildEntry(Tree ? PkgConfigId() : m_KnownLibrariesTree->GetRootItem(),Array);
347         }
348     }
349 
350     // Ok, let's present all results
351 //    m_KnownLibrariesTree->ExpandAll();
352     m_KnownLibrariesTree->Thaw();
353 }
354 
BuildEntry(const wxTreeItemId & Id,ResultArray & Array)355 void ProjectConfigurationPanel::BuildEntry(const wxTreeItemId& Id,ResultArray& Array)
356 {
357     wxString Name = Array[0]->ShortCode;
358     if ( !Array[0]->LibraryName.IsEmpty() )
359         Name = Name + _T(": ") + Array[0]->LibraryName;
360     m_KnownLibrariesTree->AppendItem(Id,Name,0,0,new TreeItemData(Array[0]->ShortCode));
361 }
362 
OtherCategoryId()363 wxTreeItemId ProjectConfigurationPanel::OtherCategoryId()
364 {
365     if ( m_IsOtherCategory )
366         return m_CategoryMap[_T(".other")];
367 
368     m_IsOtherCategory = true;
369     return m_CategoryMap[_T(".other")] = m_KnownLibrariesTree->AppendItem(m_KnownLibrariesTree->GetRootItem(),_("Other"));
370 }
371 
PkgConfigId()372 wxTreeItemId ProjectConfigurationPanel::PkgConfigId()
373 {
374     if ( m_IsPkgConfig )
375         return m_CategoryMap[_T(".pkg-config")];
376     m_IsPkgConfig = true;
377     return m_CategoryMap[_T(".pkg-config")] = m_KnownLibrariesTree->AppendItem(m_KnownLibrariesTree->GetRootItem(),_("Available in pkg-config"));
378 }
379 
CategoryId(const wxString & Category)380 wxTreeItemId ProjectConfigurationPanel::CategoryId(const wxString& Category)
381 {
382     if ( m_CategoryMap.find(Category.Lower()) != m_CategoryMap.end() )
383         return m_CategoryMap[Category.Lower()];
384 
385     wxStringTokenizer Tokens(Category,_T("."),wxTOKEN_STRTOK);
386     wxString PathSoFar = _T("");
387     wxTreeItemId IdSoFar = m_KnownLibrariesTree->GetRootItem();
388     bool FirstElem = true;
389     while ( Tokens.HasMoreTokens() )
390     {
391         // Iterate through items already added to map
392         wxString Part = Tokens.GetNextToken();
393         PathSoFar += Part.Lower();
394         if ( m_CategoryMap.find(PathSoFar) == m_CategoryMap.end() )
395         {
396             // Ok, found first node which is not yet added, this mean
397             // that all subnodes are also not yet added
398             int SkipLast = FirstElem ? (m_IsOtherCategory?1:0) + (m_IsPkgConfig?1:0) : 0;
399 
400             // First elem of the path must take into consideration
401             // that some categoies must remain at the end
402             if ( SkipLast )
403             {
404                 IdSoFar = m_CategoryMap[PathSoFar] =
405                     m_KnownLibrariesTree->InsertItem(
406                         IdSoFar,
407                         m_KnownLibrariesTree->GetChildrenCount(IdSoFar,false)-SkipLast,
408                         Part);
409                 FirstElem = false;
410             }
411             else
412             {
413                 IdSoFar = m_CategoryMap[PathSoFar] =
414                     m_KnownLibrariesTree->AppendItem(IdSoFar,Part);
415             }
416 
417             // Next items are always added at the end
418             while ( Tokens.HasMoreTokens() )
419             {
420                 Part = Tokens.GetNextToken();
421                 PathSoFar += _T(".");
422                 PathSoFar = Part.Lower();
423                 IdSoFar = m_CategoryMap[PathSoFar] =
424                     m_KnownLibrariesTree->AppendItem(IdSoFar,Part);
425             }
426 
427             // If we're here, all remaining path has been added, so we
428             // finished here
429             break;
430         }
431         FirstElem = false;
432         PathSoFar += _T(".");
433     }
434     // Just for sure if there are multiple dots
435     m_CategoryMap[Category.Lower()] = IdSoFar;
436     return IdSoFar;
437 }
438 
Onm_TreeClick(wxCommandEvent &)439 void ProjectConfigurationPanel::Onm_TreeClick(wxCommandEvent& /*event*/)
440 {
441     FillKnownLibraries();
442 }
443 
OnTimer1Trigger(wxTimerEvent &)444 void ProjectConfigurationPanel::OnTimer1Trigger(wxTimerEvent& /*event*/)
445 {
446     FillKnownLibraries();
447 }
448 
Onm_FilterText(wxCommandEvent &)449 void ProjectConfigurationPanel::Onm_FilterText(wxCommandEvent& /*event*/)
450 {
451     Timer1.Start(500,true);
452 }
453 
Onm_FilterTextEnter(wxCommandEvent &)454 void ProjectConfigurationPanel::Onm_FilterTextEnter(wxCommandEvent& /*event*/)
455 {
456     FillKnownLibraries();
457 }
458 
Onm_KnownLibrariesTreeSelectionChanged(wxTreeEvent &)459 void ProjectConfigurationPanel::Onm_KnownLibrariesTreeSelectionChanged(wxTreeEvent& /*event*/)
460 {
461     if ( m_KnownLibrariesTree->GetSelection().IsOk() )
462     {
463         TreeItemData* Data = (TreeItemData*)m_KnownLibrariesTree->GetItemData(m_KnownLibrariesTree->GetSelection());
464         if ( Data )
465         {
466             wxString Library = Data->m_ShortCode;
467             if ( m_ConfCopy.m_GlobalUsedLibs.Index(Library) == wxNOT_FOUND )
468             {
469                 m_Add->Enable();
470                 return;
471             }
472         }
473     }
474     m_Add->Disable();
475 }
476 
Onm_UsedLibrariesSelect(wxCommandEvent &)477 void ProjectConfigurationPanel::Onm_UsedLibrariesSelect(wxCommandEvent& /*event*/)
478 {
479     m_Remove->Enable( m_UsedLibraries->GetSelection() != wxNOT_FOUND );
480 }
481 
Onm_RemoveClick(wxCommandEvent &)482 void ProjectConfigurationPanel::Onm_RemoveClick(wxCommandEvent& /*event*/)
483 {
484     if ( m_UsedLibraries->GetSelection() != wxNOT_FOUND )
485     {
486         wxString Library =
487             ((ListItemData*)m_UsedLibraries->GetClientObject(
488                 m_UsedLibraries->GetSelection()))->m_ShortCode;
489         m_ConfCopy.m_GlobalUsedLibs.Remove(Library);
490         m_UsedLibraries->Delete(m_UsedLibraries->GetSelection());
491         m_Remove->Disable();
492         wxTreeEvent ev;
493         Onm_KnownLibrariesTreeSelectionChanged(ev);
494     }
495 }
496 
Onm_AddClick(wxCommandEvent &)497 void ProjectConfigurationPanel::Onm_AddClick(wxCommandEvent& /*event*/)
498 {
499     if ( m_KnownLibrariesTree->GetSelection().IsOk() )
500     {
501         TreeItemData* Data = (TreeItemData*)m_KnownLibrariesTree->GetItemData(m_KnownLibrariesTree->GetSelection());
502         if ( Data )
503         {
504             wxString Library = Data->m_ShortCode;
505             if ( m_ConfCopy.m_GlobalUsedLibs.Index(Library) == wxNOT_FOUND )
506             {
507                 m_ConfCopy.m_GlobalUsedLibs.Add(Library);
508                 m_UsedLibraries->Append(GetUserListName(Library),new ListItemData(Library));
509                 m_Add->Disable();
510                 return;
511             }
512         }
513     }
514 }
515 
Onm_UnknownLibraryText(wxCommandEvent &)516 void ProjectConfigurationPanel::Onm_UnknownLibraryText(wxCommandEvent& /*event*/)
517 {
518     m_AddUnknown->Enable(m_UnknownLibrary->GetLastPosition()!=0);
519 }
520 
Onm_AddUnknownClick(wxCommandEvent &)521 void ProjectConfigurationPanel::Onm_AddUnknownClick(wxCommandEvent& /*event*/)
522 {
523     wxString Library = m_UnknownLibrary->GetValue();
524     if ( !Library.IsEmpty() )
525     {
526         if ( m_ConfCopy.m_GlobalUsedLibs.Index(Library) == wxNOT_FOUND )
527         {
528             m_ConfCopy.m_GlobalUsedLibs.Add(Library);
529             m_UsedLibraries->Append(GetUserListName(Library),new ListItemData(Library));
530             wxTreeEvent ev;
531             Onm_KnownLibrariesTreeSelectionChanged(ev);
532         }
533     }
534 }
535 
Onm_AddScriptClick(wxCommandEvent &)536 void ProjectConfigurationPanel::Onm_AddScriptClick(wxCommandEvent& /*event*/)
537 {
538     wxFile Fl(m_Project->GetBasePath() + wxFileName::GetPathSeparator() + _T("lib_finder.script"),wxFile::write);
539     if ( !Fl.IsOpened() )
540     {
541         wxMessageBox(_("Couldn't create file \"lib_finder.script\" in project's base path"),_("lib_finder.script error"),wxOK|wxICON_ERROR,this);
542         return;
543     }
544 
545     if ( !Fl.Write(
546         _T("function SetBuildOptions(base)\n")
547         _T("{\n")
548         _T("\tif ( \"LibFinder\" in getroottable() )\n")
549         _T("\t{\n")
550         _T("\t\tLibFinder.SetupTarget(base);\n")
551         _T("\t}\n")
552         _T("}\n"),
553         wxConvUTF8) )
554     {
555         wxMessageBox(_("Couldn't write script file \"lib_finder.script\"."),_("lib_finder.script error"),wxOK|wxICON_ERROR,this);
556         return;
557     }
558     Fl.Close();
559 
560     m_Project->AddBuildScript(_T("lib_finder.script"));
561     m_AddScript->Disable();
562     m_NoAuto->SetValue(true);
563 
564     wxMessageBox(_("Script \"lib_finder.script\" successfully added."),_("lib_finder.script Success"),wxOK|wxICON_INFORMATION,this);
565 }
566 
OnButton2Click(wxCommandEvent &)567 void ProjectConfigurationPanel::OnButton2Click(wxCommandEvent& /*event*/)
568 {
569     wxArrayString HeadersBase;
570     if ( HeadersDetectorDlg(this,m_Project,HeadersBase).ShowModal() != wxID_OK )
571     {
572         cbMessageBox( _("Cancelled the search"), _("Cancelled"), wxOK | wxICON_WARNING, this );
573         return;
574     }
575 
576     if ( HeadersBase.IsEmpty() )
577     {
578         cbMessageBox( _("Didn't found any #include directive."), _("Error"), wxOK | wxICON_ERROR, this );
579         return;
580     }
581 
582     // Getting array of all known libraries
583     ResultArray AllArray;
584     for ( int i=0; i<rtCount; i++ )
585         m_KnownLibs[i].GetAllResults(AllArray);
586     wxArrayString NewLibs;
587 
588     // Sorting and removing duplicates and processing results
589     HeadersBase.Sort();
590     wxString Previous;
591     for ( size_t i=0; i<HeadersBase.Count(); i++ )
592     {
593         if ( Previous != HeadersBase[i] )
594         {
595             Previous = HeadersBase[i];
596             DetectNewLibs( Previous, AllArray, NewLibs );
597         }
598     }
599 
600     // Filtering detected results
601     wxArrayString NewLibsFiltered;
602     NewLibs.Sort();
603     Previous.Clear();
604     for ( size_t i=0; i<NewLibs.Count(); i++ )
605     {
606         if ( Previous != NewLibs[i] )
607         {
608             Previous = NewLibs[i];
609             if ( m_ConfCopy.m_GlobalUsedLibs.Index(Previous) == wxNOT_FOUND )
610                 NewLibsFiltered.Add( Previous );
611         }
612     }
613 
614     if ( NewLibsFiltered.IsEmpty() )
615     {
616         cbMessageBox(
617             _("Didn't found any missing library for your project.\n"
618               "\n"
619               "This may mean that you project is fully configured\n"
620               "or that missing libraries are not yet recognized\n"
621               "or fully supported in lib_finder plugin"),
622             _("No libraries found"),
623             wxOK | wxICON_ASTERISK,
624             this );
625         return;
626     }
627 
628     wxArrayInt Choices;
629 #if wxCHECK_VERSION(3, 0, 0)
630     wxGetSelectedChoices(
631 #else
632     wxGetMultipleChoices(
633 #endif
634         Choices,
635         _("Select libraries to include in your project"),
636         _("Adding new libraries"),
637         NewLibsFiltered,
638         this);
639 
640     if ( Choices.IsEmpty() )
641         return;
642 
643     for ( size_t i=0; i<Choices.Count(); i++ )
644     {
645         wxString Library = NewLibsFiltered[ Choices[i] ];
646         m_ConfCopy.m_GlobalUsedLibs.Add(Library);
647         m_UsedLibraries->Append(GetUserListName(Library),new ListItemData(Library));
648     }
649 
650     // Make sure that after the scan, used won't be able to manually
651     // add currently selected "known" library (through '<' button)
652     // which has just been added automatically
653     wxTreeEvent ev;
654     Onm_KnownLibrariesTreeSelectionChanged(ev);
655 }
656 
DetectNewLibs(const wxString & IncludeName,ResultArray & known,wxArrayString & LibsList)657 void ProjectConfigurationPanel::DetectNewLibs( const wxString& IncludeName, ResultArray& known, wxArrayString& LibsList )
658 {
659     wxString FixedInclude = IncludeName;
660     FixedInclude.MakeLower();
661     FixedInclude.Replace(_T("\\"),_T("/"),true);
662     for ( size_t i=0; i<known.Count(); i++ )
663     {
664         for ( size_t j=0; j<known[i]->Headers.Count(); j++ )
665         {
666             if ( FixedInclude.Matches( known[i]->Headers[j].Lower() ) )
667             {
668                 LibsList.Add( known[i]->ShortCode );
669                 break;
670             }
671         }
672     }
673 }
674