Multiple interface and functionality improvements

- Enable start of the control center after login
- Enable start of the bundled NFD when the center starts
- Slightly refactored implementation of how ndn-autoconfig starting is
  handled
- Add ability to stop NFD when the center stops

Change-Id: Ieb19b8c0a3e75a5a91961e87c8ccffad364d5170
diff --git a/src/main.qml b/src/main.qml
index 7ef1990..b051c6c 100644
--- a/src/main.qml
+++ b/src/main.qml
@@ -40,14 +40,27 @@
                         anchors.rightMargin: 10
                         CheckBox {
                             id: startOnLogin
-                            enabled: false
-                            text: "Automatically start NFD Control Center on login"
+                            text: "Launch NFD Control Center on login"
+                            checked: trayModel.isNccAutoStartEnabled()
+                            onCheckedChanged: trayModel.enableDisableNccAutoStart(this.checked)
+                        }
+                        CheckBox {
+                            id: autoStart
+                            text: "Automatically start NFD"
+                            checked: trayModel.isNfdAutoStartEnabled()
+                            onCheckedChanged: trayModel.enableDisableNfdAutoStart(this.checked)
                         }
                         CheckBox {
                             id: autoConfig
                             text: "Automatically start NDN auto configuration"
-                            checked: trayModel.isAutoConfigEnabled()
-                            onCheckedChanged: trayModel.startStopAutoConfig(this.checked)
+                            checked: trayModel.isNdnAutoConfigEnabled()
+                            onCheckedChanged: trayModel.enableDisableNdnAutoConfig(this.checked)
+                        }
+                        CheckBox {
+                            id: shutdownOnQuit
+                            text: "Shutdown NFD daemon on quit"
+                            checked: trayModel.isNfdStopOnExitEnabled()
+                            onCheckedChanged: trayModel.enableDisableNfdStopOnExit(this.checked)
                         }
                     }
                 }
@@ -78,20 +91,6 @@
                         }
                     }
                 }
-                Button {
-                    id: startStopButton
-                    text: startStopButtonText
-
-                    anchors.top: status.bottom
-                    anchors.left: parent.left
-                    anchors.right: parent.right
-                    anchors.topMargin: 20
-                    anchors.leftMargin: 20
-                    anchors.rightMargin: 20
-                    anchors.bottomMargin: 20
-
-                    onClicked: trayModel.startStopNfd(autoConfig.checked)
-                }
             }
         }
         // Tab {
@@ -144,14 +143,14 @@
         Tab {
             title: "Auto-config status"
             TextArea {
-                id: autoConfigText
+                id: ndnAutoConfigTextId
                 anchors.fill: parent
                 anchors.topMargin: 20
                 anchors.bottomMargin: 20
                 anchors.leftMargin: 20
                 anchors.rightMargin: 20
                 readOnly: true
-                text: acText
+                text: ndnAutoConfigText
             }
         }
         Tab {
diff --git a/src/tray-menu.cpp b/src/tray-menu.cpp
index 2ec3cb4..9bcdaa4 100644
--- a/src/tray-menu.cpp
+++ b/src/tray-menu.cpp
@@ -20,8 +20,12 @@
 #include "tray-menu.hpp"
 #include "tray-menu.moc"
 
+#include <chrono>
+#include <functional>
+
 #include <ndn-cxx/face.hpp>
 #include <ndn-cxx/interest.hpp>
+#include <boost/algorithm/string/replace.hpp>
 
 #ifdef OSX_BUILD
 #define CONNECT_ICON ":/res/icon-connected-black.png"
@@ -37,13 +41,22 @@
 namespace ndn {
 namespace ncc {
 
+/**
+ * @brief Maximum number of lines that can show up in auto-config status tab view
+ */
+const int MAX_LINES_IN_AUTOCONF_STATUS = 100;
+
+#ifdef OSX_BUILD
+const QString AUTO_START_SUFFIX = "Library/LaunchAgents/net.named-data.control-center.plist";
+#endif // OSX_BUILD
+
 TrayMenu::TrayMenu(QQmlContext* context, Face& face)
   : m_context(context)
   , m_isNfdRunning(false)
   , m_menu(new QMenu(this))
   , m_entryPref(new QAction("Preferences...", m_menu))
   , m_entrySec(new QAction("Security...", m_menu))
-  , m_acProc(new QProcess())
+  , m_acProc(nullptr)
   , m_settings(new QSettings())
 #ifdef OSX_BUILD
   , m_entryEnableCli(new QAction("Enable Command Terminal Usage...", m_menu))
@@ -55,18 +68,15 @@
   , m_face(face)
 {
   connect(m_entryPref, SIGNAL(triggered()), this, SIGNAL(showApp()));
-  connect(this, SIGNAL(showApp()), this, SLOT(showPref()));
   connect(m_entrySec, SIGNAL(triggered()), m_keyViewerDialog, SLOT(present()));
   connect(m_entryQuit, SIGNAL(triggered()), this, SLOT(quitApp()));
 
   connect(this, SIGNAL(nfdActivityUpdate(bool)), this, SLOT(updateNfdActivityIcon(bool)),
           Qt::QueuedConnection);
 
-  m_context->setContextProperty("startStopButtonText", QVariant::fromValue(QString("Start NFD")));
-  m_context->setContextProperty("acText", QVariant::fromValue(QString("")));
-
   m_menu->addAction(m_entryPref);
   m_menu->addAction(m_entrySec);
+
 #ifdef OSX_BUILD
   connect(m_entryEnableCli, SIGNAL(triggered()), this, SLOT(enableCli()));
   m_menu->addAction(m_entryEnableCli);
@@ -74,156 +84,85 @@
   connect(m_checkForUpdates, SIGNAL(triggered()), this, SLOT(checkForUpdates()));
   m_menu->addAction(m_checkForUpdates);
 #endif
+
   m_menu->addAction(m_entryQuit);
   m_tray = new QSystemTrayIcon(this);
   m_tray->setContextMenu(m_menu);
-  connect(m_tray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
-          this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
   m_tray->setIcon(QIcon(DISCONNECT_ICON));
   m_tray->show();
-  if (isAutoConfigEnabled()) {
-    stopAutoConfig(); // Make sure no more than one auto-config process exist
-    QTimer* mTimer = new QTimer(this);
-    mTimer->setSingleShot(true);
-    connect(mTimer, SIGNAL(timeout()), SLOT(startAutoConfig()));
-    mTimer->start(2000);
+
+  // delaying for the case when NFD is already started (to avoid starting / to avoid starting autoconfig
+  if (isNfdAutoStartEnabled()) {
+    scheduleDelayedTask(std::chrono::seconds(5), [this] {
+        if (!m_isNfdRunning) {
+          startNfd();
+        }
+      });
   }
 }
 
 TrayMenu::~TrayMenu()
 {
+  // delete for all new's
 }
 
-void
-TrayMenu::appendMsg(QString &target, QString source)
-{
-  int maxLine = 100; // Max line that will show in auto-config status tab view
-  if (target.count(QString("\n")) > maxLine) { // Only when target QString has more line than maxLine, it needs remove line
-    int end = target.indexOf(QString("\n"));
-    target.remove(0, end + 1); // Remove the first line of target
-  }
-  target.append(source);
-}
-
-void
-TrayMenu::showPref()
-{
-  m_context->setContextProperty("acText", QVariant::fromValue(m_autoConfigMsg)); // Update auto-config status tab view
-}
-
-void
-TrayMenu::processOutput()
-{
-  std::string msg = m_acProc->readAllStandardOutput().toStdString();
-  if (msg != "") {
-    appendMsg(m_autoConfigMsg, QString::fromStdString(msg));
-  }
-  msg = m_acProc->readAllStandardError().toStdString();
-  if (msg != "") {
-    appendMsg(m_autoConfigMsg, QString::fromStdString(msg));
-  }
-  m_context->setContextProperty("acText", QVariant::fromValue(m_autoConfigMsg));
-}
+////////////////////////////////////////////////////////////////////////////////
+// NFD Control Center start on login
 
 Q_INVOKABLE bool
-TrayMenu::isAutoConfigEnabled()
+TrayMenu::isNccAutoStartEnabled() const
 {
-  bool sAutoConfig = m_settings.value("main/auto-config", QVariant(false)).toBool();
-  return sAutoConfig;
-}
-
-void
-TrayMenu::startAutoConfig()
-{
-  if (m_isNfdRunning) {
-    appendMsg(m_autoConfigMsg, QString("NDN auto configuration will start...\n"));
-    connect(m_acProc, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()));
-    connect(m_acProc, SIGNAL(readyReadStandardError()), this, SLOT(processOutput()));
-    m_acProc->start((QCoreApplication::applicationDirPath().toStdString() + "/../Platform/ndn-autoconfig").c_str(),
-                      QStringList()
-                        << "--daemon");
-  }
-}
-
-void
-TrayMenu::stopAutoConfig()
-{
-#ifdef OSX_BUILD
-  QProcess* proc = new QProcess();
-  connect(proc, SIGNAL(finished(int)), proc, SLOT(deleteLater()));
-  proc->startDetached("killall", QStringList() << "ndn-autoconfig");
-#endif
+  QFileInfo file(QDir::home().path() + "/" + AUTO_START_SUFFIX);
+  return file.exists() && file.isFile();
 }
 
 Q_INVOKABLE void
-TrayMenu::startStopAutoConfig(bool autoConfig)
+TrayMenu::enableDisableNccAutoStart(bool isEnabled)
 {
-  if (m_isNfdRunning) {
-    if (autoConfig) {
-      stopAutoConfig(); // Make sure no more than one auto-config process exist
-      QTimer* mTimer = new QTimer(this);
-      mTimer->setSingleShot(true);
-      connect(mTimer, SIGNAL(timeout()), SLOT(startAutoConfig()));
-      mTimer->start(2000);
-      m_context->setContextProperty("acText", QVariant::fromValue(m_autoConfigMsg));
-      m_settings.setValue("main/auto-config", true);
-    }
-    else {
-      stopAutoConfig();
-      appendMsg(m_autoConfigMsg, QString("NDN auto configuration will be stopped!\n"));
-      m_context->setContextProperty("acText", QVariant::fromValue(m_autoConfigMsg));
-      m_settings.setValue("main/auto-config", false);
-    }
-  }
-  else { // No need to start or stop auto-config when NFD is not running, but it needs to update settings
-    if (autoConfig) {
-      m_settings.setValue("main/auto-config", true);
-    }
-    else {
-      m_settings.setValue("main/auto-config", false);
-    }
+  if (isEnabled) {
+    QFile file(QDir::home().path() + "/" + AUTO_START_SUFFIX);
+    file.open(QIODevice::WriteOnly);
+
+    std::string plist = R"PLIST(<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<?xml version="1.0" encoding="UTF-8"?>
+<plist version="1.0">
+    <dict>
+        <key>Label</key>
+        <string>net.named-data.control-center</string>
+        <key>ProgramArguments</key>
+        <array>
+            <string>%%PATH%%</string>
+        </array>
+        <key>RunAtLoad</key>
+        <true/>
+        <key>KeepAlive</key>
+        <false/>
+    </dict>
+</plist>
+)PLIST"; //"
+    boost::replace_all(plist, "%%PATH%%", QCoreApplication::applicationFilePath().toStdString());
+    file.write(plist.data(), plist.size());
+    file.close();
+  } else {
+    QFile::remove(QDir::home().path() + "/" + AUTO_START_SUFFIX);
   }
 }
 
-void
-TrayMenu::quitApp()
-{
-  QCoreApplication::exit(0);
-}
+////////////////////////////////////////////////////////////////////////////////
+// NFD start on launch
 
-void
-TrayMenu::iconActivated(QSystemTrayIcon::ActivationReason reason)
+Q_INVOKABLE bool
+TrayMenu::isNfdAutoStartEnabled() const
 {
-  switch (reason) {
-  // case QSystemTrayIcon::Trigger:
-  //   emit showApp();
-  //   break;
-  case QSystemTrayIcon::Context:
-    break;
-  default:
-    break;
-  }
+  return m_settings->value("ENABLE_AUTO_START", false).toBool();
 }
 
 Q_INVOKABLE void
-TrayMenu::startStopNfd(bool autoConfig)
+TrayMenu::enableDisableNfdAutoStart(bool isEnabled)
 {
+  m_settings->setValue("ENABLE_AUTO_START", isEnabled);
   if (!m_isNfdRunning) {
     startNfd();
-    if (autoConfig) {
-      stopAutoConfig(); // Make sure no more than one auto-config process exist
-      QTimer* mTimer = new QTimer(this);
-      mTimer->setSingleShot(true);
-      connect(mTimer, SIGNAL(timeout()), SLOT(startAutoConfig()));
-      mTimer->start(2000);
-      m_context->setContextProperty("acText", QVariant::fromValue(m_autoConfigMsg));
-    }
-  }
-  else {
-    stopNfd();
-    stopAutoConfig();
-    appendMsg(m_autoConfigMsg, QString("NDN auto configuration will be stopped!\n"));
-    m_context->setContextProperty("acText", QVariant::fromValue(m_autoConfigMsg));
   }
 }
 
@@ -233,21 +172,10 @@
 #ifdef OSX_BUILD
   QProcess* proc = new QProcess();
   connect(proc, SIGNAL(finished(int)), proc, SLOT(deleteLater()));
-  proc->startDetached((QCoreApplication::applicationDirPath().toStdString() + "/../Platform/nfd").c_str(),
+  proc->startDetached((QCoreApplication::applicationDirPath() + "/../Platform/nfd"),
                       QStringList()
                         << "--config"
-                        << (QCoreApplication::applicationDirPath().toStdString() + "/../etc/ndn/nfd.conf").c_str());
-
-
-  // #endif
-  //   QProcess * proc = new QProcess();
-  //   connect(proc, SIGNAL(finished(int)), proc, SLOT(deleteLater()));
-  // #ifdef __linux__
-  //   proc->start("gksudo", QStringList() << NFD_START_COMMAND);
-  // #else
-  //   proc->start("osascript", QStringList()
-  //               << "-e"
-  //               << "do shell script \"" NFD_START_COMMAND "\" with administrator privileges");
+                        << (QCoreApplication::applicationDirPath() + "/../etc/ndn/nfd.conf"));
 #endif
 }
 
@@ -261,6 +189,117 @@
 #endif
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// NDN Autoconfig
+
+Q_INVOKABLE bool
+TrayMenu::isNdnAutoConfigEnabled() const
+{
+  return m_settings->value("ENABLE_NDN_AUTO_CONFIG", false).toBool();
+}
+
+Q_INVOKABLE void
+TrayMenu::enableDisableNdnAutoConfig(bool isEnabled)
+{
+  m_settings->setValue("ENABLE_NDN_AUTO_CONFIG", isEnabled);
+
+  if (isEnabled) {
+    startNdnAutoConfig();
+  }
+  else {
+    stopNdnAutoConfig();
+  }
+}
+
+void
+TrayMenu::startNdnAutoConfig()
+{
+  if (m_acProc != nullptr) {
+    return;
+  }
+
+  stopNdnAutoConfig(false); // Make sure no more than one auto-config process exist
+
+  if (!m_isNfdRunning) {
+    return;
+  }
+
+  m_acProc = new QProcess();
+
+  scheduleDelayedTask(std::chrono::seconds(2), [this] {
+      appendNdnAutoConfigStatus("NDN auto configuration starting...\n");
+      m_acProc->start(QCoreApplication::applicationDirPath() + "/../Platform/ndn-autoconfig",
+                      QStringList() << "--daemon");
+      connect(m_acProc, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()));
+      connect(m_acProc, SIGNAL(readyReadStandardError()), this, SLOT(processOutput()));
+    });
+}
+
+void
+TrayMenu::stopNdnAutoConfig(bool appendStatus)
+{
+  m_acProc = nullptr;
+  QProcess* proc = new QProcess();
+  connect(proc, SIGNAL(finished(int)), proc, SLOT(deleteLater()));
+  proc->startDetached("killall", QStringList() << "ndn-autoconfig");
+  if (appendStatus) {
+    appendNdnAutoConfigStatus("NDN auto configuration stopped\n");
+  }
+}
+
+void
+TrayMenu::appendNdnAutoConfigStatus(const QString& message)
+{
+  if (message == "") {
+    return;
+  }
+  if (m_ndnAutoConfigMsg.count("\n") > MAX_LINES_IN_AUTOCONF_STATUS) {
+    int end = m_ndnAutoConfigMsg.indexOf("\n");
+    m_ndnAutoConfigMsg.remove(0, end + 1);
+  }
+  m_ndnAutoConfigMsg.append(message);
+
+  m_context->setContextProperty("ndnAutoConfigText", m_ndnAutoConfigMsg);
+}
+
+void
+TrayMenu::processOutput()
+{
+  if (m_acProc == nullptr) {
+    return;
+  }
+  appendNdnAutoConfigStatus(m_acProc->readAllStandardOutput());
+  appendNdnAutoConfigStatus(m_acProc->readAllStandardError());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NFD stop on shutdown
+
+Q_INVOKABLE bool
+TrayMenu::isNfdStopOnExitEnabled() const
+{
+  return m_settings->value("ENABLE_SHUTDOWN", false).toBool();
+}
+
+Q_INVOKABLE void
+TrayMenu::enableDisableNfdStopOnExit(bool isEnabled)
+{
+  m_settings->setValue("ENABLE_SHUTDOWN", isEnabled);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Misc
+
+void
+TrayMenu::quitApp()
+{
+  if (isNfdStopOnExitEnabled()) {
+    stopNdnAutoConfig();
+    stopNfd();
+  }
+  QCoreApplication::exit(0);
+}
+
 Q_INVOKABLE void
 TrayMenu::addDeleteRoute()
 {
@@ -296,11 +335,12 @@
 
   if (isActive) {
     m_tray->setIcon(QIcon(CONNECT_ICON));
-    m_context->setContextProperty("startStopButtonText", QVariant::fromValue(QString("Stop NFD")));
+    if (isNdnAutoConfigEnabled()) {
+      startNdnAutoConfig();
+    }
   }
   else {
     m_tray->setIcon(QIcon(DISCONNECT_ICON));
-    m_context->setContextProperty("startStopButtonText", QVariant::fromValue(QString("Start NFD")));
   }
 }
 
@@ -308,44 +348,16 @@
 TrayMenu::enableCli()
 {
 #ifdef OSX_BUILD
-  AuthorizationRef authorizationRef;
-  OSStatus status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
-                                        kAuthorizationFlagDefaults, &authorizationRef);
-  if (status != errAuthorizationSuccess)
-    return;
+  QProcess* proc = new QProcess();
+  connect(proc, SIGNAL(finished(int)), proc, SLOT(deleteLater()));
 
-  AuthorizationItem item = { kAuthorizationRightExecute, 0, 0, 0 };
-  AuthorizationRights rights = { 1, &item };
-  const AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed
-    | kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights;
-
-  status = AuthorizationCopyRights(authorizationRef, &rights, kAuthorizationEmptyEnvironment,
-                                   flags, 0);
-  if (status != errAuthorizationSuccess)
-    return;
-
-  char const* mkdir_arg[] = { "-p", "/usr/local/bin", nullptr };
-  char const* mkdir = "/bin/mkdir";
-  AuthorizationExecuteWithPrivileges(authorizationRef,
-                                     mkdir,
-                                     kAuthorizationFlagDefaults, (char**)mkdir_arg, nullptr);
-
-  std::vector<std::string> arguments = { "-f", "-s",
-                                       QCoreApplication::applicationDirPath().toStdString() + "/../Resources/ndn",
-                                       "/usr/local/bin/ndn" };
-  std::vector<const char*> args;
-  for (const auto& i : arguments) {
-    args.push_back(i.c_str());
-  }
-  args.push_back(nullptr);
-
-  char const* helperTool  = "/bin/ln";
-  AuthorizationExecuteWithPrivileges(authorizationRef,
-                                     helperTool,
-                                     kAuthorizationFlagDefaults,
-                                     (char**)args.data(), NULL);
-
-  AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights);
+  proc->start("osascript", QStringList()
+              << "-e"
+              << "do shell script \""
+                   "/bin/mkdir -vp /usr/local/bin; "
+                   "/bin/ln -s -f '" +  QCoreApplication::applicationDirPath() +
+                     "/../Resources/ndn" + "' /usr/local/bin/ndn;"
+                   "\" with administrator privileges");
 #endif
 }
 
@@ -357,5 +369,19 @@
 }
 #endif // OSX_BUILD
 
+void
+TrayMenu::scheduleDelayedTask(std::chrono::milliseconds delays, const std::function<void()>& task)
+{
+  auto timer = new QTimer();
+  timer->setSingleShot(true);
+  timer->setInterval(delays);
+  connect(timer, &QTimer::timeout,
+          [task, timer] {
+            task();
+            timer->deleteLater();
+          });
+  timer->start();
+}
+
 } // namespace ncc
 } // namespace ndn
diff --git a/src/tray-menu.hpp b/src/tray-menu.hpp
index 841f068..6015fe5 100644
--- a/src/tray-menu.hpp
+++ b/src/tray-menu.hpp
@@ -22,18 +22,17 @@
 
 #include "config.hpp"
 
+#include <QtCore/QDir>
 #include <QtCore/QObject>
 #include <QtCore/QProcess>
 #include <QtCore/QCoreApplication>
 #include <QtCore/QSettings>
+#include <QtCore/QXmlStreamWriter>
 
 #include <QtWidgets/QWidget>
 #include <QtWidgets/QSystemTrayIcon>
 #include <QtWidgets/QAction>
 #include <QtWidgets/QMenu>
-#include <QtWidgets/QVBoxLayout>
-#include <QtWidgets/QPlainTextEdit>
-#include <QtWidgets/QPushButton>
 
 #include <QtQml/QQmlContext>
 
@@ -67,13 +66,28 @@
   ~TrayMenu();
 
   Q_INVOKABLE bool
-  isAutoConfigEnabled();
+  isNccAutoStartEnabled() const;
 
   Q_INVOKABLE void
-  startStopAutoConfig(bool autoConfig);
+  enableDisableNccAutoStart(bool isEnabled);
+
+  Q_INVOKABLE bool
+  isNfdAutoStartEnabled() const;
 
   Q_INVOKABLE void
-  startStopNfd(bool autoConfig);
+  enableDisableNfdAutoStart(bool isEnabled);
+
+  Q_INVOKABLE bool
+  isNdnAutoConfigEnabled() const;
+
+  Q_INVOKABLE void
+  enableDisableNdnAutoConfig(bool isEnabled);
+
+  Q_INVOKABLE bool
+  isNfdStopOnExitEnabled() const;
+
+  Q_INVOKABLE void
+  enableDisableNfdStopOnExit(bool isEnabled);
 
   Q_INVOKABLE void
   addDeleteRoute();
@@ -85,20 +99,16 @@
   deleteRoute();
 
 private slots:
+  void
+  startNdnAutoConfig();
+
+  void
+  stopNdnAutoConfig(bool appendStatus = true);
 
   void
   quitApp();
 
   void
-  iconActivated(QSystemTrayIcon::ActivationReason reason);
-
-  void
-  startAutoConfig();
-
-  void
-  stopAutoConfig();
-
-  void
   startNfd();
 
   void
@@ -114,16 +124,16 @@
   processOutput();
 
   void
-  showPref();
-
-  static void
-  appendMsg(QString &target, QString source);
+  appendNdnAutoConfigStatus(const QString& message);
 
 #ifdef OSX_BUILD
   void
   checkForUpdates();
 #endif // OSX_BUILD
 
+  void
+  scheduleDelayedTask(std::chrono::milliseconds delays, const std::function<void()>& task);
+
 private:
   QQmlContext* m_context;
   bool m_isNfdRunning;
@@ -132,8 +142,8 @@
   QAction* m_entryPref;
   QAction* m_entrySec;
   QProcess* m_acProc;
-  QString m_autoConfigMsg;
-  QSettings m_settings;
+  QSettings* m_settings;
+  QString m_ndnAutoConfigMsg;
 #ifdef OSX_BUILD
   QAction* m_entryEnableCli;
   QAction* m_checkForUpdates;