X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fuisupport%2Fcontextmenuactionprovider.cpp;h=79c9d19b0bd2df1f71e9d8389825d7cf4fd15c5e;hp=068b84cdbf4f1eb6f1cc0c728ccd62a0859d0a69;hb=e2188dc438be6f3eb0d9cdf47d28821aefe9835e;hpb=342b6d8a5869e438362914f3848e639ac6c70bbc diff --git a/src/uisupport/contextmenuactionprovider.cpp b/src/uisupport/contextmenuactionprovider.cpp index 068b84cd..79c9d19b 100644 --- a/src/uisupport/contextmenuactionprovider.cpp +++ b/src/uisupport/contextmenuactionprovider.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-09 by the Quassel Project * + * Copyright (C) 2005-2018 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -15,339 +15,512 @@ * 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. * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ +#include "contextmenuactionprovider.h" + #include #include #include - -#include "contextmenuactionprovider.h" +#include #include "buffermodel.h" #include "buffersettings.h" -#include "iconloader.h" -#include "clientidentity.h" +#include "client.h" +#include "clientignorelistmanager.h" +#include "icon.h" #include "network.h" #include "util.h" -ContextMenuActionProvider::ContextMenuActionProvider(QObject *parent) : NetworkModelController(parent) { - registerAction(NetworkConnect, SmallIcon("network-connect"), tr("Connect")); - registerAction(NetworkDisconnect, SmallIcon("network-disconnect"), tr("Disconnect")); - - registerAction(BufferJoin, SmallIcon("irc-join-channel"), tr("Join")); - registerAction(BufferPart, SmallIcon("irc-close-channel"), tr("Part")); - registerAction(BufferRemove, tr("Delete Buffer(s)...")); - registerAction(BufferSwitchTo, tr("Show Buffer")); - - registerAction(HideJoin, tr("Joins"), true); - registerAction(HidePart, tr("Parts"), true); - registerAction(HideQuit, tr("Quits"), true); - registerAction(HideNick, tr("Nick Changes"), true); - registerAction(HideMode, tr("Mode Changes"), true); - registerAction(HideDayChange, tr("Day Changes"), true); - registerAction(HideTopic, tr("Topic Changes"), true); - registerAction(HideApplyToAll, tr("Set as Default...")); - registerAction(HideUseDefaults, tr("Use Defaults...")); - - registerAction(JoinChannel, SmallIcon("irc-join-channel"), tr("Join Channel...")); - - 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")); - registerAction(NickCtcpFinger, tr("Finger")); - - registerAction(NickOp, SmallIcon("irc-operator"), tr("Give Operator Status")); - registerAction(NickDeop, SmallIcon("irc-remove-operator"), tr("Take Operator Status")); - registerAction(NickVoice, SmallIcon("irc-voice"), tr("Give Voice")); - registerAction(NickDevoice, SmallIcon("irc-unvoice"), tr("Take Voice")); - registerAction(NickKick, SmallIcon("im-kick-user"), tr("Kick From Channel")); - registerAction(NickBan, SmallIcon("im-ban-user"), tr("Ban From Channel")); - registerAction(NickKickBan, SmallIcon("im-ban-kick-user"), tr("Kick && Ban")); - - registerAction(HideBufferTemporarily, tr("Hide Buffer(s) Temporarily")); - registerAction(HideBufferPermanently, tr("Hide Buffer(s) Permanently")); - registerAction(ShowChannelList, tr("Show Channel List")); - registerAction(ShowIgnoreList, tr("Show Ignore List")); - - QMenu *hideEventsMenu = new QMenu(); - hideEventsMenu->addAction(action(HideJoin)); - hideEventsMenu->addAction(action(HidePart)); - hideEventsMenu->addAction(action(HideQuit)); - hideEventsMenu->addAction(action(HideNick)); - hideEventsMenu->addAction(action(HideMode)); - hideEventsMenu->addAction(action(HideTopic)); - hideEventsMenu->addAction(action(HideDayChange)); - hideEventsMenu->addSeparator(); - hideEventsMenu->addAction(action(HideApplyToAll)); - hideEventsMenu->addAction(action(HideUseDefaults)); - _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)); - nickModeMenu->addSeparator(); - nickModeMenu->addAction(action(NickKick)); - nickModeMenu->addAction(action(NickBan)); - nickModeMenu->addAction(action(NickKickBan)); - _nickModeMenuAction = new Action(tr("Actions"), 0); - _nickModeMenuAction->setMenu(nickModeMenu); +ContextMenuActionProvider::ContextMenuActionProvider(QObject *parent) : NetworkModelController(parent) +{ + registerAction(NetworkConnect, icon::get("network-connect"), tr("Connect")); + registerAction(NetworkDisconnect, icon::get("network-disconnect"), tr("Disconnect")); + + registerAction(BufferJoin, icon::get("irc-join-channel"), tr("Join")); + registerAction(BufferPart, icon::get("irc-close-channel"), tr("Part")); + registerAction(BufferRemove, tr("Delete Chat(s)...")); + registerAction(BufferSwitchTo, tr("Go to Chat")); + + registerAction(HideJoinPartQuit, tr("Joins/Parts/Quits")); + registerAction(HideJoin, tr("Joins"), true); + registerAction(HidePart, tr("Parts"), true); + registerAction(HideQuit, tr("Quits"), true); + registerAction(HideNick, tr("Nick Changes"), true); + registerAction(HideMode, tr("Mode Changes"), true); + registerAction(HideDayChange, tr("Day Changes"), true); + registerAction(HideTopic, tr("Topic Changes"), true); + registerAction(HideApplyToAll, tr("Set as Default...")); + registerAction(HideUseDefaults, tr("Use Defaults...")); + + registerAction(JoinChannel, icon::get("irc-join-channel"), tr("Join Channel...")); + + 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")); + registerAction(NickCtcpClientinfo, tr("Client info")); + registerAction(NickIgnoreCustom, tr("Custom...")); + + // these texts are only dummies! don't think about tr() here! + registerAction(NickIgnoreUser, "*!ident@host.domain.tld"); + registerAction(NickIgnoreHost, "*!*@host.domain.tld"); + registerAction(NickIgnoreDomain, "*!ident@*.domain.tld"); + registerAction(NickIgnoreToggleEnabled0, "Enable", true); + registerAction(NickIgnoreToggleEnabled1, "Enable", true); + registerAction(NickIgnoreToggleEnabled2, "Enable", true); + registerAction(NickIgnoreToggleEnabled3, "Enable", true); + registerAction(NickIgnoreToggleEnabled4, "Enable", true); + + registerAction(NickOp, icon::get("irc-operator"), tr("Give Operator Status")); + registerAction(NickDeop, icon::get("irc-remove-operator"), tr("Take Operator Status")); + registerAction(NickHalfop, icon::get("irc-voice"), tr("Give Half-Operator Status")); + registerAction(NickDehalfop, icon::get("irc-unvoice"), tr("Take Half-Operator Status")); + registerAction(NickVoice, icon::get("irc-voice"), tr("Give Voice")); + registerAction(NickDevoice, icon::get("irc-unvoice"), tr("Take Voice")); + registerAction(NickKick, icon::get("im-kick-user"), tr("Kick From Channel")); + registerAction(NickBan, icon::get("im-ban-user"), tr("Ban From Channel")); + registerAction(NickKickBan, icon::get("im-ban-kick-user"), tr("Kick && Ban")); + + registerAction(HideBufferTemporarily, tr("Hide Chat(s) Temporarily")); + registerAction(HideBufferPermanently, tr("Hide Chat(s) Permanently")); + registerAction(ShowChannelList, tr("Show Channel List")); + registerAction(ShowNetworkConfig, tr("Configure")); + registerAction(ShowIgnoreList, tr("Show Ignore List")); + + auto *hideEventsMenu = new QMenu(); + hideEventsMenu->addAction(action(HideJoinPartQuit)); + hideEventsMenu->addSeparator(); + hideEventsMenu->addAction(action(HideJoin)); + hideEventsMenu->addAction(action(HidePart)); + hideEventsMenu->addAction(action(HideQuit)); + hideEventsMenu->addAction(action(HideNick)); + hideEventsMenu->addAction(action(HideMode)); + hideEventsMenu->addAction(action(HideTopic)); + hideEventsMenu->addAction(action(HideDayChange)); + hideEventsMenu->addSeparator(); + hideEventsMenu->addAction(action(HideApplyToAll)); + hideEventsMenu->addAction(action(HideUseDefaults)); + _hideEventsMenuAction = new Action(tr("Hide Events"), nullptr); + _hideEventsMenuAction->setMenu(hideEventsMenu); + + auto *nickCtcpMenu = new QMenu(); + nickCtcpMenu->addAction(action(NickCtcpPing)); + nickCtcpMenu->addAction(action(NickCtcpVersion)); + nickCtcpMenu->addAction(action(NickCtcpTime)); + nickCtcpMenu->addAction(action(NickCtcpClientinfo)); + _nickCtcpMenuAction = new Action(tr("CTCP"), nullptr); + _nickCtcpMenuAction->setMenu(nickCtcpMenu); + + auto *nickModeMenu = new QMenu(); + nickModeMenu->addAction(action(NickOp)); + nickModeMenu->addAction(action(NickDeop)); + // this is where the halfops will be placed if available + nickModeMenu->addAction(action(NickHalfop)); + nickModeMenu->addAction(action(NickDehalfop)); + nickModeMenu->addAction(action(NickVoice)); + nickModeMenu->addAction(action(NickDevoice)); + nickModeMenu->addSeparator(); + nickModeMenu->addAction(action(NickKick)); + nickModeMenu->addAction(action(NickBan)); + nickModeMenu->addAction(action(NickKickBan)); + _nickModeMenuAction = new Action(tr("Actions"), nullptr); + _nickModeMenuAction->setMenu(nickModeMenu); + + auto *ignoreMenu = new QMenu(); + _nickIgnoreMenuAction = new Action(tr("Ignore"), nullptr); + _nickIgnoreMenuAction->setMenu(ignoreMenu); + + // These are disabled actions used as descriptions + // They don't need any of the Action fancyness so we use plain QActions + _ignoreDescriptions << new QAction(tr("Add Ignore Rule"), this); + _ignoreDescriptions << new QAction(tr("Existing Rules"), this); + foreach(QAction *act, _ignoreDescriptions) + act->setEnabled(false); } -ContextMenuActionProvider::~ContextMenuActionProvider() { - _hideEventsMenuAction->menu()->deleteLater(); - _hideEventsMenuAction->deleteLater(); - _nickCtcpMenuAction->menu()->deleteLater(); - _nickCtcpMenuAction->deleteLater(); - _nickModeMenuAction->menu()->deleteLater(); - _nickModeMenuAction->deleteLater(); -} -void ContextMenuActionProvider::addActions(QMenu *menu, BufferId bufId, QObject *receiver, const char *method) { - if(!bufId.isValid()) - return; - addActions(menu, Client::networkModel()->bufferIndex(bufId), receiver, method); +ContextMenuActionProvider::~ContextMenuActionProvider() +{ + _hideEventsMenuAction->menu()->deleteLater(); + _hideEventsMenuAction->deleteLater(); + _nickCtcpMenuAction->menu()->deleteLater(); + _nickCtcpMenuAction->deleteLater(); + _nickModeMenuAction->menu()->deleteLater(); + _nickModeMenuAction->deleteLater(); + _nickIgnoreMenuAction->menu()->deleteLater(); + _nickIgnoreMenuAction->deleteLater(); + qDeleteAll(_ignoreDescriptions); + _ignoreDescriptions.clear(); } -void ContextMenuActionProvider::addActions(QMenu *menu, const QModelIndex &index, QObject *receiver, const char *method, bool isCustomBufferView) { - if(!index.isValid()) - return; - addActions(menu, QList() << index, 0, QString(), receiver, method, isCustomBufferView); -} -void ContextMenuActionProvider::addActions(QMenu *menu, MessageFilter *filter, BufferId msgBuffer, QObject *receiver, const char *slot) { - addActions(menu, filter, msgBuffer, QString(), receiver, slot); +void ContextMenuActionProvider::addActions(QMenu *menu, BufferId bufId, QObject *receiver, const char *method) +{ + if (!bufId.isValid()) + return; + addActions(menu, Client::networkModel()->bufferIndex(bufId), receiver, method); } -void ContextMenuActionProvider::addActions(QMenu *menu, MessageFilter *filter, BufferId msgBuffer, const QString &chanOrNick, QObject *receiver, const char *method) { - if(!filter) - return; - addActions(menu, QList() << Client::networkModel()->bufferIndex(msgBuffer), filter, chanOrNick, receiver, method, false); + +void ContextMenuActionProvider::addActions(QMenu *menu, const QModelIndex &index, QObject *receiver, const char *method, bool isCustomBufferView) +{ + if (!index.isValid()) + return; + addActions(menu, QList() << index, nullptr, QString(), receiver, method, isCustomBufferView); } -void ContextMenuActionProvider::addActions(QMenu *menu, const QList &indexList, QObject *receiver, const char *method, bool isCustomBufferView) { - addActions(menu, indexList, 0, QString(), receiver, method, isCustomBufferView); + +void ContextMenuActionProvider::addActions(QMenu *menu, MessageFilter *filter, BufferId msgBuffer, QObject *receiver, const char *slot) +{ + addActions(menu, filter, msgBuffer, QString(), receiver, slot); } -// add a list of actions sensible for the current item(s) -void ContextMenuActionProvider::addActions(QMenu *menu, - const QList &indexList_, - MessageFilter *filter_, - const QString &contextItem_, - QObject *receiver_, - const char *method_, - bool isCustomBufferView) + +void ContextMenuActionProvider::addActions(QMenu *menu, MessageFilter *filter, BufferId msgBuffer, const QString &chanOrNick, QObject *receiver, const char *method) { - if(!indexList_.count()) - return; + if (!filter) + return; + addActions(menu, QList() << Client::networkModel()->bufferIndex(msgBuffer), filter, chanOrNick, receiver, method, false); +} - setIndexList(indexList_); - setMessageFilter(filter_); - setContextItem(contextItem_); - setSlot(receiver_, method_); - if(!messageFilter()) { - // this means we are in a BufferView (or NickView) rather than a ChatView +void ContextMenuActionProvider::addActions(QMenu *menu, const QList &indexList, QObject *receiver, const char *method, bool isCustomBufferView) +{ + addActions(menu, indexList, nullptr, QString(), receiver, method, isCustomBufferView); +} - // first index in list determines the menu type (just in case we have both buffers and networks selected, for example) - QModelIndex index = indexList().at(0); - NetworkModel::ItemType itemType = static_cast(index.data(NetworkModel::ItemTypeRole).toInt()); - switch(itemType) { - case NetworkModel::NetworkItemType: - addNetworkItemActions(menu, index); - break; - case NetworkModel::BufferItemType: - addBufferItemActions(menu, index, isCustomBufferView); - break; - case NetworkModel::IrcUserItemType: - addIrcUserActions(menu, index); - break; - default: +// add a list of actions sensible for the current item(s) +void ContextMenuActionProvider::addActions(QMenu *menu, + const QList &indexList_, + MessageFilter *filter_, + const QString &contextItem_, + QObject *receiver_, + const char *method_, + bool isCustomBufferView) +{ + if (!indexList_.count()) return; + setIndexList(indexList_); + setMessageFilter(filter_); + setContextItem(contextItem_); + setSlot(receiver_, method_); + + if (!messageFilter()) { + // this means we are in a BufferView (or NickView) rather than a ChatView + + // first index in list determines the menu type (just in case we have both buffers and networks selected, for example) + QModelIndex index = indexList().at(0); + NetworkModel::ItemType itemType = static_cast(index.data(NetworkModel::ItemTypeRole).toInt()); + + switch (itemType) { + case NetworkModel::NetworkItemType: + addNetworkItemActions(menu, index); + break; + 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: handle like channel iff it displays a single buffer - // NOTE stuff breaks probably with merged buffers, need to rework a lot around here then - if(messageFilter()->containedBuffers().count() == 1) { - // we can handle this like a single bufferItem - QModelIndex index = Client::networkModel()->bufferIndex(messageFilter()->containedBuffers().values().at(0)); - setIndexList(index); - addBufferItemActions(menu, index); - return; - } else { - // TODO: actions for merged buffers... _indexList contains the index of the message we clicked on - - } - } else { - // context item = chan or nick, _indexList = buf where the msg clicked on originated - if(isChannelName(contextItem())) { - QModelIndex msgIdx = indexList().at(0); - if(!msgIdx.isValid()) - return; - NetworkId networkId = msgIdx.data(NetworkModel::NetworkIdRole).value(); - BufferId bufId = Client::networkModel()->bufferId(networkId, contextItem()); - if(bufId.isValid()) { - QModelIndex targetIdx = Client::networkModel()->bufferIndex(bufId); - setIndexList(targetIdx); - addAction(BufferJoin, menu, targetIdx, InactiveState); - addAction(BufferSwitchTo, menu, targetIdx, ActiveState); - } else - addAction(JoinChannel, menu); - } else { - // TODO: actions for a nick - } + else { + // ChatView actions + if (contextItem().isEmpty()) { + // a) query buffer: handle like ircuser + // b) general chatview: handle like channel iff it displays a single buffer + // NOTE stuff breaks probably with merged buffers, need to rework a lot around here then + if (messageFilter()->containedBuffers().count() == 1) { + // we can handle this like a single bufferItem + QModelIndex index = Client::networkModel()->bufferIndex(messageFilter()->containedBuffers().values().at(0)); + setIndexList(index); + addBufferItemActions(menu, index); + return; + } + else { + // TODO: actions for merged buffers... _indexList contains the index of the message we clicked on + } + } + else { + // context item = chan or nick, _indexList = buf where the msg clicked on originated + if (isChannelName(contextItem())) { + QModelIndex msgIdx = indexList().at(0); + if (!msgIdx.isValid()) + return; + NetworkId networkId = msgIdx.data(NetworkModel::NetworkIdRole).value(); + BufferId bufId = Client::networkModel()->bufferId(networkId, contextItem()); + if (bufId.isValid()) { + QModelIndex targetIdx = Client::networkModel()->bufferIndex(bufId); + setIndexList(targetIdx); + addAction(BufferJoin, menu, targetIdx, InactiveState); + addAction(BufferSwitchTo, menu, targetIdx, ActiveState); + } + else + addAction(JoinChannel, menu); + } + else { + // TODO: actions for a nick + } + } } - } } -void ContextMenuActionProvider::addNetworkItemActions(QMenu *menu, const QModelIndex &index) { - NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); - if(!networkId.isValid()) - return; - const Network *network = Client::network(networkId); - Q_CHECK_PTR(network); - if(!network) - return; - - addAction(NetworkConnect, menu, network->connectionState() == Network::Disconnected); - addAction(NetworkDisconnect, menu, network->connectionState() != Network::Disconnected); - menu->addSeparator(); - addAction(ShowChannelList, menu, index, ActiveState); - addAction(JoinChannel, menu, index, ActiveState); +void ContextMenuActionProvider::addNetworkItemActions(QMenu *menu, const QModelIndex &index) +{ + NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); + if (!networkId.isValid()) + return; + const Network *network = Client::network(networkId); + Q_CHECK_PTR(network); + if (!network) + return; + + addAction(ShowNetworkConfig, menu, index); + menu->addSeparator(); + addAction(NetworkConnect, menu, network->connectionState() == Network::Disconnected); + addAction(NetworkDisconnect, menu, network->connectionState() != Network::Disconnected); + menu->addSeparator(); + addAction(ShowChannelList, menu, index, ActiveState); + addAction(JoinChannel, menu, index, ActiveState); } -void ContextMenuActionProvider::addBufferItemActions(QMenu *menu, const QModelIndex &index, bool isCustomBufferView) { - BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); - menu->addSeparator(); - switch(bufferInfo.type()) { +void ContextMenuActionProvider::addBufferItemActions(QMenu *menu, const QModelIndex &index, bool isCustomBufferView) +{ + BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); + + menu->addSeparator(); + switch (bufferInfo.type()) { case BufferInfo::ChannelBuffer: - addAction(BufferJoin, menu, index, InactiveState); - addAction(BufferPart, menu, index, ActiveState); - menu->addSeparator(); - addHideEventsMenu(menu, bufferInfo.bufferId()); - menu->addSeparator(); - addAction(HideBufferTemporarily, menu, isCustomBufferView); - addAction(HideBufferPermanently, menu, isCustomBufferView); - addAction(BufferRemove, menu, index, InactiveState); - break; + addAction(BufferJoin, menu, index, InactiveState); + addAction(BufferPart, menu, index, ActiveState); + menu->addSeparator(); + addHideEventsMenu(menu, bufferInfo.bufferId()); + menu->addSeparator(); + addAction(HideBufferTemporarily, menu, isCustomBufferView); + addAction(HideBufferPermanently, menu, isCustomBufferView); + addAction(BufferRemove, menu, index, InactiveState); + break; case BufferInfo::QueryBuffer: { - //IrcUser *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); - //if(ircUser) { + //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); - addAction(HideBufferPermanently, menu, isCustomBufferView); - addAction(BufferRemove, menu, index); - break; + //} + addHideEventsMenu(menu, bufferInfo.bufferId()); + menu->addSeparator(); + addAction(HideBufferTemporarily, menu, isCustomBufferView); + addAction(HideBufferPermanently, menu, isCustomBufferView); + addAction(BufferRemove, menu, index); + break; } default: - addAction(HideBufferTemporarily, menu, isCustomBufferView); - addAction(HideBufferPermanently, menu, isCustomBufferView); - } + addAction(HideBufferTemporarily, menu, isCustomBufferView); + addAction(HideBufferPermanently, menu, isCustomBufferView); + } } -void ContextMenuActionProvider::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 = indexList().count() == 1 && 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 && indexList().count() == 1); - addAction(NickSwitchTo, menu, itemType == NetworkModel::IrcUserItemType && haveQuery); - menu->addSeparator(); - addAction(NickWhois, menu, true); - } else if(!contextItem().isEmpty() && messageFilter()) { - // case d - // TODO +void ContextMenuActionProvider::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 = indexList().count() == 1 && findQueryBuffer(index).isValid(); + NetworkModel::ItemType itemType = static_cast(index.data(NetworkModel::ItemTypeRole).toInt()); + addAction(_nickModeMenuAction, menu, itemType == NetworkModel::IrcUserItemType); + addAction(_nickCtcpMenuAction, menu); + + auto *ircUser = qobject_cast(index.data(NetworkModel::IrcUserRole).value()); + if (ircUser) { + Network *network = ircUser->network(); + // only show entries for usermode +h if server supports it + if (network && network->prefixModes().contains('h')) { + action(NickHalfop)->setVisible(true); + action(NickDehalfop)->setVisible(true); + } + else { + action(NickHalfop)->setVisible(false); + action(NickDehalfop)->setVisible(false); + } + // ignoreliststuff + QString bufferName; + BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); + if (bufferInfo.type() == BufferInfo::ChannelBuffer) + bufferName = bufferInfo.bufferName(); + QMap ignoreMap = Client::ignoreListManager()->matchingRulesForHostmask(ircUser->hostmask(), ircUser->network()->networkName(), bufferName); + addIgnoreMenu(menu, ircUser->hostmask(), ignoreMap); + // end of ignoreliststuff + } + menu->addSeparator(); + addAction(NickQuery, menu, itemType == NetworkModel::IrcUserItemType && !haveQuery && indexList().count() == 1); + addAction(NickSwitchTo, menu, itemType == NetworkModel::IrcUserItemType && haveQuery); + menu->addSeparator(); + addAction(NickWhois, menu, true); + } + else if (!contextItem().isEmpty() && messageFilter()) { + // case d + // TODO + } +} + - } +Action *ContextMenuActionProvider::addAction(ActionType type, QMenu *menu, const QModelIndex &index, ItemActiveStates requiredActiveState) +{ + return addAction(action(type), menu, checkRequirements(index, requiredActiveState)); } -Action * ContextMenuActionProvider::addAction(ActionType type , QMenu *menu, const QModelIndex &index, ItemActiveStates requiredActiveState) { - return addAction(action(type), menu, checkRequirements(index, requiredActiveState)); + +Action *ContextMenuActionProvider::addAction(Action *action, QMenu *menu, const QModelIndex &index, ItemActiveStates requiredActiveState) +{ + return addAction(action, menu, checkRequirements(index, requiredActiveState)); } -Action * ContextMenuActionProvider::addAction(Action *action , QMenu *menu, const QModelIndex &index, ItemActiveStates requiredActiveState) { - return addAction(action, menu, checkRequirements(index, requiredActiveState)); + +Action *ContextMenuActionProvider::addAction(ActionType type, QMenu *menu, bool condition) +{ + return addAction(action(type), menu, condition); } -Action * ContextMenuActionProvider::addAction(ActionType type , QMenu *menu, bool condition) { - return addAction(action(type), menu, condition); + +Action *ContextMenuActionProvider::addAction(Action *action, QMenu *menu, bool condition) +{ + if (condition) { + menu->addAction(action); + action->setVisible(true); + } + else { + action->setVisible(false); + } + return action; } -Action * ContextMenuActionProvider::addAction(Action *action , QMenu *menu, bool condition) { - if(condition) { - menu->addAction(action); - action->setVisible(true); - } else { - action->setVisible(false); - } - return action; + +void ContextMenuActionProvider::addHideEventsMenu(QMenu *menu, BufferId bufferId) +{ + if (BufferSettings(bufferId).hasFilter()) + addHideEventsMenu(menu, BufferSettings(bufferId).messageFilter()); + else + addHideEventsMenu(menu); } -void ContextMenuActionProvider::addHideEventsMenu(QMenu *menu, BufferId bufferId) { - if(BufferSettings(bufferId).hasFilter()) - addHideEventsMenu(menu, BufferSettings(bufferId).messageFilter()); - else - addHideEventsMenu(menu); + +void ContextMenuActionProvider::addHideEventsMenu(QMenu *menu, MessageFilter *msgFilter) +{ + if (BufferSettings(msgFilter->idString()).hasFilter()) + addHideEventsMenu(menu, BufferSettings(msgFilter->idString()).messageFilter()); + else + addHideEventsMenu(menu); } -void ContextMenuActionProvider::addHideEventsMenu(QMenu *menu, MessageFilter *msgFilter) { - if(BufferSettings(msgFilter->idString()).hasFilter()) - addHideEventsMenu(menu, BufferSettings(msgFilter->idString()).messageFilter()); - else - addHideEventsMenu(menu); + +void ContextMenuActionProvider::addHideEventsMenu(QMenu *menu, int filter) +{ + action(HideApplyToAll)->setEnabled(filter != -1); + action(HideUseDefaults)->setEnabled(filter != -1); + if (filter == -1) + filter = BufferSettings().messageFilter(); + + action(HideJoin)->setChecked(filter & Message::Join); + action(HidePart)->setChecked(filter & Message::Part); + action(HideQuit)->setChecked(filter & Message::Quit); + action(HideNick)->setChecked(filter & Message::Nick); + action(HideMode)->setChecked(filter & Message::Mode); + action(HideDayChange)->setChecked(filter & Message::DayChange); + action(HideTopic)->setChecked(filter & Message::Topic); + + menu->addAction(_hideEventsMenuAction); } -void ContextMenuActionProvider::addHideEventsMenu(QMenu *menu, int filter) { - action(HideApplyToAll)->setEnabled(filter != -1); - action(HideUseDefaults)->setEnabled(filter != -1); - if(filter == -1) - filter = BufferSettings().messageFilter(); - - action(HideJoin)->setChecked(filter & Message::Join); - action(HidePart)->setChecked(filter & Message::Part); - action(HideQuit)->setChecked(filter & Message::Quit); - action(HideNick)->setChecked(filter & Message::Nick); - action(HideMode)->setChecked(filter & Message::Mode); - action(HideDayChange)->setChecked(filter & Message::DayChange); - action(HideTopic)->setChecked(filter & Message::Topic); - - menu->addAction(_hideEventsMenuAction); + +void ContextMenuActionProvider::addIgnoreMenu(QMenu *menu, const QString &hostmask, const QMap &ignoreMap) +{ + QMenu *ignoreMenu = _nickIgnoreMenuAction->menu(); + ignoreMenu->clear(); + QString nick = nickFromMask(hostmask); + QString ident = userFromMask(hostmask); + QString host = hostFromMask(hostmask); + QString domain = host; + QRegExp domainRx = QRegExp("(\\.[^.]+\\.\\w+\\D)$"); + if (domainRx.indexIn(host) != -1) + domain = domainRx.cap(1); + // we can't rely on who-data + // if we don't have the data, we skip actions where we would need it + bool haveWhoData = !ident.isEmpty() && !host.isEmpty(); + + // add "Add Ignore Rule" description + ignoreMenu->addAction(_ignoreDescriptions.at(0)); + + if (haveWhoData) { + QString text; + text = QString("*!%1@%2").arg(ident, host); + action(NickIgnoreUser)->setText(text); + action(NickIgnoreUser)->setProperty("ignoreRule", text); + + text = QString("*!*@%1").arg(host); + action(NickIgnoreHost)->setText(text); + action(NickIgnoreHost)->setProperty("ignoreRule", text); + + text = domain.at(0) == '.' ? QString("*!%1@*%2").arg(ident, domain) + : QString("*!%1@%2").arg(ident, domain); + + action(NickIgnoreDomain)->setText(text); + action(NickIgnoreDomain)->setProperty("ignoreRule", text); + + if (!ignoreMap.contains(action(NickIgnoreUser)->property("ignoreRule").toString())) + ignoreMenu->addAction(action(NickIgnoreUser)); + if (!ignoreMap.contains(action(NickIgnoreHost)->property("ignoreRule").toString())) + ignoreMenu->addAction(action(NickIgnoreHost)); + // we only add that NickIgnoreDomain if it isn't the same as NickIgnoreUser + // as happens with @foobar.com hostmasks and ips + if (!ignoreMap.contains(action(NickIgnoreDomain)->property("ignoreRule").toString()) + && action(NickIgnoreUser)->property("ignoreRule").toString() != action(NickIgnoreDomain)->property("ignoreRule").toString()) + ignoreMenu->addAction(action(NickIgnoreDomain)); + } + + action(NickIgnoreCustom)->setProperty("ignoreRule", hostmask); + ignoreMenu->addAction(action(NickIgnoreCustom)); + + ignoreMenu->addSeparator(); + + if (haveWhoData) { + QMap::const_iterator ruleIter = ignoreMap.begin(); + int counter = 0; + if (!ignoreMap.isEmpty()) + // add "Existing Rules" description + ignoreMenu->addAction(_ignoreDescriptions.at(1)); + while (ruleIter != ignoreMap.constEnd()) { + if (counter < 5) { + auto type = static_cast(NickIgnoreToggleEnabled0 + counter*0x100000); + Action *act = action(type); + act->setText(ruleIter.key()); + act->setProperty("ignoreRule", ruleIter.key()); + act->setChecked(ruleIter.value()); + ignoreMenu->addAction(act); + } + counter++; + ++ruleIter; + } + if (counter) + ignoreMenu->addSeparator(); + } + ignoreMenu->addAction(action(ShowIgnoreList)); + addAction(_nickIgnoreMenuAction, menu); }