chatdialog: Fix issue of creating QObjects in different thread.

Change-Id: I2f0dc2006cc330cd9d4fc5973eb475d841103b59
diff --git a/src/chatdialog.cpp b/src/chatdialog.cpp
index e43aa78..6603183 100644
--- a/src/chatdialog.cpp
+++ b/src/chatdialog.cpp
@@ -77,7 +77,7 @@
   m_localChatPrefix.append("chronos").append(m_chatroomPrefix.get(-1)).append(randString.toStdString());
 
   m_session = static_cast<uint64_t>(time::now());
-  m_scene = new DigestTreeScene(this);
+  m_scene = new DigestTreeScene(m_ioService, this);
 
   initializeSetting();
   updateLabels();
@@ -122,6 +122,19 @@
           this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
   connect(m_scene, SIGNAL(rosterChanged(QStringList)), 
           this, SLOT(updateRosterList(QStringList)));
+  connect(this, SIGNAL(triggerHello()),
+          this, SLOT(sendHello()));
+  connect(this, SIGNAL(triggerJoin()),
+          this, SLOT(sendJoin()));
+  connect(this, SIGNAL(triggerLeave()),
+          this, SLOT(sendLeave()));
+  connect(this, SIGNAL(triggerReplot()),
+          this, SLOT(replot()));
+  connect(this, SIGNAL(triggerEnableTreeDisplay()),
+          this, SLOT(enableTreeDisplay()));
+  connect(this, SIGNAL(triggerReap()),
+          this, SLOT(reap()));
+  
 
 
   initializeSync();
@@ -180,14 +193,14 @@
   
   usleep(100000);
 
-  m_scheduler.scheduleEvent(time::milliseconds(600), bind(&ChatDialog::sendJoin, this));
+  m_scheduler.scheduleEvent(time::milliseconds(600), bind(&ChatDialog::sendJoinWrapper, this));
 
   if(static_cast<bool>(m_replotEventId))
     m_scheduler.cancelEvent(m_replotEventId);
   m_replotEventId = m_scheduler.schedulePeriodicEvent(time::seconds(0), time::milliseconds(FRESHNESS * 1000),
-                                                      bind(&ChatDialog::replot, this));
+                                                      bind(&ChatDialog::replotWrapper, this));
   disableTreeDisplay();
-  m_scheduler.scheduleEvent(time::milliseconds(2200), bind(&ChatDialog::enableTreeDisplay, this));
+  m_scheduler.scheduleEvent(time::milliseconds(2200), bind(&ChatDialog::enableTreeDisplayWrapper, this));
 }
 
 void
@@ -386,6 +399,10 @@
 }
 
 void
+ChatDialog::enableTreeDisplayWrapper()
+{ emit triggerEnableTreeDisplay(); }
+
+void
 ChatDialog::processTreeUpdateWrapper(const vector<Sync::MissingDataInfo>& v, Sync::SyncSocket *sock)
 {
   emit treeUpdated(v);
@@ -520,10 +537,14 @@
   boost::random::random_device rng;
   boost::random::uniform_int_distribution<> uniform(1, FRESHNESS / 5 * 1000);
   m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
-  m_scheduler.scheduleEvent(time::milliseconds(m_randomizedInterval), bind(&ChatDialog::sendHello, this));
+  m_scheduler.scheduleEvent(time::milliseconds(m_randomizedInterval), bind(&ChatDialog::sendHelloWrapper, this));
 }
 
 void
+ChatDialog::sendJoinWrapper()
+{ emit triggerJoin(); }
+
+void
 ChatDialog::sendHello()
 {
   int64_t now = time::now();
@@ -536,16 +557,20 @@
     boost::random::random_device rng;
     boost::random::uniform_int_distribution<> uniform(1, FRESHNESS / 5 * 1000);
     m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
-    m_scheduler.scheduleEvent(time::milliseconds(m_randomizedInterval), bind(&ChatDialog::sendHello, this));
+    m_scheduler.scheduleEvent(time::milliseconds(m_randomizedInterval), bind(&ChatDialog::sendHelloWrapper, this));
   }
   else
   {
     m_scheduler.scheduleEvent(time::milliseconds(m_randomizedInterval - elapsed * 1000), 
-                              bind(&ChatDialog::sendHello, this));
+                              bind(&ChatDialog::sendHelloWrapper, this));
   }
 }
 
 void
+ChatDialog::sendHelloWrapper()
+{ emit triggerHello(); }
+
+void
 ChatDialog::sendLeave()
 {
   SyncDemo::ChatMessage msg;
@@ -559,6 +584,10 @@
 }
 
 void
+ChatDialog::sendLeaveWrapper()
+{ emit triggerLeave(); }
+
+void
 ChatDialog::replot()
 {
   boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
@@ -567,6 +596,10 @@
 }
 
 void
+ChatDialog::replotWrapper()
+{ emit triggerReplot(); }
+
+void
 ChatDialog::summonReaper()
 {
   Sync::SyncLogic &logic = m_sock->getLogic ();
@@ -617,11 +650,15 @@
     m_zombieIndex++;
     // reap again in 10 seconds
     m_scheduler.scheduleEvent(time::milliseconds(10000), 
-                              bind(&ChatDialog::reap, this));
+                              bind(&ChatDialog::reapWrapper, this));
   }
 }
 
 void
+ChatDialog::reapWrapper()
+{ emit triggerReap(); }
+
+void
 ChatDialog::updateRosterList(QStringList staleUserList)
 {
   boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
@@ -702,13 +739,13 @@
                                     bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2),
                                     bind(&ChatDialog::processRemoveWrapper, this, _1));
       usleep(100000);
-      m_scheduler.scheduleEvent(time::milliseconds(600), bind(&ChatDialog::sendJoin, this));
+      m_scheduler.scheduleEvent(time::milliseconds(600), bind(&ChatDialog::sendJoinWrapper, this));
       if(static_cast<bool>(m_replotEventId))
         m_scheduler.cancelEvent(m_replotEventId);
       m_replotEventId = m_scheduler.schedulePeriodicEvent(time::seconds(0), time::milliseconds(FRESHNESS * 1000),
-                                                          bind(&ChatDialog::replot, this));
+                                                          bind(&ChatDialog::replotWrapper, this));
       disableTreeDisplay();
-      m_scheduler.scheduleEvent(time::milliseconds(2200), bind(&ChatDialog::enableTreeDisplay, this));
+      m_scheduler.scheduleEvent(time::milliseconds(2200), bind(&ChatDialog::enableTreeDisplayWrapper, this));
     }catch(Face::Error& e){
       emit noNdnConnection(QString::fromStdString("Cannot conect to ndnd!\n Have you started your ndnd?"));
     }
diff --git a/src/chatdialog.h b/src/chatdialog.h
index 742b4ee..5b7eea2 100644
--- a/src/chatdialog.h
+++ b/src/chatdialog.h
@@ -16,7 +16,6 @@
 #include <QDialog>
 #include <QTextTable>
 #include <QStringListModel>
-#include <QTimer>
 #include <QSystemTrayIcon>
 #include <QMenu>
 
@@ -233,6 +232,24 @@
   void
   inivationRejection(const QString& msg);
 
+  void
+  triggerHello();
+             
+  void
+  triggerJoin();
+  
+  void
+  triggerLeave();
+
+  void
+  triggerReplot();
+
+  void
+  triggerEnableTreeDisplay();
+
+  void
+  triggerReap();
+
 public slots:
   void 
   processTreeUpdate(const std::vector<Sync::MissingDataInfo>&);
@@ -253,18 +270,30 @@
   void
   settingUpdated(QString, QString, QString);
 
+  void
+  sendJoinWrapper();
+
   void 
   sendJoin();
 
   void
+  sendHelloWrapper();
+  
+  void
   sendHello();
 
   void
   sendLeave();
 
+  void
+  sendLeaveWrapper();
+
   void 
   replot();
 
+  void
+  replotWrapper();
+
   void 
   updateRosterList(QStringList);
 
@@ -272,6 +301,9 @@
   enableTreeDisplay();
 
   void
+  enableTreeDisplayWrapper();
+
+  void
   updateLocalPrefix();
 
   void 
@@ -280,6 +312,9 @@
   void
   reap();
 
+  void
+  reapWrapper();
+
   void 
   iconActivated(QSystemTrayIcon::ActivationReason reason);
 
diff --git a/src/digesttreescene.cpp b/src/digesttreescene.cpp
index c2aa865..d692d4e 100644
--- a/src/digesttreescene.cpp
+++ b/src/digesttreescene.cpp
@@ -25,8 +25,10 @@
 
 //DisplayUserPtr DisplayUserNullPtr;
 
-DigestTreeScene::DigestTreeScene(QWidget *parent)
+DigestTreeScene::DigestTreeScene(ndn::shared_ptr<boost::asio::io_service> ioService,
+                                 QWidget *parent)
   : QGraphicsScene(parent)
+  , m_scheduler(*ioService)
 {
   previouslyUpdatedUser = DisplayUserNullPtr;
 }
@@ -58,7 +60,7 @@
   if (rePlot) 
   {
     plot(digest);
-    QTimer::singleShot(2100, this, SLOT(emitReplot()));
+    m_scheduler.scheduleEvent(ndn::time::milliseconds(600), ndn::bind(&DigestTreeScene::emitReplot, this));
   }
   else 
   {
diff --git a/src/digesttreescene.h b/src/digesttreescene.h
index e7600e8..c239a49 100644
--- a/src/digesttreescene.h
+++ b/src/digesttreescene.h
@@ -19,6 +19,7 @@
 #include <QMap>
 
 #ifndef Q_MOC_RUN
+#include <ndn-cpp-dev/util/scheduler.hpp>
 #include <sync-seq-no.h>
 #include <sync-logic.h>
 #include <ctime>
@@ -44,7 +45,8 @@
 typedef QMapIterator<QString, DisplayUserPtr> RosterIterator;
 
 public:
-  DigestTreeScene(QWidget *parent = 0);
+  DigestTreeScene(ndn::shared_ptr<boost::asio::io_service> ioService,
+                  QWidget *parent = 0);
   void processUpdate(const std::vector<Sync::MissingDataInfo> &v, QString digest);
   void msgReceived(QString prefix, QString nick);
   void clearAll();
@@ -65,12 +67,13 @@
   void plotEdge(const std::vector<TreeLayout::Coordinate> &v, int nodeSize);
   void plotNode(const std::vector<TreeLayout::Coordinate> &v, QString digest, int nodeSize);
   void reDrawNode(DisplayUserPtr p, QColor rimColor);
+
 private:
   Roster m_roster;
   QGraphicsTextItem *m_rootDigest; 
   DisplayUserPtr previouslyUpdatedUser;
   QString m_currentPrefix;
-
+  ndn::Scheduler m_scheduler;
 };
 
 class User