diff --git a/MUtilities_VS2013.vcxproj b/MUtilities_VS2013.vcxproj
index b8a2f87..b651360 100644
--- a/MUtilities_VS2013.vcxproj
+++ b/MUtilities_VS2013.vcxproj
@@ -33,6 +33,7 @@
+
@@ -50,6 +51,7 @@
+
@@ -149,6 +151,9 @@
NoExtensions
$(ProjectDir)\include;$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(SolutionDir)\..\Prerequisites\VisualLeakDetector\include;%(AdditionalIncludeDirectories)
true
+ Disabled
+ Default
+ ProgramDatabase
Windows
diff --git a/MUtilities_VS2013.vcxproj.filters b/MUtilities_VS2013.vcxproj.filters
index 3778c5d..05c2d70 100644
--- a/MUtilities_VS2013.vcxproj.filters
+++ b/MUtilities_VS2013.vcxproj.filters
@@ -87,6 +87,9 @@
Source Files
+
+ Source Files
+
@@ -149,6 +152,9 @@
Public Headers
+
+ Public Headers
+
diff --git a/include/MUtils/Startup.h b/include/MUtils/Startup.h
index 0a30ba5..ad7699c 100644
--- a/include/MUtils/Startup.h
+++ b/include/MUtils/Startup.h
@@ -24,6 +24,9 @@
//MUtils
#include
+//Forward Declarations
+class QApplication;
+
///////////////////////////////////////////////////////////////////////////////
namespace MUtils
@@ -37,7 +40,7 @@ namespace MUtils
MUTILS_API int startup(int &argc, char **argv, main_function_t *const entry_point, const bool &debugConsole);
//Initialize Qt
- MUTILS_API bool init_qt(int &argc, char **argv, const QString &appName);
+ MUTILS_API QApplication *create_qt(int &argc, char **argv, const QString &appName);
}
}
diff --git a/include/MUtils/Translation.h b/include/MUtils/Translation.h
new file mode 100644
index 0000000..67fe8a5
--- /dev/null
+++ b/include/MUtils/Translation.h
@@ -0,0 +1,56 @@
+///////////////////////////////////////////////////////////////////////////////
+// MuldeR's Utilities for Qt
+// Copyright (C) 2004-2014 LoRd_MuldeR
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+// http://www.gnu.org/licenses/lgpl-2.1.txt
+//////////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+//MUtils
+#include
+
+//Qt
+#include
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace MUtils
+{
+ namespace Translation
+ {
+ //Register new translation
+ MUTILS_API bool insert(const QString &langId, const QString &qmFile, const QString &langName, const quint32 &systemId, const quint32 &country);
+
+ //Enumerate translations
+ MUTILS_API int enumerate(QStringList &list);
+
+ //Get translation info
+ MUTILS_API QString get_name (const QString &langId);
+ MUTILS_API quint32 get_sysid (const QString &langId);
+ MUTILS_API quint32 get_country(const QString &langId);
+
+ //Install translator
+ MUTILS_API bool install_translator(const QString &langId);
+ MUTILS_API bool install_translator_from_file(const QString &qmFile);
+
+ //Constant
+ MUTILS_API extern const char *const DEFAULT_LANGID;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/DLLMain.cpp b/src/DLLMain.cpp
index 7c94ca8..71f9ec2 100644
--- a/src/DLLMain.cpp
+++ b/src/DLLMain.cpp
@@ -31,11 +31,11 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
+ case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
break;
- }
+ };
return TRUE;
}
diff --git a/src/DirLocker.h b/src/DirLocker.h
index f4a683f..ceb94f5 100644
--- a/src/DirLocker.h
+++ b/src/DirLocker.h
@@ -56,16 +56,16 @@ namespace MUtils
:
m_dirPath(dirPath)
{
+ bool okay = false;
+ const QByteArray testData = QByteArray(TEST_DATA);
if(m_dirPath.isEmpty())
{
throw DirLockException("Path must not be empty!");
}
- const QByteArray testData = QByteArray(TEST_DATA);
- bool okay = false;
for(int i = 0; i < 32; i++)
{
m_lockFile.reset(new QFile(QString("%1/~%2.lck").arg(m_dirPath, MUtils::rand_str())));
- if(m_lockFile->open(QIODevice::WriteOnly | QIODevice::Truncate))
+ if(m_lockFile->open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Unbuffered))
{
if(m_lockFile->write(testData) >= testData.size())
{
@@ -83,20 +83,34 @@ namespace MUtils
~DirLock(void)
{
+ bool okay = false;
if(!m_lockFile.isNull())
{
- m_lockFile->remove();
+ for(int i = 0; i < 8; i++)
+ {
+ if(m_lockFile->remove())
+ {
+ break;
+ }
+ OS::sleep_ms(1);
+ }
}
for(int i = 0; i < 8; i++)
{
if(MUtils::remove_directory(m_dirPath))
{
+ okay = true;
break;
}
+ OS::sleep_ms(1);
+ }
+ if(!okay)
+ {
+ OS::system_message_wrn(L"Directory Lock", L"Warning: Not all temporary files could be removed!");
}
}
- inline const QString &path(void) const
+ inline const QString &getPath(void) const
{
return m_dirPath;
}
diff --git a/src/ErrorHandler_Win32.cpp b/src/ErrorHandler_Win32.cpp
index cdbb2e4..76208ef 100644
--- a/src/ErrorHandler_Win32.cpp
+++ b/src/ErrorHandler_Win32.cpp
@@ -19,8 +19,6 @@
// http://www.gnu.org/licenses/lgpl-2.1.txt
//////////////////////////////////////////////////////////////////////////////////
-#pragma once
-
//MUtils
#include
#include
diff --git a/src/GUI_Win32.cpp b/src/GUI_Win32.cpp
index 66bf78b..591a9cd 100644
--- a/src/GUI_Win32.cpp
+++ b/src/GUI_Win32.cpp
@@ -46,7 +46,7 @@ static QReadWriteLock g_themes_lock;
static bool g_themes_initialized = false;
static bool g_themes_enabled = false;
-typedef int (WINAPI *IsAppThemedFunction)(void);
+typedef int (WINAPI IsAppThemedFunction)(void);
bool MUtils::GUI::themes_enabled(void)
{
@@ -68,18 +68,16 @@ bool MUtils::GUI::themes_enabled(void)
const MUtils::OS::Version::os_version_t &osVersion = MUtils::OS::os_version();
if(osVersion >= MUtils::OS::Version::WINDOWS_WINXP)
{
- IsAppThemedFunction IsAppThemedPtr = NULL;
QLibrary uxTheme("UxTheme.dll");
if(uxTheme.load())
{
- IsAppThemedPtr = (IsAppThemedFunction) uxTheme.resolve("IsAppThemed");
- }
- if(IsAppThemedPtr)
- {
- g_themes_enabled = IsAppThemedPtr();
- if(!g_themes_enabled)
+ if(IsAppThemedFunction *const IsAppThemedPtr = (IsAppThemedFunction*) uxTheme.resolve("IsAppThemed"))
{
- qWarning("Theme support is disabled for this process!");
+ g_themes_enabled = IsAppThemedPtr();
+ if(!g_themes_enabled)
+ {
+ qWarning("Theme support is disabled for this process!");
+ }
}
}
}
diff --git a/src/Global.cpp b/src/Global.cpp
index 96d60e2..6c4be19 100644
--- a/src/Global.cpp
+++ b/src/Global.cpp
@@ -43,7 +43,9 @@
#include
//VLD
+#ifdef _MSC_VER
#include
+#endif
///////////////////////////////////////////////////////////////////////////////
// Random Support
@@ -112,7 +114,7 @@ QString MUtils::rand_str(const bool &bLong)
///////////////////////////////////////////////////////////////////////////////
static QScopedPointer g_temp_folder_file;
-static QReadWriteLock g_temp_folder_lock;
+static QReadWriteLock g_temp_folder_lock;
static QString try_create_subfolder(const QString &baseDir, const QString &postfix)
{
@@ -150,6 +152,17 @@ static MUtils::Internal::DirLock *try_init_temp_folder(const QString &baseDir)
return NULL;
}
+static void temp_folder_cleaup(void)
+{
+ QWriteLocker writeLock(&g_temp_folder_lock);
+
+ //Clean the directory
+ while(!g_temp_folder_file.isNull())
+ {
+ g_temp_folder_file.reset(NULL);
+ }
+}
+
const QString &MUtils::temp_folder(void)
{
QReadLocker readLock(&g_temp_folder_lock);
@@ -157,7 +170,7 @@ const QString &MUtils::temp_folder(void)
//Already initialized?
if(!g_temp_folder_file.isNull())
{
- return g_temp_folder_file->path();
+ return g_temp_folder_file->getPath();
}
//Obtain the write lock to initilaize
@@ -167,14 +180,15 @@ const QString &MUtils::temp_folder(void)
//Still uninitilaized?
if(!g_temp_folder_file.isNull())
{
- return g_temp_folder_file->path();
+ return g_temp_folder_file->getPath();
}
//Try the %TMP% or %TEMP% directory first
if(MUtils::Internal::DirLock *lockFile = try_init_temp_folder(QDir::tempPath()))
{
g_temp_folder_file.reset(lockFile);
- return lockFile->path();
+ atexit(temp_folder_cleaup);
+ return lockFile->getPath();
}
qWarning("%%TEMP%% directory not found -> trying fallback mode now!");
@@ -190,7 +204,8 @@ const QString &MUtils::temp_folder(void)
if(MUtils::Internal::DirLock *lockFile = try_init_temp_folder(tempRoot))
{
g_temp_folder_file.reset(lockFile);
- return lockFile->path();
+ atexit(temp_folder_cleaup);
+ return lockFile->getPath();
}
}
}
diff --git a/src/OSSupport_Win32.cpp b/src/OSSupport_Win32.cpp
index a875e3d..f47590d 100644
--- a/src/OSSupport_Win32.cpp
+++ b/src/OSSupport_Win32.cpp
@@ -19,8 +19,6 @@
// http://www.gnu.org/licenses/lgpl-2.1.txt
//////////////////////////////////////////////////////////////////////////////////
-#pragma once
-
//Win32 API
#define WIN32_LEAN_AND_MEAN 1
#include
diff --git a/src/Startup.cpp b/src/Startup.cpp
index e06c464..50e7015 100644
--- a/src/Startup.cpp
+++ b/src/Startup.cpp
@@ -125,20 +125,19 @@ int MUtils::Startup::startup(int &argc, char **argv, main_function_t *const entr
// QT INITIALIZATION
///////////////////////////////////////////////////////////////////////////////
-static QMutex g_qt_lock;
-static QScopedPointer g_application;
-
+static QMutex g_init_lock;
static const char *const g_imageformats[] = {"bmp", "png", "jpg", "gif", "ico", "xpm", "svg", NULL};
-bool MUtils::Startup::init_qt(int &argc, char **argv, const QString &appName)
+QApplication *MUtils::Startup::create_qt(int &argc, char **argv, const QString &appName)
{
- QMutexLocker lock(&g_qt_lock);
+ QMutexLocker lock(&g_init_lock);
const QStringList &arguments = MUtils::OS::arguments();
//Don't initialized again, if done already
- if(!g_application.isNull())
+ if(QApplication::instance() != NULL)
{
- return true;
+ qWarning("Qt is already initialized!");
+ return NULL;
}
//Extract executable name from argv[] array
@@ -205,7 +204,7 @@ bool MUtils::Startup::init_qt(int &argc, char **argv, const QString &appName)
if(!arguments.contains("--ignore-compat-mode", Qt::CaseInsensitive))
{
qFatal("%s", QApplication::tr("Executable '%1' doesn't support Windows compatibility mode.").arg(executableName).toLatin1().constData());
- return false;
+ return NULL;
}
}
@@ -219,17 +218,17 @@ bool MUtils::Startup::init_qt(int &argc, char **argv, const QString &appName)
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
//Create Qt application instance
- g_application.reset(new QApplication(argc, argv));
+ QApplication *application = new QApplication(argc, argv);
//Load plugins from application directory
QCoreApplication::setLibraryPaths(QStringList() << QApplication::applicationDirPath());
qDebug("Library Path:\n%s\n", MUTILS_UTF8(QApplication::libraryPaths().first()));
//Set application properties
- g_application->setApplicationName(appName);
- g_application->setOrganizationName("LoRd_MuldeR");
- g_application->setOrganizationDomain("mulder.at.gg");
- g_application->setEventFilter(qt_event_filter);
+ application->setApplicationName(appName);
+ application->setOrganizationName("LoRd_MuldeR");
+ application->setOrganizationDomain("mulder.at.gg");
+ application->setEventFilter(qt_event_filter);
//Check for supported image formats
QList supportedFormats = QImageReader::supportedImageFormats();
@@ -238,7 +237,8 @@ bool MUtils::Startup::init_qt(int &argc, char **argv, const QString &appName)
if(!supportedFormats.contains(g_imageformats[i]))
{
qFatal("Qt initialization error: QImageIOHandler for '%s' missing!", g_imageformats[i]);
- return false;
+ MUTILS_DELETE(application);
+ return NULL;
}
}
@@ -254,9 +254,9 @@ bool MUtils::Startup::init_qt(int &argc, char **argv, const QString &appName)
if(!qFuzzyCompare(fontScaleFactor, 1.0))
{
qWarning("Application font scale factor set to: %.3f\n", fontScaleFactor);
- QFont appFont = g_application->font();
+ QFont appFont = application->font();
appFont.setPointSizeF(appFont.pointSizeF() * fontScaleFactor);
- g_application->setFont(appFont);
+ application->setFont(appFont);
}
//Check for process elevation
@@ -267,12 +267,14 @@ bool MUtils::Startup::init_qt(int &argc, char **argv, const QString &appName)
messageBox.addButton("Ignore", QMessageBox::NoRole);
if(messageBox.exec() == 0)
{
+ MUTILS_DELETE(application);
return NULL;
}
}
- //Successful
- return g_application.data();
+ //Qt created successfully
+ return application;
}
///////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/Terminal_Win32.cpp b/src/Terminal_Win32.cpp
index f46ab57..9f1b404 100644
--- a/src/Terminal_Win32.cpp
+++ b/src/Terminal_Win32.cpp
@@ -25,7 +25,6 @@
#define WIN32_LEAN_AND_MEAN 1
#include
-
//Internal
#include
#include
@@ -162,7 +161,7 @@ void MUtils::Terminal::setup(int &argc, char **argv, const bool forceEnabled)
g_terminal_attached = true;
}
}
-
+
if(g_terminal_attached)
{
//-------------------------------------------------------------------
@@ -184,6 +183,7 @@ void MUtils::Terminal::setup(int &argc, char **argv, const bool forceEnabled)
*stderr = *hfStdErr;
g_filebufStdErr.reset(new std::filebuf(hfStdErr));
std::cerr.rdbuf(g_filebufStdErr.data());
+ std::cerr.rdbuf(new std::filebuf(hfStdErr));
}
const HWND hwndConsole = GetConsoleWindow();
diff --git a/src/Translation.cpp b/src/Translation.cpp
new file mode 100644
index 0000000..a1b20ee
--- /dev/null
+++ b/src/Translation.cpp
@@ -0,0 +1,205 @@
+///////////////////////////////////////////////////////////////////////////////
+// MuldeR's Utilities for Qt
+// Copyright (C) 2004-2014 LoRd_MuldeR
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+// http://www.gnu.org/licenses/lgpl-2.1.txt
+//////////////////////////////////////////////////////////////////////////////////
+
+//MUtils
+#include
+
+//Qt
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//////////////////////////////////////////////////////////////////////////////////
+// TYPES
+//////////////////////////////////////////////////////////////////////////////////
+
+typedef QPair translation_info_t;
+typedef QPair translation_data_t;
+
+typedef QPair translation_entry_t;
+typedef QMap translation_store_t;
+
+#define MAKE_ENTRY(NAME,PATH,SYSID,CNTRY) \
+ qMakePair(qMakePair((NAME),(PATH)),qMakePair((SYSID),(CNTRY)))
+
+//////////////////////////////////////////////////////////////////////////////////
+// TRANSLATIONS STORE
+//////////////////////////////////////////////////////////////////////////////////
+
+static QReadWriteLock g_translation_lock;
+static QScopedPointer g_translation_data;
+static QScopedPointer g_translation_inst;
+
+//////////////////////////////////////////////////////////////////////////////////
+// CONSTANT
+//////////////////////////////////////////////////////////////////////////////////
+
+namespace MUtils
+{
+ namespace Translation
+ {
+ const char *const DEFAULT_LANGID = "en";
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// REGISTER TRANSLATION
+//////////////////////////////////////////////////////////////////////////////////
+
+bool MUtils::Translation::insert(const QString &langId, const QString &qmFile, const QString &langName, const quint32 &systemId, const quint32 &country)
+{
+ QWriteLocker writeLockTranslations(&g_translation_lock);
+
+ const QString key = langId.simplified().toLower();
+ if(key.isEmpty() || qmFile.isEmpty() || langName.isEmpty() || (systemId < 1))
+ {
+ return false;
+ }
+
+ if(g_translation_data.isNull())
+ {
+ g_translation_data.reset(new translation_store_t());
+ }
+
+ if(g_translation_data->contains(key))
+ {
+ qWarning("Translation store already contains entry for '%s', going to replace!", MUTILS_UTF8(key));
+ }
+
+ g_translation_data->insert(key, MAKE_ENTRY(langName, qmFile, systemId, country));
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// GET TRANSLATION INFO
+//////////////////////////////////////////////////////////////////////////////////
+
+int MUtils::Translation::enumerate(QStringList &list)
+{
+ QReadLocker readLockTranslations(&g_translation_lock);
+
+ if(g_translation_data.isNull())
+ {
+ list.clear();
+ return -1;
+ }
+
+ list.swap(g_translation_data->keys());
+ return list.count();
+}
+
+QString MUtils::Translation::get_name(const QString &langId)
+{
+ QReadLocker readLockTranslations(&g_translation_lock);
+
+ const QString key = langId.simplified().toLower();
+ if(key.isEmpty() || g_translation_data.isNull() || (!g_translation_data->contains(key)))
+ {
+ return QString();
+ }
+
+ return (*g_translation_data)[key].first.first;
+}
+
+quint32 MUtils::Translation::get_sysid(const QString &langId)
+{
+ QReadLocker readLockTranslations(&g_translation_lock);
+
+ const QString key = langId.simplified().toLower();
+ if(key.isEmpty() || g_translation_data.isNull() || (!g_translation_data->contains(key)))
+ {
+ return 0;
+ }
+
+ return (*g_translation_data)[key].second.first;
+}
+
+quint32 MUtils::Translation::get_country(const QString &langId)
+{
+ QReadLocker readLockTranslations(&g_translation_lock);
+ const QString key = langId.simplified().toLower();
+ if(key.isEmpty() || g_translation_data.isNull() || (!g_translation_data->contains(key)))
+ {
+ return 0;
+ }
+
+ return (*g_translation_data)[key].second.second;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// INSTALL TRANSLATION
+//////////////////////////////////////////////////////////////////////////////////
+
+bool MUtils::Translation::install_translator(const QString &langId)
+{
+ QReadLocker readLockTranslations(&g_translation_lock);
+
+ const QString key = langId.simplified().toLower();
+ if(key.isEmpty() || g_translation_data.isNull() || (!g_translation_data->contains(key)))
+ {
+ return false;
+ }
+
+ const QString qmFile = (*g_translation_data)[key].first.second;
+ readLockTranslations.unlock();
+ return install_translator_from_file(qmFile);
+}
+
+bool MUtils::Translation::install_translator_from_file(const QString &qmFile)
+{
+ QWriteLocker writeLock(&g_translation_lock);
+
+ if(g_translation_inst.isNull())
+ {
+ g_translation_inst.reset(new QTranslator());
+ }
+
+ if(qmFile.isEmpty())
+ {
+ QApplication::removeTranslator(g_translation_inst.data());
+ return true;
+ }
+
+ const QFileInfo qmFileInfo(qmFile);
+ if(!(qmFileInfo.exists() && qmFileInfo.isFile()))
+ {
+ qWarning("Translation file not found:\n\"%s\"", MUTILS_UTF8(qmFile));
+ return false;
+ }
+
+ const QString qmPath = QFileInfo(qmFile).canonicalFilePath();
+ if(!qmPath.isEmpty())
+ {
+ QApplication::removeTranslator(g_translation_inst.data());
+ if(g_translation_inst->load(qmPath))
+ {
+ QApplication::installTranslator(g_translation_inst.data());
+ return true;
+ }
+ }
+
+ qWarning("Failed to load translation:\n\"%s\"", MUTILS_UTF8(qmFile));
+ return false;
+}
diff --git a/src/Version.cpp b/src/Version.cpp
index 5c3d9d8..d31a933 100644
--- a/src/Version.cpp
+++ b/src/Version.cpp
@@ -19,14 +19,14 @@
// http://www.gnu.org/licenses/lgpl-2.1.txt
//////////////////////////////////////////////////////////////////////////////////
-#define MUTILS_INC_CONFIG 1
-
+//MUtils
#include
-
-//Internal
#include
#include
#include
+
+//Internal
+#define MUTILS_INC_CONFIG 1
#include "Config.h"
///////////////////////////////////////////////////////////////////////////////