Merge branch 'master' of git.irl.cs.ucla.edu:ndn/sync
diff --git a/demo/chatdialog.cpp b/demo/chatdialog.cpp
index c31a0bb..0f6e806 100644
--- a/demo/chatdialog.cpp
+++ b/demo/chatdialog.cpp
@@ -57,7 +57,15 @@
     std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
     syncPrefix += "/";
     syncPrefix += m_user.getChatroom().toStdString();
-    m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemove, this, _1));
+    try 
+    {
+      m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemove, this, _1));
+    }
+    catch (Sync::CcnxOperationException ex)
+    {
+      QMessageBox::critical(this, tr("Sync-Demo"), tr("Canno connect to ccnd.\n Have you started your ccnd?"), QMessageBox::Ok);
+      std::exit(1);
+    }
   }
 
   connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
@@ -79,6 +87,7 @@
 void
 ChatDialog::appendMessage(const SyncDemo::ChatMessage msg) 
 {
+  boost::mutex::scoped_lock lock(m_msgMutex);
 
   if (msg.type() != SyncDemo::ChatMessage::CHAT) {
     return;
@@ -125,7 +134,10 @@
   }
 
   // reflect the changes on digest tree
-  m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
+  {
+    boost::mutex::scoped_lock lock(m_sceneMutex);
+    m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
+  }
 
   int n = v.size();
   int totalMissingPackets = 0;
@@ -192,7 +204,10 @@
 #ifdef __DEBUG
   std::cout <<"<<< updating scene for" << prefix << ": " << msg.from()  << std::endl;
 #endif
-  m_scene->msgReceived(prefix.c_str(), msg.from().c_str());
+  {
+    boost::mutex::scoped_lock lock(m_sceneMutex);
+    m_scene->msgReceived(prefix.c_str(), msg.from().c_str());
+  }
   fitView();
 }
 
@@ -284,8 +299,11 @@
   Sync::MissingDataInfo mdi = {m_user.getPrefix().toStdString(), Sync::SeqNo(0), Sync::SeqNo(nextSequence - 1)};
   std::vector<Sync::MissingDataInfo> v;
   v.push_back(mdi);
-  m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
-  m_scene->msgReceived(m_user.getPrefix(), m_user.getNick());
+  {
+    boost::mutex::scoped_lock lock(m_sceneMutex);
+    m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
+    m_scene->msgReceived(m_user.getPrefix(), m_user.getNick());
+  }
   fitView();
 }
 
@@ -295,6 +313,16 @@
   SettingDialog dialog(this, m_user.getNick(), m_user.getChatroom(), m_user.getPrefix());
   connect(&dialog, SIGNAL(updated(QString, QString, QString)), this, SLOT(settingUpdated(QString, QString, QString)));
   dialog.exec();
+  QTimer::singleShot(100, this, SLOT(checkSetting()));
+}
+
+void
+ChatDialog::checkSetting()
+{
+  if (m_user.getPrefix().isEmpty() || m_user.getNick().isEmpty() || m_user.getChatroom().isEmpty())
+  {
+    buttonPressed();
+  }
 }
 
 void
@@ -314,8 +342,11 @@
     m_user.setChatroom(chatroom);
     needWrite = true;
 
-    m_scene->clearAll();
-    m_scene->plot("Empty");
+    {
+      boost::mutex::scoped_lock lock(m_sceneMutex);
+      m_scene->clearAll();
+      m_scene->plot("Empty");
+    }
     // TODO: perhaps need to do a lot. e.g. use a new SyncAppSokcet
     if (m_sock != NULL) 
     {
@@ -325,7 +356,15 @@
     std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
     syncPrefix += "/";
     syncPrefix += m_user.getChatroom().toStdString();
-    m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemove, this, _1));
+    try
+    {
+      m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemove, this, _1));
+    }
+    catch (Sync::CcnxOperationException ex)
+    {
+      QMessageBox::critical(this, tr("Sync-Demo"), tr("Canno connect to ccnd.\n Have you started your ccnd?"), QMessageBox::Ok);
+      std::exit(1);
+    }
 
     fitView();
     
@@ -351,6 +390,7 @@
 void
 ChatDialog::fitView()
 {
+  boost::mutex::scoped_lock lock(m_sceneMutex);
   QRectF rect = m_scene->itemsBoundingRect();
   m_scene->setSceneRect(rect);
   treeViewer->fitInView(m_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
diff --git a/demo/chatdialog.h b/demo/chatdialog.h
index 452fc2e..e5e0c34 100644
--- a/demo/chatdialog.h
+++ b/demo/chatdialog.h
@@ -1,6 +1,7 @@
 #ifndef CHATDIALOG_H
 #define CHATDIALOG_H
 #include <boost/function.hpp>
+#include <boost/thread/mutex.hpp>
 #include <vector>
 #include "digesttreescene.h"
 #include "ui_chatdialog.h"
@@ -41,6 +42,7 @@
 private slots:
   void returnPressed();
   void buttonPressed();
+  void checkSetting();
   void settingUpdated(QString, QString, QString);
 
 signals:
@@ -52,5 +54,7 @@
   Sync::SyncAppSocket *m_sock;
   uint32_t m_session;
   DigestTreeScene *m_scene;
+  boost::mutex m_msgMutex;
+  boost::mutex m_sceneMutex;
 };
 #endif
diff --git a/demo/settingdialog.cpp b/demo/settingdialog.cpp
index d9640dc..8f0bbca 100644
--- a/demo/settingdialog.cpp
+++ b/demo/settingdialog.cpp
@@ -6,8 +6,13 @@
   : QDialog(parent)
 {
   setupUi(this);
+
+  QRegExp noWhiteSpace("^\\S+.*$");
+  QValidator *nwsValidator = new QRegExpValidator(noWhiteSpace, this);
   nickEdit->setPlaceholderText(nick);
+  nickEdit->setValidator(nwsValidator);
   roomEdit->setPlaceholderText(chatroom);
+  roomEdit->setValidator(nwsValidator);
   prefixEdit->setPlaceholderText(prefix);
 
   // simple validator for ccnx prefix
@@ -15,7 +20,7 @@
   QValidator *validator = new QRegExpValidator(rx, this);
   prefixEdit->setValidator(validator);
 
-  cancelButton->setDefault(true);
+  okButton->setDefault(true);
 
   connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
   connect(okButton, SIGNAL(clicked()), this, SLOT(update()));