Merging r820:825 from trunk to branches/0.3
[quassel.git] / src / uisupport / bufferview.cpp
index 49d2ae7..8e90fc6 100644 (file)
@@ -39,6 +39,7 @@
 #include <QLineEdit>
 #include <QMenu>
 #include <QMessageBox>
+#include <QSet>
 
 /*****************************************
 * The TreeView showing the Buffers
@@ -50,6 +51,8 @@ BufferView::BufferView(QWidget *parent) : QTreeView(parent) {
 
   connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
           this, SLOT(showContextMenu(const QPoint &)));
+
+  setSelectionMode(QAbstractItemView::ExtendedSelection);
 }
 
 void BufferView::init() {
@@ -81,7 +84,7 @@ void BufferView::init() {
 void BufferView::setModel(QAbstractItemModel *model) {
   delete selectionModel();
   if(QTreeView::model()) {
-    disconnect(QTreeView::model(), SIGNAL(layoutChanged()), this, SLOT(updateSelection()));
+    disconnect(QTreeView::model(), SIGNAL(layoutChanged()), this, SLOT(layoutChanged()));
   }
   
   QTreeView::setModel(model);
@@ -96,7 +99,7 @@ void BufferView::setModel(QAbstractItemModel *model) {
   if(!model)
     return;
 
-  connect(model, SIGNAL(layoutChanged()), this, SLOT(updateSelection()));
+  connect(model, SIGNAL(layoutChanged()), this, SLOT(layoutChanged()));
   
   QString sectionName;
   QAction *showSection;
@@ -129,11 +132,25 @@ void BufferView::setFilteredModel(QAbstractItemModel *model_, BufferViewConfig *
   } else {
     BufferViewFilter *filter = new BufferViewFilter(model_, config);
     setModel(filter);
-    connect(this, SIGNAL(removeBuffer(const QModelIndex &)), filter, SLOT(removeBuffer(const QModelIndex &)));
+    connect(this, SIGNAL(removeBuffer(const QModelIndex &)),
+           filter, SLOT(removeBuffer(const QModelIndex &)));
   }
   setConfig(config);
 }
 
+void BufferView::setSelectionModel(QItemSelectionModel *selectionModel) {
+  if(QTreeView::selectionModel())
+    disconnect(selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
+              model(), SIGNAL(checkPreviousCurrentForRemoval(QModelIndex, QModelIndex)));
+    
+  QTreeView::setSelectionModel(selectionModel);
+  BufferViewFilter *filter = qobject_cast<BufferViewFilter *>(model());
+  if(filter) {
+    connect(selectionModel, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
+           filter, SLOT(checkPreviousCurrentForRemoval(QModelIndex, QModelIndex)));
+  }
+}
+
 void BufferView::setConfig(BufferViewConfig *config) {
   if(_config == config)
     return;
@@ -179,17 +196,25 @@ void BufferView::joinChannel(const QModelIndex &index) {
 void BufferView::keyPressEvent(QKeyEvent *event) {
   if(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete) {
     event->accept();
-    QModelIndex index = selectionModel()->selectedIndexes().first();
-    if(index.isValid()) {
+    removeSelectedBuffers();
+  }
+  QTreeView::keyPressEvent(event);
+}
+
+void BufferView::removeSelectedBuffers() {
+  QSet<int> removedRows;
+  foreach(QModelIndex index, selectionModel()->selectedIndexes()) {
+    if(index.data(NetworkModel::ItemTypeRole) == NetworkModel::BufferItemType && !removedRows.contains(index.row())) {
+      removedRows << index.row();
       emit removeBuffer(index);
     }
   }
-  QTreeView::keyPressEvent(event);
 }
 
-// ensure that newly inserted network nodes are expanded per default
 void BufferView::rowsInserted(const QModelIndex & parent, int start, int end) {
   QTreeView::rowsInserted(parent, start, end);
+
+  // ensure that newly inserted network nodes are expanded per default
   if(parent.data(NetworkModel::ItemTypeRole) != NetworkModel::NetworkItemType)
     return;
   
@@ -200,9 +225,24 @@ void BufferView::rowsInserted(const QModelIndex & parent, int start, int end) {
   }
 }
 
-void BufferView::updateSelection() {
+void BufferView::layoutChanged() {
+  Q_ASSERT(model());
+
+  // expand all active networks
+  QModelIndex networkIdx;
+  for(int row = 0; row < model()->rowCount(); row++) {
+    networkIdx = model()->index(row, 0);
+    update(networkIdx);
+    if(model()->rowCount(networkIdx) > 0 && model()->data(networkIdx, NetworkModel::ItemActiveRole) == true) {
+      expand(networkIdx);
+    } else {
+      collapse(networkIdx);
+    }
+  }
+
+  // update selection to current one
   MappedSelectionModel *mappedSelectionModel = qobject_cast<MappedSelectionModel *>(selectionModel());
-  if(!config())
+  if(!config() || !mappedSelectionModel)
     return;
 
   mappedSelectionModel->mappedSetCurrentIndex(Client::bufferModel()->standardSelectionModel()->currentIndex(), QItemSelectionModel::Current);
@@ -223,12 +263,11 @@ void BufferView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bott
       continue;
 
     bool isActive = networkIdx.data(NetworkModel::ItemActiveRole).toBool();
-    if(Global::SPUTDEV) {
-      if(isExpanded(networkIdx) != isActive) setExpanded(networkIdx, true);
-    } else {
-      if(isExpanded(networkIdx) != isActive)
-        setExpanded(networkIdx, isActive);
-    }
+#ifdef SPUTDEV
+    if(isExpanded(networkIdx) != isActive) setExpanded(networkIdx, true);
+#else
+    if(isExpanded(networkIdx) != isActive) setExpanded(networkIdx, isActive);
+#endif
   }
 }
 
@@ -242,15 +281,17 @@ void BufferView::showContextMenu(const QPoint &pos) {
   QModelIndex index = indexAt(pos);
   if(!index.isValid()) return;
   QMenu contextMenu(this);
-  QAction *connectNetAction = new QAction(tr("Connect"), this);
-  QAction *disconnectNetAction = new QAction(tr("Disconnect"), this);
-  QAction *joinChannelAction = new QAction(tr("Join Channel"), this);
+  QAction *connectNetAction = contextMenu.addAction(tr("Connect"));
+  QAction *disconnectNetAction = contextMenu.addAction(tr("Disconnect"));
+  QAction *joinChannelAction = contextMenu.addAction(tr("Join Channel"));
 
-  QAction *joinBufferAction = new QAction(tr("Join"), this);
-  QAction *partBufferAction = new QAction(tr("Part"), this);
-  QAction *removeBufferAction = new QAction(tr("Delete buffer"), this);
+  QAction *joinBufferAction = contextMenu.addAction(tr("Join"));
+  QAction *partBufferAction = contextMenu.addAction(tr("Part"));
+  QAction *hideBufferAction = contextMenu.addAction(tr("Remove buffers"));
+  hideBufferAction->setToolTip(tr("Removes the selected buffers from a custom view but leaves the buffer itself untouched"));
+  QAction *removeBufferAction = contextMenu.addAction(tr("Delete buffer"));
 
-  QMenu *hideEventsMenu = new QMenu(tr("Hide Events"), this);
+  QMenu *hideEventsMenu = contextMenu.addMenu(tr("Hide Events"));
   QAction *hideJoinAction = hideEventsMenu->addAction(tr("Join Events"));
   QAction *hidePartAction = hideEventsMenu->addAction(tr("Part Events"));
   QAction *hideKillAction = hideEventsMenu->addAction(tr("Kill Events"));
@@ -288,6 +329,8 @@ void BufferView::showContextMenu(const QPoint &pos) {
     if(bufferInfo.type() != BufferInfo::ChannelBuffer && bufferInfo.type() != BufferInfo::QueryBuffer) return;
     contextMenu.addAction(joinBufferAction);
     contextMenu.addAction(partBufferAction);
+    if(config())
+      contextMenu.addAction(hideBufferAction);
     contextMenu.addAction(removeBufferAction);
     contextMenu.addMenu(hideEventsMenu);
     contextMenu.addAction(ignoreListAction);
@@ -332,14 +375,13 @@ void BufferView::showContextMenu(const QPoint &pos) {
       }
     }
 #endif
-  } else
-  if(result == joinBufferAction) {
+  } else if(result == joinBufferAction) {
     Client::instance()->userInput(bufferInfo, QString("/JOIN %1").arg(channelname));
-  } else
-  if(result == partBufferAction) {
+  } else if(result == partBufferAction) {
     Client::instance()->userInput(bufferInfo, QString("/PART %1").arg(channelname));
-  } else
-  if(result == removeBufferAction) {
+  } else if(result == hideBufferAction) {
+    removeSelectedBuffers();
+  } else if(result == removeBufferAction) {
     int res = QMessageBox::question(this, tr("Remove buffer permanently?"),
                                     tr("Do you want to delete the buffer \"%1\" permanently? This will delete all related data, including all backlog "
                                        "data, from the core's database!").arg(bufferInfo.bufferName()),