From 63e8840632d2eee3ad1632d1f7d7af3bcdad1503 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Thu, 4 Dec 2008 00:53:14 +0100 Subject: [PATCH] Adding nick context menu actions to NetworkModelActionProvider This gives you context menus in the nicklist as well as for query buffer items. --- src/client/quasselui.h | 9 +- src/uisupport/networkmodelactionprovider.cpp | 241 +++++++++++++++---- src/uisupport/networkmodelactionprovider.h | 66 ++--- 3 files changed, 237 insertions(+), 79 deletions(-) diff --git a/src/client/quasselui.h b/src/client/quasselui.h index e6e38591..372df3c6 100644 --- a/src/client/quasselui.h +++ b/src/client/quasselui.h @@ -66,10 +66,11 @@ class AbstractActionProvider : public QObject { AbstractActionProvider(QObject *parent = 0) : QObject(parent) {} virtual ~AbstractActionProvider() {} - virtual void addActions(QMenu *, const QModelIndex &index, QObject *receiver = 0, const char *method = 0, bool allowBufferHide = false) = 0; - virtual void addActions(QMenu *, const QList &indexList, QObject *receiver = 0, const char *method = 0, bool allowBufferHide = false) = 0; - virtual void addActions(QMenu *, BufferId id, QObject *receiver = 0, const char *method = 0) = 0; - virtual void addActions(QMenu *, MessageFilter *filter, QObject *receiver = 0, const char *method = 0) = 0; + virtual void addActions(QMenu *, const QModelIndex &index, QObject *receiver = 0, const char *slot = 0, bool allowBufferHide = false) = 0; + virtual void addActions(QMenu *, const QList &indexList, QObject *receiver = 0, const char *slot = 0, bool allowBufferHide = false) = 0; + virtual void addActions(QMenu *, BufferId id, QObject *receiver = 0, const char *slot = 0) = 0; + virtual void addActions(QMenu *, MessageFilter *filter, BufferId msgBuffer, QObject *receiver = 0, const char *slot = 0) = 0; + virtual void addActions(QMenu *, MessageFilter *filter, BufferId msgBuffer, const QString &chanOrNick, QObject *receiver = 0, const char *slot = 0) = 0; signals: void showChannelList(NetworkId); diff --git a/src/uisupport/networkmodelactionprovider.cpp b/src/uisupport/networkmodelactionprovider.cpp index 9d4c2d19..44dd460b 100644 --- a/src/uisupport/networkmodelactionprovider.cpp +++ b/src/uisupport/networkmodelactionprovider.cpp @@ -1,22 +1,22 @@ /*************************************************************************** -* Copyright (C) 2005-08 by the Quassel Project * -* 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) version 3. * -* * -* 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. * -***************************************************************************/ + * Copyright (C) 2005-08 by the Quassel Project * + * 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) version 3. * + * * + * 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 #include @@ -24,6 +24,7 @@ #include "networkmodelactionprovider.h" +#include "buffermodel.h" #include "buffersettings.h" #include "iconloader.h" #include "identity.h" @@ -41,6 +42,7 @@ NetworkModelActionProvider::NetworkModelActionProvider(QObject *parent) registerAction(BufferJoin, tr("Join")); registerAction(BufferPart, tr("Part")); registerAction(BufferRemove, tr("Delete Buffer...")); + registerAction(BufferSwitchTo, tr("Show Buffer")); registerAction(HideJoin, tr("Joins"), true); registerAction(HidePart, tr("Parts"), true); @@ -52,7 +54,10 @@ NetworkModelActionProvider::NetworkModelActionProvider(QObject *parent) registerAction(JoinChannel, tr("Join Channel...")); - registerAction(NickCtcpWhois, tr("Whois")); + registerAction(NickQuery, tr("Start Query")); + registerAction(NickSwitchTo, tr("Show Query")); + registerAction(NickWhois, tr("Whois")); + registerAction(NickCtcpVersion, tr("Version")); registerAction(NickCtcpTime, tr("Time")); registerAction(NickCtcpPing, tr("Ping")); @@ -65,7 +70,6 @@ NetworkModelActionProvider::NetworkModelActionProvider(QObject *parent) registerAction(NickKick, tr("Kick")); registerAction(NickBan, tr("Ban")); registerAction(NickKickBan, tr("Kickban")); - registerAction(NickQuery, tr("Query")); registerAction(HideBufferTemporarily, tr("Hide Buffer(s) Temporarily")); registerAction(HideBufferPermanently, tr("Hide Buffer(s) Permanently")); @@ -87,11 +91,31 @@ NetworkModelActionProvider::NetworkModelActionProvider(QObject *parent) hideEventsMenu->addAction(action(HideApplyToAll)); _hideEventsMenuAction = new Action(tr("Hide Events"), 0); _hideEventsMenuAction->setMenu(hideEventsMenu); + + QMenu *nickCtcpMenu = new QMenu(); + nickCtcpMenu->addAction(action(NickCtcpPing)); + nickCtcpMenu->addAction(action(NickCtcpVersion)); + nickCtcpMenu->addAction(action(NickCtcpTime)); + nickCtcpMenu->addAction(action(NickCtcpFinger)); + _nickCtcpMenuAction = new Action(tr("CTCP"), 0); + _nickCtcpMenuAction->setMenu(nickCtcpMenu); + + QMenu *nickModeMenu = new QMenu(); + nickModeMenu->addAction(action(NickOp)); + nickModeMenu->addAction(action(NickDeop)); + nickModeMenu->addAction(action(NickVoice)); + nickModeMenu->addAction(action(NickDevoice)); + _nickModeMenuAction = new Action(tr("Modes"), 0); + _nickModeMenuAction->setMenu(nickModeMenu); } NetworkModelActionProvider::~NetworkModelActionProvider() { _hideEventsMenuAction->menu()->deleteLater(); _hideEventsMenuAction->deleteLater(); + _nickCtcpMenuAction->menu()->deleteLater(); + _nickCtcpMenuAction->deleteLater(); + _nickModeMenuAction->menu()->deleteLater(); + _nickModeMenuAction->deleteLater(); } void NetworkModelActionProvider::registerAction(ActionType type, const QString &text, bool checkable) { @@ -116,26 +140,30 @@ void NetworkModelActionProvider::addActions(QMenu *menu, BufferId bufId, QObject if(!bufId.isValid()) return; _messageFilter = 0; + _contextItem = QString(); addActions(menu, Client::networkModel()->bufferIndex(bufId), receiver, method); } -void NetworkModelActionProvider::addActions(QMenu *menu, MessageFilter *filter, QObject *receiver, const char *method) { - if(!filter) - return; - _messageFilter = filter; - QList indexes; - foreach(BufferId bufId, filter->containedBuffers()) - indexes << Client::networkModel()->bufferIndex(bufId); - addActions(menu, indexes, receiver, method); -} - void NetworkModelActionProvider::addActions(QMenu *menu, const QModelIndex &index, QObject *receiver, const char *method, bool isCustomBufferView) { if(!index.isValid()) return; _messageFilter = 0; + _contextItem = QString(); addActions(menu, QList() << index, receiver, method, isCustomBufferView); } +void NetworkModelActionProvider::addActions(QMenu *menu, MessageFilter *filter, BufferId msgBuffer, QObject *receiver, const char *slot) { + addActions(menu, filter, msgBuffer, QString(), receiver, slot); +} + +void NetworkModelActionProvider::addActions(QMenu *menu, MessageFilter *filter, BufferId msgBuffer, const QString &chanOrNick, QObject *receiver, const char *method) { + if(!filter) + return; + _messageFilter = filter; + _contextItem = chanOrNick; + addActions(menu, QList() << Client::networkModel()->bufferIndex(msgBuffer), receiver, method); +} + // add a list of actions sensible for the current item(s) void NetworkModelActionProvider::addActions(QMenu *menu, const QList &indexList, @@ -164,15 +192,25 @@ void NetworkModelActionProvider::addActions(QMenu *menu, case NetworkModel::BufferItemType: addBufferItemActions(menu, index, isCustomBufferView); break; - + case NetworkModel::IrcUserItemType: + addIrcUserActions(menu, index); + break; default: return; } } else { // ChatView actions + if(_contextItem.isEmpty()) { + // a) query buffer: handle like ircuser + // b) general chatview: only react if _contextItem is set (i.e. we right-clicked on something) + // NOTE stuff breaks probably with merged buffers, need to rework a lot around here then + // for now, use the item type of a random buffer... assuming we never mix channel and query buffers + //if(!_messageFilter->containedBuffers.count()) + // return; + //BufferId randomBuf = _messageFilter->containedBuffers.values().at(0); - + } } } @@ -210,11 +248,11 @@ void NetworkModelActionProvider::addBufferItemActions(QMenu *menu, const QModelI case BufferInfo::QueryBuffer: { - IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); - if(ircUser) { - addIrcUserActions(menu, ircUser, false); + //IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); + //if(ircUser) { + addIrcUserActions(menu, index); menu->addSeparator(); - } + //} addHideEventsMenu(menu, bufferInfo.bufferId()); menu->addSeparator(); addAction(HideBufferTemporarily, menu, isCustomBufferView); @@ -229,9 +267,29 @@ void NetworkModelActionProvider::addBufferItemActions(QMenu *menu, const QModelI } } -void NetworkModelActionProvider::addIrcUserActions(QMenu *menu, IrcUser *ircUser, bool isNickView) { +void NetworkModelActionProvider::addIrcUserActions(QMenu *menu, const QModelIndex &index) { + // this can be called: a) as a nicklist context menu (index has IrcUserItemType) + // b) as a query buffer context menu (index has BufferItemType and is a QueryBufferItem) + // c) right-click in a query chatview (same as b), index will be the corresponding QueryBufferItem) + // d) right-click on some nickname (_contextItem will be non-null, _filter -> chatview, index -> message buffer) + if(_contextItem.isNull()) { + // cases a, b, c + bool haveQuery = findQueryBuffer(index).isValid(); + NetworkModel::ItemType itemType = static_cast(index.data(NetworkModel::ItemTypeRole).toInt()); + addAction(_nickModeMenuAction, menu, itemType == NetworkModel::IrcUserItemType); + addAction(_nickCtcpMenuAction, menu); + menu->addSeparator(); + addAction(NickQuery, menu, itemType == NetworkModel::IrcUserItemType && !haveQuery); + addAction(NickSwitchTo, menu, itemType == NetworkModel::IrcUserItemType && haveQuery); + menu->addSeparator(); + addAction(NickWhois, menu, true); + + } else if(!_contextItem.isEmpty() && _messageFilter) { + // case d + // TODO + } } /******** Helper Functions ***********************************************************************/ @@ -291,6 +349,42 @@ void NetworkModelActionProvider::addHideEventsMenu(QMenu *menu, int filter) { menu->addAction(_hideEventsMenuAction); } +QString NetworkModelActionProvider::nickName(const QModelIndex &index) const { + IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); + if(ircUser) + return ircUser->nick(); + + BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); + if(!bufferInfo.isValid()) + return QString(); + + return bufferInfo.bufferName(); // FIXME this might break with merged queries maybe +} + +BufferId NetworkModelActionProvider::findQueryBuffer(const QModelIndex &index, const QString &predefinedNick) const { + NetworkId networkId = _indexList.at(0).data(NetworkModel::NetworkIdRole).value(); + if(!networkId.isValid()) + return BufferId(); + + QString nick = predefinedNick.isEmpty() ? nickName(index) : predefinedNick; + if(nick.isEmpty()) + return BufferId(); + + return findQueryBuffer(networkId, nick); +} + +BufferId NetworkModelActionProvider::findQueryBuffer(NetworkId networkId, const QString &nick) const { + return Client::networkModel()->bufferId(networkId, nick); +} + +void NetworkModelActionProvider::handleExternalAction(ActionType type, QAction *action) { + Q_UNUSED(type); + if(_receiver && _method) { + if(!QMetaObject::invokeMethod(_receiver, _method, Q_ARG(QAction *, action))) + qWarning() << "NetworkModelActionProvider::handleExternalAction(): Could not invoke slot" << _receiver << _method; + } +} + /******** Handle Actions *************************************************************************/ void NetworkModelActionProvider::actionTriggered(QAction *action) { @@ -344,14 +438,17 @@ void NetworkModelActionProvider::handleBufferAction(ActionType type, QAction *) switch(type) { case BufferJoin: - Client::instance()->userInput(bufferInfo, QString("/JOIN %1").arg(bufferInfo.bufferName())); + Client::userInput(bufferInfo, QString("/JOIN %1").arg(bufferInfo.bufferName())); break; case BufferPart: { QString reason = Client::identity(Client::network(bufferInfo.networkId())->identity())->partReason(); - Client::instance()->userInput(bufferInfo, QString("/PART %1").arg(reason)); + Client::userInput(bufferInfo, QString("/PART %1").arg(reason)); break; } + case BufferSwitchTo: + Client::bufferModel()->switchToBuffer(bufferInfo.bufferId()); + break; case BufferRemove: { int res = QMessageBox::question(0, tr("Remove buffer permanently?"), @@ -386,6 +483,7 @@ void NetworkModelActionProvider::handleHideAction(ActionType type, QAction *acti msgType = Message::DayChange; break; case HideApplyToAll: // TODO implement "apply to all" for hiding messages + return; break; default: return; @@ -436,14 +534,63 @@ void NetworkModelActionProvider::handleGeneralAction(ActionType type, QAction *a } void NetworkModelActionProvider::handleNickAction(ActionType type, QAction *) { + if(!_indexList.count()) + return; + NetworkId networkId = _indexList.at(0).data(NetworkModel::NetworkIdRole).value(); + if(!networkId.isValid()) + return; + QString nick = nickName(_indexList.at(0)); + if(nick.isEmpty()) + return; + BufferInfo bufferInfo = _indexList.at(0).data(NetworkModel::BufferInfoRole).value(); + if(!bufferInfo.isValid()) + return; - -} - -void NetworkModelActionProvider::handleExternalAction(ActionType type, QAction *action) { - Q_UNUSED(type); - if(_receiver && _method) { - if(!QMetaObject::invokeMethod(_receiver, _method, Q_ARG(QAction *, action))) - qWarning() << "NetworkModelActionProvider::handleExternalAction(): Could not invoke slot" << _receiver << _method; + switch(type) { + case NickWhois: + Client::userInput(bufferInfo, QString("/WHOIS %1 %1").arg(nick)); + break; + case NickCtcpVersion: + Client::userInput(bufferInfo, QString("/CTCP %1 VERSION").arg(nick)); + break; + case NickCtcpPing: + Client::userInput(bufferInfo, QString("/CTCP %1 PING").arg(nick)); + break; + case NickCtcpTime: + Client::userInput(bufferInfo, QString("/CTCP %1 TIME").arg(nick)); + break; + case NickCtcpFinger: + Client::userInput(bufferInfo, QString("/CTCP %1 FINGER").arg(nick)); + break; + case NickOp: + Client::userInput(bufferInfo, QString("/OP %1").arg(nick)); + break; + case NickDeop: + Client::userInput(bufferInfo, QString("/DEOP %1").arg(nick)); + break; + case NickVoice: + Client::userInput(bufferInfo, QString("/VOICE %1").arg(nick)); + break; + case NickDevoice: + Client::userInput(bufferInfo, QString("/DEVOICE %1").arg(nick)); + break; + case NickKick: + Client::userInput(bufferInfo, QString("/KICK %1").arg(nick)); + break; + case NickBan: + Client::userInput(bufferInfo, QString("/BAN %1").arg(nick)); + break; + case NickKickBan: + Client::userInput(bufferInfo, QString("/BAN %1").arg(nick)); + Client::userInput(bufferInfo, QString("/KICK %1").arg(nick)); + break; + case NickSwitchTo: + Client::bufferModel()->switchToBuffer(findQueryBuffer(networkId, nick)); + break; + case NickQuery: + Client::userInput(bufferInfo, QString("/QUERY %1").arg(nick)); + break; + default: + qWarning() << "Unhandled nick action"; } } diff --git a/src/uisupport/networkmodelactionprovider.h b/src/uisupport/networkmodelactionprovider.h index 1dfa97ca..7f01d2fa 100644 --- a/src/uisupport/networkmodelactionprovider.h +++ b/src/uisupport/networkmodelactionprovider.h @@ -1,22 +1,22 @@ /*************************************************************************** -* Copyright (C) 2005-08 by the Quassel Project * -* 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) version 3. * -* * -* 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. * -***************************************************************************/ + * Copyright (C) 2005-08 by the Quassel Project * + * 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) version 3. * + * * + * 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 NETWORKMODELACTIONPROVIDER_H #define NETWORKMODELACTIONPROVIDER_H @@ -44,7 +44,8 @@ public: BufferMask = 0xf0, BufferJoin = 0x10, BufferPart = 0x20, - BufferRemove = 0x30, + BufferSwitchTo = 0x30, + BufferRemove = 0x40, // Hide actions HideMask = 0x0f00, @@ -64,11 +65,13 @@ public: // Nick actions NickMask = 0xff0000, - NickCtcpWhois = 0x010000, - NickCtcpVersion = 0x020000, - NickCtcpPing = 0x030000, - NickCtcpTime = 0x040000, - NickCtcpFinger = 0x050000, + NickWhois = 0x010000, + NickQuery = 0x020000, + NickSwitchTo = 0x030000, + NickCtcpVersion = 0x040000, + NickCtcpPing = 0x050000, + NickCtcpTime = 0x060000, + NickCtcpFinger = 0x070000, NickOp = 0x080000, NickDeop = 0x090000, NickVoice = 0x0a0000, @@ -76,7 +79,6 @@ public: NickKick = 0x0c0000, NickBan = 0x0d0000, NickKickBan = 0x0e0000, - NickQuery = 0x0f0000, // Actions that are handled externally // These emit a signal to the action requester, rather than being handled here @@ -102,7 +104,8 @@ public: void addActions(QMenu *, const QModelIndex &index, QObject *receiver = 0, const char *slot = 0, bool allowBufferHide = false); void addActions(QMenu *, const QList &indexList, QObject *receiver = 0, const char *slot = 0, bool allowBufferHide = false); void addActions(QMenu *, BufferId id, QObject *receiver = 0, const char *slot = 0); - void addActions(QMenu *, MessageFilter *filter, QObject *receiver = 0, const char *slot = 0); + void addActions(QMenu *, MessageFilter *filter, BufferId msgBuffer, QObject *receiver = 0, const char *slot = 0); + void addActions(QMenu *, MessageFilter *filter, BufferId msgBuffer, const QString &chanOrNick, QObject *receiver = 0, const char *slot = 0); signals: void showChannelList(NetworkId); @@ -117,7 +120,7 @@ protected slots: private: enum ItemActiveState { InactiveState = 0x01, - ActiveState = 0x02 + ActiveState = 0x02 }; public: @@ -146,7 +149,11 @@ private: void addNetworkItemActions(QMenu *, const QModelIndex &); void addBufferItemActions(QMenu *, const QModelIndex &, bool isCustomBufferView = false); - void addIrcUserActions(QMenu *, IrcUser *ircUser, bool isNickView = true); + void addIrcUserActions(QMenu *, const QModelIndex &); + + QString nickName(const QModelIndex &index) const; + BufferId findQueryBuffer(const QModelIndex &index, const QString &predefinedNick = QString()) const; + BufferId findQueryBuffer(NetworkId, const QString &nickName) const; NetworkModel *_model; @@ -154,9 +161,12 @@ private: QHash _actionByType; Action *_hideEventsMenuAction; + Action *_nickCtcpMenuAction; + Action *_nickModeMenuAction; QList _indexList; MessageFilter *_messageFilter; + QString _contextItem; ///< Channel name or nick to provide context menu for QObject *_receiver; const char *_method; }; -- 2.20.1