1 /***************************************************************************
2 * Copyright (C) 2005-2018 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 ***************************************************************************/
21 #include "networkmodelcontroller.h"
24 #include <QDialogButtonBox>
25 #include <QGridLayout>
29 #include <QInputDialog>
30 #include <QMessageBox>
31 #include <QPushButton>
33 #include "buffermodel.h"
34 #include "buffersettings.h"
36 #include "clientidentity.h"
37 #include "clientignorelistmanager.h"
42 NetworkModelController::NetworkModelController(QObject *parent)
44 _actionCollection(new ActionCollection(this))
46 connect(_actionCollection, SIGNAL(actionTriggered(QAction *)), SLOT(actionTriggered(QAction *)));
50 NetworkModelController::~NetworkModelController()
55 Action *NetworkModelController::registerAction(ActionType type, const QString &text, bool checkable)
57 return registerAction(type, QPixmap(), text, checkable);
61 Action *NetworkModelController::registerAction(ActionType type, const QIcon &icon, const QString &text, bool checkable)
65 act = new Action(text, this);
67 act = new Action(icon, text, this);
69 act->setCheckable(checkable);
72 _actionCollection->addAction(QString::number(type, 16), act);
73 _actionByType[type] = act;
78 /******** Helper Functions ***********************************************************************/
80 void NetworkModelController::setIndexList(const QModelIndex &index)
82 _indexList = QList<QModelIndex>() << index;
86 void NetworkModelController::setIndexList(const QList<QModelIndex> &list)
92 void NetworkModelController::setMessageFilter(MessageFilter *filter)
94 _messageFilter = filter;
98 void NetworkModelController::setContextItem(const QString &contextItem)
100 _contextItem = contextItem;
104 void NetworkModelController::setSlot(QObject *receiver, const char *method)
106 _receiver = receiver;
111 bool NetworkModelController::checkRequirements(const QModelIndex &index, ItemActiveStates requiredActiveState)
113 if (!index.isValid())
116 ItemActiveStates isActive = index.data(NetworkModel::ItemActiveRole).toBool()
120 if (!(isActive & requiredActiveState))
127 QString NetworkModelController::nickName(const QModelIndex &index) const
129 IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
131 return ircUser->nick();
133 BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
134 if (!bufferInfo.isValid())
136 if (bufferInfo.type() != BufferInfo::QueryBuffer)
139 return bufferInfo.bufferName(); // FIXME this might break with merged queries maybe
143 BufferId NetworkModelController::findQueryBuffer(const QModelIndex &index, const QString &predefinedNick) const
145 NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
146 if (!networkId.isValid())
149 QString nick = predefinedNick.isEmpty() ? nickName(index) : predefinedNick;
153 return findQueryBuffer(networkId, nick);
157 BufferId NetworkModelController::findQueryBuffer(NetworkId networkId, const QString &nick) const
159 return Client::networkModel()->bufferId(networkId, nick);
163 void NetworkModelController::removeBuffers(const QModelIndexList &indexList)
165 QList<BufferInfo> inactive;
166 foreach(QModelIndex index, indexList) {
167 BufferInfo info = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
168 if (info.isValid()) {
169 if (info.type() == BufferInfo::QueryBuffer
170 || (info.type() == BufferInfo::ChannelBuffer && !index.data(NetworkModel::ItemActiveRole).toBool()))
175 if (inactive.count()) {
176 msg = tr("Do you want to delete the following buffer(s) permanently?", "", inactive.count());
179 foreach(BufferInfo info, inactive) {
181 msg += QString("<li>%1</li>").arg(info.bufferName());
188 if (count > 9 && inactive.size() - count != 0)
189 msg += tr("...and <b>%1</b> more<br><br>").arg(inactive.size() - count);
190 msg += tr("<b>Note:</b> This will delete all related data, including all backlog data, from the core's database and cannot be undone.");
191 if (inactive.count() != indexList.count())
192 msg += tr("<br>Active channel buffers cannot be deleted, please part the channel first.");
194 if (QMessageBox::question(nullptr, tr("Remove buffers permanently?"), msg, QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) {
195 foreach(BufferInfo info, inactive)
196 Client::removeBuffer(info.bufferId());
202 void NetworkModelController::handleExternalAction(ActionType type, QAction *action)
205 if (receiver() && method()) {
206 if (!QMetaObject::invokeMethod(receiver(), method(), Q_ARG(QAction *, action)))
207 qWarning() << "NetworkModelActionController::handleExternalAction(): Could not invoke slot" << receiver() << method();
212 /******** Handle Actions *************************************************************************/
214 void NetworkModelController::actionTriggered(QAction *action)
216 ActionType type = (ActionType)action->data().toInt();
218 if (type & NetworkMask)
219 handleNetworkAction(type, action);
220 else if (type & BufferMask)
221 handleBufferAction(type, action);
222 else if (type & HideMask)
223 handleHideAction(type, action);
224 else if (type & GeneralMask)
225 handleGeneralAction(type, action);
226 else if (type & NickMask)
227 handleNickAction(type, action);
228 else if (type & ExternalMask)
229 handleExternalAction(type, action);
231 qWarning() << "NetworkModelController::actionTriggered(): Unhandled action!";
236 void NetworkModelController::handleNetworkAction(ActionType type, QAction *)
238 if (type == NetworkConnectAllWithDropdown || type == NetworkDisconnectAllWithDropdown || type == NetworkConnectAll || type == NetworkDisconnectAll) {
239 if (type == NetworkConnectAllWithDropdown && QMessageBox::question(nullptr, tr("Question"), tr("Really Connect to all IRC Networks?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::No)
241 if (type == NetworkDisconnectAllWithDropdown && QMessageBox::question(nullptr, tr("Question"), tr("Really disconnect from all IRC Networks?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No)
243 foreach(NetworkId id, Client::networkIds()) {
244 const Network *net = Client::network(id);
245 if ((type == NetworkConnectAllWithDropdown || type == NetworkConnectAll) && net->connectionState() == Network::Disconnected)
246 net->requestConnect();
247 if ((type == NetworkDisconnectAllWithDropdown || type == NetworkDisconnectAll) && net->connectionState() != Network::Disconnected)
248 net->requestDisconnect();
253 if (!indexList().count())
256 const Network *network = Client::network(indexList().at(0).data(NetworkModel::NetworkIdRole).value<NetworkId>());
257 Q_CHECK_PTR(network);
263 network->requestConnect();
265 case NetworkDisconnect:
266 network->requestDisconnect();
274 void NetworkModelController::handleBufferAction(ActionType type, QAction *)
276 if (type == BufferRemove) {
277 removeBuffers(indexList());
280 QList<BufferInfo> bufferList; // create temp list because model indexes might change
281 foreach(QModelIndex index, indexList()) {
282 BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
283 if (bufferInfo.isValid())
284 bufferList << bufferInfo;
287 foreach(BufferInfo bufferInfo, bufferList) {
290 Client::userInput(bufferInfo, QString("/JOIN %1").arg(bufferInfo.bufferName()));
294 QString reason = Client::identity(Client::network(bufferInfo.networkId())->identity())->partReason();
295 Client::userInput(bufferInfo, QString("/PART %1").arg(reason));
299 Client::bufferModel()->switchToBuffer(bufferInfo.bufferId());
309 void NetworkModelController::handleHideAction(ActionType type, QAction *action)
313 if (type == HideJoinPartQuit) {
314 bool anyChecked = NetworkModelController::action(HideJoin)->isChecked();
315 anyChecked |= NetworkModelController::action(HidePart)->isChecked();
316 anyChecked |= NetworkModelController::action(HideQuit)->isChecked();
318 // If any are checked, uncheck them all.
319 // If none are checked, check them all.
320 bool newCheckedState = !anyChecked;
321 NetworkModelController::action(HideJoin)->setChecked(newCheckedState);
322 NetworkModelController::action(HidePart)->setChecked(newCheckedState);
323 NetworkModelController::action(HideQuit)->setChecked(newCheckedState);
327 if (NetworkModelController::action(HideJoin)->isChecked())
328 filter |= Message::Join | Message::NetsplitJoin;
329 if (NetworkModelController::action(HidePart)->isChecked())
330 filter |= Message::Part;
331 if (NetworkModelController::action(HideQuit)->isChecked())
332 filter |= Message::Quit | Message::NetsplitQuit;
333 if (NetworkModelController::action(HideNick)->isChecked())
334 filter |= Message::Nick;
335 if (NetworkModelController::action(HideMode)->isChecked())
336 filter |= Message::Mode;
337 if (NetworkModelController::action(HideDayChange)->isChecked())
338 filter |= Message::DayChange;
339 if (NetworkModelController::action(HideTopic)->isChecked())
340 filter |= Message::Topic;
343 case HideJoinPartQuit:
352 BufferSettings(_messageFilter->idString()).setMessageFilter(filter);
354 foreach(QModelIndex index, _indexList) {
355 BufferId bufferId = index.data(NetworkModel::BufferIdRole).value<BufferId>();
356 if (!bufferId.isValid())
358 BufferSettings(bufferId).setMessageFilter(filter);
363 BufferSettings().setMessageFilter(filter);
365 case HideUseDefaults:
367 BufferSettings(_messageFilter->idString()).removeFilter();
369 foreach(QModelIndex index, _indexList) {
370 BufferId bufferId = index.data(NetworkModel::BufferIdRole).value<BufferId>();
371 if (!bufferId.isValid())
373 BufferSettings(bufferId).removeFilter();
383 void NetworkModelController::handleGeneralAction(ActionType type, QAction *action)
387 if (!indexList().count())
389 NetworkId networkId = indexList().at(0).data(NetworkModel::NetworkIdRole).value<NetworkId>();
394 QString channelName = contextItem();
395 QString channelPassword;
396 if (channelName.isEmpty()) {
397 JoinDlg dlg(indexList().first());
398 if (dlg.exec() == QDialog::Accepted) {
399 channelName = dlg.channelName();
400 networkId = dlg.networkId();
401 channelPassword = dlg.channelPassword();
404 if (!channelName.isEmpty()) {
405 if (!channelPassword.isEmpty())
406 Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId), QString("/JOIN %1 %2").arg(channelName).arg(channelPassword));
408 Client::instance()->userInput(BufferInfo::fakeStatusBuffer(networkId), QString("/JOIN %1").arg(channelName));
412 case ShowChannelList:
413 if (networkId.isValid()) {
414 // Don't immediately list channels, allowing customization of filter first
415 emit showChannelList(networkId, {}, false);
418 case ShowNetworkConfig:
419 if (networkId.isValid())
420 emit showNetworkConfig(networkId);
423 if (networkId.isValid())
424 emit showIgnoreList(QString());
432 void NetworkModelController::handleNickAction(ActionType type, QAction *action)
434 foreach(QModelIndex index, indexList()) {
435 NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
436 if (!networkId.isValid())
438 QString nick = nickName(index);
441 BufferInfo bufferInfo = index.data(NetworkModel::BufferInfoRole).value<BufferInfo>();
442 if (!bufferInfo.isValid())
447 Client::userInput(bufferInfo, QString("/WHOIS %1 %1").arg(nick));
449 case NickCtcpVersion:
450 Client::userInput(bufferInfo, QString("/CTCP %1 VERSION").arg(nick));
453 Client::userInput(bufferInfo, QString("/CTCP %1 PING").arg(nick));
456 Client::userInput(bufferInfo, QString("/CTCP %1 TIME").arg(nick));
458 case NickCtcpClientinfo:
459 Client::userInput(bufferInfo, QString("/CTCP %1 CLIENTINFO").arg(nick));
462 Client::userInput(bufferInfo, QString("/OP %1").arg(nick));
465 Client::userInput(bufferInfo, QString("/DEOP %1").arg(nick));
468 Client::userInput(bufferInfo, QString("/HALFOP %1").arg(nick));
471 Client::userInput(bufferInfo, QString("/DEHALFOP %1").arg(nick));
474 Client::userInput(bufferInfo, QString("/VOICE %1").arg(nick));
477 Client::userInput(bufferInfo, QString("/DEVOICE %1").arg(nick));
480 Client::userInput(bufferInfo, QString("/KICK %1").arg(nick));
483 Client::userInput(bufferInfo, QString("/BAN %1").arg(nick));
486 Client::userInput(bufferInfo, QString("/BAN %1").arg(nick));
487 Client::userInput(bufferInfo, QString("/KICK %1").arg(nick));
491 Client::bufferModel()->switchToOrStartQuery(networkId, nick);
495 IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
498 Client::ignoreListManager()->requestAddIgnoreListItem(IgnoreListManager::SenderIgnore,
499 action->property("ignoreRule").toString(),
500 false, IgnoreListManager::SoftStrictness,
501 IgnoreListManager::NetworkScope,
502 ircUser->network()->networkName(), true);
507 IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
510 Client::ignoreListManager()->requestAddIgnoreListItem(IgnoreListManager::SenderIgnore,
511 action->property("ignoreRule").toString(),
512 false, IgnoreListManager::SoftStrictness,
513 IgnoreListManager::NetworkScope,
514 ircUser->network()->networkName(), true);
517 case NickIgnoreDomain:
519 IrcUser *ircUser = qobject_cast<IrcUser *>(index.data(NetworkModel::IrcUserRole).value<QObject *>());
522 Client::ignoreListManager()->requestAddIgnoreListItem(IgnoreListManager::SenderIgnore,
523 action->property("ignoreRule").toString(),
524 false, IgnoreListManager::SoftStrictness,
525 IgnoreListManager::NetworkScope,
526 ircUser->network()->networkName(), true);
529 case NickIgnoreCustom:
530 // forward that to mainwin since we can access the settingspage only from there
531 emit showIgnoreList(action->property("ignoreRule").toString());
533 case NickIgnoreToggleEnabled0:
534 case NickIgnoreToggleEnabled1:
535 case NickIgnoreToggleEnabled2:
536 case NickIgnoreToggleEnabled3:
537 case NickIgnoreToggleEnabled4:
538 Client::ignoreListManager()->requestToggleIgnoreRule(action->property("ignoreRule").toString());
541 qWarning() << "Unhandled nick action";
547 /***************************************************************************************************************
549 ***************************************************************************************************************/
551 NetworkModelController::JoinDlg::JoinDlg(const QModelIndex &index, QWidget *parent) : QDialog(parent)
553 setWindowIcon(icon::get("irc-join-channel"));
554 setWindowTitle(tr("Join Channel"));
556 QGridLayout *layout = new QGridLayout(this);
557 layout->addWidget(new QLabel(tr("Network:")), 0, 0);
558 layout->addWidget(networks = new QComboBox, 0, 1);
559 layout->addWidget(new QLabel(tr("Channel:")), 1, 0);
560 layout->addWidget(channel = new QLineEdit, 1, 1);
561 layout->addWidget(new QLabel(tr("Password:")), 2, 0);
562 layout->addWidget(password = new QLineEdit, 2, 1);
563 layout->addWidget(buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel), 3, 0, 1, 2);
567 buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
568 networks->setInsertPolicy(QComboBox::InsertAlphabetically);
569 password->setEchoMode(QLineEdit::Password);
571 connect(buttonBox, SIGNAL(accepted()), SLOT(accept()));
572 connect(buttonBox, SIGNAL(rejected()), SLOT(reject()));
573 connect(channel, SIGNAL(textChanged(QString)), SLOT(on_channel_textChanged(QString)));
575 foreach(NetworkId id, Client::networkIds()) {
576 const Network *net = Client::network(id);
577 if (net->isConnected()) {
578 networks->addItem(net->networkName(), QVariant::fromValue<NetworkId>(id));
582 if (index.isValid()) {
583 NetworkId networkId = index.data(NetworkModel::NetworkIdRole).value<NetworkId>();
584 if (networkId.isValid()) {
585 networks->setCurrentIndex(networks->findText(Client::network(networkId)->networkName()));
586 if (index.data(NetworkModel::BufferTypeRole) == BufferInfo::ChannelBuffer
587 && !index.data(NetworkModel::ItemActiveRole).toBool())
588 channel->setText(index.data(Qt::DisplayRole).toString());
594 NetworkId NetworkModelController::JoinDlg::networkId() const
596 return networks->itemData(networks->currentIndex()).value<NetworkId>();
600 QString NetworkModelController::JoinDlg::channelName() const
602 return channel->text();
606 QString NetworkModelController::JoinDlg::channelPassword() const
608 return password->text();
612 void NetworkModelController::JoinDlg::on_channel_textChanged(const QString &text)
614 buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty());