fixing segfaults on part if the part results in an empty category (BR #232)
[quassel.git] / src / client / treemodel.cpp
index 4fd2687..4933f0d 100644 (file)
 #include <QDebug>
 #include <QCoreApplication>
 
+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
  *****************************************/
@@ -57,13 +66,13 @@ 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();
@@ -84,6 +93,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 +103,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.
@@ -116,14 +145,16 @@ bool AbstractTreeItem::reParent(AbstractTreeItem *newParent) {
   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;
 }