Added ModelPropertyMapper which allows to keep track of /current/ changes in the...
authorMarcus Eggenberger <egs@quassel-irc.org>
Wed, 24 Oct 2007 22:10:25 +0000 (22:10 +0000)
committerMarcus Eggenberger <egs@quassel-irc.org>
Wed, 24 Oct 2007 22:10:25 +0000 (22:10 +0000)
src/client/buffertreemodel.cpp
src/client/buffertreemodel.h
src/client/client.pri
src/client/modelpropertymapper.cpp [new file with mode: 0644]
src/client/modelpropertymapper.h [new file with mode: 0644]
src/common/ircchannel.cpp
src/common/networkinfo.cpp
src/qtui/bufferview.cpp
src/qtui/bufferviewfilter.cpp
src/qtui/mainwin.cpp

index 7117b07..a881b5f 100644 (file)
@@ -21,7 +21,9 @@
 #include <QColor>  // FIXME Dependency on QtGui!
 
 #include "buffertreemodel.h"
 #include <QColor>  // FIXME Dependency on QtGui!
 
 #include "buffertreemodel.h"
-#include "selectionmodelsynchronizer.h"
+
+#include "mappedselectionmodel.h"
+#include <QAbstractItemView>
 
 #include "bufferinfo.h"
 #include "client.h"
 
 #include "bufferinfo.h"
 #include "client.h"
@@ -119,8 +121,15 @@ Qt::ItemFlags NetworkTreeItem::flags() const {
  *****************************************/
 BufferTreeModel::BufferTreeModel(QObject *parent)
   : TreeModel(BufferTreeModel::defaultHeader(), parent),
  *****************************************/
 BufferTreeModel::BufferTreeModel(QObject *parent)
   : TreeModel(BufferTreeModel::defaultHeader(), parent),
-    _selectionModelSynchronizer(new SelectionModelSynchronizer(this))
+    _selectionModelSynchronizer(new SelectionModelSynchronizer(this)),
+    _propertyMapper(new ModelPropertyMapper(this))
 {
 {
+  _propertyMapper->setModel(this);
+  delete _propertyMapper->selectionModel();
+  MappedSelectionModel *mappedSelectionModel = new MappedSelectionModel(this);
+  _propertyMapper->setSelectionModel(mappedSelectionModel);
+  synchronizeSelectionModel(mappedSelectionModel);
+  
   connect(_selectionModelSynchronizer, SIGNAL(setCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags)),
          this, SLOT(setCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags)));
 }
   connect(_selectionModelSynchronizer, SIGNAL(setCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags)),
          this, SLOT(setCurrentIndex(QModelIndex, QItemSelectionModel::SelectionFlags)));
 }
@@ -131,6 +140,22 @@ QList<QVariant >BufferTreeModel::defaultHeader() {
   return data;
 }
 
   return data;
 }
 
+void BufferTreeModel::synchronizeSelectionModel(MappedSelectionModel *selectionModel) {
+  selectionModelSynchronizer()->addSelectionModel(selectionModel);
+}
+
+void BufferTreeModel::synchronizeView(QAbstractItemView *view) {
+  MappedSelectionModel *mappedSelectionModel = new MappedSelectionModel(view->model());
+  selectionModelSynchronizer()->addSelectionModel(mappedSelectionModel);
+  Q_ASSERT(mappedSelectionModel);
+  delete view->selectionModel();
+  view->setSelectionModel(mappedSelectionModel);
+}
+
+void BufferTreeModel::mapProperty(int column, int role, QObject *target, const QByteArray &property) {
+  propertyMapper()->addMapping(column, role, target, property);
+}
+
 bool BufferTreeModel::isBufferIndex(const QModelIndex &index) const {
   // not so purdy...
   return parent(index) != QModelIndex();
 bool BufferTreeModel::isBufferIndex(const QModelIndex &index) const {
   // not so purdy...
   return parent(index) != QModelIndex();
index f300d98..70a9619 100644 (file)
 #include "treemodel.h"
 #include "buffer.h"
 
 #include "treemodel.h"
 #include "buffer.h"
 
+#include <QPointer>
+
 #include <QItemSelectionModel>
 
 class BufferInfo;
 #include <QItemSelectionModel>
 
 class BufferInfo;
-class SelectionModelSynchronizer;
 
 
+#include "selectionmodelsynchronizer.h"
+#include "modelpropertymapper.h"
+class MappedSelectionModel;
+class QAbstractItemView;
 
 /*****************************************
  *  Fancy Buffer Items
 
 /*****************************************
  *  Fancy Buffer Items
@@ -91,6 +96,11 @@ public:
   static QList<QVariant> defaultHeader();
 
   inline SelectionModelSynchronizer *selectionModelSynchronizer() { return _selectionModelSynchronizer; }
   static QList<QVariant> defaultHeader();
 
   inline SelectionModelSynchronizer *selectionModelSynchronizer() { return _selectionModelSynchronizer; }
+  inline ModelPropertyMapper *propertyMapper() { return _propertyMapper; }
+
+  void synchronizeSelectionModel(MappedSelectionModel *selectionModel);
+  void synchronizeView(QAbstractItemView *view);
+  void mapProperty(int column, int role, QObject *target, const QByteArray &property);
 
 public slots:
   void bufferUpdated(Buffer *);
 
 public slots:
   void bufferUpdated(Buffer *);
@@ -113,7 +123,8 @@ private:
   QMimeData *mimeData(const QModelIndexList &) const;
   bool dropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex &);
 
   QMimeData *mimeData(const QModelIndexList &) const;
   bool dropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex &);
 
-  SelectionModelSynchronizer *_selectionModelSynchronizer;
+  QPointer<SelectionModelSynchronizer> _selectionModelSynchronizer;
+  QPointer<ModelPropertyMapper> _propertyMapper;
   Buffer *currentBuffer;
 };
 
   Buffer *currentBuffer;
 };
 
index 56442f8..7a47f5e 100644 (file)
@@ -1,4 +1,4 @@
 DEPMOD = common contrib/qxt
 QT_MOD = core network gui   # gui is needed just for QColor... FIXME!
 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 mappedselectionmodel.cpp selectionmodelsynchronizer.cpp
-HDRS += buffer.h buffertreemodel.h client.h clientsettings.h quasselui.h treemodel.h mappedselectionmodel.h selectionmodelsynchronizer.h
+SRCS += buffer.cpp buffertreemodel.cpp client.cpp clientsettings.cpp treemodel.cpp mappedselectionmodel.cpp selectionmodelsynchronizer.cpp modelpropertymapper.cpp
+HDRS += buffer.h buffertreemodel.h client.h clientsettings.h quasselui.h treemodel.h mappedselectionmodel.h selectionmodelsynchronizer.h modelpropertymapper.h
diff --git a/src/client/modelpropertymapper.cpp b/src/client/modelpropertymapper.cpp
new file mode 100644 (file)
index 0000000..31f8d54
--- /dev/null
@@ -0,0 +1,100 @@
+/***************************************************************************
+ *   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 "modelpropertymapper.h"
+
+#include <QItemSelectionModel>
+#include <QDebug>
+
+ModelPropertyMapper::ModelPropertyMapper(QObject *parent)
+  : QObject(parent),
+    _model(0),
+    _selectionModel(0)
+{
+}
+
+ModelPropertyMapper::~ModelPropertyMapper() {
+}
+
+void ModelPropertyMapper::setModel(QAbstractItemModel *model) {
+  if(_model)
+    setSelectionModel(new QItemSelectionModel(model));
+  _model = model;
+}
+
+QAbstractItemModel *ModelPropertyMapper::model() const {
+  return _model;
+}
+
+void ModelPropertyMapper::setSelectionModel(QItemSelectionModel *selectionModel) {
+  if(selectionModel->model() != model()) {
+    qWarning() << "cannot set itemSelectionModel" << selectionModel << "which uses different basemodel than" << model();
+    return;
+  }
+  if(_selectionModel)
+    disconnect(_selectionModel, 0, this, 0);
+  _selectionModel = selectionModel;
+  connect(_selectionModel, SIGNAL(currentRowChanged(QModelIndex, QModelIndex)),
+         this, SLOT(setCurrentRow(QModelIndex, QModelIndex)));
+  
+  setCurrentRow(selectionModel->currentIndex(), QModelIndex());
+}
+
+QItemSelectionModel *ModelPropertyMapper::selectionModel() const {
+  return _selectionModel;
+}
+
+void ModelPropertyMapper::addMapping(int column, int role, QObject *target, const QByteArray &property) {
+  Mapping mapping(column, role, target, property);
+  if(!_mappings.contains(mapping))
+    _mappings.append(mapping);
+}
+
+void ModelPropertyMapper::removeMapping(int column, int role, QObject *target, const QByteArray &property) {
+  if(column == 0 && role == 0 && target == 0 && !property.isNull()) {
+    _mappings.clear();
+    return;
+  }
+  
+  if(column == 0 && role == 0 && !property.isNull()) {
+    QList<Mapping>::iterator iter;
+    for(iter = _mappings.begin(); iter != _mappings.end(); iter++) {
+      if((*iter).target == target)
+       _mappings.erase(iter);
+    }
+    return;
+  }
+  _mappings.removeAll(Mapping(column, role, target, property));
+}
+
+void ModelPropertyMapper::setCurrentRow(const QModelIndex &current, const QModelIndex &previous) {
+  Q_UNUSED(previous)
+  foreach(Mapping mapping, _mappings) {
+    QModelIndex index = current.sibling(current.row(), mapping.column);
+    // qDebug() << mapping.target << mapping.property << index.data(mapping.role);
+    mapping.target->setProperty(mapping.property, index.data(mapping.role));
+  }
+}
+
+
+void ModelPropertyMapper::targetDestroyed() {
+  QObject *obj = static_cast<QObject *>(sender());
+  removeMapping(0, 0, obj, QByteArray());
+}
diff --git a/src/client/modelpropertymapper.h b/src/client/modelpropertymapper.h
new file mode 100644 (file)
index 0000000..988efa8
--- /dev/null
@@ -0,0 +1,73 @@
+/***************************************************************************
+ *   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 _MODELPROPERTYMAPPER_H_
+#define _MODELPROPERTYMAPPER_H_
+
+#include <QPointer>
+#include <QModelIndex>
+#include <QObject>
+
+class QAbstractItemModel;
+class QItemSelectionModel;
+
+
+class ModelPropertyMapper : public QObject {
+  Q_OBJECT
+
+public:
+  ModelPropertyMapper(QObject *parent = 0);
+  virtual ~ModelPropertyMapper();
+
+  void setModel(QAbstractItemModel *model);
+  QAbstractItemModel *model() const;
+
+  void setSelectionModel(QItemSelectionModel *selectionModel);
+  QItemSelectionModel *selectionModel() const;
+
+  void addMapping(int column, int role, QObject *target, const QByteArray &property);
+  void removeMapping(int column, int role, QObject *target, const QByteArray &property);
+                                                                                     
+public slots:
+  void setCurrentRow(const QModelIndex &current, const QModelIndex &previous);
+
+private slots:
+  void targetDestroyed();
+  
+private:
+  struct Mapping {
+    int column;
+    int role;
+    QPointer<QObject> target;
+    QByteArray property;
+
+    Mapping(int _column, int _role, QObject *_target, const QByteArray &_property)
+      : column(_column), role(_role), target(_target), property(_property) {};
+    inline bool operator==(const Mapping &other) {
+      return (column == other.column && role == other.role && target == other.target && property == other.property); }
+  };
+    
+  QPointer<QAbstractItemModel> _model;
+  QPointer<QItemSelectionModel> _selectionModel;
+  QList<Mapping> _mappings;
+  
+};
+
+#endif
index 2233861..b9caebd 100644 (file)
@@ -192,9 +192,7 @@ void IrcChannel::initSetUserModes(const QVariantMap &usermodes) {
 }
 
 void IrcChannel::ircUserDestroyed() {
 }
 
 void IrcChannel::ircUserDestroyed() {
-  IrcUser *ircUser = qobject_cast<IrcUser *>(sender());
-  // in case this assert triggers we probably need a static_cast
-  // dynamic_casts seem to screw things up when using the destroyed signal
+  IrcUser *ircUser = static_cast<IrcUser *>(sender());
   Q_ASSERT(ircUser);
   part(ircUser);
 }
   Q_ASSERT(ircUser);
   part(ircUser);
 }
index f79ef5c..24ed8d7 100644 (file)
@@ -310,17 +310,13 @@ void NetworkInfo::ircUserNickChanged(QString newnick) {
 }
 
 void NetworkInfo::ircUserDestroyed() {
 }
 
 void NetworkInfo::ircUserDestroyed() {
-  IrcUser *ircuser = qobject_cast<IrcUser *>(sender());
-  // in case this assert triggers we probably need a static_cast
-  // dynamic_casts seem to screw things up when using the destroyed signal
+  IrcUser *ircuser = static_cast<IrcUser *>(sender());
   Q_ASSERT(ircuser);
   _ircUsers.remove(_ircUsers.key(ircuser));
 }
 
 void NetworkInfo::channelDestroyed() {
   Q_ASSERT(ircuser);
   _ircUsers.remove(_ircUsers.key(ircuser));
 }
 
 void NetworkInfo::channelDestroyed() {
-  IrcChannel *channel = qobject_cast<IrcChannel *>(sender());
-  // in case this assert triggers we probably need a static_cast
-  // dynamic_casts seem to screw things up when using the destroyed signal
+  IrcChannel *channel = static_cast<IrcChannel *>(sender());
   Q_ASSERT(channel);
   _ircChannels.remove(_ircChannels.key(channel));
 }
   Q_ASSERT(channel);
   _ircChannels.remove(_ircChannels.key(channel));
 }
index 40995ad..4ad1138 100644 (file)
@@ -56,6 +56,7 @@ void BufferView::setFilteredModel(QAbstractItemModel *model, BufferViewFilter::M
 }
 
 void BufferView::setModel(QAbstractItemModel *model) {
 }
 
 void BufferView::setModel(QAbstractItemModel *model) {
+  delete selectionModel();
   QTreeView::setModel(model);
   init();
   
   QTreeView::setModel(model);
   init();
   
index 6bcfb6a..d30c313 100644 (file)
 /*****************************************
 * The Filter for the Tree View
 *****************************************/
 /*****************************************
 * The Filter for the Tree View
 *****************************************/
-BufferViewFilter::BufferViewFilter(QAbstractItemModel *model, const Modes &filtermode, const QStringList &nets) : QSortFilterProxyModel(model) {
+BufferViewFilter::BufferViewFilter(QAbstractItemModel *model, const Modes &filtermode, const QStringList &nets)
+  : QSortFilterProxyModel(model),
+    mode(filtermode),
+    networks(nets)
+{
   setSourceModel(model);
   setSortRole(BufferTreeModel::BufferNameRole);
   setSortCaseSensitivity(Qt::CaseInsensitive);
   setSourceModel(model);
   setSortRole(BufferTreeModel::BufferNameRole);
   setSortCaseSensitivity(Qt::CaseInsensitive);
-    
-  mode = filtermode;
-  networks = nets;
   
   connect(model, SIGNAL(invalidateFilter()), this, SLOT(invalidateMe()));
 }
   
   connect(model, SIGNAL(invalidateFilter()), this, SLOT(invalidateMe()));
 }
index ee25309..12bd720 100644 (file)
@@ -86,23 +86,29 @@ void MainWin::init() {
   if(serverListDlg->showOnStartup()) {
     showServerList();
   }
   if(serverListDlg->showOnStartup()) {
     showServerList();
   }
-
+  
+  setDockNestingEnabled(true);
+  
+  
   // TESTING
   // TESTING
-//   setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
-//   setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
+  setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
+  setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
 
 
-//   setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
-//   setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
-  
-//   QDockWidget *dock = new QDockWidget("Topic Dock", this);
-//   dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
+  setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
+  setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
 
 
-//   TopicWidget *topicwidget = new TopicWidget(dock);
-//   dock->setWidget(topicwidget);
-  
-//   addDockWidget(Qt::TopDockWidgetArea, dock);
 
 
-//   ui.menuViews->addAction(dock->toggleViewAction());
+  QDockWidget *dock = new QDockWidget("Topic Dock", this);
+  dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
+
+  TopicWidget *topicwidget = new TopicWidget(dock);
+  dock->setWidget(topicwidget);
+
+  Client::bufferModel()->mapProperty(0, Qt::DisplayRole, topicwidget, "topic");
+
+  addDockWidget(Qt::TopDockWidgetArea, dock);
+
+  ui.menuViews->addAction(dock->toggleViewAction());
 
 }
 
 
 }
 
@@ -159,13 +165,7 @@ 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);
   //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);
-
+  Client::bufferModel()->synchronizeView(view);
   dock->setWidget(view);
   
   addDockWidget(Qt::LeftDockWidgetArea, dock);
   dock->setWidget(view);
   
   addDockWidget(Qt::LeftDockWidgetArea, dock);