Quassel IRC  Pre-Release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
networkmodelcontroller.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2015 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  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19  ***************************************************************************/
20 
21 #include <QComboBox>
22 #include <QDialogButtonBox>
23 #include <QGridLayout>
24 #include <QIcon>
25 #include <QLabel>
26 #include <QLineEdit>
27 #include <QInputDialog>
28 #include <QMessageBox>
29 #include <QPushButton>
30 
31 #include "networkmodelcontroller.h"
32 
33 #include "buffermodel.h"
34 #include "buffersettings.h"
35 #include "clientidentity.h"
36 #include "network.h"
37 #include "util.h"
39 #include "client.h"
40 
42  : QObject(parent),
43  _actionCollection(new ActionCollection(this)),
44  _messageFilter(0),
45  _receiver(0)
46 {
47  connect(_actionCollection, SIGNAL(actionTriggered(QAction *)), SLOT(actionTriggered(QAction *)));
48 }
49 
50 
52 {
53 }
54 
55 
56 Action *NetworkModelController::registerAction(ActionType type, const QString &text, bool checkable)
57 {
58  return registerAction(type, QPixmap(), text, checkable);
59 }
60 
61 
62 Action *NetworkModelController::registerAction(ActionType type, const QIcon &icon, const QString &text, bool checkable)
63 {
64  Action *act;
65  if (icon.isNull())
66  act = new Action(text, this);
67  else
68  act = new Action(icon, text, this);
69 
70  act->setCheckable(checkable);
71  act->setData(type);
72 
73  _actionCollection->addAction(QString::number(type, 16), act);
74  _actionByType[type] = act;
75  return act;
76 }
77 
78 
79 /******** Helper Functions ***********************************************************************/
80 
81 void NetworkModelController::setIndexList(const QModelIndex &index)
82 {
83  _indexList = QList<QModelIndex>() << index;
84 }
85 
86 
87 void NetworkModelController::setIndexList(const QList<QModelIndex> &list)
88 {
89  _indexList = list;
90 }
91 
92 
94 {
95  _messageFilter = filter;
96 }
97 
98 
99 void NetworkModelController::setContextItem(const QString &contextItem)
100 {
102 }
103 
104 
105 void NetworkModelController::setSlot(QObject *receiver, const char *method)
106 {
108  _method = method;
109 }
110 
111 
112 bool NetworkModelController::checkRequirements(const QModelIndex &index, ItemActiveStates requiredActiveState)
113 {
114  if (!index.isValid())
115  return false;
116 
117  ItemActiveStates isActive = index.data(NetworkModel::ItemActiveRole).toBool()
118  ? ActiveState
119  : InactiveState;
120 
121  if (!(isActive & requiredActiveState))
122  return false;
123 
124  return true;
125 }
126 
127 
128 QString NetworkModelController::nickName(const QModelIndex &index) const
129 {
130  IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
131  if (ircUser)
132  return ircUser->nick();
133 
134  BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
135  if (!bufferInfo.isValid())
136  return QString();
137  if (bufferInfo.type() != BufferInfo::QueryBuffer)
138  return QString();
139 
140  return bufferInfo.bufferName(); // FIXME this might break with merged queries maybe
141 }
142 
143 
144 BufferId NetworkModelController::findQueryBuffer(const QModelIndex &index, const QString &predefinedNick) const
145 {
146  NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
147  if (!networkId.isValid())
148  return BufferId();
149 
150  QString nick = predefinedNick.isEmpty() ? nickName(index) : predefinedNick;
151  if (nick.isEmpty())
152  return BufferId();
153 
154  return findQueryBuffer(networkId, nick);
155 }
156 
157 
158 BufferId NetworkModelController::findQueryBuffer(NetworkId networkId, const QString &nick) const
159 {
160  return Client::networkModel()->bufferId(networkId, nick);
161 }
162 
163 
164 void NetworkModelController::removeBuffers(const QModelIndexList &indexList)
165 {
166  QList<BufferInfo> inactive;
167  foreach(QModelIndex index, indexList) {
168  BufferInfo info = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
169  if (info.isValid()) {
170  if (info.type() == BufferInfo::QueryBuffer
171  || (info.type() == BufferInfo::ChannelBuffer && !index.data(NetworkModel::ItemActiveRole).toBool()))
172  inactive << info;
173  }
174  }
175  QString msg;
176  if (inactive.count()) {
177  msg = tr("Do you want to delete the following buffer(s) permanently?", 0, inactive.count());
178  msg += "<ul>";
179  int count = 0;
180  foreach(BufferInfo info, inactive) {
181  if (count < 10) {
182  msg += QString("<li>%1</li>").arg(info.bufferName());
183  count++;
184  }
185  else
186  break;
187  }
188  msg += "</ul>";
189  if (count > 9 && inactive.size() - count != 0)
190  msg += tr("...and <b>%1</b> more<br><br>").arg(inactive.size() - count);
191  msg += tr("<b>Note:</b> This will delete all related data, including all backlog data, from the core's database and cannot be undone.");
192  if (inactive.count() != indexList.count())
193  msg += tr("<br>Active channel buffers cannot be deleted, please part the channel first.");
194 
195  if (QMessageBox::question(0, tr("Remove buffers permanently?"), msg, QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) {
196  foreach(BufferInfo info, inactive)
198  }
199  }
200 }
201 
202 
204 {
205  Q_UNUSED(type);
206  if (receiver() && method()) {
207  if (!QMetaObject::invokeMethod(receiver(), method(), Q_ARG(QAction *, action)))
208  qWarning() << "NetworkModelActionController::handleExternalAction(): Could not invoke slot" << receiver() << method();
209  }
210 }
211 
212 
213 /******** Handle Actions *************************************************************************/
214 
216 {
217  ActionType type = (ActionType)action->data().toInt();
218  if (type > 0) {
219  if (type & NetworkMask)
220  handleNetworkAction(type, action);
221  else if (type & BufferMask)
222  handleBufferAction(type, action);
223  else if (type & HideMask)
224  handleHideAction(type, action);
225  else if (type & GeneralMask)
226  handleGeneralAction(type, action);
227  else if (type & NickMask)
228  handleNickAction(type, action);
229  else if (type & ExternalMask)
230  handleExternalAction(type, action);
231  else
232  qWarning() << "NetworkModelController::actionTriggered(): Unhandled action!";
233  }
234 }
235 
236 
238 {
239  if (type == NetworkConnectAll || type == NetworkDisconnectAll) {
240  foreach(NetworkId id, Client::networkIds()) {
241  const Network *net = Client::network(id);
242  if (type == NetworkConnectAll && net->connectionState() == Network::Disconnected)
243  net->requestConnect();
244  if (type == NetworkDisconnectAll && net->connectionState() != Network::Disconnected)
245  net->requestDisconnect();
246  }
247  return;
248  }
249 
250  if (!indexList().count())
251  return;
252 
253  const Network *network = Client::network(indexList().at(0).data(NetworkModel::NetworkIdRole).value<NetworkId>());
254  Q_CHECK_PTR(network);
255  if (!network)
256  return;
257 
258  switch (type) {
259  case NetworkConnect:
260  network->requestConnect();
261  break;
262  case NetworkDisconnect:
263  network->requestDisconnect();
264  break;
265  default:
266  break;
267  }
268 }
269 
270 
272 {
273  if (type == BufferRemove) {
275  }
276  else {
277  QList<BufferInfo> bufferList; // create temp list because model indexes might change
278  foreach(QModelIndex index, indexList()) {
279  BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
280  if (bufferInfo.isValid())
281  bufferList << bufferInfo;
282  }
283 
284  foreach(BufferInfo bufferInfo, bufferList) {
285  switch (type) {
286  case BufferJoin:
287  Client::userInput(bufferInfo, QString("/JOIN %1").arg(bufferInfo.bufferName()));
288  break;
289  case BufferPart:
290  {
291  QString reason = Client::identity(Client::network(bufferInfo.networkId())->identity())->partReason();
292  Client::userInput(bufferInfo, QString("/PART %1").arg(reason));
293  break;
294  }
295  case BufferSwitchTo:
297  break;
298  default:
299  break;
300  }
301  }
302  }
303 }
304 
305 
307 {
308  Q_UNUSED(action)
309 
310  if (type == HideJoinPartQuit) {
311  bool anyChecked = NetworkModelController::action(HideJoin)->isChecked();
312  anyChecked |= NetworkModelController::action(HidePart)->isChecked();
313  anyChecked |= NetworkModelController::action(HideQuit)->isChecked();
314 
315  // If any are checked, uncheck them all.
316  // If none are checked, check them all.
317  bool newCheckedState = !anyChecked;
318  NetworkModelController::action(HideJoin)->setChecked(newCheckedState);
319  NetworkModelController::action(HidePart)->setChecked(newCheckedState);
320  NetworkModelController::action(HideQuit)->setChecked(newCheckedState);
321  }
322 
323  int filter = 0;
324  if (NetworkModelController::action(HideJoin)->isChecked())
325  filter |= Message::Join | Message::NetsplitJoin;
326  if (NetworkModelController::action(HidePart)->isChecked())
327  filter |= Message::Part;
328  if (NetworkModelController::action(HideQuit)->isChecked())
329  filter |= Message::Quit | Message::NetsplitQuit;
330  if (NetworkModelController::action(HideNick)->isChecked())
331  filter |= Message::Nick;
332  if (NetworkModelController::action(HideMode)->isChecked())
333  filter |= Message::Mode;
335  filter |= Message::DayChange;
336  if (NetworkModelController::action(HideTopic)->isChecked())
337  filter |= Message::Topic;
338 
339  switch (type) {
340  case HideJoinPartQuit:
341  case HideJoin:
342  case HidePart:
343  case HideQuit:
344  case HideNick:
345  case HideMode:
346  case HideDayChange:
347  case HideTopic:
348  if (_messageFilter)
350  else {
351  foreach(QModelIndex index, _indexList) {
352  BufferId bufferId = index.data(NetworkModel::BufferIdRole).value<BufferId>();
353  if (!bufferId.isValid())
354  continue;
355  BufferSettings(bufferId).setMessageFilter(filter);
356  }
357  }
358  return;
359  case HideApplyToAll:
361  case HideUseDefaults:
362  if (_messageFilter)
363  BufferSettings(_messageFilter->idString()).removeFilter();
364  else {
365  foreach(QModelIndex index, _indexList) {
366  BufferId bufferId = index.data(NetworkModel::BufferIdRole).value<BufferId>();
367  if (!bufferId.isValid())
368  continue;
369  BufferSettings(bufferId).removeFilter();
370  }
371  }
372  return;
373  default:
374  return;
375  };
376 }
377 
378 
380 {
381  Q_UNUSED(action)
382 
383  if (!indexList().count())
384  return;
385  NetworkId networkId = indexList().at(0).data(NetworkModel::NetworkIdRole).value<NetworkId>();
386 
387  switch (type) {
388  case JoinChannel:
389  {
390  QString channelName = contextItem();
391  QString channelPassword;
392  if (channelName.isEmpty()) {
393  JoinDlg dlg(indexList().first());
394  if (dlg.exec() == QDialog::Accepted) {
395  channelName = dlg.channelName();
396  networkId = dlg.networkId();
397  channelPassword = dlg.channelPassword();
398  }
399  }
400  if (!channelName.isEmpty()) {
401  if (!channelPassword.isEmpty())
402  Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId), QString("/JOIN %1 %2").arg(channelName).arg(channelPassword));
403  else
404  Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId), QString("/JOIN %1").arg(channelName));
405  }
406  break;
407  }
408  case ShowChannelList:
409  if (networkId.isValid())
410  emit showChannelList(networkId);
411  break;
412  case ShowIgnoreList:
413  if (networkId.isValid())
414  emit showIgnoreList(QString());
415  break;
416  default:
417  break;
418  }
419 }
420 
421 
423 {
424  foreach(QModelIndex index, indexList()) {
425  NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
426  if (!networkId.isValid())
427  continue;
428  QString nick = nickName(index);
429  if (nick.isEmpty())
430  continue;
431  BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
432  if (!bufferInfo.isValid())
433  continue;
434 
435  switch (type) {
436  case NickWhois:
437  Client::userInput(bufferInfo, QString("/WHOIS %1 %1").arg(nick));
438  break;
439  case NickCtcpVersion:
440  Client::userInput(bufferInfo, QString("/CTCP %1 VERSION").arg(nick));
441  break;
442  case NickCtcpPing:
443  Client::userInput(bufferInfo, QString("/CTCP %1 PING").arg(nick));
444  break;
445  case NickCtcpTime:
446  Client::userInput(bufferInfo, QString("/CTCP %1 TIME").arg(nick));
447  break;
448  case NickCtcpClientinfo:
449  Client::userInput(bufferInfo, QString("/CTCP %1 CLIENTINFO").arg(nick));
450  break;
451  case NickOp:
452  Client::userInput(bufferInfo, QString("/OP %1").arg(nick));
453  break;
454  case NickDeop:
455  Client::userInput(bufferInfo, QString("/DEOP %1").arg(nick));
456  break;
457  case NickHalfop:
458  Client::userInput(bufferInfo, QString("/HALFOP %1").arg(nick));
459  break;
460  case NickDehalfop:
461  Client::userInput(bufferInfo, QString("/DEHALFOP %1").arg(nick));
462  break;
463  case NickVoice:
464  Client::userInput(bufferInfo, QString("/VOICE %1").arg(nick));
465  break;
466  case NickDevoice:
467  Client::userInput(bufferInfo, QString("/DEVOICE %1").arg(nick));
468  break;
469  case NickKick:
470  Client::userInput(bufferInfo, QString("/KICK %1").arg(nick));
471  break;
472  case NickBan:
473  Client::userInput(bufferInfo, QString("/BAN %1").arg(nick));
474  break;
475  case NickKickBan:
476  Client::userInput(bufferInfo, QString("/BAN %1").arg(nick));
477  Client::userInput(bufferInfo, QString("/KICK %1").arg(nick));
478  break;
479  case NickSwitchTo:
480  case NickQuery:
481  Client::bufferModel()->switchToOrStartQuery(networkId, nick);
482  break;
483  case NickIgnoreUser:
484  {
485  IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
486  if (!ircUser)
487  break;
489  action->property("ignoreRule").toString(),
492  ircUser->network()->networkName(), true);
493  break;
494  }
495  case NickIgnoreHost:
496  {
497  IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
498  if (!ircUser)
499  break;
501  action->property("ignoreRule").toString(),
504  ircUser->network()->networkName(), true);
505  break;
506  }
507  case NickIgnoreDomain:
508  {
509  IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
510  if (!ircUser)
511  break;
513  action->property("ignoreRule").toString(),
516  ircUser->network()->networkName(), true);
517  break;
518  }
519  case NickIgnoreCustom:
520  // forward that to mainwin since we can access the settingspage only from there
521  emit showIgnoreList(action->property("ignoreRule").toString());
522  break;
528  Client::ignoreListManager()->requestToggleIgnoreRule(action->property("ignoreRule").toString());
529  break;
530  default:
531  qWarning() << "Unhandled nick action";
532  }
533  }
534 }
535 
536 
537 /***************************************************************************************************************
538  * JoinDlg
539  ***************************************************************************************************************/
540 
541 NetworkModelController::JoinDlg::JoinDlg(const QModelIndex &index, QWidget *parent) : QDialog(parent)
542 {
543  setWindowIcon(QIcon::fromTheme("irc-join-channel"));
544  setWindowTitle(tr("Join Channel"));
545 
546  QGridLayout *layout = new QGridLayout(this);
547  layout->addWidget(new QLabel(tr("Network:")), 0, 0);
548  layout->addWidget(networks = new QComboBox, 0, 1);
549  layout->addWidget(new QLabel(tr("Channel:")), 1, 0);
550  layout->addWidget(channel = new QLineEdit, 1, 1);
551  layout->addWidget(new QLabel(tr("Password:")), 2, 0);
552  layout->addWidget(password = new QLineEdit, 2, 1);
553  layout->addWidget(buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel), 3, 0, 1, 2);
554  setLayout(layout);
555 
556  channel->setFocus();
557  buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
558  networks->setInsertPolicy(QComboBox::InsertAlphabetically);
559  password->setEchoMode(QLineEdit::Password);
560 
561  connect(buttonBox, SIGNAL(accepted()), SLOT(accept()));
562  connect(buttonBox, SIGNAL(rejected()), SLOT(reject()));
563  connect(channel, SIGNAL(textChanged(QString)), SLOT(on_channel_textChanged(QString)));
564 
565  foreach(NetworkId id, Client::networkIds()) {
566  const Network *net = Client::network(id);
567  if (net->isConnected()) {
568  networks->addItem(net->networkName(), QVariant::fromValue<NetworkId>(id));
569  }
570  }
571 
572  if (index.isValid()) {
574  if (networkId.isValid()) {
575  networks->setCurrentIndex(networks->findText(Client::network(networkId)->networkName()));
577  && !index.data(NetworkModel::ItemActiveRole).toBool())
578  channel->setText(index.data(Qt::DisplayRole).toString());
579  }
580  }
581 }
582 
583 
585 {
586  return networks->itemData(networks->currentIndex()).value<NetworkId>();
587 }
588 
589 
591 {
592  return channel->text();
593 }
594 
595 
597 {
598  return password->text();
599 }
600 
601 
603 {
604  buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty());
605 }