Merge branch 'master' of git.irl.cs.ucla.edu:ndn/sync
diff --git a/demo/chatdialog.cpp b/demo/chatdialog.cpp
index 10c7af0..c31a0bb 100644
--- a/demo/chatdialog.cpp
+++ b/demo/chatdialog.cpp
@@ -4,12 +4,39 @@
 #include <ctime>
 #include <iostream>
 #include <QTimer>
+#include <QMetaType>
 
 #define BROADCAST_PREFIX_FOR_SYNC_DEMO "/ndn/broadcast/sync-demo"
 
+void
+ChatDialog::testDraw()
+{
+  std::string prefix[5] = {"/ndn/1", "/ndn/2", "/ndn/3", "/ndn/4", "/ndn/5"};
+  std::string nick[5] = {"tom", "jerry", "jason", "michael", "hurry"};
+  std::vector<Sync::MissingDataInfo> v;
+  for (int i = 0; i < 5; i++)
+  {
+    Sync::MissingDataInfo mdi = {prefix[i], Sync::SeqNo(0), Sync::SeqNo(i * (2 << i) )};
+    v.push_back(mdi);
+  }
+
+  m_scene->processUpdate(v, "12341234@!#%!@");
+
+  for (int i = 0; i < 5; i++)
+  {
+   m_scene-> msgReceived(prefix[i].c_str(), nick[i].c_str());
+  }
+
+  fitView();
+}
+
 ChatDialog::ChatDialog(QWidget *parent)
   : QDialog(parent), m_sock(NULL)
 {
+  // have to register this, otherwise
+  // the signal-slot system won't recognize this type
+  qRegisterMetaType<std::vector<Sync::MissingDataInfo> >("std::vector<Sync::MissingDataInfo>");
+  qRegisterMetaType<size_t>("size_t");
   setupUi(this);
   m_session = time(NULL);
 
@@ -30,11 +57,14 @@
     std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
     syncPrefix += "/";
     syncPrefix += m_user.getChatroom().toStdString();
-    m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdate, this, _1, _2), bind(&ChatDialog::processRemove, this, _1));
+    m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemove, this, _1));
   }
 
   connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
   connect(setButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
+  connect(this, SIGNAL(dataReceived(QString, const char *, size_t)), this, SLOT(processData(QString, const char *, size_t)));
+  connect(this, SIGNAL(treeUpdated(const std::vector<Sync::MissingDataInfo>)), this, SLOT(processTreeUpdate(const std::vector<Sync::MissingDataInfo>)));
+  //testDraw();
 }
 
 ChatDialog::~ChatDialog()
@@ -47,7 +77,7 @@
 }
 
 void
-ChatDialog::appendMessage(const SyncDemo::ChatMessage &msg) 
+ChatDialog::appendMessage(const SyncDemo::ChatMessage msg) 
 {
 
   if (msg.type() != SyncDemo::ChatMessage::CHAT) {
@@ -75,8 +105,20 @@
 }
 
 void
-ChatDialog::processTreeUpdate(const std::vector<Sync::MissingDataInfo> &v, Sync::SyncAppSocket *)
+ChatDialog::processTreeUpdateWrapper(const std::vector<Sync::MissingDataInfo> v, Sync::SyncAppSocket *sock)
 {
+  emit treeUpdated(v);
+#ifdef __DEBUG
+  std::cout << "<<< Tree update signal emitted" << std::endl;
+#endif
+}
+
+void
+ChatDialog::processTreeUpdate(const std::vector<Sync::MissingDataInfo> v)
+{
+#ifdef __DEBUG
+  std::cout << "<<< processing Tree Update" << std::endl;
+#endif
   if (v.empty())
   {
     return;
@@ -97,7 +139,10 @@
     {
       for (Sync::SeqNo seq = v[i].low; seq <= v[i].high; ++seq)
       {
-        m_sock->fetchRaw(v[i].prefix, seq, bind(&ChatDialog::processData, this, _1, _2, _3), 2);
+        m_sock->fetchRaw(v[i].prefix, seq, bind(&ChatDialog::processDataWrapper, this, _1, _2, _3), 2);
+#ifdef __DEBUG
+        std::cout << "<<< Fetching " << v[i].prefix << "/" <<seq.getSession() <<"/" << seq.getSeq() << std::endl;
+#endif
       }
     }
   }
@@ -115,7 +160,16 @@
 }
 
 void
-ChatDialog::processData(std::string name, const char *buf, size_t len)
+ChatDialog::processDataWrapper(std::string name, const char *buf, size_t len)
+{
+  emit dataReceived(name.c_str(), buf, len);
+#ifdef __DEBUG
+  std::cout <<"<<< " << name << " fetched" << std::endl;
+#endif
+}
+
+void
+ChatDialog::processData(QString name, const char *buf, size_t len)
 {
   SyncDemo::ChatMessage msg;
   if (!msg.ParseFromArray(buf, len)) 
@@ -124,12 +178,22 @@
     abort();
   }
 
-  // display
+  // display msg received from network
+  // we have to do so; this function is called by ccnd thread
+  // so if we call appendMsg directly
+  // Qt crash as "QObject: Cannot create children for a parent that is in a different thread"
+  // the "cannonical" way to is use signal-slot
   appendMessage(msg);
   
   // update the tree view
-  std::string prefix = name.substr(0, name.find_last_of('/'));
+  std::string stdStrName = name.toStdString();
+  std::string stdStrNameWithoutSeq = stdStrName.substr(0, stdStrName.find_last_of('/'));
+  std::string prefix = stdStrNameWithoutSeq.substr(0, stdStrNameWithoutSeq.find_last_of('/'));
+#ifdef __DEBUG
+  std::cout <<"<<< updating scene for" << prefix << ": " << msg.from()  << std::endl;
+#endif
   m_scene->msgReceived(prefix.c_str(), msg.from().c_str());
+  fitView();
 }
 
 void
@@ -150,6 +214,7 @@
 bool
 ChatDialog::readSettings()
 {
+#ifndef __DEBUG
   QSettings s(ORGANIZATION, APPLICATION);
   QString nick = s.value("nick", "").toString();
   QString chatroom = s.value("chatroom", "").toString();
@@ -164,15 +229,21 @@
     m_user.setPrefix(prefix);
     return true;
   }
+#else
+  QTimer::singleShot(500, this, SLOT(buttonPressed()));
+  return false;
+#endif
 }
 
 void 
 ChatDialog::writeSettings()
 {
+#ifndef __DEBUG
   QSettings s(ORGANIZATION, APPLICATION);
   s.setValue("nick", m_user.getNick());
   s.setValue("chatroom", m_user.getChatroom());
   s.setValue("prefix", m_user.getPrefix());
+#endif
 }
 
 void
@@ -208,7 +279,14 @@
     abort();
   }
   m_sock->publishRaw(m_user.getPrefix().toStdString(), m_session, buf, size, 60);
-  
+
+  int nextSequence = m_sock->getNextSeq(m_user.getPrefix().toStdString(), m_session);
+  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());
+  fitView();
 }
 
 void
@@ -247,7 +325,7 @@
     std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
     syncPrefix += "/";
     syncPrefix += m_user.getChatroom().toStdString();
-    m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdate, this, _1, _2), bind(&ChatDialog::processRemove, this, _1));
+    m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemove, this, _1));
 
     fitView();
     
@@ -273,5 +351,7 @@
 void
 ChatDialog::fitView()
 {
+  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 252144b..452fc2e 100644
--- a/demo/chatdialog.h
+++ b/demo/chatdialog.h
@@ -19,10 +19,14 @@
 public:
 	ChatDialog(QWidget *parent = 0);
   ~ChatDialog();
-  void appendMessage(const SyncDemo::ChatMessage &msg);
-  void processTreeUpdate(const std::vector<Sync::MissingDataInfo> &, Sync::SyncAppSocket *);
-  void processData(std::string, const char *buf, size_t len);
   void processRemove(const std::string);
+  void appendMessage(const SyncDemo::ChatMessage msg);
+  void processTreeUpdateWrapper(const std::vector<Sync::MissingDataInfo>, Sync::SyncAppSocket *);
+  void processDataWrapper(std::string, const char *buf, size_t len);
+
+public slots:
+  void processTreeUpdate(const std::vector<Sync::MissingDataInfo>);
+  void processData(QString name, const char *buf, size_t len);
 
 private:
   void formChatMessage(const QString &text, SyncDemo::ChatMessage &msg);
@@ -32,12 +36,17 @@
   void resizeEvent(QResizeEvent *);
   void showEvent(QShowEvent *);
   void fitView();
+  void testDraw();
 
 private slots:
   void returnPressed();
   void buttonPressed();
   void settingUpdated(QString, QString, QString);
 
+signals:
+  void dataReceived(QString name, const char *buf, size_t len);
+  void treeUpdated(const std::vector<Sync::MissingDataInfo>);
+
 private:
   User m_user; 
   Sync::SyncAppSocket *m_sock;
diff --git a/demo/digesttreescene.cpp b/demo/digesttreescene.cpp
index 0dd7a10..30c087e 100644
--- a/demo/digesttreescene.cpp
+++ b/demo/digesttreescene.cpp
@@ -1,34 +1,13 @@
-#include "digesttreescene.h"
 #include <QtGui>
-#include "ogdf/basic/Array.h"
-#include "ogdf/basic/Graph_d.h"
-#include "ogdf/tree/TreeLayout.h"
 #include <vector>
 #include <iostream>
 #include <assert.h>
 #include <boost/lexical_cast.hpp>
+#include <memory>
+#include "digesttreescene.h"
 
 static const double Pi = 3.14159265358979323846264338327950288419717;
 
-static void 
-testDraw(DigestTreeScene * scene) 
-{
-  std::string prefix[5] = {"/ndn/1", "/ndn/2", "/ndn/3", "/ndn/4", "/ndn/5"};
-  std::string nick[5] = {"tom", "jerry", "jason", "michael", "hurry"};
-  std::vector<Sync::MissingDataInfo> v;
-  for (int i = 0; i < 5; i++)
-  {
-    Sync::MissingDataInfo mdi = {prefix[i], Sync::SeqNo(0), Sync::SeqNo(i * (2 << i) )};
-    v.push_back(mdi);
-  }
-
-  scene->processUpdate(v, "12341234@!#%!@");
-
-  for (int i = 0; i < 5; i++)
-  {
-   scene-> msgReceived(prefix[i].c_str(), nick[i].c_str());
-  }
-}
 
 DigestTreeScene::DisplayUserPtr DigestTreeScene::DisplayUserNullPtr;
 
@@ -36,7 +15,6 @@
   : QGraphicsScene(parent)
 {
   previouslyUpdatedUser = DisplayUserNullPtr;
-//  testDraw(this);
 }
 
 void
@@ -47,13 +25,18 @@
   for (int i = 0; i < n; i++) 
   {
     Roster_iterator it = m_roster.find(v[i].prefix.c_str());
-    if (it == m_roster.end()) {
+    if (it == m_roster.end()) 
+    {
       rePlot = true; 
       DisplayUserPtr p(new DisplayUser());
       p->setPrefix(v[i].prefix.c_str());
       p->setSeq(v[i].high);
       m_roster.insert(p->getPrefix(), p);
     }
+    else 
+    {
+      it.value()->setSeq(v[i].high);
+    }
   }
 
   if (rePlot) 
@@ -83,6 +66,9 @@
 void
 DigestTreeScene::msgReceived(QString prefix, QString nick)
 {
+#ifdef __DEBUG
+  std::cout << "Finding " << prefix.toStdString() << std::endl;
+#endif
   Roster_iterator it = m_roster.find(prefix);
   if (it != m_roster.end()) 
   {
@@ -99,20 +85,31 @@
 
     reDrawNode(p, Qt::red);
 
-    if (previouslyUpdatedUser != DisplayUserNullPtr) 
+    if (previouslyUpdatedUser != DisplayUserNullPtr && previouslyUpdatedUser != p) 
     {
       reDrawNode(previouslyUpdatedUser, Qt::darkBlue);
     }
 
     previouslyUpdatedUser = p;
   }
+#ifdef __DEBUG
+  else 
+  {
+    std::cout << "Couldn't find prefix, let's check"<< std::endl;
+    Roster_iterator ii = m_roster.begin();
+    while (ii != m_roster.end())
+    {
+      std::cout <<"Prefix: " << ii.key().toStdString() << std::endl;
+      ++ii;
+    }
+  }
+#endif
 }
 
 void
 DigestTreeScene::clearAll()
 {
   clear();
-  m_graph.clear();
   m_roster.clear();
 }
 
@@ -120,46 +117,33 @@
 DigestTreeScene::plot(QString digest)
 {
   clear();
-  m_graph.clear();
-  int n = m_roster.size();
-  ogdf::node root = m_graph.newNode();
-  int rootIndex = root->index();
-  for (int i = 0; i < n; i++) {
-     ogdf::node leaf = m_graph.newNode();
-     m_graph.newEdge(root, leaf);
-  }
-  ogdf::GraphAttributes GA(m_graph);
 
   int nodeSize = 40;
+
   int siblingDistance = 100, levelDistance = 100;
-  ogdf::TreeLayout layout;
-  layout.siblingDistance(siblingDistance);
-  layout.levelDistance(levelDistance);
-  layout.callSortByPositions(GA, m_graph);
+  std::auto_ptr<TreeLayout> layout(new OneLevelTreeLayout());
+  layout->setSiblingDistance(siblingDistance);
+  layout->setLevelDistance(levelDistance);
 
-  int width = GA.boundingBox().width();
-  int height = GA.boundingBox().height();
-  //setSceneRect(QRect(- (width + nodeSize) / 2, - 50, width + nodeSize, height + nodeSize));
-  GA.setAllWidth(nodeSize);
-  GA.setAllHeight(nodeSize);
+  int n = m_roster.size();
+  std::vector<TreeLayout::Coordinate> childNodesCo(n);
 
-  plotEdge(GA);
-  plotNode(GA, rootIndex, digest);
+  layout->setOneLevelLayout(childNodesCo);
+
+  plotEdge(childNodesCo, nodeSize);
+  plotNode(childNodesCo, digest, nodeSize);
 
   previouslyUpdatedUser = DisplayUserNullPtr;
 
 }
 
 void
-DigestTreeScene::plotEdge(ogdf::GraphAttributes &GA)
+DigestTreeScene::plotEdge(const std::vector<TreeLayout::Coordinate> &childNodesCo, int nodeSize)
 {
-  ogdf::edge e;
-  forall_edges(e, m_graph) {
-    ogdf::node source = e->source();
-    ogdf::node target = e->target();
-    int nodeSize = GA.width(target);
-    int x1 = GA.x(source), y1 = -GA.y(source);
-    int x2 = GA.x(target), y2 = -GA.y(target);
+  int n = childNodesCo.size();
+  for (int i = 0; i < n; i++) {
+    double x1 = 0.0, y1 = 0.0;
+    double x2 = childNodesCo[i].x, y2 = childNodesCo[i].y;
     QPointF src(x1 + nodeSize/2, y1 + nodeSize/2);
     QPointF dest(x2 + nodeSize/2, y2 + nodeSize/2);
     QLineF line(src, dest);
@@ -178,69 +162,68 @@
 }
 
 void
-DigestTreeScene::plotNode(ogdf::GraphAttributes &GA, int rootIndex, QString digest)
+DigestTreeScene::plotNode(const std::vector<TreeLayout::Coordinate> &childNodesCo, QString digest, int nodeSize)
 {
-  ogdf::node n;
   RosterIterator it(m_roster);
-  forall_nodes(n, m_graph) {
-    double x = GA.x(n);
-    double y = -GA.y(n);
-    double w = GA.width(n);
-    double h = GA.height(n);
-    int rim = 3;
-    QRectF boundingRect(x, y, w, h);
-    QRectF innerBoundingRect(x + rim, y + rim, w - rim * 2, h - rim * 2);
+  int n = childNodesCo.size();
+  int rim = 3;
 
-    if (n->index() == rootIndex) 
+  // plot root node
+  QRectF rootBoundingRect(0, 0, nodeSize, nodeSize);
+  QRectF rootInnerBoundingRect(rim, rim, nodeSize - rim * 2, nodeSize - rim * 2);
+  addRect(rootBoundingRect, QPen(Qt::black), QBrush(Qt::darkRed));
+  addRect(rootInnerBoundingRect, QPen(Qt::black), QBrush(Qt::lightGray));
+  QRectF digestRect(- 5.5 * nodeSize , - nodeSize, 12 * nodeSize, 30);
+  addRect(digestRect, QPen(Qt::darkCyan), QBrush(Qt::darkCyan));
+
+  QGraphicsTextItem *digestItem = addText(digest);
+  QRectF digestBoundingRect = digestItem->boundingRect();
+  digestItem->setDefaultTextColor(Qt::black);
+  digestItem->setFont(QFont("Cursive", 12, QFont::Bold));
+  digestItem->setPos(- 4.5 * nodeSize + (12 * nodeSize - digestBoundingRect.width()) / 2, - nodeSize + 5);
+  m_rootDigest = digestItem;
+
+  // plot child nodes
+  for (int i = 0; i < n; i++)
+  {
+    if (it.hasNext()) 
     {
-      addRect(boundingRect, QPen(Qt::black), QBrush(Qt::darkRed));
-      addRect(innerBoundingRect, QPen(Qt::black), QBrush(Qt::lightGray));
-
-      QRectF digestRect(x - w, y - h, 3 * w, 30);
-      addRect(digestRect, QPen(Qt::darkCyan), QBrush(Qt::darkCyan));
-      QGraphicsTextItem *digestItem = addText(digest);
-      QRectF digestBoundingRect = digestItem->boundingRect();
-      digestItem->setDefaultTextColor(Qt::white);
-      digestItem->setFont(QFont("Cursive", 12, QFont::Bold));
-      digestItem->setPos(x - w + (3 * w - digestBoundingRect.width()) / 2, y - h + 5);
-      m_rootDigest = digestItem;
+      it.next();
     }
-    else
+    else 
     {
-      if (it.hasNext()) 
-      {
-        it.next();
-      }
-      else 
-      {
-        abort();
-      }
-      DisplayUserPtr p = it.value();
-      QGraphicsRectItem *rectItem = addRect(boundingRect, QPen(Qt::black), QBrush(Qt::darkBlue));
-      p->setRimRectItem(rectItem);
-
-      QGraphicsRectItem *innerRectItem = addRect(innerBoundingRect, QPen(Qt::black), QBrush(Qt::lightGray));
-      p->setInnerRectItem(innerRectItem);
-
-      std::string s = boost::lexical_cast<std::string>(p->getSeqNo().getSeq());
-      QGraphicsTextItem *seqItem = addText(s.c_str());
-      seqItem->setFont(QFont("Cursive", 12, QFont::Bold));
-      QRectF seqBoundingRect = seqItem->boundingRect(); 
-      seqItem->setPos(x + w / 2 - seqBoundingRect.width() / 2, y + h / 2 - seqBoundingRect.height() / 2);
-      p->setSeqTextItem(seqItem);
-
-      QRectF textRect(x - w / 2, y + h, 2 * w, 30);
-      QGraphicsRectItem *nickRectItem = addRect(textRect, QPen(Qt::darkCyan), QBrush(Qt::darkCyan));
-      p->setNickRectItem(nickRectItem);
-      QGraphicsTextItem *nickItem = addText(p->getNick());
-      QRectF textBoundingRect = nickItem->boundingRect();
-      nickItem->setDefaultTextColor(Qt::white);
-      nickItem->setFont(QFont("Cursive", 12, QFont::Bold));
-      nickItem->setPos(x + w / 2 - textBoundingRect.width() / 2, y + h + 5);
-      p->setNickTextItem(nickItem);
+      abort();
     }
 
+    double x = childNodesCo[i].x;
+    double y = childNodesCo[i].y;
+    QRectF boundingRect(x, y, nodeSize, nodeSize);
+    QRectF innerBoundingRect(x + rim, y + rim, nodeSize - rim * 2, nodeSize - rim * 2);
+    DisplayUserPtr p = it.value();
+    QGraphicsRectItem *rectItem = addRect(boundingRect, QPen(Qt::black), QBrush(Qt::darkBlue));
+    p->setRimRectItem(rectItem);
+
+    QGraphicsRectItem *innerRectItem = addRect(innerBoundingRect, QPen(Qt::black), QBrush(Qt::lightGray));
+    p->setInnerRectItem(innerRectItem);
+
+    std::string s = boost::lexical_cast<std::string>(p->getSeqNo().getSeq());
+    QGraphicsTextItem *seqItem = addText(s.c_str());
+    seqItem->setFont(QFont("Cursive", 12, QFont::Bold));
+    QRectF seqBoundingRect = seqItem->boundingRect(); 
+    seqItem->setPos(x + nodeSize / 2 - seqBoundingRect.width() / 2, y + nodeSize / 2 - seqBoundingRect.height() / 2);
+    p->setSeqTextItem(seqItem);
+
+    QRectF textRect(x - nodeSize / 2, y + nodeSize, 2 * nodeSize, 30);
+    QGraphicsRectItem *nickRectItem = addRect(textRect, QPen(Qt::darkCyan), QBrush(Qt::darkCyan));
+    p->setNickRectItem(nickRectItem);
+    QGraphicsTextItem *nickItem = addText(p->getNick());
+    QRectF textBoundingRect = nickItem->boundingRect();
+    nickItem->setDefaultTextColor(Qt::white);
+    nickItem->setFont(QFont("Cursive", 12, QFont::Bold));
+    nickItem->setPos(x + nodeSize / 2 - textBoundingRect.width() / 2, y + nodeSize + 5);
+    p->setNickTextItem(nickItem);
   }
+
 }
 
 void
diff --git a/demo/digesttreescene.h b/demo/digesttreescene.h
index 91876e6..f041b11 100644
--- a/demo/digesttreescene.h
+++ b/demo/digesttreescene.h
@@ -2,8 +2,6 @@
 #define DIGESTTREESCENE_H
 
 #include <QtGui/QGraphicsScene>
-#include "ogdf/basic/GraphAttributes.h"
-#include "ogdf/basic/Graph.h"
 #include <sync-seq-no.h>
 #include <sync-logic.h>
 #include <ctime>
@@ -11,6 +9,7 @@
 #include <vector>
 #include <tr1/memory>
 #include <QColor>
+#include "treelayout.h"
 
 class QGraphicsTextItem;
 
@@ -34,11 +33,10 @@
   void clearAll();
   void plot(QString digest);
 private:
-  void plotEdge(ogdf::GraphAttributes &GA);
-  void plotNode(ogdf::GraphAttributes &GA, int rootIndex, QString digest);
+  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:
-  ogdf::Graph m_graph;
   Roster m_roster;
   QGraphicsTextItem *m_rootDigest; 
   DisplayUserPtr previouslyUpdatedUser;
diff --git a/demo/sync-demo.pro b/demo/sync-demo.pro
index 96f6c7e..24fcdd1 100644
--- a/demo/sync-demo.pro
+++ b/demo/sync-demo.pro
@@ -1,13 +1,16 @@
 TEMPLATE = app
 TARGET = sync-demo
+DEFINES += __DEBUG
 HEADERS = chatdialog.h \
           digesttreescene.h \
-          settingdialog.h
+          settingdialog.h \
+          treelayout.h
 
 SOURCES = main.cpp \
           chatdialog.cpp \
           digesttreescene.cpp \
-          settingdialog.cpp
+          settingdialog.cpp \
+          treelayout.cpp 
 
 FORMS = chatdialog.ui \
         settingdialog.ui
@@ -15,9 +18,9 @@
 QMAKE_CXXFLAGS *= -g 
 QMAKE_CFLAGS *= -g 
 
-QMAKE_LIBDIR *= /opt/local/lib /usr/local/lib /usr/lib ../../../third_party/OGDF/_release ../build
-INCLUDEPATH *= /opt/local/include /usr/local/include ../../../third_party/OGDF ../include
-LIBS *= -lccn -lssl -lcrypto -lpthread -lOGDF -lprotobuf -lsync
+QMAKE_LIBDIR *= /opt/local/lib /usr/local/lib /usr/lib ../build
+INCLUDEPATH *= /opt/local/include /usr/local/include ../include
+LIBS *= -lccn -lssl -lcrypto -lpthread -lprotobuf -lsync
 CONFIG += console 
 
 PROTOS = chatbuf.proto
diff --git a/demo/treelayout.cpp b/demo/treelayout.cpp
new file mode 100644
index 0000000..0a40484
--- /dev/null
+++ b/demo/treelayout.cpp
@@ -0,0 +1,20 @@
+#include "treelayout.h"
+
+void
+OneLevelTreeLayout::setOneLevelLayout(std::vector<Coordinate> &childNodesCo)
+{
+  if (childNodesCo.empty())
+  {
+    return;
+  }
+  double y = getLevelDistance();
+  double sd = getSiblingDistance();
+  int n = childNodesCo.size();
+  double x = - (n - 1) * sd / 2;
+  for (int i = 0; i < n; i++)
+  {
+    childNodesCo[i].x = x;
+    childNodesCo[i].y = y;
+    x += sd;
+  }
+}
diff --git a/demo/treelayout.h b/demo/treelayout.h
new file mode 100644
index 0000000..498210c
--- /dev/null
+++ b/demo/treelayout.h
@@ -0,0 +1,32 @@
+#ifndef TREELAYOUT_H
+#define TREELAYOUT_H
+#include <vector>
+
+class TreeLayout 
+{
+public:
+  struct Coordinate
+  {
+    double x;
+    double y;
+  };
+  TreeLayout(){}
+  virtual void setOneLevelLayout(std::vector<Coordinate> &childNodesCo){};
+  void setSiblingDistance(int d) {m_siblingDistance = d;}
+  void setLevelDistance(int d) {m_levelDistance = d;}
+  int getSiblingDistance() {return m_siblingDistance;}
+  int getLevelDistance() {return m_levelDistance;}
+  virtual ~TreeLayout(){}
+private:
+  int m_siblingDistance;
+  int m_levelDistance;
+};
+
+class OneLevelTreeLayout: public TreeLayout
+{
+public:
+  OneLevelTreeLayout(){}
+  virtual void setOneLevelLayout(std::vector<Coordinate> &childNodesCo);
+  virtual ~OneLevelTreeLayout(){}
+};
+#endif
diff --git a/include/sync-app-socket.h b/include/sync-app-socket.h
index c190824..cf888d3 100644
--- a/include/sync-app-socket.h
+++ b/include/sync-app-socket.h
@@ -84,12 +84,10 @@
 
   // for sync-demo
   std::string getRootDigest() {return m_syncLogic.getRootDigest();}
-
-
-private:
   uint32_t
   getNextSeq (const std::string &prefix, uint32_t session);
 
+private:
   void 
   passCallback(const std::vector<MissingDataInfo> &v) {m_newDataCallback(v, this);}
 
diff --git a/model/sync-logic.cc b/model/sync-logic.cc
index 31a161b..860f119 100644
--- a/model/sync-logic.cc
+++ b/model/sync-logic.cc
@@ -299,7 +299,15 @@
                 {
                   diffLog->update (info, seq);
                   //m_onUpdate (info->toString (), seq, oldSeq);
-                  MissingDataInfo mdi = {info->toString(), ++oldSeq, seq};
+                  if (!oldSeq.isValid())
+                  {
+                    oldSeq = SeqNo(seq.getSession(), 0);
+                  }
+                  else
+                  {
+                    ++oldSeq;
+                  }
+                  MissingDataInfo mdi = {info->toString(), oldSeq, seq};
                   v.push_back(mdi);
                 }
             }
diff --git a/test/test_app_socket.cc b/test/test_app_socket.cc
index 5e7ddc2..df3a3a8 100644
--- a/test/test_app_socket.cc
+++ b/test/test_app_socket.cc
@@ -85,6 +85,7 @@
 
     std::cout << "In fetchNumbers. size of v is:  " << n << std::endl;
     for (int i = 0; i < n; i++) {
+      std::cout << "In fetchNumbers. v[i].low is (" <<v[i].low.getSession() <<", " << v[i].low.getSeq() << ") v[i].high is ("<<v[i].high.getSession() <<", " <<v[i].high.getSeq()<<")" << std::endl;
       for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
         PRINT
         socket->fetchRaw(v[i].prefix, s, bind(&TestSocketApp::setNum, this, _1, _2, _3));