]> vaikene.ee Git - evaf/blobdiff - src/libs/Common/app.cpp
Minor changes
[evaf] / src / libs / Common / app.cpp
index 3956548f4e1656e1c1e7f44d343d0ab89fccec19..b907a4b4ebe05c7749d026a4e52fd9d9a598cb14 100644 (file)
@@ -3,7 +3,7 @@
  * @brief Application interface implementation
  * @author Enar Vaikene
  *
- * Copyright (c) 2011 Enar Vaikene
+ * Copyright (c) 2011-2019 Enar Vaikene
  *
  * This file is part of the eVaf C++ cross-platform application development framework.
  *
@@ -19,8 +19,9 @@
 
 #include "app.h"
 #include "globals.h"
-#include "registry.h"
-#include "ienv.h"
+#include "iregistry.h"
+#include "ieventqueue.h"
+#include "event.h"
 #include "version.h"
 
 #include <QtCore>
 
 using namespace eVaf::Common;
 
+namespace
+{
+    static Internal::App * singleton = nullptr;
+}
+
 iApp * iApp::instance()
 {
-    static Internal::App singleton;
-    return &singleton;
+    if (nullptr == singleton)
+    {
+        singleton = new Internal::App;
+    }
+    return singleton;
 }
 
 char const * const iApp::EV_QUIT = "iApp::quit";
@@ -46,17 +55,31 @@ char const * const iApp::EV_TERMINATING = "iApp::terminating";
 
 using namespace eVaf::Common::Internal;
 
+void App::destroyInstance()
+{
+    if (nullptr != singleton)
+    {
+        delete singleton;
+        singleton = nullptr;
+    }
+}
+
 App::App()
     : iApp()
     , mReady(false)
     , mName(VER_PRODUCT_NAME_STR)
+    , mEvQuit(0)
+    , mEvRestart(0)
+    , mEvReady(0)
+    , mEvTerminating(0)
 {
     setObjectName(QString("%1.iApp").arg(VER_MODULE_NAME_STR));
-
+    EVAF_INFO("%s-App created", VER_MODULE_NAME_STR);
 }
 
 App::~App()
 {
+    EVAF_INFO("%s-App destroyed", VER_MODULE_NAME_STR);
 }
 
 bool App::init()
@@ -64,6 +87,12 @@ bool App::init()
     // Register our interface
     iRegistry::instance()->registerInterface("iApp", this);
 
+    // Register events
+    mEvQuit = iEventQueue::instance()->subscribeEvent(iEventQueue::instance()->registerEvent(EV_QUIT), this);
+    mEvRestart = iEventQueue::instance()->subscribeEvent(iEventQueue::instance()->registerEvent(EV_RESTART), this);
+    mEvReady = iEventQueue::instance()->registerEvent(EV_READY);
+    mEvTerminating = iEventQueue::instance()->registerEvent(EV_TERMINATING);
+
     // Set the default application name and language
     mName = VER_PRODUCT_NAME_STR;
     mLanguage = QLocale::system().name();
@@ -71,6 +100,24 @@ bool App::init()
     // Clear the XML file name
     mXmlFile.clear();
 
+    // Set initial bin and root directories
+    mRootDir = mBinDir = qApp->applicationDirPath();
+    int t = mBinDir.lastIndexOf(QChar('/'), -1);
+    if (t >= 0)
+        mRootDir = mBinDir.left(t);
+
+    if (!mBinDir.endsWith('/'))
+        mBinDir.append('/');
+    if (!mRootDir.endsWith('/'))
+        mRootDir.append('/');
+
+    // Clear other directories
+    mDataRootDir.clear();
+    mQtPluginsDir.clear();
+    mEtcDir.clear();
+    mLogDir.clear();
+    mDocDir.clear();
+
     // Process environment variables
     QStringList env = QProcess::systemEnvironment();
     for (int i = 0; i < env.size(); ++i) {
@@ -82,6 +129,36 @@ bool App::init()
             mName = value;
         else if (name == "EVAF_LANGUAGE")
             mLanguage = value;
+        else if (name == "EVAF_ROOT_DIR") {
+            mRootDir = value;
+            if (!mRootDir.endsWith('/'))
+                mRootDir.append('/');
+        }
+        else if (name == "EVAF_DATA_ROOT_DIR") {
+            mDataRootDir = value;
+            if (!mDataRootDir.endsWith('/'))
+                mDataRootDir.append('/');
+        }
+        else if (name == "EVAF_ETC_DIR") {
+            mEtcDir = value;
+            if (!mEtcDir.endsWith('/'))
+                mEtcDir.append('/');
+        }
+        else if (name == "EVAF_LOG_DIR") {
+            mLogDir = value;
+            if (!mLogDir.endsWith('/'))
+                mLogDir.append('/');
+        }
+        else if (name == "EVAF_DOC_DIR") {
+            mDocDir = value;
+            if (!mDocDir.endsWith('/'))
+                mDocDir.append('/');
+        }
+        else if (name == "EVAF_QT_PLUGINS_DIR") {
+            mQtPluginsDir = value;
+            if (!mQtPluginsDir.endsWith('/'))
+                mQtPluginsDir.append('/');
+        }
     }
 
     // Then process command-line arguments
@@ -94,11 +171,103 @@ bool App::init()
             mName = arg.at(1);
         else if (QRegExp("-[-]?lang(uage)?").exactMatch(arg.at(0)) && arg.size() > 1)
             mLanguage = arg.at(1);
+        else if (QRegExp("-[-]?root(dir)?").exactMatch(arg.at(0)) && arg.size() > 1) {
+            mRootDir = arg.at(1);
+            if (!mRootDir.endsWith('/'))
+                mRootDir.append('/');
+        }
+        else if (QRegExp("-[-]?dataroot(dir)?").exactMatch(arg.at(0)) && arg.size() > 1) {
+            mDataRootDir = arg.at(1);
+            if (!mDataRootDir.endsWith('/'))
+                mDataRootDir.append('/');
+        }
+        else if (QRegExp("-[-]?etc(dir)?").exactMatch(arg.at(0)) && arg.size() > 1) {
+            mEtcDir = arg.at(1);
+            if (!mEtcDir.endsWith('/'))
+                mEtcDir.append('/');
+        }
+        else if (QRegExp("-[-]?log(dir)?").exactMatch(arg.at(0)) && arg.size() > 1) {
+            mLogDir = arg.at(1);
+            if (!mLogDir.endsWith('/'))
+                mLogDir.append('/');
+        }
+        else if (QRegExp("-[-]?doc(dir)?").exactMatch(arg.at(0)) && arg.size() > 1) {
+            mDocDir = arg.at(1);
+            if (!mDocDir.endsWith('/'))
+                mDocDir.append('/');
+        }
+        else if (QRegExp("-[-]?qtplugins(dir)?").exactMatch(arg.at(0)) && arg.size() > 1) {
+            mQtPluginsDir = arg.at(1);
+            if (!mQtPluginsDir.endsWith('/'))
+                mQtPluginsDir.append('/');
+        }
     }
 
     return true;
 }
 
+bool App::event(QEvent * e)
+{
+    if (e->type() == Event::eVafEvent) {
+        Event * event = static_cast<Event *>(e);
+        if (event->id() == mEvQuit)
+            quit();
+        else if (event->id() == mEvRestart)
+            restart();
+
+        return false;
+    }
+    else
+        return iApp::event(e);
+}
+
+QString const App::dataRootDir() const
+{
+    if (mDataRootDir.isEmpty()) {
+#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
+        QString dataLoc = QDir::homePath();
+        if (!dataLoc.endsWith('/'))
+            dataLoc.append('/');
+        dataLoc.append(".local/share/data/");
+        mDataRootDir = dataLoc + name();
+        if (!mDataRootDir.endsWith('/'))
+            mDataRootDir.append('/');
+#endif
+        /// @TODO: Needs local data directory on Windows
+        mDataRootDir = rootDir();
+    }
+
+    return mDataRootDir;
+}
+
+QString const App::etcDir() const
+{
+    if (mEtcDir.isEmpty())
+        mEtcDir = dataRootDir() + "etc/";
+    return mEtcDir;
+}
+
+QString const App::logDir() const
+{
+    if (mLogDir.isEmpty())
+        mLogDir = dataRootDir() + "log/";
+    return mLogDir;
+}
+
+QString const App::docDir() const
+{
+    if (mDocDir.isEmpty())
+        mDocDir = rootDir() + "doc/";
+    return mDocDir;
+}
+
+QString const App::qtPluginsDir() const
+{
+    if (mQtPluginsDir.isEmpty())
+        mQtPluginsDir = binDir();
+    return mQtPluginsDir;
+}
+
 QString const App::xmlFileName() const
 {
     if (mXmlFile.isEmpty()) {
@@ -106,13 +275,13 @@ QString const App::xmlFileName() const
 
         // Try the full application name + country + language combination
         QString name = mName + "_" + mLanguage + ".xml";
-        fi.setFile(iEnv::instance()->etcDir() + name);
+        fi.setFile(etcDir() + name);
         if (fi.isReadable())
             mXmlFile = name;
         else {
             // Try application name + country
             name = mName + "_" + mLanguage.left(2) + ".xml";
-            fi.setFile(iEnv::instance()->etcDir() + name);
+            fi.setFile(etcDir() + name);
             if (fi.isReadable())
                 mXmlFile = name;
             else
@@ -123,6 +292,14 @@ QString const App::xmlFileName() const
     return mXmlFile;
 }
 
+int App::exec()
+{
+    setReady(true);
+    int const rval = QCoreApplication::exec();
+    setReady(false);
+    return rval;
+}
+
 void App::restart()
 {
     QCoreApplication::exit(RC_Restart);
@@ -132,3 +309,15 @@ void App::quit(bool err)
 {
     QCoreApplication::exit(err ? RC_Error : RC_Quit);
 }
+
+void App::setReady(bool value)
+{
+    if (mReady != value) {
+        mReady = value;
+        iEventQueue::instance()->broadcastEvent(new Event(mReady ? mEvReady : mEvTerminating));
+        if (mReady)
+            emit ready();
+        else
+            emit terminating();
+    }
+}