X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fclient%2Fnetworkmodel.cpp;h=27bb3e2f4b879bca692e4cf4d1fd29bf88a60880;hp=1a36ac0f64ff194a1be8fc3f8b2b7d4eb4c71f03;hb=ef97dad874c30d7e0586b3dcb98eed15d8987382;hpb=57acdf634ef6be56f5c8380fd2a8cb72e1e7a08c diff --git a/src/client/networkmodel.cpp b/src/client/networkmodel.cpp index 1a36ac0f..27bb3e2f 100644 --- a/src/client/networkmodel.cpp +++ b/src/client/networkmodel.cpp @@ -55,8 +55,22 @@ QVariant NetworkItem::data(int column, int role) const { } } +BufferItem *NetworkItem::findBufferItem(BufferId bufferId) { + BufferItem *bufferItem = 0; + + for(int i = 0; i < childCount(); i++) { + bufferItem = qobject_cast(child(i)); + if(!bufferItem) + continue; + if(bufferItem->bufferId() == bufferId) + return bufferItem; + } + return 0; +} + + BufferItem *NetworkItem::bufferItem(const BufferInfo &bufferInfo) { - BufferItem *bufferItem = qobject_cast(childById(qHash(bufferInfo.bufferId()))); + BufferItem *bufferItem = findBufferItem(bufferInfo); if(bufferItem) return bufferItem; @@ -90,6 +104,8 @@ void NetworkItem::attachNetwork(Network *network) { this, SLOT(setCurrentServer(QString))); connect(network, SIGNAL(ircChannelAdded(IrcChannel *)), this, SLOT(attachIrcChannel(IrcChannel *))); + connect(network, SIGNAL(ircUserAdded(IrcUser *)), + this, SLOT(attachIrcUser(IrcUser *))); connect(network, SIGNAL(connectedSet(bool)), this, SIGNAL(dataChanged())); connect(network, SIGNAL(destroyed()), @@ -112,6 +128,20 @@ void NetworkItem::attachIrcChannel(IrcChannel *ircChannel) { } } +void NetworkItem::attachIrcUser(IrcUser *ircUser) { + QueryBufferItem *queryItem = 0; + for(int i = 0; i < childCount(); i++) { + queryItem = qobject_cast(child(i)); + if(!queryItem) + continue; + + if(queryItem->bufferName().toLower() == ircUser->nick().toLower()) { + queryItem->attachIrcUser(ircUser); + break; + } + } +} + void NetworkItem::setNetworkName(const QString &networkName) { Q_UNUSED(networkName); emit dataChanged(0); @@ -130,6 +160,10 @@ QString NetworkItem::toolTip(int column) const { toolTip.append(QString("Server: %1").arg(currentServer())); toolTip.append(QString("Users: %1").arg(nickCount())); + if(_network) { + toolTip.append(QString("Lag: %1 msecs").arg(_network->latency())); + } + return QString("

%1

").arg(toolTip.join("
")); } @@ -247,21 +281,73 @@ QString StatusBufferItem::toolTip(int column) const { * QueryBufferItem *****************************************/ QueryBufferItem::QueryBufferItem(const BufferInfo &bufferInfo, NetworkItem *parent) - : BufferItem(bufferInfo, parent) + : BufferItem(bufferInfo, parent), + _ircUser(0) { setFlags(flags() | Qt::ItemIsDropEnabled); + + const Network *net = Client::network(bufferInfo.networkId()); + if(!net) + return; + + IrcUser *ircUser = net->ircUser(bufferInfo.bufferName()); + if(ircUser) + attachIrcUser(ircUser); + +} + +bool QueryBufferItem::isActive() const { + if(_ircUser) + return !_ircUser->isAway(); + else + return false; } QString QueryBufferItem::toolTip(int column) const { + // pretty much code duplication of IrcUserItem::toolTip() but inheritance won't solve this... Q_UNUSED(column); QStringList toolTip; toolTip.append(tr("Query with %1").arg(bufferName())); - if(topic() != "") { - toolTip.append(tr("Away Message: %1").arg(topic())); + + if(_ircUser) { + if(_ircUser->userModes() != "") toolTip[0].append(QString(" (%1)").arg(_ircUser->userModes())); + if(_ircUser->isAway()) { + toolTip[0].append(QString(" (away%1)").arg(!_ircUser->awayMessage().isEmpty() ? (QString(" ") + _ircUser->awayMessage()) : QString())); + } + if(!_ircUser->realName().isEmpty()) toolTip.append(_ircUser->realName()); + if(!_ircUser->ircOperator().isEmpty()) toolTip.append(QString("%1 %2").arg(_ircUser->nick()).arg(_ircUser->ircOperator())); + if(!_ircUser->suserHost().isEmpty()) toolTip.append(_ircUser->suserHost()); + if(!_ircUser->whoisServiceReply().isEmpty()) toolTip.append(_ircUser->whoisServiceReply()); + + toolTip.append(_ircUser->hostmask().remove(0, _ircUser->hostmask().indexOf("!")+1)); + + if(_ircUser->idleTime().isValid()) { + QDateTime now = QDateTime::currentDateTime(); + QDateTime idle = _ircUser->idleTime(); + int idleTime = idle.secsTo(now); + toolTip.append(tr("idling since %1").arg(secondsToString(idleTime))); + } + if(_ircUser->loginTime().isValid()) { + toolTip.append(tr("login time: %1").arg(_ircUser->loginTime().toString())); + } + + if(!_ircUser->server().isEmpty()) toolTip.append(tr("server: %1").arg(_ircUser->server())); } - return tr("

%1

").arg(toolTip.join("
")); + return QString("

%1

").arg(toolTip.join("
")); +} + +void QueryBufferItem::attachIrcUser(IrcUser *ircUser) { + _ircUser = ircUser; + connect(_ircUser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed())); + connect(_ircUser, SIGNAL(awaySet(bool)), this, SIGNAL(dataChanged())); + emit dataChanged(); +} + +void QueryBufferItem::ircUserDestroyed() { + _ircUser = 0; + emit dataChanged(); } /***************************************** @@ -271,6 +357,13 @@ ChannelBufferItem::ChannelBufferItem(const BufferInfo &bufferInfo, AbstractTreeI : BufferItem(bufferInfo, parent), _ircChannel(0) { + const Network *net = Client::network(bufferInfo.networkId()); + if(!net) + return; + + IrcChannel *ircChannel = net->ircChannel(bufferInfo.bufferName()); + if(ircChannel) + attachIrcChannel(ircChannel); } QString ChannelBufferItem::toolTip(int column) const { @@ -325,10 +418,8 @@ void ChannelBufferItem::attachIrcChannel(IrcChannel *ircChannel) { connect(ircChannel, SIGNAL(ircUserModeRemoved(IrcUser *, QString)), this, SLOT(userModeChanged(IrcUser *))); - if(!ircChannel->ircUsers().isEmpty()) { - qWarning() << "Channel" << ircChannel->name() << "has already users which is quite surprising :)"; + if(!ircChannel->ircUsers().isEmpty()) join(ircChannel->ircUsers()); - } emit dataChanged(); } @@ -341,23 +432,22 @@ void ChannelBufferItem::ircChannelDestroyed() { removeAllChilds(); } -void ChannelBufferItem::ircUserDestroyed() { - // PRIVATE - IrcUser *ircUser = static_cast(sender()); - removeUserFromCategory(ircUser); - emit dataChanged(2); -} - void ChannelBufferItem::join(const QList &ircUsers) { addUsersToCategory(ircUsers); + emit dataChanged(2); +} - foreach(IrcUser *ircUser, ircUsers) { - if(!ircUser) +UserCategoryItem *ChannelBufferItem::findCategoryItem(int categoryId) { + UserCategoryItem *categoryItem = 0; + + for(int i = 0; i < childCount(); i++) { + categoryItem = qobject_cast(child(i)); + if(!categoryItem) continue; - connect(ircUser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed())); + if(categoryItem->categoryId() == categoryId) + return categoryItem; } - - emit dataChanged(2); + return 0; } void ChannelBufferItem::addUserToCategory(IrcUser *ircUser) { @@ -374,7 +464,7 @@ void ChannelBufferItem::addUsersToCategory(const QList &ircUsers) { foreach(IrcUser *ircUser, ircUsers) { categoryId = UserCategoryItem::categoryFromModes(_ircChannel->userModes(ircUser)); - categoryItem = qobject_cast(childById(qHash(categoryId))); + categoryItem = findCategoryItem(categoryId); if(!categoryItem) { categoryItem = new UserCategoryItem(categoryId, this); categories[categoryItem] = QList(); @@ -424,22 +514,25 @@ void ChannelBufferItem::userModeChanged(IrcUser *ircUser) { Q_ASSERT(_ircChannel); int categoryId = UserCategoryItem::categoryFromModes(_ircChannel->userModes(ircUser)); - UserCategoryItem *categoryItem = qobject_cast(childById(qHash(categoryId))); + UserCategoryItem *categoryItem = findCategoryItem(categoryId); if(categoryItem) { - if(categoryItem->childById(qHash(ircUser))) + if(categoryItem->findIrcUser(ircUser)) { return; // already in the right category; + } } else { categoryItem = new UserCategoryItem(categoryId, this); newChild(categoryItem); } // find the item that needs reparenting + UserCategoryItem *oldCategoryItem = 0; IrcUserItem *ircUserItem = 0; for(int i = 0; i < childCount(); i++) { - UserCategoryItem *categoryItem = qobject_cast(child(i)); - IrcUserItem *userItem = qobject_cast(categoryItem->childById(qHash(ircUser))); + UserCategoryItem *catItem = qobject_cast(child(i)); + IrcUserItem *userItem = catItem->findIrcUser(ircUser); if(userItem) { + oldCategoryItem = catItem; ircUserItem = userItem; break; } @@ -449,7 +542,11 @@ void ChannelBufferItem::userModeChanged(IrcUser *ircUser) { qWarning() << "ChannelBufferItem::userModeChanged(IrcUser *): unable to determine old category of" << ircUser; return; } - ircUserItem->reParent(categoryItem); + + Q_ASSERT(oldCategoryItem); + if(ircUserItem->reParent(categoryItem) && oldCategoryItem->childCount() == 0) { + removeChild(oldCategoryItem); + } } /***************************************** @@ -463,6 +560,7 @@ UserCategoryItem::UserCategoryItem(int category, AbstractTreeItem *parent) : PropertyMapItem(QStringList() << "categoryName", parent), _category(category) { + setObjectName(parent->data(0, Qt::DisplayRole).toString() + "/" + QString::number(category)); } // caching this makes no sense, since we display the user number dynamically @@ -478,8 +576,17 @@ QString UserCategoryItem::categoryName() const { } } -quint64 UserCategoryItem::id() const { - return qHash(_category); +IrcUserItem *UserCategoryItem::findIrcUser(IrcUser *ircUser) { + IrcUserItem *userItem = 0; + + for(int i = 0; i < childCount(); i++) { + userItem = qobject_cast(child(i)); + if(!userItem) + continue; + if(userItem->ircUser() == ircUser) + return userItem; + } + return 0; } void UserCategoryItem::addUsers(const QList &ircUsers) { @@ -491,9 +598,12 @@ void UserCategoryItem::addUsers(const QList &ircUsers) { } bool UserCategoryItem::removeUser(IrcUser *ircUser) { - bool success = removeChildById(qHash(ircUser)); - if(success) + IrcUserItem *userItem = findIrcUser(ircUser); + bool success = (bool)userItem; + if(success) { + removeChild(userItem); emit dataChanged(0); + } return success; } @@ -530,30 +640,12 @@ QVariant UserCategoryItem::data(int column, int role) const { *****************************************/ IrcUserItem::IrcUserItem(IrcUser *ircUser, AbstractTreeItem *parent) : PropertyMapItem(QStringList() << "nickName", parent), - _ircUser(ircUser), - _id(qHash(ircUser)) + _ircUser(ircUser) { - // we don't need to handle the ircUser's destroyed signal since it's automatically removed - // by the IrcChannel::ircUserParted(); - - connect(ircUser, SIGNAL(nickSet(QString)), - this, SLOT(setNick(QString))); - connect(ircUser, SIGNAL(awaySet(bool)), - this, SLOT(setAway(bool))); -} - -QString IrcUserItem::nickName() const { - if(_ircUser) - return _ircUser->nick(); - else - return QString(); -} - -bool IrcUserItem::isActive() const { - if(_ircUser) - return !_ircUser->isAway(); - else - return false; + setObjectName(ircUser->nick()); + connect(ircUser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed())); + connect(ircUser, SIGNAL(nickSet(QString)), this, SIGNAL(dataChanged())); + connect(ircUser, SIGNAL(awaySet(bool)), this, SIGNAL(dataChanged())); } QVariant IrcUserItem::data(int column, int role) const { @@ -604,16 +696,6 @@ QString IrcUserItem::toolTip(int column) const { return QString("

%1

").arg(toolTip.join("
")); } -void IrcUserItem::setNick(QString newNick) { - Q_UNUSED(newNick); - emit dataChanged(0); -} - -void IrcUserItem::setAway(bool away) { - Q_UNUSED(away); - emit dataChanged(0); -} - /***************************************** * NetworkModel *****************************************/ @@ -639,49 +721,78 @@ Buffer *NetworkModel::getBufferByIndex(const QModelIndex &index) const { } */ +int NetworkModel::networkRow(NetworkId networkId) { + NetworkItem *netItem = 0; + for(int i = 0; i < rootItem->childCount(); i++) { + netItem = qobject_cast(rootItem->child(i)); + if(!netItem) + continue; + if(netItem->networkId() == networkId) + return i; + } + return -1; +} -// experimental stuff :) QModelIndex NetworkModel::networkIndex(NetworkId networkId) { - return indexById(qHash(networkId)); + int netRow = networkRow(networkId); + if(netRow == -1) + return QModelIndex(); + else + return indexByItem(qobject_cast(rootItem->child(netRow))); } -NetworkItem *NetworkModel::existsNetworkItem(NetworkId networkId) { - return qobject_cast(rootItem->childById(networkId.toInt())); +NetworkItem *NetworkModel::findNetworkItem(NetworkId networkId) { + int netRow = networkRow(networkId); + if(netRow == -1) + return 0; + else + return qobject_cast(rootItem->child(netRow)); } NetworkItem *NetworkModel::networkItem(NetworkId networkId) { - NetworkItem *netItem = existsNetworkItem(networkId); + NetworkItem *netItem = findNetworkItem(networkId); if(netItem == 0) { netItem = new NetworkItem(networkId, rootItem); rootItem->newChild(netItem); } - - Q_ASSERT(netItem); return netItem; } void NetworkModel::networkRemoved(const NetworkId &networkId) { - rootItem->removeChildById(qHash(networkId)); + int netRow = networkRow(networkId); + if(netRow != -1) { + rootItem->removeChild(netRow); + } } QModelIndex NetworkModel::bufferIndex(BufferId bufferId) { - AbstractTreeItem *netItem, *bufferItem; - for(int i = 0; i < rootItem->childCount(); i++) { - netItem = rootItem->child(i); - if((bufferItem = netItem->childById(qHash(bufferId)))) { - return indexByItem(bufferItem); - } - } - return QModelIndex(); + BufferItem *bufferItem = findBufferItem(bufferId); + if(bufferItem) + return indexByItem(bufferItem); + else + return QModelIndex(); } -BufferItem *NetworkModel::existsBufferItem(const BufferInfo &bufferInfo) { - QModelIndex bufferIdx = bufferIndex(bufferInfo.bufferId()); - if(bufferIdx.isValid()) - return static_cast(bufferIdx.internalPointer()); - else +BufferItem *NetworkModel::findBufferItem(const BufferInfo &bufferInfo) { + NetworkItem *netItem = findNetworkItem(bufferInfo.networkId()); + if(!netItem) return 0; + + BufferItem *bufferItem = netItem->findBufferItem(bufferInfo); + return bufferItem; +} + +BufferItem *NetworkModel::findBufferItem(BufferId bufferId) { + NetworkItem *netItem; + BufferItem *bufferItem; + + for(int i = 0; i < rootItem->childCount(); i++) { + netItem = qobject_cast(rootItem->child(i)); + if((bufferItem = netItem->findBufferItem(bufferId))) + return bufferItem; + } + return 0; } BufferItem *NetworkModel::bufferItem(const BufferInfo &bufferInfo) { @@ -765,13 +876,15 @@ bool NetworkModel::dropMimeData(const QMimeData *data, Qt::DropAction action, in // no self merges (would kill us) if(bufferId == parent.data(BufferIdRole).value()) return false; - - Q_ASSERT(rootItem->childById(qHash(netId))); - Q_ASSERT(rootItem->childById(qHash(netId))->childById(qHash(bufferId))); + + NetworkItem *netItem = findNetworkItem(netId); + Q_ASSERT(netItem); + + BufferItem *bufferItem = netItem->findBufferItem(bufferId); + Q_ASSERT(bufferItem); // source must be a query too - BufferInfo::Type sourceType = (BufferInfo::Type)rootItem->childById(qHash(netId))->childById(qHash(bufferId))->data(0, BufferTypeRole).toInt(); - if(sourceType != BufferInfo::QueryBuffer) + if(bufferItem->bufferType() != BufferInfo::QueryBuffer) return false; // TODO: warn user about buffermerge! @@ -793,14 +906,9 @@ void NetworkModel::bufferUpdated(BufferInfo bufferInfo) { } void NetworkModel::removeBuffer(BufferId bufferId) { - const int numNetworks = rootItem->childCount(); - if(numNetworks == 0) - return; - - for(int i = 0; i < numNetworks; i++) { - if(rootItem->child(i)->removeChildById(qHash(bufferId))) - break; - } + BufferItem *bufferItem = findBufferItem(bufferId); + if(bufferItem) + bufferItem->parent()->removeChild(bufferItem); } /*