Add chatroom discovery UI

Change-Id: I94ee73ce9b4bcc63e7ecbdbf2f4844b6b57615a3
diff --git a/disabled/send-invitation-request-dialog.cpp b/disabled/send-invitation-request-dialog.cpp
new file mode 100644
index 0000000..8cc0640
--- /dev/null
+++ b/disabled/send-invitation-request-dialog.cpp
@@ -0,0 +1,99 @@
+#include "send-invitation-request-dialog.hpp"
+#include "ui_send-invitation-request-dialog.h"
+
+using namespace chronos;
+
+SendInvitationRequestDialog::SendInvitationRequestDialog(QWidget *parent) :
+  QDialog(parent),
+  ui(new Ui::SendInvitationRequestDialog),
+  m_stringListModel(new QStringListModel)
+{
+  ui->setupUi(this);
+  ui->contactsListView->setEditTriggers(ui->contactsListView->NoEditTriggers);
+  ui->contactsListView->setModel(m_stringListModel);
+
+  connect(ui->sendButton, SIGNAL(clicked()),
+          this, SLOT(onSendButtonClicked()));
+  connect(ui->cancelButton, SIGNAL(clicked()),
+          this, SLOT(onCancelButtonClicked()));
+  connect(ui->contactsListView, SIGNAL(clicked(QModelIndex)),
+          this, SLOT(onContactListViewClicked(QModelIndex)));
+  connect(ui->contactsListView,SIGNAL(doubleClicked(QModelIndex)),
+          this, SLOT(onContactListViewDoubleClicked(QModelIndex)));
+}
+
+SendInvitationRequestDialog::~SendInvitationRequestDialog()
+{
+  delete ui;
+}
+
+void
+SendInvitationRequestDialog::setContacts(const std::vector<ndn::Name>& contacts)
+{
+  QStringList contactsList;
+  for(int i = 0; i < contacts.size(); i++){
+    contactsList.append(QString::fromStdString(contacts[i].toUri()));
+  }
+  m_stringListModel->setStringList(contactsList);
+}
+
+void
+SendInvitationRequestDialog::onSendButtonClicked()
+{
+  if(ui->contactsListView->selectionModel()->selectedRows().size() == 0){
+    QMessageBox messageBox;
+    messageBox.addButton(QMessageBox::Ok);
+    messageBox.setIcon(QMessageBox::Information);
+    messageBox.setText("Please select a contact to send invitation request");
+    messageBox.exec();
+  }
+  else{
+    //send invitation request
+    int selectedRow = ui->contactsListView->selectionModel()->selectedRows()[0].row();
+    QString contactName = m_stringListModel->stringList()[selectedRow];
+    qDebug() << contactName;
+
+    QMessageBox messageBox;
+    messageBox.addButton(QMessageBox::Yes);
+    messageBox.addButton(QMessageBox::No);
+    messageBox.setIcon(QMessageBox::Question);
+    messageBox.setText("Send invitation request to "+ contactName +"?");
+
+    int selection = messageBox.exec();
+
+    if(selection == QMessageBox::Yes){
+      //send invitation request
+      //need to have another message box when successfully send
+      //emit sendInvitationRequest(m_chatroomName, contactName);
+    }
+  }
+}
+
+
+void
+SendInvitationRequestDialog::onCancelButtonClicked()
+{
+  //qDebug() << "cancel";
+  this->close();
+}
+
+void
+SendInvitationRequestDialog::onContactListViewClicked(QModelIndex modelIndex)
+{}
+
+void
+SendInvitationRequestDialog::onContactListViewDoubleClicked(QModelIndex modelIndex)
+{
+  onSendButtonClicked();
+}
+
+void
+SendInvitationRequestDialog::setChatroomName(const QString chatroomName)
+{
+  m_chatroomName = chatroomName;
+}
+
+
+#if WAF
+#include "send-invitation-request-dialog.moc"
+#endif
diff --git a/disabled/send-invitation-request-dialog.hpp b/disabled/send-invitation-request-dialog.hpp
new file mode 100644
index 0000000..ea86676
--- /dev/null
+++ b/disabled/send-invitation-request-dialog.hpp
@@ -0,0 +1,55 @@
+#ifndef SENDINVITATIONREQUESTDIALOG_H
+#define SENDINVITATIONREQUESTDIALOG_H
+
+#include <QDialog>
+#include <QStringListModel>
+#include <QMessageBox>
+#include <QDebug>
+#include <QAbstractItemView>
+
+#ifndef Q_MOC_RUN
+#include "chatroom-discovery.hpp"
+#endif
+
+namespace Ui {
+class SendInvitationRequestDialog;
+}
+
+namespace chronos {
+
+class SendInvitationRequestDialog : public QDialog
+{
+  Q_OBJECT
+
+public:
+  explicit SendInvitationRequestDialog(QWidget *parent = 0);
+  ~SendInvitationRequestDialog();
+
+  void
+  setContacts(const std::vector<ndn::Name>& contacts);
+
+  void
+  setChatroomName(const QString chatroomName);
+
+public slots:
+  void
+  onSendButtonClicked();
+
+  void
+  onCancelButtonClicked();
+
+  void
+  onContactListViewClicked(QModelIndex modelIndex);
+
+  void
+  onContactListViewDoubleClicked(QModelIndex modelIndex);
+
+private:
+  Ui::SendInvitationRequestDialog *ui;
+  QString m_chatroomName;
+  QStringListModel *m_stringListModel;
+};
+
+} //namespace chronos
+
+#endif // SENDINVITATIONREQUESTDIALOG_H
diff --git a/disabled/send-invitation-request-dialog.ui b/disabled/send-invitation-request-dialog.ui
new file mode 100644
index 0000000..1108478
--- /dev/null
+++ b/disabled/send-invitation-request-dialog.ui
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SendInvitationRequestDialog</class>
+ <widget class="QDialog" name="SendInvitationRequestDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>441</width>
+    <height>308</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <widget class="QLabel" name="introLabel">
+   <property name="geometry">
+    <rect>
+     <x>40</x>
+     <y>20</y>
+     <width>391</width>
+     <height>16</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Choose your contact to send invitation request:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QListView" name="contactsListView">
+   <property name="geometry">
+    <rect>
+     <x>40</x>
+     <y>50</y>
+     <width>351</width>
+     <height>192</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="sendButton">
+   <property name="geometry">
+    <rect>
+     <x>230</x>
+     <y>260</y>
+     <width>91</width>
+     <height>32</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Send</string>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="cancelButton">
+   <property name="geometry">
+    <rect>
+     <x>330</x>
+     <y>260</y>
+     <width>91</width>
+     <height>32</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Cancel</string>
+   </property>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/chatroom-discovery-dialog.cpp b/src/chatroom-discovery-dialog.cpp
new file mode 100644
index 0000000..327e4e7
--- /dev/null
+++ b/src/chatroom-discovery-dialog.cpp
@@ -0,0 +1,187 @@
+#include "chatroom-discovery-dialog.hpp"
+#include "ui_chatroom-discovery-dialog.h"
+
+namespace chronos {
+
+using std::vector;
+using ndn::Name;
+
+ChatroomDiscoveryDialog::ChatroomDiscoveryDialog(QWidget* parent)
+  : QDialog(parent)
+  , ui(new Ui::ChatroomDiscoveryDialog)
+  , m_standardItemModel(new QStandardItemModel(0, 3, this))
+  , m_chatroomDiscoveryViewDialog(new ChatroomDiscoveryViewDialog)
+{
+  ui->setupUi(this);
+
+  connect(ui->cancelButton, SIGNAL(clicked()),
+          this, SLOT(onCancelButtonClicked()));
+  connect(ui->joinButton, SIGNAL(clicked()),
+          this, SLOT(onJoinButtonClicked()));
+  connect(ui->viewButton, SIGNAL(clicked()),
+          this, SLOT(onViewButtonClicked()));
+  connect(ui->chatroomListView, SIGNAL(clicked(QModelIndex)),
+          this, SLOT(onChatroomListViewClicked(QModelIndex)));
+  connect(ui->chatroomListView, SIGNAL(doubleClicked(QModelIndex)),
+          this, SLOT(onChatroomListViewDoubleClicked(QModelIndex)));
+
+  updateChatroomList();
+}
+
+ChatroomDiscoveryDialog::~ChatroomDiscoveryDialog()
+{
+  delete ui;
+}
+
+void
+ChatroomDiscoveryDialog::updateChatroomList()
+{
+  m_standardItemModel->clear();
+
+  m_standardItemModel
+    ->setHorizontalHeaderItem(0, new QStandardItem(QString("Chatroom Name")));
+  m_standardItemModel
+    ->setHorizontalHeaderItem(1, new QStandardItem(QString("Chatroom Trust Model")));
+  m_standardItemModel
+    ->setHorizontalHeaderItem(2, new QStandardItem(QString("Participants or Contacts")));
+
+  QHeaderView *m_headerView = ui->chatroomListView->horizontalHeader();
+  m_headerView->setResizeMode((QHeaderView::ResizeMode)3);
+  m_headerView->setStretchLastSection(true);
+
+  ui->chatroomListView->setModel(m_standardItemModel);
+
+  int i = 0;
+  for (Chatrooms::const_iterator it = m_chatrooms.begin();
+       it != m_chatrooms.end(); ++it, ++i) {
+    QStandardItem *item = new QStandardItem(QString::fromStdString(it->first.toUri()));
+    item->setEditable(false);
+    m_standardItemModel->setItem(i, 0, item);
+
+    if (it->second.getTrustModel() == ChatroomInfo::TRUST_MODEL_WEBOFTRUST)
+      item = new QStandardItem(QString("Web of trust"));
+    else
+      item = new QStandardItem(QString("Hierarchical"));
+    item->setEditable(false);
+    m_standardItemModel->setItem(i, 1, item);
+
+    QString content;
+
+    for (vector<Name>::const_iterator nameIt = it->second.getParticipants().begin();
+         nameIt != it->second.getParticipants().end(); nameIt++) {
+      content.append(QString::fromStdString(nameIt->toUri())).append(",");
+    }
+    item = new QStandardItem(content);
+    item->setEditable(false);
+    m_standardItemModel->setItem(i, 2, item);
+  }
+}
+
+void
+ChatroomDiscoveryDialog::onDiscoverChatroomChanged(const chronos::ChatroomInfo& info, bool isAdd)
+{
+  if (isAdd)
+    m_chatrooms[info.getName()] = info;
+  else
+    m_chatrooms.erase(info.getName());
+
+  updateChatroomList();
+}
+
+void
+ChatroomDiscoveryDialog::onCancelButtonClicked()
+{
+  this->close();
+}
+
+void
+ChatroomDiscoveryDialog::onJoinButtonClicked()
+{
+  if(ui->chatroomListView->selectionModel()->selectedRows().size() == 0) {
+    QMessageBox::information(this, tr("ChronoChat"), tr("Please select a chatroom to join"));
+  }
+  else {
+    m_selectedRow = ui->chatroomListView->selectionModel()->selectedRows()[0].row();
+    QStandardItem* selectedChatroomName = m_standardItemModel->item(m_selectedRow, 0);
+    emit startChatroom(selectedChatroomName->text(), false);
+
+    {
+      // Tmp disabled
+      // QStandardItem* selectedChatroomTrustModel = m_standardItemModel->item(m_selectedRow, 1);
+      // if(selectedChatroomTrustModel->text() == "Hierarchical") {
+      //   emit startChatroom(selectedChatroomName->text(), false);
+      // }
+      // else if(selectedChatroomTrustModel->text() == "Web of trust") {
+      //   ChatroomDiscoveryLogic::ChatroomList::const_iterator it;
+      //   it = m_chatroomList->find(Name::Component(selectedChatroomName->text().toStdString()));
+
+      //   if(it->second.getContacts().size() == 0) {
+      //     QMessageBox messageBox;
+      //     messageBox.addButton(QMessageBox::Ok);
+      //     messageBox.setIcon(QMessageBox::Information);
+      //     messageBox.setText
+      //       ("You do not have a contact in this chatroom. Please choose another chatroom to join");
+      //     messageBox.exec();
+      //   }
+      //   else {
+      //     m_sendInvitationRequestDialog->setChatroomName(selectedChatroomName->text());
+      //     m_sendInvitationRequestDialog->setContacts(it->second.getContacts());
+      //     m_sendInvitationRequestDialog->show();
+      //   }
+      // }
+    }
+  }
+}
+
+void
+ChatroomDiscoveryDialog::onChatroomListViewDoubleClicked(const QModelIndex &index)
+{
+  onJoinButtonClicked();
+}
+
+void
+ChatroomDiscoveryDialog::onChatroomListViewClicked(const QModelIndex &index)
+{
+  ui->chatroomListView->selectRow(index.row());
+  m_selectedRow = index.row();
+}
+
+void
+ChatroomDiscoveryDialog::onViewButtonClicked()
+{
+  if(ui->chatroomListView->selectionModel()->selectedRows().size() == 0) {
+    QMessageBox messageBox;
+    messageBox.addButton(QMessageBox::Ok);
+    messageBox.setIcon(QMessageBox::Information);
+    messageBox.setText("Please select a chatroom to view");
+    messageBox.exec();
+  }
+  else {
+    m_selectedRow = ui->chatroomListView->selectionModel()->selectedRows()[0].row();
+
+    QStandardItem* selectedChatroomName = m_standardItemModel->item(m_selectedRow);
+    m_chatroomDiscoveryViewDialog->setChatroomName(selectedChatroomName->text());
+
+    // QStandardItem *m_selectedTrustModel = m_standardItemModel->item(m_selectedRow, 1);
+    // m_chatroomDiscoveryViewDialog->setChatroomTrustModel(m_selectedTrustModel->text());
+
+    //use chatroomlist as parameter to call set participants
+    //maybe for different chatroom with different trust model???
+    //participants can be contacts
+
+    Chatrooms::const_iterator it =
+      m_chatrooms.find(Name::Component(selectedChatroomName->text().toStdString()));
+
+    if (it != m_chatrooms.end()) {
+      m_chatroomDiscoveryViewDialog->setChatroomParticipants(it->second.getParticipants());
+      m_chatroomDiscoveryViewDialog->show();
+    }
+  }
+}
+
+} // namespace chronos
+
+
+#if WAF
+#include "chatroom-discovery-dialog.moc"
+#endif
diff --git a/src/chatroom-discovery-dialog.hpp b/src/chatroom-discovery-dialog.hpp
new file mode 100644
index 0000000..0193cbd
--- /dev/null
+++ b/src/chatroom-discovery-dialog.hpp
@@ -0,0 +1,87 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Mengjin Yan <jane.yan0129@gmail.com>
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+#ifndef CHRONOCHAT_CHATROOM_DISCOVERY_DIALOG_HPP
+#define CHRONOCHAT_CHATROOM_DISCOVERY_DIALOG_HPP
+
+#include <QDialog>
+#include <QModelIndex>
+#include <QStandardItem>
+#include <QHeaderView>
+#include <QMessageBox>
+#include <QDebug>
+#include "chatroom-discovery-view-dialog.hpp"
+
+#ifndef Q_MOC_RUN
+#include "chatroom-info.hpp"
+#endif
+
+namespace Ui {
+class ChatroomDiscoveryDialog;
+}
+
+namespace chronos {
+
+class ChatroomDiscoveryDialog : public QDialog
+{
+  Q_OBJECT
+
+public:
+  explicit
+  ChatroomDiscoveryDialog(QWidget* parent = 0);
+
+  ~ChatroomDiscoveryDialog();
+
+  void
+  updateChatroomList();
+
+signals:
+  void
+  startChatroom(const QString& chatroomName, bool secured);
+
+public slots:
+  void
+  onDiscoverChatroomChanged(const chronos::ChatroomInfo& chatroom, bool isAdd);
+
+private slots:
+  void
+  onCancelButtonClicked();
+
+  void
+  onJoinButtonClicked();
+
+  void
+  onViewButtonClicked();
+
+  void
+  onChatroomListViewDoubleClicked(const QModelIndex& index);
+
+  void
+  onChatroomListViewClicked(const QModelIndex& index);
+
+private:
+
+  typedef std::map<Name::Component, ChatroomInfo> Chatrooms;
+
+  Ui::ChatroomDiscoveryDialog *ui;
+  QStandardItemModel* m_standardItemModel;
+
+  int m_selectedRow;
+
+  Chatrooms m_chatrooms;
+
+
+
+  ChatroomDiscoveryViewDialog* m_chatroomDiscoveryViewDialog;
+};
+
+} //namespace chronos
+
+#endif // CHRONOCHAT_CHATROOM_DISCOVERY_DIALOG_HPP
diff --git a/src/chatroom-discovery-dialog.ui b/src/chatroom-discovery-dialog.ui
new file mode 100644
index 0000000..66df7ae
--- /dev/null
+++ b/src/chatroom-discovery-dialog.ui
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ChatroomDiscoveryDialog</class>
+ <widget class="QDialog" name="ChatroomDiscoveryDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>570</width>
+    <height>503</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>ChatroomDiscoveryDialog</string>
+  </property>
+  <widget class="QLabel" name="introLabel">
+   <property name="geometry">
+    <rect>
+     <x>50</x>
+     <y>30</y>
+     <width>451</width>
+     <height>16</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Here are the ongoing chatrooms:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QTableView" name="chatroomListView">
+   <property name="geometry">
+    <rect>
+     <x>40</x>
+     <y>60</y>
+     <width>491</width>
+     <height>371</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="viewButton">
+   <property name="geometry">
+    <rect>
+     <x>260</x>
+     <y>450</y>
+     <width>91</width>
+     <height>32</height>
+    </rect>
+   </property>
+   <property name="contextMenuPolicy">
+    <enum>Qt::DefaultContextMenu</enum>
+   </property>
+   <property name="text">
+    <string>View</string>
+   </property>
+   <property name="autoDefault">
+    <bool>false</bool>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="joinButton">
+   <property name="geometry">
+    <rect>
+     <x>360</x>
+     <y>450</y>
+     <width>91</width>
+     <height>32</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Join</string>
+   </property>
+   <property name="autoDefault">
+    <bool>false</bool>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="cancelButton">
+   <property name="geometry">
+    <rect>
+     <x>460</x>
+     <y>450</y>
+     <width>91</width>
+     <height>32</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Cancel</string>
+   </property>
+   <property name="autoDefault">
+    <bool>false</bool>
+   </property>
+  </widget>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/chatroom-discovery-view-dialog.cpp b/src/chatroom-discovery-view-dialog.cpp
new file mode 100644
index 0000000..7eff07b
--- /dev/null
+++ b/src/chatroom-discovery-view-dialog.cpp
@@ -0,0 +1,70 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Mengjin Yan <jane.yan0129@gmail.com>
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+#include "chatroom-discovery-view-dialog.hpp"
+#include "ui_chatroom-discovery-view-dialog.h"
+
+namespace chronos {
+
+using std::vector;
+using ndn::Name;
+
+ChatroomDiscoveryViewDialog::ChatroomDiscoveryViewDialog(QWidget* parent)
+  : QDialog(parent)
+  , ui(new Ui::ChatroomDiscoveryViewDialog)
+{
+  ui->setupUi(this);
+
+  ui->participantsBrowser->setReadOnly(true);
+
+  connect(ui->closeButton, SIGNAL(clicked()),
+          this, SLOT(onCloseButtonClicked()));
+}
+
+ChatroomDiscoveryViewDialog::~ChatroomDiscoveryViewDialog()
+{
+  delete ui;
+}
+
+void
+ChatroomDiscoveryViewDialog::onCloseButtonClicked()
+{
+  this->close();
+}
+
+void
+ChatroomDiscoveryViewDialog::setChatroomName(QString chatroomName)
+{
+  ui->chatroomNameLabel->setText("Chatroom Name: "+chatroomName);
+}
+
+void
+ChatroomDiscoveryViewDialog::setChatroomTrustModel(QString chatroomTrustModel)
+{
+  ui->chatroomTrustModelLabel->setText("Chatroom Trust Model: "+chatroomTrustModel);
+}
+
+void
+ChatroomDiscoveryViewDialog::setChatroomParticipants(const vector<Name>& participants)
+{
+  QString content;
+  for (vector<Name>::const_iterator it = participants.begin();
+       it != participants.end(); it++) {
+    content.append(QString::fromStdString(it->toUri())).append("\n");
+  }
+
+  ui->participantsBrowser->setPlainText(content);
+}
+
+} // namespace chronos
+
+#if WAF
+#include "chatroom-discovery-view-dialog.moc"
+#endif
diff --git a/src/chatroom-discovery-view-dialog.hpp b/src/chatroom-discovery-view-dialog.hpp
new file mode 100644
index 0000000..d074e71
--- /dev/null
+++ b/src/chatroom-discovery-view-dialog.hpp
@@ -0,0 +1,55 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Mengjin Yan <jane.yan0129@gmail.com>
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#ifndef CHRONOCHAT_CHATROOM_DISCOVERY_VIEW_DIALOG_HPP
+#define CHRONOCHAT_CHATROOM_DISCOVERY_VIEW_DIALOG_HPP
+
+#include <QDialog>
+
+#ifndef Q_MOC_RUN
+#include "common.hpp"
+#endif
+
+namespace Ui {
+class ChatroomDiscoveryViewDialog;
+}
+
+namespace chronos {
+
+class ChatroomDiscoveryViewDialog : public QDialog
+{
+  Q_OBJECT
+
+public:
+  explicit ChatroomDiscoveryViewDialog(QWidget* parent = 0);
+  ~ChatroomDiscoveryViewDialog();
+
+  void
+  setChatroomName(QString chatroomName);
+
+  void
+  setChatroomTrustModel(QString chatroomTrustModel);
+
+  void
+  setChatroomParticipants(const std::vector<ndn::Name>& chatroomParticipants);
+
+
+private slots:
+  void
+  onCloseButtonClicked();
+
+private:
+  Ui::ChatroomDiscoveryViewDialog* ui;
+};
+
+} //namespace chronos
+
+#endif // CHRONOCHAT_CHATROOM_DISCOVERY_VIEW_DIALOG_HPP
diff --git a/src/chatroom-discovery-view-dialog.ui b/src/chatroom-discovery-view-dialog.ui
new file mode 100644
index 0000000..74d6d94
--- /dev/null
+++ b/src/chatroom-discovery-view-dialog.ui
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ChatroomDiscoveryViewDialog</class>
+ <widget class="QDialog" name="ChatroomDiscoveryViewDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>514</width>
+    <height>402</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>ViewChatroom</string>
+  </property>
+  <widget class="QLabel" name="chatroomNameLabel">
+   <property name="geometry">
+    <rect>
+     <x>40</x>
+     <y>50</y>
+     <width>431</width>
+     <height>16</height>
+    </rect>
+   </property>
+   <property name="sizePolicy">
+    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+     <horstretch>0</horstretch>
+     <verstretch>0</verstretch>
+    </sizepolicy>
+   </property>
+   <property name="text">
+    <string/>
+   </property>
+  </widget>
+  <widget class="QLabel" name="chatroomTrustModelLabel">
+   <property name="geometry">
+    <rect>
+     <x>40</x>
+     <y>80</y>
+     <width>431</width>
+     <height>16</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QLabel" name="chatroomParcitipantsLabel">
+   <property name="geometry">
+    <rect>
+     <x>40</x>
+     <y>110</y>
+     <width>171</width>
+     <height>16</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Participants or Contacts:</string>
+   </property>
+  </widget>
+  <widget class="QTextBrowser" name="participantsBrowser">
+   <property name="geometry">
+    <rect>
+     <x>40</x>
+     <y>140</y>
+     <width>431</width>
+     <height>192</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="closeButton">
+   <property name="geometry">
+    <rect>
+     <x>360</x>
+     <y>350</y>
+     <width>114</width>
+     <height>32</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Close</string>
+   </property>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/controller.cpp b/src/controller.cpp
index 2ecae87..22af126 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -13,6 +13,7 @@
 #include <QDir>
 #include <QTimer>
 #include "controller.hpp"
+//#include "chatroom-discovery.h"
 
 #ifndef Q_MOC_RUN
 #include <boost/filesystem.hpp>
@@ -31,6 +32,7 @@
 Q_DECLARE_METATYPE(Chronos::EndorseInfo)
 Q_DECLARE_METATYPE(ndn::Interest)
 Q_DECLARE_METATYPE(size_t)
+Q_DECLARE_METATYPE(chronos::ChatroomInfo)
 
 namespace chronos {
 
@@ -50,6 +52,8 @@
   , m_face(face)
   , m_invitationListenerId(0)
   , m_contactManager(m_face)
+  , m_discoveryLogic(m_face,
+                     bind(&Controller::updateDiscoveryList, this, _1, _2))
   , m_settingDialog(new SettingDialog)
   , m_startChatDialog(new StartChatDialog)
   , m_profileEditor(new ProfileEditor)
@@ -57,12 +61,14 @@
   , m_contactPanel(new ContactPanel)
   , m_browseContactDialog(new BrowseContactDialog)
   , m_addContactPanel(new AddContactPanel)
+  , m_chatroomDiscoveryDialog(new ChatroomDiscoveryDialog)
 {
   qRegisterMetaType<ndn::Name>("ndn.Name");
   qRegisterMetaType<ndn::IdentityCertificate>("ndn.IdentityCertificate");
   qRegisterMetaType<Chronos::EndorseInfo>("Chronos.EndorseInfo");
   qRegisterMetaType<ndn::Interest>("ndn.Interest");
   qRegisterMetaType<size_t>("size_t");
+  qRegisterMetaType<chronos::ChatroomInfo>("chronos.Chatroom");
 
   connect(this, SIGNAL(localPrefixUpdated(const QString&)),
           this, SLOT(onLocalPrefixUpdated(const QString&)));
@@ -156,6 +162,14 @@
           m_contactPanel, SLOT(onContactInfoReady(const QString&, const QString&,
                                                   const QString&, bool)));
 
+  // Connection to DiscoveryDialog
+  connect(this,
+          SIGNAL(discoverChatroomChanged(const chronos::ChatroomInfo&, bool)),
+          m_chatroomDiscoveryDialog,
+          SLOT(onDiscoverChatroomChanged(const chronos::ChatroomInfo&, bool)));
+  connect(m_chatroomDiscoveryDialog, SIGNAL(startChatroom(const QString&, bool)),
+          this, SLOT(onStartChatroom(const QString&, bool)));
+
   initialize();
 
   createTrayIcon();
@@ -219,6 +233,8 @@
   emit identityUpdated(QString(m_identity.toUri().c_str()));
 
   setInvitationListener();
+
+  m_discoveryLogic.sendDiscoveryInterest();
 }
 
 void
@@ -295,6 +311,9 @@
   m_startChatroom = new QAction(tr("Start new chat"), this);
   connect(m_startChatroom, SIGNAL(triggered()), this, SLOT(onStartChatAction()));
 
+  m_discoveryAction = new QAction(tr("Ongoing Chatrooms"), this);
+  connect(m_discoveryAction, SIGNAL(triggered()), this, SLOT(onDiscoveryAction()));
+
   m_settingsAction = new QAction(tr("Settings"), this);
   connect(m_settingsAction, SIGNAL(triggered()), this, SLOT(onSettingsAction()));
 
@@ -315,6 +334,7 @@
 
   m_quitAction = new QAction(tr("Quit"), this);
   connect(m_quitAction, SIGNAL(triggered()), this, SLOT(onQuitAction()));
+
 }
 
 void
@@ -324,6 +344,8 @@
 
   m_trayIconMenu = new QMenu(this);
   m_trayIconMenu->addAction(m_startChatroom);
+  m_trayIconMenu->addAction(m_discoveryAction);
+
   m_trayIconMenu->addSeparator();
   m_trayIconMenu->addAction(m_settingsAction);
   m_trayIconMenu->addAction(m_editProfileAction);
@@ -354,6 +376,8 @@
   QMenu* closeMenu = 0;
 
   menu->addAction(m_startChatroom);
+  menu->addAction(m_discoveryAction);
+
   menu->addSeparator();
   menu->addAction(m_settingsAction);
   menu->addAction(m_editProfileAction);
@@ -400,8 +424,9 @@
     .trimmed();
 
   Name localPrefix(localPrefixStr.toStdString());
-  if (m_localPrefix.empty() || m_localPrefix != localPrefix)
+  if (m_localPrefix.empty() || m_localPrefix != localPrefix) {
     emit localPrefixUpdated(localPrefixStr);
+  }
 }
 
 void
@@ -410,8 +435,9 @@
   QString localPrefixStr("/private/local");
 
   Name localPrefix(localPrefixStr.toStdString());
-  if (m_localPrefix.empty() || m_localPrefix != localPrefix)
+  if (m_localPrefix.empty() || m_localPrefix != localPrefix) {
     emit localPrefixUpdated(localPrefixStr);
+  }
 }
 
 void
@@ -481,18 +507,22 @@
 Controller::addChatDialog(const QString& chatroomName, ChatDialog* chatDialog)
 {
   m_chatDialogList[chatroomName.toStdString()] = chatDialog;
+  m_discoveryLogic.addLocalChatroom(*chatDialog->getChatroomInfo());
   connect(chatDialog, SIGNAL(closeChatDialog(const QString&)),
           this, SLOT(onRemoveChatDialog(const QString&)));
   connect(chatDialog, SIGNAL(showChatMessage(const QString&, const QString&, const QString&)),
           this, SLOT(onShowChatMessage(const QString&, const QString&, const QString&)));
   connect(chatDialog, SIGNAL(resetIcon()),
           this, SLOT(onResetIcon()));
+  connect(chatDialog, SIGNAL(rosterChanged(const chronos::ChatroomInfo&)),
+          this, SLOT(onRosterChanged(const chronos::ChatroomInfo&)));
   connect(this, SIGNAL(localPrefixUpdated(const QString&)),
           chatDialog, SLOT(onLocalPrefixUpdated(const QString&)));
 
   QAction* chatAction = new QAction(chatroomName, this);
   m_chatActionList[chatroomName.toStdString()] = chatAction;
-  connect(chatAction, SIGNAL(triggered()), chatDialog, SLOT(raise()));
+  connect(chatAction, SIGNAL(triggered()),
+          chatDialog, SLOT(raise()));//ymj
 
   QAction* closeAction = new QAction(chatroomName, this);
   m_closeActionList[chatroomName.toStdString()] = closeAction;
@@ -501,7 +531,12 @@
   updateMenu();
 }
 
-// private slots:
+void
+Controller::updateDiscoveryList(const ChatroomInfo& info, bool isAdd)
+{
+  emit discoverChatroomChanged(info, isAdd);
+}
+
 void
 Controller::onIdentityUpdated(const QString& identity)
 {
@@ -571,6 +606,17 @@
 }
 
 void
+Controller::onDiscoveryAction()
+{
+  m_discoveryLogic.sendDiscoveryInterest();
+
+  m_chatroomDiscoveryDialog->updateChatroomList();
+  m_chatroomDiscoveryDialog->show();
+  m_chatroomDiscoveryDialog->raise();
+}
+
+
+void
 Controller::onSettingsAction()
 {
   m_settingDialog->setNick(QString(m_nick.c_str()));
@@ -675,16 +721,22 @@
     return;
   }
 
-  // TODO: We should create a chatroom specific key/cert (which should be created in the first half of this method, but let's use the default one for now.
-  shared_ptr<IdentityCertificate> idCert = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
-  ChatDialog* chatDialog = new ChatDialog(&m_contactManager, m_face, *idCert, chatroomPrefix, m_localPrefix, m_nick, secured);
+  // TODO: We should create a chatroom specific key/cert
+  //(which should be created in the first half of this method
+  //, but let's use the default one for now.
+  // std::cout << "start chat room localprefix: " << m_localPrefix.toUri() << std::endl;
+  shared_ptr<IdentityCertificate> idCert
+    = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
+  ChatDialog* chatDialog
+    = new ChatDialog(&m_contactManager, m_face, *idCert, chatroomPrefix
+                     , m_localPrefix, m_nick, secured);
 
   addChatDialog(chatroomName, chatDialog);
   chatDialog->show();
 }
 
 void
-Controller::onInvitationResponded(const Name& invitationName, bool accepted)
+Controller::onInvitationResponded(const ndn::Name& invitationName, bool accepted)
 {
   Data response;
   shared_ptr<IdentityCertificate> chatroomCert;
@@ -696,8 +748,10 @@
 
     response.setName(responseName);
 
-    // We should create a particular certificate for this chatroom, but let's use default one for now.
-    chatroomCert = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
+    // We should create a particular certificate for this chatroom,
+    //but let's use default one for now.
+    chatroomCert
+      = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
 
     response.setContent(chatroomCert->wireEncode());
     response.setFreshnessPeriod(time::milliseconds(1000));
@@ -738,9 +792,14 @@
       .append("ChronoChat")
       .append(invitation.getChatroom());
 
-    //We should create a chatroom specific key/cert (which should be created in the first half of this method, but let's use the default one for now.
-    shared_ptr<IdentityCertificate> idCert = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
-    ChatDialog* chatDialog = new ChatDialog(&m_contactManager, m_face, *idCert, chatroomPrefix, m_localPrefix, m_nick, true);
+    //We should create a chatroom specific key/cert
+    //(which should be created in the first half of this method,
+    //but let's use the default one for now.
+    shared_ptr<IdentityCertificate> idCert
+      = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
+    ChatDialog* chatDialog
+      = new ChatDialog(&m_contactManager, m_face, *idCert,
+                       chatroomPrefix, m_localPrefix, m_nick, true);
     chatDialog->addSyncAnchor(invitation);
 
     addChatDialog(QString::fromStdString(invitation.getChatroom()), chatDialog);
@@ -773,6 +832,7 @@
     if (deletedChat)
       delete deletedChat;
     m_chatDialogList.erase(it);
+    m_discoveryLogic.removeLocalChatroom(Name::Component(chatroomName.toStdString()));
 
     QAction* chatAction = m_chatActionList[chatroomName.toStdString()];
     QAction* closeAction = m_closeActionList[chatroomName.toStdString()];
@@ -802,8 +862,8 @@
 }
 
 void
-Controller::onInvitationInterest(const Name& prefix,
-                                 const Interest& interest,
+Controller::onInvitationInterest(const ndn::Name& prefix,
+                                 const ndn::Interest& interest,
                                  size_t routingPrefixOffset)
 {
   // _LOG_DEBUG("onInvitationInterest: " << interest.getName());
@@ -827,6 +887,12 @@
   m_validator.validate(*invitationInterest, onValidated, onValidationFailed);
 }
 
+void
+Controller::onRosterChanged(const chronos::ChatroomInfo& info)
+{
+  m_discoveryLogic.addLocalChatroom(info);
+}
+
 } // namespace chronos
 
 #if WAF
diff --git a/src/controller.hpp b/src/controller.hpp
index 6641b20..c489470 100644
--- a/src/controller.hpp
+++ b/src/controller.hpp
@@ -24,10 +24,12 @@
 #include "browse-contact-dialog.hpp"
 #include "add-contact-panel.hpp"
 #include "chat-dialog.hpp"
+#include "chatroom-discovery-dialog.hpp"
 
 #ifndef Q_MOC_RUN
 #include "common.hpp"
 #include "contact-manager.hpp"
+#include "chatroom-discovery-logic.hpp"
 #include "validator-invitation.hpp"
 #include <ndn-cxx/security/key-chain.hpp>
 #endif
@@ -101,6 +103,9 @@
   void
   addChatDialog(const QString& chatroomName, ChatDialog* chatDialog);
 
+  void
+  updateDiscoveryList(const chronos::ChatroomInfo& chatroomName, bool isAdd);
+
 signals:
   void
   closeDBModule();
@@ -115,7 +120,11 @@
   refreshBrowseContact();
 
   void
-  invitationInterest(const Name& prefix, const Interest& interest, size_t routingPrefixOffset);
+  invitationInterest(const ndn::Name& prefix, const ndn::Interest& interest,
+                     size_t routingPrefixOffset);
+
+  void
+  discoverChatroomChanged(const chronos::ChatroomInfo& chatroomInfo, bool isAdd);
 
 private slots:
   void
@@ -137,6 +146,9 @@
   onStartChatAction();
 
   void
+  onDiscoveryAction();
+
+  void
   onSettingsAction();
 
   void
@@ -164,7 +176,7 @@
   onStartChatroom(const QString& chatroom, bool secured);
 
   void
-  onInvitationResponded(const Name& invitationName, bool accepted);
+  onInvitationResponded(const ndn::Name& invitationName, bool accepted);
 
   void
   onShowChatMessage(const QString& chatroomName, const QString& from, const QString& data);
@@ -185,6 +197,9 @@
   onInvitationInterest(const ndn::Name& prefix, const ndn::Interest& interest,
                        size_t routingPrefixOffset);
 
+  void
+  onRosterChanged(const chronos::ChatroomInfo& info);
+
 private: // private member
   typedef std::map<std::string, QAction*> ChatActionList;
   typedef std::map<std::string, ChatDialog*> ChatDialogList;
@@ -197,8 +212,12 @@
   // Contact Manager
   ContactManager m_contactManager;
 
+  // Chatroom discovery
+  ChatroomDiscoveryLogic m_discoveryLogic;
+
   // Tray
   QAction*         m_startChatroom;
+  QAction*         m_discoveryAction;
   QAction*         m_minimizeAction;
   QAction*         m_settingsAction;
   QAction*         m_editProfileAction;
@@ -221,6 +240,7 @@
   BrowseContactDialog* m_browseContactDialog;
   AddContactPanel*     m_addContactPanel;
   ChatDialogList       m_chatDialogList;
+  ChatroomDiscoveryDialog* m_chatroomDiscoveryDialog;
 
   // Conf
   Name m_identity;