From: Manuel Nickschas Date: Sun, 1 Feb 2009 00:21:29 +0000 (+0100) Subject: Split action handling and helper stuff from ContextMenuActionProvider X-Git-Tag: 0.4.0~128 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=57058eabefe58082635c0ff83bbd4714baa5b6a9 Split action handling and helper stuff from ContextMenuActionProvider This provides a common baseclass for the menu and the toolbar action providers. We can't lump the two together, since menu actions are quite different from toolbar actions in some respects. The common baseclass avoids code duplication. --- diff --git a/src/uisupport/CMakeLists.txt b/src/uisupport/CMakeLists.txt index d1c82b27..56abf4d2 100644 --- a/src/uisupport/CMakeLists.txt +++ b/src/uisupport/CMakeLists.txt @@ -19,6 +19,7 @@ set(SOURCES icon.cpp iconloader.cpp inputline.cpp + networkmodelcontroller.cpp nickview.cpp nickviewfilter.cpp settingspage.cpp @@ -43,6 +44,7 @@ set(MOC_HDRS graphicalui.h iconloader.h inputline.h + networkmodelcontroller.h nickview.h nickviewfilter.h settingspage.h diff --git a/src/uisupport/contextmenuactionprovider.cpp b/src/uisupport/contextmenuactionprovider.cpp index 8ab622e8..22147239 100644 --- a/src/uisupport/contextmenuactionprovider.cpp +++ b/src/uisupport/contextmenuactionprovider.cpp @@ -31,12 +31,7 @@ #include "network.h" #include "util.h" -ContextMenuActionProvider::ContextMenuActionProvider(QObject *parent) -: QObject(parent), - _actionCollection(new ActionCollection(this)), - _messageFilter(0), - _receiver(0) -{ +ContextMenuActionProvider::ContextMenuActionProvider(QObject *parent) : NetworkModelController(parent) { registerAction(NetworkConnect, SmallIcon("network-connect"), tr("Connect")); registerAction(NetworkDisconnect, SmallIcon("network-disconnect"), tr("Disconnect")); @@ -78,8 +73,6 @@ ContextMenuActionProvider::ContextMenuActionProvider(QObject *parent) registerAction(ShowChannelList, SmallIcon("format-list-unordered"), tr("Show Channel List")); registerAction(ShowIgnoreList, tr("Show Ignore List")); - connect(_actionCollection, SIGNAL(actionTriggered(QAction *)), SLOT(actionTriggered(QAction *))); - QMenu *hideEventsMenu = new QMenu(); hideEventsMenu->addAction(action(HideJoin)); hideEventsMenu->addAction(action(HidePart)); @@ -123,24 +116,6 @@ ContextMenuActionProvider::~ContextMenuActionProvider() { _nickModeMenuAction->deleteLater(); } -void ContextMenuActionProvider::registerAction(ActionType type, const QString &text, bool checkable) { - registerAction(type, QPixmap(), text, checkable); -} - -void ContextMenuActionProvider::registerAction(ActionType type, const QPixmap &icon, const QString &text, bool checkable) { - Action *act; - if(icon.isNull()) - act = new Action(text, this); - else - act = new Action(icon, text, this); - - act->setCheckable(checkable); - act->setData(type); - - _actionCollection->addAction(QString::number(type, 16), act); - _actionByType[type] = act; -} - void ContextMenuActionProvider::addActions(QMenu *menu, BufferId bufId, QObject *receiver, const char *method) { if(!bufId.isValid()) return; @@ -169,27 +144,26 @@ void ContextMenuActionProvider::addActions(QMenu *menu, const QList // 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, + const QList &indexList_, + MessageFilter *filter_, + const QString &contextItem_, + QObject *receiver_, + const char *method_, bool isCustomBufferView) { - if(!indexList.count()) + if(!indexList_.count()) return; - _indexList = indexList; - _messageFilter = filter; - _contextItem = contextItem; - _receiver = receiver; - _method = method; + setIndexList(indexList_); + setMessageFilter(filter_); + setContextItem(contextItem_); + setSlot(receiver_, method_); - if(!_messageFilter) { + 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); + QModelIndex index = indexList().at(0); NetworkModel::ItemType itemType = static_cast(index.data(NetworkModel::ItemTypeRole).toInt()); switch(itemType) { @@ -208,14 +182,14 @@ void ContextMenuActionProvider::addActions(QMenu *menu, } } else { // ChatView actions - if(_contextItem.isEmpty()) { + 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) { + if(messageFilter()->containedBuffers().count() == 1) { // we can handle this like a single bufferItem - QModelIndex index = Client::networkModel()->bufferIndex(_messageFilter->containedBuffers().values().at(0)); - _indexList = QList() << index; + QModelIndex index = Client::networkModel()->bufferIndex(messageFilter()->containedBuffers().values().at(0)); + setIndexList(index); addBufferItemActions(menu, index); return; } else { @@ -224,15 +198,15 @@ void ContextMenuActionProvider::addActions(QMenu *menu, } } else { // context item = chan or nick, _indexList = buf where the msg clicked on originated - if(isChannelName(_contextItem)) { - QModelIndex msgIdx = _indexList.at(0); + 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); + BufferId bufId = Client::networkModel()->bufferId(networkId, contextItem()); if(bufId.isValid()) { QModelIndex targetIdx = Client::networkModel()->bufferIndex(bufId); - _indexList = QList() << targetIdx; + setIndexList(targetIdx); addAction(BufferJoin, menu, targetIdx, InactiveState); addAction(BufferSwitchTo, menu, targetIdx, ActiveState); } else @@ -304,41 +278,25 @@ void ContextMenuActionProvider::addIrcUserActions(QMenu *menu, const QModelIndex // 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()) { + if(contextItem().isNull()) { // cases a, b, c - bool haveQuery = _indexList.count() == 1 && findQueryBuffer(index).isValid(); + 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(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) { + } else if(!contextItem().isEmpty() && messageFilter()) { // case d // TODO } } -/******** Helper Functions ***********************************************************************/ - -bool ContextMenuActionProvider::checkRequirements(const QModelIndex &index, ItemActiveStates requiredActiveState) { - if(!index.isValid()) - return false; - - ItemActiveStates isActive = index.data(NetworkModel::ItemActiveRole).toBool() - ? ActiveState - : InactiveState; - - if(!(isActive & requiredActiveState)) - return false; - - return true; -} - Action * ContextMenuActionProvider::addAction(ActionType type , QMenu *menu, const QModelIndex &index, ItemActiveStates requiredActiveState) { return addAction(action(type), menu, checkRequirements(index, requiredActiveState)); } @@ -390,294 +348,3 @@ void ContextMenuActionProvider::addHideEventsMenu(QMenu *menu, int filter) { menu->addAction(_hideEventsMenuAction); } - -QString ContextMenuActionProvider::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(); - if(!bufferInfo.type() == BufferInfo::QueryBuffer) - return QString(); - - return bufferInfo.bufferName(); // FIXME this might break with merged queries maybe -} - -BufferId ContextMenuActionProvider::findQueryBuffer(const QModelIndex &index, const QString &predefinedNick) const { - NetworkId networkId = index.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 ContextMenuActionProvider::findQueryBuffer(NetworkId networkId, const QString &nick) const { - return Client::networkModel()->bufferId(networkId, nick); -} - -void ContextMenuActionProvider::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 ContextMenuActionProvider::actionTriggered(QAction *action) { - ActionType type = (ActionType)action->data().toInt(); - if(type > 0) { - if(type & NetworkMask) - handleNetworkAction(type, action); - else if(type & BufferMask) - handleBufferAction(type, action); - else if(type & HideMask) - handleHideAction(type, action); - else if(type & GeneralMask) - handleGeneralAction(type, action); - else if(type & NickMask) - handleNickAction(type, action); - else if(type & ExternalMask) - handleExternalAction(type, action); - else - qWarning() << "NetworkModelActionProvider::actionTriggered(): Unhandled action!"; - } - _indexList.clear(); - _messageFilter = 0; - _receiver = 0; -} - -void ContextMenuActionProvider::handleNetworkAction(ActionType type, QAction *) { - if(!_indexList.count()) - return; - const Network *network = Client::network(_indexList.at(0).data(NetworkModel::NetworkIdRole).value()); - Q_CHECK_PTR(network); - if(!network) - return; - - switch(type) { - case NetworkConnect: - network->requestConnect(); - break; - case NetworkDisconnect: - network->requestDisconnect(); - break; - default: - break; - } -} - -void ContextMenuActionProvider::handleBufferAction(ActionType type, QAction *) { - if(type == BufferRemove) { - removeBuffers(_indexList); - } else { - - foreach(QModelIndex index, _indexList) { - BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); - if(!bufferInfo.isValid()) - continue; - - switch(type) { - case BufferJoin: - Client::userInput(bufferInfo, QString("/JOIN %1").arg(bufferInfo.bufferName())); - break; - case BufferPart: - { - QString reason = Client::identity(Client::network(bufferInfo.networkId())->identity())->partReason(); - Client::userInput(bufferInfo, QString("/PART %1").arg(reason)); - break; - } - case BufferSwitchTo: - Client::bufferModel()->switchToBuffer(bufferInfo.bufferId()); - break; - default: - break; - } - } - } -} - -void ContextMenuActionProvider::removeBuffers(const QModelIndexList &indexList) { - QList inactive; - foreach(QModelIndex index, indexList) { - BufferInfo info = index.data(NetworkModel::BufferInfoRole).value(); - if(info.isValid()) { - if(info.type() == BufferInfo::QueryBuffer - || (info.type() == BufferInfo::ChannelBuffer && !index.data(NetworkModel::ItemActiveRole).toBool())) - inactive << info; - } - } - QString msg; - if(inactive.count()) { - msg = tr("Do you want to delete the following buffer(s) permanently?", 0, inactive.count()); - msg += "
    "; - foreach(BufferInfo info, inactive) - msg += QString("
  • %1
  • ").arg(info.bufferName()); - msg += "
"; - msg += tr("Note: This will delete all related data, including all backlog data, from the core's database and cannot be undone."); - if(inactive.count() != indexList.count()) - msg += tr("
Active channel buffers cannot be deleted, please part the channel first."); - - if(QMessageBox::question(0, tr("Remove buffers permanently?"), msg, QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) { - foreach(BufferInfo info, inactive) - Client::removeBuffer(info.bufferId()); - } - } -} - -void ContextMenuActionProvider::handleHideAction(ActionType type, QAction *action) { - Q_UNUSED(action) - - int filter = 0; - if(ContextMenuActionProvider::action(HideJoin)->isChecked()) - filter |= Message::Join; - if(ContextMenuActionProvider::action(HidePart)->isChecked()) - filter |= Message::Part; - if(ContextMenuActionProvider::action(HideQuit)->isChecked()) - filter |= Message::Quit; - if(ContextMenuActionProvider::action(HideNick)->isChecked()) - filter |= Message::Nick; - if(ContextMenuActionProvider::action(HideMode)->isChecked()) - filter |= Message::Mode; - if(ContextMenuActionProvider::action(HideDayChange)->isChecked()) - filter |= Message::DayChange; - - switch(type) { - case HideJoin: - case HidePart: - case HideQuit: - case HideNick: - case HideMode: - case HideDayChange: - if(_messageFilter) - BufferSettings(_messageFilter->idString()).setMessageFilter(filter); - else { - foreach(QModelIndex index, _indexList) { - BufferId bufferId = index.data(NetworkModel::BufferIdRole).value(); - if(!bufferId.isValid()) - continue; - BufferSettings(bufferId).setMessageFilter(filter); - } - } - return; - case HideApplyToAll: - BufferSettings().setMessageFilter(filter); - case HideUseDefaults: - if(_messageFilter) - BufferSettings(_messageFilter->idString()).removeFilter(); - else { - foreach(QModelIndex index, _indexList) { - BufferId bufferId = index.data(NetworkModel::BufferIdRole).value(); - if(!bufferId.isValid()) - continue; - BufferSettings(bufferId).removeFilter(); - } - } - return; - default: - return; - }; -} - -void ContextMenuActionProvider::handleGeneralAction(ActionType type, QAction *action) { - Q_UNUSED(action) - - if(!_indexList.count()) - return; - NetworkId networkId = _indexList.at(0).data(NetworkModel::NetworkIdRole).value(); - if(!networkId.isValid()) - return; - - switch(type) { - case JoinChannel: { - QString channelName = _contextItem; - if(channelName.isEmpty()) { - bool ok; - channelName = QInputDialog::getText(0, tr("Join Channel"), tr("Input channel name:"), QLineEdit::Normal, QString(), &ok); - if(!ok) - return; - } - if(!channelName.isEmpty()) { - Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId), QString("/JOIN %1").arg(channelName)); - } - break; - } - case ShowChannelList: - emit showChannelList(networkId); - break; - case ShowIgnoreList: - emit showIgnoreList(networkId); - break; - default: - break; - } -} - -void ContextMenuActionProvider::handleNickAction(ActionType type, QAction *) { - foreach(QModelIndex index, _indexList) { - NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); - if(!networkId.isValid()) - continue; - QString nick = nickName(index); - if(nick.isEmpty()) - continue; - BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); - if(!bufferInfo.isValid()) - continue; - - 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/contextmenuactionprovider.h b/src/uisupport/contextmenuactionprovider.h index 8cd519f1..bdac641d 100644 --- a/src/uisupport/contextmenuactionprovider.h +++ b/src/uisupport/contextmenuactionprovider.h @@ -18,76 +18,17 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#ifndef NETWORKMODELACTIONPROVIDER_H -#define NETWORKMODELACTIONPROVIDER_H +#ifndef CONTEXTMENUACTIONPROVIDER_H +#define CONTEXTMENUACTIONPROVIDER_H -#include "action.h" -#include "actioncollection.h" -#include "messagefilter.h" +#include "networkmodelcontroller.h" -class ContextMenuActionProvider : public QObject { +class ContextMenuActionProvider : public NetworkModelController { Q_OBJECT public: ContextMenuActionProvider(QObject *parent = 0); - ~ContextMenuActionProvider(); - - // don't change enums without doublechecking masks etc. in code - enum ActionType { - // Network actions - NetworkMask = 0x0f, - NetworkConnect = 0x01, - NetworkDisconnect = 0x02, - - // Buffer actions - BufferMask = 0xf0, - BufferJoin = 0x10, - BufferPart = 0x20, - BufferSwitchTo = 0x30, - BufferRemove = 0x40, - - // Hide actions - HideMask = 0x0f00, - HideJoin = 0x0100, - HidePart = 0x0200, - HideQuit = 0x0300, - HideNick = 0x0400, - HideMode = 0x0500, - HideDayChange = 0x0600, - HideUseDefaults = 0xe00, - HideApplyToAll = 0xf00, - - // General actions - GeneralMask = 0xf000, - JoinChannel = 0x1000, - ShowChannelList = 0x2000, - ShowIgnoreList = 0x3000, - - // Nick actions - NickMask = 0xff0000, - NickWhois = 0x010000, - NickQuery = 0x020000, - NickSwitchTo = 0x030000, - NickCtcpVersion = 0x040000, - NickCtcpPing = 0x050000, - NickCtcpTime = 0x060000, - NickCtcpFinger = 0x070000, - NickOp = 0x080000, - NickDeop = 0x090000, - NickVoice = 0x0a0000, - NickDevoice = 0x0b0000, - NickKick = 0x0c0000, - NickBan = 0x0d0000, - NickKickBan = 0x0e0000, - - // Actions that are handled externally - // These emit a signal to the action requester, rather than being handled here - ExternalMask = 0xff000000, - HideBufferTemporarily = 0x01000000, - HideBufferPermanently = 0x02000000 - }; - - inline Action *action(ActionType type) const; + virtual ~ContextMenuActionProvider(); //! Provide a list of actions applying to the given item /** @@ -107,40 +48,11 @@ public: 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); - void showIgnoreList(NetworkId); - -protected: - inline ActionCollection *actionCollection() const; - -protected slots: - void actionTriggered(QAction *); - private: - enum ItemActiveState { - InactiveState = 0x01, - ActiveState = 0x02 - }; - -public: - Q_DECLARE_FLAGS(ItemActiveStates, ItemActiveState) - -private: - void registerAction(ActionType type, const QString &text, bool checkable = false); - void registerAction(ActionType type, const QPixmap &icon, const QString &text, bool checkable = false); - - void handleNetworkAction(ActionType, QAction *); - void handleBufferAction(ActionType, QAction *); - void handleHideAction(ActionType, QAction *); - void handleNickAction(ActionType, QAction *); - void handleGeneralAction(ActionType, QAction *); - void handleExternalAction(ActionType, QAction *); void addActions(QMenu *, const QList &indexList, MessageFilter *filter, const QString &chanOrNick, QObject *receiver, const char *slot, bool allowBufferHide); - bool checkRequirements(const QModelIndex &index, ItemActiveStates requiredActiveState = QFlags(ActiveState | InactiveState)); Action * addAction(ActionType, QMenu *, bool condition = true); Action * addAction(Action * , QMenu *, bool condition = true); Action * addAction(ActionType, QMenu *, const QModelIndex &index, ItemActiveStates requiredActiveState = QFlags(ActiveState | InactiveState)); @@ -154,28 +66,9 @@ private: void addBufferItemActions(QMenu *, const QModelIndex &, bool isCustomBufferView = false); 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; - void removeBuffers(const QModelIndexList &indexList); - - NetworkModel *_model; - - ActionCollection *_actionCollection; - 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; }; -// inlines -ActionCollection *ContextMenuActionProvider::actionCollection() const { return _actionCollection; } -Action *ContextMenuActionProvider::action(ActionType type) const { return _actionByType.value(type, 0); } #endif diff --git a/src/uisupport/networkmodelcontroller.cpp b/src/uisupport/networkmodelcontroller.cpp new file mode 100644 index 00000000..3d56b1a1 --- /dev/null +++ b/src/uisupport/networkmodelcontroller.cpp @@ -0,0 +1,389 @@ +/*************************************************************************** + * Copyright (C) 2005-09 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 + +#include "networkmodelcontroller.h" + +#include "buffermodel.h" +#include "buffersettings.h" +#include "iconloader.h" +#include "clientidentity.h" +#include "network.h" +#include "util.h" + +NetworkModelController::NetworkModelController(QObject *parent) +: QObject(parent), + _actionCollection(new ActionCollection(this)), + _messageFilter(0), + _receiver(0) +{ + + connect(_actionCollection, SIGNAL(actionTriggered(QAction *)), SLOT(actionTriggered(QAction *))); + +} + +NetworkModelController::~NetworkModelController() { + +} + +void NetworkModelController::registerAction(ActionType type, const QString &text, bool checkable) { + registerAction(type, QPixmap(), text, checkable); +} + +void NetworkModelController::registerAction(ActionType type, const QPixmap &icon, const QString &text, bool checkable) { + Action *act; + if(icon.isNull()) + act = new Action(text, this); + else + act = new Action(icon, text, this); + + act->setCheckable(checkable); + act->setData(type); + + _actionCollection->addAction(QString::number(type, 16), act); + _actionByType[type] = act; +} + +/******** Helper Functions ***********************************************************************/ + +void NetworkModelController::setIndexList(const QModelIndex &index) { + _indexList = QList() << index; +} + +void NetworkModelController::setIndexList(const QList &list) { + _indexList = list; +} + +void NetworkModelController::setMessageFilter(MessageFilter *filter) { + _messageFilter = filter; +} + +void NetworkModelController::setContextItem(const QString &contextItem) { + _contextItem = contextItem; +} + +void NetworkModelController::setSlot(QObject *receiver, const char *method) { + _receiver = receiver; + _method = method; +} + +bool NetworkModelController::checkRequirements(const QModelIndex &index, ItemActiveStates requiredActiveState) { + if(!index.isValid()) + return false; + + ItemActiveStates isActive = index.data(NetworkModel::ItemActiveRole).toBool() + ? ActiveState + : InactiveState; + + if(!(isActive & requiredActiveState)) + return false; + + return true; +} + +QString NetworkModelController::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(); + if(!bufferInfo.type() == BufferInfo::QueryBuffer) + return QString(); + + return bufferInfo.bufferName(); // FIXME this might break with merged queries maybe +} + +BufferId NetworkModelController::findQueryBuffer(const QModelIndex &index, const QString &predefinedNick) const { + NetworkId networkId = index.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 NetworkModelController::findQueryBuffer(NetworkId networkId, const QString &nick) const { + return Client::networkModel()->bufferId(networkId, nick); +} + +void NetworkModelController::removeBuffers(const QModelIndexList &indexList) { + QList inactive; + foreach(QModelIndex index, indexList) { + BufferInfo info = index.data(NetworkModel::BufferInfoRole).value(); + if(info.isValid()) { + if(info.type() == BufferInfo::QueryBuffer + || (info.type() == BufferInfo::ChannelBuffer && !index.data(NetworkModel::ItemActiveRole).toBool())) + inactive << info; + } + } + QString msg; + if(inactive.count()) { + msg = tr("Do you want to delete the following buffer(s) permanently?", 0, inactive.count()); + msg += "
    "; + foreach(BufferInfo info, inactive) + msg += QString("
  • %1
  • ").arg(info.bufferName()); + msg += "
"; + msg += tr("Note: This will delete all related data, including all backlog data, from the core's database and cannot be undone."); + if(inactive.count() != indexList.count()) + msg += tr("
Active channel buffers cannot be deleted, please part the channel first."); + + if(QMessageBox::question(0, tr("Remove buffers permanently?"), msg, QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) { + foreach(BufferInfo info, inactive) + Client::removeBuffer(info.bufferId()); + } + } +} + +void NetworkModelController::handleExternalAction(ActionType type, QAction *action) { + Q_UNUSED(type); + if(receiver() && method()) { + if(!QMetaObject::invokeMethod(receiver(), method(), Q_ARG(QAction *, action))) + qWarning() << "NetworkModelActionController::handleExternalAction(): Could not invoke slot" << receiver() << method(); + } +} + +/******** Handle Actions *************************************************************************/ + +void NetworkModelController::actionTriggered(QAction *action) { + ActionType type = (ActionType)action->data().toInt(); + if(type > 0) { + if(type & NetworkMask) + handleNetworkAction(type, action); + else if(type & BufferMask) + handleBufferAction(type, action); + else if(type & HideMask) + handleHideAction(type, action); + else if(type & GeneralMask) + handleGeneralAction(type, action); + else if(type & NickMask) + handleNickAction(type, action); + else if(type & ExternalMask) + handleExternalAction(type, action); + else + qWarning() << "NetworkModelController::actionTriggered(): Unhandled action!"; + } +} + +void NetworkModelController::handleNetworkAction(ActionType type, QAction *) { + if(!indexList().count()) + return; + const Network *network = Client::network(indexList().at(0).data(NetworkModel::NetworkIdRole).value()); + Q_CHECK_PTR(network); + if(!network) + return; + + switch(type) { + case NetworkConnect: + network->requestConnect(); + break; + case NetworkDisconnect: + network->requestDisconnect(); + break; + default: + break; + } +} + +void NetworkModelController::handleBufferAction(ActionType type, QAction *) { + if(type == BufferRemove) { + removeBuffers(indexList()); + } else { + + foreach(QModelIndex index, indexList()) { + BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); + if(!bufferInfo.isValid()) + continue; + + switch(type) { + case BufferJoin: + Client::userInput(bufferInfo, QString("/JOIN %1").arg(bufferInfo.bufferName())); + break; + case BufferPart: + { + QString reason = Client::identity(Client::network(bufferInfo.networkId())->identity())->partReason(); + Client::userInput(bufferInfo, QString("/PART %1").arg(reason)); + break; + } + case BufferSwitchTo: + Client::bufferModel()->switchToBuffer(bufferInfo.bufferId()); + break; + default: + break; + } + } + } +} + +void NetworkModelController::handleHideAction(ActionType type, QAction *action) { + Q_UNUSED(action) + + int filter = 0; + if(NetworkModelController::action(HideJoin)->isChecked()) + filter |= Message::Join; + if(NetworkModelController::action(HidePart)->isChecked()) + filter |= Message::Part; + if(NetworkModelController::action(HideQuit)->isChecked()) + filter |= Message::Quit; + if(NetworkModelController::action(HideNick)->isChecked()) + filter |= Message::Nick; + if(NetworkModelController::action(HideMode)->isChecked()) + filter |= Message::Mode; + if(NetworkModelController::action(HideDayChange)->isChecked()) + filter |= Message::DayChange; + + switch(type) { + case HideJoin: + case HidePart: + case HideQuit: + case HideNick: + case HideMode: + case HideDayChange: + if(_messageFilter) + BufferSettings(_messageFilter->idString()).setMessageFilter(filter); + else { + foreach(QModelIndex index, _indexList) { + BufferId bufferId = index.data(NetworkModel::BufferIdRole).value(); + if(!bufferId.isValid()) + continue; + BufferSettings(bufferId).setMessageFilter(filter); + } + } + return; + case HideApplyToAll: + BufferSettings().setMessageFilter(filter); + case HideUseDefaults: + if(_messageFilter) + BufferSettings(_messageFilter->idString()).removeFilter(); + else { + foreach(QModelIndex index, _indexList) { + BufferId bufferId = index.data(NetworkModel::BufferIdRole).value(); + if(!bufferId.isValid()) + continue; + BufferSettings(bufferId).removeFilter(); + } + } + return; + default: + return; + }; +} + +void NetworkModelController::handleGeneralAction(ActionType type, QAction *action) { + Q_UNUSED(action) + + if(!indexList().count()) + return; + NetworkId networkId = indexList().at(0).data(NetworkModel::NetworkIdRole).value(); + if(!networkId.isValid()) + return; + + switch(type) { + case JoinChannel: { + QString channelName = contextItem(); + if(channelName.isEmpty()) { + bool ok; + channelName = QInputDialog::getText(0, tr("Join Channel"), tr("Input channel name:"), QLineEdit::Normal, QString(), &ok); + if(!ok) + return; + } + if(!channelName.isEmpty()) { + Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId), QString("/JOIN %1").arg(channelName)); + } + break; + } + case ShowChannelList: + emit showChannelList(networkId); + break; + case ShowIgnoreList: + emit showIgnoreList(networkId); + break; + default: + break; + } +} + +void NetworkModelController::handleNickAction(ActionType type, QAction *) { + foreach(QModelIndex index, indexList()) { + NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value(); + if(!networkId.isValid()) + continue; + QString nick = nickName(index); + if(nick.isEmpty()) + continue; + BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value(); + if(!bufferInfo.isValid()) + continue; + + 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/networkmodelcontroller.h b/src/uisupport/networkmodelcontroller.h new file mode 100644 index 00000000..459d3873 --- /dev/null +++ b/src/uisupport/networkmodelcontroller.h @@ -0,0 +1,158 @@ +/*************************************************************************** + * Copyright (C) 2005-09 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 NETWORKMODELCONTROLLER_H_ +#define NETWORKMODELCONTROLLER_H_ + +#include "action.h" +#include "actioncollection.h" +#include "messagefilter.h" + +class NetworkModelController : public QObject { + Q_OBJECT + +public: + NetworkModelController(QObject *parent = 0); + virtual ~NetworkModelController(); + + // don't change enums without doublechecking masks etc. in code + enum ActionType { + // Network actions + NetworkMask = 0x0f, + NetworkConnect = 0x01, + NetworkDisconnect = 0x02, + + // Buffer actions + BufferMask = 0xf0, + BufferJoin = 0x10, + BufferPart = 0x20, + BufferSwitchTo = 0x30, + BufferRemove = 0x40, + + // Hide actions + HideMask = 0x0f00, + HideJoin = 0x0100, + HidePart = 0x0200, + HideQuit = 0x0300, + HideNick = 0x0400, + HideMode = 0x0500, + HideDayChange = 0x0600, + HideUseDefaults = 0xe00, + HideApplyToAll = 0xf00, + + // General actions + GeneralMask = 0xf000, + JoinChannel = 0x1000, + ShowChannelList = 0x2000, + ShowIgnoreList = 0x3000, + + // Nick actions + NickMask = 0xff0000, + NickWhois = 0x010000, + NickQuery = 0x020000, + NickSwitchTo = 0x030000, + NickCtcpVersion = 0x040000, + NickCtcpPing = 0x050000, + NickCtcpTime = 0x060000, + NickCtcpFinger = 0x070000, + NickOp = 0x080000, + NickDeop = 0x090000, + NickVoice = 0x0a0000, + NickDevoice = 0x0b0000, + NickKick = 0x0c0000, + NickBan = 0x0d0000, + NickKickBan = 0x0e0000, + + // Actions that are handled externally + // These emit a signal to the action requester, rather than being handled here + ExternalMask = 0xff000000, + HideBufferTemporarily = 0x01000000, + HideBufferPermanently = 0x02000000 + }; + + inline Action *action(ActionType type) const; + +public: + enum ItemActiveState { + InactiveState = 0x01, + ActiveState = 0x02 + }; + Q_DECLARE_FLAGS(ItemActiveStates, ItemActiveState) + +protected: + inline ActionCollection *actionCollection() const; + inline QList indexList() const; + inline MessageFilter *messageFilter() const; + inline QString contextItem() const ; ///< Channel name or nick to provide context menu for + inline QObject *receiver() const ; + inline const char *method() const; + + void setIndexList(const QModelIndex &); + void setIndexList(const QList &); + void setMessageFilter(MessageFilter *); + void setContextItem(const QString &); + void setSlot(QObject *receiver, const char *method); + + void registerAction(ActionType type, const QString &text, bool checkable = false); + void registerAction(ActionType type, const QPixmap &icon, const QString &text, bool checkable = false); + bool checkRequirements(const QModelIndex &index, ItemActiveStates requiredActiveState = QFlags(ActiveState | InactiveState)); + + QString nickName(const QModelIndex &index) const; + BufferId findQueryBuffer(const QModelIndex &index, const QString &predefinedNick = QString()) const; + BufferId findQueryBuffer(NetworkId, const QString &nickName) const; + void removeBuffers(const QModelIndexList &indexList); + +protected slots: + virtual void actionTriggered(QAction *); + +signals: + void showChannelList(NetworkId); + void showIgnoreList(NetworkId); + +private: + void handleNetworkAction(ActionType, QAction *); + void handleBufferAction(ActionType, QAction *); + void handleHideAction(ActionType, QAction *); + void handleNickAction(ActionType, QAction *); + void handleGeneralAction(ActionType, QAction *); + void handleExternalAction(ActionType, QAction *); + + NetworkModel *_model; + + ActionCollection *_actionCollection; + QHash _actionByType; + + QList _indexList; + MessageFilter *_messageFilter; + QString _contextItem; ///< Channel name or nick to provide context menu for + QObject *_receiver; + const char *_method; +}; + +// inlines +ActionCollection *NetworkModelController::actionCollection() const { return _actionCollection; } +Action *NetworkModelController::action(ActionType type) const { return _actionByType.value(type, 0); } +QList NetworkModelController::indexList() const { return _indexList; } +MessageFilter *NetworkModelController::messageFilter() const { return _messageFilter; } +QString NetworkModelController::contextItem() const { return _contextItem; } +QObject *NetworkModelController::receiver() const { return _receiver; } +const char *NetworkModelController::method() const { return _method; } + +#endif