Tray application for Linux
Change-Id: I55862204ef71f69bc88c79fe2259f7cb8365699a
diff --git a/linux/Resources/emblem-dropbox-unsyncable.png b/linux/Resources/emblem-dropbox-unsyncable.png
new file mode 100644
index 0000000..0192e41
--- /dev/null
+++ b/linux/Resources/emblem-dropbox-unsyncable.png
Binary files differ
diff --git a/linux/Resources/emblem-system.png b/linux/Resources/emblem-system.png
new file mode 100644
index 0000000..5ebfb3a
--- /dev/null
+++ b/linux/Resources/emblem-system.png
Binary files differ
diff --git a/linux/Resources/emblem-web.png b/linux/Resources/emblem-web.png
new file mode 100644
index 0000000..1fd9f76
--- /dev/null
+++ b/linux/Resources/emblem-web.png
Binary files differ
diff --git a/linux/Resources/gnome-system.png b/linux/Resources/gnome-system.png
new file mode 100644
index 0000000..168dee0
--- /dev/null
+++ b/linux/Resources/gnome-system.png
Binary files differ
diff --git a/linux/Resources/icon-connected-white.png b/linux/Resources/icon-connected-white.png
new file mode 100644
index 0000000..55f0dc4
--- /dev/null
+++ b/linux/Resources/icon-connected-white.png
Binary files differ
diff --git a/linux/Resources/icon-disconnected-white.png b/linux/Resources/icon-disconnected-white.png
new file mode 100644
index 0000000..39997cd
--- /dev/null
+++ b/linux/Resources/icon-disconnected-white.png
Binary files differ
diff --git a/linux/Resources/mail-send-receive.png b/linux/Resources/mail-send-receive.png
new file mode 100644
index 0000000..20fcbe2
--- /dev/null
+++ b/linux/Resources/mail-send-receive.png
Binary files differ
diff --git a/linux/Resources/preferences-desktop.png b/linux/Resources/preferences-desktop.png
new file mode 100644
index 0000000..8dd7ba6
--- /dev/null
+++ b/linux/Resources/preferences-desktop.png
Binary files differ
diff --git a/linux/Resources/status-to-fib.xslt b/linux/Resources/status-to-fib.xslt
new file mode 100644
index 0000000..c224ff5
--- /dev/null
+++ b/linux/Resources/status-to-fib.xslt
@@ -0,0 +1,29 @@
+<xsl:stylesheet version = '2.0'
+ xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
+
+<xsl:template match="/ndnd">
+<fibs>
+<xsl:apply-templates select="forwarding/fentry/dest" />
+</fibs>
+</xsl:template>
+
+<xsl:template match="dest">
+<fib>
+<xsl:apply-templates select="faceid" />
+<prefix><xsl:value-of select="../prefix"/></prefix>
+</fib>
+</xsl:template>
+
+<xsl:template match="faceid">
+<xsl:variable name="id"><xsl:value-of select="." /></xsl:variable>
+<faceID><xsl:copy-of select="$id" /></faceID>
+<ip>
+<xsl:choose>
+ <xsl:when test="count(//face/ip[../faceid=$id]) > 0"><xsl:value-of select="//face/ip[../faceid=$id]" />
+ </xsl:when>
+ <xsl:otherwise>app</xsl:otherwise>
+</xsl:choose>
+</ip>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/linux/Resources/status.xslt b/linux/Resources/status.xslt
new file mode 100644
index 0000000..bf33e49
--- /dev/null
+++ b/linux/Resources/status.xslt
@@ -0,0 +1,28 @@
+<xsl:stylesheet version = '2.0'
+ xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
+
+<xsl:template match="/ndnd">
+<html><body>
+<xsl:apply-templates select="forwarding/fentry" />
+</body></html>
+</xsl:template>
+
+<xsl:template match="fentry">
+<xsl:apply-templates select="dest/faceid" />
+<xsl:text> </xsl:text>
+<xsl:value-of select="prefix"/>
+<br/>
+</xsl:template>
+
+<xsl:template match="faceid">
+<xsl:variable name="id"><xsl:value-of select="." /></xsl:variable>
+<b>face: <xsl:copy-of select="$id" />
+
+<xsl:choose>
+ <xsl:when test="count(//face/ip[../faceid=$id]) > 0"> (<xsl:value-of select="//face/ip[../faceid=$id]" />)
+ </xsl:when>
+ <xsl:otherwise> (app)</xsl:otherwise>
+</xsl:choose></b>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/linux/Resources/system-run.png b/linux/Resources/system-run.png
new file mode 100644
index 0000000..17ceb32
--- /dev/null
+++ b/linux/Resources/system-run.png
Binary files differ
diff --git a/linux/fib-input-dialog.cpp b/linux/fib-input-dialog.cpp
new file mode 100644
index 0000000..5aef521
--- /dev/null
+++ b/linux/fib-input-dialog.cpp
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * @copyright See LICENCE for copyright and license information.
+ *
+ * @author Ilya Moiseenko <iliamo@ucla.edu>
+ */
+
+#include "fib-input-dialog.h"
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+
+FibInputDialog::FibInputDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ prefixLabel = new QLabel(tr("NDN name (prefix): "));
+ prefixTextField = new QLineEdit;
+ prefixLabel->setBuddy(prefixTextField);
+
+ tunnelLabel = new QLabel(tr("Tunnel type: "));
+ tunnelComboBox = new QComboBox;
+ tunnelComboBox->addItem(tr("TCP"));
+ tunnelComboBox->addItem(tr("UDP"));
+ tunnelComboBox->setEditable(false);
+ tunnelComboBox->setCurrentIndex(0);
+
+ endpointLabel = new QLabel(tr("Endpoint (IP address): "));
+ endpointTextField = new QLineEdit;
+ endpointLabel->setBuddy(endpointTextField);
+
+ okButton = new QPushButton(tr("&Ok"));
+ cancelButton = new QPushButton(tr("&Cancel"));
+
+ connect(okButton,SIGNAL(pressed()), parent, SLOT(addFibEntry()));
+ connect(cancelButton,SIGNAL(pressed()), this, SLOT(hide()));
+
+ buttonBox = new QDialogButtonBox(Qt::Horizontal);
+ buttonBox->addButton(cancelButton, QDialogButtonBox::ActionRole);
+ buttonBox->addButton(okButton, QDialogButtonBox::ActionRole);
+
+ QHBoxLayout *hlayout = new QHBoxLayout;
+ hlayout->addWidget(tunnelLabel);
+ hlayout->addWidget(tunnelComboBox);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(prefixLabel);
+ layout->addWidget(prefixTextField);
+ layout->addLayout(hlayout);
+ layout->addWidget(endpointLabel);
+ layout->addWidget(endpointTextField);
+ layout->addWidget(buttonBox);
+
+ setLayout(layout);
+
+ setWindowTitle(tr("NDNx Control Center"));
+}
+
+QString
+FibInputDialog::getPrefixName()
+{
+ return prefixTextField->text();
+}
+
+QString
+FibInputDialog::getEndpoint()
+{
+ return endpointTextField->text();
+}
+
+QString
+FibInputDialog::getTunnelType()
+{
+ return tunnelComboBox->currentText();
+}
diff --git a/linux/fib-input-dialog.h b/linux/fib-input-dialog.h
new file mode 100644
index 0000000..f4f8d27
--- /dev/null
+++ b/linux/fib-input-dialog.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * @copyright See LICENCE for copyright and license information.
+ *
+ * @author Ilya Moiseenko <iliamo@ucla.edu>
+ */
+
+#include <QDialog>
+#include <QLabel>
+#include <QDialogButtonBox>
+#include <QPushButton>
+#include <QLineEdit>
+#include <QComboBox>
+#include <QString>
+
+#ifndef FIBINPUTDIALOG_H
+#define FIBINPUTDIALOG_H
+
+class FibInputDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ FibInputDialog(QWidget *parent = 0);
+ QString getPrefixName();
+ QString getEndpoint();
+ QString getTunnelType();
+
+private:
+ QLabel *prefixLabel;
+ QLineEdit *prefixTextField;
+
+ QLabel *tunnelLabel;
+ QComboBox *tunnelComboBox;
+
+ QLabel *endpointLabel;
+ QLineEdit *endpointTextField;
+
+ QDialogButtonBox *buttonBox;
+ QPushButton *okButton;
+ QPushButton *cancelButton;
+};
+
+#endif // FIBINPUTDIALOG_H
diff --git a/linux/main.cpp b/linux/main.cpp
new file mode 100644
index 0000000..f1fc24e
--- /dev/null
+++ b/linux/main.cpp
@@ -0,0 +1,17 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * @copyright See LICENCE for copyright and license information.
+ *
+ * @author Ilya Moiseenko <iliamo@ucla.edu>
+ */
+
+#include <QtGui/QApplication>
+#include "traymenu.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ TrayMenu w;
+
+ return a.exec();
+}
diff --git a/linux/quit-dialog.cpp b/linux/quit-dialog.cpp
new file mode 100644
index 0000000..bd53f24
--- /dev/null
+++ b/linux/quit-dialog.cpp
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * @copyright See LICENCE for copyright and license information.
+ *
+ * @author Ilya Moiseenko <iliamo@ucla.edu>
+ */
+
+#include "quit-dialog.h"
+#include <QVBoxLayout>
+#include <QApplication>
+
+QuitDialog::QuitDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ question = new QLabel(tr("Shutdown NDN daemon as well?"));
+ information = new QLabel(tr("All NDN operations will become unavailable."));
+
+ confirmButton = new QPushButton(tr("Yes"));
+ noButton = new QPushButton(tr("No"));
+ cancelButton = new QPushButton(tr("Cancel"));
+ cancelButton->setDefault(true);
+
+ buttonBox = new QDialogButtonBox(Qt::Horizontal);
+ buttonBox->addButton(cancelButton, QDialogButtonBox::ActionRole);
+ buttonBox->addButton(noButton, QDialogButtonBox::ActionRole);
+ buttonBox->addButton(confirmButton, QDialogButtonBox::ActionRole);
+
+ connect(confirmButton,SIGNAL(pressed()), parent, SLOT(terminateDaemonAndClose()));
+ connect(noButton,SIGNAL(pressed()), qApp, SLOT(quit()));
+ connect(cancelButton,SIGNAL(pressed()), this, SLOT(hide()));
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(question);
+ layout->addWidget(information);
+ layout->addWidget(buttonBox);
+
+ setLayout(layout);
+
+ setWindowTitle(tr("NDNx Control Center"));
+}
diff --git a/linux/quit-dialog.h b/linux/quit-dialog.h
new file mode 100644
index 0000000..e6fc7e3
--- /dev/null
+++ b/linux/quit-dialog.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * @copyright See LICENCE for copyright and license information.
+ *
+ * @author Ilya Moiseenko <iliamo@ucla.edu>
+ */
+
+#include <QDialog>
+#include <QLabel>
+#include <QDialogButtonBox>
+#include <QPushButton>
+
+#ifndef QUITDIALOG_H
+#define QUITDIALOG_H
+
+class QuitDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ QuitDialog(QWidget *parent = 0);
+
+private:
+ QLabel *question;
+ QLabel *information;
+ QDialogButtonBox *buttonBox;
+ QPushButton *confirmButton;
+ QPushButton *noButton;
+ QPushButton *cancelButton;
+};
+
+#endif // QUITDIALOG_H
diff --git a/linux/resource.qrc b/linux/resource.qrc
new file mode 100644
index 0000000..77511fa
--- /dev/null
+++ b/linux/resource.qrc
@@ -0,0 +1,17 @@
+<RCC>
+ <qresource prefix="/resource">
+ <file>Resources/icon1.png</file>
+ <file>Resources/FlatConnected.png</file>
+ <file>Resources/emblem-dropbox-unsyncable.png</file>
+ <file>Resources/emblem-system.png</file>
+ <file>Resources/emblem-web.png</file>
+ <file>Resources/gnome-system.png</file>
+ <file>Resources/mail-send-receive.png</file>
+ <file>Resources/preferences-desktop.png</file>
+ <file>Resources/system-run.png</file>
+ <file>Resources/status.xslt</file>
+ <file>Resources/icon-connected-white.png</file>
+ <file>Resources/icon-disconnected-white.png</file>
+ <file>Resources/status-to-fib.xslt</file>
+ </qresource>
+</RCC>
diff --git a/linux/tray-menu.cpp b/linux/tray-menu.cpp
new file mode 100644
index 0000000..3d96ac9
--- /dev/null
+++ b/linux/tray-menu.cpp
@@ -0,0 +1,364 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * @copyright See LICENCE for copyright and license information.
+ *
+ * @author Ilya Moiseenko <iliamo@ucla.edu>
+ */
+
+#include "tray-menu.h"
+#include "ui_traymenu.h" //generated from traymenu.ui
+#include "quit-dialog.h"
+#include "fib-input-dialog.h"
+
+#include <QMenu>
+#include <QCloseEvent>
+#include <QDesktopServices>
+#include <QMessageBox>
+#include <QUrl>
+#include <QCheckBox>
+#include <QLabel>
+#include <QHBoxLayout>
+#include <QLineEdit>
+#include <QProcess>
+#include <QXmlStreamReader>
+#include <QXmlQuery>
+#include <QDebug>
+#include <QtXml>
+#include <QStandardItemModel>
+
+TrayMenu::TrayMenu(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::TrayMenu)
+{
+ ui->setupUi(this);
+
+ createTrayIcon();
+ setIcon(true);
+ createToolbar();
+ createTableView();
+
+ startDaemon();
+
+ connect(ui->openTrafficMapButton, SIGNAL(pressed()), this, SLOT(openTrafficMap()));
+ connect(ui->openRoutingStatusButton, SIGNAL(pressed()), this, SLOT(openRoutingStatus()));
+ connect(ui->addFibButton, SIGNAL(pressed()), this, SLOT(showFibInputDialog()));
+ connect(ui->deleteFibButton, SIGNAL(released()), this, SLOT(deleteFibEntry()));
+ connect(ui->softwareUpdateCheckbox, SIGNAL(stateChanged(int)), this, SLOT(changeSoftwareUpdate()));
+ connect(ui->hubDiscoveryCheckbox, SIGNAL(stateChanged(int)), this, SLOT(changeHubDiscovery()));
+ connect(ui->loginStartCheckbox, SIGNAL(stateChanged(int)), this, SLOT(changeLoginStart()));
+ connect(ui->shutdownCheckbox, SIGNAL(stateChanged(int)), this, SLOT(changeShutdownExit()));
+ connect(ui->tableView, SIGNAL(clicked(QModelIndex)), this, SLOT(selectTableRow()));
+
+ statusUpdateThread = new QThread();
+ statusUpdateThread->start();
+
+ daemonStatusTimer = new QTimer(statusUpdateThread);
+ connect(daemonStatusTimer, SIGNAL(timeout()), this, SLOT(daemonStatusUpdate()));
+ daemonStatusTimer->start(1000);
+
+ trayIcon->show();
+}
+
+void TrayMenu::changeSoftwareUpdate()
+{
+ if(ui->softwareUpdateCheckbox->isChecked())
+ allowAutomaticUpdates = true;
+ else
+ allowAutomaticUpdates = false;
+}
+
+void TrayMenu::changeHubDiscovery()
+{
+ if(ui->hubDiscoveryCheckbox->isChecked())
+ enableHubDiscovery = true;
+ else
+ enableHubDiscovery = false;
+}
+
+void TrayMenu::changeLoginStart()
+{
+ if(ui->loginStartCheckbox->isChecked())
+ enableStartOnLogin = true;
+ else
+ enableStartOnLogin = false;
+}
+
+void TrayMenu::changeShutdownExit()
+{
+ if(ui->shutdownCheckbox->isChecked())
+ shutdownOnExit = true;
+ else
+ shutdownOnExit = false;
+}
+
+void TrayMenu::showFibInputDialog()
+{
+ dialog = new FibInputDialog(this);
+ dialog->exec();
+}
+
+void TrayMenu::openTrafficMap()
+{
+ QDesktopServices::openUrl(QUrl("http://ndnmap.arl.wustl.edu/", QUrl::TolerantMode));
+}
+
+void TrayMenu::openRoutingStatus()
+{
+ QDesktopServices::openUrl(QUrl("http://netlab.cs.memphis.edu/script/htm/status.htm", QUrl::TolerantMode));
+}
+
+void TrayMenu::createTrayIcon()
+{
+ trayIconMenu = new QMenu(this);
+
+ statusIndicator = new QAction(tr("Inactive"), this);
+ trayIconMenu->addAction(statusIndicator);
+
+ trayIconMenu->addSeparator();
+
+ QAction *displayStatus = new QAction(tr("Status"), this);
+ connect(displayStatus, SIGNAL(triggered()), this, SLOT(displayPopup()));
+ trayIconMenu->addAction(displayStatus);
+
+ trayIconMenu->addSeparator();
+
+ open = new QAction(tr("Preferences..."), this);
+ connect(open, SIGNAL(triggered()), this, SLOT(show()));
+ trayIconMenu->addAction(open);
+
+ close = new QAction(tr("Quit..."), this);
+ connect(close, SIGNAL(triggered()), this, SLOT(confirmQuit()));
+ trayIconMenu->addAction(close);
+
+ trayIcon = new QSystemTrayIcon(this);
+ trayIcon->setContextMenu(trayIconMenu);
+
+ connect(
+ trayIcon,
+ SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
+ this,
+ SLOT(trayIconClicked(QSystemTrayIcon::ActivationReason))
+ );
+}
+
+void TrayMenu::createToolbar()
+{
+ toolBar = new QToolBar(this);
+ toolBar->setFloatable(false);
+ toolBar->setMovable(false);
+ toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+ toolBar->setAllowedAreas(Qt::TopToolBarArea);
+ toolBar->setOrientation(Qt::Horizontal);
+ toolBar->setIconSize(QSize(32,32));
+ toolBar->resize(this->width(), 64);
+
+ openGeneralSettings = new QAction(tr("General"), this);
+ openGeneralSettings->setIcon(QIcon(":/resource/Resources/preferences-desktop.png"));
+ connect(openGeneralSettings,SIGNAL(triggered()),this, SLOT(generalSettingsClicked()));
+
+ openForwardingSettings = new QAction(tr("Forwarding"), this);
+ openForwardingSettings->setIcon(QIcon(":/resource/Resources/emblem-web.png"));
+ connect(openForwardingSettings,SIGNAL(triggered()),this, SLOT(forwardingSettingsClicked()));
+
+ openSecuritySettings = new QAction(tr("Security"), this);
+ openSecuritySettings->setIcon(QIcon(":/resource/Resources/emblem-system.png"));
+ connect(openSecuritySettings,SIGNAL(triggered()),this, SLOT(securitySettingsClicked()));
+
+ toolBar->addAction(openGeneralSettings);
+ toolBar->addAction(openForwardingSettings);
+ toolBar->addAction(openSecuritySettings);
+}
+
+void TrayMenu::generalSettingsClicked()
+{
+ ui->generalSettingsWidget->show();
+ ui->forwardingSettingsWidget->hide();
+ ui->securitySettingsWidget->hide();
+}
+
+void TrayMenu::forwardingSettingsClicked()
+{
+ ui->generalSettingsWidget->hide();
+ ui->forwardingSettingsWidget->show();
+ ui->securitySettingsWidget->hide();
+}
+
+void TrayMenu::securitySettingsClicked()
+{
+ ui->generalSettingsWidget->hide();
+ ui->forwardingSettingsWidget->hide();
+ ui->securitySettingsWidget->show();
+}
+
+void TrayMenu::displayPopup()
+{
+ trayIcon->showMessage(tr("NDNx Status"), statusXml);
+}
+
+void TrayMenu::addFibEntry()
+{
+ QString name = dialog->getPrefixName();
+ QString tunnelType = dialog->getTunnelType();
+ QString endpoint = dialog->getEndpoint();
+
+ QStringList arguments;
+ arguments << "add" << name << tunnelType << endpoint;
+
+ dialog->hide();
+
+ QProcess *process = new QProcess(this);
+ process->start(NDND_FIB_COMMAND,arguments);
+}
+
+void TrayMenu::confirmQuit()
+{
+ QuitDialog dialog(this);
+ dialog.exec();
+}
+
+void TrayMenu::terminateDaemonAndClose()
+{
+ QProcess *process = new QProcess(this);
+ process->start(NDND_STOP_COMMAND);
+ connect(process,SIGNAL(finished(int)), qApp, SLOT(quit()));
+}
+
+void TrayMenu::closeEvent(QCloseEvent *event)
+{
+ if (trayIcon->isVisible())
+ {
+ hide();
+ event->ignore();
+ }
+}
+
+void TrayMenu::showEvent(QShowEvent * event)
+{
+ ui->generalSettingsWidget->show();
+ ui->forwardingSettingsWidget->hide();
+ ui->securitySettingsWidget->hide();
+}
+
+void TrayMenu::trayIconClicked(QSystemTrayIcon::ActivationReason reason)
+{
+ if(reason == QSystemTrayIcon::Trigger)
+ this->show();
+}
+
+void TrayMenu::setIcon(bool isConnected)
+{
+ if(isConnected)
+ trayIcon->setIcon(QIcon(":/resource/Resources/icon-connected-white.png"));
+ else
+ trayIcon->setIcon(QIcon(":/resource/Resources/icon-disconnected-white.png"));
+}
+
+void TrayMenu::startDaemon()
+{
+ QProcess *process = new QProcess(this);
+ process->start(NDND_START_COMMAND);
+}
+
+void TrayMenu::daemonStatusUpdate()
+{
+ QXmlQuery query(QXmlQuery::XSLT20);
+ query.setFocus(QUrl("http://localhost:9695/?f=xml"));
+
+ query.setQuery(QUrl("qrc:/resource/Resources/status.xslt")); // TODO: I suspect it's being read from HDD each time
+ query.evaluateTo(&statusXml);
+
+ query.setQuery(QUrl("qrc:/resource/Resources/status-to-fib.xslt")); // TODO: I suspect it's being read from HDD each time
+ query.evaluateTo(&fibContentsXml);
+
+ QDomDocument xmldoc;
+ QDomElement root;
+
+ xmldoc.setContent(fibContentsXml);
+ root=xmldoc.documentElement();
+
+ model = new QStandardItemModel(root.childNodes().count(),3);
+ model->setHorizontalHeaderItem(0, new QStandardItem(tr("NDN prefix")));
+ model->setHorizontalHeaderItem(1, new QStandardItem(tr("Face ID")));
+ model->setHorizontalHeaderItem(2, new QStandardItem(tr("Endpoint")));
+
+ int row = 0;
+ QDomNode fibEntry=root.firstChild();
+ while (!fibEntry.isNull())
+ {
+ QDomNodeList properties = fibEntry.childNodes();
+
+ QDomNode faceID = properties.at(0);
+ QDomNode ip = properties.at(1);
+ QDomNode prefix = properties.at(2);
+
+ // bad: causes scroll to go up every time and overall flickering
+ /*QList<QStandardItem*> row = QList<QStandardItem*>() << new QStandardItem(prefix.toElement().text())
+ << new QStandardItem(faceID.toElement().text())
+ << new QStandardItem(ip.toElement().text());
+ model->appendRow(row);*/
+
+ model->setItem(row, 0, new QStandardItem(prefix.toElement().text()));
+ model->setItem(row, 1, new QStandardItem(faceID.toElement().text()));
+ model->setItem(row, 2, new QStandardItem(ip.toElement().text()));
+
+ fibEntry = fibEntry.nextSibling();
+ row++;
+ }
+
+ ui->tableView->setModel(model);
+
+ if(selectedRow >= 0)
+ ui->tableView->selectRow(selectedRow);
+}
+
+void TrayMenu::createTableView()
+{
+ ui->tableView->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
+ ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
+ ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
+
+ selectedRow = -1;
+}
+
+void TrayMenu::selectTableRow()
+{
+ selectedRow = ui->tableView->selectionModel()->selection().indexes().at(0).row();
+}
+
+void TrayMenu::deleteFibEntry()
+{
+ if(selectedRow < 0)
+ return;
+
+ QStandardItem *prefix = model->item(selectedRow,0);
+ if(prefix == NULL)
+ return;
+
+ QStandardItem *faceID = model->item(selectedRow,1);
+ if(faceID == NULL)
+ return;
+
+ QStringList arguments;
+ arguments << "del" << prefix->text() << "face" << faceID->text();
+
+ QProcess *process = new QProcess(this);
+ process->start(NDND_FIB_COMMAND,arguments);
+}
+
+TrayMenu::~TrayMenu()
+{
+ daemonStatusTimer->stop();
+ statusUpdateThread->exit();
+ delete ui;
+ delete trayIcon;
+ delete trayIconMenu;
+ delete open;
+ delete close;
+ delete openGeneralSettings;
+ delete openForwardingSettings;
+ delete openSecuritySettings;
+ delete toolBar;
+ delete statusUpdateThread;
+ delete daemonStatusTimer;
+ delete dialog;
+}
diff --git a/linux/tray-menu.h b/linux/tray-menu.h
new file mode 100644
index 0000000..045bb09
--- /dev/null
+++ b/linux/tray-menu.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * @copyright See LICENCE for copyright and license information.
+ *
+ * @author Ilya Moiseenko <iliamo@ucla.edu>
+ */
+
+#ifndef TRAYMENU_H
+#define TRAYMENU_H
+
+#include <QMainWindow>
+#include <QWidget>
+#include <QSystemTrayIcon>
+#include <QMenu>
+#include <QTimer>
+#include <QProcess>
+#include <QThread>
+#include <QXmlStreamReader>
+#include <QStandardItemModel>
+#include <QtXml>
+
+#include "FibInputDialog.h"
+#include "QuitDialog.h"
+
+#define NDND_START_COMMAND "/usr/local/bin/ndndstart"
+#define NDND_STOP_COMMAND "/usr/local/bin/ndndstop"
+#define NDND_STATUS_COMMAND "/usr/local/bin/ndndsmoketest"
+#define NDND_FIB_COMMAND "/usr/local/bin/ndndc"
+
+namespace Ui
+{
+ class TrayMenu;
+}
+
+class TrayMenu : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit TrayMenu(QWidget *parent = 0);
+ ~TrayMenu();
+
+private:
+ Ui::TrayMenu *ui;
+
+ void createTrayIcon();
+ void setIcon(bool isConnected);
+ void createToolbar();
+ void createTableView();
+ void closeEvent(QCloseEvent *); // Overriding the window's close event
+ void showEvent(QShowEvent * event); //Overriding the window's show event
+
+ void startDaemon();
+
+ QSystemTrayIcon *trayIcon;
+ QMenu *trayIconMenu;
+ QToolBar *toolBar;
+
+ QTimer *daemonStatusTimer;
+ QThread *statusUpdateThread;
+
+ QString statusXml;
+ QString fibContentsXml;
+
+ QStandardItemModel *model;
+ int selectedRow;
+
+ QAction *statusIndicator;
+ QAction *open;
+ QAction *close;
+ QAction *openGeneralSettings;
+ QAction *openForwardingSettings;
+ QAction *openSecuritySettings;
+
+ FibInputDialog *dialog;
+
+ bool allowAutomaticUpdates;
+ bool enableHubDiscovery;
+ bool enableStartOnLogin;
+ bool shutdownOnExit;
+
+private slots:
+ void trayIconClicked(QSystemTrayIcon::ActivationReason);
+ void generalSettingsClicked();
+ void forwardingSettingsClicked();
+ void securitySettingsClicked();
+ void openTrafficMap();
+ void openRoutingStatus();
+ void displayPopup();
+ void confirmQuit();
+ void showFibInputDialog();
+ void terminateDaemonAndClose();
+ void addFibEntry();
+ void daemonStatusUpdate();
+ void selectTableRow();
+ void deleteFibEntry();
+ void changeSoftwareUpdate();
+ void changeHubDiscovery();
+ void changeLoginStart();
+ void changeShutdownExit();
+};
+
+#endif // TRAYMENU_H
diff --git a/linux/traymenu.ui b/linux/traymenu.ui
new file mode 100644
index 0000000..428f343
--- /dev/null
+++ b/linux/traymenu.ui
@@ -0,0 +1,304 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>TrayMenu</class>
+ <widget class="QMainWindow" name="TrayMenu">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>551</width>
+ <height>332</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>NDNx preferences</string>
+ </property>
+ <property name="animated">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <widget class="QWidget" name="generalSettingsWidget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>50</y>
+ <width>521</width>
+ <height>241</height>
+ </rect>
+ </property>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>0</y>
+ <width>471</width>
+ <height>141</height>
+ </rect>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">QGroupBox#groupBox {
+border: 2px solid gray;
+border-radius: 7px;
+}</string>
+ </property>
+ <property name="title">
+ <string/>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <widget class="QCheckBox" name="shutdownCheckbox">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>110</y>
+ <width>441</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>13</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Shutdown NDN daemon on exit</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="softwareUpdateCheckbox">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>80</y>
+ <width>441</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>13</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Check for software updates</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="hubDiscoveryCheckbox">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>50</y>
+ <width>431</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>13</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Discover nearest NDN-hub</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="loginStartCheckbox">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>20</y>
+ <width>451</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>13</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Automatically start NDNx Control Center at login</string>
+ </property>
+ </widget>
+ <zorder>shutdownCheckbox</zorder>
+ <zorder>softwareUpdateCheckbox</zorder>
+ <zorder>hubDiscoveryCheckbox</zorder>
+ <zorder>loginStartCheckbox</zorder>
+ <zorder>forwardingSettingsWidget</zorder>
+ </widget>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>150</y>
+ <width>471</width>
+ <height>81</height>
+ </rect>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">QGroupBox#groupBox_2 {
+border: 2px solid gray;
+border-radius: 7px;
+}</string>
+ </property>
+ <property name="title">
+ <string/>
+ </property>
+ <widget class="QPushButton" name="openTrafficMapButton">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>241</width>
+ <height>27</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Open Testbed Traffic Map</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" name="openRoutingStatusButton">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>40</y>
+ <width>241</width>
+ <height>27</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Open Testbed Routing Status</string>
+ </property>
+ </widget>
+ </widget>
+ </widget>
+ <widget class="QWidget" name="forwardingSettingsWidget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>50</y>
+ <width>521</width>
+ <height>251</height>
+ </rect>
+ </property>
+ <widget class="QLabel" name="label">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>66</width>
+ <height>17</height>
+ </rect>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">font: 18pt;</string>
+ </property>
+ <property name="text">
+ <string>FIB</string>
+ </property>
+ </widget>
+ <widget class="QTableView" name="tableView">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>30</y>
+ <width>511</width>
+ <height>181</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="addFibButton">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>220</y>
+ <width>23</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>+</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="deleteFibButton">
+ <property name="geometry">
+ <rect>
+ <x>40</x>
+ <y>220</y>
+ <width>23</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>-</string>
+ </property>
+ </widget>
+ <zorder>label</zorder>
+ <zorder>tableView</zorder>
+ <zorder>addFibButton</zorder>
+ <zorder>deleteFibButton</zorder>
+ <zorder>securitySettingsWidget</zorder>
+ </widget>
+ <widget class="QWidget" name="securitySettingsWidget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>50</y>
+ <width>521</width>
+ <height>241</height>
+ </rect>
+ </property>
+ </widget>
+ </widget>
+ <widget class="QStatusBar" name="statusBar"/>
+ <widget class="QToolBar" name="toolBar">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::DefaultContextMenu</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="movable">
+ <bool>false</bool>
+ </property>
+ <property name="allowedAreas">
+ <set>Qt::TopToolBarArea</set>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>25</width>
+ <height>17</height>
+ </size>
+ </property>
+ <property name="toolButtonStyle">
+ <enum>Qt::ToolButtonTextUnderIcon</enum>
+ </property>
+ <attribute name="toolBarArea">
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>