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,325 +122,330 @@ 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()); + availableVersionsList.updateContent(); + availableVersionsList.repaint(); +} - const String v1 (findVersionNum (header, "JUCE_MAJOR_VERSION")); - const String v2 (findVersionNum (header, "JUCE_MINOR_VERSION")); - const String v3 (findVersionNum (header, "JUCE_BUILDNUMBER")); +class WebsiteContacterThread : public Thread, + private AsyncUpdater +{ +public: + WebsiteContacterThread (JuceUpdater& owner_, const ModuleList& latestList) + : Thread ("Module updater"), + owner (owner_), + downloaded (latestList) + { + startThread(); + } - if ((v1 + v2 + v3).isEmpty()) - return String::empty; + ~WebsiteContacterThread() + { + stopThread (10000); + } + + void run() + { + if (downloaded.loadFromWebsite()) + triggerAsyncUpdate(); + else + AlertWindow::showMessageBox (AlertWindow::InfoIcon, + "Module Update", + "Couldn't connect to the website!"); + } + + void handleAsyncUpdate() + { + owner.backgroundUpdateComplete (downloaded); + } + +private: + JuceUpdater& owner; + ModuleList downloaded; +}; - return v1 + "." + v2 + "." + v3; +void JuceUpdater::checkNow() +{ + websiteContacterThread = nullptr; + websiteContacterThread = new WebsiteContacterThread (*this, latestList); } -XmlElement* JuceUpdater::downloadVersionList() +void JuceUpdater::backgroundUpdateComplete (const ModuleList& newList) { - return URL ("http://www.rawmaterialsoftware.com/juce/downloads/juce_versions.php").readEntireXmlStream(); + latestList = newList; + websiteContacterThread = nullptr; + + if (latestList == moduleList) + AlertWindow::showMessageBox (AlertWindow::InfoIcon, + "Module Update", + "No new modules are available"); + refresh(); } -void JuceUpdater::updateVersions (const XmlElement& xml) +int JuceUpdater::getNumCheckedModules() const { - availableVersions.clear(); + int numChecked = 0; - 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); - } + for (int i = latestList.modules.size(); --i >= 0;) + if (versionsToDownload [latestList.modules.getUnchecked(i)->uid]) + ++numChecked; - availableVersionsList.updateContent(); + return numChecked; } -void JuceUpdater::buttonClicked (Button*) +bool JuceUpdater::isLatestVersion (const String& moduleID) const { - ScopedPointer xml (downloadVersionList()); + const ModuleList::Module* m1 = moduleList.findModuleInfo (moduleID); + const ModuleList::Module* m2 = latestList.findModuleInfo (moduleID); - if (xml == nullptr || xml->hasTagName ("html")) - { - AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Connection Problems...", - "Couldn't connect to the Raw Material Software website!"); + return m1 != nullptr && m2 != nullptr && m1->version == m2->version; +} - return; - } +void JuceUpdater::updateInstallButtonStatus() +{ + const int numChecked = getNumCheckedModules(); + installButton.setEnabled (numChecked > 0); + selectAllButton.setToggleState (numChecked > latestList.modules.size() / 2, false); +} - 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; - } +void JuceUpdater::filenameComponentChanged (FilenameComponent*) +{ + moduleList.rescan (filenameComp.getCurrentFile()); + filenameComp.setCurrentFile (moduleList.getModulesFolder(), true, false); - const String currentVersion (getCurrentVersion()); + if (! FileHelpers::isModulesFolder (moduleList.getModulesFolder())) + currentVersionLabel.setText ("(Not a Juce folder)", false); + else + currentVersionLabel.setText (String::empty, false); - OwnedArray versions; - updateVersions (*xml); + refresh(); } -//============================================================================== -class NewVersionDownloader : public ThreadWithProgressWindow +void JuceUpdater::selectAll() { -public: - NewVersionDownloader (const String& title, const URL& url_, const File& target_) - : ThreadWithProgressWindow (title, true, true), - url (url_), target (target_) + 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); } +} - void run() - { - setStatusMessage ("Contacting website..."); +//============================================================================== +int JuceUpdater::getNumRows() +{ + return latestList.modules.size(); +} - ScopedPointer input (url.createInputStream (false)); +void JuceUpdater::paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) +{ + if (rowIsSelected) + g.fillAll (findColour (TextEditor::highlightColourId)); +} - if (input == nullptr) +Component* JuceUpdater::refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate) +{ + class UpdateListComponent : public Component + { + public: + UpdateListComponent (JuceUpdater& updater_) + : updater (updater_) { - error = "Couldn't connect to the website..."; - return; + addChildComponent (&toggle); + toggle.setBounds ("2, 2, parent.height - 2, parent.height - 2"); + toggle.setWantsKeyboardFocus (false); + setInterceptsMouseClicks (false, true); } - if (! target.deleteFile()) + void setModule (const ModuleList::Module* newModule, + const ModuleList::Module* existingModule, + const Value& value) { - error = "Couldn't delete the destination file..."; - return; + if (newModule != nullptr) + { + 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); + } } - ScopedPointer output (target.createOutputStream (32768)); - - if (output == nullptr) + void paint (Graphics& g) { - error = "Couldn't write to the destination file..."; - return; - } + g.setColour (Colours::green.withAlpha (0.12f)); - setStatusMessage ("Downloading..."); + g.fillRect (0, 1, getWidth(), getHeight() - 2); + g.setColour (Colours::black); + g.setFont (getHeight() * 0.7f); - int totalBytes = (int) input->getTotalLength(); - int bytesSoFar = 0; + g.drawText (name, toggle.getRight() + 4, 0, getWidth() / 2 - toggle.getRight() - 4, getHeight(), + Justification::centredLeft, true); - while (! (input->isExhausted() || threadShouldExit())) - { - HeapBlock buffer (8192); - const int num = input->read (buffer, 8192); + g.drawText (status, getWidth() / 2, 0, getWidth() / 2, getHeight(), + Justification::centredLeft, true); + } - if (num == 0) - break; + private: + JuceUpdater& updater; + ToggleButton toggle; + String name, status; + }; - output->write (buffer, num); - bytesSoFar += num; + UpdateListComponent* c = dynamic_cast (existingComponentToUpdate); + if (c == nullptr) + c = new UpdateListComponent (*this); - setProgress (totalBytes > 0 ? bytesSoFar / (double) totalBytes : -1.0); - } - } + ModuleList::Module* m = latestList.modules [rowNumber]; - String error; + if (m != nullptr) + c->setModule (m, + moduleList.findModuleInfo (m->uid), + versionsToDownload.getPropertyAsValue (m->uid, nullptr)); + else + c->setModule (nullptr, nullptr, Value()); -private: - URL url; - File target; -}; + return c; +} //============================================================================== -class Unzipper : public ThreadWithProgressWindow +class InstallThread : public ThreadWithProgressWindow { public: - Unzipper (ZipFile& zipFile_, const File& targetDir_) - : ThreadWithProgressWindow ("Unzipping...", true, true), - worked (true), zipFile (zipFile_), targetDir (targetDir_) + 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 < zipFile.getNumEntries(); ++i) + for (int i = 0; i < itemsToInstall.size(); ++i) { - if (threadShouldExit()) - break; + const ModuleList::Module* m = list.findModuleInfo (itemsToInstall[i]); - const ZipFile::ZipEntry* e = zipFile.getEntry (i); - setStatusMessage ("Unzipping " + e->filename + "..."); - setProgress (i / (double) zipFile.getNumEntries()); - - worked = zipFile.uncompressEntry (i, targetDir, true) && worked; - } - } + jassert (m != nullptr); + if (m != nullptr) + { + setProgress (i / (double) itemsToInstall.size()); - bool worked; + MemoryBlock downloaded; + result = download (*m, downloaded); -private: - ZipFile& zipFile; - File targetDir; -}; + if (result.failed()) + break; -//============================================================================== -void JuceUpdater::applyVersion (VersionInfo* version) -{ - File destDir (filenameComp.getCurrentFile()); + if (threadShouldExit()) + break; - const bool destDirExisted = destDir.isDirectory(); + result = unzip (*m, downloaded); - 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"); - - if (r == 0) - return; - - if (r == 1) - { - if (! destDir.deleteRecursively()) - { - AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Problems...", - "Couldn't delete the existing folder!"); - return; + if (result.failed()) + break; } + + if (threadShouldExit()) + break; } } - if (! (destDir.isDirectory() || destDir.createDirectory())) + Result download (const ModuleList::Module& m, MemoryBlock& dest) { - AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Problems...", - "Couldn't create that target folder.."); - return; - } - - File zipFile (destDir.getNonexistentChildFile ("juce_download", ".tar.gz", false)); + setStatusMessage ("Downloading " + m.uid + "..."); - bool worked = false; + if (m.url.readEntireBinaryStream (dest, false)) + return Result::ok(); - { - NewVersionDownloader downloader ("Downloading Version " + version->version + "...", - version->url, zipFile); - worked = downloader.runThread(); + return Result::fail ("Failed to download from: " + m.url.toString (false)); } - if (worked) + Result unzip (const ModuleList::Module& m, const MemoryBlock& data) { - ZipFile zip (zipFile); - Unzipper unzipper (zip, destDir); - worked = unzipper.runThread() && unzipper.worked; - } - - zipFile.deleteFile(); + setStatusMessage ("Installing " + m.uid + "..."); - if ((! destDirExisted) && (destDir.getNumberOfChildFiles (File::findFilesAndDirectories, "*") == 0 || ! worked)) - destDir.deleteRecursively(); + MemoryInputStream input (data, false); + ZipFile zip (input); - filenameComponentChanged (&filenameComp); -} - -void JuceUpdater::filenameComponentChanged (FilenameComponent*) -{ - const String version (getCurrentVersion()); + if (zip.getNumEntries() == 0) + return Result::fail ("The downloaded file wasn't a valid module file!"); - if (version.isEmpty()) - currentVersionLabel.setText ("(Not a Juce folder)", false); - else - currentVersionLabel.setText ("(Current version in this folder: " + version + ")", false); -} + return zip.uncompressTo (targetList.getModulesFolder(), true); + } -//============================================================================== -int JuceUpdater::getNumRows() -{ - return availableVersions.size(); -} + Result result; -void JuceUpdater::paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) -{ - if (rowIsSelected) - g.fillAll (findColour (TextEditor::highlightColourId)); -} +private: + ModuleList targetList, list; + StringArray itemsToInstall; +}; -Component* JuceUpdater::refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate) +void JuceUpdater::install() { - class UpdateListComponent : public Component, - public ButtonListener + if (! moduleList.getModulesFolder().createDirectory()) { - public: - UpdateListComponent (JuceUpdater& updater_) - : updater (updater_), - version (nullptr), - applyButton ("Install this version...") - { - addAndMakeVisible (&applyButton); - applyButton.addListener (this); - setInterceptsMouseClicks (false, true); - } - - ~UpdateListComponent() - { - applyButton.removeListener (this); - } - - void setVersion (VersionInfo* v) - { - if (version != v) - { - version = v; - repaint(); - resized(); - } - } - - void paint (Graphics& g) - { - if (version != nullptr) - { - g.setColour (Colours::green.withAlpha (0.12f)); - - 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 (s, 4, 0, applyButton.getX() - 4, getHeight(), Justification::centredLeft, true); - } - } - - void resized() - { - applyButton.changeWidthToFitText (getHeight() - 4); - applyButton.setTopRightPosition (getWidth(), 2); - applyButton.setVisible (version != nullptr); - } + AlertWindow::showMessageBox (AlertWindow::WarningIcon, + "Module Update", + "Couldn't create the target folder!"); + return; + } - void buttonClicked (Button*) - { - updater.applyVersion (version); - } + StringArray itemsWanted; - private: - JuceUpdater& updater; - VersionInfo* version; - TextButton applyButton; - }; + for (int i = latestList.modules.size(); --i >= 0;) + if (versionsToDownload [latestList.modules.getUnchecked(i)->uid]) + itemsWanted.add (latestList.modules.getUnchecked(i)->uid); - UpdateListComponent* c = dynamic_cast (existingComponentToUpdate); - if (c == nullptr) - c = new UpdateListComponent (*this); + { + InstallThread thread (moduleList, latestList, itemsWanted); + thread.runThread(); + } - c->setVersion (availableVersions [rowNumber]); - return c; + 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; - - XmlElement* downloadVersionList(); - String getCurrentVersion(); - bool isAlreadyUpToDate(); - - struct VersionInfo - { - URL url; - String desc; - String version; - String date; - }; - - OwnedArray availableVersions; - - void updateVersions (const XmlElement& xml); - void applyVersion (VersionInfo* version); + ValueTree versionsToDownload; + TextButton installButton; + ToggleButton selectAllButton; + ScopedPointer websiteContacterThread; + + void checkNow(); + void install(); + void updateInstallButtonStatus(); + void refresh(); + void selectAll(); + int getNumCheckedModules() const; + bool isLatestVersion (const String& moduleID) const; + + void valueTreePropertyChanged (ValueTree&, const Identifier&); + void valueTreeChildAdded (ValueTree&, ValueTree&); + void valueTreeChildRemoved (ValueTree&, ValueTree&); + void valueTreeChildOrderChanged (ValueTree&); + void valueTreeParentChanged (ValueTree&); + + 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 @@ -52,30 +137,38 @@ void ModuleList::sort() void ModuleList::rescan() { - modules.clear(); - moduleFolder = StoredSettings::getInstance()->getLastKnownJuceFolder().getChildFile ("modules"); + rescan (moduleFolder); +} - DirectoryIterator iter (moduleFolder, false, "*", File::findDirectories); +void ModuleList::rescan (const File& newModulesFolder) +{ + modules.clear(); + moduleFolder = getModulesFolderForJuceOrModulesFolder (newModulesFolder); - 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); - - info->uid = m.getID(); - info->version = m.getVersion(); - info->name = m.moduleInfo ["name"]; - info->description = m.moduleInfo ["description"]; - info->file = moduleDef; + LibraryModule m (moduleDef); + jassert (m.isValid()); + + 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.