Add TAL-Reverb-II plugin to test
[juce-lv2.git] / juce / source / extras / Introjucer / Source / Application / jucer_JuceUpdater.cpp
blobd2f068f5b06b608539f98543e5a57c3218da21dd
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-10 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../jucer_Headers.h"
27 #include "jucer_JuceUpdater.h"
30 //==============================================================================
31 JuceUpdater::JuceUpdater()
32 : filenameComp ("Juce Folder", StoredSettings::getInstance()->getLastKnownJuceFolder(),
33 true, true, false, "*", String::empty, "Select your Juce folder"),
34 checkNowButton ("Check Online for Available Updates...",
35 "Contacts the website to see if this version is up-to-date")
37 addAndMakeVisible (&label);
38 addAndMakeVisible (&filenameComp);
39 addAndMakeVisible (&checkNowButton);
40 addAndMakeVisible (&currentVersionLabel);
41 checkNowButton.addListener (this);
42 filenameComp.addListener (this);
44 currentVersionLabel.setFont (Font (14.0f, Font::italic));
45 label.setFont (Font (12.0f));
46 label.setText ("Destination folder:", false);
48 addAndMakeVisible (&availableVersionsList);
49 availableVersionsList.setModel (this);
51 setSize (600, 300);
54 JuceUpdater::~JuceUpdater()
56 checkNowButton.removeListener (this);
57 filenameComp.removeListener (this);
60 void JuceUpdater::show (Component* mainWindow)
62 JuceUpdater updater;
63 DialogWindow::showModalDialog ("Juce Update...", &updater, mainWindow,
64 Colours::lightgrey,
65 true, false, false);
68 void JuceUpdater::resized()
70 filenameComp.setBounds (20, 40, getWidth() - 40, 22);
71 label.setBounds (filenameComp.getX(), filenameComp.getY() - 18, filenameComp.getWidth(), 18);
72 currentVersionLabel.setBounds (filenameComp.getX(), filenameComp.getBottom(), filenameComp.getWidth(), 25);
73 checkNowButton.changeWidthToFitText (20);
74 checkNowButton.setCentrePosition (getWidth() / 2, filenameComp.getBottom() + 40);
75 availableVersionsList.setBounds (filenameComp.getX(), checkNowButton.getBottom() + 20, filenameComp.getWidth(), getHeight() - (checkNowButton.getBottom() + 20));
78 void JuceUpdater::paint (Graphics& g)
80 g.fillAll (Colours::white);
83 const String findVersionNum (const String& file, const String& token)
85 return file.fromFirstOccurrenceOf (token, false, false)
86 .upToFirstOccurrenceOf ("\n", false, false)
87 .trim();
90 const String JuceUpdater::getCurrentVersion()
92 const String header (filenameComp.getCurrentFile()
93 .getChildFile ("src/core/juce_StandardHeader.h").loadFileAsString());
95 const String v1 (findVersionNum (header, "JUCE_MAJOR_VERSION"));
96 const String v2 (findVersionNum (header, "JUCE_MINOR_VERSION"));
97 const String v3 (findVersionNum (header, "JUCE_BUILDNUMBER"));
99 if ((v1 + v2 + v3).isEmpty())
100 return String::empty;
102 return v1 + "." + v2 + "." + v3;
105 XmlElement* JuceUpdater::downloadVersionList()
107 return URL ("http://www.rawmaterialsoftware.com/juce/downloads/juce_versions.php").readEntireXmlStream();
110 void JuceUpdater::updateVersions (const XmlElement& xml)
112 availableVersions.clear();
114 forEachXmlChildElementWithTagName (xml, v, "VERSION")
116 VersionInfo* vi = new VersionInfo();
117 vi->url = URL (v->getStringAttribute ("url"));
118 vi->desc = v->getStringAttribute ("desc");
119 vi->version = v->getStringAttribute ("version");
120 vi->date = v->getStringAttribute ("date");
121 availableVersions.add (vi);
124 availableVersionsList.updateContent();
127 void JuceUpdater::buttonClicked (Button*)
129 ScopedPointer<XmlElement> xml (downloadVersionList());
131 if (xml == nullptr || xml->hasTagName ("html"))
133 AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Connection Problems...",
134 "Couldn't connect to the Raw Material Software website!");
136 return;
139 if (! xml->hasTagName ("JUCEVERSIONS"))
141 AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Update Problems...",
142 "This version of the Jucer may be too old to receive automatic updates!\n\n"
143 "Please visit www.rawmaterialsoftware.com and get the latest version manually!");
144 return;
147 const String currentVersion (getCurrentVersion());
149 OwnedArray<VersionInfo> versions;
150 updateVersions (*xml);
153 //==============================================================================
154 class NewVersionDownloader : public ThreadWithProgressWindow
156 public:
157 NewVersionDownloader (const String& title, const URL& url_, const File& target_)
158 : ThreadWithProgressWindow (title, true, true),
159 url (url_), target (target_)
163 void run()
165 setStatusMessage ("Contacting website...");
167 ScopedPointer<InputStream> input (url.createInputStream (false));
169 if (input == nullptr)
171 error = "Couldn't connect to the website...";
172 return;
175 if (! target.deleteFile())
177 error = "Couldn't delete the destination file...";
178 return;
181 ScopedPointer<OutputStream> output (target.createOutputStream (32768));
183 if (output == nullptr)
185 error = "Couldn't write to the destination file...";
186 return;
189 setStatusMessage ("Downloading...");
191 int totalBytes = (int) input->getTotalLength();
192 int bytesSoFar = 0;
194 while (! (input->isExhausted() || threadShouldExit()))
196 HeapBlock<char> buffer (8192);
197 const int num = input->read (buffer, 8192);
199 if (num == 0)
200 break;
202 output->write (buffer, num);
203 bytesSoFar += num;
205 setProgress (totalBytes > 0 ? bytesSoFar / (double) totalBytes : -1.0);
209 String error;
211 private:
212 URL url;
213 File target;
216 //==============================================================================
217 class Unzipper : public ThreadWithProgressWindow
219 public:
220 Unzipper (ZipFile& zipFile_, const File& targetDir_)
221 : ThreadWithProgressWindow ("Unzipping...", true, true),
222 worked (true), zipFile (zipFile_), targetDir (targetDir_)
226 void run()
228 for (int i = 0; i < zipFile.getNumEntries(); ++i)
230 if (threadShouldExit())
231 break;
233 const ZipFile::ZipEntry* e = zipFile.getEntry (i);
234 setStatusMessage ("Unzipping " + e->filename + "...");
235 setProgress (i / (double) zipFile.getNumEntries());
237 worked = zipFile.uncompressEntry (i, targetDir, true) && worked;
241 bool worked;
243 private:
244 ZipFile& zipFile;
245 File targetDir;
248 //==============================================================================
249 void JuceUpdater::applyVersion (VersionInfo* version)
251 File destDir (filenameComp.getCurrentFile());
253 const bool destDirExisted = destDir.isDirectory();
255 if (destDirExisted && destDir.getNumberOfChildFiles (File::findFilesAndDirectories, "*") > 0)
257 int r = AlertWindow::showYesNoCancelBox (AlertWindow::WarningIcon, "Folder already exists",
258 "The folder " + destDir.getFullPathName() + "\nalready contains some files...\n\n"
259 "Do you want to delete everything in the folder and replace it entirely, or just merge the new files into the existing folder?",
260 "Delete and replace entire folder",
261 "Add and overwrite existing files",
262 "Cancel");
264 if (r == 0)
265 return;
267 if (r == 1)
269 if (! destDir.deleteRecursively())
271 AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Problems...",
272 "Couldn't delete the existing folder!");
273 return;
278 if (! (destDir.isDirectory() || destDir.createDirectory()))
280 AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Problems...",
281 "Couldn't create that target folder..");
282 return;
285 File zipFile (destDir.getNonexistentChildFile ("juce_download", ".tar.gz", false));
287 bool worked = false;
290 NewVersionDownloader downloader ("Downloading Version " + version->version + "...",
291 version->url, zipFile);
292 worked = downloader.runThread();
295 if (worked)
297 ZipFile zip (zipFile);
298 Unzipper unzipper (zip, destDir);
299 worked = unzipper.runThread() && unzipper.worked;
302 zipFile.deleteFile();
304 if ((! destDirExisted) && (destDir.getNumberOfChildFiles (File::findFilesAndDirectories, "*") == 0 || ! worked))
305 destDir.deleteRecursively();
307 filenameComponentChanged (&filenameComp);
310 void JuceUpdater::filenameComponentChanged (FilenameComponent*)
312 const String version (getCurrentVersion());
314 if (version.isEmpty())
315 currentVersionLabel.setText ("(Not a Juce folder)", false);
316 else
317 currentVersionLabel.setText ("(Current version in this folder: " + version + ")", false);
320 //==============================================================================
321 int JuceUpdater::getNumRows()
323 return availableVersions.size();
326 void JuceUpdater::paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected)
328 if (rowIsSelected)
329 g.fillAll (findColour (TextEditor::highlightColourId));
332 Component* JuceUpdater::refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate)
334 class UpdateListComponent : public Component,
335 public ButtonListener
337 public:
338 UpdateListComponent (JuceUpdater& updater_)
339 : updater (updater_),
340 version (nullptr),
341 applyButton ("Install this version...")
343 addAndMakeVisible (&applyButton);
344 applyButton.addListener (this);
345 setInterceptsMouseClicks (false, true);
348 ~UpdateListComponent()
350 applyButton.removeListener (this);
353 void setVersion (VersionInfo* v)
355 if (version != v)
357 version = v;
358 repaint();
359 resized();
363 void paint (Graphics& g)
365 if (version != nullptr)
367 g.setColour (Colours::green.withAlpha (0.12f));
369 g.fillRect (0, 1, getWidth(), getHeight() - 2);
370 g.setColour (Colours::black);
371 g.setFont (getHeight() * 0.7f);
373 String s;
374 s << "Version " << version->version << " - " << version->desc << " - " << version->date;
376 g.drawText (s, 4, 0, applyButton.getX() - 4, getHeight(), Justification::centredLeft, true);
380 void resized()
382 applyButton.changeWidthToFitText (getHeight() - 4);
383 applyButton.setTopRightPosition (getWidth(), 2);
384 applyButton.setVisible (version != nullptr);
387 void buttonClicked (Button*)
389 updater.applyVersion (version);
392 private:
393 JuceUpdater& updater;
394 VersionInfo* version;
395 TextButton applyButton;
398 UpdateListComponent* c = dynamic_cast <UpdateListComponent*> (existingComponentToUpdate);
399 if (c == nullptr)
400 c = new UpdateListComponent (*this);
402 c->setVersion (availableVersions [rowNumber]);
403 return c;