1 /*
2 SPDX-License-Identifier: GPL-2.0-or-later
3
4 SPDX-FileCopyrightText: 2005-2007 Peter Simonsson <psn@linux.se>
5 SPDX-FileCopyrightText: 2006 Dario Abatianni <eisfuchs@tigress.com>
6 SPDX-FileCopyrightText: 2006-2007 Eike Hein <hein@kde.org>
7 */
8
9 #include "channeloptionsdialog.h"
10
11 #include "application.h"
12 #include "topichistorymodel.h"
13 #include "konversation_log.h"
14
15 #include <KColorScheme>
16 #include <KSharedConfig>
17 #include <KConfigGroup>
18
19 #include <QCheckBox>
20 #include <QPushButton>
21 #include <QRegularExpression>
22 #include <QStandardItemModel>
23 #include <QItemSelectionModel>
24 #include <QTreeWidget>
25 #include <QDialogButtonBox>
26 #include <QVBoxLayout>
27 #include <QLocale>
28
29 namespace Konversation
30 {
ChannelOptionsDialog(Channel * channel)31 ChannelOptionsDialog::ChannelOptionsDialog(Channel *channel)
32 : QDialog(channel)
33 {
34 setWindowTitle( i18n("Channel Settings for %1", channel->getName() ) );
35 auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
36 auto *mainWidget = new QWidget(this);
37 auto *mainLayout = new QVBoxLayout;
38 setLayout(mainLayout);
39 mainLayout->addWidget(mainWidget);
40 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
41 okButton->setDefault(true);
42 okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
43 connect(buttonBox, &QDialogButtonBox::accepted, this, &ChannelOptionsDialog::changeOptions);
44 connect(buttonBox, &QDialogButtonBox::rejected, this, &ChannelOptionsDialog::reject);
45 mainLayout->addWidget(buttonBox);
46 buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
47
48 Q_ASSERT(channel);
49 m_channel = channel;
50
51 m_ui.setupUi(mainWidget);
52
53 m_ui.addBan->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
54 m_ui.updateBan->setIcon(QIcon::fromTheme(QStringLiteral("edit-rename")));
55 m_ui.removeBan->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
56
57 auto *modesModel = new QStandardItemModel(m_ui.otherModesList);
58 m_ui.otherModesList->setModel(modesModel);
59 m_ui.otherModesList->hide();
60
61 m_ui.banListSearchLine->setTreeWidget(m_ui.banList);
62
63 m_ui.topicHistoryView->setServer(m_channel->getServer());
64 m_ui.topicHistoryView->setModel(m_channel->getTopicHistory());
65
66 m_historySearchTimer = new QTimer(this);
67 m_historySearchTimer->setSingleShot(true);
68
69 connect(m_historySearchTimer, &QTimer::timeout,
70 this, &ChannelOptionsDialog::updateHistoryFilter);
71
72 connect(m_ui.topicHistorySearchLine, &QLineEdit::textChanged,
73 this, &ChannelOptionsDialog::startHistorySearchTimer);
74
75 m_editingTopic = false;
76
77 m_ui.topicEdit->setChannel(channel);
78 m_ui.topicEdit->setMaximumLength(m_channel->getServer()->topicLength());
79
80 connect(m_ui.topicHistoryView->selectionModel(), &QItemSelectionModel::selectionChanged,
81 this, &ChannelOptionsDialog::topicHistoryItemClicked);
82 connect(m_ui.toggleAdvancedModes, &QPushButton::clicked, this, &ChannelOptionsDialog::toggleAdvancedModes);
83 connect(m_ui.topicEdit, &TopicEdit::undoAvailable, this, &ChannelOptionsDialog::topicBeingEdited);
84 connect(this, &ChannelOptionsDialog::finished, m_ui.topicEdit, &TopicEdit::clear);
85
86 connect(m_channel, &Channel::modesChanged, this, &ChannelOptionsDialog::refreshModes);
87 connect(m_channel->getServer(), &Server::channelNickChanged, this, [this]() { refreshEnableModes(); });
88
89 connect(m_channel, &Channel::banAdded, this, &ChannelOptionsDialog::addBan);
90 connect(m_channel, &Channel::banRemoved, this, &ChannelOptionsDialog::removeBan);
91 connect(m_channel, &Channel::banListCleared, m_ui.banList, &QTreeWidget::clear);
92
93 connect(m_ui.addBan, &QPushButton::clicked, this, &ChannelOptionsDialog::addBanClicked);
94 connect(m_ui.updateBan, &QPushButton::clicked, this, &ChannelOptionsDialog::updateBanClicked);
95 connect(m_ui.removeBan, &QPushButton::clicked, this, &ChannelOptionsDialog::removeBanClicked);
96 connect(m_ui.banList, &QTreeWidget::itemSelectionChanged, this, &ChannelOptionsDialog::banSelectionChanged);
97 connect(m_ui.hostmask, &KLineEdit::textChanged, this, &ChannelOptionsDialog::hostmaskChanged);
98
99 m_ui.topicModeChBox->setWhatsThis(whatsThisForMode('T'));
100 m_ui.messageModeChBox->setWhatsThis(whatsThisForMode('N'));
101 m_ui.secretModeChBox->setWhatsThis(whatsThisForMode('S'));
102 m_ui.inviteModeChBox->setWhatsThis(whatsThisForMode('I'));
103 m_ui.moderatedModeChBox->setWhatsThis(whatsThisForMode('M'));
104 m_ui.keyModeChBox->setWhatsThis(whatsThisForMode('P'));
105 m_ui.keyModeEdit->setWhatsThis(whatsThisForMode('P'));
106 m_ui.userLimitEdit->setWhatsThis(whatsThisForMode('L'));
107 m_ui.userLimitChBox->setWhatsThis(whatsThisForMode('L'));
108
109 refreshBanList();
110
111 resize(QSize(450, 420));
112 }
113
~ChannelOptionsDialog()114 ChannelOptionsDialog::~ChannelOptionsDialog()
115 {
116 }
117
showEvent(QShowEvent * event)118 void ChannelOptionsDialog::showEvent(QShowEvent* event)
119 {
120 if (!event->spontaneous())
121 {
122 refreshAllowedChannelModes();
123 refreshModes();
124
125 m_ui.topicEdit->clear();
126 m_editingTopic = false;
127
128 m_ui.topicHistoryView->selectionModel()->clearSelection();
129 const QModelIndex& currentTopic = m_ui.topicHistoryView->model()->index(m_ui.topicHistoryView->model()->rowCount() - 1, 0);
130 m_ui.topicHistoryView->selectionModel()->select(currentTopic, QItemSelectionModel::Select);
131 m_ui.topicHistoryView->scrollTo(currentTopic, QAbstractItemView::EnsureVisible);
132
133 if (!m_ui.topicEdit->isReadOnly())
134 m_ui.topicEdit->setFocus();
135
136 KConfigGroup config(KSharedConfig::openConfig(), "ChannelOptionsDialog");
137
138 resize(config.readEntry("Size", sizeHint()));
139
140 const QList<int>& sizes = config.readEntry("SplitterSizes", QList<int>());
141
142 if (!sizes.isEmpty())
143 m_ui.splitter->setSizes(sizes);
144
145 Preferences::restoreColumnState(m_ui.banList, QStringLiteral("BanList ViewSettings"));
146 }
147
148 QDialog::showEvent(event);
149 }
150
hideEvent(QHideEvent * event)151 void ChannelOptionsDialog::hideEvent(QHideEvent* event)
152 {
153 KConfigGroup config(KSharedConfig::openConfig(), "ChannelOptionsDialog");
154
155 config.writeEntry("Size", size());
156 config.writeEntry("SplitterSizes", m_ui.splitter->sizes());
157
158 Preferences::saveColumnState(m_ui.banList, QStringLiteral("BanList ViewSettings"));
159
160 QDialog::hideEvent(event);
161 }
162
changeOptions()163 void ChannelOptionsDialog::changeOptions()
164 {
165 const QString& newTopic = topic();
166 const QString& oldTopic = m_channel->getTopic();
167
168 if (newTopic != oldTopic)
169 {
170 // Pass a ^A so we can determine if we want to clear the channel topic.
171 if (newTopic.isEmpty())
172 {
173 if (!oldTopic.isEmpty())
174 m_channel->sendText(Preferences::self()->commandChar() + QLatin1String("TOPIC ") + m_channel->getName() + QLatin1String(" \x01"));
175 }
176 else
177 m_channel->sendText(Preferences::self()->commandChar() + QLatin1String("TOPIC ") + m_channel->getName() + QLatin1Char(' ') + newTopic);
178 }
179
180 const QStringList newModeList = modes();
181 const QStringList currentModeList = m_channel->getModeList();
182
183 QString command(QStringLiteral("MODE %1 %2%3 %4"));
184
185 for (const QString &mode : newModeList)
186 {
187 const QString modeString = mode.mid(1);
188 const bool plus = mode.at(0) == QLatin1Char('+');
189 const QStringList tmp = currentModeList.filter(QRegularExpression(QLatin1Char('^') + modeString));
190
191 if(tmp.isEmpty() && plus)
192 {
193 m_channel->getServer()->queue(command.arg(m_channel->getName(), QStringLiteral("+"),
194 modeString.at(0), modeString.mid(1)));
195 }
196 else if(!tmp.isEmpty() && !plus)
197 {
198 //FIXME: Bahamuth requires the key parameter for -k, but ircd breaks on -l with limit number.
199 //Hence two versions of this.
200 if (modeString.at(0) == QLatin1Char('k')) {
201 m_channel->getServer()->queue(command.arg(m_channel->getName(), QStringLiteral("-"),
202 modeString.at(0), modeString.mid(1)));
203 } else {
204 m_channel->getServer()->queue(command.arg(m_channel->getName(), QStringLiteral("-"),
205 modeString.at(0), QString()));
206 }
207 }
208 }
209 hide();
210 }
211
toggleAdvancedModes()212 void ChannelOptionsDialog::toggleAdvancedModes()
213 {
214 bool ison = m_ui.toggleAdvancedModes->isChecked();
215 m_ui.otherModesList->setVisible(ison);
216 if(ison)
217 {
218 m_ui.toggleAdvancedModes->setText(i18n("&Hide Advanced Modes <<"));
219 }
220 else
221 {
222 m_ui.toggleAdvancedModes->setText(i18n("&Show Advanced Modes >>"));
223 }
224 }
225
topicBeingEdited(bool edited)226 void ChannelOptionsDialog::topicBeingEdited(bool edited)
227 {
228 m_editingTopic = edited;
229 m_ui.topicHistoryView->setTextSelectable(edited);
230 }
231
topic() const232 QString ChannelOptionsDialog::topic() const
233 {
234 return m_ui.topicEdit->toPlainText().replace(QLatin1Char('\n'), QLatin1Char(' '));
235 }
236
topicHistoryItemClicked(const QItemSelection & selection)237 void ChannelOptionsDialog::topicHistoryItemClicked(const QItemSelection& selection)
238 {
239 if (!m_editingTopic)
240 {
241 m_ui.topicEdit->clear();
242
243 if (!selection.isEmpty())
244 {
245 m_ui.topicEdit->setUndoRedoEnabled(false);
246 m_ui.topicEdit->setPlainText(m_ui.topicHistoryView->model()->data(selection.indexes().first()).toString());
247 m_ui.topicEdit->setUndoRedoEnabled(true);
248 }
249 }
250 }
251
refreshEnableModes(bool forceUpdate)252 void ChannelOptionsDialog::refreshEnableModes(bool forceUpdate)
253 {
254 if(!m_channel->getOwnChannelNick() || m_channel->getOwnChannelNick()->isChanged() || forceUpdate)
255 {
256 // cache the value
257 m_isAnyTypeOfOp = m_channel->getOwnChannelNick() ? m_channel->getOwnChannelNick()->isAnyTypeOfOp() : false;
258
259 m_ui.topicEdit->setReadOnly(!m_isAnyTypeOfOp && m_ui.topicModeChBox->isChecked());
260
261 m_ui.topicModeChBox->setEnabled(m_isAnyTypeOfOp);
262 m_ui.messageModeChBox->setEnabled(m_isAnyTypeOfOp);
263 m_ui.userLimitChBox->setEnabled(m_isAnyTypeOfOp);
264 m_ui.userLimitEdit->setEnabled(m_isAnyTypeOfOp);
265 m_ui.inviteModeChBox->setEnabled(m_isAnyTypeOfOp);
266 m_ui.moderatedModeChBox->setEnabled(m_isAnyTypeOfOp);
267 m_ui.secretModeChBox->setEnabled(m_isAnyTypeOfOp);
268 m_ui.keyModeChBox->setEnabled(m_isAnyTypeOfOp);
269 m_ui.keyModeEdit->setEnabled(m_isAnyTypeOfOp);
270
271 auto* model = qobject_cast<QStandardItemModel*>(m_ui.otherModesList->model());
272
273 if (model)
274 {
275 QList<QStandardItem*> items = model->findItems(QStringLiteral("*"), Qt::MatchWildcard, 0);
276 items += model->findItems(QStringLiteral("*"), Qt::MatchWildcard, 1);
277
278 for (QStandardItem* item : qAsConst(items))
279 item->setEnabled(m_isAnyTypeOfOp);
280 }
281
282 m_ui.addBan->setEnabled(m_isAnyTypeOfOp);
283 m_ui.updateBan->setEnabled(m_isAnyTypeOfOp);
284 m_ui.removeBan->setEnabled(m_isAnyTypeOfOp);
285 banSelectionChanged();
286
287 m_ui.hostmask->setEnabled(m_isAnyTypeOfOp);
288 hostmaskChanged(m_ui.hostmask->text());
289 }
290 }
291
refreshAllowedChannelModes()292 void ChannelOptionsDialog::refreshAllowedChannelModes()
293 {
294 QString modeString = m_channel->getServer()->allowedChannelModes();
295 // These modes are handled in a special way: ntimslkbeI
296 modeString.remove(QLatin1Char('t'));
297 modeString.remove(QLatin1Char('n'));
298 modeString.remove(QLatin1Char('l'));
299 modeString.remove(QLatin1Char('i'));
300 modeString.remove(QLatin1Char('m'));
301 modeString.remove(QLatin1Char('s'));
302 modeString.remove(QLatin1Char('k'));
303 modeString.remove(QLatin1Char('b'));
304 modeString.remove(QLatin1Char('e'));
305 modeString.remove(QLatin1Char('I'));
306 modeString.remove(QLatin1Char('O'));
307 modeString.remove(QLatin1Char('o'));
308 modeString.remove(QLatin1Char('v'));
309
310 auto* modesModel = static_cast<QStandardItemModel *>(m_ui.otherModesList->model());
311
312 modesModel->clear();
313 modesModel->setHorizontalHeaderLabels(QStringList { i18n("Mode"), i18n("Parameter") });
314
315 for (const QChar mode : qAsConst(modeString)) {
316 const QString modeAsString(mode);
317
318 QStandardItem *item = nullptr;
319 if (!Preferences::self()->useLiteralModes() && getChannelModesHash().contains(mode))
320 item = new QStandardItem(i18nc("<mode character> (<mode description>)","%1 (%2)", mode, getChannelModesHash().value(mode)));
321 else
322 item = new QStandardItem(modeAsString);
323 item->setData(modeAsString);
324 item->setCheckable(true);
325 item->setEditable(false);
326
327 auto* secondItem = new QStandardItem();
328 secondItem->setEditable(true);
329
330 const QList<QStandardItem *> newRow { item, secondItem };
331 modesModel->invisibleRootItem()->appendRow(newRow);
332 }
333 }
334
refreshModes()335 void ChannelOptionsDialog::refreshModes()
336 {
337 const QStringList modes = m_channel->getModeList();
338
339 m_ui.topicModeChBox->setChecked(false);
340 m_ui.messageModeChBox->setChecked(false);
341 m_ui.userLimitChBox->setChecked(false);
342 m_ui.userLimitEdit->setValue(0);
343 m_ui.inviteModeChBox->setChecked(false);
344 m_ui.moderatedModeChBox->setChecked(false);
345 m_ui.secretModeChBox->setChecked(false);
346 m_ui.keyModeChBox->setChecked(false);
347 m_ui.keyModeEdit->setText(QString());
348
349 auto* modesModel = static_cast<QStandardItemModel *>(m_ui.otherModesList->model());
350 for (int i = 0; i < modesModel->rowCount(); ++i)
351 {
352 modesModel->item(i, 0)->setCheckState(Qt::Unchecked);
353 }
354
355 char mode;
356
357 for (const QString ¤tMode : modes) {
358 mode = currentMode[0].toLatin1();
359 switch(mode)
360 {
361 case 't':
362 m_ui.topicModeChBox->setChecked(true);
363 break;
364 case 'n':
365 m_ui.messageModeChBox->setChecked(true);
366 break;
367 case 'l':
368 m_ui.userLimitChBox->setChecked(true);
369 m_ui.userLimitEdit->setValue(currentMode.midRef(1).toInt());
370 break;
371 case 'i':
372 m_ui.inviteModeChBox->setChecked(true);
373 break;
374 case 'm':
375 m_ui.moderatedModeChBox->setChecked(true);
376 break;
377 case 's':
378 m_ui.secretModeChBox->setChecked(true);
379 break;
380 case 'k':
381 m_ui.keyModeChBox->setChecked(true);
382 m_ui.keyModeEdit->setText(currentMode.mid(1));
383 break;
384 default:
385 {
386 bool found = false;
387 QString modeString;
388 modeString = QLatin1Char(mode);
389
390 for (int i = 0; !found && i < modesModel->rowCount(); ++i)
391 {
392 QStandardItem *item = modesModel->item(i, 0);
393 if (item->data().toString() == modeString)
394 {
395 found = true;
396 item->setCheckState(Qt::Checked);
397 modesModel->item(i, 1)->setText(currentMode.mid(1));
398 }
399 }
400
401 break;
402 }
403 }
404 }
405
406 refreshEnableModes(true);
407 }
408
modes() const409 QStringList ChannelOptionsDialog::modes() const
410 {
411 QStringList modes;
412 QString mode;
413
414 const QString plus = QStringLiteral("+");
415 const QString minus = QStringLiteral("-");
416 mode = (m_ui.topicModeChBox->isChecked() ? plus : minus);
417 mode += QLatin1Char('t');
418 modes.append(mode);
419 mode = (m_ui.messageModeChBox->isChecked() ? plus : minus);
420 mode += QLatin1Char('n');
421 modes.append(mode);
422 mode = (m_ui.userLimitChBox->isChecked() ? plus : minus);
423 mode += QLatin1Char('l') + QString::number( m_ui.userLimitEdit->value() );
424 modes.append(mode);
425 mode = (m_ui.inviteModeChBox->isChecked() ? plus : minus);
426 mode += QLatin1Char('i');
427 modes.append(mode);
428 mode = (m_ui.moderatedModeChBox->isChecked() ? plus : minus);
429 mode += QLatin1Char('m');
430 modes.append(mode);
431 mode = (m_ui.secretModeChBox->isChecked() ? plus : minus);
432 mode += QLatin1Char('s');
433 modes.append(mode);
434
435 if (m_ui.keyModeChBox->isChecked() && !m_ui.keyModeEdit->text().isEmpty())
436 {
437 mode = plus;
438 mode += QLatin1Char('k') + m_ui.keyModeEdit->text();
439 modes.append(mode);
440 }
441 else if (!m_ui.keyModeChBox->isChecked())
442 {
443 mode = minus;
444 mode += QLatin1Char('k') + m_ui.keyModeEdit->text();
445 modes.append(mode);
446 }
447
448 auto* modesModel = static_cast<QStandardItemModel *>(m_ui.otherModesList->model());
449 for (int i = 0; i < modesModel->rowCount(); ++i)
450 {
451 mode = (modesModel->item(i, 0)->checkState() == Qt::Checked) ? plus : minus;
452 mode += modesModel->item(i, 0)->data().toString() + modesModel->item(i, 1)->text();
453 modes.append(mode);
454 }
455
456 return modes;
457 }
458
459 // Ban List tab related functions
460
refreshBanList()461 void ChannelOptionsDialog::refreshBanList()
462 {
463 QStringList banlist = m_channel->getBanList();
464 m_ui.banList->clear();
465
466 for (QStringList::const_iterator it = --banlist.constEnd(); it != --banlist.constBegin(); --it)
467 addBan((*it));
468 }
469
addBan(const QString & newban)470 void ChannelOptionsDialog::addBan(const QString& newban)
471 {
472 auto *item = new BanListViewItem(m_ui.banList, newban.section(QLatin1Char(' '), 0, 0), newban.section(QLatin1Char(' '), 1, 1).section(QLatin1Char('!'), 0, 0), newban.section(QLatin1Char(' '), 2 ,2).toUInt());
473 // set item as current item
474 m_ui.banList->setCurrentItem(item);
475 // update button states
476 hostmaskChanged(m_ui.hostmask->text());
477 }
478
removeBan(const QString & ban)479 void ChannelOptionsDialog::removeBan(const QString& ban)
480 {
481 QList<QTreeWidgetItem *> items = m_ui.banList->findItems(ban, Qt::MatchCaseSensitive | Qt::MatchExactly, 0);
482 if (!items.isEmpty())
483 delete items.at(0);
484 }
485
addBanClicked()486 void ChannelOptionsDialog::addBanClicked()
487 {
488 QString newHostmask = m_ui.hostmask->text();
489 if (!newHostmask.isEmpty())
490 m_channel->getServer()->requestBan(QStringList(newHostmask), m_channel->getName(), QString());
491 }
492
removeBanClicked()493 void ChannelOptionsDialog::removeBanClicked()
494 {
495 QString oldHostmask = m_ui.banList->currentItem()->text(0);
496 // We delete the existing item because it's possible the server may
497 // Modify the ban causing us not to catch it. If that happens we'll be
498 // stuck with a stale item and a new item with the modified hostmask.
499 delete m_ui.banList->currentItem();
500 // request unban
501 m_channel->getServer()->requestUnban(oldHostmask, m_channel->getName());
502 }
503
updateBanClicked()504 void ChannelOptionsDialog::updateBanClicked()
505 {
506 QString oldHostmask = m_ui.banList->currentItem()->text(0);
507 QString newHostmask = m_ui.hostmask->text();
508 if (!newHostmask.isEmpty() && newHostmask.compare(oldHostmask))
509 {
510 // We delete the existing item because it's possible the server may
511 // Modify the ban causing us not to catch it. If that happens we'll be
512 // stuck with a stale item and a new item with the modified hostmask.
513 delete m_ui.banList->currentItem();
514 // request unban for the of the old hostmask
515 m_channel->getServer()->requestUnban(oldHostmask, m_channel->getName());
516 // request ban for the of the old hostmask
517 m_channel->getServer()->requestBan(QStringList(newHostmask), m_channel->getName(), QString());
518 }
519 }
520 /// Enables/disables updateBan and removeBan buttons depending on the currentItem of the banList
banSelectionChanged()521 void ChannelOptionsDialog::banSelectionChanged()
522 {
523 if (m_ui.banList->currentItem())
524 {
525 m_ui.updateBan->setEnabled(m_isAnyTypeOfOp);
526 m_ui.removeBan->setEnabled(m_isAnyTypeOfOp);
527 // update line edit content
528 m_ui.hostmask->setText(m_ui.banList->currentItem()->text(0));
529 }
530 else
531 {
532 m_ui.updateBan->setEnabled(false);
533 m_ui.removeBan->setEnabled(false);
534 }
535 }
536 /// Enables/disables addBan and updateBan buttons depending on the value of @p text
hostmaskChanged(const QString & text)537 void ChannelOptionsDialog::hostmaskChanged(const QString& text)
538 {
539 if (!text.trimmed().isEmpty()) {
540 if (m_isAnyTypeOfOp)
541 {
542 QList<QTreeWidgetItem*> items = m_ui.banList->findItems(text, Qt::MatchExactly | Qt::MatchCaseSensitive, 0);
543 m_ui.addBan->setEnabled(items.isEmpty());
544 m_ui.updateBan->setEnabled(items.isEmpty() && m_ui.banList->currentItem());
545 }
546 }
547 else
548 {
549 m_ui.addBan->setEnabled(false);
550 m_ui.updateBan->setEnabled(false);
551 }
552 }
553
startHistorySearchTimer(const QString & filter)554 void ChannelOptionsDialog::startHistorySearchTimer(const QString &filter)
555 {
556 Q_UNUSED(filter)
557 m_historySearchTimer->start(300);
558 }
559
updateHistoryFilter()560 void ChannelOptionsDialog::updateHistoryFilter()
561 {
562 auto* proxy = qobject_cast<QSortFilterProxyModel*>(m_ui.topicHistoryView->model());
563
564 if(!proxy)
565 return;
566
567 proxy->setFilterFixedString(m_ui.topicHistorySearchLine->text());
568 }
569
570
571 // This is our implementation of BanListViewItem
572
BanListViewItem(QTreeWidget * parent)573 BanListViewItem::BanListViewItem(QTreeWidget *parent)
574 : QTreeWidgetItem()
575 {
576 parent->addTopLevelItem(this);
577 }
578
BanListViewItem(QTreeWidget * parent,const QString & label1,const QString & label2,uint timestamp)579 BanListViewItem::BanListViewItem (QTreeWidget *parent, const QString& label1, const QString& label2,
580 uint timestamp) : QTreeWidgetItem()
581 {
582 setText(0, label1);
583 setText(1, label2);
584 m_timestamp.setMSecsSinceEpoch(static_cast<qint64>(timestamp) * 1000);
585 setText(2, QLocale().toString(m_timestamp, QLocale::ShortFormat));
586 setData(2, Qt::UserRole, m_timestamp);
587 parent->addTopLevelItem(this);
588 }
589
operator <(const QTreeWidgetItem & item) const590 bool BanListViewItem::operator<(const QTreeWidgetItem &item) const
591 {
592 if (treeWidget()->sortColumn() == 2)
593 {
594 QVariant userdata = item.data(2, Qt::UserRole);
595 if (userdata.isValid() && userdata.type() == QVariant::DateTime)
596 {
597 return m_timestamp < userdata.toDateTime();
598 }
599 }
600
601 return text(treeWidget()->sortColumn()) < item.text(treeWidget()->sortColumn());
602 }
603 }
604
whatsThisForMode(char mode)605 QString Konversation::ChannelOptionsDialog::whatsThisForMode(char mode)
606 {
607 switch (mode) {
608 case 'T':
609 return i18n("<qt><p>These control the <em>mode</em> of the channel. Only an operator can change these.</p><p>The <b>T</b>opic mode means that only the channel operator can change the topic for the channel.</p></qt>");
610 case 'N':
611 return i18n("<qt><p>These control the <em>mode</em> of the channel. Only an operator can change these.</p><p><b>N</b>o messages from outside means users who are not in the channel cannot send messages for everybody in the channel to see. Almost all channels have this set to prevent nuisance messages.</p></qt>");
612 case 'S':
613 return i18n("<qt><p>These control the <em>mode</em> of the channel. Only an operator can change these.</p><p>A <b>S</b>ecret channel will not show up in the channel list, nor will any user be able to see that you are in the channel with the <em>WHOIS</em> command or anything similar. Only the people that are in the same channel will know that you are in this channel, if this mode is set.</p></qt>");
614 case 'I':
615 return i18n("<qt><p>These control the <em>mode</em> of the channel. Only an operator can change these.</p><p>An <b>I</b>nvite only channel means that people can only join the channel if they are invited. To invite someone, a channel operator needs to issue the command <em>/invite nick</em> from within the channel.</p></qt>");
616 case 'P':
617 return i18n("<qt><p>These control the <em>mode</em> of the channel. Only an operator can change these.</p><p>A <b>P</b>rivate channel is shown in a listing of all channels, but the topic is not shown. A user's <em>WHOIS</em> may or may not show them as being in a private channel depending on the IRC server.</p></qt>");
618 case 'M':
619 return i18n("<qt><p>These control the <em>mode</em> of the channel. Only an operator can change these.</p><p>A <b>M</b>oderated channel is one where only operators, half-operators and those with voice can talk.</p></qt>");
620 case 'K':
621 return i18n("<qt><p>These control the <em>mode</em> of the channel. Only an operator can change these.</p><p>A protected channel requires users to enter a password in order to join.</p></qt>");
622 case 'L':
623 return i18n("<qt><p>These control the <em>mode</em> of the channel. Only an operator can change these.</p><p>A channel that has a user <b>L</b>imit means that only that many users can be in the channel at any one time. Some channels have a bot that sits in the channel and changes this automatically depending on how busy the channel is.</p></qt>");
624 default:
625 qCWarning(KONVERSATION_LOG) << "called for unknown mode" << mode;
626 return QString();
627 }
628 }
629
630
631