Browse Source

Projucer: Refactored the module handling code

tags/2021-05-28
ed 5 years ago
parent
commit
c73c5512d5
11 changed files with 316 additions and 309 deletions
  1. +2
    -8
      extras/Projucer/Source/Application/Windows/jucer_GlobalPathsWindowComponent.h
  2. +4
    -4
      extras/Projucer/Source/LiveBuildEngine/jucer_CompileEngineClient.cpp
  3. +16
    -10
      extras/Projucer/Source/Project/UI/Sidebar/jucer_ModuleTreeItems.h
  4. +18
    -11
      extras/Projucer/Source/Project/UI/jucer_ModulesInformationComponent.h
  5. +222
    -234
      extras/Projucer/Source/Project/jucer_Module.cpp
  6. +38
    -38
      extras/Projucer/Source/Project/jucer_Module.h
  7. +1
    -1
      extras/Projucer/Source/Project/jucer_Project.cpp
  8. +2
    -2
      extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp
  9. +10
    -0
      extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.cpp
  10. +3
    -0
      extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.h
  11. +0
    -1
      extras/Projucer/Source/Utility/UI/PropertyComponents/jucer_FilePathPropertyComponent.h

+ 2
- 8
extras/Projucer/Source/Application/Windows/jucer_GlobalPathsWindowComponent.h View File

@@ -75,14 +75,8 @@ public:
auto juceValue = getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()); auto juceValue = getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS());
auto userValue = getAppSettings().getStoredPath (Ids::defaultUserModulePath, TargetOS::getThisOS()); auto userValue = getAppSettings().getStoredPath (Ids::defaultUserModulePath, TargetOS::getThisOS());
auto jucePathNeedsScanning = (! juceValue.isUsingDefault() && juceValue.get() != lastJUCEModulePath);
auto userPathNeedsScanning = (! userValue.isUsingDefault() && userValue.get() != lastUserModulePath);
if (jucePathNeedsScanning)
ProjucerApplication::getApp().rescanJUCEPathModules();
if (userPathNeedsScanning)
ProjucerApplication::getApp().rescanUserPathModules();
if (juceValue.get() != lastJUCEModulePath) ProjucerApplication::getApp().rescanJUCEPathModules();
if (userValue.get() != lastUserModulePath) ProjucerApplication::getApp().rescanUserPathModules();
} }
void paint (Graphics& g) override void paint (Graphics& g) override


+ 4
- 4
extras/Projucer/Source/LiveBuildEngine/jucer_CompileEngineClient.cpp View File

@@ -256,7 +256,7 @@ public:
build.setGlobalDefs (getGlobalDefs()); build.setGlobalDefs (getGlobalDefs());
build.setCompileFlags (project.getCompileEngineSettings().getExtraCompilerFlagsString()); build.setCompileFlags (project.getCompileEngineSettings().getExtraCompilerFlagsString());
build.setExtraDLLs (getExtraDLLs()); build.setExtraDLLs (getExtraDLLs());
build.setJuceModulesFolder (EnabledModuleList::findDefaultModulesFolder (project).getFullPathName());
build.setJuceModulesFolder (project.getEnabledModules().getDefaultModulesFolder().getFullPathName());
build.setUtilsCppInclude (project.getAppIncludeFile().getFullPathName()); build.setUtilsCppInclude (project.getAppIncludeFile().getFullPathName());
@@ -388,10 +388,10 @@ private:
{ {
for (auto* m : modules) for (auto* m : modules)
{ {
auto localModuleFolder = proj.getEnabledModules().shouldCopyModuleFilesLocally (m->moduleInfo.getID()).getValue()
? proj.getLocalModuleFolder (m->moduleInfo.getID())
: m->moduleInfo.getFolder();
auto copyLocally = proj.getEnabledModules().shouldCopyModuleFilesLocally (m->moduleInfo.getID());
auto localModuleFolder = copyLocally ? proj.getLocalModuleFolder (m->moduleInfo.getID())
: m->moduleInfo.getFolder();
m->findAndAddCompiledUnits (*exporter, nullptr, compileUnits, m->findAndAddCompiledUnits (*exporter, nullptr, compileUnits,
isPluginProject || isVSTHost ? ProjectType::Target::SharedCodeTarget isPluginProject || isVSTHost ? ProjectType::Target::SharedCodeTarget


+ 16
- 10
extras/Projucer/Source/Project/UI/Sidebar/jucer_ModuleTreeItems.h View File

@@ -153,6 +153,7 @@ private:
group.properties.clear(); group.properties.clear();
exporterModulePathDefaultValues.clear(); exporterModulePathDefaultValues.clear();
exporterModulePathValues.clear(); exporterModulePathValues.clear();
globalPathValues.clear();
for (Project::ExporterIterator exporter (project); exporter.next();) for (Project::ExporterIterator exporter (project); exporter.next();)
{ {
@@ -179,34 +180,39 @@ private:
"This can be an absolute path, or relative to the jucer project folder, but it " "This can be an absolute path, or relative to the jucer project folder, but it "
"must be valid on the filesystem of the target machine that will be performing this build. If this " "must be valid on the filesystem of the target machine that will be performing this build. If this "
"is empty then the global path will be used."); "is empty then the global path will be used.");
globalPathValues.add (getAppSettings().getStoredPath (isJUCEModule (moduleID) ? Ids::defaultJuceModulePath : Ids::defaultUserModulePath,
exporter->getTargetOSForExporter()).getPropertyAsValue());
} }
for (int i = 0; i < exporterModulePathDefaultValues.size(); ++i) for (int i = 0; i < exporterModulePathDefaultValues.size(); ++i)
{ {
exporterModulePathDefaultValues.getReference (i).onDefaultChange = [this] { startTimer (50); }; exporterModulePathDefaultValues.getReference (i).onDefaultChange = [this] { startTimer (50); };
exporterModulePathValues.getReference (i).addListener (this); exporterModulePathValues.getReference (i).addListener (this);
globalPathValues.getReference (i).addListener (this);
} }
globalPathValue.removeListener (this);
globalPathValue.referTo (modules.getShouldUseGlobalPathValue (moduleID));
globalPathValue.addListener (this);
useGlobalPathValue.removeListener (this);
useGlobalPathValue.referTo (modules.shouldUseGlobalPathValue (moduleID));
useGlobalPathValue.addListener (this);
auto menuItemString = (TargetOS::getThisOS() == TargetOS::osx ? "\"Projucer->Global Paths...\"" auto menuItemString = (TargetOS::getThisOS() == TargetOS::osx ? "\"Projucer->Global Paths...\""
: "\"File->Global Paths...\""); : "\"File->Global Paths...\"");
props.add (new BooleanPropertyComponent (globalPathValue,
props.add (new BooleanPropertyComponent (useGlobalPathValue,
"Use global path", "Use global path for this module"), "Use global path", "Use global path for this module"),
String ("If this is enabled, then the locally-stored global path (set in the ") + menuItemString + " menu item) " String ("If this is enabled, then the locally-stored global path (set in the ") + menuItemString + " menu item) "
"will be used as the path to this module. " "will be used as the path to this module. "
"This means that if this Projucer project is opened on another machine it will use that machine's global path as the path to this module."); "This means that if this Projucer project is opened on another machine it will use that machine's global path as the path to this module.");
props.add (new BooleanPropertyComponent (modules.shouldCopyModuleFilesLocally (moduleID),
props.add (new BooleanPropertyComponent (modules.shouldCopyModuleFilesLocallyValue (moduleID),
"Create local copy", "Copy the module into the project folder"), "Create local copy", "Copy the module into the project folder"),
"If this is enabled, then a local copy of the entire module will be made inside your project (in the auto-generated JuceLibraryFiles folder), " "If this is enabled, then a local copy of the entire module will be made inside your project (in the auto-generated JuceLibraryFiles folder), "
"so that your project will be self-contained, and won't need to contain any references to files in other folders. " "so that your project will be self-contained, and won't need to contain any references to files in other folders. "
"This also means that you can check the module into your source-control system to make sure it is always in sync with your own code."); "This also means that you can check the module into your source-control system to make sure it is always in sync with your own code.");
props.add (new BooleanPropertyComponent (modules.shouldShowAllModuleFilesInProject (moduleID),
props.add (new BooleanPropertyComponent (modules.shouldShowAllModuleFilesInProjectValue (moduleID),
"Add source to project", "Make module files browsable in projects"), "Add source to project", "Make module files browsable in projects"),
"If this is enabled, then the entire source tree from this module will be shown inside your project, " "If this is enabled, then the entire source tree from this module will be shown inside your project, "
"making it easy to browse/edit the module's classes. If disabled, then only the minimum number of files " "making it easy to browse/edit the module's classes. If disabled, then only the minimum number of files "
@@ -262,8 +268,8 @@ private:
//============================================================================== //==============================================================================
Array<ValueWithDefault> exporterModulePathDefaultValues; Array<ValueWithDefault> exporterModulePathDefaultValues;
Array<Value> exporterModulePathValues;
Value globalPathValue;
Array<Value> exporterModulePathValues, globalPathValues;
Value useGlobalPathValue;
OwnedArray <Project::ConfigFlag> configFlags; OwnedArray <Project::ConfigFlag> configFlags;
@@ -475,7 +481,7 @@ class EnabledModulesItem : public ProjectTreeItemBase,
public: public:
EnabledModulesItem (Project& p) EnabledModulesItem (Project& p)
: project (p), : project (p),
moduleListTree (p.getEnabledModules().state)
moduleListTree (project.getEnabledModules().getState())
{ {
moduleListTree.addListener (this); moduleListTree.addListener (this);
@@ -618,7 +624,7 @@ public:
} }
else if (resultCode > 0) else if (resultCode > 0)
{ {
std::vector<ModuleIDAndFolder> list;
std::vector<AvailableModuleList::ModuleIDAndFolder> list;
int offset = -1; int offset = -1;
if (resultCode < 200) if (resultCode < 200)


+ 18
- 11
extras/Projucer/Source/Project/UI/jucer_ModulesInformationComponent.h View File

@@ -35,7 +35,7 @@ class ModulesInformationComponent : public Component,
public: public:
ModulesInformationComponent (Project& p) ModulesInformationComponent (Project& p)
: project (p), : project (p),
modulesValueTree (p.getEnabledModules().state)
modulesValueTree (project.getEnabledModules().getState())
{ {
listHeader = new ListBoxHeader ( { "Module", "Version", "Make Local Copy", "Paths" }, listHeader = new ListBoxHeader ( { "Module", "Version", "Make Local Copy", "Paths" },
{ 0.25f, 0.2f, 0.2f, 0.35f } ); { 0.25f, 0.2f, 0.2f, 0.35f } );
@@ -135,9 +135,8 @@ public:
g.drawFittedText (version, bounds.removeFromLeft (roundToInt (listHeader->getProportionAtIndex (1) * width)), Justification::centredLeft, 1); g.drawFittedText (version, bounds.removeFromLeft (roundToInt (listHeader->getProportionAtIndex (1) * width)), Justification::centredLeft, 1);
//============================================================================== //==============================================================================
auto copyLocally = project.getEnabledModules().shouldCopyModuleFilesLocally (moduleID).getValue() ? "Yes" : "No";
g.drawFittedText (copyLocally, bounds.removeFromLeft (roundToInt (listHeader->getProportionAtIndex (2) * width)), Justification::centredLeft, 1);
g.drawFittedText (String (project.getEnabledModules().shouldCopyModuleFilesLocally (moduleID) ? "Yes" : "No"),
bounds.removeFromLeft (roundToInt (listHeader->getProportionAtIndex (2) * width)), Justification::centredLeft, 1);
//============================================================================== //==============================================================================
String pathText; String pathText;
@@ -215,33 +214,41 @@ private:
repaint(); repaint();
} }
static void setLocalCopyModeForAllModules (Project& project, bool copyLocally)
{
auto& modules = project.getEnabledModules();
for (auto i = modules.getNumModules(); --i >= 0;)
modules.shouldCopyModuleFilesLocallyValue (modules.getModuleID (i)) = copyLocally;
}
void showCopyModeMenu() void showCopyModeMenu()
{ {
PopupMenu m; PopupMenu m;
m.addItem (PopupMenu::Item ("Set all modules to copy locally") m.addItem (PopupMenu::Item ("Set all modules to copy locally")
.setAction ([&] { project.getEnabledModules().setLocalCopyModeForAllModules (true); }));
.setAction ([&] { setLocalCopyModeForAllModules (project, true); }));
m.addItem (PopupMenu::Item ("Set all modules to not copy locally") m.addItem (PopupMenu::Item ("Set all modules to not copy locally")
.setAction ([&] { project.getEnabledModules().setLocalCopyModeForAllModules (false); }));
.setAction ([&] { setLocalCopyModeForAllModules (project, false); }));
m.showMenuAsync (PopupMenu::Options().withTargetComponent (setCopyModeButton)); m.showMenuAsync (PopupMenu::Options().withTargetComponent (setCopyModeButton));
} }
static void setAllModulesToUseGlobalPaths (Project& project, bool useGlobal) static void setAllModulesToUseGlobalPaths (Project& project, bool useGlobal)
{ {
auto& moduleList = project.getEnabledModules();
auto& modules = project.getEnabledModules();
for (auto id : moduleList.getAllModules())
moduleList.getShouldUseGlobalPathValue (id).setValue (useGlobal);
for (auto moduleID : modules.getAllModules())
modules.shouldUseGlobalPathValue (moduleID) = useGlobal;
} }
static void setSelectedModulesToUseGlobalPaths (Project& project, SparseSet<int> selected, bool useGlobal) static void setSelectedModulesToUseGlobalPaths (Project& project, SparseSet<int> selected, bool useGlobal)
{ {
auto& moduleList = project.getEnabledModules();
auto& modules = project.getEnabledModules();
for (int i = 0; i < selected.size(); ++i) for (int i = 0; i < selected.size(); ++i)
moduleList.getShouldUseGlobalPathValue (moduleList.getModuleID (selected[i])).setValue (useGlobal);
modules.shouldUseGlobalPathValue (modules.getModuleID (selected[i])) = useGlobal;
} }
void showGlobalPathsMenu() void showGlobalPathsMenu()


+ 222
- 234
extras/Projucer/Source/Project/jucer_Module.cpp View File

@@ -40,7 +40,7 @@ File ModuleDescription::getHeader() const
{ {
if (moduleFolder != File()) if (moduleFolder != File())
{ {
const char* extensions[] = { ".h", ".hpp", ".hxx" };
static const char* extensions[] = { ".h", ".hpp", ".hxx" };
for (auto e : extensions) for (auto e : extensions)
{ {
@@ -56,14 +56,15 @@ File ModuleDescription::getHeader() const
StringArray ModuleDescription::getDependencies() const StringArray ModuleDescription::getDependencies() const
{ {
auto deps = StringArray::fromTokens (moduleInfo ["dependencies"].toString(), " \t;,", "\"'");
deps.trim();
deps.removeEmptyStrings();
return deps;
auto moduleDependencies = StringArray::fromTokens (moduleInfo ["dependencies"].toString(), " \t;,", "\"'");
moduleDependencies.trim();
moduleDependencies.removeEmptyStrings();
return moduleDependencies;
} }
//============================================================================== //==============================================================================
static bool tryToAddModuleFromFolder (const File& path, ModuleIDAndFolderList& list)
static bool tryToAddModuleFromFolder (const File& path, AvailableModuleList::ModuleIDAndFolderList& list)
{ {
ModuleDescription m (path); ModuleDescription m (path);
@@ -76,7 +77,7 @@ static bool tryToAddModuleFromFolder (const File& path, ModuleIDAndFolderList& l
return false; return false;
} }
static void addAllModulesInSubfoldersRecursively (const File& path, int depth, ModuleIDAndFolderList& list)
static void addAllModulesInSubfoldersRecursively (const File& path, int depth, AvailableModuleList::ModuleIDAndFolderList& list)
{ {
if (depth > 0) if (depth > 0)
{ {
@@ -94,27 +95,19 @@ static void addAllModulesInSubfoldersRecursively (const File& path, int depth, M
} }
} }
static void addAllModulesInFolder (const File& path, ModuleIDAndFolderList& list)
static void addAllModulesInFolder (const File& path, AvailableModuleList::ModuleIDAndFolderList& list)
{ {
if (! tryToAddModuleFromFolder (path, list)) if (! tryToAddModuleFromFolder (path, list))
{ {
int subfolders = 3;
static constexpr int subfolders = 3;
addAllModulesInSubfoldersRecursively (path, subfolders, list); addAllModulesInSubfoldersRecursively (path, subfolders, list);
} }
} }
static void sort (ModuleIDAndFolderList& listToSort)
{
std::sort (listToSort.begin(), listToSort.end(), [] (const ModuleIDAndFolder& m1, const ModuleIDAndFolder& m2)
{
return m1.first.compareIgnoreCase (m2.first) < 0;
});
}
//==============================================================================
struct ModuleScannerJob : public ThreadPoolJob
struct ModuleScannerJob : public ThreadPoolJob
{ {
ModuleScannerJob (const Array<File>& paths, std::function<void (const ModuleIDAndFolderList&)>&& callback)
ModuleScannerJob (const Array<File>& paths,
std::function<void (const AvailableModuleList::ModuleIDAndFolderList&)>&& callback)
: ThreadPoolJob ("ModuleScannerJob"), : ThreadPoolJob ("ModuleScannerJob"),
pathsToScan (paths), pathsToScan (paths),
completionCallback (std::move (callback)) completionCallback (std::move (callback))
@@ -123,14 +116,19 @@ struct ModuleScannerJob : public ThreadPoolJob
JobStatus runJob() override JobStatus runJob() override
{ {
ModuleIDAndFolderList list;
AvailableModuleList::ModuleIDAndFolderList list;
for (auto& p : pathsToScan) for (auto& p : pathsToScan)
addAllModulesInFolder (p, list); addAllModulesInFolder (p, list);
if (! shouldExit()) if (! shouldExit())
{ {
sort (list);
std::sort (list.begin(), list.end(), [] (const AvailableModuleList::ModuleIDAndFolder& m1,
const AvailableModuleList::ModuleIDAndFolder& m2)
{
return m1.first.compareIgnoreCase (m2.first) < 0;
});
completionCallback (list); completionCallback (list);
} }
@@ -138,16 +136,12 @@ struct ModuleScannerJob : public ThreadPoolJob
} }
Array<File> pathsToScan; Array<File> pathsToScan;
std::function<void (const ModuleIDAndFolderList&)> completionCallback;
std::function<void (const AvailableModuleList::ModuleIDAndFolderList&)> completionCallback;
}; };
AvailableModuleList::AvailableModuleList()
{
}
ThreadPoolJob* AvailableModuleList::createScannerJob (const Array<File>& paths) ThreadPoolJob* AvailableModuleList::createScannerJob (const Array<File>& paths)
{ {
return new ModuleScannerJob (paths, [this] (ModuleIDAndFolderList scannedModuleList)
return new ModuleScannerJob (paths, [this] (AvailableModuleList::ModuleIDAndFolderList scannedModuleList)
{ {
{ {
const ScopedLock swapLock (lock); const ScopedLock swapLock (lock);
@@ -177,14 +171,13 @@ void AvailableModuleList::scanPathsAsync (const Array<File>& paths)
removePendingAndAddJob (createScannerJob (paths)); removePendingAndAddJob (createScannerJob (paths));
} }
ModuleIDAndFolderList AvailableModuleList::getAllModules() const
AvailableModuleList::ModuleIDAndFolderList AvailableModuleList::getAllModules() const
{ {
const ScopedLock readLock (lock); const ScopedLock readLock (lock);
return moduleList; return moduleList;
} }
ModuleIDAndFolder AvailableModuleList::getModuleWithID (const String& id) const
AvailableModuleList::ModuleIDAndFolder AvailableModuleList::getModuleWithID (const String& id) const
{ {
const ScopedLock readLock (lock); const ScopedLock readLock (lock);
@@ -214,19 +207,18 @@ LibraryModule::LibraryModule (const ModuleDescription& d)
{ {
} }
//==============================================================================
void LibraryModule::writeIncludes (ProjectSaver& projectSaver, OutputStream& out) void LibraryModule::writeIncludes (ProjectSaver& projectSaver, OutputStream& out)
{ {
auto& project = projectSaver.project; auto& project = projectSaver.project;
auto& modules = project.getEnabledModules(); auto& modules = project.getEnabledModules();
auto id = getID();
auto moduleID = getID();
if (modules.shouldCopyModuleFilesLocally (id).getValue())
if (modules.shouldCopyModuleFilesLocally (moduleID))
{ {
auto juceModuleFolder = moduleInfo.getFolder(); auto juceModuleFolder = moduleInfo.getFolder();
auto localModuleFolder = project.getLocalModuleFolder (id);
auto localModuleFolder = project.getLocalModuleFolder (moduleID);
localModuleFolder.createDirectory(); localModuleFolder.createDirectory();
projectSaver.copyFolder (juceModuleFolder, localModuleFolder); projectSaver.copyFolder (juceModuleFolder, localModuleFolder);
} }
@@ -236,23 +228,14 @@ void LibraryModule::writeIncludes (ProjectSaver& projectSaver, OutputStream& out
<< ">" << newLine; << ">" << newLine;
} }
//==============================================================================
static void parseAndAddLibs (StringArray& libList, const String& libs)
{
libList.addTokens (libs, ", ", {});
libList.trim();
libList.removeDuplicates (false);
}
void LibraryModule::addSettingsForModuleToExporter (ProjectExporter& exporter, ProjectSaver& projectSaver) const
void LibraryModule::addSearchPathsToExporter (ProjectExporter& exporter) const
{ {
auto& project = exporter.getProject();
auto moduleRelativePath = exporter.getModuleFolderRelativeToProject (getID()); auto moduleRelativePath = exporter.getModuleFolderRelativeToProject (getID());
exporter.addToExtraSearchPaths (moduleRelativePath.getParentDirectory()); exporter.addToExtraSearchPaths (moduleRelativePath.getParentDirectory());
String libDirPlatform; String libDirPlatform;
if (exporter.isLinux()) if (exporter.isLinux())
libDirPlatform = "Linux"; libDirPlatform = "Linux";
else if (exporter.isCodeBlocks() && exporter.isWindows()) else if (exporter.isCodeBlocks() && exporter.isWindows())
@@ -261,7 +244,7 @@ void LibraryModule::addSettingsForModuleToExporter (ProjectExporter& exporter, P
libDirPlatform = exporter.getTargetFolder().getFileName(); libDirPlatform = exporter.getTargetFolder().getFileName();
auto libSubdirPath = moduleRelativePath.toUnixStyle() + "/libs/" + libDirPlatform; auto libSubdirPath = moduleRelativePath.toUnixStyle() + "/libs/" + libDirPlatform;
auto moduleLibDir = File (project.getProjectFolder().getFullPathName() + "/" + libSubdirPath);
auto moduleLibDir = File (exporter.getProject().getProjectFolder().getFullPathName() + "/" + libSubdirPath);
if (moduleLibDir.exists()) if (moduleLibDir.exists())
exporter.addToModuleLibPaths ({ libSubdirPath, moduleRelativePath.getRoot() }); exporter.addToModuleLibPaths ({ libSubdirPath, moduleRelativePath.getRoot() });
@@ -275,27 +258,43 @@ void LibraryModule::addSettingsForModuleToExporter (ProjectExporter& exporter, P
for (auto& path : paths) for (auto& path : paths)
exporter.addToExtraSearchPaths (moduleRelativePath.getChildFile (path.unquoted())); exporter.addToExtraSearchPaths (moduleRelativePath.getChildFile (path.unquoted()));
} }
}
{
auto extraDefs = moduleInfo.getPreprocessorDefs().trim();
void LibraryModule::addDefinesToExporter (ProjectExporter& exporter) const
{
auto extraDefs = moduleInfo.getPreprocessorDefs().trim();
if (extraDefs.isNotEmpty())
exporter.getExporterPreprocessorDefsValue() = exporter.getExporterPreprocessorDefsString() + "\n" + extraDefs;
}
if (extraDefs.isNotEmpty())
exporter.getExporterPreprocessorDefsValue() = exporter.getExporterPreprocessorDefsString() + "\n" + extraDefs;
}
{
Array<File> compiled;
auto& modules = project.getEnabledModules();
auto id = getID();
void LibraryModule::addCompileUnitsToExporter (ProjectExporter& exporter, ProjectSaver& projectSaver) const
{
auto& project = exporter.getProject();
auto& modules = project.getEnabledModules();
auto localModuleFolder = modules.shouldCopyModuleFilesLocally (id).getValue() ? project.getLocalModuleFolder (id)
: moduleInfo.getFolder();
auto moduleID = getID();
findAndAddCompiledUnits (exporter, &projectSaver, compiled);
auto localModuleFolder = modules.shouldCopyModuleFilesLocally (moduleID) ? project.getLocalModuleFolder (moduleID)
: moduleInfo.getFolder();
if (modules.shouldShowAllModuleFilesInProject (id).getValue())
addBrowseableCode (exporter, compiled, localModuleFolder);
}
Array<File> compiled;
findAndAddCompiledUnits (exporter, &projectSaver, compiled);
if (modules.shouldShowAllModuleFilesInProject (moduleID))
addBrowseableCode (exporter, compiled, localModuleFolder);
}
void LibraryModule::addLibsToExporter (ProjectExporter& exporter) const
{
auto parseAndAddLibsToList = [] (StringArray& libList, const String& libs)
{
libList.addTokens (libs, ", ", {});
libList.trim();
libList.removeDuplicates (false);
};
auto& project = exporter.getProject();
if (exporter.isXcode()) if (exporter.isXcode())
{ {
@@ -312,26 +311,34 @@ void LibraryModule::addSettingsForModuleToExporter (ProjectExporter& exporter, P
auto frameworks = moduleInfo.moduleInfo [xcodeExporter.isOSX() ? "OSXFrameworks" : "iOSFrameworks"].toString(); auto frameworks = moduleInfo.moduleInfo [xcodeExporter.isOSX() ? "OSXFrameworks" : "iOSFrameworks"].toString();
xcodeExporter.xcodeFrameworks.addTokens (frameworks, ", ", {}); xcodeExporter.xcodeFrameworks.addTokens (frameworks, ", ", {});
parseAndAddLibs (xcodeExporter.xcodeLibs, moduleInfo.moduleInfo [exporter.isOSX() ? "OSXLibs" : "iOSLibs"].toString());
parseAndAddLibsToList (xcodeExporter.xcodeLibs, moduleInfo.moduleInfo [exporter.isOSX() ? "OSXLibs" : "iOSLibs"].toString());
} }
else if (exporter.isLinux()) else if (exporter.isLinux())
{ {
parseAndAddLibs (exporter.linuxLibs, moduleInfo.moduleInfo ["linuxLibs"].toString());
parseAndAddLibs (exporter.linuxPackages, moduleInfo.moduleInfo ["linuxPackages"].toString());
parseAndAddLibsToList (exporter.linuxLibs, moduleInfo.moduleInfo ["linuxLibs"].toString());
parseAndAddLibsToList (exporter.linuxPackages, moduleInfo.moduleInfo ["linuxPackages"].toString());
} }
else if (exporter.isWindows()) else if (exporter.isWindows())
{ {
if (exporter.isCodeBlocks()) if (exporter.isCodeBlocks())
parseAndAddLibs (exporter.mingwLibs, moduleInfo.moduleInfo ["mingwLibs"].toString());
parseAndAddLibsToList (exporter.mingwLibs, moduleInfo.moduleInfo ["mingwLibs"].toString());
else else
parseAndAddLibs (exporter.windowsLibs, moduleInfo.moduleInfo ["windowsLibs"].toString());
parseAndAddLibsToList (exporter.windowsLibs, moduleInfo.moduleInfo ["windowsLibs"].toString());
} }
else if (exporter.isAndroid()) else if (exporter.isAndroid())
{ {
parseAndAddLibs (exporter.androidLibs, moduleInfo.moduleInfo ["androidLibs"].toString());
parseAndAddLibsToList (exporter.androidLibs, moduleInfo.moduleInfo ["androidLibs"].toString());
} }
} }
void LibraryModule::addSettingsForModuleToExporter (ProjectExporter& exporter, ProjectSaver& projectSaver) const
{
addSearchPathsToExporter (exporter);
addDefinesToExporter (exporter);
addCompileUnitsToExporter (exporter, projectSaver);
addLibsToExporter (exporter);
}
void LibraryModule::getConfigFlags (Project& project, OwnedArray<Project::ConfigFlag>& flags) const void LibraryModule::getConfigFlags (Project& project, OwnedArray<Project::ConfigFlag>& flags) const
{ {
auto header = moduleInfo.getHeader(); auto header = moduleInfo.getHeader();
@@ -384,7 +391,25 @@ void LibraryModule::getConfigFlags (Project& project, OwnedArray<Project::Config
} }
} }
//==============================================================================
static void addFileWithGroups (Project::Item& group, const RelativePath& file, const String& path)
{
auto slash = path.indexOfChar (File::getSeparatorChar());
if (slash >= 0)
{
auto topLevelGroup = path.substring (0, slash);
auto remainingPath = path.substring (slash + 1);
auto newGroup = group.getOrCreateSubGroup (topLevelGroup);
addFileWithGroups (newGroup, file, remainingPath);
}
else
{
if (! group.containsChildForFile (file))
group.addRelativeFile (file, -1, false);
}
}
struct FileSorter struct FileSorter
{ {
static int compareElements (const File& f1, const File& f2) static int compareElements (const File& f1, const File& f2)
@@ -393,16 +418,19 @@ struct FileSorter
} }
}; };
bool LibraryModule::CompileUnit::hasSuffix (const File& f, const char* suffix)
void LibraryModule::findBrowseableFiles (const File& folder, Array<File>& filesFound) const
{ {
auto fileWithoutSuffix = f.getFileNameWithoutExtension() + ".";
Array<File> tempList;
FileSorter sorter;
return fileWithoutSuffix.containsIgnoreCase (suffix + String ("."))
|| fileWithoutSuffix.containsIgnoreCase (suffix + String ("_"));
}
DirectoryIterator iter (folder, true, "*", File::findFiles);
bool isHiddenFile;
void LibraryModule::CompileUnit::writeInclude (MemoryOutputStream&) const
{
while (iter.next (nullptr, &isHiddenFile, nullptr, nullptr, nullptr, nullptr))
if (! isHiddenFile && iter.getFile().hasFileExtension (browseableFileExtensions))
tempList.addSorted (sorter, iter.getFile());
filesFound.addArray (tempList);
} }
bool LibraryModule::CompileUnit::isNeededForExporter (ProjectExporter& exporter) const bool LibraryModule::CompileUnit::isNeededForExporter (ProjectExporter& exporter) const
@@ -428,6 +456,14 @@ String LibraryModule::CompileUnit::getFilenameForProxyFile() const
return "include_" + file.getFileName(); return "include_" + file.getFileName();
} }
bool LibraryModule::CompileUnit::hasSuffix (const File& f, const char* suffix)
{
auto fileWithoutSuffix = f.getFileNameWithoutExtension() + ".";
return fileWithoutSuffix.containsIgnoreCase (suffix + String ("."))
|| fileWithoutSuffix.containsIgnoreCase (suffix + String ("_"));
}
Array<LibraryModule::CompileUnit> LibraryModule::getAllCompileUnits (ProjectType::Target::Type forTarget) const Array<LibraryModule::CompileUnit> LibraryModule::getAllCompileUnits (ProjectType::Target::Type forTarget) const
{ {
auto files = getFolder().findChildFiles (File::findFiles, false); auto files = getFolder().findChildFiles (File::findFiles, false);
@@ -486,40 +522,6 @@ void LibraryModule::findAndAddCompiledUnits (ProjectExporter& exporter,
} }
} }
static void addFileWithGroups (Project::Item& group, const RelativePath& file, const String& path)
{
auto slash = path.indexOfChar (File::getSeparatorChar());
if (slash >= 0)
{
auto topLevelGroup = path.substring (0, slash);
auto remainingPath = path.substring (slash + 1);
auto newGroup = group.getOrCreateSubGroup (topLevelGroup);
addFileWithGroups (newGroup, file, remainingPath);
}
else
{
if (! group.containsChildForFile (file))
group.addRelativeFile (file, -1, false);
}
}
void LibraryModule::findBrowseableFiles (const File& folder, Array<File>& filesFound) const
{
Array<File> tempList;
FileSorter sorter;
DirectoryIterator iter (folder, true, "*", File::findFiles);
bool isHiddenFile;
while (iter.next (nullptr, &isHiddenFile, nullptr, nullptr, nullptr, nullptr))
if (! isHiddenFile && iter.getFile().hasFileExtension (browseableFileExtensions))
tempList.addSorted (sorter, iter.getFile());
filesFound.addArray (tempList);
}
void LibraryModule::addBrowseableCode (ProjectExporter& exporter, const Array<File>& compiled, const File& localModuleFolder) const void LibraryModule::addBrowseableCode (ProjectExporter& exporter, const Array<File>& compiled, const File& localModuleFolder) const
{ {
if (sourceFiles.isEmpty()) if (sourceFiles.isEmpty())
@@ -531,7 +533,7 @@ void LibraryModule::addBrowseableCode (ProjectExporter& exporter, const Array<Fi
auto& project = exporter.getProject(); auto& project = exporter.getProject();
if (project.getEnabledModules().shouldCopyModuleFilesLocally (getID()).getValue())
if (project.getEnabledModules().shouldCopyModuleFilesLocally (getID()))
moduleHeader = project.getLocalModuleFolder (getID()).getChildFile (moduleHeader.getFileName()); moduleHeader = project.getLocalModuleFolder (getID()).getChildFile (moduleHeader.getFileName());
auto isModuleHeader = [&] (const File& f) { return f.getFileName() == moduleHeader.getFileName(); }; auto isModuleHeader = [&] (const File& f) { return f.getFileName() == moduleHeader.getFileName(); };
@@ -552,131 +554,68 @@ void LibraryModule::addBrowseableCode (ProjectExporter& exporter, const Array<Fi
exporter.getModulesGroup().state.appendChild (sourceGroup.state.createCopy(), nullptr); exporter.getModulesGroup().state.appendChild (sourceGroup.state.createCopy(), nullptr);
} }
//============================================================================== //==============================================================================
EnabledModuleList::EnabledModuleList (Project& p, const ValueTree& s) EnabledModuleList::EnabledModuleList (Project& p, const ValueTree& s)
: project (p), state (s) : project (p), state (s)
{ {
} }
ModuleDescription EnabledModuleList::getModuleInfo (const String& moduleID)
{
return ModuleDescription (project.getModuleWithID (moduleID).second);
}
bool EnabledModuleList::isModuleEnabled (const String& moduleID) const
{
return state.getChildWithProperty (Ids::ID, moduleID).isValid();
}
bool EnabledModuleList::isAudioPluginModuleMissing() const
StringArray EnabledModuleList::getAllModules() const
{ {
return project.isAudioPluginProject()
&& ! isModuleEnabled ("juce_audio_plugin_client");
}
StringArray moduleIDs;
bool EnabledModuleList::shouldUseGlobalPath (const String& moduleID) const
{
return static_cast<bool> (state.getChildWithProperty (Ids::ID, moduleID)
.getProperty (Ids::useGlobalPath));
}
for (int i = 0; i < getNumModules(); ++i)
moduleIDs.add (getModuleID (i));
Value EnabledModuleList::getShouldUseGlobalPathValue (const String& moduleID) const
{
return state.getChildWithProperty (Ids::ID, moduleID)
.getPropertyAsValue (Ids::useGlobalPath, getUndoManager());
return moduleIDs;
} }
Value EnabledModuleList::shouldShowAllModuleFilesInProject (const String& moduleID)
void EnabledModuleList::createRequiredModules (OwnedArray<LibraryModule>& modules)
{ {
return state.getChildWithProperty (Ids::ID, moduleID)
.getPropertyAsValue (Ids::showAllCode, getUndoManager());
for (int i = 0; i < getNumModules(); ++i)
modules.add (new LibraryModule (getModuleInfo (getModuleID (i))));
} }
struct ModuleTreeSorter
void EnabledModuleList::sortAlphabetically()
{ {
static int compareElements (const ValueTree& m1, const ValueTree& m2)
struct ModuleTreeSorter
{ {
return m1[Ids::ID].toString().compareIgnoreCase (m2[Ids::ID]);
}
};
static int compareElements (const ValueTree& m1, const ValueTree& m2)
{
return m1[Ids::ID].toString().compareIgnoreCase (m2[Ids::ID]);
}
};
void EnabledModuleList::sortAlphabetically()
{
ModuleTreeSorter sorter; ModuleTreeSorter sorter;
state.sort (sorter, getUndoManager(), false); state.sort (sorter, getUndoManager(), false);
} }
Value EnabledModuleList::shouldCopyModuleFilesLocally (const String& moduleID) const
File EnabledModuleList::getDefaultModulesFolder() const
{ {
return state.getChildWithProperty (Ids::ID, moduleID)
.getPropertyAsValue (Ids::useLocalCopy, getUndoManager());
}
File globalPath (getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get().toString());
void EnabledModuleList::addModule (const File& moduleFolder, bool copyLocally, bool useGlobalPath, bool sendAnalyticsEvent)
{
ModuleDescription info (moduleFolder);
if (globalPath.exists())
return globalPath;
if (info.isValid())
for (auto& exporterPathModule : project.getExporterPathsModuleList().getAllModules())
{ {
auto moduleID = info.getID();
if (! isModuleEnabled (moduleID))
{
ValueTree module (Ids::MODULE);
module.setProperty (Ids::ID, moduleID, getUndoManager());
state.appendChild (module, getUndoManager());
sortAlphabetically();
shouldShowAllModuleFilesInProject (moduleID) = true;
shouldCopyModuleFilesLocally (moduleID) = copyLocally;
getShouldUseGlobalPathValue (moduleID) = useGlobalPath;
RelativePath path (moduleFolder.getParentDirectory(),
project.getProjectFolder(), RelativePath::projectFolder);
for (Project::ExporterIterator exporter (project); exporter.next();)
exporter->getPathForModuleValue (moduleID) = path.toUnixStyle();
if (! useGlobalPath)
project.rescanExporterPathModules (false);
if (sendAnalyticsEvent)
{
StringPairArray data;
data.set ("label", moduleID);
auto f = exporterPathModule.second;
Analytics::getInstance()->logEvent ("Module Added", data, ProjucerAnalyticsEvent::projectEvent);
}
}
if (f.isDirectory())
return f.getParentDirectory();
} }
}
void EnabledModuleList::removeModule (String moduleID) // must be pass-by-value, and not a const ref!
{
for (auto i = state.getNumChildren(); --i >= 0;)
if (state.getChild(i) [Ids::ID] == moduleID)
state.removeChild (i, getUndoManager());
for (Project::ExporterIterator exporter (project); exporter.next();)
exporter->removePathForModule (moduleID);
return File::getCurrentWorkingDirectory();
} }
void EnabledModuleList::createRequiredModules (OwnedArray<LibraryModule>& modules)
ModuleDescription EnabledModuleList::getModuleInfo (const String& moduleID)
{ {
for (int i = 0; i < getNumModules(); ++i)
modules.add (new LibraryModule (getModuleInfo (getModuleID (i))));
return ModuleDescription (project.getModuleWithID (moduleID).second);
} }
StringArray EnabledModuleList::getAllModules() const
bool EnabledModuleList::isModuleEnabled (const String& moduleID) const
{ {
StringArray moduleIDs;
for (int i = 0; i < getNumModules(); ++i)
moduleIDs.add (getModuleID (i));
return moduleIDs;
return state.getChildWithProperty (Ids::ID, moduleID).isValid();
} }
static void getDependencies (Project& project, const String& moduleID, StringArray& dependencies) static void getDependencies (Project& project, const String& moduleID, StringArray& dependencies)
@@ -717,6 +656,39 @@ bool EnabledModuleList::doesModuleHaveHigherCppStandardThanProject (const String
return (moduleCppStandard.getIntValue() > projectCppStandard.getIntValue()); return (moduleCppStandard.getIntValue() > projectCppStandard.getIntValue());
} }
bool EnabledModuleList::shouldUseGlobalPath (const String& moduleID) const
{
return (bool) shouldUseGlobalPathValue (moduleID).getValue();
}
Value EnabledModuleList::shouldUseGlobalPathValue (const String& moduleID) const
{
return state.getChildWithProperty (Ids::ID, moduleID)
.getPropertyAsValue (Ids::useGlobalPath, getUndoManager());
}
bool EnabledModuleList::shouldShowAllModuleFilesInProject (const String& moduleID) const
{
return (bool) shouldShowAllModuleFilesInProjectValue (moduleID).getValue();
}
Value EnabledModuleList::shouldShowAllModuleFilesInProjectValue (const String& moduleID) const
{
return state.getChildWithProperty (Ids::ID, moduleID)
.getPropertyAsValue (Ids::showAllCode, getUndoManager());
}
bool EnabledModuleList::shouldCopyModuleFilesLocally (const String& moduleID) const
{
return (bool) shouldCopyModuleFilesLocallyValue (moduleID).getValue();
}
Value EnabledModuleList::shouldCopyModuleFilesLocallyValue (const String& moduleID) const
{
return state.getChildWithProperty (Ids::ID, moduleID)
.getPropertyAsValue (Ids::useLocalCopy, getUndoManager());
}
bool EnabledModuleList::areMostModulesUsingGlobalPath() const bool EnabledModuleList::areMostModulesUsingGlobalPath() const
{ {
int numYes = 0, numNo = 0; int numYes = 0, numNo = 0;
@@ -738,7 +710,7 @@ bool EnabledModuleList::areMostModulesCopiedLocally() const
for (auto i = getNumModules(); --i >= 0;) for (auto i = getNumModules(); --i >= 0;)
{ {
if (shouldCopyModuleFilesLocally (getModuleID (i)).getValue())
if (shouldCopyModuleFilesLocally (getModuleID (i)))
++numYes; ++numYes;
else else
++numNo; ++numNo;
@@ -747,40 +719,43 @@ bool EnabledModuleList::areMostModulesCopiedLocally() const
return numYes > numNo; return numYes > numNo;
} }
void EnabledModuleList::setLocalCopyModeForAllModules (bool copyLocally)
void EnabledModuleList::addModule (const File& moduleFolder, bool copyLocally, bool useGlobalPath, bool sendAnalyticsEvent)
{ {
for (auto i = getNumModules(); --i >= 0;)
shouldCopyModuleFilesLocally (project.getEnabledModules().getModuleID (i)) = copyLocally;
}
ModuleDescription info (moduleFolder);
File EnabledModuleList::findDefaultModulesFolder (Project& project)
{
File globalPath (getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get().toString());
if (info.isValid())
{
auto moduleID = info.getID();
if (globalPath.exists())
return globalPath;
if (! isModuleEnabled (moduleID))
{
ValueTree module (Ids::MODULE);
module.setProperty (Ids::ID, moduleID, getUndoManager());
for (auto& exporterPathModule : project.getExporterPathsModuleList().getAllModules())
{
auto f = exporterPathModule.second;
state.appendChild (module, getUndoManager());
sortAlphabetically();
if (f.isDirectory())
return f.getParentDirectory();
}
shouldShowAllModuleFilesInProjectValue (moduleID) = true;
shouldCopyModuleFilesLocallyValue (moduleID) = copyLocally;
shouldUseGlobalPathValue (moduleID) = useGlobalPath;
return File::getCurrentWorkingDirectory();
}
RelativePath path (moduleFolder.getParentDirectory(),
project.getProjectFolder(), RelativePath::projectFolder);
void EnabledModuleList::addModuleFromUserSelectedFile()
{
static auto lastLocation = findDefaultModulesFolder (project);
for (Project::ExporterIterator exporter (project); exporter.next();)
exporter->getPathForModuleValue (moduleID) = path.toUnixStyle();
FileChooser fc ("Select a module to add...", lastLocation, {});
if (! useGlobalPath)
project.rescanExporterPathModules (false);
if (fc.browseForDirectory())
{
lastLocation = fc.getResult();
addModuleOfferingToCopy (lastLocation, true);
if (sendAnalyticsEvent)
{
StringPairArray data;
data.set ("label", moduleID);
Analytics::getInstance()->logEvent ("Module Added", data, ProjucerAnalyticsEvent::projectEvent);
}
}
} }
} }
@@ -797,6 +772,19 @@ void EnabledModuleList::addModuleInteractive (const String& moduleID)
addModuleFromUserSelectedFile(); addModuleFromUserSelectedFile();
} }
void EnabledModuleList::addModuleFromUserSelectedFile()
{
auto lastLocation = getDefaultModulesFolder();
FileChooser fc ("Select a module to add...", lastLocation, {});
if (fc.browseForDirectory())
{
lastLocation = fc.getResult();
addModuleOfferingToCopy (lastLocation, true);
}
}
void EnabledModuleList::addModuleOfferingToCopy (const File& f, bool isFromUserSpecifiedFolder) void EnabledModuleList::addModuleOfferingToCopy (const File& f, bool isFromUserSpecifiedFolder)
{ {
ModuleDescription m (f); ModuleDescription m (f);
@@ -820,12 +808,12 @@ void EnabledModuleList::addModuleOfferingToCopy (const File& f, bool isFromUserS
true); true);
} }
bool isJUCEFolder (const File& f)
void EnabledModuleList::removeModule (String moduleID) // must be pass-by-value, and not a const ref!
{ {
return isJUCEModulesFolder (f.getChildFile ("modules"));
}
for (auto i = state.getNumChildren(); --i >= 0;)
if (state.getChild(i) [Ids::ID] == moduleID)
state.removeChild (i, getUndoManager());
bool isJUCEModulesFolder (const File& f)
{
return f.isDirectory() && f.getChildFile ("juce_core").isDirectory();
for (Project::ExporterIterator exporter (project); exporter.next();)
exporter->removePathForModule (moduleID);
} }

+ 38
- 38
extras/Projucer/Source/Project/jucer_Module.h View File

@@ -30,16 +30,11 @@
class ProjectExporter; class ProjectExporter;
class ProjectSaver; class ProjectSaver;
//==============================================================================
bool isJUCEModulesFolder (const File&);
bool isJUCEFolder (const File&);
//============================================================================== //==============================================================================
struct ModuleDescription struct ModuleDescription
{ {
ModuleDescription() {}
ModuleDescription() = default;
ModuleDescription (const File& folder); ModuleDescription (const File& folder);
ModuleDescription (const var& info) : moduleInfo (info) {}
bool isValid() const { return getID().isNotEmpty(); } bool isValid() const { return getID().isNotEmpty(); }
@@ -57,8 +52,6 @@ struct ModuleDescription
File getFolder() const { jassert (moduleFolder != File()); return moduleFolder; } File getFolder() const { jassert (moduleFolder != File()); return moduleFolder; }
File getHeader() const; File getHeader() const;
bool isPluginClient() const { return getID() == "juce_audio_plugin_client"; }
File moduleFolder; File moduleFolder;
var moduleInfo; var moduleInfo;
URL url; URL url;
@@ -91,7 +84,6 @@ public:
File file; File file;
bool isCompiledForObjC, isCompiledForNonObjC; bool isCompiledForObjC, isCompiledForNonObjC;
void writeInclude (MemoryOutputStream&) const;
bool isNeededForExporter (ProjectExporter&) const; bool isNeededForExporter (ProjectExporter&) const;
String getFilenameForProxyFile() const; String getFilenameForProxyFile() const;
static bool hasSuffix (const File&, const char*); static bool hasSuffix (const File&, const char*);
@@ -104,20 +96,25 @@ public:
ModuleDescription moduleInfo; ModuleDescription moduleInfo;
private: private:
mutable Array<File> sourceFiles;
OwnedArray<Project::ConfigFlag> configFlags;
void addSearchPathsToExporter (ProjectExporter&) const;
void addDefinesToExporter (ProjectExporter&) const;
void addCompileUnitsToExporter (ProjectExporter&, ProjectSaver&) const;
void addLibsToExporter (ProjectExporter&) const;
void addBrowseableCode (ProjectExporter&, const Array<File>& compiled, const File& localModuleFolder) const; void addBrowseableCode (ProjectExporter&, const Array<File>& compiled, const File& localModuleFolder) const;
mutable Array<File> sourceFiles;
OwnedArray<Project::ConfigFlag> configFlags;
}; };
//============================================================================== //==============================================================================
using ModuleIDAndFolder = std::pair<String, File>;
using ModuleIDAndFolderList = std::vector<ModuleIDAndFolder>;
class AvailableModuleList class AvailableModuleList
{ {
public: public:
AvailableModuleList();
using ModuleIDAndFolder = std::pair<String, File>;
using ModuleIDAndFolderList = std::vector<ModuleIDAndFolder>;
AvailableModuleList() = default;
void scanPaths (const Array<File>&); void scanPaths (const Array<File>&);
void scanPathsAsync (const Array<File>&); void scanPathsAsync (const Array<File>&);
@@ -157,46 +154,49 @@ class EnabledModuleList
public: public:
EnabledModuleList (Project&, const ValueTree&); EnabledModuleList (Project&, const ValueTree&);
static File findDefaultModulesFolder (Project&);
bool isModuleEnabled (const String& moduleID) const;
//==============================================================================
ValueTree getState() const { return state; }
bool shouldUseGlobalPath (const String& moduleID) const;
Value getShouldUseGlobalPathValue (const String& moduleID) const;
StringArray getAllModules() const;
void createRequiredModules (OwnedArray<LibraryModule>& modules);
void sortAlphabetically();
Value shouldShowAllModuleFilesInProject (const String& moduleID);
Value shouldCopyModuleFilesLocally (const String& moduleID) const;
File getDefaultModulesFolder() const;
void removeModule (String moduleID);
bool isAudioPluginModuleMissing() const;
int getNumModules() const { return state.getNumChildren(); }
String getModuleID (int index) const { return state.getChild (index) [Ids::ID].toString(); }
ModuleDescription getModuleInfo (const String& moduleID); ModuleDescription getModuleInfo (const String& moduleID);
void addModule (const File& moduleManifestFile, bool copyLocally, bool useGlobalPath, bool sendAnalyticsEvent);
void addModuleInteractive (const String& moduleID);
void addModuleFromUserSelectedFile();
void addModuleOfferingToCopy (const File&, bool isFromUserSpecifiedFolder);
StringArray getAllModules() const;
bool isModuleEnabled (const String& moduleID) const;
StringArray getExtraDependenciesNeeded (const String& moduleID) const; StringArray getExtraDependenciesNeeded (const String& moduleID) const;
bool doesModuleHaveHigherCppStandardThanProject (const String& moduleID); bool doesModuleHaveHigherCppStandardThanProject (const String& moduleID);
void createRequiredModules (OwnedArray<LibraryModule>& modules);
int getNumModules() const { return state.getNumChildren(); }
String getModuleID (int index) const { return state.getChild (index) [Ids::ID].toString(); }
bool shouldUseGlobalPath (const String& moduleID) const;
Value shouldUseGlobalPathValue (const String& moduleID) const;
bool shouldShowAllModuleFilesInProject (const String& moduleID) const;
Value shouldShowAllModuleFilesInProjectValue (const String& moduleID) const;
bool shouldCopyModuleFilesLocally (const String& moduleID) const;
Value shouldCopyModuleFilesLocallyValue (const String& moduleID) const;
bool areMostModulesUsingGlobalPath() const; bool areMostModulesUsingGlobalPath() const;
bool areMostModulesCopiedLocally() const; bool areMostModulesCopiedLocally() const;
void setLocalCopyModeForAllModules (bool copyLocally);
void sortAlphabetically();
//==============================================================================
void addModule (const File& moduleManifestFile, bool copyLocally, bool useGlobalPath, bool sendAnalyticsEvent);
void addModuleInteractive (const String& moduleID);
void addModuleFromUserSelectedFile();
void addModuleOfferingToCopy (const File&, bool isFromUserSpecifiedFolder);
Project& project;
ValueTree state;
void removeModule (String moduleID);
private: private:
UndoManager* getUndoManager() const { return project.getUndoManagerFor (state); } UndoManager* getUndoManager() const { return project.getUndoManagerFor (state); }
Project& project;
ValueTree state;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EnabledModuleList) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EnabledModuleList)
}; };

+ 1
- 1
extras/Projucer/Source/Project/jucer_Project.cpp View File

@@ -2100,7 +2100,7 @@ void Project::rescanExporterPathModules (bool async)
exporterPathsModuleList->scanPaths (getExporterModulePathsToScan (*this)); exporterPathsModuleList->scanPaths (getExporterModulePathsToScan (*this));
} }
ModuleIDAndFolder Project::getModuleWithID (const String& id)
AvailableModuleList::ModuleIDAndFolder Project::getModuleWithID (const String& id)
{ {
if (! getEnabledModules().shouldUseGlobalPath (id)) if (! getEnabledModules().shouldUseGlobalPath (id))
{ {


+ 2
- 2
extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp View File

@@ -617,7 +617,7 @@ TargetOS::OS ProjectExporter::getTargetOSForExporter() const
RelativePath ProjectExporter::getModuleFolderRelativeToProject (const String& moduleID) const RelativePath ProjectExporter::getModuleFolderRelativeToProject (const String& moduleID) const
{ {
if (project.getEnabledModules().shouldCopyModuleFilesLocally (moduleID).getValue())
if (project.getEnabledModules().shouldCopyModuleFilesLocally (moduleID))
return RelativePath (project.getRelativePathForFile (project.getLocalModuleFolder (moduleID)), return RelativePath (project.getRelativePathForFile (project.getLocalModuleFolder (moduleID)),
RelativePath::projectFolder); RelativePath::projectFolder);
@@ -636,7 +636,7 @@ String ProjectExporter::getLegacyModulePath() const
RelativePath ProjectExporter::getLegacyModulePath (const String& moduleID) const RelativePath ProjectExporter::getLegacyModulePath (const String& moduleID) const
{ {
if (project.getEnabledModules().state.getChildWithProperty (Ids::ID, moduleID) ["useLocalCopy"])
if (project.getEnabledModules().shouldCopyModuleFilesLocally (moduleID))
return RelativePath (project.getRelativePathForFile (project.getGeneratedCodeFolder() return RelativePath (project.getRelativePathForFile (project.getGeneratedCodeFolder()
.getChildFile ("modules") .getChildFile ("modules")
.getChildFile (moduleID)), RelativePath::projectFolder); .getChildFile (moduleID)), RelativePath::projectFolder);


+ 10
- 0
extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.cpp View File

@@ -411,6 +411,16 @@ bool isValidJUCEExamplesDirectory (const File& directory) noexcept
return directory.getChildFile ("Assets").getChildFile ("juce_icon.png").existsAsFile(); return directory.getChildFile ("Assets").getChildFile ("juce_icon.png").existsAsFile();
} }
bool isJUCEFolder (const File& f)
{
return isJUCEModulesFolder (f.getChildFile ("modules"));
}
bool isJUCEModulesFolder (const File& f)
{
return f.isDirectory() && f.getChildFile ("juce_core").isDirectory();
}
//============================================================================== //==============================================================================
static var parseJUCEHeaderMetadata (const StringArray& lines) static var parseJUCEHeaderMetadata (const StringArray& lines)
{ {


+ 3
- 0
extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.h View File

@@ -73,6 +73,9 @@ bool isPIPFile (const File&) noexcept;
bool isValidJUCEExamplesDirectory (const File&) noexcept; bool isValidJUCEExamplesDirectory (const File&) noexcept;
bool isJUCEModulesFolder (const File&);
bool isJUCEFolder (const File&);
//============================================================================== //==============================================================================
int indexOfLineStartingWith (const StringArray& lines, const String& text, int startIndex); int indexOfLineStartingWith (const StringArray& lines, const String& text, int startIndex);


+ 0
- 1
extras/Projucer/Source/Utility/UI/PropertyComponents/jucer_FilePathPropertyComponent.h View File

@@ -87,7 +87,6 @@ public:
void filesDropped (const StringArray& selectedFiles, int, int) override void filesDropped (const StringArray& selectedFiles, int, int) override
{ {
setTo (selectedFiles[0]); setTo (selectedFiles[0]);
highlightForDragAndDrop = false; highlightForDragAndDrop = false;


Loading…
Cancel
Save