/***************************************************************************
- * Copyright (C) 2005-2012 by the Quassel Project *
+ * Copyright (C) 2005-2020 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include "messagefilter.h"
+#include <algorithm>
+
+#include "buffermodel.h"
#include "buffersettings.h"
#include "client.h"
-#include "buffermodel.h"
+#include "clientignorelistmanager.h"
#include "messagemodel.h"
#include "networkmodel.h"
-#include "clientignorelistmanager.h"
+#include "util.h"
-MessageFilter::MessageFilter(QAbstractItemModel *source, QObject *parent)
- : QSortFilterProxyModel(parent),
- _messageTypeFilter(0)
+MessageFilter::MessageFilter(QAbstractItemModel* source, QObject* parent)
+ : QSortFilterProxyModel(parent)
+ , _messageTypeFilter(0)
{
init();
setSourceModel(source);
}
-
-MessageFilter::MessageFilter(MessageModel *source, const QList<BufferId> &buffers, QObject *parent)
- : QSortFilterProxyModel(parent),
- _validBuffers(buffers.toSet()),
- _messageTypeFilter(0)
+MessageFilter::MessageFilter(MessageModel* source, const QList<BufferId>& buffers, QObject* parent)
+ : QSortFilterProxyModel(parent)
+ , _validBuffers(toQSet(buffers))
+ , _messageTypeFilter(0)
{
init();
setSourceModel(source);
}
-
void MessageFilter::init()
{
setDynamicSortFilter(true);
_userNoticesTarget = _serverNoticesTarget = _errorMsgsTarget = -1;
BufferSettings defaultSettings;
- defaultSettings.notify("UserNoticesTarget", this, SLOT(messageRedirectionChanged()));
- defaultSettings.notify("ServerNoticesTarget", this, SLOT(messageRedirectionChanged()));
- defaultSettings.notify("ErrorMsgsTarget", this, SLOT(messageRedirectionChanged()));
+ defaultSettings.notify("UserNoticesTarget", this, &MessageFilter::messageRedirectionChanged);
+ defaultSettings.notify("ServerNoticesTarget", this, &MessageFilter::messageRedirectionChanged);
+ defaultSettings.notify("ErrorMsgsTarget", this, &MessageFilter::messageRedirectionChanged);
messageRedirectionChanged();
_messageTypeFilter = defaultSettings.messageFilter();
- defaultSettings.notify("MessageTypeFilter", this, SLOT(messageTypeFilterChanged()));
+ defaultSettings.notify("MessageTypeFilter", this, &MessageFilter::messageTypeFilterChanged);
- BufferSettings mySettings(idString());
+ BufferSettings mySettings(MessageFilter::idString());
if (mySettings.hasFilter())
_messageTypeFilter = mySettings.messageFilter();
- mySettings.notify("MessageTypeFilter", this, SLOT(messageTypeFilterChanged()));
- mySettings.notify("hasMessageTypeFilter", this, SLOT(messageTypeFilterChanged()));
+ mySettings.notify("MessageTypeFilter", this, &MessageFilter::messageTypeFilterChanged);
+ mySettings.notify("hasMessageTypeFilter", this, &MessageFilter::messageTypeFilterChanged);
}
-
void MessageFilter::messageTypeFilterChanged()
{
int newFilter;
if (_messageTypeFilter != newFilter) {
_messageTypeFilter = newFilter;
- _filteredQuitMsgs.clear();
+ _filteredQuitMsgTime.clear();
invalidateFilter();
}
}
-
void MessageFilter::messageRedirectionChanged()
{
BufferSettings bufferSettings;
invalidateFilter();
}
-
QString MessageFilter::idString() const
{
if (_validBuffers.isEmpty())
return "*";
- QList<BufferId> bufferIds = _validBuffers.toList();
- qSort(bufferIds);
+ QList<BufferId> bufferIds = _validBuffers.values();
+ std::sort(bufferIds.begin(), bufferIds.end());
QStringList bufferIdStrings;
- foreach(BufferId id, bufferIds)
- bufferIdStrings << QString::number(id.toInt());
+ foreach (BufferId id, bufferIds)
+ bufferIdStrings << QString::number(id.toInt());
return bufferIdStrings.join("|");
}
-
-bool MessageFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+bool MessageFilter::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
Q_UNUSED(sourceParent);
QModelIndex sourceIdx = sourceModel()->index(sourceRow, 2);
// ignorelist handling
// only match if message is not flagged as server msg
if (!(flags & Message::ServerMsg) && Client::ignoreListManager()
- && Client::ignoreListManager()->match(sourceIdx.data(MessageModel::MessageRole).value<Message>(), Client::networkModel()->networkName(bufferId)))
+ && Client::ignoreListManager()->match(sourceIdx.data(MessageModel::MessageRole).value<Message>(),
+ Client::networkModel()->networkName(bufferId)))
return false;
if (flags & Message::Redirected) {
if (!redirectedTo.isValid()) {
BufferId redirectedTo = Client::bufferModel()->currentIndex().data(NetworkModel::BufferIdRole).value<BufferId>();
if (redirectedTo.isValid())
- sourceModel()->setData(sourceIdx, QVariant::fromValue<BufferId>(redirectedTo), MessageModel::RedirectedToRole);
+ sourceModel()->setData(sourceIdx, QVariant::fromValue(redirectedTo), MessageModel::RedirectedToRole);
}
if (_validBuffers.contains(redirectedTo))
while (idIter != _validBuffers.constEnd()) {
if (Client::networkModel()->bufferType(*idIter) == BufferInfo::StatusBuffer)
return true;
- idIter++;
+ ++idIter;
}
}
if (myNetworkId != msgNetworkId)
return false;
- uint messageTimestamp = sourceModel()->data(sourceIdx, MessageModel::TimestampRole).value<QDateTime>().toTime_t();
- QString quiter = sourceModel()->data(sourceIdx, Qt::DisplayRole).toString().section(' ', 0, 0, QString::SectionSkipEmpty).toLower();
+ // Extract timestamp and nickname from the new quit message
+ qint64 messageTimestamp = sourceModel()->data(sourceIdx, MessageModel::TimestampRole).value<QDateTime>().toMSecsSinceEpoch();
+ QString quiter = nickFromMask(sourceModel()->data(sourceIdx, MessageModel::MessageRole).value<Message>().sender()).toLower();
+
+ // Check that nickname matches query name
if (quiter != bufferName().toLower())
return false;
- if (_filteredQuitMsgs.contains(quiter, messageTimestamp))
+ // Check if a quit message was already forwarded within +/- 1000 ms
+ static constexpr qint64 MAX_QUIT_DELTA_MS = 1 * 1000;
+ // No need to check if it's the appropriate buffer, each query has a unique message filter
+ if (std::binary_search(_filteredQuitMsgTime.begin(), _filteredQuitMsgTime.end(), messageTimestamp, [](qint64 a, qint64 b) {
+ return ((a + MAX_QUIT_DELTA_MS) < b);
+ })) {
+ // New element is less than if at least 1000 ms older/newer
+ // Match found, no need to forward another quit message
return false;
+ }
- MessageFilter *that = const_cast<MessageFilter *>(this);
- that->_filteredQuitMsgs.insert(quiter, messageTimestamp);
+ // Mark query as having a quit message inserted
+ auto* that = const_cast<MessageFilter*>(this);
+ that->_filteredQuitMsgTime.insert(messageTimestamp);
return true;
}
}
-
void MessageFilter::requestBacklog()
{
QSet<BufferId>::const_iterator bufferIdIter = _validBuffers.constBegin();
while (bufferIdIter != _validBuffers.constEnd()) {
Client::messageModel()->requestBacklog(*bufferIdIter);
- bufferIdIter++;
+ ++bufferIdIter;
}
}