2022-10-06 22:59:59 +03:00
|
|
|
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
2022-10-06 02:39:30 +03:00
|
|
|
#include "TimelineFilter.h"
|
|
|
|
|
|
|
|
#include "Logging.h"
|
|
|
|
|
|
|
|
TimelineFilter::TimelineFilter(QObject *parent)
|
|
|
|
: QSortFilterProxyModel(parent)
|
|
|
|
{
|
|
|
|
setDynamicSortFilter(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TimelineFilter::setThreadId(const QString &t)
|
|
|
|
{
|
|
|
|
nhlog::ui()->debug("Filtering by thread '{}'", t.toStdString());
|
|
|
|
if (this->threadId != t) {
|
|
|
|
this->threadId = t;
|
|
|
|
invalidateFilter();
|
2022-11-04 01:26:59 +03:00
|
|
|
|
|
|
|
fetchMore({});
|
|
|
|
emit threadIdChanged();
|
2022-10-06 02:39:30 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-06 22:59:59 +03:00
|
|
|
void
|
|
|
|
TimelineFilter::setContentFilter(const QString &c)
|
|
|
|
{
|
|
|
|
nhlog::ui()->debug("Filtering by content '{}'", c.toStdString());
|
|
|
|
if (this->contentFilter != c) {
|
|
|
|
this->contentFilter = c;
|
|
|
|
invalidateFilter();
|
2022-11-04 01:26:59 +03:00
|
|
|
|
|
|
|
fetchMore({});
|
|
|
|
emit contentFilterChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TimelineFilter::fetchAgain()
|
|
|
|
{
|
|
|
|
if (threadId.isEmpty() && contentFilter.isEmpty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (auto s = source()) {
|
|
|
|
if (rowCount() == cachedCount && s->canFetchMore(QModelIndex()))
|
|
|
|
s->fetchMore(QModelIndex());
|
|
|
|
else
|
|
|
|
cachedCount = rowCount();
|
2022-10-06 22:59:59 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-06 02:39:30 +03:00
|
|
|
void
|
|
|
|
TimelineFilter::setSource(TimelineModel *s)
|
|
|
|
{
|
|
|
|
if (auto orig = this->source(); orig != s) {
|
2022-11-04 01:26:59 +03:00
|
|
|
cachedCount = 0;
|
|
|
|
|
|
|
|
if (orig) {
|
2022-10-06 02:39:30 +03:00
|
|
|
disconnect(orig,
|
|
|
|
&TimelineModel::currentIndexChanged,
|
|
|
|
this,
|
|
|
|
&TimelineFilter::currentIndexChanged);
|
2022-11-04 01:26:59 +03:00
|
|
|
disconnect(orig, &TimelineModel::fetchedMore, this, &TimelineFilter::fetchAgain);
|
|
|
|
}
|
|
|
|
|
2022-10-06 02:39:30 +03:00
|
|
|
this->setSourceModel(s);
|
2022-11-04 01:26:59 +03:00
|
|
|
|
2022-10-06 02:39:30 +03:00
|
|
|
connect(s, &TimelineModel::currentIndexChanged, this, &TimelineFilter::currentIndexChanged);
|
2022-11-04 01:26:59 +03:00
|
|
|
connect(s, &TimelineModel::fetchedMore, this, &TimelineFilter::fetchAgain);
|
|
|
|
|
2022-10-06 02:39:30 +03:00
|
|
|
emit sourceChanged();
|
|
|
|
invalidateFilter();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TimelineModel *
|
|
|
|
TimelineFilter::source() const
|
|
|
|
{
|
|
|
|
return qobject_cast<TimelineModel *>(sourceModel());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TimelineFilter::setCurrentIndex(int idx)
|
|
|
|
{
|
|
|
|
// TODO: maybe send read receipt in thread timeline? Or not at all?
|
|
|
|
if (auto s = source()) {
|
|
|
|
s->setCurrentIndex(this->mapToSource(index(idx, 0)).row());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
TimelineFilter::currentIndex() const
|
|
|
|
{
|
|
|
|
if (auto s = source())
|
|
|
|
return this->mapFromSource(s->index(s->currentIndex())).row();
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
TimelineFilter::filterAcceptsRow(int source_row, const QModelIndex &) const
|
|
|
|
{
|
2022-10-06 22:59:59 +03:00
|
|
|
if (threadId.isEmpty() && contentFilter.isEmpty())
|
2022-10-06 02:39:30 +03:00
|
|
|
return true;
|
|
|
|
|
|
|
|
if (auto s = sourceModel()) {
|
|
|
|
auto idx = s->index(source_row, 0);
|
2022-10-06 22:59:59 +03:00
|
|
|
if (!contentFilter.isEmpty() && !s->data(idx, TimelineModel::Body)
|
|
|
|
.toString()
|
|
|
|
.contains(contentFilter, Qt::CaseInsensitive)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (threadId.isEmpty())
|
|
|
|
return true;
|
|
|
|
|
2022-10-06 02:39:30 +03:00
|
|
|
return s->data(idx, TimelineModel::EventId) == threadId ||
|
|
|
|
s->data(idx, TimelineModel::ThreadId) == threadId;
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|