1 /***************************************************************************
2 * Copyright (C) 2005-08 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include <QColor> // FIXME Dependency on QtGui!
23 #include "networkmodel.h"
25 #include <QAbstractItemView>
27 #include "bufferinfo.h"
29 #include "signalproxy.h"
30 #include "networkinfo.h"
31 #include "ircchannel.h"
34 /*****************************************
36 *****************************************/
37 BufferItem::BufferItem(Buffer *buffer, AbstractTreeItem *parent)
38 : PropertyMapItem(QStringList() << "bufferName" << "topic" << "nickCount", parent),
40 activity(Buffer::NoActivity)
42 Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
43 if(buf->bufferType() == Buffer::QueryType)
44 flags |= Qt::ItemIsDropEnabled;
48 quint64 BufferItem::id() const {
49 return buf->bufferInfo().uid();
52 void BufferItem::setActivity(const Buffer::ActivityLevel &level) {
56 QColor BufferItem::foreground(int column) const {
58 // for the time beeing we ignore the column :)
59 if(activity & Buffer::Highlight) {
60 return QColor(Qt::red);
61 } else if(activity & Buffer::NewMessage) {
62 return QColor(Qt::darkYellow);
63 } else if(activity & Buffer::OtherActivity) {
64 return QColor(Qt::darkGreen);
67 return QColor(Qt::black);
69 return QColor(Qt::gray);
73 QVariant BufferItem::data(int column, int role) const {
75 case NetworkModel::ItemTypeRole:
76 return NetworkModel::BufferItemType;
77 case NetworkModel::BufferUidRole:
78 return buf->bufferInfo().uid();
79 case NetworkModel::NetworkIdRole:
80 return buf->bufferInfo().networkId();
81 case NetworkModel::BufferTypeRole:
82 return int(buf->bufferType());
83 case NetworkModel::BufferActiveRole:
84 return buf->isActive();
85 case Qt::ForegroundRole:
86 return foreground(column);
88 return PropertyMapItem::data(column, role);
92 void BufferItem::attachIrcChannel(IrcChannel *ircChannel) {
96 _ircChannel = ircChannel;
98 connect(ircChannel, SIGNAL(topicSet(QString)),
99 this, SLOT(setTopic(QString)));
100 connect(ircChannel, SIGNAL(ircUserJoined(IrcUser *)),
101 this, SLOT(join(IrcUser *)));
102 connect(ircChannel, SIGNAL(ircUserParted(IrcUser *)),
103 this, SLOT(part(IrcUser *)));
106 QString BufferItem::bufferName() const {
110 QString BufferItem::topic() const {
112 return _ircChannel->topic();
117 int BufferItem::nickCount() const {
119 return _ircChannel->ircUsers().count();
124 void BufferItem::setTopic(const QString &topic) {
129 void BufferItem::join(IrcUser *ircUser) {
130 emit newChild(new IrcUserItem(ircUser, this));
134 void BufferItem::part(IrcUser *ircUser) {
139 /*****************************************
141 *****************************************/
142 NetworkItem::NetworkItem(const uint &netid, const QString &network, AbstractTreeItem *parent)
143 : PropertyMapItem(QList<QString>() << "networkName" << "currentServer" << "nickCount", parent),
145 _networkName(network)
147 setFlags(Qt::ItemIsEnabled);
150 QVariant NetworkItem::data(int column, int role) const {
152 case NetworkModel::NetworkIdRole:
154 case NetworkModel::ItemTypeRole:
155 return NetworkModel::NetworkItemType;
157 return PropertyMapItem::data(column, role);
161 quint64 NetworkItem::id() const {
165 QString NetworkItem::networkName() const {
167 return _networkInfo->networkName();
172 QString NetworkItem::currentServer() const {
174 return _networkInfo->currentServer();
179 int NetworkItem::nickCount() const {
180 BufferItem *bufferItem;
182 for(int i = 0; i < childCount(); i++) {
183 bufferItem = qobject_cast<BufferItem *>(child(i));
186 count += bufferItem->nickCount();
191 void NetworkItem::attachNetworkInfo(NetworkInfo *networkInfo) {
195 _networkInfo = networkInfo;
197 connect(networkInfo, SIGNAL(networkNameSet(QString)),
198 this, SLOT(setNetworkName(QString)));
199 connect(networkInfo, SIGNAL(currentServerSet(QString)),
200 this, SLOT(setCurrentServer(QString)));
201 connect(networkInfo, SIGNAL(ircChannelAdded(QString)),
202 this, SLOT(attachIrcChannel(QString)));
203 // FIXME: connect this and that...
206 void NetworkItem::attachIrcChannel(const QString &channelName) {
207 IrcChannel *ircChannel = _networkInfo->ircChannel(channelName);
209 qWarning() << "NetworkItem::attachIrcChannel(): unkown Channel" << channelName;
213 BufferItem *bufferItem;
214 for(int i = 0; i < childCount(); i++) {
215 bufferItem = qobject_cast<BufferItem *>(child(i));
216 if(bufferItem->bufferName() == ircChannel->name()) {
217 bufferItem->attachIrcChannel(ircChannel);
223 void NetworkItem::setNetworkName(const QString &networkName) {
224 Q_UNUSED(networkName);
228 void NetworkItem::setCurrentServer(const QString &serverName) {
229 Q_UNUSED(serverName);
233 /*****************************************
235 *****************************************/
236 IrcUserItem::IrcUserItem(IrcUser *ircUser, AbstractTreeItem *parent)
237 : PropertyMapItem(QStringList() << "nickName", parent),
240 connect(ircUser, SIGNAL(destroyed()),
241 this, SLOT(ircUserDestroyed()));
243 connect(ircUser, SIGNAL(nickSet(QString)),
244 this, SLOT(setNick(QString)));
247 QString IrcUserItem::nickName() {
248 return _ircUser->nick();
251 void IrcUserItem::setNick(QString newNick) {
255 void IrcUserItem::ircUserDestroyed() {
260 /*****************************************
262 *****************************************/
263 NetworkModel::NetworkModel(QObject *parent)
264 : TreeModel(NetworkModel::defaultHeader(), parent)
268 QList<QVariant >NetworkModel::defaultHeader() {
269 QList<QVariant> data;
270 data << tr("Buffer") << tr("Topic") << tr("Nick Count");
274 bool NetworkModel::isBufferIndex(const QModelIndex &index) const {
275 return index.data(NetworkModel::ItemTypeRole) == NetworkModel::BufferItemType;
278 Buffer *NetworkModel::getBufferByIndex(const QModelIndex &index) const {
279 BufferItem *item = static_cast<BufferItem *>(index.internalPointer());
280 // FIXME get rid of this
281 Q_ASSERT(item->buffer() == Client::instance()->buffer(item->id()));
282 return item->buffer();
286 // experimental stuff :)
287 QModelIndex NetworkModel::networkIndex(uint networkId) {
288 return indexById(networkId);
291 NetworkItem *NetworkModel::network(uint networkId) {
292 return qobject_cast<NetworkItem *>(rootItem->childById(networkId));
295 NetworkItem *NetworkModel::newNetwork(uint networkId, const QString &networkName) {
296 NetworkItem *networkItem = network(networkId);
298 if(networkItem == 0) {
299 networkItem = new NetworkItem(networkId, networkName, rootItem);
300 appendChild(rootItem, networkItem);
303 Q_ASSERT(networkItem);
307 QModelIndex NetworkModel::bufferIndex(BufferInfo bufferInfo) {
308 QModelIndex networkIdx = networkIndex(bufferInfo.networkId());
309 if(!networkIdx.isValid())
310 return QModelIndex();
312 return indexById(bufferInfo.uid(), networkIdx);
315 BufferItem *NetworkModel::buffer(BufferInfo bufferInfo) {
316 QModelIndex bufferIdx = bufferIndex(bufferInfo);
317 if(bufferIdx.isValid())
318 return static_cast<BufferItem *>(bufferIdx.internalPointer());
323 BufferItem *NetworkModel::newBuffer(BufferInfo bufferInfo) {
324 BufferItem *bufferItem = buffer(bufferInfo);
325 if(bufferItem == 0) {
326 NetworkItem *networkItem = newNetwork(bufferInfo.networkId(), bufferInfo.network());
328 // FIXME: get rid of the buffer pointer
329 Buffer *buffer = Client::instance()->buffer(bufferInfo.uid());
330 bufferItem = new BufferItem(buffer, networkItem);
331 appendChild(networkItem, bufferItem);
334 Q_ASSERT(bufferItem);
338 QStringList NetworkModel::mimeTypes() const {
339 // mimetypes we accept for drops
341 // comma separated list of colon separated pairs of networkid and bufferid
342 // example: 0:1,0:2,1:4
343 types << "application/Quassel/BufferItemList";
347 bool NetworkModel::mimeContainsBufferList(const QMimeData *mimeData) {
348 return mimeData->hasFormat("application/Quassel/BufferItemList");
351 QList< QPair<uint, uint> > NetworkModel::mimeDataToBufferList(const QMimeData *mimeData) {
352 QList< QPair<uint, uint> > bufferList;
354 if(!mimeContainsBufferList(mimeData))
357 QStringList rawBufferList = QString::fromAscii(mimeData->data("application/Quassel/BufferItemList")).split(",");
358 uint networkId, bufferUid;
359 foreach(QString rawBuffer, rawBufferList) {
360 if(!rawBuffer.contains(":"))
362 networkId = rawBuffer.section(":", 0, 0).toUInt();
363 bufferUid = rawBuffer.section(":", 1, 1).toUInt();
364 bufferList.append(qMakePair(networkId, bufferUid));
370 QMimeData *NetworkModel::mimeData(const QModelIndexList &indexes) const {
371 QMimeData *mimeData = new QMimeData();
373 QStringList bufferlist;
374 QString netid, uid, bufferid;
375 foreach(QModelIndex index, indexes) {
376 netid = QString::number(index.data(NetworkIdRole).toUInt());
377 uid = QString::number(index.data(BufferUidRole).toUInt());
378 bufferid = QString("%1:%2").arg(netid).arg(uid);
379 if(!bufferlist.contains(bufferid))
380 bufferlist << bufferid;
383 mimeData->setData("application/Quassel/BufferItemList", bufferlist.join(",").toAscii());
388 bool NetworkModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) {
393 if(!mimeContainsBufferList(data))
396 // target must be a query
397 Buffer::Type targetType = (Buffer::Type)parent.data(NetworkModel::BufferTypeRole).toInt();
398 if(targetType != Buffer::QueryType)
401 QList< QPair<uint, uint> > bufferList = mimeDataToBufferList(data);
403 // exactly one buffer has to be dropped
404 if(bufferList.count() != 1)
407 uint netId = bufferList.first().first;
408 uint bufferId = bufferList.first().second;
410 // no self merges (would kill us)
411 if(bufferId == parent.data(BufferUidRole).toUInt())
414 Q_ASSERT(rootItem->childById(netId));
415 Q_ASSERT(rootItem->childById(netId)->childById(bufferId));
417 // source must be a query too
418 Buffer::Type sourceType = (Buffer::Type)rootItem->childById(netId)->childById(bufferId)->data(0, BufferTypeRole).toInt();
419 if(sourceType != Buffer::QueryType)
422 // TODO: warn user about buffermerge!
423 qDebug() << "merging" << bufferId << parent.data(BufferUidRole).toInt();
424 removeRow(parent.row(), parent.parent());
429 void NetworkModel::attachNetworkInfo(NetworkInfo *networkInfo) {
430 NetworkItem *networkItem = network(networkInfo->networkId());
432 qWarning() << "NetworkModel::attachNetworkInfo(): network is unknown!";
435 networkItem->attachNetworkInfo(networkInfo);
438 void NetworkModel::bufferUpdated(Buffer *buffer) {
439 BufferItem *bufferItem = newBuffer(buffer->bufferInfo());
440 QModelIndex itemindex = indexByItem(bufferItem);
441 emit dataChanged(itemindex, itemindex);
444 void NetworkModel::bufferActivity(Buffer::ActivityLevel level, Buffer *buf) {
445 BufferItem *bufferItem = buffer(buf->bufferInfo());
447 qWarning() << "NetworkModel::bufferActivity(): received Activity Info for uknown Buffer";
450 bufferItem->setActivity(level);