+#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
+ *****************************************/
+AbstractTreeItem::AbstractTreeItem(AbstractTreeItem *parent)
+ : QObject(parent),
+ _flags(Qt::ItemIsSelectable | Qt::ItemIsEnabled),
+ _treeItemFlags(0)
+{
+}
+
+
+bool AbstractTreeItem::newChild(AbstractTreeItem *item)
+{
+ int newRow = childCount();
+ emit beginAppendChilds(newRow, newRow);
+ _childItems.append(item);
+ emit endAppendChilds();
+ return true;
+}
+
+
+bool AbstractTreeItem::newChilds(const QList<AbstractTreeItem *> &items)
+{
+ if (items.isEmpty())
+ return false;
+
+ int nextRow = childCount();
+ int lastRow = nextRow + items.count() - 1;
+
+ emit beginAppendChilds(nextRow, lastRow);
+ _childItems << items;
+ emit endAppendChilds();
+
+ return true;
+}
+
+
+bool AbstractTreeItem::removeChild(int row)
+{
+ if (row < 0 || childCount() <= row)
+ return false;
+
+ child(row)->removeAllChilds();
+ emit beginRemoveChilds(row, row);
+ AbstractTreeItem *treeitem = _childItems.takeAt(row);
+ delete treeitem;
+ emit endRemoveChilds();
+
+ checkForDeletion();
+
+ return true;
+}
+
+
+void AbstractTreeItem::removeAllChilds()
+{
+ const int numChilds = childCount();
+
+ if (numChilds == 0)
+ return;
+
+ AbstractTreeItem *child;
+
+ QList<AbstractTreeItem *>::iterator childIter;
+
+ 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++;
+ }
+
+ emit beginRemoveChilds(0, numChilds - 1);
+ childIter = _childItems.begin();
+ while (childIter != _childItems.end()) {
+ child = *childIter;
+ childIter = _childItems.erase(childIter);
+ 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;
+
+ // since we are called asynchronously we have to recheck if the item in question still has no childs
+ if (removeEvent->child()->childCount())
+ 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.
+ if (childCount() != 0) {
+ qDebug() << "AbstractTreeItem::reParent(): cannot reparent" << this << "with children.";
+ return false;
+ }
+
+ int oldRow = row();
+ if (oldRow == -1)
+ return false;
+
+ emit parent()->beginRemoveChilds(oldRow, oldRow);
+ parent()->_childItems.removeAt(oldRow);
+ emit parent()->endRemoveChilds();
+
+ 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;
+}
+
+
+AbstractTreeItem *AbstractTreeItem::child(int row) const
+{
+ if (childCount() <= row)
+ return 0;
+ else
+ return _childItems[row];
+}
+
+
+int AbstractTreeItem::childCount(int column) const
+{
+ if (column > 0)
+ return 0;
+ else
+ return _childItems.count();
+}
+
+
+int AbstractTreeItem::row() const
+{
+ if (!parent()) {
+ 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();
+ return row_;
+}
+
+
+void AbstractTreeItem::dumpChildList()
+{
+ qDebug() << "==== Childlist for Item:" << this << "====";
+ if (childCount() > 0) {
+ AbstractTreeItem *child;
+ QList<AbstractTreeItem *>::const_iterator childIter = _childItems.constBegin();
+ while (childIter != _childItems.constEnd()) {
+ child = *childIter;
+ qDebug() << "Row:" << child->row() << child << child->data(0, Qt::DisplayRole);
+ childIter++;
+ }
+ }
+ qDebug() << "==== End Of Childlist ====";
+}
+
+