mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Projucer various fixes
* Use separate folder for disk cache in debug mode to avoid mixing debug/release-mode object files while testing * Quote the server's file name as it may contain spaces etc. * Fix saving source files during compilation on Windows * Fix JuceDemo for live builds on Mac: long chains of recursive operator<< invocations caused compiler crash * Move code for creating disabled Build tab to extra function and add names to improve readability * Implement new "subscribe" behavior for createDisabledBuildTab * Clean up trailing spaces
This commit is contained in:
parent
e35aba3444
commit
8ec9443543
10 changed files with 150 additions and 64 deletions
|
|
@ -119,7 +119,9 @@ static String getAllSystemInfo()
|
|||
<< "User region: " << SystemStats::getUserRegion() << newLine
|
||||
<< "User language: " << SystemStats::getUserLanguage() << newLine
|
||||
<< "Display language: " << SystemStats::getDisplayLanguage() << newLine
|
||||
<< newLine
|
||||
<< newLine;
|
||||
|
||||
systemInfo
|
||||
<< "Number of CPUs: " << SystemStats::getNumCpus() << newLine
|
||||
<< "Memory size: " << SystemStats::getMemorySizeInMegabytes() << " MB" << newLine
|
||||
<< "CPU vendor: " << SystemStats::getCpuVendor() << newLine
|
||||
|
|
@ -134,12 +136,16 @@ static String getAllSystemInfo()
|
|||
<< "CPU has 3DNOW: " << (SystemStats::has3DNow() ? "yes" : "no") << newLine
|
||||
<< "CPU has AVX: " << (SystemStats::hasAVX() ? "yes" : "no") << newLine
|
||||
<< "CPU has AVX2: " << (SystemStats::hasAVX2() ? "yes" : "no") << newLine
|
||||
<< newLine
|
||||
<< newLine;
|
||||
|
||||
systemInfo
|
||||
<< "Current working directory: " << File::getCurrentWorkingDirectory().getFullPathName() << newLine
|
||||
<< "Current application file: " << File::getSpecialLocation (File::currentApplicationFile).getFullPathName() << newLine
|
||||
<< "Current executable file: " << File::getSpecialLocation (File::currentExecutableFile) .getFullPathName() << newLine
|
||||
<< "Invoked executable file: " << File::getSpecialLocation (File::invokedExecutableFile) .getFullPathName() << newLine
|
||||
<< newLine
|
||||
<< newLine;
|
||||
|
||||
systemInfo
|
||||
<< "User home folder: " << File::getSpecialLocation (File::userHomeDirectory) .getFullPathName() << newLine
|
||||
<< "User desktop folder: " << File::getSpecialLocation (File::userDesktopDirectory) .getFullPathName() << newLine
|
||||
<< "User documents folder: " << File::getSpecialLocation (File::userDocumentsDirectory) .getFullPathName() << newLine
|
||||
|
|
@ -150,7 +156,9 @@ static String getAllSystemInfo()
|
|||
<< "Common application data folder: " << File::getSpecialLocation (File::commonApplicationDataDirectory).getFullPathName() << newLine
|
||||
<< "Common documents folder: " << File::getSpecialLocation (File::commonDocumentsDirectory) .getFullPathName() << newLine
|
||||
<< "Local temp folder: " << File::getSpecialLocation (File::tempDirectory) .getFullPathName() << newLine
|
||||
<< newLine
|
||||
<< newLine;
|
||||
|
||||
systemInfo
|
||||
<< "File System roots: " << getFileSystemRoots() << newLine
|
||||
<< "Free space in home folder: " << File::descriptionOfSizeInBytes (File::getSpecialLocation (File::userHomeDirectory)
|
||||
.getBytesFreeOnVolume()) << newLine
|
||||
|
|
|
|||
|
|
@ -89,9 +89,15 @@ namespace ProjectProperties
|
|||
|
||||
static File getCacheLocation (Project& project)
|
||||
{
|
||||
String cacheFolderName = project.getProjectFilenameRoot() + "_" + project.getProjectUID();
|
||||
|
||||
#if JUCE_DEBUG
|
||||
cacheFolderName += "_debug";
|
||||
#endif
|
||||
|
||||
return getProjucerTempFolder()
|
||||
.getChildFile ("Intermediate Files")
|
||||
.getChildFile (project.getProjectFilenameRoot() + "_" + project.getProjectUID());
|
||||
.getChildFile (cacheFolderName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ String createCommandLineForLaunchingServer (const String& pipeName, const String
|
|||
|
||||
const File exe (File::getSpecialLocation (File::currentExecutableFile).getFullPathName());
|
||||
|
||||
return exe.getFullPathName() + " " + commandPrefix + info.joinIntoString (commandTokenSeparator);
|
||||
return "\"" + exe.getFullPathName() + "\" " + commandPrefix + info.joinIntoString (commandTokenSeparator);
|
||||
}
|
||||
|
||||
static ServerIPC* currentServer = nullptr;
|
||||
|
|
|
|||
|
|
@ -354,65 +354,95 @@ struct BuildTabComponent : public ConcertinaPanel
|
|||
struct ProjucerDisabledComp : public Component,
|
||||
private Button::Listener
|
||||
{
|
||||
ProjucerDisabledComp (String message, bool loggedIn, bool canLogin, bool requirePurchase = false,
|
||||
const String& loginName = String())
|
||||
: isLoggedIn (loggedIn), isPurchaseButton (requirePurchase)
|
||||
ProjucerDisabledComp (String message, bool loggedIn, bool showSubscribeButton,
|
||||
bool showSignInButton, bool showSwitchAccountButton)
|
||||
: isLoggedIn (loggedIn)
|
||||
{
|
||||
infoLabel.setColour (Label::textColourId, findColour (mainBackgroundColourId).contrasting (0.7f));
|
||||
infoLabel.setJustificationType (Justification::centred);
|
||||
infoLabel.setText (message, dontSendNotification);
|
||||
addAndMakeVisible (infoLabel);
|
||||
|
||||
if (canLogin)
|
||||
if (showSubscribeButton)
|
||||
{
|
||||
addAndMakeVisible (loginButton);
|
||||
loginButton.addListener (this);
|
||||
subscribeButton = new TextButton (String ( "Subscribe..."));
|
||||
addAndMakeVisible (*subscribeButton);
|
||||
subscribeButton->addListener (this);
|
||||
}
|
||||
|
||||
if (isPurchaseButton)
|
||||
{
|
||||
loginButton.setButtonText ("Purchase JUCE Pro...");
|
||||
signOutButton = new TextButton (String ("Sign Out ") + loginName);
|
||||
addAndMakeVisible (*signOutButton);
|
||||
signOutButton->addListener (this);
|
||||
}
|
||||
if (showSignInButton)
|
||||
{
|
||||
signInButton = new TextButton (String ( "Sign in..."));
|
||||
addAndMakeVisible (*signInButton);
|
||||
signInButton->addListener (this);
|
||||
}
|
||||
|
||||
if (showSwitchAccountButton)
|
||||
{
|
||||
switchAccountButton = new TextButton (String ("Switch account..."));
|
||||
addAndMakeVisible (*switchAccountButton);
|
||||
switchAccountButton->addListener (this);
|
||||
}
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
infoLabel.centreWithSize (proportionOfWidth (0.9f), 200);
|
||||
loginButton.setSize (jmin (getWidth() - 10, 150), 22);
|
||||
loginButton.setCentrePosition (infoLabel.getBounds().getCentreX(),
|
||||
infoLabel.getBottom() + loginButton.getHeight() * 2);
|
||||
int infoWidth = proportionOfWidth (0.9f);
|
||||
int infoHeight = 100;
|
||||
|
||||
if (signOutButton != nullptr)
|
||||
infoLabel.centreWithSize (infoWidth, infoHeight);
|
||||
|
||||
int buttonWidth = jmin (getWidth() - 10, 150);
|
||||
int buttonHeight = 22;
|
||||
int itemDistance = 10;
|
||||
|
||||
int buttonCenterX = infoLabel.getBounds().getCentreX();
|
||||
int buttonCenterY = infoLabel.getBottom() + itemDistance + buttonHeight / 2;
|
||||
|
||||
if (subscribeButton.get() != nullptr)
|
||||
{
|
||||
signOutButton->setSize (jmin (getWidth() - 10, 150), 22);
|
||||
signOutButton->setCentrePosition (infoLabel.getBounds().getCentreX(),
|
||||
loginButton.getBottom() + 20);
|
||||
subscribeButton->setSize (buttonWidth, buttonHeight);
|
||||
subscribeButton->setCentrePosition (buttonCenterX, buttonCenterY);
|
||||
buttonCenterY += itemDistance + buttonHeight;
|
||||
}
|
||||
|
||||
if (signInButton.get() != nullptr)
|
||||
{
|
||||
signInButton->setSize (buttonWidth, buttonHeight);
|
||||
signInButton->setCentrePosition (buttonCenterX, buttonCenterY);
|
||||
buttonCenterY += itemDistance + buttonHeight;
|
||||
}
|
||||
|
||||
if (switchAccountButton.get() != nullptr)
|
||||
{
|
||||
switchAccountButton->setSize (buttonWidth, buttonHeight);
|
||||
switchAccountButton->setCentrePosition (buttonCenterX, buttonCenterY);
|
||||
}
|
||||
}
|
||||
|
||||
void buttonClicked (Button* btn) override
|
||||
{
|
||||
if (btn == &loginButton)
|
||||
if (btn == subscribeButton.get())
|
||||
{
|
||||
if (isPurchaseButton)
|
||||
URL ("http://www.juce.com").launchInDefaultBrowser();
|
||||
else
|
||||
ProjucerApplication::getApp().showLoginForm();
|
||||
URL ("http://www.juce.com/get-juce").launchInDefaultBrowser();
|
||||
}
|
||||
else if (btn == signOutButton.get())
|
||||
else if (btn == signInButton.get())
|
||||
{
|
||||
ProjucerLicenses::getInstance()->logout();
|
||||
ProjucerApplication::getApp().updateAllBuildTabs();
|
||||
ProjucerApplication::getApp().showLoginForm();
|
||||
}
|
||||
else if (btn == switchAccountButton.get())
|
||||
{
|
||||
ProjucerApplication::getApp().showLoginForm();
|
||||
}
|
||||
}
|
||||
|
||||
bool isLoggedIn;
|
||||
|
||||
private:
|
||||
Label infoLabel { "info", String() };
|
||||
TextButton loginButton { "Log-in..." };
|
||||
ScopedPointer<TextButton> signOutButton;
|
||||
bool isLoggedIn, isPurchaseButton;
|
||||
ScopedPointer<TextButton> subscribeButton;
|
||||
ScopedPointer<TextButton> signInButton;
|
||||
ScopedPointer<TextButton> switchAccountButton;
|
||||
};
|
||||
|
||||
struct EnableBuildComp : public Component
|
||||
|
|
@ -458,33 +488,30 @@ Component* ProjectContentComponent::createBuildTab (CompileEngineChildProcess* c
|
|||
return new BuildTabComponent (child, new ProjucerAppClasses::ErrorListComp (child->errorList));
|
||||
}
|
||||
|
||||
auto& unlockStatus = *ProjucerLicenses::getInstance();
|
||||
jassert (project != nullptr);
|
||||
const auto& unlockStatus = *ProjucerLicenses::getInstance();
|
||||
|
||||
if (unlockStatus.hasLiveCodingLicence()
|
||||
&& project != nullptr
|
||||
&& LiveBuildProjectSettings::isBuildDisabled (*project))
|
||||
return new EnableBuildComp();
|
||||
if (unlockStatus.hasLiveCodingLicence())
|
||||
{
|
||||
jassert (unlockStatus.isLoggedIn());
|
||||
jassert (unlockStatus.isDLLPresent());
|
||||
return new EnableBuildComp();
|
||||
}
|
||||
|
||||
if (unlockStatus.isLoggedIn())
|
||||
return new ProjucerDisabledComp (String ("The Projucer's live-build features are currently disabled!") + newLine
|
||||
+ newLine
|
||||
+ "Your account " + unlockStatus.getLoginName().quoted()
|
||||
+ " does not have an asscociated JUCE Pro license:",
|
||||
true, true, true, unlockStatus.getLoginName());
|
||||
|
||||
if (! unlockStatus.isDLLPresent())
|
||||
return new ProjucerDisabledComp (String ("The live-building DLL is missing!") + newLine
|
||||
+ newLine
|
||||
+ "To enable the compiler, you'll need to install the missing DLL "
|
||||
+ CompileEngineDLL::getDLLName().quoted() + newLine
|
||||
+ newLine
|
||||
+ "Visit the JUCE website/forum for more help on getting and installing the DLL!",
|
||||
false, false);
|
||||
|
||||
return new ProjucerDisabledComp ("The Projucer's live-build features are currently disabled!\n\n"
|
||||
"To enable them, you'll need to log-in with your JUCE account details:",
|
||||
false, true, false);
|
||||
return createDisabledBuildTab(unlockStatus.isLoggedIn(),
|
||||
unlockStatus.isDLLPresent());
|
||||
#endif
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
Component* ProjectContentComponent::createDisabledBuildTab(bool loggedIn, bool dllPresent) {
|
||||
bool showSubscribeButton = true;
|
||||
bool showSignInButton = dllPresent && ! loggedIn;
|
||||
bool showSwitchAccountButton = dllPresent && loggedIn;
|
||||
|
||||
return new ProjucerDisabledComp (
|
||||
"Subscribe to JUCE Pro or Indie to use the Projucer's live-build features:",
|
||||
loggedIn, showSubscribeButton, showSignInButton, showSwitchAccountButton);
|
||||
}
|
||||
|
||||
BuildTabComponent* findBuildTab (const TabbedComponent& tabs)
|
||||
|
|
@ -1499,7 +1526,8 @@ void ProjectContentComponent::handleMissingSystemHeaders()
|
|||
deleteProjectTabs();
|
||||
createProjectTabs();
|
||||
|
||||
ProjucerDisabledComp* buildTab = new ProjucerDisabledComp (tabMessage, false, false);
|
||||
bool isLoggedIn = ProjucerLicenses::getInstance()->isLoggedIn();
|
||||
ProjucerDisabledComp* buildTab = new ProjucerDisabledComp (tabMessage, isLoggedIn, false, false, false);
|
||||
|
||||
treeViewTabs.addTab ("Build", Colours::transparentBlack, buildTab, true);
|
||||
showBuildTab();
|
||||
|
|
|
|||
|
|
@ -154,6 +154,8 @@ private:
|
|||
void timerCallback() override;
|
||||
|
||||
Component* createBuildTab (CompileEngineChildProcess*);
|
||||
Component* createDisabledBuildTab (bool loggedIn, bool dllPresent);
|
||||
|
||||
bool isContinuousRebuildEnabled() { return getAppSettings().getGlobalProperties().getBoolValue ("continuousRebuild", true); }
|
||||
void setContinuousRebuildEnabled (bool b) { getAppSettings().getGlobalProperties().setValue ("continuousRebuild", b); }
|
||||
void rebuildNow();
|
||||
|
|
|
|||
|
|
@ -300,6 +300,21 @@ bool File::copyFileTo (const File& newFile) const
|
|||
|| (exists() && newFile.deleteFile() && copyInternal (newFile));
|
||||
}
|
||||
|
||||
bool File::replaceFileIn (const File& newFile) const
|
||||
{
|
||||
if (newFile.fullPath == fullPath)
|
||||
return true;
|
||||
|
||||
if (! newFile.exists())
|
||||
return moveFileTo (newFile);
|
||||
|
||||
if (! replaceInternal (newFile))
|
||||
return false;
|
||||
|
||||
deleteFile();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool File::copyDirectoryTo (const File& newDirectory) const
|
||||
{
|
||||
if (isDirectory() && newDirectory.createDirectory())
|
||||
|
|
|
|||
|
|
@ -503,6 +503,18 @@ public:
|
|||
*/
|
||||
bool copyFileTo (const File& targetLocation) const;
|
||||
|
||||
/** Replaces a file.
|
||||
|
||||
Replace the file in the given location, assuming the replaced files identity.
|
||||
Depending on the file system this will preserve file attributes such as
|
||||
creation date, short file name, etc.
|
||||
|
||||
If replacement succeeds the original file is deleted.
|
||||
|
||||
@returns true if the operation succeeds
|
||||
*/
|
||||
bool replaceFileIn (const File& targetLocation) const;
|
||||
|
||||
/** Copies a directory.
|
||||
|
||||
Tries to copy an entire directory, recursively.
|
||||
|
|
@ -982,6 +994,7 @@ private:
|
|||
Result createDirectoryInternal (const String&) const;
|
||||
bool copyInternal (const File&) const;
|
||||
bool moveInternal (const File&) const;
|
||||
bool replaceInternal (const File&) const;
|
||||
bool setFileTimesInternal (int64 m, int64 a, int64 c) const;
|
||||
void getFileTimesInternal (int64& m, int64& a, int64& c) const;
|
||||
bool setFileReadOnlyInternal (bool) const;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ bool TemporaryFile::overwriteTargetFileWithTemporary() const
|
|||
// Have a few attempts at overwriting the file before giving up..
|
||||
for (int i = 5; --i >= 0;)
|
||||
{
|
||||
if (temporaryFile.moveFileTo (targetFile))
|
||||
if (temporaryFile.replaceFileIn (targetFile))
|
||||
return true;
|
||||
|
||||
Thread::sleep (100);
|
||||
|
|
|
|||
|
|
@ -440,6 +440,11 @@ bool File::moveInternal (const File& dest) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool File::replaceInternal (const File& dest) const
|
||||
{
|
||||
return moveInternal (dest);
|
||||
}
|
||||
|
||||
Result File::createDirectoryInternal (const String& fileName) const
|
||||
{
|
||||
return getResultForReturnValue (mkdir (fileName.toUTF8(), 0777));
|
||||
|
|
|
|||
|
|
@ -220,6 +220,15 @@ bool File::moveInternal (const File& dest) const
|
|||
return MoveFile (fullPath.toWideCharPointer(), dest.getFullPathName().toWideCharPointer()) != 0;
|
||||
}
|
||||
|
||||
bool File::replaceInternal (const File& dest) const
|
||||
{
|
||||
void* lpExclude = 0;
|
||||
void* lpReserved = 0;
|
||||
|
||||
return ReplaceFile (dest.getFullPathName().toWideCharPointer(), fullPath.toWideCharPointer(),
|
||||
0, REPLACEFILE_IGNORE_MERGE_ERRORS, lpExclude, lpReserved) != 0;
|
||||
}
|
||||
|
||||
Result File::createDirectoryInternal (const String& fileName) const
|
||||
{
|
||||
return CreateDirectory (fileName.toWideCharPointer(), 0) ? Result::ok()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue