Refactoring the Tree- and Networkmodel (internal stuff only).
authorMarcus Eggenberger <egs@quassel-irc.org>
Sun, 27 Jul 2008 11:48:14 +0000 (13:48 +0200)
committerMarcus Eggenberger <egs@quassel-irc.org>
Sun, 27 Jul 2008 11:48:14 +0000 (13:48 +0200)
 - the all purpose virtual quint AbstractTreeItem::id() const is gone.
 - exists*Item is no renamed to find*Item to fit the Qt naming scheme of findChild()

src/client/networkmodel.cpp
src/client/networkmodel.h
src/client/treemodel.cpp
src/client/treemodel.h

index 1a36ac0..270fbec 100644 (file)
@@ -55,8 +55,22 @@ QVariant NetworkItem::data(int column, int role) const {
   }
 }
 
+BufferItem *NetworkItem::findBufferItem(BufferId bufferId) {
+  BufferItem *bufferItem = 0;
+  
+  for(int i = 0; i < childCount(); i++) {
+    bufferItem = qobject_cast<BufferItem *>(child(i));
+    if(!bufferItem)
+      continue;
+    if(bufferItem->bufferId() == bufferId)
+      return bufferItem;
+  }
+  return 0;
+}
+
+
 BufferItem *NetworkItem::bufferItem(const BufferInfo &bufferInfo) {
-  BufferItem *bufferItem = qobject_cast<BufferItem *>(childById(qHash(bufferInfo.bufferId())));
+  BufferItem *bufferItem = findBufferItem(bufferInfo);
   if(bufferItem)
     return bufferItem;
   
@@ -360,6 +374,19 @@ void ChannelBufferItem::join(const QList<IrcUser *> &ircUsers) {
   emit dataChanged(2);
 }
 
+UserCategoryItem *ChannelBufferItem::findCategoryItem(int categoryId) {
+  UserCategoryItem *categoryItem = 0;
+  
+  for(int i = 0; i < childCount(); i++) {
+    categoryItem = qobject_cast<UserCategoryItem *>(child(i));
+    if(!categoryItem)
+      continue;
+    if(categoryItem->categoryId() == categoryId)
+      return categoryItem;
+  }
+  return 0;
+}
+
 void ChannelBufferItem::addUserToCategory(IrcUser *ircUser) {
   addUsersToCategory(QList<IrcUser *>() << ircUser);
 }
@@ -374,7 +401,7 @@ void ChannelBufferItem::addUsersToCategory(const QList<IrcUser *> &ircUsers) {
   
   foreach(IrcUser *ircUser, ircUsers) {
     categoryId = UserCategoryItem::categoryFromModes(_ircChannel->userModes(ircUser));
-    categoryItem = qobject_cast<UserCategoryItem *>(childById(qHash(categoryId)));
+    categoryItem = findCategoryItem(categoryId);
     if(!categoryItem) {
       categoryItem = new UserCategoryItem(categoryId, this);
       categories[categoryItem] = QList<IrcUser *>();
@@ -424,22 +451,25 @@ void ChannelBufferItem::userModeChanged(IrcUser *ircUser) {
   Q_ASSERT(_ircChannel);
 
   int categoryId = UserCategoryItem::categoryFromModes(_ircChannel->userModes(ircUser));
-  UserCategoryItem *categoryItem = qobject_cast<UserCategoryItem *>(childById(qHash(categoryId)));
+  UserCategoryItem *categoryItem = findCategoryItem(categoryId);
     
   if(categoryItem) {
-    if(categoryItem->childById(qHash(ircUser)))
+    if(categoryItem->findIrcUser(ircUser)) {
       return; // already in the right category;
+    }
   } else {
     categoryItem = new UserCategoryItem(categoryId, this);
     newChild(categoryItem);
   }
 
   // find the item that needs reparenting
+  UserCategoryItem *oldCategoryItem = 0;
   IrcUserItem *ircUserItem = 0;
   for(int i = 0; i < childCount(); i++) {
-    UserCategoryItem *categoryItem = qobject_cast<UserCategoryItem *>(child(i));
-    IrcUserItem *userItem = qobject_cast<IrcUserItem *>(categoryItem->childById(qHash(ircUser)));
+    UserCategoryItem *catItem = qobject_cast<UserCategoryItem *>(child(i));
+    IrcUserItem *userItem = catItem->findIrcUser(ircUser);
     if(userItem) {
+      oldCategoryItem = catItem;
       ircUserItem = userItem;
       break;
     }
@@ -449,7 +479,11 @@ void ChannelBufferItem::userModeChanged(IrcUser *ircUser) {
     qWarning() << "ChannelBufferItem::userModeChanged(IrcUser *): unable to determine old category of" << ircUser;
     return;
   }
-  ircUserItem->reParent(categoryItem);
+
+  Q_ASSERT(oldCategoryItem);
+  if(ircUserItem->reParent(categoryItem) && oldCategoryItem->childCount() == 0) {
+    removeChild(oldCategoryItem);
+  }
 }
 
 /*****************************************
@@ -463,6 +497,7 @@ UserCategoryItem::UserCategoryItem(int category, AbstractTreeItem *parent)
   : PropertyMapItem(QStringList() << "categoryName", parent),
     _category(category)
 {
+  setObjectName(parent->data(0, Qt::DisplayRole).toString() + "/" + QString::number(category));
 }
 
 // caching this makes no sense, since we display the user number dynamically
@@ -478,8 +513,17 @@ QString UserCategoryItem::categoryName() const {
   }
 }
 
-quint64 UserCategoryItem::id() const {
-  return qHash(_category);
+IrcUserItem *UserCategoryItem::findIrcUser(IrcUser *ircUser) {
+  IrcUserItem *userItem = 0;
+
+  for(int i = 0; i < childCount(); i++) {
+    userItem = qobject_cast<IrcUserItem *>(child(i));
+    if(!userItem)
+      continue;
+    if(userItem->ircUser() == ircUser)
+      return userItem;
+  }
+  return 0;
 }
 
 void UserCategoryItem::addUsers(const QList<IrcUser *> &ircUsers) {
@@ -491,9 +535,12 @@ void UserCategoryItem::addUsers(const QList<IrcUser *> &ircUsers) {
 }
 
 bool UserCategoryItem::removeUser(IrcUser *ircUser) {
-  bool success = removeChildById(qHash(ircUser));
-  if(success)
+  IrcUserItem *userItem = findIrcUser(ircUser);
+  bool success = (bool)userItem;
+  if(success) {
+    removeChild(userItem);
     emit dataChanged(0);
+  }
   return success;
 }
 
@@ -530,12 +577,12 @@ QVariant UserCategoryItem::data(int column, int role) const {
 *****************************************/
 IrcUserItem::IrcUserItem(IrcUser *ircUser, AbstractTreeItem *parent)
   : PropertyMapItem(QStringList() << "nickName", parent),
-    _ircUser(ircUser),
-    _id(qHash(ircUser))
+    _ircUser(ircUser)
 {
+  setObjectName(ircUser->nick());  
   // we don't need to handle the ircUser's destroyed signal since it's automatically removed
   // by the IrcChannel::ircUserParted();
-  
+
   connect(ircUser, SIGNAL(nickSet(QString)),
          this, SLOT(setNick(QString)));
   connect(ircUser, SIGNAL(awaySet(bool)),
@@ -639,49 +686,78 @@ Buffer *NetworkModel::getBufferByIndex(const QModelIndex &index) const {
 }
 */
 
+int NetworkModel::networkRow(NetworkId networkId) {
+  NetworkItem *netItem = 0;
+  for(int i = 0; i < rootItem->childCount(); i++) {
+    netItem = qobject_cast<NetworkItem *>(rootItem->child(i));
+    if(!netItem)
+      continue;
+    if(netItem->networkId() == networkId)
+      return i;
+  }
+  return -1;
+}
 
-// experimental stuff :)
 QModelIndex NetworkModel::networkIndex(NetworkId networkId) {
-  return indexById(qHash(networkId));
+  int netRow = networkRow(networkId);
+  if(netRow == -1)
+    return QModelIndex();
+  else
+    return indexByItem(qobject_cast<NetworkItem *>(rootItem->child(netRow)));
 }
 
-NetworkItem *NetworkModel::existsNetworkItem(NetworkId networkId) {
-  return qobject_cast<NetworkItem *>(rootItem->childById(networkId.toInt()));
+NetworkItem *NetworkModel::findNetworkItem(NetworkId networkId) {
+  int netRow = networkRow(networkId);
+  if(netRow == -1)
+    return 0;
+  else
+    return qobject_cast<NetworkItem *>(rootItem->child(netRow));
 }
 
 NetworkItem *NetworkModel::networkItem(NetworkId networkId) {
-  NetworkItem *netItem = existsNetworkItem(networkId);
+  NetworkItem *netItem = findNetworkItem(networkId);
 
   if(netItem == 0) {
     netItem = new NetworkItem(networkId, rootItem);
     rootItem->newChild(netItem);
   }
-
-  Q_ASSERT(netItem);
   return netItem;
 }
 
 void NetworkModel::networkRemoved(const NetworkId &networkId) {
-  rootItem->removeChildById(qHash(networkId));
+  int netRow = networkRow(networkId);
+  if(netRow != -1) {
+    rootItem->removeChild(netRow);
+  }
 }
 
 QModelIndex NetworkModel::bufferIndex(BufferId bufferId) {
-  AbstractTreeItem *netItem, *bufferItem;
-  for(int i = 0; i < rootItem->childCount(); i++) {
-    netItem = rootItem->child(i);
-    if((bufferItem = netItem->childById(qHash(bufferId)))) {
-      return indexByItem(bufferItem);
-    }
-  }
-  return QModelIndex();
+  BufferItem *bufferItem = findBufferItem(bufferId);
+  if(bufferItem)
+    return indexByItem(bufferItem);
+  else
+    return QModelIndex();
 }
 
-BufferItem *NetworkModel::existsBufferItem(const BufferInfo &bufferInfo) {
-  QModelIndex bufferIdx = bufferIndex(bufferInfo.bufferId());
-  if(bufferIdx.isValid())
-    return static_cast<BufferItem *>(bufferIdx.internalPointer());
-  else
+BufferItem *NetworkModel::findBufferItem(const BufferInfo &bufferInfo) {
+  NetworkItem *netItem = findNetworkItem(bufferInfo.networkId());
+  if(!netItem)
     return 0;
+
+  BufferItem *bufferItem = netItem->findBufferItem(bufferInfo);
+  return bufferItem;
+}
+
+BufferItem *NetworkModel::findBufferItem(BufferId bufferId) {
+  NetworkItem *netItem;
+  BufferItem *bufferItem;
+  
+  for(int i = 0; i < rootItem->childCount(); i++) {
+    netItem = qobject_cast<NetworkItem *>(rootItem->child(i));
+    if((bufferItem = netItem->findBufferItem(bufferId)))
+      return bufferItem;
+  }
+  return 0;
 }
 
 BufferItem *NetworkModel::bufferItem(const BufferInfo &bufferInfo) {
@@ -765,13 +841,15 @@ bool NetworkModel::dropMimeData(const QMimeData *data, Qt::DropAction action, in
   // no self merges (would kill us)
   if(bufferId == parent.data(BufferIdRole).value<BufferId>())
     return false; 
-  
-  Q_ASSERT(rootItem->childById(qHash(netId)));
-  Q_ASSERT(rootItem->childById(qHash(netId))->childById(qHash(bufferId)));
+
+  NetworkItem *netItem = findNetworkItem(netId);
+  Q_ASSERT(netItem);
+
+  BufferItem *bufferItem = netItem->findBufferItem(bufferId);
+  Q_ASSERT(bufferItem);
 
   // source must be a query too
-  BufferInfo::Type sourceType = (BufferInfo::Type)rootItem->childById(qHash(netId))->childById(qHash(bufferId))->data(0, BufferTypeRole).toInt();
-  if(sourceType != BufferInfo::QueryBuffer)
+  if(bufferItem->bufferType() != BufferInfo::QueryBuffer)
     return false;
     
   // TODO: warn user about buffermerge!
@@ -793,14 +871,9 @@ void NetworkModel::bufferUpdated(BufferInfo bufferInfo) {
 }
 
 void NetworkModel::removeBuffer(BufferId bufferId) {
-  const int numNetworks = rootItem->childCount();
-  if(numNetworks == 0)
-    return;
-
-  for(int i = 0; i < numNetworks; i++) {
-    if(rootItem->child(i)->removeChildById(qHash(bufferId)))
-      break;
-  }
+  BufferItem *bufferItem = findBufferItem(bufferId);
+  if(bufferItem)
+    bufferItem->parent()->removeChild(bufferItem);
 }
 
 /*
index 014cab1..22c77b8 100644 (file)
@@ -53,7 +53,6 @@ class NetworkItem : public PropertyMapItem {
 public:
   NetworkItem(const NetworkId &netid, AbstractTreeItem *parent = 0);
 
-  virtual quint64 id() const { return qHash(_networkId); }
   virtual QVariant data(int column, int row) const;
 
   inline bool isActive() const { return (bool)_network ? _network->isConnected() : false; }
@@ -65,6 +64,8 @@ public:
 
   virtual QString toolTip(int column) const;
 
+  BufferItem *findBufferItem(BufferId bufferId);
+  inline BufferItem *findBufferItem(const BufferInfo &bufferInfo) { return findBufferItem(bufferInfo.bufferId()); }
   BufferItem *bufferItem(const BufferInfo &bufferInfo);
 
 public slots:
@@ -93,7 +94,6 @@ public:
   BufferItem(const BufferInfo &bufferInfo, AbstractTreeItem *parent = 0);
 
   inline const BufferInfo &bufferInfo() const { return _bufferInfo; }
-  virtual inline quint64 id() const { return qHash(_bufferInfo.bufferId()); }
   virtual QVariant data(int column, int role) const;
   virtual bool setData(int column, const QVariant &value, int role);
 
@@ -153,6 +153,8 @@ public:
 /*****************************************
 *  ChannelBufferItem
 *****************************************/
+class UserCategoryItem;
+
 class ChannelBufferItem : public BufferItem {
   Q_OBJECT
 
@@ -171,6 +173,7 @@ public slots:
   void join(const QList<IrcUser *> &ircUsers);
   void part(IrcUser *ircUser);
 
+  UserCategoryItem *findCategoryItem(int categoryId);
   void addUserToCategory(IrcUser *ircUser);
   void addUsersToCategory(const QList<IrcUser *> &ircUser);
   void removeUserFromCategory(IrcUser *ircUser);
@@ -187,6 +190,7 @@ private:
 /*****************************************
 *  User Category Items (like @vh etc.)
 *****************************************/
+class IrcUserItem;
 class UserCategoryItem : public PropertyMapItem {
   Q_OBJECT
   Q_PROPERTY(QString categoryName READ categoryName)
@@ -195,9 +199,10 @@ public:
   UserCategoryItem(int category, AbstractTreeItem *parent);
 
   QString categoryName() const;
-  virtual quint64 id() const;
+  inline int categoryId() const { return _category; }
   virtual QVariant data(int column, int role) const;
-  
+
+  IrcUserItem *findIrcUser(IrcUser *ircUser);
   void addUsers(const QList<IrcUser *> &ircUser);
   bool removeUser(IrcUser *ircUser);
 
@@ -223,7 +228,6 @@ public:
   bool isActive() const;
 
   inline IrcUser *ircUser() { return _ircUser; }
-  inline virtual quint64 id() const { return _id; }
   virtual QVariant data(int column, int role) const;
   virtual QString toolTip(int column) const;
 
@@ -233,7 +237,6 @@ private slots:
 
 private:
   QPointer<IrcUser> _ircUser;
-  quint64 _id;
 };
 
 
@@ -290,10 +293,12 @@ public slots:
   void networkRemoved(const NetworkId &networkId);
   
 private:
+  int networkRow(NetworkId networkId);
+  NetworkItem *findNetworkItem(NetworkId networkId);
   NetworkItem *networkItem(NetworkId networkId);
-  NetworkItem *existsNetworkItem(NetworkId networkId);
+  BufferItem *findBufferItem(const BufferInfo &bufferInfo);
+  BufferItem *findBufferItem(BufferId bufferId);
   BufferItem *bufferItem(const BufferInfo &bufferInfo);
-  BufferItem *existsBufferItem(const BufferInfo &bufferInfo);
 
 };
 Q_DECLARE_OPERATORS_FOR_FLAGS(NetworkModel::itemTypes);
index c61cf9e..f79befb 100644 (file)
@@ -35,19 +35,11 @@ AbstractTreeItem::AbstractTreeItem(AbstractTreeItem *parent)
 AbstractTreeItem::~AbstractTreeItem() {
 }
 
-quint64 AbstractTreeItem::id() const {
-  return qHash(this);
-}
-
 bool AbstractTreeItem::newChild(AbstractTreeItem *item) {
-  // check if a child with that ID is already known
-  Q_ASSERT(childById(item->id()) == 0);
-    
   int newRow = childCount();
   emit beginAppendChilds(newRow, newRow);
   _childItems.append(item);
   emit endAppendChilds();
-  
   return true;
 }
 
@@ -55,26 +47,11 @@ bool AbstractTreeItem::newChilds(const QList<AbstractTreeItem *> &items) {
   if(items.isEmpty())
     return false;
   
-  QList<AbstractTreeItem *>::const_iterator itemIter = items.constBegin();
-  AbstractTreeItem *item;
-  while(itemIter != items.constEnd()) {
-    item = *itemIter;
-    if(childById(item->id()) != 0) {
-      qWarning() << "AbstractTreeItem::newChilds(): received child that is already attached" << item << item->id();
-      return false;
-    }
-    itemIter++;
-  }
-
   int nextRow = childCount();
   int lastRow = nextRow + items.count() - 1;
 
   emit beginAppendChilds(nextRow, lastRow);
-  itemIter = items.constBegin();
-  while(itemIter != items.constEnd()) {
-    _childItems.append(*itemIter);
-    itemIter++;
-  }
+  _childItems << items;
   emit endAppendChilds();
 
   return true;
@@ -93,17 +70,6 @@ bool AbstractTreeItem::removeChild(int row) {
   return true;
 }
 
-bool AbstractTreeItem::removeChildById(const quint64 &id) {
-  const int numChilds = childCount();
-  
-  for(int i = 0; i < numChilds; i++) {
-    if(_childItems[i]->id() == id)
-      return removeChild(i);
-  }
-  
-  return false;
-}
-
 void AbstractTreeItem::removeAllChilds() {
   const int numChilds = childCount();
   
@@ -163,15 +129,6 @@ AbstractTreeItem *AbstractTreeItem::child(int row) const {
     return _childItems[row];
 }
 
-AbstractTreeItem *AbstractTreeItem::childById(const quint64 &id) const {
-  const int numChilds = childCount();
-  for(int i = 0; i < numChilds; i++) {
-    if(_childItems[i]->id() == id)
-      return _childItems[i];
-  }
-  return 0;
-}
-
 int AbstractTreeItem::childCount(int column) const {
   if(column > 0)
     return 0;
@@ -191,26 +148,14 @@ int AbstractTreeItem::row() const {
   return row_;
 }
 
-AbstractTreeItem *AbstractTreeItem::parent() const {
-  return qobject_cast<AbstractTreeItem *>(QObject::parent());
-}
-
-Qt::ItemFlags AbstractTreeItem::flags() const {
-  return _flags;
-}
-
-void AbstractTreeItem::setFlags(Qt::ItemFlags flags) {
-  _flags = flags;
-}
-
 void AbstractTreeItem::dumpChildList() {
-  qDebug() << "==== Childlist for Item:" << this << id() << "====";
+  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->id() << child->data(0, Qt::DisplayRole);
+      qDebug() << "Row:" << child->row() << child << child->data(0, Qt::DisplayRole);
       childIter++;
     }
   }
@@ -354,22 +299,6 @@ QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) con
     return QModelIndex();
 }
 
-QModelIndex TreeModel::indexById(quint64 id, const QModelIndex &parent) const {
-  AbstractTreeItem *parentItem; 
-  
-  if(!parent.isValid())
-    parentItem = rootItem;
-  else
-    parentItem = static_cast<AbstractTreeItem *>(parent.internalPointer());
-  
-  AbstractTreeItem *childItem = parentItem->childById(id);
-  
-  if(childItem)
-    return createIndex(childItem->row(), 0, childItem);
-  else
-    return QModelIndex();
-}
-
 QModelIndex TreeModel::indexByItem(AbstractTreeItem *item) const {
   if(item == 0) {
     qWarning() << "TreeModel::indexByItem(AbstractTreeItem *item) received NULL-Pointer";
@@ -584,7 +513,7 @@ void TreeModel::debug_rowsAboutToBeRemoved(const QModelIndex &parent, int start,
     child = parent.child(i, 0);
     childItem = parentItem->child(i);
     Q_ASSERT(childItem);
-    qDebug() << ">>>" << i << child << childItem->id() << child.data().toString();
+    qDebug() << ">>>" << i << child << child.data().toString();
   }
 }
 
@@ -601,7 +530,7 @@ void TreeModel::debug_rowsInserted(const QModelIndex &parent, int start, int end
     child = parent.child(i, 0);
     childItem = parentItem->child(i);
     Q_ASSERT(childItem);
-    qDebug() << "<<<" << i << child << childItem->id() << child.data().toString();
+    qDebug() << "<<<" << i << child << child.data().toString();
   }
 }
 
index 6dd6ed8..8a5e3ac 100644 (file)
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
-#ifndef _TREEMODEL_H_
-#define _TREEMODEL_H_
+#ifndef TREEMODEL_H
+#define TREEMODEL_H
 
 #include <QList>
 #include <QStringList>
 #include <QVariant>
-#include <QHash>
 #include <QAbstractItemModel>
 
 #include <QLinkedList> // needed for debug
@@ -34,7 +33,6 @@
  *****************************************/
 class AbstractTreeItem : public QObject {
   Q_OBJECT
-  Q_PROPERTY(quint64 id READ id)
 
 public:
   AbstractTreeItem(AbstractTreeItem *parent = 0);
@@ -44,15 +42,12 @@ public:
   bool newChilds(const QList<AbstractTreeItem *> &items);
 
   bool removeChild(int row);
-  bool removeChildById(const quint64 &id);
+  inline bool removeChild(AbstractTreeItem *child) { return removeChild(child->row()); }
   void removeAllChilds();
 
-  virtual quint64 id() const;
-
   bool reParent(AbstractTreeItem *newParent);
     
   AbstractTreeItem *child(int row) const;
-  AbstractTreeItem *childById(const quint64 &id) const;
 
   int childCount(int column = 0) const;
 
@@ -61,11 +56,11 @@ public:
   virtual QVariant data(int column, int role) const = 0;
   virtual bool setData(int column, const QVariant &value, int role) = 0;
 
-  virtual Qt::ItemFlags flags() const;
-  virtual void setFlags(Qt::ItemFlags);
+  virtual inline Qt::ItemFlags flags() const { return _flags; }
+  virtual inline void setFlags(Qt::ItemFlags flags) { _flags = flags; }
 
   int row() const;
-  AbstractTreeItem *parent() const;
+  inline AbstractTreeItem *parent() const { return qobject_cast<AbstractTreeItem *>(QObject::parent()); }
 
   void dumpChildList();
 
@@ -150,7 +145,6 @@ public:
   QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
   
   QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
-  QModelIndex indexById(quint64 id, const QModelIndex &parent = QModelIndex()) const;
   QModelIndex indexByItem(AbstractTreeItem *item) const;
 
   QModelIndex parent(const QModelIndex &index) const;