fixing crash on disconnect
[quassel.git] / src / client / treemodel.cpp
index 4fd2687..64cc26f 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2005-08 by the Quassel Project                          *
+ *   Copyright (C) 2005-09 by the Quassel Project                          *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  ***************************************************************************/
 
 #include "treemodel.h"
-#include "global.h"
 
-#include <QDebug>
 #include <QCoreApplication>
+#include <QDebug>
+
+#include "quassel.h"
+
+class RemoveChildLaterEvent : public QEvent {
+public:
+  RemoveChildLaterEvent(AbstractTreeItem *child) : QEvent(QEvent::User), _child(child) {};
+  inline AbstractTreeItem *child() { return _child; }
+private:
+  AbstractTreeItem *_child;
+};
+
 
 /*****************************************
  *  Abstract Items of a TreeModel
@@ -45,7 +55,7 @@ bool AbstractTreeItem::newChild(AbstractTreeItem *item) {
 bool AbstractTreeItem::newChilds(const QList<AbstractTreeItem *> &items) {
   if(items.isEmpty())
     return false;
-  
+
   int nextRow = childCount();
   int lastRow = nextRow + items.count() - 1;
 
@@ -57,26 +67,26 @@ bool AbstractTreeItem::newChilds(const QList<AbstractTreeItem *> &items) {
 }
 
 bool AbstractTreeItem::removeChild(int row) {
-  if(childCount() <= row)
+  if(row < 0 || childCount() <= row)
     return false;
 
   child(row)->removeAllChilds();
   emit beginRemoveChilds(row, row);
   AbstractTreeItem *treeitem = _childItems.takeAt(row);
-  treeitem->deleteLater();
+  delete treeitem;
   emit endRemoveChilds();
 
   checkForDeletion();
-  
+
   return true;
 }
 
 void AbstractTreeItem::removeAllChilds() {
   const int numChilds = childCount();
-  
+
   if(numChilds == 0)
     return;
-  
+
   AbstractTreeItem *child;
 
   QList<AbstractTreeItem *>::iterator childIter;
@@ -84,6 +94,7 @@ void AbstractTreeItem::removeAllChilds() {
   childIter = _childItems.begin();
   while(childIter != _childItems.end()) {
     child = *childIter;
+    child->setTreeItemFlags(0); // disable self deletion, as this would only fuck up consitency and the child gets deleted anyways
     child->removeAllChilds();
     childIter++;
   }
@@ -93,13 +104,32 @@ void AbstractTreeItem::removeAllChilds() {
   while(childIter != _childItems.end()) {
     child = *childIter;
     childIter = _childItems.erase(childIter);
-    child->deleteLater();
+    delete child;
   }
   emit endRemoveChilds();
 
   checkForDeletion();
 }
 
+void AbstractTreeItem::removeChildLater(AbstractTreeItem *child) {
+  Q_ASSERT(child);
+  QCoreApplication::postEvent(this, new RemoveChildLaterEvent(child));
+}
+
+void AbstractTreeItem::customEvent(QEvent *event) {
+  if(event->type() != QEvent::User)
+    return;
+
+  event->accept();
+
+  RemoveChildLaterEvent *removeEvent = static_cast<RemoveChildLaterEvent *>(event);
+  int childRow = _childItems.indexOf(removeEvent->child());
+  if(childRow == -1)
+    return;
+
+  removeChild(childRow);
+}
+
 bool AbstractTreeItem::reParent(AbstractTreeItem *newParent) {
   // currently we support only re parenting if the child that's about to be
   // adopted does not have any children itself.
@@ -111,19 +141,21 @@ bool AbstractTreeItem::reParent(AbstractTreeItem *newParent) {
   int oldRow = row();
   if(oldRow == -1)
     return false;
-  
+
   emit parent()->beginRemoveChilds(oldRow, oldRow);
   parent()->_childItems.removeAt(oldRow);
   emit parent()->endRemoveChilds();
 
-  parent()->checkForDeletion();
-
+  AbstractTreeItem *oldParent = parent();
   setParent(newParent);
 
   bool success = newParent->newChild(this);
   if(!success)
     qWarning() << "AbstractTreeItem::reParent(): failed to attach to new parent after removing from old parent! this:" << this << "new parent:" << newParent;
 
+  if(oldParent)
+    oldParent->checkForDeletion();
+
   return success;
 }
 
@@ -146,7 +178,7 @@ int AbstractTreeItem::row() const {
     qWarning() << "AbstractTreeItem::row():" << this << "has no parent AbstractTreeItem as it's parent! parent is" << QObject::parent();
     return -1;
   }
-  
+
   int row_ = parent()->_childItems.indexOf(const_cast<AbstractTreeItem *>(this));
   if(row_ == -1)
     qWarning() << "AbstractTreeItem::row():" << this << "is not in the child list of" << QObject::parent();
@@ -164,7 +196,7 @@ void AbstractTreeItem::dumpChildList() {
       childIter++;
     }
   }
-  qDebug() << "==== End Of Childlist ====";  
+  qDebug() << "==== End Of Childlist ====";
 }
 
 /*****************************************
@@ -221,7 +253,7 @@ PropertyMapItem::PropertyMapItem(AbstractTreeItem *parent)
 
 PropertyMapItem::~PropertyMapItem() {
 }
-  
+
 QVariant PropertyMapItem::data(int column, int role) const {
   if(column >= columnCount())
     return QVariant();
@@ -235,7 +267,7 @@ QVariant PropertyMapItem::data(int column, int role) const {
   default:
     return QVariant();
   }
-  
+
 }
 
 bool PropertyMapItem::setData(int column, const QVariant &value, int role) {
@@ -249,7 +281,7 @@ bool PropertyMapItem::setData(int column, const QVariant &value, int role) {
 int PropertyMapItem::columnCount() const {
   return _propertyOrder.count();
 }
-  
+
 void PropertyMapItem::appendProperty(const QString &property) {
   _propertyOrder << property;
 }
@@ -267,7 +299,7 @@ TreeModel::TreeModel(const QList<QVariant> &data, QObject *parent)
   rootItem = new SimpleTreeItem(data, 0);
   connectItem(rootItem);
 
-  if(Global::parser.isSet("debugmodel")) {
+  if(Quassel::isOptionSet("debugmodel")) {
     connect(this, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
            this, SLOT(debug_rowsAboutToBeInserted(const QModelIndex &, int, int)));
     connect(this, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
@@ -288,14 +320,14 @@ TreeModel::~TreeModel() {
 QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const {
   if(!hasIndex(row, column, parent))
     return QModelIndex();
-  
+
   AbstractTreeItem *parentItem;
-  
+
   if(!parent.isValid())
     parentItem = rootItem;
   else
     parentItem = static_cast<AbstractTreeItem *>(parent.internalPointer());
-  
+
   AbstractTreeItem *childItem = parentItem->child(row);
 
   if(childItem)
@@ -309,7 +341,7 @@ QModelIndex TreeModel::indexByItem(AbstractTreeItem *item) const {
     qWarning() << "TreeModel::indexByItem(AbstractTreeItem *item) received NULL-Pointer";
     return QModelIndex();
   }
-  
+
   if(item == rootItem)
     return QModelIndex();
   else
@@ -321,14 +353,14 @@ QModelIndex TreeModel::parent(const QModelIndex &index) const {
     qWarning() << "TreeModel::parent(): has been asked for the rootItems Parent!";
     return QModelIndex();
   }
-  
+
   AbstractTreeItem *childItem = static_cast<AbstractTreeItem *>(index.internalPointer());
   AbstractTreeItem *parentItem = childItem->parent();
 
   Q_ASSERT(parentItem);
   if(parentItem == rootItem)
     return QModelIndex();
-  
+
   return createIndex(parentItem->row(), 0, parentItem);
 }
 
@@ -411,12 +443,12 @@ void TreeModel::itemDataChanged(int column) {
 void TreeModel::connectItem(AbstractTreeItem *item) {
   connect(item, SIGNAL(dataChanged(int)),
          this, SLOT(itemDataChanged(int)));
-  
+
   connect(item, SIGNAL(beginAppendChilds(int, int)),
          this, SLOT(beginAppendChilds(int, int)));
   connect(item, SIGNAL(endAppendChilds()),
          this, SLOT(endAppendChilds()));
-  
+
   connect(item, SIGNAL(beginRemoveChilds(int, int)),
          this, SLOT(beginRemoveChilds(int, int)));
   connect(item, SIGNAL(endRemoveChilds()),
@@ -432,7 +464,7 @@ void TreeModel::beginAppendChilds(int firstRow, int lastRow) {
 
   QModelIndex parent = indexByItem(parentItem);
   Q_ASSERT(!_aboutToRemoveOrInsert);
-  
+
   _aboutToRemoveOrInsert = true;
   _childStatus = ChildStatus(parent, rowCount(parent), firstRow, lastRow);
   beginInsertRows(parent, firstRow, lastRow);
@@ -467,7 +499,7 @@ void TreeModel::beginRemoveChilds(int firstRow, int lastRow) {
   for(int i = firstRow; i <= lastRow; i++) {
     disconnect(parentItem->child(i), 0, this, 0);
   }
-  
+
   // consitency checks
   QModelIndex parent = indexByItem(parentItem);
   Q_ASSERT(firstRow <= lastRow);