1 /***************************************************************************
2 * Copyright (C) 2005-2015 by the Quassel Project *
3 * devel@quassel-irc.org *
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. *
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. *
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 ***************************************************************************/
22 #include <QDialogButtonBox>
23 #include <QGridLayout>
27 #include <QInputDialog>
28 #include <QMessageBox>
29 #include <QPushButton>
31 #include "networkmodelcontroller.h"
33 #include "buffermodel.h"
34 #include "buffersettings.h"
35 #include "clientidentity.h"
38 #include "clientignorelistmanager.h"
41 NetworkModelController::NetworkModelController(QObject *parent)
43 _actionCollection(new ActionCollection(this)),
47 connect(_actionCollection, SIGNAL(actionTriggered(QAction *)), SLOT(actionTriggered(QAction *)));
51 NetworkModelController::~NetworkModelController()
56 Action *NetworkModelController::registerAction(ActionType type, const QString &text, bool checkable)
58 return registerAction(type, QPixmap(), text, checkable);
62 Action *NetworkModelController::registerAction(ActionType type, const QIcon &icon, const QString &text, bool checkable)
66 act = new Action(text, this);
68 act = new Action(icon, text, this);
70 act->setCheckable(checkable);
73 _actionCollection->addAction(QString::number(type, 16), act);
74 _actionByType[type] = act;
79 /******** Helper Functions ***********************************************************************/
81 void NetworkModelController::setIndexList(const QModelIndex &index)
83 _indexList = QList<QModelIndex>() << index;
87 void NetworkModelController::setIndexList(const QList<QModelIndex> &list)
93 void NetworkModelController::setMessageFilter(MessageFilter *filter)
95 _messageFilter = filter;
99 void NetworkModelController::setContextItem(const QString &contextItem)
101 _contextItem = contextItem;
105 void NetworkModelController::setSlot(QObject *receiver, const char *method)
107 _receiver = receiver;
112 bool NetworkModelController::checkRequirements(const QModelIndex &index, ItemActiveStates requiredActiveState)
114 if (!index.isValid())
117 ItemActiveStates isActive = index.data(NetworkModel::ItemActiveRole).toBool()
121 if (!(isActive & requiredActiveState))
128 QString NetworkModelController::nickName(const QModelIndex &index) const
130 IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
132 return ircUser->nick();
134 BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
135 if (!bufferInfo.isValid())
137 if (bufferInfo.type() != BufferInfo::QueryBuffer)
140 return bufferInfo.bufferName(); // FIXME this might break with merged queries maybe
144 BufferId NetworkModelController::findQueryBuffer(const QModelIndex &index, const QString &predefinedNick) const
146 NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
147 if (!networkId.isValid())
150 QString nick = predefinedNick.isEmpty() ? nickName(index) : predefinedNick;
154 return findQueryBuffer(networkId, nick);
158 BufferId NetworkModelController::findQueryBuffer(NetworkId networkId, const QString &nick) const
160 return Client::networkModel()->bufferId(networkId, nick);
164 void NetworkModelController::removeBuffers(const QModelIndexList &indexList)
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()))
176 if (inactive.count()) {
177 msg = tr("Do you want to delete the following buffer(s) permanently?", 0, inactive.count());
180 foreach(BufferInfo info, inactive) {
182 msg += QString("<li>%1</li>").arg(info.bufferName());
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.");
195 if (QMessageBox::question(0, tr("Remove buffers permanently?"), msg, QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) {
196 foreach(BufferInfo info, inactive)
197 Client::removeBuffer(info.bufferId());
203 void NetworkModelController::handleExternalAction(ActionType type, QAction *action)
206 if (receiver() && method()) {
207 if (!QMetaObject::invokeMethod(receiver(), method(), Q_ARG(QAction *, action)))
208 qWarning() << "NetworkModelActionController::handleExternalAction(): Could not invoke slot" << receiver() << method();
213 /******** Handle Actions *************************************************************************/
215 void NetworkModelController::actionTriggered(QAction *action)
217 ActionType type = (ActionType)action->data().toInt();
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);
232 qWarning() << "NetworkModelController::actionTriggered(): Unhandled action!";
237 void NetworkModelController::handleNetworkAction(ActionType type, QAction *)
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();
250 if (!indexList().count())
253 const Network *network = Client::network(indexList().at(0).data(NetworkModel::NetworkIdRole).value<NetworkId>());
254 Q_CHECK_PTR(network);
260 network->requestConnect();
262 case NetworkDisconnect:
263 network->requestDisconnect();
271 void NetworkModelController::handleBufferAction(ActionType type, QAction *)
273 if (type == BufferRemove) {
274 removeBuffers(indexList());
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;
284 foreach(BufferInfo bufferInfo, bufferList) {
287 Client::userInput(bufferInfo, QString("/JOIN %1").arg(bufferInfo.bufferName()));
291 QString reason = Client::identity(Client::network(bufferInfo.networkId())->identity())->partReason();
292 Client::userInput(bufferInfo, QString("/PART %1").arg(reason));
296 Client::bufferModel()->switchToBuffer(bufferInfo.bufferId());
306 void NetworkModelController::handleHideAction(ActionType type, QAction *action)
310 if (type == HideJoinPartQuit) {
311 bool anyChecked = NetworkModelController::action(HideJoin)->isChecked();
312 anyChecked |= NetworkModelController::action(HidePart)->isChecked();
313 anyChecked |= NetworkModelController::action(HideQuit)->isChecked();
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);
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;
334 if (NetworkModelController::action(HideDayChange)->isChecked())
335 filter |= Message::DayChange;
336 if (NetworkModelController::action(HideTopic)->isChecked())
337 filter |= Message::Topic;
340 case HideJoinPartQuit:
349 BufferSettings(_messageFilter->idString()).setMessageFilter(filter);
351 foreach(QModelIndex index, _indexList) {
352 BufferId bufferId = index.data(NetworkModel::BufferIdRole).value<BufferId>();
353 if (!bufferId.isValid())
355 BufferSettings(bufferId).setMessageFilter(filter);
360 BufferSettings().setMessageFilter(filter);
361 case HideUseDefaults:
363 BufferSettings(_messageFilter->idString()).removeFilter();
365 foreach(QModelIndex index, _indexList) {
366 BufferId bufferId = index.data(NetworkModel::BufferIdRole).value<BufferId>();
367 if (!bufferId.isValid())
369 BufferSettings(bufferId).removeFilter();
379 void NetworkModelController::handleGeneralAction(ActionType type, QAction *action)
383 if (!indexList().count())
385 NetworkId networkId = indexList().at(0).data(NetworkModel::NetworkIdRole).value<NetworkId>();
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();
400 if (!channelName.isEmpty()) {
401 if (!channelPassword.isEmpty())
402 Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId), QString("/JOIN %1 %2").arg(channelName).arg(channelPassword));
404 Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId), QString("/JOIN %1").arg(channelName));
408 case ShowChannelList:
409 if (networkId.isValid())
410 emit showChannelList(networkId);
413 if (networkId.isValid())
414 emit showIgnoreList(QString());
422 void NetworkModelController::handleNickAction(ActionType type, QAction *action)
424 foreach(QModelIndex index, indexList()) {
425 NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
426 if (!networkId.isValid())
428 QString nick = nickName(index);
431 BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
432 if (!bufferInfo.isValid())
437 Client::userInput(bufferInfo, QString("/WHOIS %1 %1").arg(nick));
439 case NickCtcpVersion:
440 Client::userInput(bufferInfo, QString("/CTCP %1 VERSION").arg(nick));
443 Client::userInput(bufferInfo, QString("/CTCP %1 PING").arg(nick));
446 Client::userInput(bufferInfo, QString("/CTCP %1 TIME").arg(nick));
448 case NickCtcpClientinfo:
449 Client::userInput(bufferInfo, QString("/CTCP %1 CLIENTINFO").arg(nick));
452 Client::userInput(bufferInfo, QString("/OP %1").arg(nick));
455 Client::userInput(bufferInfo, QString("/DEOP %1").arg(nick));
458 Client::userInput(bufferInfo, QString("/HALFOP %1").arg(nick));
461 Client::userInput(bufferInfo, QString("/DEHALFOP %1").arg(nick));
464 Client::userInput(bufferInfo, QString("/VOICE %1").arg(nick));
467 Client::userInput(bufferInfo, QString("/DEVOICE %1").arg(nick));
470 Client::userInput(bufferInfo, QString("/KICK %1").arg(nick));
473 Client::userInput(bufferInfo, QString("/BAN %1").arg(nick));
476 Client::userInput(bufferInfo, QString("/BAN %1").arg(nick));
477 Client::userInput(bufferInfo, QString("/KICK %1").arg(nick));
481 Client::bufferModel()->switchToOrStartQuery(networkId, nick);
485 IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
488 Client::ignoreListManager()->requestAddIgnoreListItem(IgnoreListManager::SenderIgnore,
489 action->property("ignoreRule").toString(),
490 false, IgnoreListManager::SoftStrictness,
491 IgnoreListManager::NetworkScope,
492 ircUser->network()->networkName(), true);
497 IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
500 Client::ignoreListManager()->requestAddIgnoreListItem(IgnoreListManager::SenderIgnore,
501 action->property("ignoreRule").toString(),
502 false, IgnoreListManager::SoftStrictness,
503 IgnoreListManager::NetworkScope,
504 ircUser->network()->networkName(), true);
507 case NickIgnoreDomain:
509 IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
512 Client::ignoreListManager()->requestAddIgnoreListItem(IgnoreListManager::SenderIgnore,
513 action->property("ignoreRule").toString(),
514 false, IgnoreListManager::SoftStrictness,
515 IgnoreListManager::NetworkScope,
516 ircUser->network()->networkName(), true);
519 case NickIgnoreCustom:
520 // forward that to mainwin since we can access the settingspage only from there
521 emit showIgnoreList(action->property("ignoreRule").toString());
523 case NickIgnoreToggleEnabled0:
524 case NickIgnoreToggleEnabled1:
525 case NickIgnoreToggleEnabled2:
526 case NickIgnoreToggleEnabled3:
527 case NickIgnoreToggleEnabled4:
528 Client::ignoreListManager()->requestToggleIgnoreRule(action->property("ignoreRule").toString());
531 qWarning() << "Unhandled nick action";
537 /***************************************************************************************************************
539 ***************************************************************************************************************/
541 NetworkModelController::JoinDlg::JoinDlg(const QModelIndex &index, QWidget *parent) : QDialog(parent)
543 setWindowIcon(QIcon::fromTheme("irc-join-channel"));
544 setWindowTitle(tr("Join Channel"));
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);
557 buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
558 networks->setInsertPolicy(QComboBox::InsertAlphabetically);
559 password->setEchoMode(QLineEdit::Password);
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)));
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));
572 if (index.isValid()) {
573 NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
574 if (networkId.isValid()) {
575 networks->setCurrentIndex(networks->findText(Client::network(networkId)->networkName()));
576 if (index.data(NetworkModel::BufferTypeRole) == BufferInfo::ChannelBuffer
577 && !index.data(NetworkModel::ItemActiveRole).toBool())
578 channel->setText(index.data(Qt::DisplayRole).toString());
584 NetworkId NetworkModelController::JoinDlg::networkId() const
586 return networks->itemData(networks->currentIndex()).value<NetworkId>();
590 QString NetworkModelController::JoinDlg::channelName() const
592 return channel->text();
596 QString NetworkModelController::JoinDlg::channelPassword() const
598 return password->text();
602 void NetworkModelController::JoinDlg::on_channel_textChanged(const QString &text)
604 buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty());