Add key viewer
diff --git a/src/fib-status.cpp b/src/fib-status.cpp
index 8f56483..9b8079f 100644
--- a/src/fib-status.cpp
+++ b/src/fib-status.cpp
@@ -36,7 +36,7 @@
 
 FibStatusModel::FibStatusModel(Face& face, QObject *parent/* = 0*/)
   : QAbstractListModel(parent)
-  , m_face(face)
+  // , m_face(face)
 {
 }
 
diff --git a/src/fib-status.hpp b/src/fib-status.hpp
index 0ebd80e..a5d365e 100644
--- a/src/fib-status.hpp
+++ b/src/fib-status.hpp
@@ -103,7 +103,7 @@
   onTimeout();
 
 private:
-  Face& m_face;
+  // Face& m_face;
   QList<FibStatusItem> m_items;
   // shared_ptr<OBufferStream> m_buffer;
 };
diff --git a/src/key-tree-item.cpp b/src/key-tree-item.cpp
new file mode 100644
index 0000000..070537e
--- /dev/null
+++ b/src/key-tree-item.cpp
@@ -0,0 +1,104 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014, Regents of the University of California,
+ *
+ * This file is part of NFD Control Center.  See AUTHORS.md for complete list of NFD
+ * authors and contributors.
+ *
+ * NFD Control Center is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD Control Center 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with NFD
+ * Control Center, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <QStringList>
+#include "key-tree-item.hpp"
+
+namespace ndn {
+namespace ncc {
+
+KeyTreeItem::KeyTreeItem(const QVariant& name, const QVariant& data, Type type, KeyTreeItem* parent)
+  : m_name(name)
+  , m_data(data)
+  , m_type(type)
+  , m_parentItem(parent)
+{
+}
+
+KeyTreeItem::~KeyTreeItem()
+{
+  qDeleteAll(m_childItems);
+}
+
+void
+KeyTreeItem::setParent(KeyTreeItem* parent)
+{
+  m_parentItem = parent;
+}
+
+void
+KeyTreeItem::appendChild(KeyTreeItem* item)
+{
+  m_childItems.append(item);
+}
+
+KeyTreeItem*
+KeyTreeItem::child(int row)
+{
+  return m_childItems.value(row);
+}
+
+int
+KeyTreeItem::childCount() const
+{
+  return m_childItems.count();
+}
+
+int
+KeyTreeItem::columnCount() const
+{
+  return 1;
+}
+
+QVariant
+KeyTreeItem::name() const
+{
+  return m_name;
+}
+
+QVariant
+KeyTreeItem::data() const
+{
+  return m_data;
+}
+
+KeyTreeItem::Type
+KeyTreeItem::type() const
+{
+  return m_type;
+}
+
+KeyTreeItem*
+KeyTreeItem::parentItem()
+{
+  return m_parentItem;
+}
+
+int
+KeyTreeItem::row() const
+{
+  if (m_parentItem)
+    return m_parentItem->m_childItems.indexOf(const_cast<KeyTreeItem*>(this));
+
+  return 0;
+}
+
+} // namespace ndn
+} // namespace ncc
diff --git a/src/key-tree-item.hpp b/src/key-tree-item.hpp
new file mode 100644
index 0000000..6d7a02a
--- /dev/null
+++ b/src/key-tree-item.hpp
@@ -0,0 +1,90 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014, Regents of the University of California,
+ *
+ * This file is part of NFD Control Center.  See AUTHORS.md for complete list of NFD
+ * authors and contributors.
+ *
+ * NFD Control Center is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD Control Center 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with NFD
+ * Control Center, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NDN_NCC_KEY_TREE_ITEM_HPP
+#define NDN_NCC_KEY_TREE_ITEM_HPP
+
+#include <string>
+#include <QList>
+#include <QVariant>
+
+namespace ndn {
+namespace ncc {
+
+class KeyTreeItem
+{
+public:
+  enum class Type {
+    ROOT = 0,
+    ID = 1,
+    KEY = 2,
+    CERT = 3
+  };
+
+public:
+  explicit
+  KeyTreeItem(const QVariant& name,
+              const QVariant& data = QVariant(),
+              Type type = Type::ROOT,
+              KeyTreeItem* parent = nullptr);
+
+  ~KeyTreeItem();
+
+  void
+  setParent(KeyTreeItem* parent);
+
+  void
+  appendChild(KeyTreeItem* child);
+
+  KeyTreeItem*
+  child(int row);
+
+  int
+  childCount() const;
+
+  int
+  columnCount() const;
+
+  QVariant
+  name() const;
+
+  QVariant
+  data() const;
+
+  Type
+  type() const;
+
+  int
+  row() const;
+
+  KeyTreeItem*
+  parentItem();
+
+private:
+  QList<KeyTreeItem*> m_childItems;
+  QVariant m_name;
+  QVariant m_data;
+  Type m_type;
+  KeyTreeItem* m_parentItem;
+};
+
+} // namespace ndn
+} // namespace ncc
+
+#endif // NDN_NCC_KEY_TREE_ITEM_HPP
diff --git a/src/key-tree-model.cpp b/src/key-tree-model.cpp
new file mode 100644
index 0000000..ec4fc02
--- /dev/null
+++ b/src/key-tree-model.cpp
@@ -0,0 +1,214 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014, Regents of the University of California,
+ *
+ * This file is part of NFD Control Center.  See AUTHORS.md for complete list of NFD
+ * authors and contributors.
+ *
+ * NFD Control Center is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD Control Center 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with NFD
+ * Control Center, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "key-tree-model.hpp"
+#include "key-tree-item.hpp"
+
+#include <QStringList>
+
+
+#ifdef WAF
+#include "key-tree-model.moc"
+#endif
+
+namespace ndn {
+namespace ncc {
+
+KeyTreeModel::KeyTreeModel(QObject *parent)
+  : QAbstractItemModel(parent)
+  , m_rootItem(new KeyTreeItem(QVariant("")))
+{
+}
+
+KeyTreeModel::~KeyTreeModel()
+{
+  delete m_rootItem;
+}
+
+void
+KeyTreeModel::clear()
+{
+  delete m_rootItem;
+  m_rootItem = new KeyTreeItem(QVariant(""));
+}
+
+void
+KeyTreeModel::addChild(KeyTreeItem* child)
+{
+  child->setParent(m_rootItem);
+  m_rootItem->appendChild(child);
+}
+
+int
+KeyTreeModel::columnCount(const QModelIndex& parent) const
+{
+  if (parent.isValid())
+    return static_cast<KeyTreeItem*>(parent.internalPointer())->columnCount();
+  else
+    return m_rootItem->columnCount();
+}
+
+QVariant
+KeyTreeModel::name(const QModelIndex& index, int role) const
+{
+  if (!index.isValid())
+    return QVariant();
+
+  if (role != Qt::DisplayRole)
+    return QVariant();
+
+  KeyTreeItem* item = static_cast<KeyTreeItem*>(index.internalPointer());
+
+  return item->name();
+}
+
+QVariant
+KeyTreeModel::data(const QModelIndex& index, int role) const
+{
+  if (!index.isValid())
+    return QVariant();
+
+  if (role != Qt::DisplayRole)
+    return QVariant();
+
+  KeyTreeItem* item = static_cast<KeyTreeItem*>(index.internalPointer());
+
+  return item->data();
+}
+
+Qt::ItemFlags
+KeyTreeModel::flags(const QModelIndex& index) const
+{
+  if (!index.isValid())
+    return 0;
+
+  return QAbstractItemModel::flags(index);
+}
+
+QVariant
+KeyTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+  // if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
+  //   return m_rootItem->data();
+
+  return QVariant();
+}
+
+QModelIndex
+KeyTreeModel::index(int row, int column, const QModelIndex &parent) const
+{
+  if (!hasIndex(row, column, parent))
+    return QModelIndex();
+
+  KeyTreeItem *parentItem;
+
+  if (!parent.isValid())
+    parentItem = m_rootItem;
+  else
+    parentItem = static_cast<KeyTreeItem*>(parent.internalPointer());
+
+  KeyTreeItem *childItem = parentItem->child(row);
+  if (childItem)
+    return createIndex(row, column, childItem);
+  else
+    return QModelIndex();
+}
+
+QModelIndex
+KeyTreeModel::parent(const QModelIndex &index) const
+{
+  if (!index.isValid())
+    return QModelIndex();
+
+  KeyTreeItem *childItem = static_cast<KeyTreeItem*>(index.internalPointer());
+  KeyTreeItem *parentItem = childItem->parentItem();
+
+  if (parentItem == m_rootItem)
+    return QModelIndex();
+
+  return createIndex(parentItem->row(), 0, parentItem);
+}
+
+int
+KeyTreeModel::rowCount(const QModelIndex &parent) const
+{
+  KeyTreeItem *parentItem;
+  if (parent.column() > 0)
+    return 0;
+
+  if (!parent.isValid())
+    parentItem = m_rootItem;
+  else
+    parentItem = static_cast<KeyTreeItem*>(parent.internalPointer());
+
+  return parentItem->childCount();
+}
+
+// void
+// KeyTreeModel::setupModelData(const QStringList &lines, KeyTreeItem *parent)
+// {
+  // QList<KeyTreeItem*> parents;
+  // QList<int> indentations;
+  // parents << parent;
+  // indentations << 0;
+
+  // int number = 0;
+
+  // while (number < lines.count()) {
+  //   int position = 0;
+  //   while (position < lines[number].length()) {
+  //     if (lines[number].at(position) != ' ')
+  //       break;
+  //     position++;
+  //   }
+
+  //   QString lineData = lines[number].mid(position).trimmed();
+
+  //   if (!lineData.isEmpty()) {
+  //     // Read the column data from the rest of the line.
+  //     QStringList columnStrings = lineData.split("\t", QString::SkipEmptyParts);
+  //     QList<QVariant> columnData;
+  //     for (int column = 0; column < columnStrings.count(); ++column)
+  //       columnData << columnStrings[column];
+
+  //     if (position > indentations.last()) {
+  //       // The last child of the current parent is now the new parent
+  //       // unless the current parent has no children.
+
+  //       if (parents.last()->childCount() > 0) {
+  //         parents << parents.last()->child(parents.last()->childCount()-1);
+  //         indentations << position;
+  //       }
+  //     } else {
+  //       while (position < indentations.last() && parents.count() > 0) {
+  //         parents.pop_back();
+  //         indentations.pop_back();
+  //       }
+  //     }
+
+  //     // Append a new item to the current parent's list of children.
+  //     parents.last()->appendChild(new TreeItem(columnData, parents.last()));
+  //   }
+
+  //   ++number;
+  // }
+// }
+
+} // namespace ndn
+} // namespace ncc
diff --git a/src/key-tree-model.hpp b/src/key-tree-model.hpp
new file mode 100644
index 0000000..4cb72ce
--- /dev/null
+++ b/src/key-tree-model.hpp
@@ -0,0 +1,80 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014, Regents of the University of California,
+ *
+ * This file is part of NFD Control Center.  See AUTHORS.md for complete list of NFD
+ * authors and contributors.
+ *
+ * NFD Control Center is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD Control Center 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with NFD
+ * Control Center, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NDN_NCC_KEY_TREE_MODEL_HPP
+#define NDN_NCC_KEY_TREE_MODEL_HPP
+
+#include <QAbstractItemModel>
+#include <QModelIndex>
+#include <QVariant>
+
+namespace ndn {
+namespace ncc {
+
+class KeyTreeItem;
+
+class KeyTreeModel : public QAbstractItemModel
+{
+  Q_OBJECT
+
+public:
+  explicit
+  KeyTreeModel(QObject* parent = 0);
+
+  ~KeyTreeModel();
+
+  void
+  clear();
+
+  void
+  addChild(KeyTreeItem* child);
+
+  QVariant
+  name(const QModelIndex& index, int role) const;
+
+  QVariant
+  data(const QModelIndex& index, int role) const Q_DECL_OVERRIDE;
+
+  Qt::ItemFlags
+  flags(const QModelIndex& index) const Q_DECL_OVERRIDE;
+
+  QVariant
+  headerData(int section, Qt::Orientation orientation,
+             int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+
+  QModelIndex
+  index(int row, int column, const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+
+  QModelIndex
+  parent(const QModelIndex& index) const Q_DECL_OVERRIDE;
+
+  int
+  rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+
+  int
+  columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+
+private:
+  KeyTreeItem* m_rootItem;
+};
+
+} // namespace ncc
+} // namespace ndn
+
+#endif // NDN_NCC_KEY_TREE_MODEL_HPP
diff --git a/src/key-viewer-dialog.cpp b/src/key-viewer-dialog.cpp
new file mode 100644
index 0000000..9a95bbd
--- /dev/null
+++ b/src/key-viewer-dialog.cpp
@@ -0,0 +1,189 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014, Regents of the University of California,
+ *
+ * This file is part of NFD Control Center.  See AUTHORS.md for complete list of NFD
+ * authors and contributors.
+ *
+ * NFD Control Center is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD Control Center 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with NFD
+ * Control Center, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "key-viewer-dialog.hpp"
+#include "ui_key-viewer-dialog.h"
+#include "key-tree-item.hpp"
+
+#include <iostream>
+
+
+#ifdef WAF
+#include "key-viewer-dialog.moc"
+#endif
+
+namespace ndn {
+namespace ncc {
+
+KeyViewerDialog::KeyViewerDialog(QWidget *parent)
+  : QDialog(parent)
+  , ui(new Ui::KeyViewerDialog)
+  , m_model(new KeyTreeModel)
+{
+  ui->setupUi(this);
+
+  ui->treeView->setModel(m_model.get());
+  ui->treeView->show();
+
+  connect(ui->treeView, SIGNAL(clicked(const QModelIndex&)), this, SLOT(displayCert(const QModelIndex&)));
+}
+
+KeyViewerDialog::~KeyViewerDialog()
+{
+}
+
+void
+KeyViewerDialog::updateModel()
+{
+}
+
+void
+KeyViewerDialog::present()
+{
+  m_keyChain = make_shared<KeyChain>();
+  auto newModel = make_shared<KeyTreeModel>();
+
+  std::vector<Name> defaultIdentities;
+  m_keyChain->getAllIdentities(defaultIdentities, true);
+  for (const auto& identity : defaultIdentities) {
+    newModel->addChild(createIdentityNode(identity));
+  }
+
+  std::vector<Name> otherIdentities;
+  m_keyChain->getAllIdentities(otherIdentities, false);
+  for (const auto& identity : otherIdentities) {
+    newModel->addChild(createIdentityNode(identity));
+  }
+
+  ui->treeView->setModel(newModel.get());
+  ui->treeView->show();
+  m_model = newModel;
+
+  show();
+  raise();
+}
+
+void
+KeyViewerDialog::displayCert(const QModelIndex& index)
+{
+  std::cerr << "clicked" << std::endl;
+
+  QModelIndex parent = index;
+  KeyTreeItem* item = static_cast<KeyTreeItem*>(parent.internalPointer());
+  if (item->type() == KeyTreeItem::Type::ID) {
+    std::cerr << item->name().toString().toStdString() << std::endl;
+    parent = m_model->index(0, 0, parent);
+  }
+
+  item = static_cast<KeyTreeItem*>(parent.internalPointer());
+  if (item->type() == KeyTreeItem::Type::KEY) {
+    std::cerr << item->name().toString().toStdString() << std::endl;
+    parent = m_model->index(0, 0, parent);
+  }
+
+  shared_ptr<QStandardItemModel> tableModel;
+  item = static_cast<KeyTreeItem*>(parent.internalPointer());
+  if (item->type() == KeyTreeItem::Type::CERT) {
+    std::cerr << item->name().toString().toStdString() << std::endl;
+
+    shared_ptr<IdentityCertificate> cert =
+      m_keyChain->getCertificate(Name(item->name().toString().toStdString()));
+
+    tableModel = make_shared<QStandardItemModel>(5, 2);
+    tableModel->setItem(0, 0, new QStandardItem(QString("Name")));
+    tableModel->setItem(0, 1, new QStandardItem(item->name().toString()));
+
+    tableModel->setItem(1, 0, new QStandardItem(QString("NotBefore")));
+    tableModel->setItem(1, 1, new QStandardItem(QString::fromStdString(time::toIsoString(cert->getNotBefore()))));
+
+    tableModel->setItem(2, 0, new QStandardItem(QString("NotAfter")));
+    tableModel->setItem(2, 1, new QStandardItem(QString::fromStdString(time::toIsoString(cert->getNotAfter()))));
+
+    tableModel->setItem(3, 0, new QStandardItem(QString("FingerPrint")));
+    tableModel->setItem(3, 1, new QStandardItem(QString("FFFF")));
+
+    Name signerName = cert->getSignature().getKeyLocator().getName();
+    tableModel->setItem(4, 0, new QStandardItem(QString("KeyLocator")));
+    tableModel->setItem(4, 1, new QStandardItem(QString::fromStdString(signerName.toUri())));
+  }
+  else {
+    tableModel = make_shared<QStandardItemModel>(5, 2);
+  }
+  ui->tableView->setModel(tableModel.get());
+  ui->tableView->resizeColumnsToContents();
+  QHeaderView* header = ui->tableView->horizontalHeader();
+  header->setStretchLastSection(true);
+  ui->tableView->setHorizontalHeader(header);
+  ui->tableView->show();
+  m_tableModel = tableModel;
+}
+
+KeyTreeItem*
+KeyViewerDialog::createIdentityNode(const Name& identity)
+{
+  KeyTreeItem* idItem = new KeyTreeItem(QVariant(QString::fromStdString(identity.toUri())),
+                                        QVariant(QString::fromStdString(identity.toUri())),
+                                        KeyTreeItem::Type::ID);
+
+  std::vector<Name> defaultKeys;
+  m_keyChain->getAllKeyNamesOfIdentity(identity, defaultKeys, true);
+  for (const auto& keyName : defaultKeys) {
+    idItem->appendChild(createKeyNode(keyName, idItem));
+  }
+
+  std::vector<ndn::Name> otherKeys;
+  m_keyChain->getAllKeyNamesOfIdentity(identity, otherKeys, false);
+  for (const auto& keyName : otherKeys) {
+    idItem->appendChild(createKeyNode(keyName, idItem));
+  }
+
+  return idItem;
+}
+
+KeyTreeItem*
+KeyViewerDialog::createKeyNode(const Name& keyName, KeyTreeItem* idItem)
+{
+  KeyTreeItem* keyItem = new KeyTreeItem(QVariant(QString::fromStdString(keyName.toUri())),
+                                         QVariant(QString::fromStdString(keyName[-1].toUri())),
+                                         KeyTreeItem::Type::KEY,
+                                         idItem);
+
+  std::vector<Name> defaultCertificates;
+  m_keyChain->getAllCertificateNamesOfKey(keyName, defaultCertificates, true);
+  for (const auto& certName : defaultCertificates) {
+    keyItem->appendChild(new KeyTreeItem(QVariant(QString::fromStdString(certName.toUri())),
+                                         QVariant(QString::fromStdString(certName[-1].toUri())),
+                                         KeyTreeItem::Type::CERT,
+                                         keyItem));
+  }
+
+  std::vector<ndn::Name> otherCertificates;
+  m_keyChain->getAllCertificateNamesOfKey(keyName, otherCertificates, false);
+  for (const auto& certName : otherCertificates) {
+    keyItem->appendChild(new KeyTreeItem(QVariant(QString::fromStdString(certName.toUri())),
+                                         QVariant(QString::fromStdString(certName[-1].toUri())),
+                                         KeyTreeItem::Type::CERT,
+                                         keyItem));
+  }
+
+  return keyItem;
+}
+
+} // namespace ncc
+} // namespace ndn
diff --git a/src/key-viewer-dialog.hpp b/src/key-viewer-dialog.hpp
new file mode 100644
index 0000000..60996af
--- /dev/null
+++ b/src/key-viewer-dialog.hpp
@@ -0,0 +1,85 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014, Regents of the University of California,
+ *
+ * This file is part of NFD Control Center.  See AUTHORS.md for complete list of NFD
+ * authors and contributors.
+ *
+ * NFD Control Center is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD Control Center 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with NFD
+ * Control Center, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NDN_NCC_KEY_VIEWER_DIALOG_HPP
+#define NDN_NCC_KEY_VIEWER_DIALOG_HPP
+
+#include "key-tree-model.hpp"
+#include <ndn-cxx/security/key-chain.hpp>
+
+#include <QDialog>
+#include <QStandardItemModel>
+
+namespace Ui {
+class KeyViewerDialog;
+}
+
+namespace ndn {
+namespace ncc {
+
+class KeyViewerDialog : public QDialog
+{
+  Q_OBJECT
+
+public:
+  KeyViewerDialog(QWidget *parent = 0);
+
+  virtual
+  ~KeyViewerDialog();
+
+  void
+  updateModel();
+
+private:
+  KeyTreeItem*
+  createIdentityNode(const Name& identity);
+
+  KeyTreeItem*
+  createKeyNode(const Name& keyName, KeyTreeItem* idItem);
+
+signals:
+  void
+  clicked(const QModelIndex &index);
+
+public slots:
+  void
+  present();
+
+private slots:
+  void
+  displayCert(const QModelIndex& index);
+  // void insertChild();
+  // bool insertColumn();
+  // void insertRow();
+  // bool removeColumn();
+  // void removeRow();
+
+private:
+  Ui::KeyViewerDialog* ui;
+
+  shared_ptr<KeyTreeModel> m_model;
+  shared_ptr<KeyChain> m_keyChain;
+
+  shared_ptr<QStandardItemModel> m_tableModel;
+};
+
+} // namespace ncc
+} // namespace ndn
+
+#endif // NDN_NCC_KEY_VIEWER_DIALOG_HPP
diff --git a/src/key-viewer-dialog.ui b/src/key-viewer-dialog.ui
new file mode 100644
index 0000000..e3b6e38
--- /dev/null
+++ b/src/key-viewer-dialog.ui
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>KeyViewerDialog</class>
+ <widget class="QDialog" name="KeyViewerDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>800</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="maximumSize">
+   <size>
+    <width>960</width>
+    <height>720</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>NDN Key Viewer</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <property name="modal">
+   <bool>false</bool>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout_2">
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1">
+     <property name="sizeConstraint">
+      <enum>QLayout::SetMaximumSize</enum>
+     </property>
+     <item>
+      <widget class="QTreeView" name="treeView"/>
+     </item>
+     <item>
+      <widget class="QTableView" name="tableView"/>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/tray-menu.cpp b/src/tray-menu.cpp
index 115cec1..1d47216 100644
--- a/src/tray-menu.cpp
+++ b/src/tray-menu.cpp
@@ -46,11 +46,14 @@
   , m_entryPref(new QAction("Preferences...", m_menu))
   , m_entrySec(new QAction("Security", m_menu))
   , m_entryQuit(new QAction("Quit", m_menu))
+  , m_keyViewerDialog(new ncc::KeyViewerDialog)
 
 {
   connect(m_entryPref, SIGNAL(triggered()), this, SIGNAL(showApp()));
+  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);
 
diff --git a/src/tray-menu.hpp b/src/tray-menu.hpp
index 952260a..9e78abc 100644
--- a/src/tray-menu.hpp
+++ b/src/tray-menu.hpp
@@ -30,6 +30,8 @@
 
 #include <QtQml/QQmlContext>
 
+#include "key-viewer-dialog.hpp"
+
 namespace ndn {
 
 class TrayMenu : public QWidget
@@ -90,6 +92,8 @@
   QAction* m_entryPref;
   QAction* m_entrySec;
   QAction* m_entryQuit;
+
+  ncc::KeyViewerDialog* m_keyViewerDialog;
 };
 
 } // namespace ndn