We finally got a nice solution to synchronize multiple views or whatevers[tm] even...
authorMarcus Eggenberger <egs@quassel-irc.org>
Tue, 23 Oct 2007 19:29:01 +0000 (19:29 +0000)
committerMarcus Eggenberger <egs@quassel-irc.org>
Tue, 23 Oct 2007 19:29:01 +0000 (19:29 +0000)
Client::bufferModel()->selectionModelSynchronizer()->addSelectionModel(mappedSelectionModel)
(maybe I'll make this a bit easier... ;))

12 files changed:
src/client/buffertreemodel.cpp
src/client/buffertreemodel.h
src/client/client.pri
src/client/mappedselectionmodel.cpp [new file with mode: 0644]
src/client/mappedselectionmodel.h [new file with mode: 0644]
src/client/selectionmodelsynchronizer.cpp [new file with mode: 0644]
src/client/selectionmodelsynchronizer.h [new file with mode: 0644]
src/qtui/bufferview.cpp
src/qtui/bufferview.h
src/qtui/bufferviewfilter.cpp
src/qtui/bufferviewfilter.h
src/qtui/mainwin.cpp

index 633731b..7117b07 100644 (file)
@@ -21,6 +21,7 @@
 #include <QColor>  // FIXME Dependency on QtGui!
 
 #include "buffertreemodel.h"
+#include "selectionmodelsynchronizer.h"
 
 #include "bufferinfo.h"
 #include "client.h"
@@ -117,9 +118,11 @@ Qt::ItemFlags NetworkTreeItem::flags() const {
  * BufferTreeModel
  *****************************************/
 BufferTreeModel::BufferTreeModel(QObject *parent)
-  : TreeModel(BufferTreeModel::defaultHeader(), parent)
+  : TreeModel(BufferTreeModel::defaultHeader(), parent),
+    _selectionModelSynchronizer(new SelectionModelSynchronizer(this))
 {
-  Client::signalProxy()->attachSignal(this, SIGNAL(fakeUserInput(BufferInfo, QString)), SIGNAL(sendInput(BufferInfo, QString)));
+  connect(_selectionModelSynchronizer, SIGNAL(setCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags)),
+         this, SLOT(setCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags)));
 }
 
 QList<QVariant >BufferTreeModel::defaultHeader() {
@@ -229,12 +232,13 @@ void BufferTreeModel::bufferUpdated(Buffer *buffer) {
 }
 
 // This Slot indicates that the user has selected a different buffer in the gui
-void BufferTreeModel::changeCurrent(const QModelIndex &current, const QModelIndex &/*previous*/) {
-  if(isBufferIndex(current)) {
-    currentBuffer = getBufferByIndex(current);
+void BufferTreeModel::setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command) {
+  Q_UNUSED(command)
+  if(isBufferIndex(index)) {
+    currentBuffer = getBufferByIndex(index);
     bufferActivity(Buffer::NoActivity, currentBuffer);
     emit bufferSelected(currentBuffer);
-    emit selectionChanged(current);
+    emit selectionChanged(index);
   }
 }
 
@@ -249,6 +253,6 @@ void BufferTreeModel::bufferActivity(Buffer::ActivityLevel level, Buffer *buffer
 
 void BufferTreeModel::selectBuffer(Buffer *buffer) {
   QModelIndex index = getOrCreateBufferItemIndex(buffer);
-  //emit selectionChanged(index);
-  changeCurrent(index, QModelIndex());
+  // SUPER UGLY!
+  setCurrentIndex(index, 0);
 }
index 602cf57..f300d98 100644 (file)
 #include <QtCore>
 
 #include "treemodel.h"
-class BufferInfo;
 #include "buffer.h"
 
+#include <QItemSelectionModel>
+
+class BufferInfo;
+class SelectionModelSynchronizer;
+
+
 /*****************************************
  *  Fancy Buffer Items
  *****************************************/
@@ -84,17 +89,18 @@ public:
   
   BufferTreeModel(QObject *parent = 0);
   static QList<QVariant> defaultHeader();
-  
+
+  inline SelectionModelSynchronizer *selectionModelSynchronizer() { return _selectionModelSynchronizer; }
+
 public slots:
-  void bufferUpdated(Buffer *);    
-  void changeCurrent(const QModelIndex &, const QModelIndex &);
+  void bufferUpdated(Buffer *);
+  void setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command);
   void selectBuffer(Buffer *buffer);
   void bufferActivity(Buffer::ActivityLevel, Buffer *buffer);
   
 signals:
   void bufferSelected(Buffer *);
   void invalidateFilter();
-  void fakeUserInput(BufferInfo, QString);
   void selectionChanged(const QModelIndex &);
     
 private:
@@ -106,7 +112,8 @@ private:
   QStringList mimeTypes() const;
   QMimeData *mimeData(const QModelIndexList &) const;
   bool dropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex &);
-  
+
+  SelectionModelSynchronizer *_selectionModelSynchronizer;
   Buffer *currentBuffer;
 };
 
index 3e694ea..56442f8 100644 (file)
@@ -1,4 +1,4 @@
 DEPMOD = common contrib/qxt
 QT_MOD = core network gui   # gui is needed just for QColor... FIXME!
-SRCS += buffer.cpp buffertreemodel.cpp client.cpp clientsettings.cpp treemodel.cpp
-HDRS += buffer.h buffertreemodel.h client.h clientsettings.h quasselui.h treemodel.h
+SRCS += buffer.cpp buffertreemodel.cpp client.cpp clientsettings.cpp treemodel.cpp mappedselectionmodel.cpp selectionmodelsynchronizer.cpp
+HDRS += buffer.h buffertreemodel.h client.h clientsettings.h quasselui.h treemodel.h mappedselectionmodel.h selectionmodelsynchronizer.h
diff --git a/src/client/mappedselectionmodel.cpp b/src/client/mappedselectionmodel.cpp
new file mode 100644 (file)
index 0000000..e304aa6
--- /dev/null
@@ -0,0 +1,129 @@
+/***************************************************************************
+ *   Copyright (C) 2005-07 by The Quassel Team                             *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "mappedselectionmodel.h"
+
+#include <QItemSelectionModel>
+#include <QAbstractItemModel>
+#include <QAbstractProxyModel>
+#include <QDebug>
+
+MappedSelectionModel::MappedSelectionModel(QAbstractItemModel *model)
+  : QItemSelectionModel(model)
+{
+  _isProxyModel = (bool)proxyModel();
+  connect(this, SIGNAL(currentChanged(QModelIndex, QModelIndex)),
+         this, SLOT(_currentChanged(QModelIndex, QModelIndex)));
+  connect(this, SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+         this, SLOT(_selectionChanged(QItemSelection, QItemSelection)));
+}
+
+MappedSelectionModel::~MappedSelectionModel() {
+}
+
+const QAbstractItemModel *MappedSelectionModel::baseModel() const {
+  if(isProxyModel())
+    return proxyModel()->sourceModel();
+  else
+    return model();
+}
+
+const QAbstractProxyModel *MappedSelectionModel::proxyModel() const {
+  return qobject_cast<const QAbstractProxyModel *>(model());
+}
+
+QModelIndex MappedSelectionModel::mapFromSource(const QModelIndex &sourceIndex) {
+  if(isProxyModel())
+    return proxyModel()->mapFromSource(sourceIndex);
+  else
+    return sourceIndex;
+}
+
+QItemSelection MappedSelectionModel::mapFromSource(const QItemSelection &sourceSelection) {
+  if(isProxyModel()) {
+    QItemSelection mappedSelection;
+    foreach(QItemSelectionRange range, sourceSelection) {
+      QModelIndex topleft = mapFromSource(range.topLeft());
+      QModelIndex bottomright = mapFromSource(range.bottomRight());
+      if(topleft.isValid() && bottomright.isValid())
+       mappedSelection << QItemSelectionRange(topleft, bottomright);
+      else 
+       Q_ASSERT(!topleft.isValid() && !bottomright.isValid());
+    }
+    return mappedSelection;
+  } else {
+    return sourceSelection;
+  }
+}
+                                   
+QModelIndex MappedSelectionModel::mapToSource(const QModelIndex &proxyIndex) {
+  if(isProxyModel())
+    return proxyModel()->mapToSource(proxyIndex);
+  else
+    return proxyIndex;
+}
+
+QItemSelection MappedSelectionModel::mapToSource(const QItemSelection &proxySelection) {
+  if(isProxyModel()) {
+    QItemSelection mappedSelection;
+    foreach(QItemSelectionRange range, proxySelection) {
+      mappedSelection << QItemSelectionRange(mapToSource(range.topLeft()), mapToSource(range.bottomRight()));
+    }
+    return mappedSelection;
+  } else {
+    return proxySelection;
+  }
+}
+                                                                       
+void MappedSelectionModel::mappedSelect(const QModelIndex &index, QItemSelectionModel::SelectionFlags command) {
+  QModelIndex mappedIndex = mapFromSource(index);
+  if(!isSelected(mappedIndex))
+    select(mappedIndex, command);
+}
+
+void MappedSelectionModel::mappedSelect(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) {
+  QItemSelection mappedSelection = mapFromSource(selection);
+  if(mappedSelection != QItemSelectionModel::selection())
+    select(mappedSelection, command);  
+}
+
+void MappedSelectionModel::mappedSetCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command) {
+  QModelIndex mappedIndex = mapFromSource(index);
+  if(mappedIndex == currentIndex())
+    return;
+
+  if(mappedIndex.isValid())
+    setCurrentIndex(mappedIndex, command);
+  else if(hasSelection())
+    setCurrentIndex(currentIndex(), QItemSelectionModel::Clear);
+}
+
+
+void MappedSelectionModel::_currentChanged(const QModelIndex &current, const QModelIndex &previous) {
+  Q_UNUSED(previous)
+  emit mappedCurrentChanged(mapToSource(current));
+}
+
+void MappedSelectionModel::_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) {
+  Q_UNUSED(selected)
+  Q_UNUSED(deselected)
+  emit mappedSelectionChanged(mapToSource(QItemSelectionModel::selection()));
+}
+  
diff --git a/src/client/mappedselectionmodel.h b/src/client/mappedselectionmodel.h
new file mode 100644 (file)
index 0000000..226f81e
--- /dev/null
@@ -0,0 +1,67 @@
+/***************************************************************************
+ *   Copyright (C) 2005-07 by The Quassel Team                             *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef _MAPPEDSELECTIONMODEL_H_
+#define _MAPPEDSELECTIONMODEL_H_
+
+#include <QObject>
+#include <QModelIndex>
+#include <QItemSelection>
+#include <QItemSelectionModel>;
+
+class QAbstractProxyModel;
+
+class MappedSelectionModel : public QItemSelectionModel {
+  Q_OBJECT
+
+public:
+  MappedSelectionModel(QAbstractItemModel *model = 0);
+  virtual ~MappedSelectionModel();
+
+  inline bool isProxyModel() const { return _isProxyModel; }
+
+  const QAbstractItemModel *baseModel() const;
+  const QAbstractProxyModel *proxyModel() const;
+  
+  QModelIndex mapFromSource(const QModelIndex &sourceIndex);
+  QItemSelection mapFromSource(const QItemSelection &sourceSelection);
+                                   
+  QModelIndex mapToSource(const QModelIndex &proxyIndex);
+  QItemSelection mapToSource(const QItemSelection &proxySelection);
+                                                                       
+public slots:
+  void mappedSelect(const QModelIndex &index, QItemSelectionModel::SelectionFlags command);
+  void mappedSelect(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command);
+  void mappedSetCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command);
+
+private slots:
+  void _currentChanged(const QModelIndex &current, const QModelIndex &previous);
+  void _selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
+  
+signals:
+  void mappedCurrentChanged(const QModelIndex &current);
+  void mappedSelectionChanged(const QItemSelection &selected);
+
+private:
+  bool _isProxyModel;
+
+};
+
+#endif
diff --git a/src/client/selectionmodelsynchronizer.cpp b/src/client/selectionmodelsynchronizer.cpp
new file mode 100644 (file)
index 0000000..2975f79
--- /dev/null
@@ -0,0 +1,67 @@
+/***************************************************************************
+ *   Copyright (C) 2005-07 by The Quassel Team                             *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "selectionmodelsynchronizer.h"
+
+
+#include <QAbstractItemModel>
+#include "mappedselectionmodel.h"
+
+#include <QDebug>
+
+SelectionModelSynchronizer::SelectionModelSynchronizer(QAbstractItemModel *parent)
+  : QObject(parent),
+    _model(parent)
+{
+}
+
+SelectionModelSynchronizer::~SelectionModelSynchronizer() {
+}
+
+void SelectionModelSynchronizer::addSelectionModel(MappedSelectionModel *selectionmodel) {
+  if(selectionmodel->baseModel() != model()) {
+    qWarning() << "cannot Syncronize SelectionModel" << selectionmodel << "which has a different baseModel()";
+    return;
+  }
+
+  connect(selectionmodel, SIGNAL(mappedCurrentChanged(QModelIndex)),
+         this, SLOT(_mappedCurrentChanged(QModelIndex)));
+  connect(selectionmodel, SIGNAL(mappedSelectionChanged(QItemSelection)),
+         this, SLOT(_mappedSelectionChanged(QItemSelection)));
+  
+  connect(this, SIGNAL(setCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags)),
+         selectionmodel, SLOT(mappedSetCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags)));
+  connect(this, SIGNAL(select(QItemSelection, QItemSelectionModel::SelectionFlags)),
+         selectionmodel, SLOT(mappedSelect(QItemSelection, QItemSelectionModel::SelectionFlags)));
+  
+}
+
+void SelectionModelSynchronizer::removeSelectionModel(MappedSelectionModel *model) {
+  disconnect(model, 0, this, 0);
+  disconnect(this, 0, model, 0);
+}
+
+void SelectionModelSynchronizer::_mappedCurrentChanged(const QModelIndex &current) {
+  emit setCurrentIndex(current, QItemSelectionModel::ClearAndSelect);
+}
+
+void SelectionModelSynchronizer::_mappedSelectionChanged(const QItemSelection &selected) {
+  emit select(selected, QItemSelectionModel::ClearAndSelect);
+}
diff --git a/src/client/selectionmodelsynchronizer.h b/src/client/selectionmodelsynchronizer.h
new file mode 100644 (file)
index 0000000..cdf2415
--- /dev/null
@@ -0,0 +1,54 @@
+/***************************************************************************
+ *   Copyright (C) 2005-07 by The Quassel Team                             *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef _SELECTIONMODELSYNCHRONIZER_H_
+#define _SELECTIONMODELSYNCHRONIZER_H_
+
+#include <QObject>
+#include <QItemSelectionModel>
+
+class QAbstractItemModel;
+class MappedSelectionModel;
+
+class SelectionModelSynchronizer : public QObject {
+  Q_OBJECT
+
+public:
+  SelectionModelSynchronizer(QAbstractItemModel *parent = 0);
+  virtual ~SelectionModelSynchronizer();
+
+  void addSelectionModel(MappedSelectionModel *model);
+  void removeSelectionModel(MappedSelectionModel *model);
+
+  inline QAbstractItemModel *model() { return _model; }
+
+private slots:
+  void _mappedCurrentChanged(const QModelIndex &current);
+  void _mappedSelectionChanged(const QItemSelection &selected);
+
+signals:
+  void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command);
+  void setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command);
+  
+private:
+  QAbstractItemModel *_model;
+};
+
+#endif
index c60aa80..40995ad 100644 (file)
@@ -45,15 +45,6 @@ void BufferView::init() {
   setSortingEnabled(true);
   sortByColumn(0, Qt::AscendingOrder);
   
-  connect(selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
-          model(), SLOT(changeCurrent(const QModelIndex &, const QModelIndex &)));
-  
-  connect(model(), SIGNAL(selectionChanged(const QModelIndex &)),
-          this, SLOT(select(const QModelIndex &)));
-  
-  connect(this, SIGNAL(selectionChanged(const QModelIndex &, QItemSelectionModel::SelectionFlags)),
-          selectionModel(), SLOT(select(const QModelIndex &, QItemSelectionModel::SelectionFlags)));
-
   connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(joinChannel(QModelIndex)));
 }
 
@@ -67,10 +58,7 @@ void BufferView::setFilteredModel(QAbstractItemModel *model, BufferViewFilter::M
 void BufferView::setModel(QAbstractItemModel *model) {
   QTreeView::setModel(model);
   init();
-}
-
-void BufferView::select(const QModelIndex &current) {
-  emit selectionChanged(current, QItemSelectionModel::ClearAndSelect);
+  
 }
 
 void BufferView::dropEvent(QDropEvent *event) {
index 0c06caf..8240f8d 100644 (file)
@@ -38,13 +38,9 @@ public:
   void setModel(QAbstractItemModel *model);
   void setFilteredModel(QAbstractItemModel *model, BufferViewFilter::Modes mode, QStringList nets);
   
-public slots:
-  void select(const QModelIndex &);
-    
 signals:
   void eventDropped(QDropEvent *);
   void removeBuffer(const QModelIndex &);
-  void selectionChanged(const QModelIndex &, QItemSelectionModel::SelectionFlags);
   
 private slots:
   void dropEvent(QDropEvent *);
index 4fe8fed..6bcfb6a 100644 (file)
@@ -32,29 +32,12 @@ BufferViewFilter::BufferViewFilter(QAbstractItemModel *model, const Modes &filte
   networks = nets;
   
   connect(model, SIGNAL(invalidateFilter()), this, SLOT(invalidateMe()));
-  connect(model, SIGNAL(selectionChanged(const QModelIndex &)),
-          this, SLOT(select(const QModelIndex &)));
-  
-  connect(this, SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
-          model, SLOT(changeCurrent(const QModelIndex &, const QModelIndex &)));
 }
 
 void BufferViewFilter::invalidateMe() {
   invalidateFilter();
 }
 
-void BufferViewFilter::select(const QModelIndex &index) {
-  emit selectionChanged(mapFromSource(index));
-}
-
-void BufferViewFilter::changeCurrent(const QModelIndex &current, const QModelIndex &previous) {
-  emit currentChanged(mapToSource(current), mapToSource(previous));
-}
-
-void BufferViewFilter::doubleClickReceived(const QModelIndex &clicked) {
-  emit doubleClicked(mapToSource(clicked));
-}
-
 void BufferViewFilter::dropEvent(QDropEvent *event) {
   const QMimeData *data = event->mimeData();
   if(!(mode & FullCustom))
index 93478c7..edda7ac 100644 (file)
@@ -50,18 +50,9 @@ public:
   
 public slots:
   void invalidateMe();
-  void changeCurrent(const QModelIndex &, const QModelIndex &);
-  void doubleClickReceived(const QModelIndex &);
-  void select(const QModelIndex &);
   void dropEvent(QDropEvent *);
   void removeBuffer(const QModelIndex &);
 
-  
-signals:
-  void currentChanged(const QModelIndex &, const QModelIndex &);
-  void doubleClicked(const QModelIndex &);
-  void selectionChanged(const QModelIndex &);
-  
 private:
   bool filterAcceptBuffer(const QModelIndex &) const;
   bool filterAcceptNetwork(const QModelIndex &) const;
index f94ee4a..ee25309 100644 (file)
@@ -31,6 +31,9 @@
 
 #include "topicwidget.h"
 
+#include "selectionmodelsynchronizer.h"
+#include "mappedselectionmodel.h"
+
 MainWin::MainWin(QtUi *_gui, QWidget *parent) : QMainWindow(parent), gui(_gui) {
   ui.setupUi(this);
   setWindowTitle("Quassel IRC");
@@ -156,6 +159,13 @@ void MainWin::addBufferView(const QString &viewname, QAbstractItemModel *model,
   //create the view and initialize it's filter
   BufferView *view = new BufferView(dock);
   view->setFilteredModel(model, mode, nets);
+
+  MappedSelectionModel *mappedSelectionModel = new MappedSelectionModel(view->model());
+  Client::bufferModel()->selectionModelSynchronizer()->addSelectionModel(mappedSelectionModel);
+  Q_ASSERT(mappedSelectionModel);
+  delete view->selectionModel();
+  view->setSelectionModel(mappedSelectionModel);
+
   dock->setWidget(view);
   
   addDockWidget(Qt::LeftDockWidgetArea, dock);