1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Big refactoring of the introjucer's module handling - removed the global module path, and each module now stores its path for each exporter. Rewrote all the UI for downloading + updating modules.

This commit is contained in:
jules 2013-09-30 14:41:36 +01:00
parent 35286f06be
commit a9aae9651b
36 changed files with 1706 additions and 1862 deletions

View file

@ -29,31 +29,18 @@
#include "../Application/jucer_OpenDocumentManager.h"
#include "../Application/jucer_Application.h"
//==============================================================================
namespace Tags
{
const Identifier projectRoot ("JUCERPROJECT");
const Identifier projectMainGroup ("MAINGROUP");
const Identifier group ("GROUP");
const Identifier file ("FILE");
const Identifier exporters ("EXPORTFORMATS");
const Identifier configGroup ("JUCEOPTIONS");
}
const char* Project::projectFileExtension = ".jucer";
//==============================================================================
Project::Project (const File& f)
: FileBasedDocument (projectFileExtension,
String ("*") + projectFileExtension,
"Choose a Jucer project to load",
"Save Jucer project"),
projectRoot (Tags::projectRoot)
projectRoot (Ids::JUCERPROJECT)
{
Logger::writeToLog ("Loading project: " + f.getFullPathName());
setFile (f);
removeDefunctExporters();
updateOldModulePaths();
setMissingDefaultValues();
setChangedFlag (false);
@ -67,6 +54,8 @@ Project::~Project()
IntrojucerApp::getApp().openDocumentManager.closeAllDocumentsUsingProject (*this, false);
}
const char* Project::projectFileExtension = ".jucer";
//==============================================================================
void Project::setTitle (const String& newTitle)
{
@ -76,7 +65,7 @@ void Project::setTitle (const String& newTitle)
String Project::getTitle() const
{
return projectRoot.getChildWithName (Tags::projectMainGroup) [Ids::name];
return projectRoot.getChildWithName (Ids::MAINGROUP) [Ids::name];
}
String Project::getDocumentTitle()
@ -96,9 +85,9 @@ void Project::setMissingDefaultValues()
projectRoot.setProperty (Ids::ID, createAlphaNumericUID(), nullptr);
// Create main file group if missing
if (! projectRoot.getChildWithName (Tags::projectMainGroup).isValid())
if (! projectRoot.getChildWithName (Ids::MAINGROUP).isValid())
{
Item mainGroup (*this, ValueTree (Tags::projectMainGroup));
Item mainGroup (*this, ValueTree (Ids::MAINGROUP));
projectRoot.addChild (mainGroup.state, 0, 0);
}
@ -119,8 +108,7 @@ void Project::setMissingDefaultValues()
getProjectType().setMissingProjectProperties (*this);
if (! projectRoot.getChildWithName (EnabledModuleList::modulesGroupTag).isValid())
getModules().addDefaultModules (false);
getModules().sortAlphabetically();
if (getBundleIdentifier().toString().isEmpty())
getBundleIdentifier() = getDefaultBundleIdentifier();
@ -133,7 +121,7 @@ void Project::setMissingDefaultValues()
void Project::updateOldStyleConfigList()
{
ValueTree deprecatedConfigsList (projectRoot.getChildWithName (ProjectExporter::configurations));
ValueTree deprecatedConfigsList (projectRoot.getChildWithName (Ids::CONFIGURATIONS));
if (deprecatedConfigsList.isValid())
{
@ -176,7 +164,7 @@ void Project::moveOldPropertyFromProjectToAllExporters (Identifier name)
void Project::removeDefunctExporters()
{
ValueTree exporters (projectRoot.getChildWithName (Tags::exporters));
ValueTree exporters (projectRoot.getChildWithName (Ids::EXPORTFORMATS));
for (;;)
{
@ -189,18 +177,69 @@ void Project::removeDefunctExporters()
}
}
File Project::getBinaryDataCppFile (int index) const
void Project::updateOldModulePaths()
{
const File cpp (getGeneratedCodeFolder().getChildFile ("BinaryData.cpp"));
if (index > 0)
return cpp.getSiblingFile (cpp.getFileNameWithoutExtension() + String (index + 1))
.withFileExtension (cpp.getFileExtension());
return cpp;
for (Project::ExporterIterator exporter (*this); exporter.next();)
exporter->updateOldModulePaths();
}
//==============================================================================
static int getVersionElement (const String& v, int index)
{
StringArray parts;
parts.addTokens (v, "., ", String::empty);
return parts [parts.size() - index - 1].getIntValue();
}
static int getJuceVersion (const String& v)
{
return getVersionElement (v, 2) * 100000
+ getVersionElement (v, 1) * 1000
+ getVersionElement (v, 0);
}
static int getBuiltJuceVersion()
{
return JUCE_MAJOR_VERSION * 100000
+ JUCE_MINOR_VERSION * 1000
+ JUCE_BUILDNUMBER;
}
static bool isAnyModuleNewerThanIntrojucer (const OwnedArray<ModuleDescription>& modules)
{
for (int i = modules.size(); --i >= 0;)
{
const ModuleDescription* m = modules.getUnchecked(i);
if (m->getID().startsWith ("juce_")
&& getJuceVersion (m->getVersion()) > getBuiltJuceVersion())
return true;
}
return false;
}
void Project::warnAboutOldIntrojucerVersion()
{
ModuleList available;
available.scanAllKnownFolders (*this);
if (isAnyModuleNewerThanIntrojucer (available.modules))
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
"Introjucer",
"This version of the introjucer is out-of-date!"
"\n\n"
"Always make sure that you're running the very latest version, "
"preferably compiled directly from the JUCE repository that you're working with!");
}
//==============================================================================
static File lastDocumentOpened;
File Project::getLastDocumentOpened() { return lastDocumentOpened; }
void Project::setLastDocumentOpened (const File& file) { lastDocumentOpened = file; }
static void registerRecentFile (const File& file)
{
RecentlyOpenedFilesList::registerRecentFileNatively (file);
@ -208,24 +247,28 @@ static void registerRecentFile (const File& file)
getAppSettings().flush();
}
//==============================================================================
Result Project::loadDocument (const File& file)
{
ScopedPointer <XmlElement> xml (XmlDocument::parse (file));
if (xml == nullptr || ! xml->hasTagName (Tags::projectRoot.toString()))
if (xml == nullptr || ! xml->hasTagName (Ids::JUCERPROJECT.toString()))
return Result::fail ("Not a valid Jucer project!");
ValueTree newTree (ValueTree::fromXml (*xml));
if (! newTree.hasType (Tags::projectRoot))
if (! newTree.hasType (Ids::JUCERPROJECT))
return Result::fail ("The document contains errors and couldn't be parsed!");
registerRecentFile (file);
enabledModulesList = nullptr;
projectRoot = newTree;
removeDefunctExporters();
setMissingDefaultValues();
updateOldModulePaths();
setChangedFlag (false);
warnAboutOldIntrojucerVersion();
return Result::ok();
}
@ -253,12 +296,6 @@ Result Project::saveResourcesOnly (const File& file)
return saver.saveResourcesOnly();
}
//==============================================================================
static File lastDocumentOpened;
File Project::getLastDocumentOpened() { return lastDocumentOpened; }
void Project::setLastDocumentOpened (const File& file) { lastDocumentOpened = file; }
//==============================================================================
void Project::valueTreePropertyChanged (ValueTree&, const Identifier& property)
{
@ -389,6 +426,7 @@ void Project::createPropertyEditors (PropertyListBuilder& props)
"Extra comments: This field is not used for code or project generation, it's just a space where you can express your thoughts.");
}
//==============================================================================
static StringArray getConfigs (const Project& p)
{
StringArray configs;
@ -422,10 +460,25 @@ StringPairArray Project::getPreprocessorDefs() const
return parsePreprocessorDefs (projectRoot [Ids::defines]);
}
//==============================================================================
File Project::getBinaryDataCppFile (int index) const
{
const File cpp (getGeneratedCodeFolder().getChildFile ("BinaryData.cpp"));
if (index > 0)
return cpp.getSiblingFile (cpp.getFileNameWithoutExtension() + String (index + 1))
.withFileExtension (cpp.getFileExtension());
return cpp;
}
Project::Item Project::getMainGroup()
{
return Item (*this, projectRoot.getChildWithName (Tags::projectMainGroup));
return Item (*this, projectRoot.getChildWithName (Ids::MAINGROUP));
}
PropertiesFile& Project::getStoredProperties() const
{
return getAppSettings().getProjectProperties (getProjectUID());
}
static void findImages (const Project::Item& item, OwnedArray<Project::Item>& found)
@ -470,16 +523,16 @@ Image Project::Item::loadAsImageFile() const
Project::Item Project::Item::createGroup (Project& project, const String& name, const String& uid)
{
Item group (project, ValueTree (Tags::group));
Item group (project, ValueTree (Ids::GROUP));
group.setID (uid);
group.initialiseMissingProperties();
group.getNameValue() = name;
return group;
}
bool Project::Item::isFile() const { return state.hasType (Tags::file); }
bool Project::Item::isGroup() const { return state.hasType (Tags::group) || isMainGroup(); }
bool Project::Item::isMainGroup() const { return state.hasType (Tags::projectMainGroup); }
bool Project::Item::isFile() const { return state.hasType (Ids::FILE); }
bool Project::Item::isGroup() const { return state.hasType (Ids::GROUP) || isMainGroup(); }
bool Project::Item::isMainGroup() const { return state.hasType (Ids::MAINGROUP); }
bool Project::Item::isImageFile() const { return isFile() && ImageFileFormat::findImageFormatForFileExtension (getFile()) != nullptr; }
Project::Item Project::Item::findItemWithID (const String& targetId) const
@ -618,7 +671,7 @@ File Project::Item::determineGroupFolder() const
}
else
{
f = project.getFile().getParentDirectory();
f = project.getProjectFolder();
if (f.getChildFile ("Source").isDirectory())
f = f.getChildFile ("Source");
@ -683,8 +736,8 @@ struct ItemSorterWithGroupsAtStart
{
static int compareElements (const ValueTree& first, const ValueTree& second)
{
const bool firstIsGroup = first.hasType (Tags::group);
const bool secondIsGroup = second.hasType (Tags::group);
const bool firstIsGroup = first.hasType (Ids::GROUP);
const bool secondIsGroup = second.hasType (Ids::GROUP);
if (firstIsGroup == secondIsGroup)
return first [Ids::name].toString().compareIgnoreCase (second [Ids::name].toString());
@ -712,7 +765,7 @@ Project::Item Project::Item::getOrCreateSubGroup (const String& name)
for (int i = state.getNumChildren(); --i >= 0;)
{
const ValueTree child (state.getChild (i));
if (child.getProperty (Ids::name) == name && child.hasType (Tags::group))
if (child.getProperty (Ids::name) == name && child.hasType (Ids::GROUP))
return Item (project, child);
}
@ -764,7 +817,7 @@ bool Project::Item::addFile (const File& file, int insertIndex, const bool shoul
void Project::Item::addFileUnchecked (const File& file, int insertIndex, const bool shouldCompile)
{
Item item (project, ValueTree (Tags::file));
Item item (project, ValueTree (Ids::FILE));
item.initialiseMissingProperties();
item.getNameValue() = file.getFileName();
item.getShouldCompileValue() = shouldCompile && file.hasFileExtension ("cpp;mm;c;m;cc;cxx;r");
@ -779,7 +832,7 @@ void Project::Item::addFileUnchecked (const File& file, int insertIndex, const b
bool Project::Item::addRelativeFile (const RelativePath& file, int insertIndex, bool shouldCompile)
{
Item item (project, ValueTree (Tags::file));
Item item (project, ValueTree (Ids::FILE));
item.initialiseMissingProperties();
item.getNameValue() = file.getFileName();
item.getShouldCompileValue() = shouldCompile;
@ -824,7 +877,7 @@ bool Project::Item::isIconCrossedOut() const
//==============================================================================
ValueTree Project::getConfigNode()
{
return projectRoot.getOrCreateChildWithName (Tags::configGroup, nullptr);
return projectRoot.getOrCreateChildWithName (Ids::JUCEOPTIONS, nullptr);
}
const char* const Project::configFlagDefault = "default";
@ -844,7 +897,7 @@ Value Project::getConfigFlag (const String& name)
bool Project::isConfigFlagEnabled (const String& name) const
{
return projectRoot.getChildWithName (Tags::configGroup).getProperty (name) == configFlagEnabled;
return projectRoot.getChildWithName (Ids::JUCEOPTIONS).getProperty (name) == configFlagEnabled;
}
void Project::sanitiseConfigFlags()
@ -861,15 +914,18 @@ void Project::sanitiseConfigFlags()
}
//==============================================================================
EnabledModuleList Project::getModules()
EnabledModuleList& Project::getModules()
{
return EnabledModuleList (*this, projectRoot.getOrCreateChildWithName (EnabledModuleList::modulesGroupTag, nullptr));
if (enabledModulesList == nullptr)
enabledModulesList = new EnabledModuleList (*this, projectRoot.getOrCreateChildWithName (Ids::MODULES, nullptr));
return *enabledModulesList;
}
//==============================================================================
ValueTree Project::getExporters()
{
return projectRoot.getOrCreateChildWithName (Tags::exporters, nullptr);
return projectRoot.getOrCreateChildWithName (Ids::EXPORTFORMATS, nullptr);
}
int Project::getNumExporters()
@ -930,8 +986,3 @@ bool Project::ExporterIterator::next()
return true;
}
PropertiesFile& Project::getStoredProperties() const
{
return getAppSettings().getProjectProperties (getProjectUID());
}