Cleanupination/Prettyfication/Refactorination of the BufferModel
authorMarcus Eggenberger <egs@quassel-irc.org>
Mon, 29 Oct 2007 17:29:46 +0000 (17:29 +0000)
committerMarcus Eggenberger <egs@quassel-irc.org>
Mon, 29 Oct 2007 17:29:46 +0000 (17:29 +0000)
12 files changed:
src/client/buffer.cpp
src/client/buffer.h
src/client/buffertreemodel.cpp
src/client/buffertreemodel.h
src/client/treemodel.cpp
src/client/treemodel.h
src/qtui/bufferview.cpp
src/qtui/bufferview.h
src/qtui/bufferviewfilter.cpp
src/qtui/bufferviewfilter.h
src/qtui/mainwin.cpp
src/qtui/mainwin.h

index 3e6e339..48d8a70 100644 (file)
@@ -86,15 +86,11 @@ QString Buffer::networkName() const {
   return bufferInfo().network();
 }
 
-QString Buffer::bufferName() const {
-  return bufferInfo().buffer();
-}
-
-QString Buffer::displayName() const {
+QString Buffer::name() const {
   if(bufferType() == StatusType)
     return tr("Status Buffer");
   else
-    return bufferName();
+    return bufferInfo().buffer();
 }
 
 QList<AbstractUiMsg *> Buffer::contents() const {
index fa2e472..781a996 100644 (file)
@@ -65,8 +65,7 @@ public:
   uint networkId() const;
   
   QString networkName() const;
-  QString bufferName() const;
-  QString displayName() const;
+  QString name() const;
   
   QList<AbstractUiMsg *> contents() const;
   
index 93c9063..23e3688 100644 (file)
 /*****************************************
 *  Fancy Buffer Items
 *****************************************/
-BufferTreeItem::BufferTreeItem(Buffer *buffer, TreeItem *parent) : TreeItem(parent) {
-  buf = buffer;
-  activity = Buffer::NoActivity;
+BufferTreeItem::BufferTreeItem(Buffer *buffer, TreeItem *parent)
+  : TreeItem(parent),
+    buf(buffer),
+    activity(Buffer::NoActivity)
+{
+  Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
+  if(buf->bufferType() == Buffer::QueryType)
+    flags |= Qt::ItemIsDropEnabled;
+  setFlags(flags);
 }
 
 uint BufferTreeItem::id() const {
@@ -48,7 +54,7 @@ void BufferTreeItem::setActivity(const Buffer::ActivityLevel &level) {
 QString BufferTreeItem::text(int column) const {
   switch(column) {
     case 0:
-      return buf->displayName();
+      return buf->name();
     case 1:
       return buf->networkName();
     default:
@@ -56,7 +62,8 @@ QString BufferTreeItem::text(int column) const {
   }
 }
 
-QColor BufferTreeItem::foreground(int /*column*/) const {
+QColor BufferTreeItem::foreground(int column) const {
+  Q_UNUSED(column)
   // for the time beeing we ignore the column :)
   if(activity & Buffer::Highlight) {
     return QColor(Qt::red);
@@ -75,45 +82,48 @@ QColor BufferTreeItem::foreground(int /*column*/) const {
 
 QVariant BufferTreeItem::data(int column, int role) const {
   switch(role) {
-    case Qt::DisplayRole:
-      return text(column);
-    case Qt::ForegroundRole:
-      return foreground(column);
-    case BufferTreeModel::BufferNameRole:
-      return buf->bufferName();
-    case BufferTreeModel::BufferTypeRole:
-      return int(buf->bufferType());
-    case BufferTreeModel::BufferActiveRole:
-      return buf->isActive();
-    case BufferTreeModel::BufferUidRole:
-      return buf->bufferInfo().uid();
-    default:
-      return QVariant();
+  case Qt::DisplayRole:
+    return text(column);
+  case Qt::ForegroundRole:
+    return foreground(column);
+  case BufferTreeModel::BufferTypeRole:
+    return int(buf->bufferType());
+  case BufferTreeModel::BufferActiveRole:
+    return buf->isActive();
+  case BufferTreeModel::BufferUidRole:
+    return buf->bufferInfo().uid();
+  case BufferTreeModel::NetworkIdRole:
+    return buf->bufferInfo().networkId();
+    
+  default:
+    return TreeItem::data(column, role);
   }
 }
 
-Qt::ItemFlags BufferTreeItem::flags() const {
-  Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
-  if(buf->bufferType() == Buffer::QueryType)
-    flags |= Qt::ItemIsDropEnabled;
-
-  return flags;
-}
-
 /*****************************************
 *  Network Items
 *****************************************/
-NetworkTreeItem::NetworkTreeItem(const QString &network, TreeItem *parent) : TreeItem(parent) {
+NetworkTreeItem::NetworkTreeItem(const uint &netid, const QString &network, TreeItem *parent)
+  : TreeItem(parent),
+    _networkId(netid),
+    net(network)
+{
   net = network;
   itemData << net << "";
+  setFlags(Qt::ItemIsEnabled);
 }
 
-uint NetworkTreeItem::id() const {
-  return qHash(net);
+QVariant NetworkTreeItem::data(int column, int role) const {
+  switch(role) {
+  case BufferTreeModel::NetworkIdRole:
+    return _networkId;
+  default:
+    return TreeItem::data(column, role);
+  }
 }
 
-Qt::ItemFlags NetworkTreeItem::flags() const {
-  return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled;
+uint NetworkTreeItem::id() const {
+  return _networkId;
 }
 
 /*****************************************
@@ -124,7 +134,7 @@ BufferTreeModel::BufferTreeModel(QObject *parent)
     _selectionModelSynchronizer(new SelectionModelSynchronizer(this)),
     _propertyMapper(new ModelPropertyMapper(this))
 {
-  rootItem->setFlags(rootItem->flags() | Qt::ItemIsDropEnabled);
+  // initialize the Property Mapper
   _propertyMapper->setModel(this);
   delete _propertyMapper->selectionModel();
   MappedSelectionModel *mappedSelectionModel = new MappedSelectionModel(this);
@@ -169,11 +179,12 @@ Buffer *BufferTreeModel::getBufferByIndex(const QModelIndex &index) const {
 
 QModelIndex BufferTreeModel::getOrCreateNetworkItemIndex(Buffer *buffer) {
   QString net = buffer->networkName();
+  uint netId = buffer->networkId();
   TreeItem *networkItem;
 
-  if(!(networkItem = rootItem->childById(qHash(net)))) {
+  if(!(networkItem = rootItem->childById(netId))) {
     int nextRow = rootItem->childCount();
-    networkItem = new NetworkTreeItem(net, rootItem);
+    networkItem = new NetworkTreeItem(netId, net, rootItem);
     
     beginInsertRows(QModelIndex(), nextRow, nextRow);
     rootItem->appendChild(networkItem);
@@ -203,50 +214,92 @@ QModelIndex BufferTreeModel::getOrCreateBufferItemIndex(Buffer *buffer) {
 }
 
 QStringList BufferTreeModel::mimeTypes() const {
+  // mimetypes we accept for drops
   QStringList types;
-  types << "application/Quassel/BufferItem/row"
-    << "application/Quassel/BufferItem/network"
-    << "application/Quassel/BufferItem/bufferInfo";
+  // comma separated list of colon separated pairs of networkid and bufferid
+  // example: 0:1,0:2,1:4
+  types << "application/Quassel/BufferItemList";
   return types;
 }
 
+bool BufferTreeModel::mimeContainsBufferList(const QMimeData *mimeData) {
+  return mimeData->hasFormat("application/Quassel/BufferItemList");
+}
+
+QList< QPair<uint, uint> > BufferTreeModel::mimeDataToBufferList(const QMimeData *mimeData) {
+  QList< QPair<uint, uint> > bufferList;
+
+  if(!mimeContainsBufferList(mimeData))
+    return bufferList;
+
+  QStringList rawBufferList = QString::fromAscii(mimeData->data("application/Quassel/BufferItemList")).split(",");
+  uint networkId, bufferUid;
+  foreach(QString rawBuffer, rawBufferList) {
+    if(!rawBuffer.contains(":"))
+      continue;
+    networkId = rawBuffer.section(":", 0, 0).toUInt();
+    bufferUid = rawBuffer.section(":", 1, 1).toUInt();
+    bufferList.append(qMakePair(networkId, bufferUid));
+  }
+  return bufferList;
+}
+
+
 QMimeData *BufferTreeModel::mimeData(const QModelIndexList &indexes) const {
   QMimeData *mimeData = new QMimeData();
 
-  QModelIndex index = indexes.first();
-  
-  mimeData->setData("application/Quassel/BufferItem/row", QByteArray::number(index.row()));
-  mimeData->setData("application/Quassel/BufferItem/network", getBufferByIndex(index)->networkName().toUtf8());
-  mimeData->setData("application/Quassel/BufferItem/bufferInfo", QByteArray::number(getBufferByIndex(index)->bufferInfo().uid()));
+  QStringList bufferlist;
+  QString netid, uid, bufferid;
+  foreach(QModelIndex index, indexes) {
+    netid = QString::number(index.data(NetworkIdRole).toUInt());
+    uid = QString::number(index.data(BufferUidRole).toUInt());
+    bufferid = QString("%1:%2").arg(netid).arg(uid);
+    if(!bufferlist.contains(bufferid))
+      bufferlist << bufferid;
+  }
+
+  mimeData->setData("application/Quassel/BufferItemList", bufferlist.join(",").toAscii());
+
   return mimeData;
 }
 
-bool BufferTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction /*action*/, int /*row*/, int /*column*/, const QModelIndex &parent) {
-  foreach(QString mimeType, mimeTypes()) {
-    if(!(data->hasFormat(mimeType)))
-      return false; // whatever the drop is... it's not a buffer...
-  }
-  
-  int sourcerow = data->data("application/Quassel/BufferItem/row").toInt();
-  QString network = QString::fromUtf8(data->data("application/Quassel/BufferItem/network"));
-  
-  Q_ASSERT(rootItem->childById(qHash(network)));
+bool BufferTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) {
+  Q_UNUSED(action)
+  Q_UNUSED(row)
+  Q_UNUSED(column)
 
-  if(parent == QModelIndex()) // can't be a query...
+  if(!mimeContainsBufferList(data))
     return false;
-  
-  Buffer *sourceBuffer = static_cast<BufferTreeItem *>(rootItem->childById(qHash(network))->child(sourcerow))->buffer();
-  Buffer *targetBuffer = getBufferByIndex(parent);
 
-  if(!(sourceBuffer->bufferType() & targetBuffer->bufferType() & Buffer::QueryType)) // only queries can be merged
+  // target must be a query
+  Buffer::Type targetType = (Buffer::Type)parent.data(BufferTreeModel::BufferTypeRole).toInt();
+  if(targetType != Buffer::QueryType)
     return false;
+
+  QList< QPair<uint, uint> > bufferList = mimeDataToBufferList(data);
+
+  // exactly one buffer has to be dropped
+  if(bufferList.count() != 1)
+    return false;
+
+  uint netId = bufferList.first().first;
+  uint bufferId = bufferList.first().second;
+
+  // no self merges (would kill us)
+  if(bufferId == parent.data(BufferUidRole).toInt())
+    return false; 
   
-  if(sourceBuffer == targetBuffer) // we won't merge with ourself :)
+  Q_ASSERT(rootItem->childById(netId));
+  Q_ASSERT(rootItem->childById(netId)->childById(bufferId));
+
+  // source must be a query too
+  Buffer::Type sourceType = (Buffer::Type)rootItem->childById(netId)->childById(bufferId)->data(0, BufferTypeRole).toInt();
+  if(sourceType != Buffer::QueryType)
     return false;
     
   // TODO: warn user about buffermerge!
-  qDebug() << "merging" << sourceBuffer->bufferName() << "with" << targetBuffer->bufferName();
-  removeRow(parent.row(), BufferTreeModel::parent(parent));
+  qDebug() << "merging" << bufferId << parent.data(BufferUidRole).toInt();
+  removeRow(parent.row(), parent.parent());
   
   return true;
 }
index 70a9619..e194c27 100644 (file)
@@ -48,7 +48,6 @@ public:
 
   virtual uint id() const;
   QVariant data(int column, int role) const;
-  virtual Qt::ItemFlags flags() const;
   
   Buffer *buffer() const { return buf; }
   void setActivity(const Buffer::ActivityLevel &);
@@ -68,14 +67,14 @@ class NetworkTreeItem : public TreeItem {
   Q_OBJECT
   
 public:
-  NetworkTreeItem(const QString &, TreeItem *parent = 0);
+  NetworkTreeItem(const uint &netid, const QString &, TreeItem *parent = 0);
 
+  virtual QVariant data(int column, int row) const;
   virtual uint id() const;
-  virtual Qt::ItemFlags flags() const;
   
 private:
+  uint _networkId;
   QString net;
-  
 };
 
 /*****************************************
@@ -88,8 +87,8 @@ public:
   enum myRoles {
     BufferTypeRole = Qt::UserRole,
     BufferActiveRole,
-    BufferNameRole,
-    BufferUidRole
+    BufferUidRole,
+    NetworkIdRole
   };
   
   BufferTreeModel(QObject *parent = 0);
@@ -102,6 +101,14 @@ public:
   void synchronizeView(QAbstractItemView *view);
   void mapProperty(int column, int role, QObject *target, const QByteArray &property);
 
+  static bool mimeContainsBufferList(const QMimeData *mimeData);
+  static QList< QPair<uint, uint> > mimeDataToBufferList(const QMimeData *mimeData);
+  
+  virtual QStringList mimeTypes() const;
+  virtual QMimeData *mimeData(const QModelIndexList &) const;
+  virtual bool dropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex &);
+
+
 public slots:
   void bufferUpdated(Buffer *);
   void setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command);
@@ -119,10 +126,6 @@ private:
   QModelIndex getOrCreateNetworkItemIndex(Buffer *buffer);
   QModelIndex getOrCreateBufferItemIndex(Buffer *buffer);
 
-  QStringList mimeTypes() const;
-  QMimeData *mimeData(const QModelIndexList &) const;
-  bool dropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex &);
-
   QPointer<SelectionModelSynchronizer> _selectionModelSynchronizer;
   QPointer<ModelPropertyMapper> _propertyMapper;
   Buffer *currentBuffer;
index 52439af..bee4cfa 100644 (file)
  *****************************************/
 TreeItem::TreeItem(const QList<QVariant> &data, TreeItem *parent)
   : QObject(parent),
-    parentItem(parent),
     itemData(data),
-  _flags(Qt::ItemIsSelectable | Qt::ItemIsEnabled)
+    _parentItem(parent),
+    _flags(Qt::ItemIsSelectable | Qt::ItemIsEnabled)
 {
 }
 
-TreeItem::TreeItem(TreeItem *parent) {
-  itemData = QList<QVariant>();
-  parentItem = parent;
+TreeItem::TreeItem(TreeItem *parent)
+  : QObject(parent),
+    itemData(QList<QVariant>()),
+    _parentItem(parent),
+    _flags(Qt::ItemIsSelectable | Qt::ItemIsEnabled)
+{
 }
 
 TreeItem::~TreeItem() {
-  qDeleteAll(childItems);
+  qDeleteAll(_childItems);
 }
 
 uint TreeItem::id() const {
@@ -46,45 +49,47 @@ uint TreeItem::id() const {
 }
 
 void TreeItem::appendChild(TreeItem *item) {
-  childItems.append(item);
-  childHash[item->id()] = item;
+  _childItems.append(item);
+  _childHash[item->id()] = item;
+  connect(item, SIGNAL(destroyed()),
+         this, SLOT(childDestroyed()));
 }
 
 void TreeItem::removeChild(int row) {
-  if(row >= childItems.size())
+  if(row >= _childItems.size())
     return;
-  TreeItem *treeitem = childItems.value(row);
-  childItems.removeAt(row);
-  childHash.remove(childHash.key(treeitem));
+  TreeItem *treeitem = _childItems.value(row);
+  _childItems.removeAt(row);
+  _childHash.remove(_childHash.key(treeitem));
 }
 
 TreeItem *TreeItem::child(int row) const {
-  if(row < childItems.size())
-    return childItems.value(row);
+  if(row < _childItems.size())
+    return _childItems.value(row);
   else
     return 0;
 }
 
 TreeItem *TreeItem::childById(const uint &id) const {
-  if(childHash.contains(id))
-    return childHash.value(id);
+  if(_childHash.contains(id))
+    return _childHash.value(id);
   else
     return 0;
 }
 
 int TreeItem::childCount() const {
-  return childItems.count();
+  return _childItems.count();
 }
 
 int TreeItem::row() const {
-  if(parentItem)
-    return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));
+  if(_parentItem)
+    return _parentItem->_childItems.indexOf(const_cast<TreeItem*>(this));
   else
     return 0;
 }
 
 TreeItem *TreeItem::parent() {
-  return parentItem;
+  return _parentItem;
 }
 
 int TreeItem::columnCount() const {
@@ -99,7 +104,6 @@ QVariant TreeItem::data(int column, int role) const {
 }
 
 Qt::ItemFlags TreeItem::flags() const {
-  // some sane defaults
   return _flags;
 }
 
@@ -107,6 +111,12 @@ void TreeItem::setFlags(Qt::ItemFlags flags) {
   _flags = flags;
 }
 
+void TreeItem::childDestroyed() {
+  TreeItem *item = static_cast<TreeItem*>(sender());
+  removeChild(item->row());
+}
+  
+
 
 /*****************************************
  * TreeModel
@@ -159,7 +169,7 @@ QModelIndex TreeModel::parent(const QModelIndex &index) const {
     return QModelIndex();
   
   TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
-  TreeItem *parentItem = childItem->parent();
+  TreeItem *parentItem = static_cast<TreeItem*>(childItem->parent());
   
   if(parentItem == rootItem)
     return QModelIndex();
@@ -169,9 +179,6 @@ QModelIndex TreeModel::parent(const QModelIndex &index) const {
 
 int TreeModel::rowCount(const QModelIndex &parent) const {
   TreeItem *parentItem;
-  if(parent.column() > 0)
-    return 0;
-  
   if(!parent.isValid())
     parentItem = rootItem;
   else
index 6346d4f..c720216 100644 (file)
@@ -42,21 +42,33 @@ public:
   void removeChild(int row);
                    
   virtual uint id() const;
+  
   TreeItem *child(int row) const;
   TreeItem *childById(const uint &) const;
+  
   int childCount() const;
   int columnCount() const;
+  
   virtual QVariant data(int column, int role) const;
-  virtual Qt::ItemFlags flags() const;
-  virtual void setFlags(Qt::ItemFlags);
+    
+  Qt::ItemFlags flags() const;
+  void setFlags(Qt::ItemFlags);
+  
   int row() const;
   TreeItem *parent();
-    
+
+
+private slots:
+  void childDestroyed();
+  
 protected:
-  QList<TreeItem *> childItems;
-  QHash<uint, TreeItem *> childHash; // uint to be compatible to qHash functions
-  TreeItem *parentItem;
   QList<QVariant> itemData;
+  
+private:
+  QList<TreeItem *> _childItems;
+  QHash<uint, TreeItem *> _childHash; // uint to be compatible to qHash functions
+  TreeItem *_parentItem;
   Qt::ItemFlags _flags;
 };
 
index 4ad1138..e06ef72 100644 (file)
@@ -44,14 +44,12 @@ void BufferView::init() {
   
   setSortingEnabled(true);
   sortByColumn(0, Qt::AscendingOrder);
-  
   connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(joinChannel(QModelIndex)));
 }
 
-void BufferView::setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QStringList nets) {
+void BufferView::setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QList<uint> nets) {
   BufferViewFilter *filter = new BufferViewFilter(model, mode, nets);
   setModel(filter);
-  connect(this, SIGNAL(eventDropped(QDropEvent *)), filter, SLOT(dropEvent(QDropEvent *)));
   connect(this, SIGNAL(removeBuffer(const QModelIndex &)), filter, SLOT(removeBuffer(const QModelIndex &)));
 }
 
@@ -62,16 +60,6 @@ void BufferView::setModel(QAbstractItemModel *model) {
   
 }
 
-void BufferView::dropEvent(QDropEvent *event) {
-  if(event->source() != this) {
-    // another view(?) or widget is the source. maybe it's a drag 'n drop 
-    // view customization -> we tell our friend the filter:
-    emit eventDropped(event);
-  }
-  // in the case that the filter did not accept the event or if it's a merge
-  QTreeView::dropEvent(event);    
-}
-
 void BufferView::joinChannel(const QModelIndex &index) {
   Buffer::Type bufferType = (Buffer::Type)index.data(BufferTreeModel::BufferTypeRole).toInt();
 
index 8240f8d..b7d5043 100644 (file)
@@ -36,14 +36,12 @@ public:
   BufferView(QWidget *parent = 0);
   void init();
   void setModel(QAbstractItemModel *model);
-  void setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QStringList nets);
+  void setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QList<uint> nets);
   
 signals:
-  void eventDropped(QDropEvent *);
   void removeBuffer(const QModelIndex &);
   
 private slots:
-  void dropEvent(QDropEvent *);
   void joinChannel(const QModelIndex &index);
   void keyPressEvent(QKeyEvent *);
   void rowsInserted (const QModelIndex & parent, int start, int end);
index d30c313..656fd5f 100644 (file)
 /*****************************************
 * The Filter for the Tree View
 *****************************************/
-BufferViewFilter::BufferViewFilter(QAbstractItemModel *model, const Modes &filtermode, const QStringList &nets)
+BufferViewFilter::BufferViewFilter(QAbstractItemModel *model, const Modes &filtermode, const QList<uint> &nets)
   : QSortFilterProxyModel(model),
     mode(filtermode),
-    networks(nets)
+    networks(QSet<uint>::fromList(nets))
 {
   setSourceModel(model);
-  setSortRole(BufferTreeModel::BufferNameRole);
   setSortCaseSensitivity(Qt::CaseInsensitive);
   
-  connect(model, SIGNAL(invalidateFilter()), this, SLOT(invalidateMe()));
+  // I have this feeling that this resulted in a fuckup once... no clue though right now and invalidateFilter isn't a slot -.-
+  connect(model, SIGNAL(invalidateFilter()), this, SLOT(invalidate()));
 }
 
-void BufferViewFilter::invalidateMe() {
-  invalidateFilter();
+Qt::ItemFlags BufferViewFilter::flags(const QModelIndex &index) const {
+  Qt::ItemFlags flags = mapToSource(index).flags();
+  if(mode & FullCustom) {
+    if(index == QModelIndex() || index.parent() == QModelIndex())
+      flags |= Qt::ItemIsDropEnabled;
+  }
+  return flags;
 }
 
-void BufferViewFilter::dropEvent(QDropEvent *event) {
-  const QMimeData *data = event->mimeData();
-  if(!(mode & FullCustom))
-    return; // only custom buffers can be customized... obviously... :)
-  
-  if(!(data->hasFormat("application/Quassel/BufferItem/row")
-       && data->hasFormat("application/Quassel/BufferItem/network")
-       && data->hasFormat("application/Quassel/BufferItem/bufferInfo")))
-    return; // whatever the drop is... it's not a buffer...
-  
-  event->accept();
-  uint bufferuid = data->data("application/Quassel/BufferItem/bufferInfo").toUInt();
-  QString networkname = QString::fromUtf8("application/Quassel/BufferItem/network");
-  
-  for(int rowid = 0; rowid < rowCount(); rowid++) {
-    QModelIndex networkindex = index(rowid, 0);
-    if(networkindex.data(Qt::DisplayRole) == networkname) {
-      addBuffer(bufferuid);
-      return;
-    }
+bool BufferViewFilter::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) {
+  // drops have to occur in the open field
+  if(parent != QModelIndex())
+    return QSortFilterProxyModel::dropMimeData(data, action, row, column, parent);
+
+  if(!BufferTreeModel::mimeContainsBufferList(data))
+    return false;
+
+  QList< QPair<uint, uint> > bufferList = BufferTreeModel::mimeDataToBufferList(data);
+
+  uint netId, bufferId;
+  for(int i = 0; i < bufferList.count(); i++) {
+    netId = bufferList[i].first;
+    bufferId = bufferList[i].second;
+    networks << netId;
+    addBuffer(bufferId);
   }
-  beginInsertRows(QModelIndex(), rowCount(), rowCount());
-  addBuffer(bufferuid);
-  endInsertRows();
+  return true;
 }
 
-
 void BufferViewFilter::addBuffer(const uint &bufferuid) {
-  if(!customBuffers.contains(bufferuid)) {
-    customBuffers << bufferuid;
+  if(!buffers.contains(bufferuid)) {
+    buffers << bufferuid;
     invalidateFilter();
   }
 }
@@ -79,12 +77,14 @@ void BufferViewFilter::removeBuffer(const QModelIndex &index) {
   
   if(index.parent() == QModelIndex())
     return; // only child elements can be deleted
-  
+
+  bool lastBuffer = (rowCount(index.parent()) == 1);
+  uint netId = index.data(BufferTreeModel::NetworkIdRole).toUInt();
   uint bufferuid = index.data(BufferTreeModel::BufferUidRole).toUInt();
-  if(customBuffers.contains(bufferuid)) {
-    beginRemoveRows(index.parent(), index.row(), index.row());
-    customBuffers.removeAt(customBuffers.indexOf(bufferuid));
-    endRemoveRows();
+  if(buffers.contains(bufferuid)) {
+    buffers.remove(bufferuid);
+    if(lastBuffer)
+      networks.remove(netId);
     invalidateFilter();
   }
   
@@ -93,17 +93,23 @@ void BufferViewFilter::removeBuffer(const QModelIndex &index) {
 
 bool BufferViewFilter::filterAcceptBuffer(const QModelIndex &source_bufferIndex) const {
   Buffer::Type bufferType = (Buffer::Type) source_bufferIndex.data(BufferTreeModel::BufferTypeRole).toInt();
-  if((mode & NoChannels) && bufferType == Buffer::ChannelType) return false;
-  if((mode & NoQueries) && bufferType == Buffer::QueryType) return false;
-  if((mode & NoServers) && bufferType == Buffer::StatusType) return false;
+  
+  if((mode & NoChannels) && bufferType == Buffer::ChannelType)
+    return false;
+  if((mode & NoQueries) && bufferType == Buffer::QueryType)
+    return false;
+  if((mode & NoServers) && bufferType == Buffer::StatusType)
+    return false;
 
   bool isActive = source_bufferIndex.data(BufferTreeModel::BufferActiveRole).toBool();
-  if((mode & NoActive) && isActive) return false;
-  if((mode & NoInactive) && !isActive) return false;
+  if((mode & NoActive) && isActive)
+    return false;
+  if((mode & NoInactive) && !isActive)
+    return false;
 
   if((mode & FullCustom)) {
     uint bufferuid = source_bufferIndex.data(BufferTreeModel::BufferUidRole).toUInt();
-    if(!customBuffers.contains(bufferuid))
+    if(!buffers.contains(bufferuid))
       return false;
   }
     
@@ -111,22 +117,8 @@ bool BufferViewFilter::filterAcceptBuffer(const QModelIndex &source_bufferIndex)
 }
 
 bool BufferViewFilter::filterAcceptNetwork(const QModelIndex &source_index) const {
-  QString net = source_index.data(Qt::DisplayRole).toString();
-  if((mode & SomeNets) && !networks.contains(net)) {
-    return false;
-  } else if(mode & FullCustom) {
-    // let's check if we got a child that want's to show off
-    int childcount = sourceModel()->rowCount(source_index);
-    for(int rowid = 0; rowid < childcount; rowid++) {
-      QModelIndex child = sourceModel()->index(rowid, 0, source_index);
-      uint bufferuid = child.data(BufferTreeModel::BufferUidRole).toUInt();
-      if(customBuffers.contains(bufferuid))
-        return true;
-    }
-    return false;
-  } else {
-    return true;
-  }
+  uint net = source_index.data(BufferTreeModel::NetworkIdRole).toUInt();
+  return !((mode & (SomeNets | FullCustom)) && !networks.contains(net));
 }
 
 bool BufferViewFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const {
@@ -143,8 +135,13 @@ bool BufferViewFilter::filterAcceptsRow(int source_row, const QModelIndex &sourc
     return filterAcceptBuffer(child);
 }
 
-bool BufferViewFilter::lessThan(const QModelIndex &left, const QModelIndex &right) {
-  // pretty interesting stuff here, eh?
-  return QSortFilterProxyModel::lessThan(left, right);
+bool BufferViewFilter::lessThan(const QModelIndex &left, const QModelIndex &right) const {
+  int lefttype = left.data(BufferTreeModel::BufferTypeRole).toInt();
+  int righttype = right.data(BufferTreeModel::BufferTypeRole).toInt();
+
+  if(lefttype != righttype)
+    return lefttype < righttype;
+  else
+    return QSortFilterProxyModel::lessThan(left, right);
 }
 
index edda7ac..bd00e41 100644 (file)
@@ -24,6 +24,7 @@
 #include <QFlags>
 #include <QDropEvent>
 #include <QSortFilterProxyModel>
+#include <QSet>
 #include "buffer.h"
 #include "buffertreemodel.h"
 
@@ -46,23 +47,27 @@ public:
   };
   Q_DECLARE_FLAGS(Modes, Mode);
 
-  BufferViewFilter(QAbstractItemModel *model, const Modes &mode, const QStringList &nets);
+  BufferViewFilter(QAbstractItemModel *model, const Modes &mode, const QList<uint> &nets);
+  
+  virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+  virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
   
 public slots:
-  void invalidateMe();
-  void dropEvent(QDropEvent *);
   void removeBuffer(const QModelIndex &);
 
+protected:
+  bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
+  bool lessThan(const QModelIndex &, const QModelIndex &) const;
+  
 private:
+  Modes mode;
+  QSet<uint> networks;
+  QSet<uint> buffers;
+
   bool filterAcceptBuffer(const QModelIndex &) const;
   bool filterAcceptNetwork(const QModelIndex &) const;
-  bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
-  bool lessThan(const QModelIndex &, const QModelIndex &);
   void addBuffer(const uint &);
-  
-  Modes mode;
-  QStringList networks;
-  QList<uint> customBuffers;
+
 };
 Q_DECLARE_OPERATORS_FOR_FLAGS(BufferViewFilter::Modes)    
 
index f078a54..6f62adf 100644 (file)
@@ -149,16 +149,16 @@ void MainWin::setupViews() {
   BufferTreeModel *model = Client::bufferModel();
   connect(model, SIGNAL(bufferSelected(Buffer *)), this, SLOT(showBuffer(Buffer *)));
 
-  addBufferView(tr("All Buffers"), model, BufferViewFilter::AllNets, QStringList());
-  addBufferView(tr("All Channels"), model, BufferViewFilter::AllNets|BufferViewFilter::NoQueries|BufferViewFilter::NoServers, QStringList());
-  addBufferView(tr("All Queries"), model, BufferViewFilter::AllNets|BufferViewFilter::NoChannels|BufferViewFilter::NoServers, QStringList());
-  addBufferView(tr("All Networks"), model, BufferViewFilter::AllNets|BufferViewFilter::NoChannels|BufferViewFilter::NoQueries, QStringList());
-  addBufferView(tr("Full Custom"), model, BufferViewFilter::FullCustom, QStringList());
+  addBufferView(tr("All Buffers"), model, BufferViewFilter::AllNets, QList<uint>());
+  addBufferView(tr("All Channels"), model, BufferViewFilter::AllNets|BufferViewFilter::NoQueries|BufferViewFilter::NoServers, QList<uint>());
+  addBufferView(tr("All Queries"), model, BufferViewFilter::AllNets|BufferViewFilter::NoChannels|BufferViewFilter::NoServers, QList<uint>());
+  addBufferView(tr("All Networks"), model, BufferViewFilter::AllNets|BufferViewFilter::NoChannels|BufferViewFilter::NoQueries, QList<uint>());
+  addBufferView(tr("Full Custom"), model, BufferViewFilter::FullCustom, QList<uint>());
   
   ui.menuViews->addSeparator();
 }
 
-void MainWin::addBufferView(const QString &viewname, QAbstractItemModel *model, const BufferViewFilter::Modes &mode, const QStringList &nets) {
+void MainWin::addBufferView(const QString &viewname, QAbstractItemModel *model, const BufferViewFilter::Modes &mode, const QList<uint> &nets) {
   QDockWidget *dock = new QDockWidget(viewname, this);
   dock->setObjectName(QString("ViewDock-" + viewname)); // should be unique for mainwindow state!
   dock->setAllowedAreas(Qt::RightDockWidgetArea|Qt::LeftDockWidgetArea);
index 2e7bf64..d841630 100644 (file)
@@ -42,7 +42,7 @@ class MainWin : public QMainWindow {
     virtual ~MainWin();
 
     void init();
-    void addBufferView(const QString &, QAbstractItemModel *, const BufferViewFilter::Modes &, const QStringList &);
+    void addBufferView(const QString &, QAbstractItemModel *, const BufferViewFilter::Modes &, const QList<uint> &);
 
     AbstractUiMsg *layoutMsg(const Message &);