plotting
diff --git a/chatdialog.cpp b/chatdialog.cpp
index 34f5682..b7edf20 100644
--- a/chatdialog.cpp
+++ b/chatdialog.cpp
@@ -17,7 +17,7 @@
   DigestTreeScene *scene = new DigestTreeScene();
 
   treeViewer->setScene(scene);
-  scene->plot();
+  //scene->plot();
 
   connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
   connect(setButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
@@ -53,8 +53,8 @@
 
 void
 ChatDialog::formChatMessage(const QString &text, SyncDemo::ChatMessage &msg) {
-  msg.set_from(m_nick.toStdString());
-  msg.set_to(m_chatroom.toStdString());
+  msg.set_from(m_user.getNick().toStdString());
+  msg.set_to(m_user.getChatroom().toStdString());
   msg.set_data(text.toStdString());
   time_t seconds = time(NULL);
   msg.set_timestamp(seconds);
@@ -64,29 +64,34 @@
 ChatDialog::readSettings()
 {
   QSettings s(ORGANIZATION, APPLICATION);
-  m_nick = s.value("nick", "").toString();
-  m_chatroom = s.value("chatroom", "").toString();
-  m_prefix = s.value("prefix", "").toString();
-  if (m_nick == "" || m_chatroom == "" || m_prefix == "") {
+  QString nick = s.value("nick", "").toString();
+  QString chatroom = s.value("chatroom", "").toString();
+  QString prefix = s.value("prefix", "").toString();
+  if (nick == "" || chatroom == "" || prefix == "") {
     QTimer::singleShot(500, this, SLOT(buttonPressed()));
   }
+  else {
+    m_user.setNick(nick);
+    m_user.setChatroom(chatroom);
+    m_user.setPrefix(prefix);
+  }
 }
 
 void 
 ChatDialog::writeSettings()
 {
   QSettings s(ORGANIZATION, APPLICATION);
-  s.setValue("nick", m_nick);
-  s.setValue("chatroom", m_chatroom);
-  s.setValue("prefix", m_prefix);
+  s.setValue("nick", m_user.getNick());
+  s.setValue("chatroom", m_user.getChatroom());
+  s.setValue("prefix", m_user.getPrefix());
 }
 
 void
 ChatDialog::updateLabels()
 {
-  QString settingDisp = QString("<User: %1>, <Chatroom: %2>").arg(m_nick).arg(m_chatroom);
+  QString settingDisp = QString("<User: %1>, <Chatroom: %2>").arg(m_user.getNick()).arg(m_user.getChatroom());
   infoLabel->setText(settingDisp);
-  QString prefixDisp = QString("<Prefix: %1>").arg(m_prefix);
+  QString prefixDisp = QString("<Prefix: %1>").arg(m_user.getPrefix());
   prefixLabel->setText(prefixDisp);
 }
 
@@ -111,7 +116,7 @@
 void
 ChatDialog::buttonPressed()
 {
-  SettingDialog dialog(this, m_nick, m_chatroom, m_prefix);
+  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();
 }
@@ -120,17 +125,17 @@
 ChatDialog::settingUpdated(QString nick, QString chatroom, QString prefix)
 {
   bool needWrite = false;
-  if (!nick.isEmpty() && nick != m_nick) {
-    m_nick = nick;
+  if (!nick.isEmpty() && nick != m_user.getNick()) {
+    m_user.setNick(nick);
     needWrite = true;
   }
-  if (!prefix.isEmpty() && prefix != m_prefix) {
-    m_prefix = prefix;
+  if (!prefix.isEmpty() && prefix != m_user.getPrefix()) {
+    m_user.setPrefix(prefix);
     needWrite = true;
     // TODO: set the previous prefix as left?
   }
-  if (!chatroom.isEmpty() && chatroom != m_chatroom) {
-    m_chatroom = chatroom;
+  if (!chatroom.isEmpty() && chatroom != m_user.getChatroom()) {
+    m_user.setChatroom(chatroom);
     needWrite = true;
     // TODO: perhaps need to do a lot. e.g. use a new SyncAppSokcet
   }
diff --git a/chatdialog.h b/chatdialog.h
index 337f20f..3ae668b 100644
--- a/chatdialog.h
+++ b/chatdialog.h
@@ -33,9 +33,7 @@
   void settingUpdated(QString, QString, QString);
 
 private:
-  QString m_nick;
-  QString m_chatroom;
-  QString m_prefix;
+  User m_user; 
   Sync::SyncAppSocket *m_sock;
 };
 #endif
diff --git a/digesttreescene.cpp b/digesttreescene.cpp
index 483f1f6..2d2f631 100644
--- a/digesttreescene.cpp
+++ b/digesttreescene.cpp
@@ -6,6 +6,7 @@
 #include <vector>
 #include <iostream>
 #include <assert.h>
+#include <boost/lexical_cast.hpp>
 
 static const double Pi = 3.14159265358979323846264338327950288419717;
 
@@ -15,86 +16,176 @@
 }
 
 void
-DigestTreeScene::plot() {
+DigestTreeScene::processUpdate(std::vector<Sync::MissingDataInfo> &v, QString digest)
+{
+  int n = v.size();
+  bool rePlot = false; 
+  for (int i = 0; i < n; i++) 
+  {
+    Roster_iterator it = m_roster.find(v[i].prefix.c_str());
+    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);
+    }
+  }
+
+  if (rePlot) 
+  {
+    plot(digest);
+  }
+  else 
+  {
+    for (int i = 0; i < n; i++) 
+    {
+      Roster_iterator it = m_roster.find(v[i].prefix.c_str());
+      if (it != m_roster.end()) {
+        DisplayUserPtr p = it.value();
+        QGraphicsTextItem *item = p->getSeqTextItem();
+        std::string s = boost::lexical_cast<std::string>(p->getSeqNo().getSeq());
+        item->setPlainText(s.c_str());
+      }
+    }
+    m_rootDigest->setPlainText(digest);
+  }
+}
+
+void
+DigestTreeScene::msgReceived(QString prefix, QString nick)
+{
+  Roster_iterator it = m_roster.find(prefix);
+  if (it != m_roster.end()) 
+  {
+    DisplayUserPtr p = it.value();
+    if (nick != p->getNick()) {
+      p->setNick(nick);
+      QGraphicsTextItem *nickItem = p->getNickTextItem();
+      nickItem->setPlainText(p->getNick());
+    }
+    QGraphicsRectItem *rimItem = p->getRimRectItem();
+    rimItem->setBrush(QBrush(Qt::red));
+  }
+}
+
+void
+DigestTreeScene::plot(QString digest)
+{
   clear();
   m_graph.clear();
-  std::vector<ogdf::node> v(5);
-  for (int i = 0; i < 5; i++)
-    v[i] = m_graph.newNode();
-
-  m_graph.newEdge(v[0], v[1]);
-  m_graph.newEdge(v[0], v[2]);
-  m_graph.newEdge(v[0], v[3]);
-  m_graph.newEdge(v[0], v[4]);
-
+  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);
-  GA.initAttributes(ogdf::GraphAttributes::nodeLabel);
-  int nodeWidth = 30, nodeHeight = 30, siblingDistance = 60;
+
+  int nodeSize = 50;
+  int siblingDistance = 100, levelDistance = 100;
   ogdf::TreeLayout layout;
   layout.siblingDistance(siblingDistance);
-  layout.rootSelection(ogdf::TreeLayout::rootIsSource);
-  //layout.call(GA);
+  layout.levelDistance(levelDistance);
   layout.callSortByPositions(GA, m_graph);
 
   int width = GA.boundingBox().width();
-  std::cout << "GA width " << width << std::endl;
   int height = GA.boundingBox().height();
-  std::cout << "GA height " << height << std::endl;
-  setSceneRect(QRect(0, 0, width + nodeWidth, height + nodeHeight));
-  GA.setAllWidth(nodeWidth);
-  GA.setAllHeight(nodeHeight);
+  setSceneRect(QRect(- (width + nodeSize) / 2, - 40, width + nodeSize, height + nodeSize));
+  GA.setAllWidth(nodeSize);
+  GA.setAllHeight(nodeSize);
 
+  plotEdge(GA);
+  plotNode(GA, rootIndex, digest);
+
+}
+
+void
+DigestTreeScene::plotEdge(ogdf::GraphAttributes &GA)
+{
   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);
-  //  QPainterPath p;
-    QPointF src(x1 + nodeWidth/2, y1 + nodeHeight/2);
-    QPointF dest(x2 + nodeWidth/2, y2 + nodeHeight/2);
+    QPointF src(x1 + nodeSize/2, y1 + nodeSize/2);
+    QPointF dest(x2 + nodeSize/2, y2 + nodeSize/2);
     QLineF line(src, dest);
-    //p.moveTo(x1 + nodeWidth/2, y1 + nodeHeight/2);
-    //p.lineTo(x2 + nodeWidth/2, y2 + nodeHeight/2);
-    //addPath(p, QPen(Qt::black), QBrush(Qt::black));
-    addLine(line, QPen(Qt::black));
-    
     double angle = ::acos(line.dx() / line.length());
 
     double arrowSize = 10;
-
-   QPointF sourceArrowP0 = src + QPointF(nodeWidth/2 * line.dx() / line.length(),  nodeHeight/2 * line.dy() / line.length());
-   //QPointF sourceArrowP0 = src + QPointF(cos(angle) * nodeHeight/2, sin(angle) * nodeHeight/2);
-
-   std::cout << "src " << src.x() << ", " << src.y() << std::endl;
-   std::cout << "dest " << dest.x() << ", " << dest.y() << std::endl;
-   std::cout << "line dx " << line.dx() << ", dy " << line.dy() << ", lenght << " << line.length() << std::endl;
-   std::cout << "sap " << sourceArrowP0.x() << ", " << sourceArrowP0.y() << std::endl;
-
-   QPointF sourceArrowP1 = sourceArrowP0 + QPointF(cos(angle + Pi / 3 - Pi/2) * arrowSize,
+    QPointF sourceArrowP0 = src + QPointF((nodeSize/2 + 10) * line.dx() / line.length(),  (nodeSize/2 +10) * line.dy() / line.length());
+    QPointF sourceArrowP1 = sourceArrowP0 + QPointF(cos(angle + Pi / 3 - Pi/2) * arrowSize,
                                                     sin(angle + Pi / 3 - Pi/2) * arrowSize);
-      QPointF sourceArrowP2 = sourceArrowP0 + QPointF(cos(angle + Pi - Pi / 3 - Pi/2) * arrowSize,
+    QPointF sourceArrowP2 = sourceArrowP0 + QPointF(cos(angle + Pi - Pi / 3 - Pi/2) * arrowSize,
                                                          sin(angle + Pi - Pi / 3 - Pi/2) * arrowSize);
-    QLineF line1(sourceArrowP1, sourceArrowP2);
-    addLine(line1, QPen(Qt::black));
-     
-     addPolygon(QPolygonF() << sourceArrowP0<< sourceArrowP1 << sourceArrowP2, QPen(Qt::black), QBrush(Qt::black));
-  }
 
+    addLine(QLineF(sourceArrowP0, dest), QPen(Qt::black));
+    addPolygon(QPolygonF() << sourceArrowP0<< sourceArrowP1 << sourceArrowP2, QPen(Qt::black), QBrush(Qt::black));
+  }
+}
+
+void
+DigestTreeScene::plotNode(ogdf::GraphAttributes &GA, int rootIndex, QString digest)
+{
   ogdf::node n;
-  int i = 0;
-  std::string s[5] = {"A", "B", "C", "D", "E"};
+  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);
-    addEllipse(boundingRect, QPen(Qt::black), QBrush(Qt::green));
-    QGraphicsTextItem *text = addText(s[i].c_str());
-    text->setPos(x + 5, y + 5);
-    i++; 
+    QRectF innerBoundingRect(x + rim, y + rim, w - rim * 2, h - rim * 2);
+    addRect(innerBoundingRect, QPen(Qt::black), QBrush(Qt::lightGray));
+
+    if (n->index() == rootIndex) 
+    {
+      addRect(boundingRect, QPen(Qt::black), QBrush(Qt::darkRed));
+
+      QRectF digestRect(x - w / 2, y - h - 5, 2 * 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 / 2 - digestBoundingRect.width() / 2, y - h - 15);
+      m_rootDigest = digestItem;
+    }
+    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);
+
+      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 + 10, 2 * w, 30);
+      addRect(textRect, QPen(Qt::darkCyan), QBrush(Qt::darkCyan));
+      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 + 15);
+      p->setNickTextItem(nickItem);
+    }
   }
 }
 
diff --git a/digesttreescene.h b/digesttreescene.h
index 1915c2f..5c8af9d 100644
--- a/digesttreescene.h
+++ b/digesttreescene.h
@@ -4,15 +4,79 @@
 #include <QtGui/QGraphicsScene>
 #include "ogdf/basic/GraphAttributes.h"
 #include "ogdf/basic/Graph.h"
+#include <sync-seq-no.h>
+#include <sync-logic.h>
+#include <ctime>
+#include <QMap>
+#include <vector>
+#include <tr1/memory>
+
+class QGraphicsTextItem;
+
+class User;
+class DisplayUser;
 
 class DigestTreeScene : public QGraphicsScene
 {
   Q_OBJECT
 
+typedef std::tr1::shared_ptr<DisplayUser> DisplayUserPtr;
+typedef QMap<QString, DisplayUserPtr> Roster;
+typedef QMap<QString, DisplayUserPtr>::iterator Roster_iterator;
+typedef QMapIterator<QString, DisplayUserPtr> RosterIterator;
+
 public:
   DigestTreeScene(QWidget *parent = 0);
-  void plot();
+  void processUpdate(std::vector<Sync::MissingDataInfo> &v, QString digest);
+  void msgReceived(QString prefix, QString nick);
+  void plot(QString digest);
+  void plotEdge(ogdf::GraphAttributes &GA);
+  void plotNode(ogdf::GraphAttributes &GA, int rootIndex, QString digest);
 private:
   ogdf::Graph m_graph;
+  Roster m_roster;
+  QGraphicsTextItem *m_rootDigest; 
+
 };
+
+class User 
+{
+public:
+  User():m_received(time(NULL)) {}
+  User(QString n, QString p, QString c): m_nick(n), m_prefix(p), m_chatroom(c), m_received(time(NULL)) {}
+  void setNick(QString nick) {m_nick = nick;}
+  void setPrefix(QString prefix) {m_prefix = prefix;}
+  void setChatroom(QString chatroom) {m_chatroom = chatroom;}
+  void setSeq(Sync::SeqNo seq) {m_seq = seq;}
+  void setReceived() {m_received = time(NULL);}
+  QString getNick() { return m_nick;}
+  QString getPrefix() { return m_prefix;}
+  QString getChatroom() { return m_chatroom;}
+  Sync::SeqNo getSeqNo() { return m_seq;}
+  time_t getReceived() { return m_received;}
+private:
+  QString m_nick;
+  QString m_prefix;
+  QString m_chatroom;
+  Sync::SeqNo m_seq;
+  time_t m_received;
+};
+
+class DisplayUser : public User 
+{
+public:
+  DisplayUser():m_seqTextItem(NULL), m_nickTextItem(NULL), m_rimRectItem(NULL) {}
+  DisplayUser(QString n, QString p , QString c): User(n, p, c), m_seqTextItem(NULL), m_nickTextItem(NULL), m_rimRectItem(NULL) {}
+  QGraphicsTextItem *getSeqTextItem() {return m_seqTextItem;}
+  QGraphicsTextItem *getNickTextItem() {return m_nickTextItem;}
+  QGraphicsRectItem *getRimRectItem() {return m_rimRectItem;}
+  void setSeqTextItem(QGraphicsTextItem *item) { m_seqTextItem = item;}
+  void setNickTextItem(QGraphicsTextItem *item) { m_nickTextItem = item;}
+  void setRimRectItem(QGraphicsRectItem *item) {m_rimRectItem = item;}
+private:
+  QGraphicsTextItem *m_seqTextItem;
+  QGraphicsTextItem *m_nickTextItem;
+  QGraphicsRectItem *m_rimRectItem;
+};
+
 #endif