]> Creatis software - crea.git/blob - lib/creaDevManagerLib/modelCDMAppli.cpp
Feature #1711 CreaDevManager application implementation
[crea.git] / lib / creaDevManagerLib / modelCDMAppli.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  * modelCDMAppli.cpp
30  *
31  *  Created on: Nov 23, 2012
32  *      Author: Daniel Felipe Gonzalez Obando
33  */
34
35 #include "modelCDMAppli.h"
36
37 #include <iostream>
38 #include <fstream>
39 #include <sstream>
40 #include <algorithm>
41
42 #include "CDMUtilities.h"
43 #include "creaWx.h"
44 #include "wx/dir.h"
45
46 modelCDMAppli::modelCDMAppli()
47 {
48 }
49
50 modelCDMAppli::modelCDMAppli(modelCDMIProjectTreeNode* parent, const std::string& path, const std::string& name, const int& level)
51 {
52   std::cout << "creating appli\n";
53   this->parent = parent;
54   this->type = wxDIR_DIRS;
55   this->name = name;
56   this->level = level;
57   this->path = path;
58
59
60
61   this->path = CDMUtilities::fixPath(path);
62   std::string pathFixed(CDMUtilities::fixPath(path));
63
64   this->applications.clear();
65   wxDir dir(crea::std2wx((pathFixed).c_str()));
66   if (dir.IsOpened())
67     {
68       wxString fileName;
69       bool cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_DIRS);
70       while (cont)
71         {
72           std::string stdfileName = crea::wx2std(fileName);
73
74           if(stdfileName != "template_appli" && stdfileName != "template_wx_appli")
75             {
76               modelCDMApplication* application = new modelCDMApplication(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
77               this->applications.push_back(application);
78               this->children.push_back(application);
79             }
80           else
81             {
82               modelCDMFolder* folder = new modelCDMFolder(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
83               this->children.push_back(folder);
84             }
85
86           cont = dir.GetNext(&fileName);
87         }
88       //files
89       cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_FILES);
90       while (cont)
91         {
92           std::string stdfileName = crea::wx2std(fileName);
93
94           //if CMakeLists, create CMakeLists
95           if(stdfileName == "CMakeLists.txt")
96             {
97               this->CMakeLists = new modelCDMCMakeListsFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
98               this->children.push_back(this->CMakeLists);
99             }
100           //if is an unknown file, create file
101           else
102             {
103               this->children.push_back(new modelCDMFile(this, pathFixed + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1));
104             }
105
106           cont = dir.GetNext(&fileName);
107         }
108
109     }
110   this->SortChildren();
111   std::sort(this->applications.begin(), this->applications.end(), CompareNodeItem);
112 }
113
114 modelCDMAppli::~modelCDMAppli()
115 {
116 }
117
118 const std::vector<modelCDMApplication*>& modelCDMAppli::GetApplications() const
119 {
120   return this->applications;
121 }
122
123 modelCDMApplication* modelCDMAppli::CreateApplication(
124     const std::string& namein,
125     const int& type,
126     std::string*& result
127 )
128 {
129   std::vector<std::string> words;
130   CDMUtilities::splitter::split(words,namein," '/\\*\"%",CDMUtilities::splitter::no_empties);
131   std::string name;
132   for (int i = 0; i < (int)(words.size()); i++)
133     {
134       name += words[i];
135     }
136   if (name == "")
137     {
138       result = new std::string("The given name is not valid:  '/\\*\"% are forbidden.");
139       return NULL;
140     }
141
142   if (type == 0)
143     {
144       //copy template application folder with new name
145 #ifdef _WIN32
146       std::string copyCommand = "xcopy \"" + this->path + CDMUtilities::SLASH + "template_appli\" \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "\" /Y";
147 #else
148       std::string copyCommand = "cp -r \"" + this->path + CDMUtilities::SLASH + "template_appli\" \"" + this->path + CDMUtilities::SLASH + name + "\"";
149 #endif
150
151       if(system(copyCommand.c_str()))
152         {
153           result = new std::string("An error occurred while running '" + copyCommand + "'.");
154           return NULL;
155         }
156       //set name of library in CMakeLists inside copied folder
157       std::string line;
158       std::ifstream in((this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt").c_str());
159       if( !in.is_open())
160         {
161           result = new std::string("CMakeLists.txt file failed to open.");
162           return NULL;
163         }
164       std::ofstream out((this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt.tmp").c_str());
165       while (getline(in, line))
166         {
167           if(line == "SET ( EXE_NAME   MyExe  )")
168             line = "SET ( EXE_NAME   " + name + "  )";
169           out << line << std::endl;
170         }
171       in.close();
172       out.close();
173       //delete old file and rename new file
174 #ifdef _WIN32
175       std::string renameCommand = "move /Y \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt\"";
176 #else
177       std::string renameCommand = "mv \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt\"";
178 #endif
179
180       if(system(renameCommand.c_str()))
181         {
182           result = new std::string("An error occurred while running '" + renameCommand + "'.");
183           return NULL;
184         }
185
186       //add application to appli CMakeLists
187       std::fstream out1((this->path + CDMUtilities::SLASH + "CMakeLists.txt").c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
188       if (out1.is_open())
189         {
190           out1 << "ADD_SUBDIRECTORY(" << name << ")" << std::endl;
191           out1.close();
192         }
193
194       //add application to model
195       modelCDMApplication* application = new modelCDMApplication(this, this->path + CDMUtilities::SLASH + name, name, this->level + 1);
196       this->applications.push_back(application);
197       this->children.push_back(application);
198
199       this->SortChildren();
200
201       result = new std::string(this->path + CDMUtilities::SLASH + name);
202       return application;
203     }
204   else if(type == 1)
205     {
206       //copy template application folder with new name
207 #ifdef _WIN32
208       std::string copyCommand = "xcopy \"" + this->path + CDMUtilities::SLASH + "template_wx_appli\" \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "\" /Y";
209 #else
210       std::string copyCommand = "cp -r \"" + this->path + CDMUtilities::SLASH + "template_wx_appli\" \"" + this->path + CDMUtilities::SLASH + name + "\"";
211 #endif
212
213       if(system(copyCommand.c_str()))
214         {
215           result = new std::string("An error occurred while running '" + copyCommand + "'.");
216           return NULL;
217         }
218       //set name of library in CMakeLists inside copied folder
219       std::string line;
220       std::ifstream in((this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt").c_str());
221       if( !in.is_open())
222         {
223           result = new std::string("CMakeLists.txt file failed to open.");
224           return NULL;
225         }
226       std::ofstream out((this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt.tmp").c_str());
227       while (getline(in, line))
228         {
229           if(line == "SET ( EXE_NAME   MyExeWx  )")
230             line = "SET ( EXE_NAME   " + name + "  )";
231           out << line << std::endl;
232         }
233       in.close();
234       out.close();
235       //delete old file and rename new file
236 #ifdef _WIN32
237       std::string renameCommand = "move /Y \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt\"";
238 #else
239       std::string renameCommand = "mv \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt.tmp\" \"" + this->path + CDMUtilities::SLASH + name + CDMUtilities::SLASH + "CMakeLists.txt\"";
240 #endif
241
242       if(system(renameCommand.c_str()))
243         {
244           result = new std::string("An error occurred while running '" + renameCommand + "'.");
245           return NULL;
246         }
247
248       //add application to appli CMakeLists
249       std::fstream out1((this->path + CDMUtilities::SLASH + "CMakeLists.txt").c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
250       if (out1.is_open())
251         {
252           out1 << "ADD_SUBDIRECTORY(" << name << ")" << std::endl;
253           out1.close();
254         }
255
256       //add application to model
257       modelCDMApplication* application = new modelCDMApplication(this, this->path + CDMUtilities::SLASH + name, name, this->level + 1);
258       this->applications.push_back(application);
259       this->children.push_back(application);
260
261       this->SortChildren();
262
263       result = new std::string(this->path + CDMUtilities::SLASH + name);
264       return application;
265     }
266   else
267     {
268       std::string res = "Invalid application type: ";
269       res += type;
270       res += std::string(".\n0:Console application.\n1:GUI Application (wxWidgets).");
271       result = new std::string(res);
272
273       return NULL;
274     }
275 }
276
277 const bool modelCDMAppli::Refresh(std::string*& result)
278 {
279   std::cout << "refreshing appli" << std::endl;
280   this->type = wxDIR_DIRS;
281
282   std::vector<bool> checked(this->children.size(), false);
283   std::vector<bool> checkedApplications(this->applications.size(), false);
284
285   //check all folders
286   wxDir dir(crea::std2wx((this->path).c_str()));
287   if (dir.IsOpened())
288     {
289       wxString fileName;
290       bool cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_DIRS);
291       while (cont)
292         {
293           std::string stdfileName = crea::wx2std(fileName);
294
295           if(stdfileName != "template_appli" && stdfileName != "template_wx_appli")
296             {
297               std::string applicationName = stdfileName;
298               //check if application already exist
299               bool found = false;
300               for (int i = 0; !found && i < (int)(this->applications.size()); i++)
301                 {
302                   if (this->applications[i]->GetName() == applicationName)
303                     {
304                       found = true;
305                       int pos = std::find(this->children.begin(), this->children.end(), this->applications[i]) - this->children.begin();
306                       checked[pos] = true;
307                       checkedApplications[i] = true;
308                       if(!this->applications[i]->Refresh(result))
309                         return false;
310                     }
311                 }
312               if(!found)
313                 {
314                   modelCDMApplication* application= new modelCDMApplication(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
315                   this->applications.push_back(application);
316                   this->children.push_back(application);
317                 }
318             }
319           else
320             {
321               //check if folder already exist
322               bool found = false;
323               for (int i = 0; !found && i < (int)(this->children.size()); i++)
324                 {
325                   if (this->children[i]->GetName() == stdfileName)
326                     {
327                       found = true;
328                       checked[i] = true;
329
330                       if(!this->children[i]->Refresh(result))
331                         return false;
332                     }
333                 }
334               if(!found)
335                 {
336                   modelCDMFolder* folder= new modelCDMFolder(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
337                   this->children.push_back(folder);
338                 }
339             }
340           cont = dir.GetNext(&fileName);
341         }
342
343       cont = dir.GetFirst(&fileName, wxEmptyString, wxDIR_FILES);
344       while (cont)
345         {
346           std::string stdfileName = crea::wx2std(fileName);
347
348           //if CMakeLists, create CMakeLists
349           if(stdfileName == "CMakeLists.txt")
350             {
351               if (this->CMakeLists == NULL)
352                 {
353                   this->CMakeLists = new modelCDMCMakeListsFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
354                   this->children.push_back(this->CMakeLists);
355                 }
356               else
357                 {
358                   int pos = std::find(this->children.begin(), this->children.end(), this->CMakeLists) - this->children.begin();
359                   checked[pos] = true;
360                   if(!this->CMakeLists->Refresh(result))
361                     return false;
362                 }
363             }
364           //if is an unknown file, create file
365           else
366             {
367               bool found = false;
368               for (int i = 0; !found && i < (int)(this->children.size()); i++)
369                 {
370                   if (this->children[i]->GetName() == stdfileName)
371                     {
372                       found = true;
373                       checked[i] = true;
374                       if(!this->children[i]->Refresh(result))
375                         return false;
376                     }
377                 }
378
379               if(!found)
380                 {
381                   modelCDMFile* file = new modelCDMFile(this, this->path + CDMUtilities::SLASH + stdfileName, stdfileName, this->level + 1);
382                   this->children.push_back(file);
383                 }
384             }
385
386           cont = dir.GetNext(&fileName);
387         }
388     }
389
390   for (int i = 0; i < (int)(checkedApplications.size()); i++)
391     {
392       if(!checkedApplications[i])
393         {
394           this->applications.erase(this->applications.begin()+i);
395           checkedApplications.erase(checkedApplications.begin()+i);
396           i--;
397         }
398     }
399   for (int i = 0; i < (int)(checked.size()); i++)
400     {
401       if(!checked[i])
402         {
403           delete this->children[i];
404           this->children.erase(this->children.begin()+i);
405           checked.erase(checked.begin()+i);
406           i--;
407         }
408     }
409   this->SortChildren();
410   std::sort(this->applications.begin(), this->applications.end(), CompareNodeItem);
411   return true;
412 }
413
414 void modelCDMAppli::CheckStructure(std::map<std::string, bool>& properties)
415 {
416   //check cmake exist
417   if(this->CMakeLists != NULL)
418     {
419       //set properties parameters based on model
420       for (int i = 0; i < (int)(this->applications.size()); i++)
421         properties["appli add " + this->applications[i]->GetName()] = false;
422
423       //open cmakelists
424       std::ifstream confFile;
425       confFile.open((this->CMakeLists->GetPath()).c_str());
426
427       //take everything that is not commented
428       std::string fileContent;
429
430       std::string word;
431       std::vector<std::string> words;
432       while(confFile.is_open() && !confFile.eof())
433         {
434           std::getline(confFile,word, '\n');
435           if(word[0] != '#')
436             {
437               CDMUtilities::splitter::split(words, word, "#", CDMUtilities::splitter::empties_ok);
438               if (words.size() > 0)
439                 {
440                   word = words[0];
441                   CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::empties_ok);
442                   for (int i = 0; i < (int)(words.size()); i++)
443                     {
444                       if(words[i].substr(0,2) == "//")
445                         break;
446                       fileContent += words[i] + " ";
447                     }
448                 }
449             }
450         }
451
452       //check every instruction
453       std::stringstream ss(fileContent);
454       while(!ss.eof())
455         {
456           std::getline(ss,word, '(');
457
458           //check instruction name
459           CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::no_empties);
460
461           //add instructions
462           if (words.size() > 0 && words[words.size()-1] == "ADD_SUBDIRECTORY")
463             {
464               std::getline(ss,word, ')');
465               //std::cout << word << std::endl;
466               CDMUtilities::splitter::split(words, word, " ", CDMUtilities::splitter::no_empties);
467
468               if (words.size() > 0)
469                 {
470                   {
471                     properties["appli add " + words[0]] = true;
472                   }
473                 }
474             }
475         }
476
477     }
478
479   //check libraries' structure
480   for (int i = 0; i < (int)(this->applications.size()); i++)
481     {
482       properties["application " + this->applications[i]->GetName()] = true;
483       this->applications[i]->CheckStructure(properties);
484     }
485 }
486
487 bool modelCDMAppli::IsApplicationIncluded(const std::string& application_name)
488 {
489   if(this->HasCMakeLists())
490     {
491       std::ifstream CMFile(this->CMakeLists->GetPath().c_str());
492       if (CMFile.is_open())
493         {
494           std::string line;
495           while(!CMFile.eof())
496             {
497               std::getline(CMFile, line);
498               while(line[0]==' ')
499                 line.erase(0);
500               if(line[0] != '#')
501                 {
502                   std::vector<std::string> lineSeg;
503                   CDMUtilities::splitter::split(lineSeg,line,"()",CDMUtilities::splitter::no_empties);
504                   if(lineSeg.size() > 0 && lineSeg[0] == "ADD_SUBDIRECTORY" && lineSeg[1] == application_name)
505                     {
506                       CMFile.close();
507                       return true;
508                     }
509                 }
510             }
511           CMFile.close();
512         }
513     }
514   return false;
515 }
516
517 bool modelCDMAppli::SetApplicationInclude(const std::string& application_name, const bool& toInclude)
518 {
519   if (this->HasCMakeLists())
520     {
521       std::ifstream CMFile(this->CMakeLists->GetPath().c_str());
522       if (CMFile.is_open())
523         {
524           std::stringstream outs;
525           std::string line;
526           bool found = false;
527           while(!CMFile.eof())
528             {
529               std::getline(CMFile, line);
530               if (CMFile.eof()) {
531                 break;
532               }
533               if(line != "")
534                 {
535                   std::vector<std::string> segs;
536                   CDMUtilities::splitter::split(segs, line, " ", CDMUtilities::splitter::no_empties);
537                   //is comment
538                   if(segs.size() > 0 && segs[0][0] == '#')
539                     {
540                       if(toInclude)
541                         {
542                           CDMUtilities::splitter::split(segs, line, " #()", CDMUtilities::splitter::no_empties);
543                           if (segs.size() > 1 && segs[0] == "ADD_SUBDIRECTORY" && segs[1] == application_name)
544                             {
545                               found = true;
546                               outs << "ADD_SUBDIRECTORY(" << application_name << ")\n";
547                             }
548                           else
549                             outs << line << "\n";
550                         }
551                       else
552                         {
553                           outs << line << "\n";
554                         }
555                     }
556                   //is not comment
557                   else
558                     {
559                       if (segs.size() > 0 && !toInclude)
560                         {
561                           CDMUtilities::splitter::split(segs, line, " ()", CDMUtilities::splitter::no_empties);
562                           if (segs.size() > 1 && segs[0] == "ADD_SUBDIRECTORY" && segs[1] == application_name)
563                             {
564                               outs << "#" << line << "\n";
565                             }
566                           else
567                             {
568                               outs << line << "\n";
569                             }
570                         }
571                       else
572                         {
573                           CDMUtilities::splitter::split(segs, line, " ()", CDMUtilities::splitter::no_empties);
574                           if (segs.size() > 1 && segs[0] == "ADD_SUBDIRECTORY" && segs[1] == application_name)
575                             {
576                               found = true;
577                             }
578                           outs << line << "\n";
579                         }
580                     }
581                 }
582               else
583                 {
584                   outs << "\n";
585                 }
586             }
587
588           CMFile.close();
589
590           if(!found && toInclude)
591             outs << "ADD_SUBDIRECTORY(" << application_name << ")\n";
592
593           std::ofstream CMFileOut(this->CMakeLists->GetPath().c_str());
594           if (CMFileOut.is_open())
595             {
596               CMFileOut << outs.rdbuf();
597               CMFileOut.close();
598               return true;
599             }
600         }
601     }
602   return false;
603 }