]> Creatis software - crea.git/blob - lib/creaDevManagerLib/modelCDMProject.cpp
Feature #1711 CreaDevManager application implementation
[crea.git] / lib / creaDevManagerLib / modelCDMProject.cpp
1 /*
2 # ---------------------------------------------------------------------
3 #
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image 
5 #                        pour la Sant�)
6 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
9 #
10 #  This software is governed by the CeCILL-B license under French law and 
11 #  abiding by the rules of distribution of free software. You can  use, 
12 #  modify and/ or redistribute the software under the terms of the CeCILL-B 
13 #  license as circulated by CEA, CNRS and INRIA at the following URL 
14 #  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html 
15 #  or in the file LICENSE.txt.
16 #
17 #  As a counterpart to the access to the source code and  rights to copy,
18 #  modify and redistribute granted by the license, users are provided only
19 #  with a limited warranty  and the software's author,  the holder of the
20 #  economic rights,  and the successive licensors  have only  limited
21 #  liability. 
22 #
23 #  The fact that you are presently reading this means that you have had
24 #  knowledge of the CeCILL-B license and that you accept its terms.
25 # ------------------------------------------------------------------------ 
26  */
27
28 /*
29  * modelCDMProject.cpp
30  *
31  *  Created on: 13/11/2012
32  *      Author: Daniel Felipe Gonzalez Obando
33  */
34
35 #include "modelCDMProject.h"
36
37 #include <iostream>
38 #include <sstream>
39 #include <vector>
40 #include <algorithm>
41 #include <fstream>
42 #include <ctime>
43 #include <boost/regex.hpp>
44
45 #include "CDMUtilities.h"
46 #include "creaWx.h"
47 #include "wx/dir.h"
48
49 modelCDMProject::modelCDMProject()
50 {
51   std::cout << "in constructor1" << std::endl;
52   this->appli = NULL;
53   this->lib = NULL;
54   this->CMakeLists = NULL;
55 }
56
57 modelCDMProject::modelCDMProject(
58     modelCDMIProjectTreeNode* parent,
59     const std::string& path,
60     const std::string& name,
61     const std::string& buildPath
62 )
63 {
64   std::cout << "creating project: " + name + " in " + path + "\n";
65   this->parent = parent;
66   this->path = CDMUtilities::fixPath(path);
67   //open makelists file
68   std::string pathFixed(CDMUtilities::fixPath(path));
69
70   std::string pathMakeLists = pathFixed + CDMUtilities::SLASH + "CMakeLists.txt";
71
72   std::ifstream confFile;
73   confFile.open((pathMakeLists).c_str());
74
75   std::string word;
76   while(confFile.is_open() && !confFile.eof())
77     {
78       //std::cout << "leyendo " << word << std::endl;
79       //get project name
80       std::getline(confFile,word,'(');
81       std::vector<std::string> wordBits;
82       CDMUtilities::splitter::split(wordBits,word," (\n",CDMUtilities::splitter::no_empties);
83
84       if(wordBits[wordBits.size()-1] == "PROJECT")
85         {
86           std::getline(confFile,word,')');
87           std::vector<std::string> nameBits;
88           CDMUtilities::splitter::split(nameBits, word, " ", CDMUtilities::splitter::no_empties);
89
90           this->name = this->nameProject = "";
91           for (int i = 0; i < (int)(nameBits.size()); i++)
92             {
93               if(i != 0)
94                 this->name += " ";
95               this->name += nameBits[i];
96             }
97           this->nameProject = this->name;
98
99         }
100
101
102       if(wordBits[wordBits.size()-1] == "SET")
103         {
104           //get project version
105           std::getline(confFile,word,')');
106           CDMUtilities::splitter::split(wordBits, word, " ", CDMUtilities::splitter::no_empties);
107           if(wordBits[0] == "PROJECT_MAJOR_VERSION")
108             {
109               version = wordBits[1];
110             }
111           if(wordBits[0] == "PROJECT_MINOR_VERSION")
112             {
113               version += "." + wordBits[1];
114             }
115           if(wordBits[0] == "PROJECT_BUILD_VERSION")
116             {
117               version += "." + wordBits[1];
118             }
119
120           //get project versionDate
121           if(wordBits[0] == "PROJECT_VERSION_DATE")
122             {
123               std::vector<std::string> versionBits;
124               CDMUtilities::splitter::split(versionBits, wordBits[1], "\"", CDMUtilities::splitter::no_empties);
125               versionDate = versionBits[0];
126             }
127           //get project buildPath
128
129           if (buildPath != "")
130             {
131               this->buildPath = buildPath;
132             }
133           else
134             {
135               this->buildPath = this->path + "Bin";
136             }
137         }
138     }
139   confFile.close();
140
141   this->type = wxDIR_DIRS;
142   this->level = 0;
143
144   this->children.clear();
145   this->appli = NULL;
146   this->lib = NULL;
147   this->packages.clear();
148
149
150   //check all folders
151   wxDir dir(crea::std2wx((pathFixed).c_str()));
152   if (dir.IsOpened())
153     {
154       wxString fileName;
155       bool cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_DIRS);
156       while (cont)
157         {
158           std::string stdfileName = crea::wx2std(fileName);
159
160           //if appli, create appli
161           if(stdfileName == "appli")
162             {
163               this->appli = new modelCDMAppli(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
164               this->children.push_back(this->appli);
165             }
166           //if lib, create lib
167           else if(stdfileName == "lib")
168             {
169               this->lib = new modelCDMLib(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
170               this->children.push_back(this->lib);
171             }
172           //if package , create package
173           else if(stdfileName.size() > 9 && stdfileName.substr(0,5) == "bbtk_" && stdfileName.substr(stdfileName.size()-4,4) == "_PKG")
174             {
175               modelCDMPackage* package = new modelCDMPackage(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
176               this->packages.push_back(package);
177               this->children.push_back(package);
178             }
179           //if is an unknown folder, create folder
180           else
181             {
182               this->children.push_back(new modelCDMFolder(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
183             }
184
185           cont = dir.GetNext(&fileName);
186         }
187
188       cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_FILES);
189       while (cont)
190         {
191           std::string stdfileName = crea::wx2std(fileName);
192           std::size_t fileTypePos = stdfileName.find_last_of(".");
193           std::string fileType = stdfileName.substr(fileTypePos);
194
195           //if CMakeLists, create CMakeLists
196           if(stdfileName == "CMakeLists.txt")
197             {
198               this->CMakeLists = new modelCDMCMakeListsFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
199               this->children.push_back(this->CMakeLists);
200             }
201           //if is a code file, create modelCDMCodeFile
202           else if(
203               fileType == ".c" ||
204               fileType == ".cxx" ||
205               fileType == ".h" ||
206               fileType == ".cpp" ||
207               fileType == ".txx" ||
208               fileType == ".cmake" )
209             {
210               this->children.push_back(new modelCDMCodeFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
211             }
212           //if is an unknown file, create file
213           else
214             {
215               this->children.push_back(new modelCDMFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
216             }
217
218           cont = dir.GetNext(&fileName);
219         }
220     }
221
222   this->SortChildren();
223   std::sort(this->packages.begin(), this->packages.end(), CompareNodeItem);
224
225 }
226
227 modelCDMProject::~modelCDMProject()
228 {
229 }
230
231 const std::string& modelCDMProject::GetNameProject() const
232 {
233   return this->nameProject;
234 }
235
236 const std::string& modelCDMProject::GetVersion() const
237 {
238   return this->version;
239 }
240
241 const std::string& modelCDMProject::GetVersionDate() const
242 {
243   return this->versionDate;
244 }
245
246 const std::string& modelCDMProject::GetBuildPath() const
247 {
248   return this->buildPath;
249 }
250
251 const std::vector<modelCDMPackage*>& modelCDMProject::GetPackages() const
252 {
253   return this->packages;
254 }
255
256 modelCDMAppli* modelCDMProject::GetAppli() const
257 {
258   return this->appli;
259 }
260
261 modelCDMLib* modelCDMProject::GetLib() const
262 {
263   return this->lib;
264 }
265
266 std::string modelCDMProject::GetBuildInstruction() const
267 {
268   std::string makeComm = "make -C \"" + this->buildPath + "\""; /*> \"" + this->buildPath + CDMUtilities::SLASH + "building.log\" 2>&1";*/
269   return makeComm;
270 }
271
272 bool modelCDMProject::SetVersion(const std::string& version, std::string*& result)
273 {
274
275   std::vector<std::string> vers;
276   CDMUtilities::splitter::split(vers, version, " .", CDMUtilities::splitter::no_empties);
277
278   time_t now = time(0);
279
280   tm ltm;
281 #ifdef _WIN32
282   localtime_s(&ltm, &now);
283 #else
284   ltm = *(localtime(&now));
285 #endif
286
287   std::stringstream date;
288   date << ltm.tm_mday << "/" << 1 + ltm.tm_mon << "/" << 1900 + ltm.tm_year;
289
290   //set name of library in CMakeLists inside copied folder
291   std::string line;
292   std::ifstream in((this->path + CDMUtilities::SLASH + "CMakeLists.txt").c_str());
293   if( !in.is_open())
294     {
295       result = new std::string("CMakeLists.txt file failed to open.");
296       return false;
297     }
298   std::ofstream out((this->path + CDMUtilities::SLASH + "CMakeLists.txt.tmp").c_str());
299   if( !out.is_open())
300     {
301       result = new std::string("CMakeLists.txt.tmp file failed to open.");
302       return false;
303     }
304   while (getline(in, line))
305     {
306       if(line.find("SET(PROJECT_MAJOR_VERSION") != std::string::npos)
307         line = "SET(PROJECT_MAJOR_VERSION " + vers[0] + ")";
308       else if(line.find("SET(PROJECT_MINOR_VERSION") != std::string::npos)
309         line = "SET(PROJECT_MINOR_VERSION " + vers[1] + ")";
310       else if(line.find("SET(PROJECT_BUILD_VERSION") != std::string::npos)
311         line = "SET(PROJECT_BUILD_VERSION " + vers[2] + ")";
312       else if(line.find("SET(PROJECT_VERSION_DATE") != std::string::npos)
313         line = "SET(PROJECT_VERSION_DATE \"" + date.str() + "\")";
314       out << line << std::endl;
315     }
316   in.close();
317   out.close();
318   //delete old file and rename new file
319 #ifdef _WIN32
320   std::string renameCommand = "move /Y \"" + this->path + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + "CMakeLists.txt\"";
321 #else
322   std::string renameCommand = "mv \"" + this->path + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + "CMakeLists.txt\"";
323 #endif
324   if(system(renameCommand.c_str()))
325     {
326       result = new std::string("An error occurred while running '" + renameCommand + "'.");
327       return false;
328     }
329
330   this->version = vers[0] + "." + vers[1] + "." + vers[2];
331   this->versionDate = date.str();
332   return true;
333 }
334
335 bool modelCDMProject::SetBuildPath(const std::string& path, std::string*& result)
336 {
337   if(path == "")
338     {
339       result = new std::string("The path cannot be empty");
340       return false;
341     }
342   if(path == this->path)
343     {
344       result = new std::string("The path cannot be same as the project sources");
345       return false;
346     }
347   this->buildPath = path;
348   return true;
349 }
350
351 modelCDMIProjectTreeNode* modelCDMProject::CreatePackage(
352     const std::string& name,
353     std::string*& result,
354     const std::string& authors,
355     const std::string& authorsEmail,
356     const std::string& description,
357     const std::string& version
358 )
359 {
360   //fixing input parameters
361   std::vector<std::string> words;
362
363   CDMUtilities::splitter::split(words,name," '/\"\\,.",CDMUtilities::splitter::no_empties);
364   std::string nameFixed = "";
365   for (int i = 0; i < (int)(words.size()); i++)
366     {
367       nameFixed += words[i];
368     }
369
370   words.clear();
371   CDMUtilities::splitter::split(words,authors," '/\"\\,.",CDMUtilities::splitter::no_empties);
372   std::string authorFixed;
373   for (int i = 0; i < (int)(words.size()); i++)
374     {
375       authorFixed += words[i];
376     }
377
378   words.clear();
379   std::string descriptionFixed;
380   CDMUtilities::splitter::split(words,authorsEmail," '/\"\\,",CDMUtilities::splitter::no_empties);
381   for (int i = 0; i < (int)(words.size()); i++)
382     {
383       descriptionFixed += words[i] + "/";
384     }
385   words.clear();
386   CDMUtilities::splitter::split(words,description," '\"",CDMUtilities::splitter::no_empties);
387   for (int i = 0; i < (int)(words.size()); i++)
388     {
389       descriptionFixed += "_" + words[i];
390     }
391
392   //call project to create package : use bbCreatePackage <path> <name> [author] [description]
393   std::string creationCommand = "bbCreatePackage \"" + this->path + "\" \"" + nameFixed + "\" \"" + authorFixed + "\" \"" + descriptionFixed + "\"";
394   //TODO: bbCreatePackage script always returning 0. It should return 1 or greater if any error
395   bool resultCommand = 0 != system(creationCommand.c_str());
396 #ifdef _WIN32
397   resultCommand = false;
398 #endif
399   if(resultCommand)
400     {
401       result = new std::string("An error occurred while running '" + creationCommand + "'.");
402       return NULL;
403     }
404
405   //add library to project CMakeLists
406   std::fstream out1((this->path + CDMUtilities::SLASH + "CMakeLists.txt").c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
407   if (out1.is_open())
408     {
409       out1 << "ADD_SUBDIRECTORY(bbtk_" << nameFixed << "_PKG)" << std::endl;
410       out1.close();
411     }
412
413   //add library to model
414   modelCDMPackage* package = new modelCDMPackage(this, this->path + CDMUtilities::SLASH + "bbtk_" + nameFixed + "_PKG", "bbtk_" + nameFixed + "_PKG", this->level + 1);
415   this->packages.push_back(package);
416   this->children.push_back(package);
417
418   //TODO: set package version
419
420   this->SortChildren();
421
422   result = new std::string(this->path + CDMUtilities::SLASH + name);
423   return package;
424 }
425
426 modelCDMIProjectTreeNode* modelCDMProject::CreateLibrary(
427     const std::string& name,
428     std::string*& result,
429     const std::string& path
430 )
431 {
432   if(this->lib != NULL)
433     {
434       return this->lib->CreateLibrary(name, result);
435     }
436   result = new std::string("there is no lib folder in this project.");
437   return NULL;
438 }
439
440 modelCDMIProjectTreeNode* modelCDMProject::CreateApplication(
441     const std::string& name,
442     const int& type,
443     std::string*& result,
444     const std::string& path
445 )
446 {
447   if(this->appli != NULL)
448     {
449       return this->appli->CreateApplication(name, type, result);
450     }
451   result = new std::string("there is no appli folder in this project.");
452   return NULL;
453 }
454
455 modelCDMIProjectTreeNode* modelCDMProject::CreateBlackBox(
456     const std::string& name,
457     const std::string& package,
458     const std::string& authors,
459     const std::string& authorsEmail,
460     const std::string& categories,
461     const std::string& description
462 )
463 {
464   //TODO: implement method
465   return NULL;
466 }
467
468 bool modelCDMProject::OpenCMakeListsFile(std::string*& result)
469 {
470   if (!CDMUtilities::openTextEditor(this->CMakeLists->GetPath()))
471     return true;
472   else
473     {
474       result = new std::string("Couldn't open CMakeLists file.");
475       return false;
476     }
477 }
478
479 const bool modelCDMProject::Refresh(std::string*& result)
480 {
481   std::cout << "refreshing project" << std::endl;
482   //open makelists file
483   std::string pathMakeLists = this->path + CDMUtilities::SLASH + "CMakeLists.txt";
484
485   std::ifstream confFile;
486   confFile.open((pathMakeLists).c_str());
487
488   std::string word;
489   while(confFile.is_open() && !confFile.eof())
490     {
491       //std::cout << "leyendo " << word << std::endl;
492       //get project name
493       std::getline(confFile,word,'(');
494       std::vector<std::string> wordBits;
495       CDMUtilities::splitter::split(wordBits,word," (\n",CDMUtilities::splitter::no_empties);
496
497       if(wordBits[wordBits.size()-1] == "PROJECT")
498         {
499           std::getline(confFile,word,')');
500           std::vector<std::string> nameBits;
501           CDMUtilities::splitter::split(nameBits, word, " ", CDMUtilities::splitter::no_empties);
502
503           this->name = this->nameProject = "";
504           for (int i = 0; i < (int)(nameBits.size()); i++)
505             {
506               if(i != 0)
507                 this->name += " ";
508               this->name += nameBits[i];
509             }
510           this->nameProject = this->name;
511
512         }
513
514
515       if(wordBits[wordBits.size()-1] == "SET")
516         {
517           //get project version
518           std::getline(confFile,word,')');
519           CDMUtilities::splitter::split(wordBits, word, " ", CDMUtilities::splitter::no_empties);
520           if(wordBits[0] == "PROJECT_MAJOR_VERSION")
521             {
522               version = wordBits[1];
523             }
524           if(wordBits[0] == "PROJECT_MINOR_VERSION")
525             {
526               version += "." + wordBits[1];
527             }
528           if(wordBits[0] == "PROJECT_BUILD_VERSION")
529             {
530               version += "." + wordBits[1];
531             }
532
533           //get project versionDate
534           if(wordBits[0] == "PROJECT_VERSION_DATE")
535             {
536               std::vector<std::string> versionBits;
537               CDMUtilities::splitter::split(versionBits, wordBits[1], "\"", CDMUtilities::splitter::no_empties);
538               versionDate = versionBits[0];
539             }
540         }
541     }
542   confFile.close();
543
544   this->type = wxDIR_DIRS;
545   this->level = 0;
546
547   std::vector<bool> checked(this->children.size(), false);
548   std::vector<bool> checkedPackages(this->packages.size(), false);
549
550   //check all folders
551   wxDir dir(crea::std2wx((this->path).c_str()));
552   if (dir.IsOpened())
553     {
554       wxString fileName;
555       bool cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_DIRS);
556       while (cont)
557         {
558           std::string stdfileName = crea::wx2std(fileName);
559
560           //if appli, create appli
561           if(stdfileName == "appli")
562             {
563               if (this->appli == NULL)
564                 {
565                   this->appli = new modelCDMAppli(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
566                   this->children.push_back(this->appli);
567                 }
568               else
569                 {
570                   int pos = std::find(this->children.begin(), this->children.end(), this->appli) - this->children.begin();
571                   checked[pos] = true;
572                   if(!this->appli->Refresh(result))
573                     return false;
574                 }
575             }
576           //if lib, create lib
577           else if(stdfileName == "lib")
578             {
579               if (this->lib == NULL)
580                 {
581                   this->lib = new modelCDMLib(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
582                   this->children.push_back(this->lib);
583                 }
584               else
585                 {
586                   int pos = std::find(this->children.begin(), this->children.end(), this->lib) - this->children.begin();
587                   checked[pos] = true;
588                   if(!this->lib->Refresh(result))
589                     return false;
590                 }
591
592             }
593           //if package , create package
594           else if(stdfileName.size() > 9 && stdfileName.substr(0,5) == "bbtk_" && stdfileName.substr(stdfileName.size()-4,4) == "_PKG")
595             {
596               bool found = false;
597               for (int i = 0; !found && i < (int)(this->packages.size()); i++)
598                 {
599                   if (this->packages[i]->GetName() == stdfileName)
600                     {
601                       found = true;
602                       int pos = std::find(this->children.begin(), this->children.end(), this->packages[i]) - this->children.begin();
603                       checked[pos] = true;
604                       checkedPackages[i] = true;
605                       if(!this->packages[i]->Refresh(result))
606                         return false;
607                     }
608                 }
609               if(!found)
610                 {
611                   modelCDMPackage* package = new modelCDMPackage(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
612                   this->packages.push_back(package);
613                   this->children.push_back(package);
614                 }
615
616             }
617           //if is an unknown folder, create folder
618           else
619             {
620               bool found = false;
621               for (int i = 0; !found && i < (int)(this->children.size()); i++)
622                 {
623                   if (this->children[i]->GetName() == stdfileName)
624                     {
625                       found = true;
626                       checked[i] = true;
627                       if(!this->children[i]->Refresh(result))
628                         return false;
629                     }
630                 }
631
632               if(!found)
633                 {
634                   modelCDMFolder* folder = new modelCDMFolder(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
635                   this->children.push_back(folder);
636                 }
637             }
638
639           cont = dir.GetNext(&fileName);
640         }
641
642       cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_FILES);
643       while (cont)
644         {
645           std::string stdfileName = crea::wx2std(fileName);
646           std::size_t fileTypePos = stdfileName.find_last_of(".");
647           std::string fileType = stdfileName.substr(fileTypePos);
648
649           //if CMakeLists, create CMakeLists
650           if(stdfileName == "CMakeLists.txt")
651             {
652               if (this->CMakeLists == NULL)
653                 {
654                   this->CMakeLists = new modelCDMCMakeListsFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
655                   this->children.push_back(this->CMakeLists);
656                 }
657               else
658                 {
659                   int pos = std::find(this->children.begin(), this->children.end(), this->CMakeLists) - this->children.begin();
660                   checked[pos] = true;
661                   if(!this->CMakeLists->Refresh(result))
662                     return false;
663                 }
664             }
665           //if is a code file, create modelCDMCodeFile
666           //if is an unknown file, create file
667           else
668             {
669               bool found = false;
670               for (int i = 0; !found && i < (int)(this->children.size()); i++)
671                 {
672                   if (this->children[i]->GetName() == stdfileName)
673                     {
674                       found = true;
675                       checked[i] = true;
676                       if(!this->children[i]->Refresh(result))
677                         return false;
678                     }
679                 }
680
681               if(!found)
682                 {
683                   if(
684                     fileType == ".c" ||
685                     fileType == ".cxx" ||
686                     fileType == ".h" ||
687                     fileType == ".cpp" ||
688                     fileType == ".txx" ||
689                     fileType == ".cmake" )
690                     {
691                       this->children.push_back(new modelCDMCodeFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
692                     }
693                   else
694                     {
695                       modelCDMFile* file = new modelCDMFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
696                       this->children.push_back(file);
697                     }
698                 }
699             }
700
701           cont = dir.GetNext(&fileName);
702         }
703     }
704
705   for (int i = 0; i < (int)(checkedPackages.size()); i++)
706     {
707       if(!checkedPackages[i])
708         {
709           this->packages.erase(this->packages.begin()+i);
710           checkedPackages.erase(checkedPackages.begin()+i);
711           i--;
712         }
713     }
714   for (int i = 0; i < (int)(checked.size()); i++)
715     {
716       if(!checked[i])
717         {
718           delete this->children[i];
719           this->children.erase(this->children.begin()+i);
720           checked.erase(checked.begin()+i);
721           i--;
722         }
723     }
724
725   this->SortChildren();
726   std::sort(this->packages.begin(), this->packages.end(), CompareNodeItem);
727   return true;
728 }
729
730 bool modelCDMProject::ConfigureBuild(std::string*& result)
731 {
732   //TODO: adjust for windows and mac
733 #ifdef _WIN32
734   // ------ Windows
735   if(0 == system("cmake-gui"))
736     return true;
737   else
738     {
739           result = new std::string("There was an error opening cmake-gui. Please make sure it's installed and that cmake's bin folder is in the system path.");
740       return false;
741     }
742 #elif __APPLE__
743   // ------ Apple
744 #else
745   // ------ Linux
746   //open binary folder
747   wxDir dir(crea::std2wx((this->buildPath).c_str()));
748
749   //if folder doesn't exist then create it
750   if (!dir.IsOpened())
751     {
752       //create command line to create folder
753       std::string createComm = "mkdir \"" + this->buildPath + "\"";
754       //execute creation command
755       if (system(createComm.c_str()))
756         {
757           //if there was an error then report it
758           result = new std::string("There was an error creating the build path: \"" + this->buildPath + "\"");
759           return false;
760         }
761     }
762   //create command line to execute ccmake
763   //TODO:: adjust for different Linux distributions
764   std::string confComm = "gnome-terminal --tab --working-directory=\"" + this->buildPath + "\" -e \"ccmake '" + this->path + "'\"";
765   //execute command
766   if(CDMUtilities::openTerminal(confComm))
767     {
768       //if there was an error then report it
769       result = new std::string("There was an error opening the configuration tool in the desired place.");
770       return false;
771     }
772 #endif
773   return true;
774 }
775
776 bool modelCDMProject::Build(std::string*& result, const std::string& line)
777 {
778   //TODO: adjust for windows and mac
779 #ifdef _WIN32
780   // ------ Windows
781         std::string command = "start \"\" \"" + this->buildPath + CDMUtilities::SLASH + this->nameProject + ".sln\"";
782   //wxMessageBox(crea::std2wx(command), wxT("Project Compilation - Check!"));
783         if(0 == system(command.c_str()))
784     return true;
785   else
786     {
787       result = new std::string("An error has happened running: \"" + command + "\". Please make sure to have visual c++ installed.");
788           return false;
789     }
790 #elif __APPLE__
791   // ------ Apple
792 #else
793   // ------ Linux
794   //open binary folder
795   wxDir dir(crea::std2wx((this->buildPath).c_str()));
796
797   //if binary folder can't be opened then return false
798   if (!dir.IsOpened())
799     {
800       result = new std::string("The build path could not be opened. Make sure to configure the project before compiling it");
801       return false;
802     }
803   //create make command
804   std::string makeComm = "gnome-terminal -e \"bash -c \\\"";
805   for (int i = 0; i < line.size(); i++)
806     {
807       if(line[i] == '"')
808         {
809           makeComm+="\\\\\\\"";
810         }
811       else if(line[i] == '\\')
812         {
813           makeComm+="\\\\\\\\";
814         }
815       else
816         {
817           makeComm.push_back(line[i]);
818         }
819     }
820   makeComm += "; echo -e '\\a'; bash";
821   makeComm += "\\\"\"";
822
823   std::cout << "executing '" << makeComm << "'" << std::endl;
824   //execute make command
825   if(system(makeComm.c_str()))
826     {
827       //if there was an error then report it
828       result = new std::string("There was an error compiling the project, please check the \"building.log\" file located in the build folder to read more about the problem.");
829       return false;
830     }
831 #endif
832   return true;
833 }
834
835 bool modelCDMProject::Connect(std::string*& result, const std::string& folder)
836 {
837   //TODO: adjust for mac
838 #ifdef _WIN32
839   // ------ Windows
840   //open binary folder
841   wxDir dir(crea::std2wx(folder));
842
843   //if binary folder can't be opened then return false
844   if (!dir.IsOpened())
845     {
846       result = new std::string("The path could not be opened. Make sure the folder exists and contains a bbtkPackage file.");
847       return false;
848     }
849   //create plug command
850   std::string plugComm = "bbPlugPackage \"" + folder + "\"";
851   std::cout << "executing '" << plugComm << "'" << std::endl;
852   //execute plug command
853   if(system(std::string("start cmd.exe /k \"" + plugComm + "\"").c_str()))
854     {
855       //if there was an error then report it
856       result = new std::string("There was an error plugging the packages of the project, please check the console to read more about the problem.");
857       return false;
858     }
859 #elif __APPLE__
860   // ------ Apple
861 #else
862   // ------ Linux
863   //open binary folder
864   wxDir dir(crea::std2wx(folder));
865
866   //if binary folder can't be opened then return false
867   if (!dir.IsOpened())
868     {
869       result = new std::string("The path could not be opened. Make sure the folder exists and contains a bbtkPackage file.");
870       return false;
871     }
872   //create plug command
873   std::string plugComm = "bbPlugPackage \"" + this->buildPath + "\"";
874
875   std::string Comm = "gnome-terminal -e \"bash -c \\\"";
876     for (int i = 0; i < plugComm.size(); i++)
877       {
878         if(plugComm[i] == '"')
879           {
880             Comm+="\\\\\\\"";
881           }
882         else if(plugComm[i] == '\\')
883           {
884             Comm+="\\\\\\\\";
885           }
886         else
887           {
888             Comm.push_back(plugComm[i]);
889           }
890       }
891     Comm += "; echo -e '\\a'; bash";
892     Comm += "\\\"\"";
893
894
895   std::cout << "executing '" << Comm << "'" << std::endl;
896   //execute plug command
897   if(system(Comm.c_str()))
898     {
899       //if there was an error then report it
900       result = new std::string("There was an error plugging the packages of the project, please check the console to read more about the problem.");
901       return false;
902     }
903 #endif
904   return true;
905 }
906
907 void modelCDMProject::CheckStructure(std::map<std::string, bool>& properties)
908 {
909   //check cmake exist
910   if(this->CMakeLists != NULL)
911     {
912       //set properties parameters based on model
913       properties["project add appli"] = this->appli != NULL;
914       properties["project add lib"] = this->lib != NULL;
915       for (int i = 0; i < (int)(this->packages.size()); i++)
916         properties["project add " + packages[i]->GetName()] = false;
917
918       //open cmakelists
919       std::ifstream confFile;
920       confFile.open((this->CMakeLists->GetPath()).c_str());
921
922       //take everything that is not commented
923       std::string fileContent;
924
925       std::string word;
926       std::vector<std::string> words;
927       while(confFile.is_open() && !confFile.eof())
928         {
929           std::getline(confFile,word, '\n');
930           if(word[0] != '#')
931             {
932               CDMUtilities::splitter::split(words, word, "#", CDMUtilities::splitter::empties_ok);
933               if (words.size() > 0)
934                 {
935                   word = words[0];
936                   CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::empties_ok);
937                   for (int i = 0; i < (int)(words.size()); i++)
938                     {
939                       if(words[i].substr(0,2) == "//")
940                         break;
941                       fileContent += words[i] + " ";
942                     }
943                 }
944
945             }
946         }
947
948       //check every instruction
949       std::stringstream ss(fileContent);
950       while(!ss.eof())
951         {
952           std::getline(ss,word, '(');
953
954           //check instruction name
955           CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::no_empties);
956
957           //set instructions
958           if (words.size() > 0 && words[words.size()-1] == "SET")
959             {
960               std::getline(ss,word, ')');
961
962               CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::no_empties);
963               if (words.size() > 1)
964                 {
965                   if (words[0] == "USE_CREA" && words[1] == "ON")
966                     {
967                       properties["project set USE_CREA"] = true;
968                     }
969                   else if (words[0] == "USE_GDCM" && words[1] == "ON")
970                     {
971                       properties["project set USE_GDCM"] = true;
972                     }
973                   else if (words[0] == "USE_GDCM_VTK" && words[1] == "ON")
974                     {
975                       properties["project set USE_GDCM_VTK"] = true;
976                     }
977                   else if (words[0] == "USE_GDCM2" && words[1] == "ON")
978                     {
979                       properties["project set USE_GDCM2"] = true;
980                     }
981                   else if (words[0] == "USE_WXWIDGETS" && words[1] == "ON")
982                     {
983                       properties["project set USE_WXWIDGETS"] = true;
984                     }
985                   else if (words[0] == "USE_KWWIDGETS" && words[1] == "ON")
986                     {
987                       properties["project set USE_KWWIDGETS"] = true;
988                     }
989                   else if (words[0] == "USE_VTK" && words[1] == "ON")
990                     {
991                       properties["project set USE_VTK"] = true;
992                     }
993                   else if (words[0] == "USE_ITK" && words[1] == "ON")
994                     {
995                       properties["project set USE_ITK"] = true;
996                     }
997                   else if (words[0] == "USE_BOOST" && words[1] == "ON")
998                     {
999                       properties["project set USE_BOOST"] = true;
1000                     }
1001                 }
1002             }
1003           //add instructions
1004           else if (words.size() > 0 && words[words.size()-1] == "ADD_SUBDIRECTORY")
1005             {
1006               std::getline(ss,word, ')');
1007               //std::cout << word << std::endl;
1008               CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::no_empties);
1009
1010               if (words.size() > 0)
1011                 {
1012                   if(words[0] == "appli")
1013                     {
1014                       properties["project add "+words[0]] = this->appli != NULL;
1015                     }
1016                   else if(words[0] == "lib")
1017                     {
1018                       properties["project add "+words[0]] = this->lib != NULL;
1019                     }
1020                   else
1021                     {
1022                       properties["project add "+words[0]] = true;
1023                     }
1024                 }
1025             }
1026         }
1027
1028     }
1029
1030   //check appli's structure
1031   this->appli->CheckStructure(properties);
1032   //check lib's structure
1033   this->lib->CheckStructure(properties);
1034   //check packages' structure
1035   for (int i = 0; i < (int)(this->packages.size()); i++)
1036     {
1037       properties["package " + this->packages[i]->GetName()] = true;
1038       this->packages[i]->CheckStructure(properties);
1039     }
1040 }
1041
1042 bool modelCDMProject::IsPackageIncluded(const std::string& package_name)
1043 {
1044   if (this->HasCMakeLists())
1045     {
1046       CDMUtilities::CMLFile cmlFile = CDMUtilities::readCMLFile(this->CMakeLists->GetPath().c_str());
1047       for (int i = 0; i < cmlFile.size(); ++i)
1048         {
1049           if (cmlFile[i].first=="command" && cmlFile[i].second[0] == "ADD_SUBDIRECTORY")
1050             {
1051               int pos = 1;
1052               while (pos < cmlFile[i].second.size())
1053                 {
1054                   if (!isspace(cmlFile[i].second[pos][0]) && cmlFile[i].second[pos][0] != '(' && cmlFile[i].second[pos][0] != '#')
1055                     {
1056                       if (package_name == cmlFile[i].second[pos])
1057                         return true;
1058                       break;
1059                     }
1060                   pos++;
1061                 }
1062             }
1063         }
1064     }
1065   return false;
1066
1067 }
1068
1069 bool modelCDMProject::SetPackageInclude(const std::string& package_name, const bool& toInclude)
1070 {
1071   if (this->HasCMakeLists())
1072     {
1073       CDMUtilities::CMLFile cmlFile = CDMUtilities::readCMLFile(this->CMakeLists->GetPath().c_str());
1074
1075       bool found = false;
1076
1077       for (int i = 0; i < cmlFile.size(); ++i)
1078         {
1079           if(toInclude && cmlFile[i].first == "comment")
1080             {
1081               std::vector<std::string> segments;
1082               std::string line = cmlFile[i].second[0];
1083               while(line[0] == '#')
1084                 line.erase(0,1);
1085
1086               CDMUtilities::splitter::split(segments, line, " ()", CDMUtilities::splitter::no_empties);
1087               if (segments.size() > 1 && segments[0] == "ADD_SUBDIRECTORY" && segments[1] == package_name)
1088                 {
1089                   found = true;
1090                   while(cmlFile[i].second[0][0] == '#')
1091                     cmlFile[i].second[0].erase(0,1);
1092                 }
1093             }
1094           else if(cmlFile[i].first == "command" && cmlFile[i].second[0] == "ADD_SUBDIRECTORY")
1095             {
1096               int pos = 1;
1097               while (pos < cmlFile[i].second.size())
1098                 {
1099                   if (!isspace(cmlFile[i].second[pos][0]) && cmlFile[i].second[pos][0] != '(' && cmlFile[i].second[pos][0] != '#')
1100                     {
1101                       if (package_name == cmlFile[i].second[pos])
1102                         {
1103                           found = true;
1104                           if (!toInclude)
1105                             {
1106                               cmlFile[i].first = "comment";
1107                               cmlFile[i].second[0] = "#" + cmlFile[i].second[0];
1108                               while (cmlFile[i].second.size() > 1)
1109                                 {
1110                                   cmlFile[i].second[0] += cmlFile[i].second[1];
1111                                   cmlFile[i].second.erase(cmlFile[i].second.begin()+1);
1112                                 }
1113
1114                             }
1115                         }
1116                       break;
1117                     }
1118                   pos++;
1119                 }
1120             }
1121         }
1122       if (!found && toInclude)
1123         {
1124           CDMUtilities::syntaxElement element;
1125           element.first = "command";
1126           element.second.push_back("ADD_SUBDIRECTORY(" + package_name + ")");
1127           cmlFile.push_back(element);
1128         }
1129
1130       return CDMUtilities::writeCMLFile(this->CMakeLists->GetPath().c_str(),cmlFile);
1131     }
1132   return false;
1133 }
1134
1135 std::map<std::string, bool> modelCDMProject::Get3rdPartyLibraries()
1136 {
1137   std::map<std::string, std::string> correspondence;
1138   correspondence["USE_CREA"] = "Crea";
1139   correspondence["USE_GDCM"] = "GDCM";
1140   correspondence["USE_GDCM_VTK"] = "GDCM_VTK";
1141   correspondence["USE_GDCM2"] = "GDCM2";
1142   correspondence["USE_WXWIDGETS"] = "WxWidgets";
1143   correspondence["USE_KWWIDGETS"] = "KWWidgets";
1144   correspondence["USE_VTK"] = "VTK";
1145   correspondence["USE_ITK"] = "ITK";
1146   correspondence["USE_BOOST"] = "Boost";
1147
1148   std::map<std::string, bool> res;
1149   res["Crea"] = false;
1150   res["GDCM"] = false;
1151   res["GDCM_VTK"] = false;
1152   res["GDCM2"] = false;
1153   res["WxWidgets"] = false;
1154   res["KWWidgets"] = false;
1155   res["VTK"] = false;
1156   res["ITK"] = false;
1157   res["Boost"] = false;
1158
1159   if (this->HasCMakeLists())
1160     {
1161       std::string CMfile = CDMUtilities::readFile(this->CMakeLists->GetPath().c_str());
1162
1163       boost::regex expression("^\\h*SET([\\s]|#[^\\n]*\\n)*\\(([\\s]|#[^\\n]*\\n)*USE_\\w+\\s+ON");
1164       std::string::const_iterator start, end;
1165       start = CMfile.begin();
1166       end = CMfile.end();
1167       boost::match_results<std::string::const_iterator> what;
1168       boost::match_flag_type flags = boost::match_default;
1169       while(boost::regex_search(start, end, what, expression, flags))
1170         {
1171           //std::cout << what[0].str() << std::endl;
1172           boost::regex expression1 = boost::regex("USE_\\w+");
1173           std::string::const_iterator start1, end1;
1174           start1 = what[0].first;
1175           end1 = what[0].second;
1176           boost::match_results<std::string::const_iterator> what1;
1177           if(boost::regex_search(start1, end1, what1, expression1, flags))
1178             {
1179               std::string dete = what1.str();
1180               CDMUtilities::normalizeStr(dete);
1181               //std::cout << dete << std::endl;
1182               if(correspondence.find(dete) != correspondence.end())
1183                 res[correspondence[dete]] = true;
1184             }
1185           start = what[0].second;
1186         }
1187     }
1188
1189   return res;
1190 }
1191
1192 bool modelCDMProject::Set3rdPartyLibrary(const std::string& library_name,
1193     const bool& toInclude)
1194 {
1195   std::map<std::string, std::string> correspondence;
1196   correspondence["Crea"] = "USE_CREA";
1197   correspondence["GDCM"] = "USE_GDCM";
1198   correspondence["GDCM_VTK"] = "USE_GDCM_VTK";
1199   correspondence["GDCM2"] = "USE_GDCM2";
1200   correspondence["WxWidgets"] = "USE_WXWIDGETS";
1201   correspondence["KWWidgets"] = "USE_KWWIDGETS";
1202   correspondence["VTK"] = "USE_VTK";
1203   correspondence["ITK"] = "USE_ITK";
1204   correspondence["Boost"] = "USE_BOOST";
1205
1206   if (correspondence.find(library_name) != correspondence.end())
1207     {
1208       std::string library_command = correspondence[library_name];
1209
1210       if (this->HasCMakeLists())
1211         {
1212           std::string CMfile = CDMUtilities::readFile(this->CMakeLists->GetPath().c_str());
1213           std::string resCMfile = "";
1214
1215           std::string::const_iterator start, end;
1216           boost::match_results<std::string::const_iterator> what, tmp;
1217           boost::match_flag_type flags = boost::match_default;
1218           bool found = false;
1219
1220           start = CMfile.begin();
1221           end = CMfile.end();
1222
1223           //search for existing inclusions
1224           boost::regex expression("^\\h*SET([\\s]|#[^\\n]*\\n)*\\(([\\s]|#[^\\n]*\\n)*" + library_command + "\\s+ON\\s*\\)");
1225           while(boost::regex_search(start, end, what, expression, flags))
1226             {
1227               found = true;
1228               resCMfile += what.prefix().str();
1229               if(!toInclude)
1230                 {
1231                   std::string dete = what.str();
1232                   int pos = dete.find("ON",0);
1233                   dete.replace(pos, 2, "OFF");
1234                   resCMfile += dete;
1235                 }
1236               else
1237                 resCMfile += what.str();
1238               tmp = what;
1239               start = what[0].second;
1240             }
1241
1242           if (found)
1243             resCMfile += tmp.suffix().str();
1244           else
1245             {
1246               start = CMfile.begin();
1247               end = CMfile.end();
1248
1249               //search for existing exclusions
1250               boost::regex expression("^\\h*SET([\\s]|#[^\\n]*\\n)*\\(([\\s]|#[^\\n]*\\n)*" + library_command + "\\s+OFF\\s*\\)");
1251               while(boost::regex_search(start, end, what, expression, flags))
1252                 {
1253                   found = true;
1254                   resCMfile += what.prefix().str();
1255                   if(toInclude)
1256                     {
1257                       std::string dete = what.str();
1258                       int pos = dete.find("OFF",0);
1259                       dete.replace(pos, 3, "ON");
1260                       resCMfile += dete;
1261                     }
1262                   else
1263                     resCMfile += what.str();
1264                   tmp = what;
1265                   start = what[0].second;
1266                 }
1267
1268               if (found)
1269                 resCMfile += tmp.suffix().str();
1270               else
1271                 {
1272                   start = CMfile.begin();
1273                   end = CMfile.end();
1274
1275                   //search for existing commented inclusions
1276                   expression = boost::regex("^\\h*#+\\h*SET([\\s]|#[^\\n]*\\n)*\\(([\\s]|#[^\\n]*\\n)*" + library_command + "\\s+ON\\s*\\)");
1277                   while(boost::regex_search(start, end, what, expression, flags))
1278                     {
1279                       found = true;
1280                       resCMfile += what.prefix().str();
1281                       if(toInclude)
1282                         {
1283                           std::string dete = what.str();
1284                           for (int i = 0; i < dete.size(); ++i) {
1285                             if(dete[i] == '#')
1286                               {
1287                                 dete.erase(i,1);
1288                                 i--;
1289                               }
1290                           }
1291                           resCMfile += dete;
1292                         }
1293                       else
1294                         resCMfile += what.str();
1295
1296                       tmp = what;
1297                       start = what[0].second;
1298                     }
1299
1300                   if (found)
1301                     resCMfile += tmp.suffix().str();
1302                   else
1303                     {
1304                       if(toInclude)
1305                         {
1306                           start = CMfile.begin();
1307                           end = CMfile.end();
1308
1309                           //search for position to insert
1310                           expression = boost::regex("^\\h*#\\h*Libraries\\/tools used\\h*$");
1311                           if(boost::regex_search(start, end, what, expression, flags))
1312                             {
1313                               found = true;
1314                               resCMfile += what.prefix().str();
1315                               resCMfile += what.str();
1316                               resCMfile += "\nSET(" + library_command + " ON)";
1317                               resCMfile += what.suffix().str();
1318                             }
1319                         }
1320                       else
1321                         {
1322                           found = true;
1323                         }
1324                     }
1325                 }
1326             }
1327           if (!found) {
1328             return false;
1329           }
1330           else
1331             return CDMUtilities::writeFile(this->CMakeLists->GetPath().c_str(), resCMfile);
1332         }
1333     }
1334
1335   return false;
1336 }