From: Marcus Eggenberger Date: Thu, 20 Dec 2007 13:25:16 +0000 (+0000) Subject: First part of the BufferTreeModel pimpification (maybe I should get of X-Git-Tag: 0.1.0~26 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=4bd0fcd5b0599f3658253353bf2bdc01b32951f7 First part of the BufferTreeModel pimpification (maybe I should get of the "tree" in it's name... can't see/write it anymore :p). - The basic structure of the model has been improved. - NetworkInfos and IrcChannel objects are now connected to the model which allows pretty nice stuff. (we got a working topic yeahi!) to be continued... --- diff --git a/src/client/buffertreemodel.cpp b/src/client/buffertreemodel.cpp index d62d8045..e0039c8f 100644 --- a/src/client/buffertreemodel.cpp +++ b/src/client/buffertreemodel.cpp @@ -28,12 +28,15 @@ #include "bufferinfo.h" #include "client.h" #include "signalproxy.h" +#include "networkinfo.h" +#include "ircchannel.h" +#include "ircuser.h" /***************************************** * Fancy Buffer Items *****************************************/ -BufferTreeItem::BufferTreeItem(Buffer *buffer, TreeItem *parent) - : TreeItem(parent), +BufferTreeItem::BufferTreeItem(Buffer *buffer, AbstractTreeItem *parent) + : PropertyMapItem(QStringList() << "bufferName" << "topic" << "nickCount", parent), buf(buffer), activity(Buffer::NoActivity) { @@ -51,17 +54,6 @@ void BufferTreeItem::setActivity(const Buffer::ActivityLevel &level) { activity = level; } -QString BufferTreeItem::text(int column) const { - switch(column) { - case 0: - return buf->name(); - case 1: - return buf->networkName(); - default: - return QString(); - } -} - QColor BufferTreeItem::foreground(int column) const { Q_UNUSED(column) // for the time beeing we ignore the column :) @@ -79,37 +71,78 @@ 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::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(); - + case BufferTreeModel::BufferTypeRole: + return int(buf->bufferType()); + case BufferTreeModel::BufferActiveRole: + return buf->isActive(); + case Qt::ForegroundRole: + return foreground(column); default: - return TreeItem::data(column, role); + return PropertyMapItem::data(column, role); } } +void BufferTreeItem::attachIrcChannel(IrcChannel *ircChannel) { + if(!ircChannel) + return; + + _ircChannel = ircChannel; + + connect(ircChannel, SIGNAL(topicSet(QString)), + this, SLOT(setTopic(QString))); + connect(ircChannel, SIGNAL(ircUserJoined(IrcUser *)), + this, SLOT(join(IrcUser *))); + connect(ircChannel, SIGNAL(ircUserParted(IrcUser *)), + this, SLOT(part(IrcUser *))); +} + +QString BufferTreeItem::bufferName() const { + return buf->name(); +} + +QString BufferTreeItem::topic() const { + if(_ircChannel) + return _ircChannel->topic(); + else + return QString(); +} + +int BufferTreeItem::nickCount() const { + if(_ircChannel) + return _ircChannel->ircUsers().count(); + else + return 0; +} + +void BufferTreeItem::setTopic(const QString &topic) { + Q_UNUSED(topic); + emit dataChanged(1); +} + +void BufferTreeItem::join(IrcUser *ircUser) { + Q_UNUSED(ircUser); + emit dataChanged(2); +} + +void BufferTreeItem::part(IrcUser *ircUser) { + Q_UNUSED(ircUser); + emit dataChanged(2); +} + /***************************************** * Network Items *****************************************/ -NetworkTreeItem::NetworkTreeItem(const uint &netid, const QString &network, TreeItem *parent) - : TreeItem(parent), +NetworkTreeItem::NetworkTreeItem(const uint &netid, const QString &network, AbstractTreeItem *parent) + : PropertyMapItem(QList() << "networkName" << "currentServer" << "nickCount", parent), _networkId(netid), - net(network) + _networkName(network) { - net = network; - itemData << net << ""; setFlags(Qt::ItemIsEnabled); } @@ -117,8 +150,10 @@ QVariant NetworkTreeItem::data(int column, int role) const { switch(role) { case BufferTreeModel::NetworkIdRole: return _networkId; + case BufferTreeModel::ItemTypeRole: + return BufferTreeModel::NetworkItem; default: - return TreeItem::data(column, role); + return PropertyMapItem::data(column, role); } } @@ -126,6 +161,74 @@ quint64 NetworkTreeItem::id() const { return _networkId; } +QString NetworkTreeItem::networkName() const { + if(_networkInfo) + return _networkInfo->networkName(); + else + return _networkName; +} + +QString NetworkTreeItem::currentServer() const { + if(_networkInfo) + return _networkInfo->currentServer(); + else + return QString(); +} + +int NetworkTreeItem::nickCount() const { + BufferTreeItem *bufferItem; + int count = 0; + for(int i = 0; i < childCount(); i++) { + bufferItem = qobject_cast(child(i)); + if(!bufferItem) + continue; + count += bufferItem->nickCount(); + } + return count; +} + +void NetworkTreeItem::attachNetworkInfo(NetworkInfo *networkInfo) { + if(!networkInfo) + return; + + _networkInfo = networkInfo; + + connect(networkInfo, SIGNAL(networkNameSet(QString)), + this, SLOT(setNetworkName(QString))); + connect(networkInfo, SIGNAL(currentServerSet(QString)), + this, SLOT(setCurrentServer(QString))); + connect(networkInfo, SIGNAL(ircChannelAdded(QString)), + this, SLOT(attachIrcChannel(QString))); + // FIXME: connect this and that... +} + +void NetworkTreeItem::attachIrcChannel(const QString &channelName) { + IrcChannel *ircChannel = _networkInfo->ircChannel(channelName); + if(!ircChannel) { + qWarning() << "NetworkTreeItem::attachIrcChannel(): unkown Channel" << channelName; + return; + } + + BufferTreeItem *bufferItem; + for(int i = 0; i < childCount(); i++) { + bufferItem = qobject_cast(child(i)); + if(bufferItem->bufferName() == ircChannel->name()) { + bufferItem->attachIrcChannel(ircChannel); + break; + } + } +} + +void NetworkTreeItem::setNetworkName(const QString &networkName) { + Q_UNUSED(networkName); + emit dataChanged(0); +} + +void NetworkTreeItem::setCurrentServer(const QString &serverName) { + Q_UNUSED(serverName); + emit dataChanged(1); +} + /***************************************** * BufferTreeModel *****************************************/ @@ -147,7 +250,7 @@ BufferTreeModel::BufferTreeModel(QObject *parent) QListBufferTreeModel::defaultHeader() { QList data; - data << tr("Buffer") << tr("Network"); + data << tr("Buffer") << tr("Topic") << tr("Nick Count"); return data; } @@ -174,43 +277,62 @@ bool BufferTreeModel::isBufferIndex(const QModelIndex &index) const { Buffer *BufferTreeModel::getBufferByIndex(const QModelIndex &index) const { BufferTreeItem *item = static_cast(index.internalPointer()); + // FIXME get rid of this + Q_ASSERT(item->buffer() == Client::instance()->buffer(item->id())); return item->buffer(); } -QModelIndex BufferTreeModel::getOrCreateNetworkItemIndex(Buffer *buffer) { - QString net = buffer->networkName(); - uint netId = buffer->networkId(); - TreeItem *networkItem; - if(!(networkItem = rootItem->childById(netId))) { - int nextRow = rootItem->childCount(); - networkItem = new NetworkTreeItem(netId, net, rootItem); - - beginInsertRows(QModelIndex(), nextRow, nextRow); - rootItem->appendChild(networkItem); - endInsertRows(); +// experimental stuff :) +QModelIndex BufferTreeModel::networkIndex(uint networkId) { + return indexById(networkId); +} + +NetworkTreeItem *BufferTreeModel::network(uint networkId) { + return qobject_cast(rootItem->childById(networkId)); +} + +NetworkTreeItem *BufferTreeModel::newNetwork(uint networkId, const QString &networkName) { + NetworkTreeItem *networkItem = network(networkId); + + if(networkItem == 0) { + networkItem = new NetworkTreeItem(networkId, networkName, rootItem); + appendChild(rootItem, networkItem); } Q_ASSERT(networkItem); - return index(networkItem->row(), 0); + return networkItem; } -QModelIndex BufferTreeModel::getOrCreateBufferItemIndex(Buffer *buffer) { - QModelIndex networkItemIndex = getOrCreateNetworkItemIndex(buffer); - NetworkTreeItem *networkItem = static_cast(networkItemIndex.internalPointer()); - TreeItem *bufferItem; - - if(!(bufferItem = networkItem->childById(buffer->bufferInfo().uid()))) { - int nextRow = networkItem->childCount(); +QModelIndex BufferTreeModel::bufferIndex(BufferInfo bufferInfo) { + QModelIndex networkIdx = networkIndex(bufferInfo.networkId()); + if(!networkIdx.isValid()) + return QModelIndex(); + else + return indexById(bufferInfo.uid(), networkIdx); +} + +BufferTreeItem *BufferTreeModel::buffer(BufferInfo bufferInfo) { + QModelIndex bufferIdx = bufferIndex(bufferInfo); + if(bufferIdx.isValid()) + return static_cast(bufferIdx.internalPointer()); + else + return 0; +} + +BufferTreeItem *BufferTreeModel::newBuffer(BufferInfo bufferInfo) { + BufferTreeItem *bufferItem = buffer(bufferInfo); + if(bufferItem == 0) { + NetworkTreeItem *networkItem = newNetwork(bufferInfo.networkId(), bufferInfo.network()); + + // FIXME: get rid of the buffer pointer + Buffer *buffer = Client::instance()->buffer(bufferInfo.uid()); bufferItem = new BufferTreeItem(buffer, networkItem); - - beginInsertRows(networkItemIndex, nextRow, nextRow); - networkItem->appendChild(bufferItem); - endInsertRows(); + appendChild(networkItem, bufferItem); } Q_ASSERT(bufferItem); - return index(bufferItem->row(), 0, networkItemIndex); + return bufferItem; } QStringList BufferTreeModel::mimeTypes() const { @@ -304,8 +426,18 @@ bool BufferTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, return true; } +void BufferTreeModel::attachNetworkInfo(NetworkInfo *networkInfo) { + NetworkTreeItem *networkItem = network(networkInfo->networkId()); + if(!networkItem) { + qWarning() << "BufferTreeModel::attachNetworkInfo(): network is unknown!"; + return; + } + networkItem->attachNetworkInfo(networkInfo); +} + void BufferTreeModel::bufferUpdated(Buffer *buffer) { - QModelIndex itemindex = getOrCreateBufferItemIndex(buffer); + BufferTreeItem *bufferItem = newBuffer(buffer->bufferInfo()); + QModelIndex itemindex = indexByItem(bufferItem); emit dataChanged(itemindex, itemindex); } @@ -321,17 +453,26 @@ void BufferTreeModel::setCurrentIndex(const QModelIndex &index, QItemSelectionMo } } -void BufferTreeModel::bufferActivity(Buffer::ActivityLevel level, Buffer *buffer) { - BufferTreeItem *bufferItem = static_cast(getOrCreateBufferItemIndex(buffer).internalPointer()); - if(buffer != currentBuffer) +void BufferTreeModel::bufferActivity(Buffer::ActivityLevel level, Buffer *buf) { + BufferTreeItem *bufferItem = buffer(buf->bufferInfo()); + if(!bufferItem) { + qWarning() << "BufferTreeModel::bufferActivity(): received Activity Info for uknown Buffer"; + return; + } + + if(buf != currentBuffer) bufferItem->setActivity(level); else bufferItem->setActivity(Buffer::NoActivity); - bufferUpdated(buffer); + bufferUpdated(buf); } void BufferTreeModel::selectBuffer(Buffer *buffer) { - QModelIndex index = getOrCreateBufferItemIndex(buffer); + QModelIndex index = bufferIndex(buffer->bufferInfo()); + if(!index.isValid()) { + qWarning() << "BufferTreeModel::selectBuffer(): unknown Buffer has been selected."; + return; + } // SUPER UGLY! setCurrentIndex(index, 0); } diff --git a/src/client/buffertreemodel.h b/src/client/buffertreemodel.h index 05b390b4..f2e118e1 100644 --- a/src/client/buffertreemodel.h +++ b/src/client/buffertreemodel.h @@ -36,45 +36,80 @@ class BufferInfo; #include "modelpropertymapper.h" class MappedSelectionModel; class QAbstractItemView; +class NetworkInfo; +class IrcChannel; +class IrcUser; /***************************************** * Fancy Buffer Items *****************************************/ -class BufferTreeItem : public TreeItem { +class BufferTreeItem : public PropertyMapItem { Q_OBJECT + Q_PROPERTY(QString bufferName READ bufferName) + Q_PROPERTY(QString topic READ topic) + Q_PROPERTY(int nickCount READ nickCount) public: - BufferTreeItem(Buffer *, TreeItem *parent = 0); + BufferTreeItem(Buffer *, AbstractTreeItem *parent = 0); virtual quint64 id() const; - QVariant data(int column, int role) const; + virtual QVariant data(int column, int role) const; + void attachIrcChannel(IrcChannel *ircChannel); + + QString bufferName() const; + QString topic() const; + int nickCount() const; + + Buffer *buffer() const { return buf; } void setActivity(const Buffer::ActivityLevel &); +public slots: + void setTopic(const QString &topic); + void join(IrcUser *ircUser); + void part(IrcUser *ircUser); + private: - QString text(int column) const; QColor foreground(int column) const; Buffer *buf; Buffer::ActivityLevel activity; + + QPointer _ircChannel; }; /***************************************** * Network Items *****************************************/ -class NetworkTreeItem : public TreeItem { +class NetworkTreeItem : public PropertyMapItem { Q_OBJECT - + Q_PROPERTY(QString networkName READ networkName) + Q_PROPERTY(QString currentServer READ currentServer) + Q_PROPERTY(int nickCount READ nickCount) + public: - NetworkTreeItem(const uint &netid, const QString &, TreeItem *parent = 0); + NetworkTreeItem(const uint &netid, const QString &, AbstractTreeItem *parent = 0); virtual QVariant data(int column, int row) const; virtual quint64 id() const; + QString networkName() const; + QString currentServer() const; + int nickCount() const; + +public slots: + void setNetworkName(const QString &networkName); + void setCurrentServer(const QString &serverName); + + void attachNetworkInfo(NetworkInfo *networkInfo); + void attachIrcChannel(const QString &channelName); + private: uint _networkId; - QString net; + QString _networkName; + + QPointer _networkInfo; }; /***************************************** @@ -88,9 +123,18 @@ public: BufferTypeRole = Qt::UserRole, BufferActiveRole, BufferUidRole, - NetworkIdRole + NetworkIdRole, + ItemTypeRole }; + enum itemTypes { + AbstractItem, + SimpleItem, + NetworkItem, + BufferItem, + NickItem + }; + BufferTreeModel(QObject *parent = 0); static QList defaultHeader(); @@ -108,7 +152,8 @@ public: virtual QMimeData *mimeData(const QModelIndexList &) const; virtual bool dropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex &); - + void attachNetworkInfo(NetworkInfo *networkInfo); + public slots: void bufferUpdated(Buffer *); void setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command); @@ -122,8 +167,14 @@ signals: private: bool isBufferIndex(const QModelIndex &) const; Buffer *getBufferByIndex(const QModelIndex &) const; - QModelIndex getOrCreateNetworkItemIndex(Buffer *buffer); - QModelIndex getOrCreateBufferItemIndex(Buffer *buffer); + + QModelIndex networkIndex(uint networkId); + NetworkTreeItem *network(uint networkId); + NetworkTreeItem *newNetwork(uint networkId, const QString &networkName); + + QModelIndex bufferIndex(BufferInfo bufferInfo); + BufferTreeItem *buffer(BufferInfo bufferInfo); + BufferTreeItem *newBuffer(BufferInfo bufferInfo); QPointer _selectionModelSynchronizer; QPointer _propertyMapper; diff --git a/src/client/client.cpp b/src/client/client.cpp index 296c870d..28c656e9 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -444,6 +444,7 @@ void Client::networkConnected(uint netid) { NetworkInfo *netinfo = new NetworkInfo(netid, this); netinfo->setProxy(signalProxy()); + bufferModel()->attachNetworkInfo(netinfo); if(!isConnected()) { connect(netinfo, SIGNAL(initDone()), this, SLOT(updateCoreConnectionProgress())); diff --git a/src/client/treemodel.cpp b/src/client/treemodel.cpp index c113b287..3ae2bc3a 100644 --- a/src/client/treemodel.cpp +++ b/src/client/treemodel.cpp @@ -20,101 +20,204 @@ #include "treemodel.h" +#include + /***************************************** - * Buffer Items stored in the Tree Model + * Abstract Items of a TreeModel *****************************************/ -TreeItem::TreeItem(const QList &data, TreeItem *parent) +AbstractTreeItem::AbstractTreeItem(AbstractTreeItem *parent) : QObject(parent), - itemData(data), _parentItem(parent), _flags(Qt::ItemIsSelectable | Qt::ItemIsEnabled) { } -TreeItem::TreeItem(TreeItem *parent) - : QObject(parent), - itemData(QList()), - _parentItem(parent), - _flags(Qt::ItemIsSelectable | Qt::ItemIsEnabled) -{ +AbstractTreeItem::~AbstractTreeItem() { + foreach(int key, _childItems.keys()) { + qDeleteAll(_childItems[key]); + } } -TreeItem::~TreeItem() { - qDeleteAll(_childItems); +quint64 AbstractTreeItem::id() const { + return (quint64)this; } -quint64 TreeItem::id() const { - return (quint64)this; +int AbstractTreeItem::defaultColumn() const { + // invalid QModelIndexes aka rootNodes get their Childs stuffed into column -1 + // all others to 0 + if(_parentItem == 0) + return -1; + else + return 0; } -void TreeItem::appendChild(TreeItem *item) { - _childItems.append(item); - _childHash[item->id()] = item; - connect(item, SIGNAL(destroyed()), - this, SLOT(childDestroyed())); +void AbstractTreeItem::appendChild(int column, AbstractTreeItem *item) { + if(!_childItems.contains(column)) { + _childItems[column] = QList(); + _childHash[column] = QHash(); + } + + _childItems[column].append(item); + _childHash[column][item->id()] = item; + + connect(item, SIGNAL(destroyed()), this, SLOT(childDestroyed())); +} + +void AbstractTreeItem::appendChild(AbstractTreeItem *child) { + appendChild(defaultColumn(), child); } -void TreeItem::removeChild(int row) { - if(row >= _childItems.size()) +void AbstractTreeItem::removeChild(int column, int row) { + if(!_childItems.contains(column) + || _childItems[column].size() <= row) return; - TreeItem *treeitem = _childItems.value(row); - _childItems.removeAt(row); - _childHash.remove(_childHash.key(treeitem)); + + AbstractTreeItem *treeitem = _childItems[column].value(row); + _childItems[column].removeAt(row); + _childHash[column].remove(_childHash[column].key(treeitem)); + treeitem->deleteLater(); } -TreeItem *TreeItem::child(int row) const { - if(row < _childItems.size()) - return _childItems.value(row); - else +void AbstractTreeItem::removeChild(int row) { + removeChild(defaultColumn(), row); +} + +AbstractTreeItem *AbstractTreeItem::child(int column, int row) const { + if(!_childItems.contains(column) + || _childItems[column].size() <= row) return 0; + else + return _childItems[column].value(row); } -TreeItem *TreeItem::childById(const uint &id) const { - if(_childHash.contains(id)) - return _childHash.value(id); +AbstractTreeItem *AbstractTreeItem::child(int row) const { + return child(defaultColumn(), row); +} + +AbstractTreeItem *AbstractTreeItem::childById(int column, const uint &id) const { + if(!_childHash.contains(column) + || !_childHash[column].contains(id)) + return 0; else + return _childHash[column].value(id); +} + +AbstractTreeItem *AbstractTreeItem::childById(const uint &id) const { + return childById(defaultColumn(), id); +} + +int AbstractTreeItem::childCount(int column) const { + if(!_childItems.contains(column)) return 0; + else + return _childItems[column].count(); } -int TreeItem::childCount() const { - return _childItems.count(); +int AbstractTreeItem::childCount() const { + return childCount(defaultColumn()); } -int TreeItem::row() const { - if(_parentItem) - return _parentItem->_childItems.indexOf(const_cast(this)); +int AbstractTreeItem::column() const { + if(!_parentItem) + return -1; + + QHash >::const_iterator iter = _parentItem->_childItems.constBegin(); + int pos; + while(iter != _parentItem->_childItems.constEnd()) { + pos = iter.value().indexOf(const_cast(this)); + if(pos != -1) + return iter.key(); + iter++; + } + + // unable to find us o_O + return _parentItem->defaultColumn(); +} + +int AbstractTreeItem::row() const { + if(!_parentItem) + return -1; else - return 0; + return _parentItem->_childItems[column()].indexOf(const_cast(this)); } -TreeItem *TreeItem::parent() { +AbstractTreeItem *AbstractTreeItem::parent() { return _parentItem; } -int TreeItem::columnCount() const { - return itemData.count(); +Qt::ItemFlags AbstractTreeItem::flags() const { + return _flags; +} + +void AbstractTreeItem::setFlags(Qt::ItemFlags flags) { + _flags = flags; } -QVariant TreeItem::data(int column, int role) const { - if(role == Qt::DisplayRole && column < itemData.count()) - return itemData[column]; +void AbstractTreeItem::childDestroyed() { + AbstractTreeItem *item = static_cast(sender()); + removeChild(item->column(), item->row()); +} + +/***************************************** + * SimpleTreeItem + *****************************************/ +SimpleTreeItem::SimpleTreeItem(const QList &data, AbstractTreeItem *parent) + : AbstractTreeItem(parent), + _itemData(data) +{ +} + +SimpleTreeItem::~SimpleTreeItem() { +} + +QVariant SimpleTreeItem::data(int column, int role) const { + if(role == Qt::DisplayRole && column < _itemData.count()) + return _itemData[column]; else return QVariant(); } -Qt::ItemFlags TreeItem::flags() const { - return _flags; +int SimpleTreeItem::columnCount() const { + return _itemData.count(); } -void TreeItem::setFlags(Qt::ItemFlags flags) { - _flags = flags; +/***************************************** + * PropertyMapItem + *****************************************/ +PropertyMapItem::PropertyMapItem(const QStringList &propertyOrder, AbstractTreeItem *parent) + : AbstractTreeItem(parent), + _propertyOrder(propertyOrder) +{ +} + +PropertyMapItem::PropertyMapItem(AbstractTreeItem *parent) + : AbstractTreeItem(parent), + _propertyOrder(QStringList()) +{ +} + + +PropertyMapItem::~PropertyMapItem() { } + +QVariant PropertyMapItem::data(int column, int role) const { + if(column >= columnCount()) + return QVariant(); -void TreeItem::childDestroyed() { - TreeItem *item = static_cast(sender()); - removeChild(item->row()); + if(role != Qt::DisplayRole) + return QVariant(); + + return property(_propertyOrder[column].toAscii()); +} + +int PropertyMapItem::columnCount() const { + return _propertyOrder.count(); } +void PropertyMapItem::appendProperty(const QString &property) { + _propertyOrder << property; +} + /***************************************** @@ -123,7 +226,7 @@ void TreeItem::childDestroyed() { TreeModel::TreeModel(const QList &data, QObject *parent) : QAbstractItemModel(parent) { - rootItem = new TreeItem(data, 0); + rootItem = new SimpleTreeItem(data, 0); } TreeModel::~TreeModel() { @@ -134,14 +237,15 @@ QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) con if(!hasIndex(row, column, parent)) return QModelIndex(); - TreeItem *parentItem; + AbstractTreeItem *parentItem; if(!parent.isValid()) parentItem = rootItem; else - parentItem = static_cast(parent.internalPointer()); + parentItem = static_cast(parent.internalPointer()); - TreeItem *childItem = parentItem->child(row); + AbstractTreeItem *childItem = parentItem->child(parent.column(), row); + if(childItem) return createIndex(row, column, childItem); else @@ -149,26 +253,40 @@ QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) con } QModelIndex TreeModel::indexById(uint id, const QModelIndex &parent) const { - TreeItem *parentItem; + AbstractTreeItem *parentItem; if(!parent.isValid()) parentItem = rootItem; else - parentItem = static_cast(parent.internalPointer()); + parentItem = static_cast(parent.internalPointer()); + + AbstractTreeItem *childItem = parentItem->childById(parent.column(), id); - TreeItem *childItem = parentItem->childById(id); if(childItem) return createIndex(childItem->row(), 0, childItem); else return QModelIndex(); } +QModelIndex TreeModel::indexByItem(AbstractTreeItem *item) const { + if(item == 0) { + qWarning() << "TreeModel::indexByItem(AbstractTreeItem *item) received NULL-Pointer"; + return QModelIndex(); + } + + if(item == rootItem) + return QModelIndex(); + else + return createIndex(item->row(), 0, item); + +} + QModelIndex TreeModel::parent(const QModelIndex &index) const { if(!index.isValid()) return QModelIndex(); - TreeItem *childItem = static_cast(index.internalPointer()); - TreeItem *parentItem = static_cast(childItem->parent()); + AbstractTreeItem *childItem = static_cast(index.internalPointer()); + AbstractTreeItem *parentItem = static_cast(childItem->parent()); if(parentItem == rootItem) return QModelIndex(); @@ -177,18 +295,18 @@ QModelIndex TreeModel::parent(const QModelIndex &index) const { } int TreeModel::rowCount(const QModelIndex &parent) const { - TreeItem *parentItem; + AbstractTreeItem *parentItem; if(!parent.isValid()) parentItem = rootItem; else - parentItem = static_cast(parent.internalPointer()); - - return parentItem->childCount(); + parentItem = static_cast(parent.internalPointer()); + + return parentItem->childCount(parent.column()); } int TreeModel::columnCount(const QModelIndex &parent) const { if(parent.isValid()) - return static_cast(parent.internalPointer())->columnCount(); + return static_cast(parent.internalPointer())->columnCount(); else return rootItem->columnCount(); } @@ -197,16 +315,16 @@ QVariant TreeModel::data(const QModelIndex &index, int role) const { if(!index.isValid()) return QVariant(); - TreeItem *item = static_cast(index.internalPointer()); + AbstractTreeItem *item = static_cast(index.internalPointer()); return item->data(index.column(), role); } Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const { - TreeItem *item; + AbstractTreeItem *item; if(!index.isValid()) item = rootItem; else - item = static_cast(index.internalPointer()); + item = static_cast(index.internalPointer()); return item->flags(); } @@ -217,18 +335,46 @@ QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int rol return QVariant(); } +void TreeModel::itemDataChanged(int column) { + AbstractTreeItem *item = qobject_cast(sender()); + QModelIndex itemIndex; + + if(item == rootItem) + itemIndex = QModelIndex(); + else + itemIndex = createIndex(item->row(), column, item); + + emit dataChanged(itemIndex, itemIndex); +} + +void TreeModel::appendChild(AbstractTreeItem *parent, AbstractTreeItem *child) { + if(parent == 0 or child == 0) { + qWarning() << "TreeModel::apendChild(parent, child) parent and child have to be valid pointers!" << parent << child; + return; + } + + int nextRow = parent->childCount(); + beginInsertRows(indexByItem(parent), nextRow, nextRow); + parent->appendChild(child); + endInsertRows(); + + connect(child, SIGNAL(dataChanged(int)), + this, SLOT(itemDataChanged(int))); +} + + bool TreeModel::removeRow(int row, const QModelIndex &parent) { if(row > rowCount(parent)) return false; - TreeItem *item; + AbstractTreeItem *item; if(!parent.isValid()) item = rootItem; else - item = static_cast(parent.internalPointer()); + item = static_cast(parent.internalPointer()); beginRemoveRows(parent, row, row); - item->removeChild(row); + item->removeChild(parent.column(), row); endRemoveRows(); return true; } @@ -242,17 +388,17 @@ bool TreeModel::removeRows(int row, int count, const QModelIndex &parent) { if(row + count - 1 > rowCount(parent) || row < 0 || count < 0) return false; - TreeItem *item; + AbstractTreeItem *item; if(!parent.isValid()) item = rootItem; else - item = static_cast(parent.internalPointer()); + item = static_cast(parent.internalPointer()); beginRemoveRows(parent, row, row + count - 1); for(int i = row + count - 1; i >= 0; i--) { - item->removeChild(i); + item->removeChild(parent.column(), i); } endRemoveRows(); return true; diff --git a/src/client/treemodel.h b/src/client/treemodel.h index dc7e70d2..0d23405a 100644 --- a/src/client/treemodel.h +++ b/src/client/treemodel.h @@ -22,6 +22,7 @@ #define _TREEMODEL_H_ #include +#include #include #include #include @@ -29,47 +30,93 @@ /***************************************** * general item used in the Tree Model *****************************************/ -class TreeItem : public QObject { +class AbstractTreeItem : public QObject { Q_OBJECT Q_PROPERTY(uint id READ id) public: - TreeItem(const QList &data, TreeItem *parent = 0); - TreeItem(TreeItem *parent = 0); - virtual ~TreeItem(); + AbstractTreeItem(AbstractTreeItem *parent = 0); + virtual ~AbstractTreeItem(); - void appendChild(TreeItem *child); + void appendChild(int column, AbstractTreeItem *child); + void appendChild(AbstractTreeItem *child); + + void removeChild(int column, int row); void removeChild(int row); virtual quint64 id() const; - TreeItem *child(int row) const; - TreeItem *childById(const uint &) const; + AbstractTreeItem *child(int column, int row) const; + AbstractTreeItem *child(int row) const; + + AbstractTreeItem *childById(int column, const uint &id) const; + AbstractTreeItem *childById(const uint &id) const; + int childCount(int column) const; int childCount() const; - int columnCount() const; - virtual QVariant data(int column, int role) const; + virtual int columnCount() const = 0; - Qt::ItemFlags flags() const; - void setFlags(Qt::ItemFlags); + virtual QVariant data(int column, int role) const = 0; - int row() const; - TreeItem *parent(); + virtual Qt::ItemFlags flags() const; + virtual void setFlags(Qt::ItemFlags); + int column() const; + int row() const; + AbstractTreeItem *parent(); +signals: + void dataChanged(int column); + private slots: void childDestroyed(); +private: + QHash > _childItems; + QHash > _childHash; // uint to be compatible to qHash functions + AbstractTreeItem *_parentItem; + Qt::ItemFlags _flags; + + int defaultColumn() const; +}; -protected: - QList itemData; + +/***************************************** + * SimpleTreeItem + *****************************************/ +class SimpleTreeItem : public AbstractTreeItem { + Q_OBJECT + +public: + SimpleTreeItem(const QList &data, AbstractTreeItem *parent = 0); + virtual ~SimpleTreeItem(); + virtual QVariant data(int column, int role) const; + virtual int columnCount() const; private: - QList _childItems; - QHash _childHash; // uint to be compatible to qHash functions - TreeItem *_parentItem; - Qt::ItemFlags _flags; + QList _itemData; +}; + +/***************************************** + * PropertyMapItem + *****************************************/ +class PropertyMapItem : public AbstractTreeItem { + Q_OBJECT + +public: + PropertyMapItem(const QStringList &propertyOrder, AbstractTreeItem *parent = 0); + PropertyMapItem(AbstractTreeItem *parent = 0); + + virtual ~PropertyMapItem(); + + virtual QVariant data(int column, int role) const; + virtual int columnCount() const; + + void appendProperty(const QString &property); + +private: + QStringList _propertyOrder; }; @@ -86,19 +133,28 @@ public: QVariant data(const QModelIndex &index, int role) const; virtual Qt::ItemFlags flags(const QModelIndex &index) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; QModelIndex indexById(uint id, const QModelIndex &parent = QModelIndex()) const; + QModelIndex indexByItem(AbstractTreeItem *item) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; virtual void clear(); +private slots: + void itemDataChanged(int column); + protected: + void appendChild(AbstractTreeItem *parent, AbstractTreeItem *child); + bool removeRow(int row, const QModelIndex &parent = QModelIndex()); bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); - TreeItem *rootItem; + AbstractTreeItem *rootItem; }; #endif diff --git a/src/common/signalproxy.cpp b/src/common/signalproxy.cpp index aba57623..c30fe4f1 100644 --- a/src/common/signalproxy.cpp +++ b/src/common/signalproxy.cpp @@ -327,7 +327,6 @@ const QByteArray &SignalProxy::methodName(QObject *obj, int methodId) { void SignalProxy::setSyncMap(QObject *obj) { const QMetaObject *meta = obj->metaObject(); - QHash syncMap; QList slotIndexes; @@ -567,8 +566,17 @@ void SignalProxy::handleSync(QVariantList params) { QObject *receiver = _syncSlave[className][objectName]; if(!syncMap(receiver).contains(signalId)) { - qWarning() << "received Sync Call with invalid SignalId" << className << objectName << signalId; - } + const QMetaObject *meta = receiver->metaObject(); + QString signalName; + if(signalId < meta->methodCount()) + signalName = QString(meta->method(signalId).signature()); + else + signalName = QString::number(signalId); + + qWarning() << "received Sync Call for Object" << receiver + << "- no matching Slot for Signal:" << signalName; + return; + } int slotId = syncMap(receiver)[signalId]; if(!invokeSlot(receiver, slotId, params)) qWarning("SignalProxy::handleSync(): invokeMethod for \"%s\" failed ", methodName(receiver, slotId).constData()); @@ -811,4 +819,14 @@ void SignalProxy::dumpProxyStats() { qDebug() << "number of Classes cached:" << _classInfo.count(); } +void SignalProxy::dumpSyncMap(QObject *object) { + const QMetaObject *meta = object->metaObject(); + qDebug() << "SignalProxy: SyncMap for Class" << meta->className(); + QHash syncMap_ = syncMap(object); + QHash::const_iterator iter = syncMap_.constBegin(); + while(iter != syncMap_.constEnd()) { + qDebug() << iter.key() << meta->method(iter.key()).signature() << "-->" << iter.value() << meta->method(iter.value()).signature(); + iter++; + } +} diff --git a/src/common/signalproxy.h b/src/common/signalproxy.h index bf55936c..b787c2ad 100644 --- a/src/common/signalproxy.h +++ b/src/common/signalproxy.h @@ -133,6 +133,8 @@ private: void _detachSignals(QObject *sender); void _detachSlots(QObject *receiver); + void dumpSyncMap(QObject *object); + // containg a list of argtypes for fast access QHash _classInfo; @@ -152,7 +154,7 @@ private: QHash _peerByteCount; ProxyMode _proxyMode; - + friend class SignalRelay; }; diff --git a/src/qtui/mainwin.cpp b/src/qtui/mainwin.cpp index f75d1653..963ee4b5 100644 --- a/src/qtui/mainwin.cpp +++ b/src/qtui/mainwin.cpp @@ -119,7 +119,7 @@ void MainWin::init() { TopicWidget *topicwidget = new TopicWidget(dock); dock->setWidget(topicwidget); - Client::bufferModel()->mapProperty(0, Qt::DisplayRole, topicwidget, "topic"); + Client::bufferModel()->mapProperty(1, Qt::DisplayRole, topicwidget, "topic"); addDockWidget(Qt::TopDockWidgetArea, dock); diff --git a/src/uisupport/bufferview.cpp b/src/uisupport/bufferview.cpp index 8ddd2b3f..e362da53 100644 --- a/src/uisupport/bufferview.cpp +++ b/src/uisupport/bufferview.cpp @@ -33,8 +33,8 @@ BufferView::BufferView(QWidget *parent) : QTreeView(parent) { void BufferView::init() { setIndentation(10); - header()->hide(); - header()->hideSection(1); + // header()->hide(); + // header()->hideSection(1); expandAll(); setAnimated(true);