Properly initialize _messageFilter in all cases, fixes #482
[quassel.git] / src / uisupport / networkmodelactionprovider.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-09 by the Quassel Project                          *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) version 3.                                           *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 #include <QInputDialog>
22 #include <QMenu>
23 #include <QMessageBox>
24
25 #include "networkmodelactionprovider.h"
26
27 #include "buffermodel.h"
28 #include "buffersettings.h"
29 #include "iconloader.h"
30 #include "clientidentity.h"
31 #include "network.h"
32 #include "util.h"
33
34 NetworkModelActionProvider::NetworkModelActionProvider(QObject *parent)
35 : AbstractActionProvider(parent),
36   _actionCollection(new ActionCollection(this)),
37   _messageFilter(0),
38   _receiver(0)
39 {
40   registerAction(NetworkConnect, SmallIcon("network-connect"), tr("Connect"));
41   registerAction(NetworkDisconnect, SmallIcon("network-disconnect"), tr("Disconnect"));
42
43   registerAction(BufferJoin, tr("Join"));
44   registerAction(BufferPart, tr("Part"));
45   registerAction(BufferRemove, tr("Delete Buffer(s)..."));
46   registerAction(BufferSwitchTo, tr("Show Buffer"));
47
48   registerAction(HideJoin, tr("Joins"), true);
49   registerAction(HidePart, tr("Parts"), true);
50   registerAction(HideQuit, tr("Quits"), true);
51   registerAction(HideNick, tr("Nick Changes"), true);
52   registerAction(HideMode, tr("Mode Changes"), true);
53   registerAction(HideDayChange, tr("Day Changes"), true);
54   registerAction(HideApplyToAll, tr("Set as Default..."));
55   registerAction(HideUseDefaults, tr("Use Defaults..."));
56
57   registerAction(JoinChannel, tr("Join Channel..."));
58
59   registerAction(NickQuery, tr("Start Query"));
60   registerAction(NickSwitchTo, tr("Show Query"));
61   registerAction(NickWhois, tr("Whois"));
62
63   registerAction(NickCtcpVersion, tr("Version"));
64   registerAction(NickCtcpTime, tr("Time"));
65   registerAction(NickCtcpPing, tr("Ping"));
66   registerAction(NickCtcpFinger, tr("Finger"));
67
68   registerAction(NickOp, tr("Give Operator Status"));
69   registerAction(NickDeop, tr("Take Operator Status"));
70   registerAction(NickVoice, tr("Give Voice"));
71   registerAction(NickDevoice, tr("Take Voice"));
72   registerAction(NickKick, tr("Kick From Channel"));
73   registerAction(NickBan, tr("Ban From Channel"));
74   registerAction(NickKickBan, tr("Kick && Ban"));
75
76   registerAction(HideBufferTemporarily, tr("Hide Buffer(s) Temporarily"));
77   registerAction(HideBufferPermanently, tr("Hide Buffer(s) Permanently"));
78   registerAction(ShowChannelList, SmallIcon("format-list-unordered"), tr("Show Channel List"));
79   registerAction(ShowIgnoreList, tr("Show Ignore List"));
80
81   connect(_actionCollection, SIGNAL(actionTriggered(QAction *)), SLOT(actionTriggered(QAction *)));
82
83   QMenu *hideEventsMenu = new QMenu();
84   hideEventsMenu->addAction(action(HideJoin));
85   hideEventsMenu->addAction(action(HidePart));
86   hideEventsMenu->addAction(action(HideQuit));
87   hideEventsMenu->addAction(action(HideNick));
88   hideEventsMenu->addAction(action(HideMode));
89   hideEventsMenu->addAction(action(HideDayChange));
90   hideEventsMenu->addSeparator();
91   hideEventsMenu->addAction(action(HideApplyToAll));
92   hideEventsMenu->addAction(action(HideUseDefaults));
93   _hideEventsMenuAction = new Action(tr("Hide Events"), 0);
94   _hideEventsMenuAction->setMenu(hideEventsMenu);
95
96   QMenu *nickCtcpMenu = new QMenu();
97   nickCtcpMenu->addAction(action(NickCtcpPing));
98   nickCtcpMenu->addAction(action(NickCtcpVersion));
99   nickCtcpMenu->addAction(action(NickCtcpTime));
100   nickCtcpMenu->addAction(action(NickCtcpFinger));
101   _nickCtcpMenuAction = new Action(tr("CTCP"), 0);
102   _nickCtcpMenuAction->setMenu(nickCtcpMenu);
103
104   QMenu *nickModeMenu = new QMenu();
105   nickModeMenu->addAction(action(NickOp));
106   nickModeMenu->addAction(action(NickDeop));
107   nickModeMenu->addAction(action(NickVoice));
108   nickModeMenu->addAction(action(NickDevoice));
109   nickModeMenu->addSeparator();
110   nickModeMenu->addAction(action(NickKick));
111   nickModeMenu->addAction(action(NickBan));
112   nickModeMenu->addAction(action(NickKickBan));
113   _nickModeMenuAction = new Action(tr("Actions"), 0);
114   _nickModeMenuAction->setMenu(nickModeMenu);
115 }
116
117 NetworkModelActionProvider::~NetworkModelActionProvider() {
118   _hideEventsMenuAction->menu()->deleteLater();
119   _hideEventsMenuAction->deleteLater();
120   _nickCtcpMenuAction->menu()->deleteLater();
121   _nickCtcpMenuAction->deleteLater();
122   _nickModeMenuAction->menu()->deleteLater();
123   _nickModeMenuAction->deleteLater();
124 }
125
126 void NetworkModelActionProvider::registerAction(ActionType type, const QString &text, bool checkable) {
127   registerAction(type, QPixmap(), text, checkable);
128 }
129
130 void NetworkModelActionProvider::registerAction(ActionType type, const QPixmap &icon, const QString &text, bool checkable) {
131   Action *act;
132   if(icon.isNull())
133     act = new Action(text, this);
134   else
135     act = new Action(icon, text, this);
136
137   act->setCheckable(checkable);
138   act->setData(type);
139
140   _actionCollection->addAction(QString::number(type, 16), act);
141   _actionByType[type] = act;
142 }
143
144 void NetworkModelActionProvider::addActions(QMenu *menu, BufferId bufId, QObject *receiver, const char *method) {
145   if(!bufId.isValid())
146     return;
147   _messageFilter = 0;
148   _contextItem = QString();
149   addActions(menu, Client::networkModel()->bufferIndex(bufId), receiver, method);
150 }
151
152 void NetworkModelActionProvider::addActions(QMenu *menu, const QModelIndex &index, QObject *receiver, const char *method, bool isCustomBufferView) {
153   if(!index.isValid())
154     return;
155   _messageFilter = 0;
156   _contextItem = QString();
157   addActions(menu, QList<QModelIndex>() << index, receiver, method, isCustomBufferView);
158 }
159
160 void NetworkModelActionProvider::addActions(QMenu *menu, MessageFilter *filter, BufferId msgBuffer, QObject *receiver, const char *slot) {
161   addActions(menu, filter, msgBuffer, QString(), receiver, slot);
162 }
163
164 void NetworkModelActionProvider::addActions(QMenu *menu, MessageFilter *filter, BufferId msgBuffer, const QString &chanOrNick, QObject *receiver, const char *method) {
165   if(!filter)
166     return;
167   _messageFilter = filter;
168   _contextItem = chanOrNick;
169   addActions(menu, QList<QModelIndex>() << Client::networkModel()->bufferIndex(msgBuffer), receiver, method);
170 }
171
172 void NetworkModelActionProvider::addActions(QMenu *menu, const QList<QModelIndex> &indexList, QObject *receiver,  const char *method, bool isCustomBufferView) {
173   addActions(menu, indexList, 0, receiver, method, isCustomBufferView);
174 }
175
176 // add a list of actions sensible for the current item(s)
177 void NetworkModelActionProvider::addActions(QMenu *menu,
178                                             const QList<QModelIndex> &indexList,
179                                             MessageFilter *filter,
180                                             QObject *receiver,
181                                             const char *method,
182                                             bool isCustomBufferView)
183 {
184   if(!indexList.count())
185     return;
186
187   _indexList = indexList;
188   _messageFilter = filter;
189   _receiver = receiver;
190   _method = method;
191
192   if(!_messageFilter) {
193     // this means we are in a BufferView (or NickView) rather than a ChatView
194
195     // first index in list determines the menu type (just in case we have both buffers and networks selected, for example)
196     QModelIndex index = _indexList.at(0);
197     NetworkModel::ItemType itemType = static_cast<NetworkModel::ItemType>(index.data(NetworkModel::ItemTypeRole).toInt());
198
199     switch(itemType) {
200       case NetworkModel::NetworkItemType:
201         addNetworkItemActions(menu, index);
202         break;
203       case NetworkModel::BufferItemType:
204         addBufferItemActions(menu, index, isCustomBufferView);
205         break;
206       case NetworkModel::IrcUserItemType:
207         addIrcUserActions(menu, index);
208         break;
209       default:
210         return;
211
212     }
213   } else {
214     // ChatView actions
215     if(_contextItem.isEmpty()) {
216       // a) query buffer: handle like ircuser
217       // b) general chatview: handle like channel iff it displays a single buffer
218       // NOTE stuff breaks probably with merged buffers, need to rework a lot around here then
219       if(_messageFilter->containedBuffers().count() == 1) {
220         // we can handle this like a single bufferItem
221         QModelIndex index = Client::networkModel()->bufferIndex(_messageFilter->containedBuffers().values().at(0));
222         _indexList = QList<QModelIndex>() << index;
223         addBufferItemActions(menu, index);
224         return;
225       } else {
226         // TODO: actions for merged buffers... _indexList contains the index of the message we clicked on
227
228       }
229     } else {
230       // context item = chan or nick, _indexList = buf where the msg clicked on originated
231       if(isChannelName(_contextItem)) {
232         QModelIndex msgIdx = _indexList.at(0);
233         if(!msgIdx.isValid())
234           return;
235         NetworkId networkId = msgIdx.data(NetworkModel::NetworkIdRole).value<NetworkId>();
236         BufferId bufId = Client::networkModel()->bufferId(networkId, _contextItem);
237         if(bufId.isValid()) {
238           QModelIndex targetIdx = Client::networkModel()->bufferIndex(bufId);
239           _indexList = QList<QModelIndex>() << targetIdx;
240           addAction(BufferJoin, menu, targetIdx, InactiveState);
241           addAction(BufferSwitchTo, menu, targetIdx, ActiveState);
242         } else
243           addAction(JoinChannel, menu);
244       } else {
245         // TODO: actions for a nick
246       }
247     }
248   }
249 }
250
251 void NetworkModelActionProvider::addNetworkItemActions(QMenu *menu, const QModelIndex &index) {
252   NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
253   if(!networkId.isValid())
254     return;
255   const Network *network = Client::network(networkId);
256   Q_CHECK_PTR(network);
257   if(!network)
258     return;
259
260   addAction(NetworkConnect, menu, network->connectionState() == Network::Disconnected);
261   addAction(NetworkDisconnect, menu, network->connectionState() != Network::Disconnected);
262   menu->addSeparator();
263   addAction(ShowChannelList, menu, index, ActiveState);
264   addAction(JoinChannel, menu, index, ActiveState);
265
266 }
267
268 void NetworkModelActionProvider::addBufferItemActions(QMenu *menu, const QModelIndex &index, bool isCustomBufferView) {
269   BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
270
271   switch(bufferInfo.type()) {
272     case BufferInfo::ChannelBuffer:
273       addAction(BufferJoin, menu, index, InactiveState);
274       addAction(BufferPart, menu, index, ActiveState);
275       menu->addSeparator();
276       addHideEventsMenu(menu, bufferInfo.bufferId());
277       menu->addSeparator();
278       addAction(HideBufferTemporarily, menu, isCustomBufferView);
279       addAction(HideBufferPermanently, menu, isCustomBufferView);
280       addAction(BufferRemove, menu, index, InactiveState);
281       break;
282
283     case BufferInfo::QueryBuffer:
284     {
285       //IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
286       //if(ircUser) {
287         addIrcUserActions(menu, index);
288         menu->addSeparator();
289       //}
290       addHideEventsMenu(menu, bufferInfo.bufferId());
291       menu->addSeparator();
292       addAction(HideBufferTemporarily, menu, isCustomBufferView);
293       addAction(HideBufferPermanently, menu, isCustomBufferView);
294       addAction(BufferRemove, menu, index);
295       break;
296     }
297
298     default:
299       addAction(HideBufferTemporarily, menu, isCustomBufferView);
300       addAction(HideBufferPermanently, menu, isCustomBufferView);
301   }
302 }
303
304 void NetworkModelActionProvider::addIrcUserActions(QMenu *menu, const QModelIndex &index) {
305   // this can be called: a) as a nicklist context menu (index has IrcUserItemType)
306   //                     b) as a query buffer context menu (index has BufferItemType and is a QueryBufferItem)
307   //                     c) right-click in a query chatview (same as b), index will be the corresponding QueryBufferItem)
308   //                     d) right-click on some nickname (_contextItem will be non-null, _filter -> chatview, index -> message buffer)
309
310   if(_contextItem.isNull()) {
311     // cases a, b, c
312     bool haveQuery = _indexList.count() == 1 && findQueryBuffer(index).isValid();
313     NetworkModel::ItemType itemType = static_cast<NetworkModel::ItemType>(index.data(NetworkModel::ItemTypeRole).toInt());
314     addAction(_nickModeMenuAction, menu, itemType == NetworkModel::IrcUserItemType);
315     addAction(_nickCtcpMenuAction, menu);
316     menu->addSeparator();
317     addAction(NickQuery, menu, itemType == NetworkModel::IrcUserItemType && !haveQuery && _indexList.count() == 1);
318     addAction(NickSwitchTo, menu, itemType == NetworkModel::IrcUserItemType && haveQuery);
319     menu->addSeparator();
320     addAction(NickWhois, menu, true);
321
322   } else if(!_contextItem.isEmpty() && _messageFilter) {
323     // case d
324     // TODO
325
326   }
327 }
328
329 /******** Helper Functions ***********************************************************************/
330
331 bool NetworkModelActionProvider::checkRequirements(const QModelIndex &index, ItemActiveStates requiredActiveState) {
332   if(!index.isValid())
333     return false;
334
335   ItemActiveStates isActive = index.data(NetworkModel::ItemActiveRole).toBool()
336   ? ActiveState
337   : InactiveState;
338
339   if(!(isActive & requiredActiveState))
340     return false;
341
342   return true;
343 }
344
345 Action * NetworkModelActionProvider::addAction(ActionType type , QMenu *menu, const QModelIndex &index, ItemActiveStates requiredActiveState) {
346   return addAction(action(type), menu, checkRequirements(index, requiredActiveState));
347 }
348
349 Action * NetworkModelActionProvider::addAction(Action *action , QMenu *menu, const QModelIndex &index, ItemActiveStates requiredActiveState) {
350   return addAction(action, menu, checkRequirements(index, requiredActiveState));
351 }
352
353 Action * NetworkModelActionProvider::addAction(ActionType type , QMenu *menu, bool condition) {
354   return addAction(action(type), menu, condition);
355 }
356
357 Action * NetworkModelActionProvider::addAction(Action *action , QMenu *menu, bool condition) {
358   if(condition) {
359     menu->addAction(action);
360     action->setVisible(true);
361   } else {
362     action->setVisible(false);
363   }
364   return action;
365 }
366
367 void NetworkModelActionProvider::addHideEventsMenu(QMenu *menu, BufferId bufferId) {
368   if(BufferSettings(bufferId).hasFilter())
369     addHideEventsMenu(menu, BufferSettings(bufferId).messageFilter());
370   else
371     addHideEventsMenu(menu);
372 }
373
374 void NetworkModelActionProvider::addHideEventsMenu(QMenu *menu, MessageFilter *msgFilter) {
375   if(BufferSettings(msgFilter->idString()).hasFilter())
376     addHideEventsMenu(menu, BufferSettings(msgFilter->idString()).messageFilter());
377   else
378     addHideEventsMenu(menu);
379 }
380
381 void NetworkModelActionProvider::addHideEventsMenu(QMenu *menu, int filter) {
382   action(HideApplyToAll)->setEnabled(filter != -1);
383   action(HideUseDefaults)->setEnabled(filter != -1);
384   if(filter == -1)
385     filter = BufferSettings().messageFilter();
386
387   action(HideJoin)->setChecked(filter & Message::Join);
388   action(HidePart)->setChecked(filter & Message::Part);
389   action(HideQuit)->setChecked(filter & Message::Quit);
390   action(HideNick)->setChecked(filter & Message::Nick);
391   action(HideMode)->setChecked(filter & Message::Mode);
392   action(HideDayChange)->setChecked(filter & Message::DayChange);
393
394   menu->addAction(_hideEventsMenuAction);
395 }
396
397 QString NetworkModelActionProvider::nickName(const QModelIndex &index) const {
398   IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
399   if(ircUser)
400     return ircUser->nick();
401
402   BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
403   if(!bufferInfo.isValid())
404     return QString();
405   if(!bufferInfo.type() == BufferInfo::QueryBuffer)
406     return QString();
407
408   return bufferInfo.bufferName(); // FIXME this might break with merged queries maybe
409 }
410
411 BufferId NetworkModelActionProvider::findQueryBuffer(const QModelIndex &index, const QString &predefinedNick) const {
412   NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
413   if(!networkId.isValid())
414     return BufferId();
415
416   QString nick = predefinedNick.isEmpty() ? nickName(index) : predefinedNick;
417   if(nick.isEmpty())
418     return BufferId();
419
420   return findQueryBuffer(networkId, nick);
421 }
422
423 BufferId NetworkModelActionProvider::findQueryBuffer(NetworkId networkId, const QString &nick) const {
424   return Client::networkModel()->bufferId(networkId, nick);
425 }
426
427 void NetworkModelActionProvider::handleExternalAction(ActionType type, QAction *action) {
428   Q_UNUSED(type);
429   if(_receiver && _method) {
430     if(!QMetaObject::invokeMethod(_receiver, _method, Q_ARG(QAction *, action)))
431       qWarning() << "NetworkModelActionProvider::handleExternalAction(): Could not invoke slot" << _receiver << _method;
432   }
433 }
434
435 /******** Handle Actions *************************************************************************/
436
437 void NetworkModelActionProvider::actionTriggered(QAction *action) {
438   ActionType type = (ActionType)action->data().toInt();
439   if(type > 0) {
440     if(type & NetworkMask)
441       handleNetworkAction(type, action);
442     else if(type & BufferMask)
443       handleBufferAction(type, action);
444     else if(type & HideMask)
445       handleHideAction(type, action);
446     else if(type & GeneralMask)
447       handleGeneralAction(type, action);
448     else if(type & NickMask)
449       handleNickAction(type, action);
450     else if(type & ExternalMask)
451       handleExternalAction(type, action);
452     else
453       qWarning() << "NetworkModelActionProvider::actionTriggered(): Unhandled action!";
454   }
455   _indexList.clear();
456   _messageFilter = 0;
457   _receiver = 0;
458 }
459
460 void NetworkModelActionProvider::handleNetworkAction(ActionType type, QAction *) {
461   if(!_indexList.count())
462     return;
463   const Network *network = Client::network(_indexList.at(0).data(NetworkModel::NetworkIdRole).value<NetworkId>());
464   Q_CHECK_PTR(network);
465   if(!network)
466     return;
467
468   switch(type) {
469     case NetworkConnect:
470       network->requestConnect();
471       break;
472     case NetworkDisconnect:
473       network->requestDisconnect();
474       break;
475     default:
476       break;
477   }
478 }
479
480 void NetworkModelActionProvider::handleBufferAction(ActionType type, QAction *) {
481   if(type == BufferRemove) {
482     removeBuffers(_indexList);
483   } else {
484
485     foreach(QModelIndex index, _indexList) {
486       BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
487       if(!bufferInfo.isValid())
488         continue;
489
490       switch(type) {
491         case BufferJoin:
492           Client::userInput(bufferInfo, QString("/JOIN %1").arg(bufferInfo.bufferName()));
493           break;
494         case BufferPart:
495         {
496           QString reason = Client::identity(Client::network(bufferInfo.networkId())->identity())->partReason();
497           Client::userInput(bufferInfo, QString("/PART %1").arg(reason));
498           break;
499         }
500         case BufferSwitchTo:
501           Client::bufferModel()->switchToBuffer(bufferInfo.bufferId());
502           break;
503         default:
504           break;
505       }
506     }
507   }
508 }
509
510 void NetworkModelActionProvider::removeBuffers(const QModelIndexList &indexList) {
511   QList<BufferInfo> inactive;
512   foreach(QModelIndex index, indexList) {
513     BufferInfo info = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
514     if(info.isValid()) {
515       if(info.type() == BufferInfo::QueryBuffer
516         || (info.type() == BufferInfo::ChannelBuffer && !index.data(NetworkModel::ItemActiveRole).toBool()))
517           inactive << info;
518     }
519   }
520   QString msg;
521   if(inactive.count()) {
522     msg = tr("Do you want to delete the following buffer(s) permanently?", 0, inactive.count());
523     msg += "<ul>";
524     foreach(BufferInfo info, inactive)
525       msg += QString("<li>%1</li>").arg(info.bufferName());
526     msg += "</ul>";
527     msg += tr("<b>Note:</b> This will delete all related data, including all backlog data, from the core's database and cannot be undone.");
528     if(inactive.count() != indexList.count())
529       msg += tr("<br>Active channel buffers cannot be deleted, please part the channel first.");
530
531     if(QMessageBox::question(0, tr("Remove buffers permanently?"), msg, QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) {
532       foreach(BufferInfo info, inactive)
533         Client::removeBuffer(info.bufferId());
534     }
535   }
536 }
537
538 void NetworkModelActionProvider::handleHideAction(ActionType type, QAction *action) {
539   Q_UNUSED(action)
540
541   int filter = 0;
542   if(NetworkModelActionProvider::action(HideJoin)->isChecked())
543     filter |= Message::Join;
544   if(NetworkModelActionProvider::action(HidePart)->isChecked())
545     filter |= Message::Part;
546   if(NetworkModelActionProvider::action(HideQuit)->isChecked())
547     filter |= Message::Quit;
548   if(NetworkModelActionProvider::action(HideNick)->isChecked())
549     filter |= Message::Nick;
550   if(NetworkModelActionProvider::action(HideMode)->isChecked())
551     filter |= Message::Mode;
552   if(NetworkModelActionProvider::action(HideDayChange)->isChecked())
553     filter |= Message::DayChange;
554
555   switch(type) {
556   case HideJoin:
557   case HidePart:
558   case HideQuit:
559   case HideNick:
560   case HideMode:
561   case HideDayChange:
562     if(_messageFilter)
563       BufferSettings(_messageFilter->idString()).setMessageFilter(filter);
564     else {
565       foreach(QModelIndex index, _indexList) {
566         BufferId bufferId = index.data(NetworkModel::BufferIdRole).value<BufferId>();
567         if(!bufferId.isValid())
568           continue;
569         BufferSettings(bufferId).setMessageFilter(filter);
570       }
571     }
572     return;
573   case HideApplyToAll:
574     BufferSettings().setMessageFilter(filter);
575   case HideUseDefaults:
576     if(_messageFilter)
577       BufferSettings(_messageFilter->idString()).removeFilter();
578     else {
579       foreach(QModelIndex index, _indexList) {
580         BufferId bufferId = index.data(NetworkModel::BufferIdRole).value<BufferId>();
581         if(!bufferId.isValid())
582           continue;
583         BufferSettings(bufferId).removeFilter();
584       }
585     }
586     return;
587   default:
588     return;
589   };
590 }
591
592 void NetworkModelActionProvider::handleGeneralAction(ActionType type, QAction *action) {
593   Q_UNUSED(action)
594
595   if(!_indexList.count())
596     return;
597   NetworkId networkId = _indexList.at(0).data(NetworkModel::NetworkIdRole).value<NetworkId>();
598   if(!networkId.isValid())
599     return;
600
601   switch(type) {
602     case JoinChannel: {
603       QString channelName = _contextItem;
604       if(channelName.isEmpty()) {
605         bool ok;
606         channelName = QInputDialog::getText(0, tr("Join Channel"), tr("Input channel name:"), QLineEdit::Normal, QString(), &ok);
607         if(!ok)
608           return;
609       }
610       if(!channelName.isEmpty()) {
611         Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId), QString("/JOIN %1").arg(channelName));
612       }
613       break;
614     }
615     case ShowChannelList:
616       emit showChannelList(networkId);
617       break;
618     case ShowIgnoreList:
619       emit showIgnoreList(networkId);
620       break;
621     default:
622       break;
623   }
624 }
625
626 void NetworkModelActionProvider::handleNickAction(ActionType type, QAction *) {
627   foreach(QModelIndex index, _indexList) {
628     NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
629     if(!networkId.isValid())
630       continue;
631     QString nick = nickName(index);
632     if(nick.isEmpty())
633       continue;
634     BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
635     if(!bufferInfo.isValid())
636       continue;
637
638     switch(type) {
639       case NickWhois:
640         Client::userInput(bufferInfo, QString("/WHOIS %1 %1").arg(nick));
641         break;
642       case NickCtcpVersion:
643         Client::userInput(bufferInfo, QString("/CTCP %1 VERSION").arg(nick));
644         break;
645       case NickCtcpPing:
646         Client::userInput(bufferInfo, QString("/CTCP %1 PING").arg(nick));
647         break;
648       case NickCtcpTime:
649         Client::userInput(bufferInfo, QString("/CTCP %1 TIME").arg(nick));
650         break;
651       case NickCtcpFinger:
652         Client::userInput(bufferInfo, QString("/CTCP %1 FINGER").arg(nick));
653         break;
654       case NickOp:
655         Client::userInput(bufferInfo, QString("/OP %1").arg(nick));
656         break;
657       case NickDeop:
658         Client::userInput(bufferInfo, QString("/DEOP %1").arg(nick));
659         break;
660       case NickVoice:
661         Client::userInput(bufferInfo, QString("/VOICE %1").arg(nick));
662         break;
663       case NickDevoice:
664         Client::userInput(bufferInfo, QString("/DEVOICE %1").arg(nick));
665         break;
666       case NickKick:
667         Client::userInput(bufferInfo, QString("/KICK %1").arg(nick));
668         break;
669       case NickBan:
670         Client::userInput(bufferInfo, QString("/BAN %1").arg(nick));
671         break;
672       case NickKickBan:
673         Client::userInput(bufferInfo, QString("/BAN %1").arg(nick));
674         Client::userInput(bufferInfo, QString("/KICK %1").arg(nick));
675         break;
676       case NickSwitchTo:
677         Client::bufferModel()->switchToBuffer(findQueryBuffer(networkId, nick));
678         break;
679       case NickQuery:
680         Client::userInput(bufferInfo, QString("/QUERY %1").arg(nick));
681         break;
682       default:
683         qWarning() << "Unhandled nick action";
684     }
685   }
686 }