enable summon reaper
diff --git a/chatdialog.cpp b/chatdialog.cpp
index 464ac91..79ac9d0 100644
--- a/chatdialog.cpp
+++ b/chatdialog.cpp
@@ -55,6 +55,7 @@
   connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
   connect(setButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
   connect(treeButton, SIGNAL(pressed()), this, SLOT(treeButtonPressed()));
+  connect(reapButton, SIGNAL(pressed()), this, SLOT(summonReaper()));
   connect(refreshButton, SIGNAL(pressed()), this, SLOT(updateLocalPrefix()));
   connect(this, SIGNAL(dataReceived(QString, const char *, size_t, bool, bool)), this, SLOT(processData(QString, const char *, size_t, bool, bool)));
   connect(this, SIGNAL(treeUpdated(const std::vector<Sync::MissingDataInfo>)), this, SLOT(processTreeUpdate(const std::vector<Sync::MissingDataInfo>)));
@@ -138,6 +139,60 @@
 }
 
 void
+ChatDialog::summonReaper()
+{
+  Sync::SyncLogic &logic = m_sock->getLogic ();
+  std::map<std::string, bool> branches = logic.getBranchPrefixes();
+  QMap<QString, DisplayUserPtr> roster = m_scene->getRosterFull();
+
+  m_zombieList.clear(); 
+
+  QMapIterator<QString, DisplayUserPtr> it(roster);
+  std::map<std::string, bool>::iterator mapIt;
+  while(it.hasNext())
+  {
+    it.next();
+    DisplayUserPtr p = it.value();
+    if (p != DisplayUserNullPtr)
+    {
+      mapIt = branches.find(p->getPrefix().toStdString());
+      if (mapIt != branches.end())
+      {
+        mapIt->second = true;
+      }
+    }
+  }
+
+  for (mapIt = branches.begin(); mapIt != branches.end(); ++mapIt)
+  {
+    // this is zombie. all active users should have been marked true
+    if (! mapIt->second)
+    {
+      m_zombieList.append(mapIt->first.c_str());
+    }
+  }
+
+  m_zombieIndex = 0;
+
+  // start reaping
+  reap();
+}
+
+void
+ChatDialog::reap()
+{
+  if (m_zombieIndex < m_zombieList.size())
+  {
+    std::string prefix = m_zombieList.at(m_zombieIndex).toStdString();
+    m_sock->remove(prefix);
+    std::cout << "Reaped: prefix = " << prefix << std::endl;
+    m_zombieIndex++;
+    // reap again in 10 seconds
+    QTimer::singleShot(10000, this, SLOT(reap()));
+  }
+}
+
+void
 ChatDialog::updateRosterList(QStringList staleUserList)
 {
   boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
diff --git a/chatdialog.h b/chatdialog.h
index 8ad91e3..97e5d6f 100644
--- a/chatdialog.h
+++ b/chatdialog.h
@@ -79,6 +79,8 @@
   void updateRosterList(QStringList);
   void enableTreeDisplay();
   void updateLocalPrefix();
+  void reap();
+  void summonReaper();
 
   // icon related
   void iconActivated(QSystemTrayIcon::ActivationReason reason);
@@ -106,6 +108,9 @@
   QQueue<SyncDemo::ChatMessage> m_history;
   bool m_historyInitialized;
   bool m_joined;
+
+  QList<QString> m_zombieList;
+  int m_zombieIndex;
   
   // icon related
   QAction *minimizeAction;
diff --git a/chatdialog.ui b/chatdialog.ui
index 31bcbbf..dcee37e 100644
--- a/chatdialog.ui
+++ b/chatdialog.ui
@@ -116,6 +116,22 @@
                 </property>
                 </widget>
               </item>
+              <item>
+                <widget class="QPushButton" name="reapButton">
+                <property name="focusPolicy">
+                  <enum>Qt::NoFocus</enum>
+                </property>
+                <property name="text">
+                  <string>Summon Reaper!</string> 
+                </property>
+                <property name="minimumWidth">
+                  <number>150</number>
+                </property>
+                <property name="maximumWidth">
+                  <number>150</number>
+                </property>
+                </widget>
+              </item>
             </layout>
           </item>
         </layout>
diff --git a/digesttreescene.cpp b/digesttreescene.cpp
index b876a17..2265fd0 100644
--- a/digesttreescene.cpp
+++ b/digesttreescene.cpp
@@ -8,7 +8,7 @@
 
 static const double Pi = 3.14159265358979323846264338327950288419717;
 
-DigestTreeScene::DisplayUserPtr DigestTreeScene::DisplayUserNullPtr;
+//DisplayUserPtr DisplayUserNullPtr;
 
 DigestTreeScene::DigestTreeScene(QWidget *parent)
   : QGraphicsScene(parent)
@@ -152,9 +152,6 @@
   // do some cleaning, get rid of stale member info
   Roster_iterator it = m_roster.begin();
   QStringList staleUserList;
-#ifdef __DEBUG
-  std::cout << "------------------------------------------------------" << std::endl;
-#endif
   while (it != m_roster.end())
   {
     DisplayUserPtr p = it.value();
@@ -173,10 +170,6 @@
       }
       else
       {
-#ifdef __DEBUG
-        std::cout << "having user: " << p->getNick().toStdString() << std::endl;
-        std::cout << "prefix: " << p->getPrefix().toStdString() << std::endl;
-#endif
         if (!m_currentPrefix.startsWith("/private/local") && p->getPrefix().startsWith("/private/local"))
         {
 #ifdef __DEBUG
@@ -194,9 +187,6 @@
     {
       it = m_roster.erase(it);
     }
-#ifdef __DEBUG
-  std::cout << "------------------------------------------------------" << std::endl;
-#endif
   }
 
   // for simpicity here, whenever we replot, we also redo the roster list
diff --git a/digesttreescene.h b/digesttreescene.h
index 9d9dee4..a2cc69a 100644
--- a/digesttreescene.h
+++ b/digesttreescene.h
@@ -17,16 +17,16 @@
 
 class User;
 class DisplayUser;
+typedef std::tr1::shared_ptr<DisplayUser> DisplayUserPtr;
+static DisplayUserPtr DisplayUserNullPtr;
 
 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;
-static DisplayUserPtr DisplayUserNullPtr;
 
 public:
   DigestTreeScene(QWidget *parent = 0);
@@ -37,6 +37,7 @@
   void plot(QString digest);
   QStringList getRosterList();
   void setCurrentPrefix(QString prefix) {m_currentPrefix = prefix;}
+  QMap<QString, DisplayUserPtr> getRosterFull() { return m_roster;}
 
 signals:
   void replot();