@@ -244,7 +244,8 @@ | |||||
JUCE_ALSA="disabled" JUCE_QUICKTIME="disabled" JUCE_OPENGL="disabled" | JUCE_ALSA="disabled" JUCE_QUICKTIME="disabled" JUCE_OPENGL="disabled" | ||||
JUCE_USE_FLAC="disabled" JUCE_USE_CDBURNER="disabled" JUCE_USE_CDREADER="disabled" | JUCE_USE_FLAC="disabled" JUCE_USE_CDBURNER="disabled" JUCE_USE_CDREADER="disabled" | ||||
JUCE_USE_CAMERA="disabled" JUCE_PLUGINHOST_VST="disabled" JUCE_PLUGINHOST_AU="disabled" | JUCE_USE_CAMERA="disabled" JUCE_PLUGINHOST_VST="disabled" JUCE_PLUGINHOST_AU="disabled" | ||||
JUCE_USE_OGGVORBIS="disabled" JUCE_USE_COREIMAGE_LOADER="disabled"/> | |||||
JUCE_USE_OGGVORBIS="disabled" JUCE_USE_COREIMAGE_LOADER="disabled" | |||||
JUCE_LOG_ASSERTIONS="enabled"/> | |||||
<MODULES> | <MODULES> | ||||
<MODULE id="juce_core" showAllCode="1"/> | <MODULE id="juce_core" showAllCode="1"/> | ||||
<MODULE id="juce_events" showAllCode="1"/> | <MODULE id="juce_events" showAllCode="1"/> | ||||
@@ -38,7 +38,7 @@ | |||||
#endif | #endif | ||||
#ifndef JUCE_LOG_ASSERTIONS | #ifndef JUCE_LOG_ASSERTIONS | ||||
//#define JUCE_LOG_ASSERTIONS | |||||
#define JUCE_LOG_ASSERTIONS 1 | |||||
#endif | #endif | ||||
#ifndef JUCE_CHECK_MEMORY_LEAKS | #ifndef JUCE_CHECK_MEMORY_LEAKS | ||||
@@ -44,6 +44,8 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
void initialise (const String& commandLine) | void initialise (const String& commandLine) | ||||
{ | { | ||||
initialiseLogger ("log_"); | |||||
LookAndFeel::setDefaultLookAndFeel (&lookAndFeel); | LookAndFeel::setDefaultLookAndFeel (&lookAndFeel); | ||||
settings = new StoredSettings(); | settings = new StoredSettings(); | ||||
settings->initialise(); | settings->initialise(); | ||||
@@ -116,6 +118,10 @@ public: | |||||
settings = nullptr; | settings = nullptr; | ||||
LookAndFeel::setDefaultLookAndFeel (nullptr); | LookAndFeel::setDefaultLookAndFeel (nullptr); | ||||
Logger::writeToLog ("Shutdown"); | |||||
deleteLogger(); | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
@@ -463,8 +469,57 @@ public: | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
void initialiseLogger (const char* filePrefix) | |||||
{ | |||||
if (logger == nullptr) | |||||
{ | |||||
logger = FileLogger::createDateStampedLogger (getLogFolderName(), filePrefix, ".txt", | |||||
getApplicationName() + " " + getApplicationVersion()); | |||||
Logger::setCurrentLogger (logger); | |||||
} | |||||
} | |||||
void deleteLogger() | |||||
{ | |||||
const int maxNumLogFilesToKeep = 50; | |||||
Logger::setCurrentLogger (nullptr); | |||||
if (logger != nullptr) | |||||
{ | |||||
Array<File> logFiles; | |||||
logger->getLogFile().getParentDirectory().findChildFiles (logFiles, File::findFiles, false); | |||||
if (logFiles.size() > maxNumLogFilesToKeep) | |||||
{ | |||||
struct FileWithTime | |||||
{ | |||||
FileWithTime (const File& f) : file (f), time (f.getLastModificationTime()) {} | |||||
FileWithTime() {} | |||||
bool operator< (const FileWithTime& other) const { return time < other.time; } | |||||
bool operator== (const FileWithTime& other) const { return time == other.time; } | |||||
File file; | |||||
Time time; | |||||
}; | |||||
Array <FileWithTime> files; | |||||
for (int i = 0; i < logFiles.size(); ++i) | |||||
files.addUsingDefaultSort (logFiles.getReference(i)); | |||||
for (int i = 0; i < files.size() - maxNumLogFilesToKeep; ++i) | |||||
files.getReference(i).file.deleteFile(); | |||||
} | |||||
} | |||||
logger = nullptr; | |||||
} | |||||
virtual void doExtraInitialisation() {} | virtual void doExtraInitialisation() {} | ||||
virtual void addExtraConfigItems (Project&, TreeViewItem&) {} | virtual void addExtraConfigItems (Project&, TreeViewItem&) {} | ||||
virtual String getLogFolderName() const { return "com.juce.introjucer"; } | |||||
virtual Component* createProjectContentComponent() const | virtual Component* createProjectContentComponent() const | ||||
{ | { | ||||
@@ -484,6 +539,8 @@ public: | |||||
ScopedPointer<Component> appearanceEditorWindow, utf8Window; | ScopedPointer<Component> appearanceEditorWindow, utf8Window; | ||||
ScopedPointer<FileLogger> logger; | |||||
private: | private: | ||||
class AsyncQuitRetrier : private Timer | class AsyncQuitRetrier : private Timer | ||||
{ | { | ||||
@@ -90,22 +90,13 @@ public: | |||||
project.createRequiredModules (moduleList, modules); | project.createRequiredModules (moduleList, modules); | ||||
} | } | ||||
if (errors.size() == 0) | |||||
writeAppConfigFile (modules, appConfigUserContent); | |||||
if (errors.size() == 0) writeAppConfigFile (modules, appConfigUserContent); | |||||
if (errors.size() == 0) writeBinaryDataFiles(); | |||||
if (errors.size() == 0) writeAppHeader (modules); | |||||
if (errors.size() == 0) writeProjects (modules); | |||||
if (errors.size() == 0) writeAppConfigFile (modules, appConfigUserContent); // (this is repeated in case the projects added anything to it) | |||||
if (errors.size() == 0) | |||||
writeBinaryDataFiles(); | |||||
if (errors.size() == 0) | |||||
writeAppHeader (modules); | |||||
if (errors.size() == 0) | |||||
writeProjects (modules); | |||||
if (errors.size() == 0) | |||||
writeAppConfigFile (modules, appConfigUserContent); // (this is repeated in case the projects added anything to it) | |||||
if (generatedCodeFolder.exists() && errors.size() == 0) | |||||
if (errors.size() == 0 && generatedCodeFolder.exists()) | |||||
writeReadmeFile(); | writeReadmeFile(); | ||||
if (generatedCodeFolder.exists()) | if (generatedCodeFolder.exists()) | ||||
@@ -47,14 +47,15 @@ namespace Tags | |||||
const char* Project::projectFileExtension = ".jucer"; | const char* Project::projectFileExtension = ".jucer"; | ||||
//============================================================================== | //============================================================================== | ||||
Project::Project (const File& file_) | |||||
Project::Project (const File& f) | |||||
: FileBasedDocument (projectFileExtension, | : FileBasedDocument (projectFileExtension, | ||||
String ("*") + projectFileExtension, | String ("*") + projectFileExtension, | ||||
"Choose a Jucer project to load", | "Choose a Jucer project to load", | ||||
"Save Jucer project"), | "Save Jucer project"), | ||||
projectRoot (Tags::projectRoot) | projectRoot (Tags::projectRoot) | ||||
{ | { | ||||
setFile (file_); | |||||
Logger::writeToLog ("Loading project: " + f.getFullPathName()); | |||||
setFile (f); | |||||
removeDefunctExporters(); | removeDefunctExporters(); | ||||
setMissingDefaultValues(); | setMissingDefaultValues(); | ||||
@@ -90,31 +90,34 @@ PropertiesFile& StoredSettings::getProjectProperties (const String& projectUID) | |||||
return *p; | return *p; | ||||
} | } | ||||
void StoredSettings::flush() | |||||
void StoredSettings::updateGlobalProps() | |||||
{ | { | ||||
for (int i = propertyFiles.size(); --i >= 0;) | |||||
PropertiesFile& props = getGlobalProperties(); | |||||
{ | { | ||||
PropertiesFile* const props = propertyFiles.getUnchecked(i); | |||||
const ScopedPointer<XmlElement> xml (appearance.settings.createXml()); | |||||
props.setValue ("editorColours", xml); | |||||
} | |||||
{ | |||||
const ScopedPointer<XmlElement> xml (appearance.settings.createXml()); | |||||
props->setValue ("editorColours", xml); | |||||
} | |||||
props.setValue ("recentFiles", recentFiles.toString()); | |||||
props->setValue ("recentFiles", recentFiles.toString()); | |||||
props.removeValue ("keyMappings"); | |||||
props->removeValue ("keyMappings"); | |||||
if (commandManager != nullptr) | |||||
{ | |||||
const ScopedPointer <XmlElement> keys (commandManager->getKeyMappings()->createXml (true)); | |||||
if (commandManager != nullptr) | |||||
{ | |||||
ScopedPointer <XmlElement> keys (commandManager->getKeyMappings()->createXml (true)); | |||||
if (keys != nullptr) | |||||
props.setValue ("keyMappings", keys); | |||||
} | |||||
} | |||||
if (keys != nullptr) | |||||
props->setValue ("keyMappings", (XmlElement*) keys); | |||||
} | |||||
void StoredSettings::flush() | |||||
{ | |||||
updateGlobalProps(); | |||||
props->saveIfNeeded(); | |||||
} | |||||
for (int i = propertyFiles.size(); --i >= 0;) | |||||
propertyFiles.getUnchecked(i)->saveIfNeeded(); | |||||
} | } | ||||
void StoredSettings::reload() | void StoredSettings::reload() | ||||
@@ -71,6 +71,7 @@ public: | |||||
private: | private: | ||||
OwnedArray<PropertiesFile> propertyFiles; | OwnedArray<PropertiesFile> propertyFiles; | ||||
void updateGlobalProps(); | |||||
void loadSwatchColours(); | void loadSwatchColours(); | ||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StoredSettings); | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StoredSettings); | ||||
@@ -130,21 +130,29 @@ String File::parseAbsolutePath (const String& p) | |||||
// expand a name of type "~dave/abc" | // expand a name of type "~dave/abc" | ||||
const String userName (path.substring (1).upToFirstOccurrenceOf ("/", false, false)); | const String userName (path.substring (1).upToFirstOccurrenceOf ("/", false, false)); | ||||
struct passwd* const pw = getpwnam (userName.toUTF8()); | |||||
if (pw != nullptr) | |||||
if (struct passwd* const pw = getpwnam (userName.toUTF8())) | |||||
path = addTrailingSeparator (pw->pw_dir) + path.fromFirstOccurrenceOf ("/", false, false); | path = addTrailingSeparator (pw->pw_dir) + path.fromFirstOccurrenceOf ("/", false, false); | ||||
} | } | ||||
} | } | ||||
else if (! path.startsWithChar (separator)) | else if (! path.startsWithChar (separator)) | ||||
{ | { | ||||
/* When you supply a raw string to the File object constructor, it must be an absolute path. | |||||
If you're trying to parse a string that may be either a relative path or an absolute path, | |||||
you MUST provide a context against which the partial path can be evaluated - you can do | |||||
this by simply using File::getChildFile() instead of the File constructor. E.g. saying | |||||
"File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute | |||||
path if that's what was supplied, or would evaluate a partial path relative to the CWD. | |||||
*/ | |||||
jassert (path.startsWith ("./") || path.startsWith ("../")); // (assume that a path "./xyz" is deliberately intended to be relative to the CWD) | |||||
#if JUCE_DEBUG || JUCE_LOG_ASSERTIONS | |||||
if (! (path.startsWith ("./") || path.startsWith ("../"))) | |||||
{ | |||||
/* When you supply a raw string to the File object constructor, it must be an absolute path. | |||||
If you're trying to parse a string that may be either a relative path or an absolute path, | |||||
you MUST provide a context against which the partial path can be evaluated - you can do | |||||
this by simply using File::getChildFile() instead of the File constructor. E.g. saying | |||||
"File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute | |||||
path if that's what was supplied, or would evaluate a partial path relative to the CWD. | |||||
*/ | |||||
jassertfalse; | |||||
#if JUCE_LOG_ASSERTIONS | |||||
Logger::writeToLog ("Illegal absolute path: " + path); | |||||
#endif | |||||
} | |||||
#endif | |||||
return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName(); | return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName(); | ||||
} | } | ||||
@@ -23,19 +23,16 @@ | |||||
============================================================================== | ============================================================================== | ||||
*/ | */ | ||||
FileLogger::FileLogger (const File& logFile_, | |||||
FileLogger::FileLogger (const File& file, | |||||
const String& welcomeMessage, | const String& welcomeMessage, | ||||
const int maxInitialFileSizeBytes) | |||||
: logFile (logFile_) | |||||
const int64 maxInitialFileSizeBytes) | |||||
: logFile (file) | |||||
{ | { | ||||
if (maxInitialFileSizeBytes >= 0) | if (maxInitialFileSizeBytes >= 0) | ||||
trimFileSize (maxInitialFileSizeBytes); | trimFileSize (maxInitialFileSizeBytes); | ||||
if (! logFile_.exists()) | |||||
{ | |||||
// do this so that the parent directories get created.. | |||||
logFile_.create(); | |||||
} | |||||
if (! file.exists()) | |||||
file.create(); // (to create the parent directories) | |||||
String welcome; | String welcome; | ||||
welcome << newLine | welcome << newLine | ||||
@@ -46,23 +43,18 @@ FileLogger::FileLogger (const File& logFile_, | |||||
FileLogger::logMessage (welcome); | FileLogger::logMessage (welcome); | ||||
} | } | ||||
FileLogger::~FileLogger() | |||||
{ | |||||
} | |||||
FileLogger::~FileLogger() {} | |||||
//============================================================================== | //============================================================================== | ||||
void FileLogger::logMessage (const String& message) | void FileLogger::logMessage (const String& message) | ||||
{ | { | ||||
DBG (message); | |||||
const ScopedLock sl (logLock); | const ScopedLock sl (logLock); | ||||
DBG (message); | |||||
FileOutputStream out (logFile, 256); | FileOutputStream out (logFile, 256); | ||||
out << message << newLine; | out << message << newLine; | ||||
} | } | ||||
void FileLogger::trimFileSize (int maxFileSizeBytes) const | |||||
void FileLogger::trimFileSize (int64 maxFileSizeBytes) const | |||||
{ | { | ||||
if (maxFileSizeBytes <= 0) | if (maxFileSizeBytes <= 0) | ||||
{ | { | ||||
@@ -74,59 +66,66 @@ void FileLogger::trimFileSize (int maxFileSizeBytes) const | |||||
if (fileSize > maxFileSizeBytes) | if (fileSize > maxFileSizeBytes) | ||||
{ | { | ||||
ScopedPointer <FileInputStream> in (logFile.createInputStream()); | |||||
jassert (in != nullptr); | |||||
TemporaryFile tempFile (logFile); | |||||
if (in != nullptr) | |||||
{ | { | ||||
in->setPosition (fileSize - maxFileSizeBytes); | |||||
String content; | |||||
FileOutputStream out (tempFile.getFile()); | |||||
FileInputStream in (logFile); | |||||
{ | |||||
MemoryBlock contentToSave; | |||||
contentToSave.setSize ((size_t) maxFileSizeBytes + 4); | |||||
contentToSave.fillWith (0); | |||||
if (! (out.openedOk() && in.openedOk())) | |||||
return; | |||||
in->read (contentToSave.getData(), maxFileSizeBytes); | |||||
in = nullptr; | |||||
in.setPosition (fileSize - maxFileSizeBytes); | |||||
content = contentToSave.toString(); | |||||
for (;;) | |||||
{ | |||||
const char c = in.readByte(); | |||||
if (c == 0) | |||||
return; | |||||
if (c == '\n' || c == '\r') | |||||
{ | |||||
out << c; | |||||
break; | |||||
} | |||||
} | } | ||||
int newStart = 0; | |||||
while (newStart < fileSize | |||||
&& content[newStart] != '\n' | |||||
&& content[newStart] != '\r') | |||||
++newStart; | |||||
logFile.deleteFile(); | |||||
logFile.appendText (content.substring (newStart), false, false); | |||||
out.writeFromInputStream (in, -1); | |||||
} | } | ||||
tempFile.overwriteTargetFileWithTemporary(); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
FileLogger* FileLogger::createDefaultAppLogger (const String& logFileSubDirectoryName, | |||||
const String& logFileName, | |||||
const String& welcomeMessage, | |||||
const int maxInitialFileSizeBytes) | |||||
File FileLogger::getSystemLogFileFolder() | |||||
{ | { | ||||
#if JUCE_MAC | #if JUCE_MAC | ||||
File logFile ("~/Library/Logs"); | |||||
logFile = logFile.getChildFile (logFileSubDirectoryName) | |||||
.getChildFile (logFileName); | |||||
return File ("~/Library/Logs"); | |||||
#else | #else | ||||
File logFile (File::getSpecialLocation (File::userApplicationDataDirectory)); | |||||
if (logFile.isDirectory()) | |||||
{ | |||||
logFile = logFile.getChildFile (logFileSubDirectoryName) | |||||
.getChildFile (logFileName); | |||||
} | |||||
return File::getSpecialLocation (File::userApplicationDataDirectory); | |||||
#endif | #endif | ||||
} | |||||
return new FileLogger (logFile, welcomeMessage, maxInitialFileSizeBytes); | |||||
FileLogger* FileLogger::createDefaultAppLogger (const String& logFileSubDirectoryName, | |||||
const String& logFileName, | |||||
const String& welcomeMessage, | |||||
const int64 maxInitialFileSizeBytes) | |||||
{ | |||||
return new FileLogger (getSystemLogFileFolder().getChildFile (logFileSubDirectoryName) | |||||
.getChildFile (logFileName), | |||||
welcomeMessage, maxInitialFileSizeBytes); | |||||
} | |||||
FileLogger* FileLogger::createDateStampedLogger (const String& logFileSubDirectoryName, | |||||
const String& logFileNameRoot, | |||||
const String& logFileNameSuffix, | |||||
const String& welcomeMessage) | |||||
{ | |||||
return new FileLogger (getSystemLogFileFolder().getChildFile (logFileSubDirectoryName) | |||||
.getChildFile (logFileNameRoot + Time::getCurrentTime().formatted ("%Y-%m-%d_%H-%M-%S")) | |||||
.withFileExtension (logFileNameSuffix) | |||||
.getNonexistentSibling(), | |||||
welcomeMessage, 0); | |||||
} | } |
@@ -59,47 +59,75 @@ public: | |||||
*/ | */ | ||||
FileLogger (const File& fileToWriteTo, | FileLogger (const File& fileToWriteTo, | ||||
const String& welcomeMessage, | const String& welcomeMessage, | ||||
const int maxInitialFileSizeBytes = 128 * 1024); | |||||
const int64 maxInitialFileSizeBytes = 128 * 1024); | |||||
/** Destructor. */ | /** Destructor. */ | ||||
~FileLogger(); | ~FileLogger(); | ||||
//============================================================================== | //============================================================================== | ||||
void logMessage (const String& message); | |||||
File getLogFile() const { return logFile; } | |||||
/** Returns the file that this logger is writing to. */ | |||||
const File& getLogFile() const noexcept { return logFile; } | |||||
//============================================================================== | //============================================================================== | ||||
/** Helper function to create a log file in the correct place for this platform. | /** Helper function to create a log file in the correct place for this platform. | ||||
On Windows this will return a logger with a path such as: | |||||
c:\\Documents and Settings\\username\\Application Data\\[logFileSubDirectoryName]\\[logFileName] | |||||
On the Mac it'll create something like: | |||||
~/Library/Logs/[logFileName] | |||||
The method might return 0 if the file can't be created for some reason. | |||||
The method might return nullptr if the file can't be created for some reason. | |||||
@param logFileSubDirectoryName if a subdirectory is needed, this is what it will be called - | |||||
it's best to use the something like the name of your application here. | |||||
@param logFileName the name of the file to create, e.g. "MyAppLog.txt". Don't just | |||||
call it "log.txt" because if it goes in a directory with logs | |||||
from other applications (as it will do on the Mac) then no-one | |||||
will know which one is yours! | |||||
@param logFileSubDirectoryName the name of the subdirectory to create inside the logs folder (as | |||||
returned by getSystemLogFileFolder). It's best to use something | |||||
like the name of your application here. | |||||
@param logFileName the name of the file to create, e.g. "MyAppLog.txt". | |||||
@param welcomeMessage a message that will be written to the log when it's opened. | @param welcomeMessage a message that will be written to the log when it's opened. | ||||
@param maxInitialFileSizeBytes (see the FileLogger constructor for more info on this) | @param maxInitialFileSizeBytes (see the FileLogger constructor for more info on this) | ||||
*/ | */ | ||||
static FileLogger* createDefaultAppLogger (const String& logFileSubDirectoryName, | static FileLogger* createDefaultAppLogger (const String& logFileSubDirectoryName, | ||||
const String& logFileName, | const String& logFileName, | ||||
const String& welcomeMessage, | const String& welcomeMessage, | ||||
const int maxInitialFileSizeBytes = 128 * 1024); | |||||
const int64 maxInitialFileSizeBytes = 128 * 1024); | |||||
/** Helper function to create a log file in the correct place for this platform. | |||||
The filename used is based on the root and suffix strings provided, along with a | |||||
time and date string, meaning that a new, empty log file will be always be created | |||||
rather than appending to an exising one. | |||||
The method might return nullptr if the file can't be created for some reason. | |||||
@param logFileSubDirectoryName the name of the subdirectory to create inside the logs folder (as | |||||
returned by getSystemLogFileFolder). It's best to use something | |||||
like the name of your application here. | |||||
@param logFileNameRoot the start of the filename to use, e.g. "MyAppLog_". This will have | |||||
a timestamp and the logFileNameSuffix appended to it | |||||
@param logFileNameSuffix the file suffix to use, e.g. ".txt" | |||||
@param welcomeMessage a message that will be written to the log when it's opened. | |||||
*/ | |||||
static FileLogger* createDateStampedLogger (const String& logFileSubDirectoryName, | |||||
const String& logFileNameRoot, | |||||
const String& logFileNameSuffix, | |||||
const String& welcomeMessage); | |||||
//============================================================================== | |||||
/** Returns an OS-specific folder where log-files should be stored. | |||||
On Windows this will return a logger with a path such as: | |||||
c:\\Documents and Settings\\username\\Application Data\\[logFileSubDirectoryName]\\[logFileName] | |||||
On the Mac it'll create something like: | |||||
~/Library/Logs/[logFileSubDirectoryName]/[logFileName] | |||||
@see createDefaultAppLogger | |||||
*/ | |||||
static File getSystemLogFileFolder(); | |||||
// (implementation of the Logger virtual method) | |||||
void logMessage (const String&); | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
File logFile; | File logFile; | ||||
CriticalSection logLock; | CriticalSection logLock; | ||||
void trimFileSize (int maxFileSizeBytes) const; | |||||
void trimFileSize (int64 maxFileSizeBytes) const; | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileLogger); | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileLogger); | ||||
}; | }; | ||||
@@ -23,25 +23,20 @@ | |||||
============================================================================== | ============================================================================== | ||||
*/ | */ | ||||
Logger::Logger() | |||||
{ | |||||
} | |||||
Logger::Logger() {} | |||||
Logger::~Logger() | Logger::~Logger() | ||||
{ | { | ||||
// You're deleting this logger while it's still being used! | |||||
// Always call Logger::setCurrentLogger (nullptr) before deleting the active logger. | |||||
jassert (currentLogger != this); | |||||
} | } | ||||
//============================================================================== | |||||
Logger* Logger::currentLogger = nullptr; | Logger* Logger::currentLogger = nullptr; | ||||
void Logger::setCurrentLogger (Logger* const newLogger, | |||||
const bool deleteOldLogger) | |||||
void Logger::setCurrentLogger (Logger* const newLogger) noexcept | |||||
{ | { | ||||
Logger* const oldLogger = currentLogger; | |||||
currentLogger = newLogger; | currentLogger = newLogger; | ||||
if (deleteOldLogger) | |||||
delete oldLogger; | |||||
} | } | ||||
void Logger::writeToLog (const String& message) | void Logger::writeToLog (const String& message) | ||||
@@ -53,10 +48,10 @@ void Logger::writeToLog (const String& message) | |||||
} | } | ||||
#if JUCE_LOG_ASSERTIONS | #if JUCE_LOG_ASSERTIONS | ||||
void JUCE_API logAssertion (const char* filename, const int lineNum) noexcept | |||||
void JUCE_API logAssertion (const char* const filename, const int lineNum) noexcept | |||||
{ | { | ||||
String m ("JUCE Assertion failure in "); | String m ("JUCE Assertion failure in "); | ||||
m << filename << ", line " << lineNum; | |||||
m << File (filename).getFileName() << ':' << lineNum; | |||||
Logger::writeToLog (m); | Logger::writeToLog (m); | ||||
} | } | ||||
@@ -51,14 +51,11 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
/** Sets the current logging class to use. | /** Sets the current logging class to use. | ||||
Note that the object passed in won't be deleted when no longer needed. | |||||
Note that the object passed in will not be owned or deleted by the logger, so | |||||
the caller must make sure that it is not deleted while still being used. | |||||
A null pointer can be passed-in to disable any logging. | A null pointer can be passed-in to disable any logging. | ||||
If deleteOldLogger is set to true, the existing logger will be | |||||
deleted (if there is one). | |||||
*/ | */ | ||||
static void JUCE_CALLTYPE setCurrentLogger (Logger* newLogger, | |||||
bool deleteOldLogger = false); | |||||
static void JUCE_CALLTYPE setCurrentLogger (Logger* newLogger) noexcept; | |||||
/** Writes a string to the current logger. | /** Writes a string to the current logger. | ||||
@@ -84,7 +81,6 @@ protected: | |||||
Logger(); | Logger(); | ||||
/** This is overloaded by subclasses to implement custom logging behaviour. | /** This is overloaded by subclasses to implement custom logging behaviour. | ||||
@see setCurrentLogger | @see setCurrentLogger | ||||
*/ | */ | ||||
virtual void logMessage (const String& message) = 0; | virtual void logMessage (const String& message) = 0; | ||||
@@ -103,17 +103,17 @@ File PropertiesFile::Options::getDefaultFile() const | |||||
//============================================================================== | //============================================================================== | ||||
PropertiesFile::PropertiesFile (const File& file_, const Options& options_) | |||||
: PropertySet (options_.ignoreCaseOfKeyNames), | |||||
file (file_), options (options_), | |||||
PropertiesFile::PropertiesFile (const File& f, const Options& o) | |||||
: PropertySet (o.ignoreCaseOfKeyNames), | |||||
file (f), options (o), | |||||
loadedOk (false), needsWriting (false) | loadedOk (false), needsWriting (false) | ||||
{ | { | ||||
initialise(); | initialise(); | ||||
} | } | ||||
PropertiesFile::PropertiesFile (const Options& options_) | |||||
: PropertySet (options_.ignoreCaseOfKeyNames), | |||||
file (options_.getDefaultFile()), options (options_), | |||||
PropertiesFile::PropertiesFile (const Options& o) | |||||
: PropertySet (o.ignoreCaseOfKeyNames), | |||||
file (o.getDefaultFile()), options (o), | |||||
loadedOk (false), needsWriting (false) | loadedOk (false), needsWriting (false) | ||||
{ | { | ||||
initialise(); | initialise(); | ||||