filter.cpp 5.96 KB
Newer Older
1
2
/******************************************************************************
 *
3
 *  SPDX-FileCopyrightText: 2008 Szymon Tomasz Stefanek <pragma@kvirc.net>
4
 *
5
 *  SPDX-License-Identifier: GPL-2.0-or-later
6
7
8
9
10
 *
 *******************************************************************************/

#include "core/filter.h"
#include "core/messageitem.h"
11

12
13
14
15
16
17
18
19
20
21
22
23
24
#include <AkonadiSearch/PIM/emailquery.h>
#include <AkonadiSearch/PIM/resultiterator.h>

using namespace MessageList::Core;

Filter::Filter(QObject *parent)
    : QObject(parent)
{
}

bool Filter::containString(const QString &searchInString) const
{
    bool found = false;
Laurent Montel's avatar
Laurent Montel committed
25
    for (const QString &str : qAsConst(mSearchList)) {
26
27
28
29
30
31
32
33
34
35
36
37
38
        if (searchInString.contains(str, Qt::CaseInsensitive)) {
            found = true;
        } else {
            found = false;
            break;
        }
    }
    return found;
}

bool Filter::match(const MessageItem *item) const
{
    if (!mStatus.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
39
        for (Akonadi::MessageStatus status : qAsConst(mStatus)) {
40
41
42
43
44
45
46
47
48
49
            if (!(status & item->status())) {
                return false;
            }
        }
    }

    if (!mSearchString.isEmpty()) {
        if (mMatchingItemIds.contains(item->itemId())) {
            return true;
        }
50

51
        bool searchMatches = false;
Laurent Montel's avatar
Laurent Montel committed
52
        bool searchEveryWhere = (mOptions & QuickSearchLine::SearchEveryWhere);
Laurent Montel's avatar
Laurent Montel committed
53
        if (containString(item->subject()) && ((mOptions & QuickSearchLine::SearchAgainstSubject) || searchEveryWhere)) {
54
            searchMatches = true;
Laurent Montel's avatar
Laurent Montel committed
55
        } else if (containString(item->sender()) && ((mOptions & QuickSearchLine::SearchAgainstFrom) || searchEveryWhere)) {
56
            searchMatches = true;
Laurent Montel's avatar
Laurent Montel committed
57
        } else if (containString(item->receiver()) && ((mOptions & QuickSearchLine::SearchAgainstTo) || searchEveryWhere)) {
58
59
60
61
62
63
64
65
            searchMatches = true;
        }
        if (!searchMatches) {
            return false;
        }
    }

    if (!mTagId.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
66
        // mTagId is a Akonadi::Tag::url
Laurent Montel's avatar
Laurent Montel committed
67
        const bool tagMatches = item->findTag(mTagId) != nullptr;
68
69
70
71
72
73
74
75
        if (!tagMatches) {
            return false;
        }
    }

    return true;
}

Laurent Montel's avatar
Laurent Montel committed
76
77
78
79
80
81
82
83
84
85
QVector<Akonadi::MessageStatus> Filter::status() const
{
    return mStatus;
}

void Filter::setStatus(const QVector<Akonadi::MessageStatus> &lstStatus)
{
    mStatus = lstStatus;
}

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
bool Filter::isEmpty() const
{
    if (!mStatus.isEmpty()) {
        return false;
    }

    if (!mSearchString.isEmpty()) {
        return false;
    }

    if (!mTagId.isEmpty()) {
        return false;
    }

    return true;
}

void Filter::clear()
{
    mStatus.clear();
    mSearchString.clear();
    mTagId.clear();
    mMatchingItemIds.clear();
    mSearchList.clear();
}

void Filter::setCurrentFolder(const Akonadi::Collection &folder)
{
    mCurrentFolder = folder;
}

Laurent Montel's avatar
Laurent Montel committed
117
118
119
120
121
const QString &Filter::searchString() const
{
    return mSearchString;
}

122
123
124
125
126
QuickSearchLine::SearchOptions Filter::currentOptions() const
{
    return mOptions;
}

Laurent Montel's avatar
Laurent Montel committed
127
128
129
130
131
132
133
void Filter::save(const KSharedConfig::Ptr &config, const QString &filtername)
{
    KConfigGroup grp(config, "General");
    int numberFilter = grp.readEntry("NumberFilter").toInt();
    KConfigGroup newGroup(config, QStringLiteral("Filter_%1").arg(numberFilter++));
    newGroup.writeEntry("name", filtername);
    newGroup.writeEntry("searchString", mSearchString);
Laurent Montel's avatar
Laurent Montel committed
134
    newGroup.writeEntry("searchOptions", static_cast<int>(mOptions));
Laurent Montel's avatar
Laurent Montel committed
135
    newGroup.writeEntry("tagId", mTagId);
Laurent Montel's avatar
Laurent Montel committed
136
    newGroup.writeEntry("currentFolder", mCurrentFolder.id());
Laurent Montel's avatar
Laurent Montel committed
137
138
139
140
    // TODO mStatus.toQInt32()
    newGroup.sync();
}

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
void Filter::setSearchString(const QString &search, QuickSearchLine::SearchOptions options)
{
    const QString trimStr = search.trimmed();
    if ((mSearchString == trimStr) && (mOptions == options)) {
        return;
    }
    mOptions = options;
    mSearchString = trimStr;
    mMatchingItemIds.clear();

    if (mSearchString.isEmpty()) {
        return;
    }
    bool needToSplitString = false;
    QString newStr = mSearchString;
    if (mSearchString.startsWith(QLatin1Char('"')) && mSearchString.startsWith(QLatin1Char('"'))) {
157
158
        newStr.remove(0, 1);
        newStr.remove(newStr.length() - 1, 1);
159
160
        mSearchList = QStringList() << newStr;
    } else {
161
        const QStringList searchListTmp = mSearchString.split(QLatin1Char(' '), Qt::SkipEmptyParts);
162
163
        mSearchList.clear();
        newStr.clear();
Laurent Montel's avatar
Laurent Montel committed
164
        for (const QString &text : searchListTmp) {
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
            if (text.size() >= 3) {
                mSearchList << text;
                if (!newStr.isEmpty()) {
                    newStr += QLatin1Char(' ');
                }
                newStr += text;
            }
        }
        needToSplitString = true;
    }
    if (!newStr.trimmed().isEmpty()) {
        Akonadi::Search::PIM::EmailQuery query;
        if (options & QuickSearchLine::SearchEveryWhere) {
            query.matches(newStr);
            query.setSplitSearchMatchString(needToSplitString);
        } else if (options & QuickSearchLine::SearchAgainstSubject) {
            query.subjectMatches(newStr);
        } else if (options & QuickSearchLine::SearchAgainstBody) {
            query.bodyMatches(newStr);
        } else if (options & QuickSearchLine::SearchAgainstFrom) {
            query.setFrom(newStr);
        } else if (options & QuickSearchLine::SearchAgainstBcc) {
            query.setBcc(QStringList() << newStr);
        } else if (options & QuickSearchLine::SearchAgainstTo) {
            query.setTo(QStringList() << newStr);
        }

Laurent Montel's avatar
Laurent Montel committed
192
        // If the collection is virtual we're probably trying to filter the search collection, so we just search globally
193
194
195
196
197
198
199
200
201
202
203
        if (mCurrentFolder.isValid() && !mCurrentFolder.isVirtual()) {
            query.addCollection(mCurrentFolder.id());
        }

        Akonadi::Search::PIM::ResultIterator it = query.exec();
        while (it.next()) {
            mMatchingItemIds << it.id();
        }
    }
    Q_EMIT finished();
}
Laurent Montel's avatar
Laurent Montel committed
204
205
206
207
208
209
210
211
212
213

const QString &Filter::tagId() const
{
    return mTagId;
}

void Filter::setTagId(const QString &tagId)
{
    mTagId = tagId;
}