Implemented Custom Views (configurable via drag and drop)
authorMarcus Eggenberger <egs@quassel-irc.org>
Fri, 22 Jun 2007 15:06:11 +0000 (15:06 +0000)
committerMarcus Eggenberger <egs@quassel-irc.org>
Fri, 22 Jun 2007 15:06:11 +0000 (15:06 +0000)
src/client/buffertreemodel.cpp
src/client/buffertreemodel.h
src/qtgui/bufferview.cpp
src/qtgui/bufferview.h
src/qtgui/bufferviewfilter.cpp
src/qtgui/bufferviewfilter.h
src/qtgui/mainwin.cpp

index 2d51d85..43f624e 100644 (file)
@@ -69,10 +69,14 @@ QVariant BufferTreeItem::data(int column, int role) const {
       return text(column);
     case Qt::ForegroundRole:
       return foreground(column);
+    case BufferTreeModel::BufferNameRole:
+      return buf->bufferName();
     case BufferTreeModel::BufferTypeRole:
       return buf->bufferType();
     case BufferTreeModel::BufferActiveRole:
       return buf->isActive();
+    case BufferTreeModel::BufferIdRole:
+      return buf->bufferId().uid();
     default:
       return QVariant();
   }
@@ -94,7 +98,8 @@ QList<QVariant >BufferTreeModel::defaultHeader() {
 
 Qt::ItemFlags BufferTreeModel::flags(const QModelIndex &index) const {
   if(!index.isValid())
-    return 0;
+    return Qt::ItemIsDropEnabled;
+    //return 0;
 
   // I think this is pretty ugly..
   if(isBufferIndex(index)) {
@@ -102,7 +107,7 @@ Qt::ItemFlags BufferTreeModel::flags(const QModelIndex &index) const {
     if(buffer->bufferType() == Buffer::QueryBuffer)
       return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
     else
-      return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+      return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
   } else {
     return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled; 
   }
@@ -160,7 +165,8 @@ QModelIndex BufferTreeModel::getOrCreateBufferItemIndex(Buffer *buffer) {
 QStringList BufferTreeModel::mimeTypes() const {
   QStringList types;
   types << "application/Quassel/BufferItem/row"
-    << "application/Quassel/BufferItem/network";
+    << "application/Quassel/BufferItem/network"
+    << "application/Quassel/BufferItem/bufferId";
   return types;
 }
 
@@ -171,25 +177,41 @@ QMimeData *BufferTreeModel::mimeData(const QModelIndexList &indexes) const {
   
   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/bufferId", QByteArray::number(getBufferByIndex(index)->bufferId().uid()));
   return mimeData;
 }
 
 bool BufferTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) {
+  if(!(data->hasFormat("application/Quassel/BufferItem/row")
+       && data->hasFormat("application/Quassel/BufferItem/network")
+       && data->hasFormat("application/Quassel/BufferItem/bufferId")))
+    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"));
   
   if(!networkItem.contains(network))
     return false;
 
-  if(!isBufferIndex(parent)) // dropping at a network -> no merging needed
-    return false;
-
+  
   Buffer *sourceBuffer = static_cast<BufferTreeItem *>(networkItem[network]->child(sourcerow))->buffer();
+
+  if(parent == QModelIndex()) { // droping into empty space
+    emit addBuffer(sourceBuffer->bufferId().uid(), network);
+    return true;
+  }
+    
+  if(!isBufferIndex(parent)) { // dropping at a network
+    emit addBuffer(sourceBuffer->bufferId().uid(), network);
+    return true;
+  }
+
+
   Buffer *targetBuffer = getBufferByIndex(parent);
   
   if(sourceBuffer == targetBuffer) // we won't merge with ourself :)
     return false;
-  
+    
   /*
   if(QMessageBox::warning(static_cast<QWidget *>(QObject::parent()),
                           tr("Merge Buffers?"),
index 9d71dee..f849018 100644 (file)
@@ -58,7 +58,9 @@ class BufferTreeModel : public TreeModel {
 public:
   enum  myRoles {
     BufferTypeRole = Qt::UserRole,
-    BufferActiveRole
+    BufferActiveRole,
+    BufferNameRole,
+    BufferIdRole
   };
   
   //BufferTreeModel(const QList<QVariant> &, QObject *parent = 0);
@@ -81,6 +83,7 @@ signals:
   void invalidateFilter();
   void fakeUserInput(BufferId, QString);
   void updateSelection(const QModelIndex &, QItemSelectionModel::SelectionFlags);
+  void addBuffer(const uint &, const QString &);
     
 private:
   bool isBufferIndex(const QModelIndex &) const;
index f805418..33eab93 100644 (file)
@@ -30,7 +30,7 @@ BufferView::BufferView(QWidget *parent) : QTreeView(parent) {
 
 void BufferView::init() {
   setIndentation(10);
-  header()->hide();
+  //header()->hide();
   header()->hideSection(1);
   expandAll();
   
@@ -38,15 +38,25 @@ void BufferView::init() {
   setAcceptDrops(true);
   setDropIndicatorShown(true);
   
-  connect(selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), model(), SLOT(changeCurrent(const QModelIndex &, const QModelIndex &)));
-  connect(this, SIGNAL(doubleClicked(const QModelIndex &)), model(), SLOT(doubleClickReceived(const QModelIndex &)));
-  connect(model(), SIGNAL(updateSelection(const QModelIndex &, QItemSelectionModel::SelectionFlags)), selectionModel(), SLOT(select(const QModelIndex &, QItemSelectionModel::SelectionFlags)));
+  setSortingEnabled(true);
+  sortByColumn(0, Qt::AscendingOrder);
+  
+  connect(selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
+          model(), SLOT(changeCurrent(const QModelIndex &, const QModelIndex &)));
+  
+  connect(this, SIGNAL(doubleClicked(const QModelIndex &)),
+          model(), SLOT(doubleClickReceived(const QModelIndex &)));
+  
+  connect(model(), SIGNAL(updateSelection(const QModelIndex &, QItemSelectionModel::SelectionFlags)),
+          selectionModel(), SLOT(select(const QModelIndex &, QItemSelectionModel::SelectionFlags)));
 
 }
 
 void BufferView::setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QStringList nets) {
   BufferViewFilter *filter = new BufferViewFilter(model, mode, nets);
   setModel(filter);
+  connect(this, SIGNAL(dragEnter()), filter, SLOT(enterDrag()));
+  connect(this, SIGNAL(dragLeave()), filter, SLOT(leaveDrag()));
 }
 
 void BufferView::setModel(QAbstractItemModel *model) {
@@ -54,11 +64,19 @@ void BufferView::setModel(QAbstractItemModel *model) {
   init();
 }
 
+// dragEnterEvent and dragLeaveEvent are needed to keep track of the active
+// view when customizing them via drag and drop
 void BufferView::dragEnterEvent(QDragEnterEvent *event) {
-  // not yet needed... this will be usefull to keep track of the active view when customizing them with drag and drop
+  emit dragEnter();
   QTreeView::dragEnterEvent(event);
 }
 
+void BufferView::dragLeaveEvent(QDragLeaveEvent *event) {
+  emit dragLeave();
+  QTreeView::dragLeaveEvent(event);
+}
+
+// ensure that newly inserted network nodes are expanded per default
 void BufferView::rowsInserted(const QModelIndex & parent, int start, int end) {
   if(parent.parent() == QModelIndex()) setExpanded(parent, true);
   QTreeView::rowsInserted(parent, start, end);
index 561cae7..1cb0986 100644 (file)
 class BufferView : public QTreeView {
   Q_OBJECT
   
-  public:
-    BufferView(QWidget *parent = 0);
-    void init();
-    void setModel(QAbstractItemModel *model);
-    void setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QStringList nets);
+public:
+  BufferView(QWidget *parent = 0);
+  void init();
+  void setModel(QAbstractItemModel *model);
+  void setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QStringList nets);
+  
+  void dragEnterEvent(QDragEnterEvent *);
+  void dragLeaveEvent(QDragLeaveEvent *);
+  
+signals:
+  void dragEnter();
+  void dragLeave();
   
-    void dragEnterEvent(QDragEnterEvent *);
-
   protected:
     void rowsInserted (const QModelIndex & parent, int start, int end);
 };
index caa1fb3..57155ea 100644 (file)
@@ -25,6 +25,9 @@
 *****************************************/
 BufferViewFilter::BufferViewFilter(QAbstractItemModel *model, Modes filtermode, QStringList nets, QObject *parent) : QSortFilterProxyModel(parent) {
   setSourceModel(model);
+  setSortRole(BufferTreeModel::BufferNameRole);
+  setSortCaseSensitivity(Qt::CaseInsensitive);
+    
   mode = filtermode;
   networks = nets;
   
@@ -51,22 +54,70 @@ void BufferViewFilter::doubleClickReceived(const QModelIndex &clicked) {
   emit doubleClicked(mapToSource(clicked));
 }
 
-bool BufferViewFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const {
-  QModelIndex child = source_parent.child(source_row, 0);
-  if(!child.isValid())
-    return true; // can't imagine this case but true sounds good :)
+void BufferViewFilter::enterDrag() {
+  connect(sourceModel(), SIGNAL(addBuffer(const uint &, const QString &)),
+          this, SLOT(addBuffer(const uint &, const QString &)));
+}
+
+void BufferViewFilter::leaveDrag() {
+  disconnect(sourceModel(), SIGNAL(addBuffer(const uint &, const QString &)),
+             this, SLOT(addBuffer(const uint &, const QString &)));
+}
 
-  Buffer::Type bufferType = (Buffer::Type) child.data(BufferTreeModel::BufferTypeRole).toInt();
+void BufferViewFilter::addBuffer(const uint &bufferuid, const QString &network) {
+  if(!networks.contains(network)) {
+    networks << network;
+  }
+  
+  if(!customBuffers.contains(bufferuid)) {
+    customBuffers << bufferuid;
+    invalidateFilter();
+  }
+  
+}
+
+bool BufferViewFilter::filterAcceptBuffer(const QModelIndex &source_bufferIndex) const {
+  Buffer::Type bufferType = (Buffer::Type) source_bufferIndex.data(BufferTreeModel::BufferTypeRole).toInt();
   if((mode & NoChannels) && bufferType == Buffer::ChannelBuffer) return false;
   if((mode & NoQueries) && bufferType == Buffer::QueryBuffer) return false;
   if((mode & NoServers) && bufferType == Buffer::ServerBuffer) return false;
 
-  bool isActive = child.data(BufferTreeModel::BufferActiveRole).toBool();
+  bool isActive = source_bufferIndex.data(BufferTreeModel::BufferActiveRole).toBool();
   if((mode & NoActive) && isActive) return false;
   if((mode & NoInactive) && !isActive) return false;
 
-  QString net = child.data(Qt::DisplayRole).toString();
-  if((mode & SomeNets) && !networks.contains(net)) return false;
+  if((mode & FullCustom)) {
+    uint bufferuid = source_bufferIndex.data(BufferTreeModel::BufferIdRole).toUInt();
+    if(!customBuffers.contains(bufferuid))
+      return false;
+  }
     
   return true;
 }
+
+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
+    return true;
+}
+
+bool BufferViewFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const {
+  QModelIndex child = sourceModel()->index(source_row, 0, source_parent);
+  
+  if(!child.isValid()) {
+    qDebug() << "filterAcceptsRow has been called with an invalid Child";
+    return false;
+  }
+
+  if(source_parent == QModelIndex())
+    return filterAcceptNetwork(child);
+  else
+    return filterAcceptBuffer(child);
+}
+
+bool BufferViewFilter::lessThan(const QModelIndex &left, const QModelIndex &right) {
+  return QSortFilterProxyModel::lessThan(left, right);
+}
+
index 8bce143..cd93a22 100644 (file)
@@ -40,7 +40,8 @@ public:
     AllNets = 0x08,
     NoChannels = 0x10,
     NoQueries = 0x20,
-    NoServers = 0x40
+    NoServers = 0x40,
+    FullCustom = 0x80
   };
   Q_DECLARE_FLAGS(Modes, Mode)
 
@@ -51,6 +52,9 @@ public slots:
   void changeCurrent(const QModelIndex &, const QModelIndex &);
   void doubleClickReceived(const QModelIndex &);
   void select(const QModelIndex &, QItemSelectionModel::SelectionFlags);
+  void enterDrag();
+  void leaveDrag();
+  void addBuffer(const uint &, const QString &);
   
 signals:
   void currentChanged(const QModelIndex &, const QModelIndex &);
@@ -58,10 +62,14 @@ signals:
   void updateSelection(const QModelIndex &, QItemSelectionModel::SelectionFlags);
   
 private:
+  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 &);
 
   Modes mode;
   QStringList networks;
+  QList<uint> customBuffers;
 };
 Q_DECLARE_OPERATORS_FOR_FLAGS(BufferViewFilter::Modes)    
 
index 0ef57c1..f4f0c7e 100644 (file)
@@ -141,6 +141,8 @@ void MainWin::setupViews() {
   BufferViewDock *allnets = new BufferViewDock(model, tr("All Networks"), BufferViewFilter::AllNets|BufferViewFilter::NoChannels|BufferViewFilter::NoQueries);
   registerBufferViewDock(allnets);
 
+  BufferViewDock *fullCustom = new BufferViewDock(model, tr("Full Custom"), BufferViewFilter::FullCustom|BufferViewFilter::SomeNets);
+  registerBufferViewDock(fullCustom);
 
   ui.menuViews->addSeparator();
 }