From 2d56bedab5c94ea708a602794c3c876d6a3c8d10 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Sat, 17 Sep 2011 16:15:38 +0100 Subject: [PATCH] Introjucer update to provide downloading of new modules directly from the website. --- .../Source/Application/jucer_Application.h | 55 +- .../Source/Application/jucer_CommandLine.cpp | 2 +- .../Source/Application/jucer_CommonHeaders.h | 2 +- .../Source/Application/jucer_JuceUpdater.cpp | 559 ++++++++++-------- .../Source/Application/jucer_JuceUpdater.h | 50 +- .../Source/Application/jucer_MainWindow.cpp | 2 +- .../Project Saving/jucer_ProjectExporter.cpp | 23 +- .../Project Saving/jucer_ProjectSaver.h | 2 +- .../Source/Project/jucer_Module.cpp | 147 ++++- .../Introjucer/Source/Project/jucer_Module.h | 24 +- .../Source/Project/jucer_NewProjectWizard.cpp | 3 +- .../Source/Project/jucer_Project.cpp | 12 - .../jucer_ProjectInformationComponent.cpp | 77 ++- .../Source/Utility/jucer_FileHelpers.cpp | 23 +- .../Source/Utility/jucer_FileHelpers.h | 3 +- .../Source/Utility/jucer_StoredSettings.cpp | 17 - .../Source/Utility/jucer_StoredSettings.h | 3 - .../juce_core/system/juce_StandardHeader.h | 2 +- 18 files changed, 606 insertions(+), 400 deletions(-) diff --git a/extras/Introjucer/Source/Application/jucer_Application.h b/extras/Introjucer/Source/Application/jucer_Application.h index f0586fb2d6..d69d4088f9 100644 --- a/extras/Introjucer/Source/Application/jucer_Application.h +++ b/extras/Introjucer/Source/Application/jucer_Application.h @@ -38,7 +38,10 @@ class JucerApplication : public JUCEApplication { public: //============================================================================== - JucerApplication() {} + JucerApplication() + { + } + ~JucerApplication() {} //============================================================================== @@ -96,12 +99,18 @@ public: mainWindows.clear(); OpenDocumentManager::deleteInstance(); - deleteAndZero (commandManager); + commandManager = nullptr; } //============================================================================== void systemRequestedQuit() { + if (cancelAnyModalComponents()) + { + new AsyncQuitRetrier(); + return; + } + while (mainWindows.size() > 0) { if (! mainWindows[0]->closeCurrentProject()) @@ -139,11 +148,11 @@ public: bool moreThanOneInstanceAllowed() { - #ifndef JUCE_LINUX + #ifndef JUCE_LINUX return false; - #else + #else return true; //xxx should be false but doesn't work on linux.. - #endif + #endif } void anotherInstanceStarted (const String& commandLine) @@ -352,7 +361,12 @@ public: case CommandIDs::showPrefs: showPrefsPanel(); break; case CommandIDs::saveAll: OpenDocumentManager::getInstance()->saveAll(); break; case CommandIDs::closeAllDocuments: closeAllDocuments (true); break; - case CommandIDs::showJuceVersion: JuceUpdater::show (mainWindows[0]); break; + case CommandIDs::showJuceVersion: + { + ModuleList list (ModuleList::getDefaultModulesFolder (nullptr)); + JuceUpdater::show (list, mainWindows[0]); + break; + } default: return JUCEApplication::perform (info); } @@ -503,6 +517,35 @@ private: return createNewMainWindow(); } + + //============================================================================== + static bool cancelAnyModalComponents() + { + const int numModal = ModalComponentManager::getInstance()->getNumModalComponents(); + + for (int i = numModal; --i >= 0;) + if (ModalComponentManager::getInstance()->getModalComponent(i) != nullptr) + ModalComponentManager::getInstance()->getModalComponent(i)->exitModalState (0); + + return numModal > 0; + } + + class AsyncQuitRetrier : public Timer + { + public: + AsyncQuitRetrier() { startTimer (500); } + + void timerCallback() + { + stopTimer(); + delete this; + + if (JUCEApplication::getInstance() != nullptr) + JUCEApplication::getInstance()->systemRequestedQuit(); + } + + JUCE_DECLARE_NON_COPYABLE (AsyncQuitRetrier); + }; }; diff --git a/extras/Introjucer/Source/Application/jucer_CommandLine.cpp b/extras/Introjucer/Source/Application/jucer_CommandLine.cpp index 239eb68f5c..aabfab1bb9 100644 --- a/extras/Introjucer/Source/Application/jucer_CommandLine.cpp +++ b/extras/Introjucer/Source/Application/jucer_CommandLine.cpp @@ -192,7 +192,7 @@ namespace int listModules() { std::cout << "Downloading list of available modules..." << std::endl; - ModuleList list; + ModuleList list (File::nonexistent); list.loadFromWebsite(); for (int i = 0; i < list.modules.size(); ++i) diff --git a/extras/Introjucer/Source/Application/jucer_CommonHeaders.h b/extras/Introjucer/Source/Application/jucer_CommonHeaders.h index 30cc37f663..8cc17acf96 100644 --- a/extras/Introjucer/Source/Application/jucer_CommonHeaders.h +++ b/extras/Introjucer/Source/Application/jucer_CommonHeaders.h @@ -37,7 +37,7 @@ #include "jucer_CommandIDs.h" //============================================================================== -extern ApplicationCommandManager* commandManager; +extern ScopedPointer commandManager; //============================================================================== const char* const projectItemDragType = "Project Items"; diff --git a/extras/Introjucer/Source/Application/jucer_JuceUpdater.cpp b/extras/Introjucer/Source/Application/jucer_JuceUpdater.cpp index b598e39ecd..0cf759733a 100644 --- a/extras/Introjucer/Source/Application/jucer_JuceUpdater.cpp +++ b/extras/Introjucer/Source/Application/jucer_JuceUpdater.cpp @@ -25,30 +25,45 @@ #include "../jucer_Headers.h" #include "jucer_JuceUpdater.h" +#include "../Project/jucer_Module.h" //============================================================================== -JuceUpdater::JuceUpdater() - : filenameComp ("Juce Folder", StoredSettings::getInstance()->getLastKnownJuceFolder(), +JuceUpdater::JuceUpdater (ModuleList& moduleList_) + : moduleList (moduleList_), + latestList (File::nonexistent), + filenameComp ("Juce Folder", ModuleList::getLocalModulesFolder (nullptr), true, true, false, "*", String::empty, "Select your Juce folder"), - checkNowButton ("Check Online for Available Updates...", - "Contacts the website to see if this version is up-to-date") + checkNowButton ("Check for available updates on the JUCE website...", + "Contacts the website to see if new modules are available"), + installButton ("Download and install selected modules..."), + selectAllButton ("Select/Deselect All") { addAndMakeVisible (&label); + addAndMakeVisible (¤tVersionLabel); addAndMakeVisible (&filenameComp); addAndMakeVisible (&checkNowButton); - addAndMakeVisible (¤tVersionLabel); + addAndMakeVisible (&installButton); + addAndMakeVisible (&selectAllButton); checkNowButton.addListener (this); + installButton.addListener (this); + selectAllButton.addListener (this); filenameComp.addListener (this); currentVersionLabel.setFont (Font (14.0f, Font::italic)); label.setFont (Font (12.0f)); - label.setText ("Destination folder:", false); + label.setText ("Local modules folder:", false); addAndMakeVisible (&availableVersionsList); availableVersionsList.setModel (this); - setSize (600, 300); + updateInstallButtonStatus(); + versionsToDownload = ValueTree ("modules"); + versionsToDownload.addListener (this); + + setSize (600, 500); + + checkNow(); } JuceUpdater::~JuceUpdater() @@ -57,12 +72,32 @@ JuceUpdater::~JuceUpdater() filenameComp.removeListener (this); } -void JuceUpdater::show (Component* mainWindow) +//============================================================================== +class UpdateDialogWindow : public DialogWindow { - JuceUpdater updater; - DialogWindow::showModalDialog ("Juce Update...", &updater, mainWindow, - Colours::lightgrey, - true, false, false); +public: + UpdateDialogWindow (JuceUpdater* updater, Component* componentToCentreAround) + : DialogWindow ("JUCE Module Updater", + Colours::lightgrey, true, true) + { + setContentOwned (updater, true); + centreAroundComponent (componentToCentreAround, getWidth(), getHeight()); + setResizable (true, true); + } + + void closeButtonPressed() + { + setVisible (false); + } + +private: + JUCE_DECLARE_NON_COPYABLE (UpdateDialogWindow); +}; + +void JuceUpdater::show (ModuleList& moduleList, Component* mainWindow) +{ + UpdateDialogWindow w (new JuceUpdater (moduleList), mainWindow); + w.runModalLoop(); } void JuceUpdater::resized() @@ -70,9 +105,16 @@ void JuceUpdater::resized() filenameComp.setBounds (20, 40, getWidth() - 40, 22); label.setBounds (filenameComp.getX(), filenameComp.getY() - 18, filenameComp.getWidth(), 18); currentVersionLabel.setBounds (filenameComp.getX(), filenameComp.getBottom(), filenameComp.getWidth(), 25); - checkNowButton.changeWidthToFitText (20); - checkNowButton.setCentrePosition (getWidth() / 2, filenameComp.getBottom() + 40); - availableVersionsList.setBounds (filenameComp.getX(), checkNowButton.getBottom() + 20, filenameComp.getWidth(), getHeight() - (checkNowButton.getBottom() + 20)); + checkNowButton.changeWidthToFitText (22); + checkNowButton.setCentrePosition (getWidth() / 2, filenameComp.getBottom() + 20); + availableVersionsList.setBounds (filenameComp.getX(), checkNowButton.getBottom() + 20, + filenameComp.getWidth(), + getHeight() - 30 - (checkNowButton.getBottom() + 20)); + installButton.changeWidthToFitText (22); + installButton.setTopRightPosition (availableVersionsList.getRight(), getHeight() - 28); + selectAllButton.setBounds (availableVersionsList.getX(), + availableVersionsList.getBottom() + 4, + installButton.getX() - availableVersionsList.getX() - 20, 22); } void JuceUpdater::paint (Graphics& g) @@ -80,247 +122,134 @@ void JuceUpdater::paint (Graphics& g) g.fillAll (Colours::white); } -String findVersionNum (const String& file, const String& token) +void JuceUpdater::buttonClicked (Button* b) { - return file.fromFirstOccurrenceOf (token, false, false) - .upToFirstOccurrenceOf ("\n", false, false) - .trim(); + if (b == &installButton) + install(); + else if (b == &selectAllButton) + selectAll(); + else + checkNow(); } -String JuceUpdater::getCurrentVersion() +void JuceUpdater::refresh() { - const String header (filenameComp.getCurrentFile() - .getChildFile ("src/core/juce_StandardHeader.h").loadFileAsString()); - - const String v1 (findVersionNum (header, "JUCE_MAJOR_VERSION")); - const String v2 (findVersionNum (header, "JUCE_MINOR_VERSION")); - const String v3 (findVersionNum (header, "JUCE_BUILDNUMBER")); - - if ((v1 + v2 + v3).isEmpty()) - return String::empty; - - return v1 + "." + v2 + "." + v3; -} - -XmlElement* JuceUpdater::downloadVersionList() -{ - return URL ("http://www.rawmaterialsoftware.com/juce/downloads/juce_versions.php").readEntireXmlStream(); -} - -void JuceUpdater::updateVersions (const XmlElement& xml) -{ - availableVersions.clear(); - - forEachXmlChildElementWithTagName (xml, v, "VERSION") - { - VersionInfo* vi = new VersionInfo(); - vi->url = URL (v->getStringAttribute ("url")); - vi->desc = v->getStringAttribute ("desc"); - vi->version = v->getStringAttribute ("version"); - vi->date = v->getStringAttribute ("date"); - availableVersions.add (vi); - } - availableVersionsList.updateContent(); + availableVersionsList.repaint(); } -void JuceUpdater::buttonClicked (Button*) -{ - ScopedPointer xml (downloadVersionList()); - - if (xml == nullptr || xml->hasTagName ("html")) - { - AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Connection Problems...", - "Couldn't connect to the Raw Material Software website!"); - - return; - } - - if (! xml->hasTagName ("JUCEVERSIONS")) - { - AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Update Problems...", - "This version of the Introjucer may be too old to receive automatic updates!\n\n" - "Please visit www.rawmaterialsoftware.com and get the latest version manually!"); - return; - } - - const String currentVersion (getCurrentVersion()); - - OwnedArray versions; - updateVersions (*xml); -} - -//============================================================================== -class NewVersionDownloader : public ThreadWithProgressWindow +class WebsiteContacterThread : public Thread, + private AsyncUpdater { public: - NewVersionDownloader (const String& title, const URL& url_, const File& target_) - : ThreadWithProgressWindow (title, true, true), - url (url_), target (target_) + WebsiteContacterThread (JuceUpdater& owner_, const ModuleList& latestList) + : Thread ("Module updater"), + owner (owner_), + downloaded (latestList) { + startThread(); + } + + ~WebsiteContacterThread() + { + stopThread (10000); } void run() { - setStatusMessage ("Contacting website..."); - - ScopedPointer input (url.createInputStream (false)); - - if (input == nullptr) - { - error = "Couldn't connect to the website..."; - return; - } - - if (! target.deleteFile()) - { - error = "Couldn't delete the destination file..."; - return; - } - - ScopedPointer output (target.createOutputStream (32768)); - - if (output == nullptr) - { - error = "Couldn't write to the destination file..."; - return; - } - - setStatusMessage ("Downloading..."); - - int totalBytes = (int) input->getTotalLength(); - int bytesSoFar = 0; - - while (! (input->isExhausted() || threadShouldExit())) - { - HeapBlock buffer (8192); - const int num = input->read (buffer, 8192); - - if (num == 0) - break; - - output->write (buffer, num); - bytesSoFar += num; - - setProgress (totalBytes > 0 ? bytesSoFar / (double) totalBytes : -1.0); - } + if (downloaded.loadFromWebsite()) + triggerAsyncUpdate(); + else + AlertWindow::showMessageBox (AlertWindow::InfoIcon, + "Module Update", + "Couldn't connect to the website!"); } - String error; + void handleAsyncUpdate() + { + owner.backgroundUpdateComplete (downloaded); + } private: - URL url; - File target; + JuceUpdater& owner; + ModuleList downloaded; }; -//============================================================================== -class Unzipper : public ThreadWithProgressWindow +void JuceUpdater::checkNow() { -public: - Unzipper (ZipFile& zipFile_, const File& targetDir_) - : ThreadWithProgressWindow ("Unzipping...", true, true), - worked (true), zipFile (zipFile_), targetDir (targetDir_) - { - } + websiteContacterThread = nullptr; + websiteContacterThread = new WebsiteContacterThread (*this, latestList); +} - void run() - { - for (int i = 0; i < zipFile.getNumEntries(); ++i) - { - if (threadShouldExit()) - break; - - const ZipFile::ZipEntry* e = zipFile.getEntry (i); - setStatusMessage ("Unzipping " + e->filename + "..."); - setProgress (i / (double) zipFile.getNumEntries()); - - worked = zipFile.uncompressEntry (i, targetDir, true) && worked; - } - } - - bool worked; - -private: - ZipFile& zipFile; - File targetDir; -}; - -//============================================================================== -void JuceUpdater::applyVersion (VersionInfo* version) +void JuceUpdater::backgroundUpdateComplete (const ModuleList& newList) { - File destDir (filenameComp.getCurrentFile()); + latestList = newList; + websiteContacterThread = nullptr; - const bool destDirExisted = destDir.isDirectory(); + if (latestList == moduleList) + AlertWindow::showMessageBox (AlertWindow::InfoIcon, + "Module Update", + "No new modules are available"); + refresh(); +} - if (destDirExisted && destDir.getNumberOfChildFiles (File::findFilesAndDirectories, "*") > 0) - { - int r = AlertWindow::showYesNoCancelBox (AlertWindow::WarningIcon, "Folder already exists", - "The folder " + destDir.getFullPathName() + "\nalready contains some files...\n\n" - "Do you want to delete everything in the folder and replace it entirely, or just merge the new files into the existing folder?", - "Delete and replace entire folder", - "Add and overwrite existing files", - "Cancel"); +int JuceUpdater::getNumCheckedModules() const +{ + int numChecked = 0; - if (r == 0) - return; + for (int i = latestList.modules.size(); --i >= 0;) + if (versionsToDownload [latestList.modules.getUnchecked(i)->uid]) + ++numChecked; - if (r == 1) - { - if (! destDir.deleteRecursively()) - { - AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Problems...", - "Couldn't delete the existing folder!"); - return; - } - } - } + return numChecked; +} - if (! (destDir.isDirectory() || destDir.createDirectory())) - { - AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Problems...", - "Couldn't create that target folder.."); - return; - } +bool JuceUpdater::isLatestVersion (const String& moduleID) const +{ + const ModuleList::Module* m1 = moduleList.findModuleInfo (moduleID); + const ModuleList::Module* m2 = latestList.findModuleInfo (moduleID); - File zipFile (destDir.getNonexistentChildFile ("juce_download", ".tar.gz", false)); + return m1 != nullptr && m2 != nullptr && m1->version == m2->version; +} - bool worked = false; - - { - NewVersionDownloader downloader ("Downloading Version " + version->version + "...", - version->url, zipFile); - worked = downloader.runThread(); - } - - if (worked) - { - ZipFile zip (zipFile); - Unzipper unzipper (zip, destDir); - worked = unzipper.runThread() && unzipper.worked; - } - - zipFile.deleteFile(); - - if ((! destDirExisted) && (destDir.getNumberOfChildFiles (File::findFilesAndDirectories, "*") == 0 || ! worked)) - destDir.deleteRecursively(); - - filenameComponentChanged (&filenameComp); +void JuceUpdater::updateInstallButtonStatus() +{ + const int numChecked = getNumCheckedModules(); + installButton.setEnabled (numChecked > 0); + selectAllButton.setToggleState (numChecked > latestList.modules.size() / 2, false); } void JuceUpdater::filenameComponentChanged (FilenameComponent*) { - const String version (getCurrentVersion()); + moduleList.rescan (filenameComp.getCurrentFile()); + filenameComp.setCurrentFile (moduleList.getModulesFolder(), true, false); - if (version.isEmpty()) + if (! FileHelpers::isModulesFolder (moduleList.getModulesFolder())) currentVersionLabel.setText ("(Not a Juce folder)", false); else - currentVersionLabel.setText ("(Current version in this folder: " + version + ")", false); + currentVersionLabel.setText (String::empty, false); + + refresh(); +} + +void JuceUpdater::selectAll() +{ + bool enable = getNumCheckedModules() < latestList.modules.size() / 2; + + versionsToDownload.removeAllProperties (nullptr); + + if (enable) + { + for (int i = latestList.modules.size(); --i >= 0;) + if (! isLatestVersion (latestList.modules.getUnchecked(i)->uid)) + versionsToDownload.setProperty (latestList.modules.getUnchecked(i)->uid, true, nullptr); + } } //============================================================================== int JuceUpdater::getNumRows() { - return availableVersions.size(); + return latestList.modules.size(); } void JuceUpdater::paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) @@ -331,74 +260,192 @@ void JuceUpdater::paintListBoxItem (int rowNumber, Graphics& g, int width, int h Component* JuceUpdater::refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate) { - class UpdateListComponent : public Component, - public ButtonListener + class UpdateListComponent : public Component { public: UpdateListComponent (JuceUpdater& updater_) - : updater (updater_), - version (nullptr), - applyButton ("Install this version...") + : updater (updater_) { - addAndMakeVisible (&applyButton); - applyButton.addListener (this); + addChildComponent (&toggle); + toggle.setBounds ("2, 2, parent.height - 2, parent.height - 2"); + toggle.setWantsKeyboardFocus (false); setInterceptsMouseClicks (false, true); } - ~UpdateListComponent() + void setModule (const ModuleList::Module* newModule, + const ModuleList::Module* existingModule, + const Value& value) { - applyButton.removeListener (this); - } - - void setVersion (VersionInfo* v) - { - if (version != v) + if (newModule != nullptr) { - version = v; - repaint(); - resized(); + toggle.getToggleStateValue().referTo (value); + toggle.setVisible (true); + toggle.setEnabled (true); + + name = newModule->uid; + status = String::empty; + + if (existingModule == nullptr) + { + status << " (not currently installed)"; + } + else if (existingModule->version != newModule->version) + { + status << " installed: " << existingModule->version + << ", available: " << newModule->version; + } + else + { + status << " (latest version already installed)"; + toggle.setEnabled (false); + } + } + else + { + name = status = String::empty; + toggle.setVisible (false); } } void paint (Graphics& g) { - if (version != nullptr) - { - g.setColour (Colours::green.withAlpha (0.12f)); + g.setColour (Colours::green.withAlpha (0.12f)); - g.fillRect (0, 1, getWidth(), getHeight() - 2); - g.setColour (Colours::black); - g.setFont (getHeight() * 0.7f); + g.fillRect (0, 1, getWidth(), getHeight() - 2); + g.setColour (Colours::black); + g.setFont (getHeight() * 0.7f); - String s; - s << "Version " << version->version << " - " << version->desc << " - " << version->date; + g.drawText (name, toggle.getRight() + 4, 0, getWidth() / 2 - toggle.getRight() - 4, getHeight(), + Justification::centredLeft, true); - g.drawText (s, 4, 0, applyButton.getX() - 4, getHeight(), Justification::centredLeft, true); - } - } - - void resized() - { - applyButton.changeWidthToFitText (getHeight() - 4); - applyButton.setTopRightPosition (getWidth(), 2); - applyButton.setVisible (version != nullptr); - } - - void buttonClicked (Button*) - { - updater.applyVersion (version); + g.drawText (status, getWidth() / 2, 0, getWidth() / 2, getHeight(), + Justification::centredLeft, true); } private: JuceUpdater& updater; - VersionInfo* version; - TextButton applyButton; + ToggleButton toggle; + String name, status; }; UpdateListComponent* c = dynamic_cast (existingComponentToUpdate); if (c == nullptr) c = new UpdateListComponent (*this); - c->setVersion (availableVersions [rowNumber]); + ModuleList::Module* m = latestList.modules [rowNumber]; + + if (m != nullptr) + c->setModule (m, + moduleList.findModuleInfo (m->uid), + versionsToDownload.getPropertyAsValue (m->uid, nullptr)); + else + c->setModule (nullptr, nullptr, Value()); + return c; } + +//============================================================================== +class InstallThread : public ThreadWithProgressWindow +{ +public: + InstallThread (const ModuleList& targetList_, + const ModuleList& list_, const StringArray& itemsToInstall_) + : ThreadWithProgressWindow ("Installing New Modules", true, true), + result (Result::ok()), + targetList (targetList_), + list (list_), + itemsToInstall (itemsToInstall_) + { + } + + void run() + { + for (int i = 0; i < itemsToInstall.size(); ++i) + { + const ModuleList::Module* m = list.findModuleInfo (itemsToInstall[i]); + + jassert (m != nullptr); + if (m != nullptr) + { + setProgress (i / (double) itemsToInstall.size()); + + MemoryBlock downloaded; + result = download (*m, downloaded); + + if (result.failed()) + break; + + if (threadShouldExit()) + break; + + result = unzip (*m, downloaded); + + if (result.failed()) + break; + } + + if (threadShouldExit()) + break; + } + } + + Result download (const ModuleList::Module& m, MemoryBlock& dest) + { + setStatusMessage ("Downloading " + m.uid + "..."); + + if (m.url.readEntireBinaryStream (dest, false)) + return Result::ok(); + + return Result::fail ("Failed to download from: " + m.url.toString (false)); + } + + Result unzip (const ModuleList::Module& m, const MemoryBlock& data) + { + setStatusMessage ("Installing " + m.uid + "..."); + + MemoryInputStream input (data, false); + ZipFile zip (input); + + if (zip.getNumEntries() == 0) + return Result::fail ("The downloaded file wasn't a valid module file!"); + + return zip.uncompressTo (targetList.getModulesFolder(), true); + } + + Result result; + +private: + ModuleList targetList, list; + StringArray itemsToInstall; +}; + +void JuceUpdater::install() +{ + if (! moduleList.getModulesFolder().createDirectory()) + { + AlertWindow::showMessageBox (AlertWindow::WarningIcon, + "Module Update", + "Couldn't create the target folder!"); + return; + } + + StringArray itemsWanted; + + for (int i = latestList.modules.size(); --i >= 0;) + if (versionsToDownload [latestList.modules.getUnchecked(i)->uid]) + itemsWanted.add (latestList.modules.getUnchecked(i)->uid); + + { + InstallThread thread (moduleList, latestList, itemsWanted); + thread.runThread(); + } + + moduleList.rescan(); + refresh(); +} + +void JuceUpdater::valueTreePropertyChanged (ValueTree&, const Identifier&) { updateInstallButtonStatus(); } +void JuceUpdater::valueTreeChildAdded (ValueTree&, ValueTree&) {} +void JuceUpdater::valueTreeChildRemoved (ValueTree&, ValueTree&) {} +void JuceUpdater::valueTreeChildOrderChanged (ValueTree&) {} +void JuceUpdater::valueTreeParentChanged (ValueTree&) {} diff --git a/extras/Introjucer/Source/Application/jucer_JuceUpdater.h b/extras/Introjucer/Source/Application/jucer_JuceUpdater.h index 292ea0e956..989ed3c740 100644 --- a/extras/Introjucer/Source/Application/jucer_JuceUpdater.h +++ b/extras/Introjucer/Source/Application/jucer_JuceUpdater.h @@ -26,18 +26,21 @@ #ifndef __JUCER_JUCEUPDATER_JUCEHEADER__ #define __JUCER_JUCEUPDATER_JUCEHEADER__ +#include "../Project/jucer_Module.h" + //============================================================================== class JuceUpdater : public Component, - public ButtonListener, - public FilenameComponentListener, - public ListBoxModel + private ButtonListener, + private FilenameComponentListener, + private ListBoxModel, + private ValueTree::Listener { public: - JuceUpdater(); + JuceUpdater (ModuleList& moduleList); ~JuceUpdater(); - static void show (Component* mainWindow); + static void show (ModuleList& moduleList, Component* mainWindow); //============================================================================== void resized(); @@ -49,29 +52,36 @@ public: void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected); Component* refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate); + void backgroundUpdateComplete (const ModuleList& newList); + private: + ModuleList& moduleList; + ModuleList latestList; + Label label, currentVersionLabel; FilenameComponent filenameComp; TextButton checkNowButton; ListBox availableVersionsList; + ValueTree versionsToDownload; + TextButton installButton; + ToggleButton selectAllButton; + ScopedPointer websiteContacterThread; - XmlElement* downloadVersionList(); - String getCurrentVersion(); - bool isAlreadyUpToDate(); + void checkNow(); + void install(); + void updateInstallButtonStatus(); + void refresh(); + void selectAll(); + int getNumCheckedModules() const; + bool isLatestVersion (const String& moduleID) const; - struct VersionInfo - { - URL url; - String desc; - String version; - String date; - }; + void valueTreePropertyChanged (ValueTree&, const Identifier&); + void valueTreeChildAdded (ValueTree&, ValueTree&); + void valueTreeChildRemoved (ValueTree&, ValueTree&); + void valueTreeChildOrderChanged (ValueTree&); + void valueTreeParentChanged (ValueTree&); - OwnedArray availableVersions; - - void updateVersions (const XmlElement& xml); - void applyVersion (VersionInfo* version); + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceUpdater); }; - #endif // __JUCER_JUCEUPDATER_JUCEHEADER__ diff --git a/extras/Introjucer/Source/Application/jucer_MainWindow.cpp b/extras/Introjucer/Source/Application/jucer_MainWindow.cpp index 470cb5f5ff..66ab6faf89 100644 --- a/extras/Introjucer/Source/Application/jucer_MainWindow.cpp +++ b/extras/Introjucer/Source/Application/jucer_MainWindow.cpp @@ -30,7 +30,7 @@ #include "../Code Editor/jucer_SourceCodeEditor.h" #include "../Project/jucer_NewProjectWizard.h" -ApplicationCommandManager* commandManager = nullptr; +ScopedPointer commandManager; //============================================================================== diff --git a/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp b/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp index 33a17ca540..f056bd97be 100644 --- a/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp +++ b/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp @@ -66,18 +66,18 @@ ProjectExporter* ProjectExporter::createNewExporter (Project& project, const int switch (index) { - case 0: exp = new XCodeProjectExporter (project, ValueTree (XCodeProjectExporter::getValueTreeTypeName (false)), false); break; - case 1: exp = new XCodeProjectExporter (project, ValueTree (XCodeProjectExporter::getValueTreeTypeName (true)), true); break; - case 2: exp = new MSVCProjectExporterVC6 (project, ValueTree (MSVCProjectExporterVC6::getValueTreeTypeName())); break; + case 0: exp = new XCodeProjectExporter (project, ValueTree (XCodeProjectExporter ::getValueTreeTypeName (false)), false); break; + case 1: exp = new XCodeProjectExporter (project, ValueTree (XCodeProjectExporter ::getValueTreeTypeName (true)), true); break; + case 2: exp = new MSVCProjectExporterVC6 (project, ValueTree (MSVCProjectExporterVC6 ::getValueTreeTypeName())); break; case 3: exp = new MSVCProjectExporterVC2005 (project, ValueTree (MSVCProjectExporterVC2005::getValueTreeTypeName())); break; case 4: exp = new MSVCProjectExporterVC2008 (project, ValueTree (MSVCProjectExporterVC2008::getValueTreeTypeName())); break; case 5: exp = new MSVCProjectExporterVC2010 (project, ValueTree (MSVCProjectExporterVC2010::getValueTreeTypeName())); break; - case 6: exp = new MakefileProjectExporter (project, ValueTree (MakefileProjectExporter::getValueTreeTypeName())); break; - case 7: exp = new AndroidProjectExporter (project, ValueTree (AndroidProjectExporter::getValueTreeTypeName())); break; + case 6: exp = new MakefileProjectExporter (project, ValueTree (MakefileProjectExporter ::getValueTreeTypeName())); break; + case 7: exp = new AndroidProjectExporter (project, ValueTree (AndroidProjectExporter ::getValueTreeTypeName())); break; default: jassertfalse; return 0; } - File juceFolder (StoredSettings::getInstance()->getLastKnownJuceFolder()); + File juceFolder (ModuleList::getLocalModulesFolder (&project)); File target (exp->getTargetFolder()); if (FileHelpers::shouldPathsBeRelative (juceFolder.getFullPathName(), project.getFile().getFullPathName())) @@ -95,13 +95,13 @@ ProjectExporter* ProjectExporter::createNewExporter (Project& project, const Str ProjectExporter* ProjectExporter::createExporter (Project& project, const ValueTree& settings) { - ProjectExporter* exp = MSVCProjectExporterVC6::createForSettings (project, settings); + ProjectExporter* exp = MSVCProjectExporterVC6 ::createForSettings (project, settings); if (exp == nullptr) exp = MSVCProjectExporterVC2005::createForSettings (project, settings); if (exp == nullptr) exp = MSVCProjectExporterVC2008::createForSettings (project, settings); if (exp == nullptr) exp = MSVCProjectExporterVC2010::createForSettings (project, settings); - if (exp == nullptr) exp = XCodeProjectExporter::createForSettings (project, settings); - if (exp == nullptr) exp = MakefileProjectExporter::createForSettings (project, settings); - if (exp == nullptr) exp = AndroidProjectExporter::createForSettings (project, settings); + if (exp == nullptr) exp = XCodeProjectExporter ::createForSettings (project, settings); + if (exp == nullptr) exp = MakefileProjectExporter ::createForSettings (project, settings); + if (exp == nullptr) exp = AndroidProjectExporter ::createForSettings (project, settings); jassert (exp != nullptr); return exp; @@ -115,7 +115,6 @@ ProjectExporter* ProjectExporter::createPlatformDefaultExporter (Project& projec for (int i = 0; i < project.getNumExporters(); ++i) { ScopedPointer exp (project.createExporter (i)); - const int pref = exp->getLaunchPreferenceOrderForCurrentOS(); if (pref > bestPref) @@ -210,7 +209,7 @@ void ProjectExporter::createPropertyEditors (Array & props) props.getLast()->setTooltip ("The location of the Juce library folder that the " + name + " project will use to when compiling. This can be an absolute path, or relative to the jucer project folder, but it must be valid on the filesystem of the machine you use to actually do the compiling."); OwnedArray modules; - ModuleList moduleList; + ModuleList moduleList (ModuleList::getDefaultModulesFolder (&project)); project.createRequiredModules (moduleList, modules); for (int i = 0; i < modules.size(); ++i) modules.getUnchecked(i)->createPropertyEditors (*this, props); diff --git a/extras/Introjucer/Source/Project Saving/jucer_ProjectSaver.h b/extras/Introjucer/Source/Project Saving/jucer_ProjectSaver.h index 30fc926474..8953663f43 100644 --- a/extras/Introjucer/Source/Project Saving/jucer_ProjectSaver.h +++ b/extras/Introjucer/Source/Project Saving/jucer_ProjectSaver.h @@ -61,7 +61,7 @@ public: OwnedArray modules; { - ModuleList moduleList; + ModuleList moduleList (ModuleList::getDefaultModulesFolder (&project)); project.createRequiredModules (moduleList, modules); } diff --git a/extras/Introjucer/Source/Project/jucer_Module.cpp b/extras/Introjucer/Source/Project/jucer_Module.cpp index d0f65b0c21..0b6ba8c2de 100644 --- a/extras/Introjucer/Source/Project/jucer_Module.cpp +++ b/extras/Introjucer/Source/Project/jucer_Module.cpp @@ -31,9 +31,94 @@ //============================================================================== -ModuleList::ModuleList() +ModuleList::ModuleList (const File& modulesFolder_) { - rescan(); + rescan (modulesFolder_); +} + +ModuleList::ModuleList (const ModuleList& other) + : moduleFolder (other.moduleFolder) +{ + modules.addCopiesOf (other.modules); +} + +ModuleList& ModuleList::operator= (const ModuleList& other) +{ + moduleFolder = other.moduleFolder; + modules.clear(); + modules.addCopiesOf (other.modules); + + return *this; +} + +bool ModuleList::operator== (const ModuleList& other) const +{ + if (modules.size() != other.modules.size()) + return false; + + for (int i = modules.size(); --i >= 0;) + { + const Module* m1 = modules.getUnchecked(i); + const Module* m2 = other.findModuleInfo (m1->uid); + + if (m2 == nullptr || *m1 != *m2) + return false; + } + + return true; +} + +File ModuleList::getModulesFolderForJuceOrModulesFolder (const File& f) +{ + if (f.getFileName() != "modules" && f.isDirectory() && f.getChildFile ("modules").isDirectory()) + return f.getChildFile ("modules"); + + return f; +} + +File ModuleList::getDefaultModulesFolder (Project* project) +{ + if (project != nullptr) + { + ScopedPointer exp (ProjectExporter::createPlatformDefaultExporter (*project)); + + if (exp != nullptr) + { + File f (project->resolveFilename (exp->getJuceFolder().toString())); + f = getModulesFolderForJuceOrModulesFolder (f); + + if (FileHelpers::isModulesFolder (f)) + return f; + } + } + + return File::getSpecialLocation (File::userHomeDirectory) + .getChildFile ("juce") + .getChildFile ("modules"); +} + +File ModuleList::getLocalModulesFolder (Project* project) +{ + File defaultJuceFolder (getDefaultModulesFolder (project)); + + File f (StoredSettings::getInstance()->getProps().getValue ("lastJuceFolder", defaultJuceFolder.getFullPathName())); + f = getModulesFolderForJuceOrModulesFolder (f); + + if ((! FileHelpers::isModulesFolder (f)) && FileHelpers::isModulesFolder (defaultJuceFolder)) + f = defaultJuceFolder; + + return f; +} + +File ModuleList::getModuleFolder (const String& uid) const +{ + return getModulesFolder().getChildFile (uid); +} + +void ModuleList::setLocalModulesFolder (const File& file) +{ + //jassert (FileHelpers::isJuceFolder (file)); + StoredSettings::getInstance()->getProps().setValue ("lastJuceFolder", file.getFullPathName()); } struct ModuleSorter @@ -51,31 +136,39 @@ void ModuleList::sort() } void ModuleList::rescan() +{ + rescan (moduleFolder); +} + +void ModuleList::rescan (const File& newModulesFolder) { modules.clear(); - moduleFolder = StoredSettings::getInstance()->getLastKnownJuceFolder().getChildFile ("modules"); + moduleFolder = getModulesFolderForJuceOrModulesFolder (newModulesFolder); - DirectoryIterator iter (moduleFolder, false, "*", File::findDirectories); - - while (iter.next()) + if (moduleFolder.isDirectory()) { - const File moduleDef (iter.getFile().getChildFile (LibraryModule::getInfoFileName())); + DirectoryIterator iter (moduleFolder, false, "*", File::findDirectories); - if (moduleDef.exists()) + while (iter.next()) { - LibraryModule m (moduleDef); - jassert (m.isValid()); + const File moduleDef (iter.getFile().getChildFile (LibraryModule::getInfoFileName())); - if (m.isValid()) + if (moduleDef.exists()) { - Module* info = new Module(); - modules.add (info); + LibraryModule m (moduleDef); + jassert (m.isValid()); - info->uid = m.getID(); - info->version = m.getVersion(); - info->name = m.moduleInfo ["name"]; - info->description = m.moduleInfo ["description"]; - info->file = moduleDef; + if (m.isValid()) + { + Module* info = new Module(); + modules.add (info); + + info->uid = m.getID(); + info->version = m.getVersion(); + info->name = m.moduleInfo ["name"]; + info->description = m.moduleInfo ["description"]; + info->file = moduleDef; + } } } } @@ -83,7 +176,7 @@ void ModuleList::rescan() sort(); } -void ModuleList::loadFromWebsite() +bool ModuleList::loadFromWebsite() { modules.clear(); @@ -122,6 +215,7 @@ void ModuleList::loadFromWebsite() } sort(); + return infoList.isArray(); } LibraryModule* ModuleList::Module::create() const @@ -129,6 +223,21 @@ LibraryModule* ModuleList::Module::create() const return new LibraryModule (file); } +bool ModuleList::Module::operator== (const Module& other) const +{ + return uid == other.uid + && version == other.version + && name == other.name + && description == other.description + && file == other.file + && url == other.url; +} + +bool ModuleList::Module::operator!= (const Module& other) const +{ + return ! operator== (other); +} + LibraryModule* ModuleList::loadModule (const String& uid) const { const Module* const m = findModuleInfo (uid); diff --git a/extras/Introjucer/Source/Project/jucer_Module.h b/extras/Introjucer/Source/Project/jucer_Module.h index 713a570452..fed4967ae3 100644 --- a/extras/Introjucer/Source/Project/jucer_Module.h +++ b/extras/Introjucer/Source/Project/jucer_Module.h @@ -86,11 +86,17 @@ private: class ModuleList { public: - ModuleList(); + ModuleList (const File& modulesFolder); + ModuleList (const ModuleList&); + ModuleList& operator= (const ModuleList&); //============================================================================== + void rescan (const File& newModulesFolder); void rescan(); - void loadFromWebsite(); + File getModulesFolder() const { return moduleFolder; } + File getModuleFolder (const String& uid) const; + + bool loadFromWebsite(); LibraryModule* loadModule (const String& uid) const; @@ -105,10 +111,24 @@ public: String uid, version, name, description; File file; URL url; + + bool operator== (const Module&) const; + bool operator!= (const Module&) const; }; const Module* findModuleInfo (const String& uid) const; + bool operator== (const ModuleList&) const; + + //============================================================================== + static File getDefaultModulesFolder (Project* project); + + static File getLocalModulesFolder (Project* project); + static void setLocalModulesFolder (const File& newFile); + + static File getModulesFolderForJuceOrModulesFolder (const File& f); + + //============================================================================== OwnedArray modules; private: diff --git a/extras/Introjucer/Source/Project/jucer_NewProjectWizard.cpp b/extras/Introjucer/Source/Project/jucer_NewProjectWizard.cpp index 8d26883322..46c3cae344 100644 --- a/extras/Introjucer/Source/Project/jucer_NewProjectWizard.cpp +++ b/extras/Introjucer/Source/Project/jucer_NewProjectWizard.cpp @@ -25,6 +25,7 @@ #include "jucer_NewProjectWizard.h" #include "jucer_ProjectType.h" +#include "jucer_Module.h" //============================================================================== class GUIAppWizard : public NewProjectWizard @@ -451,7 +452,7 @@ Project* NewProjectWizard::runNewProjectWizard (Component* ownerWindow) aw.addComboBox ("type", getWizards(), "Project Type"); - FilenameComponent juceFolderSelector ("Juce Library Location", StoredSettings::getInstance()->getLastKnownJuceFolder(), + FilenameComponent juceFolderSelector ("Juce Library Location", ModuleList::getLocalModulesFolder (nullptr), true, true, false, "*", String::empty, "(Please select the folder containing Juce!)"); juceFolderSelector.setSize (350, 22); diff --git a/extras/Introjucer/Source/Project/jucer_Project.cpp b/extras/Introjucer/Source/Project/jucer_Project.cpp index a5f0710383..f75e42abc8 100644 --- a/extras/Introjucer/Source/Project/jucer_Project.cpp +++ b/extras/Introjucer/Source/Project/jucer_Project.cpp @@ -177,18 +177,6 @@ const String Project::saveDocument (const File& file) updateProjectSettings(); sanitiseConfigFlags(); - { - ScopedPointer exp (ProjectExporter::createPlatformDefaultExporter (*this)); - - if (exp != nullptr) - { - File f (resolveFilename (exp->getJuceFolder().toString())); - - if (FileHelpers::isJuceFolder (f)) - StoredSettings::getInstance()->setLastKnownJuceFolder (f.getFullPathName()); - } - } - StoredSettings::getInstance()->recentFiles.addFile (file); ProjectSaver saver (*this, file); diff --git a/extras/Introjucer/Source/Project/jucer_ProjectInformationComponent.cpp b/extras/Introjucer/Source/Project/jucer_ProjectInformationComponent.cpp index ba521e844b..33b989acf5 100644 --- a/extras/Introjucer/Source/Project/jucer_ProjectInformationComponent.cpp +++ b/extras/Introjucer/Source/Project/jucer_ProjectInformationComponent.cpp @@ -19,6 +19,7 @@ //[CppHeaders] You can add your own extra header files here... #include "../Project Saving/jucer_ProjectExporter.h" #include "jucer_Module.h" +#include "../Application/jucer_JuceUpdater.h" //[/CppHeaders] #include "jucer_ProjectInformationComponent.h" @@ -126,7 +127,7 @@ public: ModuleSettingsPanel (Project& project_, ModuleList& moduleList_, const String& moduleID_) : PanelBase (project_), moduleList (moduleList_), moduleID (moduleID_) { - setBounds ("parent.width / 2 + 1, 3, parent.width - 3, parent.height - 3"); + setBounds ("parent.width / 2 + 1, 31, parent.width - 3, parent.height - 3"); } void rebuildProperties (Array & props) @@ -207,7 +208,7 @@ private: if (module != nullptr) { String text; - text << module->name << newLine << newLine + text << module->name << newLine << "Version: " << module->version << newLine << newLine << module->description; GlyphArrangement ga; @@ -279,16 +280,34 @@ private: //============================================================================== class ModulesPanel : public Component, - public ListBoxModel + public ListBoxModel, + public FilenameComponentListener, + public ButtonListener { public: ModulesPanel (Project& project_) - : project (project_) + : project (project_), + moduleList (ModuleList::getLocalModulesFolder (&project)), + modulesLocation ("modules", moduleList.getModulesFolder(), + true, true, false, "*", String::empty, + "Select a folder containing your JUCE modules..."), + modulesLabel (String::empty, "Module source folder:"), + updateModulesButton ("Check for module updates...") { + addAndMakeVisible (&modulesLocation); + modulesLocation.setBounds ("150, 3, parent.width - 180, 28"); + modulesLocation.addListener (this); + + modulesLabel.attachToComponent (&modulesLocation, true); + + addAndMakeVisible (&updateModulesButton); + updateModulesButton.setBounds ("parent.width - 175, 3, parent.width - 4, 28"); + updateModulesButton.addListener (this); + modulesList.setModel (this); modulesList.setColour (ListBox::backgroundColourId, Colours::white.withAlpha (0.4f)); addAndMakeVisible (&modulesList); - modulesList.setBounds ("4, 3, parent.width / 2 - 4, parent.height - 3"); + modulesList.setBounds ("4, 31, parent.width / 2 - 4, parent.height - 3"); } int getNumRows() @@ -330,36 +349,29 @@ public: if (m != nullptr) { if (project.isModuleEnabled (m->uid)) - { project.removeModule (m->uid); - } else - { - const StringArray extraDepsNeeded (getExtraDependenciesNeeded (project, moduleList, *m)); - -/* if (extraDepsNeeded.size() > 0) - { - if (AlertWindow::showOkCancelBox (AlertWindow::NoIcon, - "Module Dependencies", - "The '" + m->uid + "' module requires the following dependencies:\n" - + extraDepsNeeded.joinIntoString (", ") + "\n\nDo you want to add all these to your project?")) - { - project.addModule (m->uid); - - for (int i = extraDepsNeeded.size(); --i >= 0;) - project.addModule (extraDepsNeeded[i]); - } - } - else*/ - { - project.addModule (m->uid); - } - } + project.addModule (m->uid); } refresh(); } + void filenameComponentChanged (FilenameComponent*) + { + moduleList.rescan (modulesLocation.getCurrentFile()); + modulesLocation.setCurrentFile (moduleList.getModulesFolder(), false, false); + ModuleList::setLocalModulesFolder (moduleList.getModulesFolder()); + modulesList.updateContent(); + } + + void buttonClicked (Button*) + { + JuceUpdater::show (moduleList, getTopLevelComponent()); + + filenameComponentChanged (nullptr); + } + void listBoxItemClicked (int row, const MouseEvent& e) { if (e.x < modulesList.getRowHeight()) @@ -397,6 +409,9 @@ public: private: Project& project; ModuleList moduleList; + FilenameComponent modulesLocation; + Label modulesLabel; + TextButton updateModulesButton; ListBox modulesList; ScopedPointer settings; }; @@ -440,16 +455,16 @@ ProjectInformationComponent::ProjectInformationComponent (Project& project_) //[UserPreSize] rebuildConfigTabs(); -#if JUCE_MAC || JUCE_WINDOWS + #if JUCE_MAC || JUCE_WINDOWS openProjectButton.setCommandToTrigger (commandManager, CommandIDs::openInIDE, true); openProjectButton.setButtonText (commandManager->getNameOfCommand (CommandIDs::openInIDE)); saveAndOpenButton.setCommandToTrigger (commandManager, CommandIDs::saveAndOpenInIDE, true); saveAndOpenButton.setButtonText (commandManager->getNameOfCommand (CommandIDs::saveAndOpenInIDE)); -#else + #else openProjectButton.setVisible (false); saveAndOpenButton.setVisible (false); -#endif + #endif //[/UserPreSize] setSize (836, 427); diff --git a/extras/Introjucer/Source/Utility/jucer_FileHelpers.cpp b/extras/Introjucer/Source/Utility/jucer_FileHelpers.cpp index 0bb5edce30..c27d006bf2 100644 --- a/extras/Introjucer/Source/Utility/jucer_FileHelpers.cpp +++ b/extras/Introjucer/Source/Utility/jucer_FileHelpers.cpp @@ -150,10 +150,16 @@ namespace FileHelpers bool isJuceFolder (const File& folder) { return folder.getFileName().containsIgnoreCase ("juce") - && folder.getChildFile ("modules").isDirectory(); + && isModulesFolder (folder.getChildFile ("modules")); } - static File lookInFolderForJuceFolder (const File& folder) + bool isModulesFolder (const File& folder) + { + return folder.getFileName().equalsIgnoreCase ("modules") + && folder.isDirectory(); + } + + File lookInFolderForJuceFolder (const File& folder) { for (DirectoryIterator di (folder, false, "*juce*", File::findDirectories); di.next();) { @@ -182,17 +188,4 @@ namespace FileHelpers return File::nonexistent; } - - File findDefaultJuceFolder() - { - File f = findParentJuceFolder (File::getSpecialLocation (File::currentApplicationFile)); - - if (! f.exists()) - f = lookInFolderForJuceFolder (File::getSpecialLocation (File::userHomeDirectory)); - - if (! f.exists()) - f = lookInFolderForJuceFolder (File::getSpecialLocation (File::userDocumentsDirectory)); - - return f; - } } diff --git a/extras/Introjucer/Source/Utility/jucer_FileHelpers.h b/extras/Introjucer/Source/Utility/jucer_FileHelpers.h index ec03b10db5..0d969760f5 100644 --- a/extras/Introjucer/Source/Utility/jucer_FileHelpers.h +++ b/extras/Introjucer/Source/Utility/jucer_FileHelpers.h @@ -46,8 +46,9 @@ namespace FileHelpers //============================================================================== bool isJuceFolder (const File& folder); + bool isModulesFolder (const File& folder); File findParentJuceFolder (const File& file); - File findDefaultJuceFolder(); + File lookInFolderForJuceFolder (const File& folder); } //============================================================================== diff --git a/extras/Introjucer/Source/Utility/jucer_StoredSettings.cpp b/extras/Introjucer/Source/Utility/jucer_StoredSettings.cpp index 46449fffc3..626f04b72c 100644 --- a/extras/Introjucer/Source/Utility/jucer_StoredSettings.cpp +++ b/extras/Introjucer/Source/Utility/jucer_StoredSettings.cpp @@ -143,23 +143,6 @@ void StoredSettings::setLastProjects (const Array& files) props->setValue ("lastProjects", s.joinIntoString ("|")); } -File StoredSettings::getLastKnownJuceFolder() const -{ - File defaultJuceFolder (FileHelpers::findDefaultJuceFolder()); - File f (props->getValue ("lastJuceFolder", defaultJuceFolder.getFullPathName())); - - if ((! FileHelpers::isJuceFolder (f)) && FileHelpers::isJuceFolder (defaultJuceFolder)) - f = defaultJuceFolder; - - return f; -} - -void StoredSettings::setLastKnownJuceFolder (const File& file) -{ - jassert (FileHelpers::isJuceFolder (file)); - props->setValue ("lastJuceFolder", file.getFullPathName()); -} - const StringArray& StoredSettings::getFontNames() { if (fontNames.size() == 0) diff --git a/extras/Introjucer/Source/Utility/jucer_StoredSettings.h b/extras/Introjucer/Source/Utility/jucer_StoredSettings.h index 6b99043817..bffcc22210 100644 --- a/extras/Introjucer/Source/Utility/jucer_StoredSettings.h +++ b/extras/Introjucer/Source/Utility/jucer_StoredSettings.h @@ -50,9 +50,6 @@ public: Array getLastProjects() const; void setLastProjects (const Array& files); - File getLastKnownJuceFolder() const; - void setLastKnownJuceFolder (const File& file); - const StringArray& getFontNames(); //============================================================================== diff --git a/modules/juce_core/system/juce_StandardHeader.h b/modules/juce_core/system/juce_StandardHeader.h index 7f6530a074..fa8f627973 100644 --- a/modules/juce_core/system/juce_StandardHeader.h +++ b/modules/juce_core/system/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 2 #define JUCE_MINOR_VERSION 0 -#define JUCE_BUILDNUMBER 4 +#define JUCE_BUILDNUMBER 5 /** Current Juce version number.