diff options
Diffstat (limited to 'common/mail/threadindexer.cpp')
-rw-r--r-- | common/mail/threadindexer.cpp | 84 |
1 files changed, 11 insertions, 73 deletions
diff --git a/common/mail/threadindexer.cpp b/common/mail/threadindexer.cpp index d91ab5f..4171d85 100644 --- a/common/mail/threadindexer.cpp +++ b/common/mail/threadindexer.cpp | |||
@@ -21,74 +21,15 @@ | |||
21 | #include "typeindex.h" | 21 | #include "typeindex.h" |
22 | #include "log.h" | 22 | #include "log.h" |
23 | 23 | ||
24 | SINK_DEBUG_AREA("threadindex") | ||
25 | |||
26 | using namespace Sink; | 24 | using namespace Sink; |
27 | using namespace Sink::ApplicationDomain; | 25 | using namespace Sink::ApplicationDomain; |
28 | 26 | ||
29 | static QString stripOffPrefixes(const QString &subject) | ||
30 | { | ||
31 | //TODO this hardcoded list is probably not good enough (especially regarding internationalization) | ||
32 | //TODO this whole routine, including internationalized re/fwd ... should go into some library. | ||
33 | //We'll require the same for generating reply/forward subjects in kube | ||
34 | static QStringList defaultReplyPrefixes = QStringList() << QLatin1String("Re\\s*:") | ||
35 | << QLatin1String("Re\\[\\d+\\]:") | ||
36 | << QLatin1String("Re\\d+:"); | ||
37 | |||
38 | static QStringList defaultForwardPrefixes = QStringList() << QLatin1String("Fwd:") | ||
39 | << QLatin1String("FW:"); | ||
40 | |||
41 | QStringList replyPrefixes; // = GlobalSettings::self()->replyPrefixes(); | ||
42 | if (replyPrefixes.isEmpty()) { | ||
43 | replyPrefixes = defaultReplyPrefixes; | ||
44 | } | ||
45 | |||
46 | QStringList forwardPrefixes; // = GlobalSettings::self()->forwardPrefixes(); | ||
47 | if (forwardPrefixes.isEmpty()) { | ||
48 | forwardPrefixes = defaultReplyPrefixes; | ||
49 | } | ||
50 | |||
51 | const QStringList prefixRegExps = replyPrefixes + forwardPrefixes; | ||
52 | |||
53 | // construct a big regexp that | ||
54 | // 1. is anchored to the beginning of str (sans whitespace) | ||
55 | // 2. matches at least one of the part regexps in prefixRegExps | ||
56 | const QString bigRegExp = QString::fromLatin1("^(?:\\s+|(?:%1))+\\s*").arg(prefixRegExps.join(QLatin1String(")|(?:"))); | ||
57 | |||
58 | static QString regExpPattern; | ||
59 | static QRegExp regExp; | ||
60 | |||
61 | regExp.setCaseSensitivity(Qt::CaseInsensitive); | ||
62 | if (regExpPattern != bigRegExp) { | ||
63 | // the prefixes have changed, so update the regexp | ||
64 | regExpPattern = bigRegExp; | ||
65 | regExp.setPattern(regExpPattern); | ||
66 | } | ||
67 | |||
68 | if(regExp.isValid()) { | ||
69 | QString tmp = subject; | ||
70 | if (regExp.indexIn( tmp ) == 0) { | ||
71 | return tmp.remove(0, regExp.matchedLength()); | ||
72 | } | ||
73 | } else { | ||
74 | SinkWarning() << "bigRegExp = \"" | ||
75 | << bigRegExp << "\"\n" | ||
76 | << "prefix regexp is invalid!"; | ||
77 | } | ||
78 | |||
79 | return subject; | ||
80 | } | ||
81 | |||
82 | |||
83 | void ThreadIndexer::updateThreadingIndex(const QByteArray &identifier, const ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction) | 27 | void ThreadIndexer::updateThreadingIndex(const QByteArray &identifier, const ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction) |
84 | { | 28 | { |
85 | auto messageId = entity.getProperty(Mail::MessageId::name); | 29 | auto messageId = entity.getProperty(Mail::MessageId::name); |
86 | auto parentMessageId = entity.getProperty(Mail::ParentMessageId::name); | 30 | auto parentMessageId = entity.getProperty(Mail::ParentMessageId::name); |
87 | const auto subject = entity.getProperty(Mail::Subject::name); | ||
88 | const auto normalizedSubject = stripOffPrefixes(subject.toString()).toUtf8(); | ||
89 | if (messageId.toByteArray().isEmpty()) { | 31 | if (messageId.toByteArray().isEmpty()) { |
90 | SinkWarning() << "Found an email without messageId. This is illegal and threading will break. Entity id: " << identifier; | 32 | SinkWarning() << "Found an email without messageId. This is illegal and threading will break. Entity id: " << identifier; |
91 | SinkWarning() << "Subject: " << subject; | ||
92 | } | 33 | } |
93 | 34 | ||
94 | QVector<QByteArray> thread; | 35 | QVector<QByteArray> thread; |
@@ -101,18 +42,9 @@ void ThreadIndexer::updateThreadingIndex(const QByteArray &identifier, const App | |||
101 | thread = index().secondaryLookup<Mail::MessageId, Mail::ThreadId>(parentMessageId); | 42 | thread = index().secondaryLookup<Mail::MessageId, Mail::ThreadId>(parentMessageId); |
102 | SinkTrace() << "Found parent: " << thread; | 43 | SinkTrace() << "Found parent: " << thread; |
103 | } | 44 | } |
104 | |||
105 | if (thread.isEmpty()) { | 45 | if (thread.isEmpty()) { |
106 | //Try to lookup the thread by subject if not empty | 46 | thread << QUuid::createUuid().toByteArray(); |
107 | if ( !normalizedSubject.isEmpty()) { | 47 | SinkTrace() << "Created a new thread: " << thread; |
108 | thread = index().secondaryLookup<Mail::Subject, Mail::ThreadId>(normalizedSubject); | ||
109 | } | ||
110 | if (thread.isEmpty()) { | ||
111 | thread << QUuid::createUuid().toByteArray(); | ||
112 | SinkTrace() << "Created a new thread: " << thread; | ||
113 | } else { | ||
114 | SinkTrace() << "Found thread by subject: " << thread; | ||
115 | } | ||
116 | } | 48 | } |
117 | 49 | ||
118 | Q_ASSERT(!thread.isEmpty()); | 50 | Q_ASSERT(!thread.isEmpty()); |
@@ -124,9 +56,6 @@ void ThreadIndexer::updateThreadingIndex(const QByteArray &identifier, const App | |||
124 | } | 56 | } |
125 | index().index<Mail::MessageId, Mail::ThreadId>(messageId, thread.first(), transaction); | 57 | index().index<Mail::MessageId, Mail::ThreadId>(messageId, thread.first(), transaction); |
126 | index().index<Mail::ThreadId, Mail::MessageId>(thread.first(), messageId, transaction); | 58 | index().index<Mail::ThreadId, Mail::MessageId>(thread.first(), messageId, transaction); |
127 | if (!normalizedSubject.isEmpty()) { | ||
128 | index().index<Mail::Subject, Mail::ThreadId>(normalizedSubject, thread.first(), transaction); | ||
129 | } | ||
130 | } | 59 | } |
131 | 60 | ||
132 | 61 | ||
@@ -142,6 +71,15 @@ void ThreadIndexer::modify(const ApplicationDomain::ApplicationDomainType &old, | |||
142 | 71 | ||
143 | void ThreadIndexer::remove(const ApplicationDomain::ApplicationDomainType &entity) | 72 | void ThreadIndexer::remove(const ApplicationDomain::ApplicationDomainType &entity) |
144 | { | 73 | { |
74 | auto messageId = entity.getProperty(Mail::MessageId::name); | ||
75 | auto thread = index().secondaryLookup<Mail::MessageId, Mail::ThreadId>(messageId); | ||
76 | index().unindex<Mail::MessageId, Mail::ThreadId>(messageId.toByteArray(), thread.first(), transaction()); | ||
77 | index().unindex<Mail::ThreadId, Mail::MessageId>(thread.first(), messageId.toByteArray(), transaction()); | ||
78 | } | ||
145 | 79 | ||
80 | QMap<QByteArray, int> ThreadIndexer::databases() | ||
81 | { | ||
82 | return {{"mail.index.messageIdthreadId", 1}, | ||
83 | {"mail.index.threadIdmessageId", 1}}; | ||
146 | } | 84 | } |
147 | 85 | ||