Bladeren bron

ENH: create a "Virtual Folder" in CodeBlocks, which contains all the cmake
files of the project, i.e. there is now a "CMake Files" folder additionally
to the "Sources", "Headers" and "Others" folders which already existed.
Patch by Daniel Teske.

Alex

Alexander Neundorf 16 jaren geleden
bovenliggende
commit
45652bc20b
1 gewijzigde bestanden met toevoegingen van 192 en 0 verwijderingen
  1. 192 0
      Source/cmExtraCodeBlocksGenerator.cxx

+ 192 - 0
Source/cmExtraCodeBlocksGenerator.cxx

@@ -110,6 +110,146 @@ void cmExtraCodeBlocksGenerator::CreateProjectFile(
 }
 
 
+/* Tree is used to create a "Virtual Folder" in CodeBlocks, in which all
+ CMake files this project depends on will be put. This means additionally
+ to the "Sources" and "Headers" virtual folders of CodeBlocks, there will
+ now also be a "CMake Files" virtual folder. 
+ Patch by Daniel Teske <daniel.teske AT nokia.com> (which use C::B project
+ files in QtCreator).*/
+struct Tree
+{
+  std::string path; //only one component of the path
+  std::vector<Tree> folders;
+  std::vector<std::string> files;
+  void InsertPath(const std::vector<std::string>& splitted, 
+                  std::vector<std::string>::size_type start, 
+                  const std::string& fileName);
+  void BuildVirtualFolder(std::string& virtualFolders) const;
+  void BuildVirtualFolderImpl(std::string& virtualFolders, 
+                              const std::string& prefix) const;
+  void BuildUnit(std::string& unitString, const std::string& fsPath) const;
+  void BuildUnitImpl(std::string& unitString, 
+                     const std::string& virtualFolderPath, 
+                     const std::string& fsPath) const;
+};
+
+
+void Tree::InsertPath(const std::vector<std::string>& splitted, 
+                      std::vector<std::string>::size_type start, 
+                      const std::string& fileName)
+{
+  if (start == splitted.size()) 
+    {
+    files.push_back(fileName);
+    return;
+    }
+  for (std::vector<Tree>::iterator
+       it = folders.begin();
+       it != folders.end();
+       ++it)
+    {
+    if ((*it).path == splitted.at(start))
+      {
+      if (start + 1 <  splitted.size())
+        {
+        it->InsertPath(splitted, start + 1, fileName);
+        return;
+        }
+      else
+        {
+        // last part of splitted
+        it->files.push_back(fileName);
+        return;
+        }
+      }
+    }
+  // Not found in folders, thus insert
+  Tree newFolder;
+  newFolder.path = splitted.at(start);
+  if (start + 1 <  splitted.size())
+    {
+    newFolder.InsertPath(splitted, start + 1, fileName);
+    folders.push_back(newFolder);
+    return;
+    }
+  else
+    {
+    // last part of splitted
+    newFolder.files.push_back(fileName);
+    folders.push_back(newFolder);
+    return;
+    }
+}
+
+
+void Tree::BuildVirtualFolder(std::string& virtualFolders) const
+{
+  virtualFolders += "<Option virtualFolders=\"CMake Files\\;";
+  for (std::vector<Tree>::const_iterator it = folders.begin();
+     it != folders.end();
+     ++it)
+    {
+    it->BuildVirtualFolderImpl(virtualFolders, "");
+    }
+  virtualFolders += "\" />";
+}
+
+
+void Tree::BuildVirtualFolderImpl(std::string& virtualFolders,
+                                  const std::string& prefix) const
+{
+  virtualFolders += "CMake Files\\" + prefix +  path + "\\;";
+  for (std::vector<Tree>::const_iterator it = folders.begin();
+     it != folders.end();
+     ++it)
+    {
+    it->BuildVirtualFolderImpl(virtualFolders, prefix + path + "\\");
+    }
+}
+
+
+void Tree::BuildUnit(std::string& unitString, const std::string& fsPath) const
+{
+  for (std::vector<std::string>::const_iterator it = files.begin();
+       it != files.end();
+       ++it)
+    {
+    unitString += "      <Unit filename=\"" + fsPath + *it + "\">\n";
+    unitString += "          <Option virtualFolder=\"CMake Files\\\" />\n";
+    unitString += "      </Unit>\n";
+    }
+  for (std::vector<Tree>::const_iterator it = folders.begin();
+     it != folders.end();
+     ++it)
+    {
+    it->BuildUnitImpl(unitString, "", fsPath);
+    }
+}
+
+
+void Tree::BuildUnitImpl(std::string& unitString,
+                         const std::string& virtualFolderPath,
+                         const std::string& fsPath) const
+{
+  for (std::vector<std::string>::const_iterator it = files.begin();
+       it != files.end();
+       ++it)
+    {
+    unitString += "      <Unit filename=\"" +fsPath+path+ "/" + *it + "\">\n";
+    unitString += "          <Option virtualFolder=\"CMake Files\\"
+               + virtualFolderPath + path + "\\\" />\n";
+    unitString += "      </Unit>\n";
+    }
+  for (std::vector<Tree>::const_iterator it = folders.begin();
+     it != folders.end();
+     ++it)
+    {
+    it->BuildUnitImpl(unitString,
+                      virtualFolderPath + path + "\\", fsPath + path + "/");
+    }
+}
+
+
 void cmExtraCodeBlocksGenerator
   ::CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
                          const std::string& filename)
@@ -121,6 +261,54 @@ void cmExtraCodeBlocksGenerator
     return;
     }
 
+  Tree tree;
+
+  // build tree of virtual folders
+  for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
+          it = this->GlobalGenerator->GetProjectMap().begin();
+         it != this->GlobalGenerator->GetProjectMap().end();
+         ++it)
+    {
+      // Convert
+      std::vector<std::string> listFiles =
+              it->second[0]->GetMakefile()->GetListFiles();
+
+      for (std::vector<std::string>::const_iterator jt = listFiles.begin();
+           jt != listFiles.end();
+           ++jt)
+         {
+         const std::string &relative =
+                 cmSystemTools::RelativePath(
+                         it->second[0]->GetMakefile()->GetHomeDirectory(),
+                         jt->c_str());
+         std::vector<std::string> splitted;
+         cmSystemTools::SplitPath(relative.c_str(), splitted, false);
+         // Split filename from path
+         std::string fileName = *(splitted.end()-1);
+         splitted.erase(splitted.end() - 1, splitted.end());
+
+         // We don't want paths with ".." in them
+         // reasons are that we don't want files outside the project
+         // TODO: the path should be normalized first though
+         // We don't want paths with CMakeFiles in them
+         // or do we?
+         // In speedcrunch those where purely internal
+         if (splitted.size() >= 1
+             && relative.find("..") == std::string::npos
+             && relative.find("CMakeFiles") == std::string::npos)
+           {
+           tree.InsertPath(splitted, 1, fileName);
+           }
+         }
+    }
+
+  // Now build a virtual tree string
+  std::string virtualFolders;  
+  tree.BuildVirtualFolder(virtualFolders);
+  // And one for <Unit>
+  std::string unitFiles;
+  tree.BuildUnit(unitFiles, std::string(mf->GetHomeDirectory()) + "/");
+
   // figure out the compiler
   std::string compiler = this->GetCBCompilerId(mf);
   std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
@@ -132,6 +320,7 @@ void cmExtraCodeBlocksGenerator
         "      <Option title=\"" << mf->GetProjectName()<<"\" />\n"
         "      <Option makefile_is_custom=\"1\" />\n"
         "      <Option compiler=\"" << compiler << "\" />\n"
+        "      "<<virtualFolders<<"\n"
         "      <Build>\n";
 
   bool installTargetCreated = false;
@@ -345,6 +534,9 @@ void cmExtraCodeBlocksGenerator
           "      </Unit>\n";
     }
 
+  // Add CMakeLists.txt
+  fout<<unitFiles;
+
   fout<<"   </Project>\n"
         "</CodeBlocks_project_file>\n";
 }