--- /dev/null
+/***************************************************************************
+* 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 <QInputDialog>
+#include <QMenu>
+#include <QMessageBox>
+
+#include "networkmodelactionprovider.h"
+
+#include "buffersettings.h"
+#include "iconloader.h"
+#include "identity.h"
+#include "network.h"
+
+NetworkModelActionProvider::NetworkModelActionProvider(QObject *parent)
+: AbstractActionProvider(parent),
+ _actionCollection(new ActionCollection(this)),
+ _messageFilter(0),
+ _receiver(0)
+{
+ registerAction(NetworkConnect, SmallIcon("network-connect"), tr("Connect"));
+ registerAction(NetworkDisconnect, SmallIcon("network-disconnect"), tr("Disconnect"));
+
+ registerAction(BufferJoin, tr("Join"));
+ registerAction(BufferPart, tr("Part"));
+ registerAction(BufferRemove, tr("Delete 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(HideApplyToAll, tr("Apply to All Chat Views..."));
+
+ registerAction(JoinChannel, tr("Join Channel..."));
+
+ registerAction(NickCtcpWhois, tr("Whois"));
+ registerAction(NickCtcpVersion, tr("Version"));
+ registerAction(NickCtcpTime, tr("Time"));
+ registerAction(NickCtcpPing, tr("Ping"));
+ registerAction(NickCtcpFinger, tr("Finger"));
+
+ registerAction(NickOp, tr("Give Operator Status"));
+ registerAction(NickDeop, tr("Take Operator Status"));
+ registerAction(NickVoice, tr("Give Voice"));
+ registerAction(NickDevoice, tr("Take Voice"));
+ 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"));
+ registerAction(ShowChannelList, SmallIcon("format-list-unordered"), tr("Show Channel List"));
+ registerAction(ShowIgnoreList, tr("Show Ignore List"));
+
+ connect(_actionCollection, SIGNAL(actionTriggered(QAction *)), SLOT(actionTriggered(QAction *)));
+
+ action(HideApplyToAll)->setDisabled(true);
+
+ 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(HideDayChange));
+ hideEventsMenu->addSeparator();
+ hideEventsMenu->addAction(action(HideApplyToAll));
+ _hideEventsMenuAction = new Action(tr("Hide Events"), 0);
+ _hideEventsMenuAction->setMenu(hideEventsMenu);
+}
+
+NetworkModelActionProvider::~NetworkModelActionProvider() {
+ _hideEventsMenuAction->menu()->deleteLater();
+ _hideEventsMenuAction->deleteLater();
+}
+
+void NetworkModelActionProvider::registerAction(ActionType type, const QString &text, bool checkable) {
+ registerAction(type, QPixmap(), text, checkable);
+}
+
+void NetworkModelActionProvider::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 NetworkModelActionProvider::addActions(QMenu *menu, BufferId bufId, QObject *receiver, const char *method) {
+ if(!bufId.isValid())
+ return;
+ _messageFilter = 0;
+ 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<QModelIndex> 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;
+ addActions(menu, QList<QModelIndex>() << index, receiver, method, isCustomBufferView);
+}
+
+// add a list of actions sensible for the current item(s)
+void NetworkModelActionProvider::addActions(QMenu *menu,
+ const QList<QModelIndex> &indexList,
+ QObject *receiver,
+ const char *method,
+ bool isCustomBufferView)
+{
+ if(!indexList.count())
+ return;
+
+ _indexList = indexList;
+ _receiver = receiver;
+ _method = 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<NetworkModel::ItemType>(index.data(NetworkModel::ItemTypeRole).toInt());
+
+ switch(itemType) {
+ case NetworkModel::NetworkItemType:
+ addNetworkItemActions(menu, index);
+ break;
+ case NetworkModel::BufferItemType:
+ addBufferItemActions(menu, index, isCustomBufferView);
+ break;
+
+ default:
+ return;
+
+ }
+ } else {
+ // ChatView actions
+
+
+ }
+}
+
+void NetworkModelActionProvider::addNetworkItemActions(QMenu *menu, const QModelIndex &index) {
+ NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
+ 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 NetworkModelActionProvider::addBufferItemActions(QMenu *menu, const QModelIndex &index, bool isCustomBufferView) {
+ BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
+
+ 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);
+ break;
+
+ case BufferInfo::QueryBuffer:
+ {
+ IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
+ if(ircUser) {
+ addIrcUserActions(menu, ircUser, false);
+ menu->addSeparator();
+ }
+ 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);
+ }
+}
+
+void NetworkModelActionProvider::addIrcUserActions(QMenu *menu, IrcUser *ircUser, bool isNickView) {
+
+
+}
+
+/******** Helper Functions ***********************************************************************/
+
+bool NetworkModelActionProvider::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 * NetworkModelActionProvider::addAction(ActionType type , QMenu *menu, const QModelIndex &index, ItemActiveStates requiredActiveState) {
+ return addAction(action(type), menu, checkRequirements(index, requiredActiveState));
+}
+
+Action * NetworkModelActionProvider::addAction(Action *action , QMenu *menu, const QModelIndex &index, ItemActiveStates requiredActiveState) {
+ return addAction(action, menu, checkRequirements(index, requiredActiveState));
+}
+
+Action * NetworkModelActionProvider::addAction(ActionType type , QMenu *menu, bool condition) {
+ return addAction(action(type), menu, condition);
+}
+
+Action * NetworkModelActionProvider::addAction(Action *action , QMenu *menu, bool condition) {
+ if(condition) {
+ menu->addAction(action);
+ action->setVisible(true);
+ } else {
+ action->setVisible(false);
+ }
+ return action;
+}
+
+void NetworkModelActionProvider::addHideEventsMenu(QMenu *menu, BufferId bufferId) {
+ addHideEventsMenu(menu, BufferSettings(bufferId).messageFilter());
+}
+
+void NetworkModelActionProvider::addHideEventsMenu(QMenu *menu, MessageFilter *msgFilter) {
+ addHideEventsMenu(menu, BufferSettings(msgFilter->idString()).messageFilter());
+}
+
+void NetworkModelActionProvider::addHideEventsMenu(QMenu *menu, int filter) {
+ 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);
+
+ menu->addAction(_hideEventsMenuAction);
+}
+
+/******** Handle Actions *************************************************************************/
+
+void NetworkModelActionProvider::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 NetworkModelActionProvider::handleNetworkAction(ActionType type, QAction *) {
+ if(!_indexList.count())
+ return;
+ const Network *network = Client::network(_indexList.at(0).data(NetworkModel::NetworkIdRole).value<NetworkId>());
+ Q_CHECK_PTR(network);
+ if(!network)
+ return;
+
+ switch(type) {
+ case NetworkConnect:
+ network->requestConnect();
+ break;
+ case NetworkDisconnect:
+ network->requestDisconnect();
+ break;
+ default:
+ break;
+ }
+}
+
+void NetworkModelActionProvider::handleBufferAction(ActionType type, QAction *) {
+ foreach(QModelIndex index, _indexList) {
+ BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
+ if(!bufferInfo.isValid())
+ continue;
+
+ switch(type) {
+ case BufferJoin:
+ Client::instance()->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));
+ break;
+ }
+ case BufferRemove:
+ {
+ int res = QMessageBox::question(0, tr("Remove buffer permanently?"),
+ tr("Do you want to delete the buffer \"%1\" permanently? This will delete all related data, including all backlog "
+ "data, from the core's database!").arg(bufferInfo.bufferName()),
+ QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
+ if(res == QMessageBox::Yes) {
+ Client::removeBuffer(bufferInfo.bufferId());
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+void NetworkModelActionProvider::handleHideAction(ActionType type, QAction *action) {
+ Message::Type msgType;
+ switch(type) {
+ case HideJoin:
+ msgType = Message::Join; break;
+ case HidePart:
+ msgType = Message::Part; break;
+ case HideQuit:
+ msgType = Message::Quit; break;
+ case HideNick:
+ msgType = Message::Nick; break;
+ case HideMode:
+ msgType = Message::Mode; break;
+ case HideDayChange:
+ msgType = Message::DayChange; break;
+ case HideApplyToAll:
+ // TODO implement "apply to all" for hiding messages
+ break;
+ default:
+ return;
+ }
+
+ if(_messageFilter)
+ BufferSettings(_messageFilter->idString()).filterMessage(msgType, action->isChecked());
+ else {
+ foreach(QModelIndex index, _indexList) {
+ BufferId bufferId = index.data(NetworkModel::BufferIdRole).value<BufferId>();
+ if(!bufferId.isValid())
+ continue;
+ BufferSettings(bufferId).filterMessage(msgType, action->isChecked());
+ }
+ }
+}
+
+void NetworkModelActionProvider::handleGeneralAction(ActionType type, QAction *action) {
+ if(!_indexList.count())
+ return;
+ NetworkId networkId = _indexList.at(0).data(NetworkModel::NetworkIdRole).value<NetworkId>();
+ if(!networkId.isValid())
+ return;
+
+ switch(type) {
+ case JoinChannel:
+ {
+ // FIXME no QInputDialog in Qtopia
+# ifndef Q_WS_QWS
+ bool ok;
+ QString channelName = QInputDialog::getText(0, tr("Join Channel"), tr("Input channel name:"), QLineEdit::Normal, QString(), &ok);
+ if(ok && !channelName.isEmpty()) {
+ Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId),
+ QString("/JOIN %1").arg(channelName));
+ }
+# endif
+ break;
+ }
+ case ShowChannelList:
+ emit showChannelList(networkId);
+ break;
+ case ShowIgnoreList:
+ emit showIgnoreList(networkId);
+ break;
+ default:
+ break;
+ }
+}
+
+void NetworkModelActionProvider::handleNickAction(ActionType type, QAction *) {
+
+
+}
+
+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;
+ }
+}
--- /dev/null
+/***************************************************************************
+* 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
+
+#include "action.h"
+#include "actioncollection.h"
+#include "messagefilter.h"
+#include "quasselui.h"
+
+class NetworkModelActionProvider : public AbstractActionProvider {
+ Q_OBJECT
+
+public:
+ NetworkModelActionProvider(QObject *parent = 0);
+ ~NetworkModelActionProvider();
+
+ // 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,
+ BufferRemove = 0x30,
+
+ // Hide actions
+ HideMask = 0x0f00,
+ HideJoin = 0x0100,
+ HidePart = 0x0200,
+ HideQuit = 0x0300,
+ HideNick = 0x0400,
+ HideMode = 0x0500,
+ HideDayChange = 0x0600,
+ HideApplyToAll = 0xf00,
+
+ // General actions
+ GeneralMask = 0xf000,
+ JoinChannel = 0x1000,
+ ShowChannelList = 0x2000,
+ ShowIgnoreList = 0x3000,
+
+ // Nick actions
+ NickMask = 0xff0000,
+ NickCtcpWhois = 0x010000,
+ NickCtcpVersion = 0x020000,
+ NickCtcpPing = 0x030000,
+ NickCtcpTime = 0x040000,
+ NickCtcpFinger = 0x050000,
+ NickOp = 0x080000,
+ NickDeop = 0x090000,
+ NickVoice = 0x0a0000,
+ NickDevoice = 0x0b0000,
+ 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
+ ExternalMask = 0xff000000,
+ HideBufferTemporarily = 0x01000000,
+ HideBufferPermanently = 0x02000000
+ };
+
+ inline Action *action(ActionType type) const;
+
+ //! Provide a list of actions applying to the given item
+ /**
+ * Note that this list ist not persistent, hence it should only be used immediately after
+ * calling this function (e.g. in a context menu). Optionally one can provide a QObject and a slot
+ * (that should take a QAction * as parameter) that is invoked for actions that require external
+ * handling.
+ * @param index The item index in the NetworkModel
+ * @param receiver The optional object that is notified for actions that need to be handled externally.
+ * The action type will be stored in the QAction's data().
+ * @param slot The receiving slot name; should be "mySlot" rather than SLOT(mySlot(QAction *))
+ * @return A list of actions applying to the given item
+ */
+ void addActions(QMenu *, const QModelIndex &index, QObject *receiver = 0, const char *slot = 0, bool allowBufferHide = false);
+ void addActions(QMenu *, const QList<QModelIndex> &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);
+
+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 *);
+
+ bool checkRequirements(const QModelIndex &index, ItemActiveStates requiredActiveState = QFlags<ItemActiveState>(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<ItemActiveState>(ActiveState | InactiveState));
+ Action * addAction(Action * , QMenu *, const QModelIndex &index, ItemActiveStates requiredActiveState = QFlags<ItemActiveState>(ActiveState | InactiveState));
+
+ void addHideEventsMenu(QMenu *, BufferId bufferId);
+ void addHideEventsMenu(QMenu *, MessageFilter *msgFilter);
+ void addHideEventsMenu(QMenu *, int filter);
+
+ void addNetworkItemActions(QMenu *, const QModelIndex &);
+ void addBufferItemActions(QMenu *, const QModelIndex &, bool isCustomBufferView = false);
+ void addIrcUserActions(QMenu *, IrcUser *ircUser, bool isNickView = true);
+
+ NetworkModel *_model;
+
+ ActionCollection *_actionCollection;
+ QHash<ActionType, Action *> _actionByType;
+
+ Action *_hideEventsMenuAction;
+
+ QList<QModelIndex> _indexList;
+ MessageFilter *_messageFilter;
+ QObject *_receiver;
+ const char *_method;
+};
+
+// inlines
+ActionCollection *NetworkModelActionProvider::actionCollection() const { return _actionCollection; }
+Action *NetworkModelActionProvider::action(ActionType type) const { return _actionByType.value(type, 0); }
+#endif