summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/domain/mail.cpp79
1 files changed, 72 insertions, 7 deletions
diff --git a/common/domain/mail.cpp b/common/domain/mail.cpp
index 859ebef..0c737fa 100644
--- a/common/domain/mail.cpp
+++ b/common/domain/mail.cpp
@@ -63,34 +63,98 @@ static TypeIndex &getIndex()
63 return *index; 63 return *index;
64} 64}
65 65
66static QString stripOffPrefixes(const QString &subject)
67{
68 //TODO this hardcoded list is probably not good enough (especially regarding internationalization)
69 //TODO this whole routine, including internationalized re/fwd ... should go into some library.
70 //We'll require the same for generating reply/forward subjects in kube
71 static QStringList defaultReplyPrefixes = QStringList() << QLatin1String("Re\\s*:")
72 << QLatin1String("Re\\[\\d+\\]:")
73 << QLatin1String("Re\\d+:");
74
75 static QStringList defaultForwardPrefixes = QStringList() << QLatin1String("Fwd:")
76 << QLatin1String("FW:");
77
78 QStringList replyPrefixes; // = GlobalSettings::self()->replyPrefixes();
79 if (replyPrefixes.isEmpty()) {
80 replyPrefixes = defaultReplyPrefixes;
81 }
82
83 QStringList forwardPrefixes; // = GlobalSettings::self()->forwardPrefixes();
84 if (forwardPrefixes.isEmpty()) {
85 forwardPrefixes = defaultReplyPrefixes;
86 }
87
88 const QStringList prefixRegExps = replyPrefixes + forwardPrefixes;
89
90 // construct a big regexp that
91 // 1. is anchored to the beginning of str (sans whitespace)
92 // 2. matches at least one of the part regexps in prefixRegExps
93 const QString bigRegExp = QString::fromLatin1("^(?:\\s+|(?:%1))+\\s*").arg(prefixRegExps.join(QLatin1String(")|(?:")));
94
95 static QString regExpPattern;
96 static QRegExp regExp;
97
98 regExp.setCaseSensitivity(Qt::CaseInsensitive);
99 if (regExpPattern != bigRegExp) {
100 // the prefixes have changed, so update the regexp
101 regExpPattern = bigRegExp;
102 regExp.setPattern(regExpPattern);
103 }
104
105 if(regExp.isValid()) {
106 QString tmp = subject;
107 if (regExp.indexIn( tmp ) == 0) {
108 return tmp.remove(0, regExp.matchedLength());
109 }
110 } else {
111 SinkWarning() << "bigRegExp = \""
112 << bigRegExp << "\"\n"
113 << "prefix regexp is invalid!";
114 }
115
116 return subject;
117}
118
119
66static void updateThreadingIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction) 120static void updateThreadingIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction)
67{ 121{
68 auto messageId = bufferAdaptor.getProperty(Mail::MessageId::name).toByteArray(); 122 auto messageId = bufferAdaptor.getProperty(Mail::MessageId::name).toByteArray();
69 auto parentMessageId = bufferAdaptor.getProperty(Mail::ParentMessageId::name).toByteArray(); 123 auto parentMessageId = bufferAdaptor.getProperty(Mail::ParentMessageId::name).toByteArray();
124 auto subject = bufferAdaptor.getProperty(Mail::Subject::name).toString();
70 125
71 Index msgIdIndex("msgId", transaction); 126 Index msgIdIndex("msgId", transaction);
72 Index msgIdThreadIdIndex("msgIdThreadId", transaction); 127 Index msgIdThreadIdIndex("msgIdThreadId", transaction);
128 Index subjectThreadIdIndex("subjectThreadId", transaction);
73 129
74 //Add the message to the index 130 //Add the message to the index
75 Q_ASSERT(msgIdIndex.lookup(messageId).isEmpty()); 131 Q_ASSERT(msgIdIndex.lookup(messageId).isEmpty());
76 msgIdIndex.add(messageId, identifier); 132 msgIdIndex.add(messageId, identifier);
77 133
78 //If parent is already available, add to thread of parent 134 auto normalizedSubject = stripOffPrefixes(subject).toUtf8();
135
79 QByteArray thread; 136 QByteArray thread;
137 //If parent is already available, add to thread of parent
80 if (!parentMessageId.isEmpty() && !msgIdIndex.lookup(parentMessageId).isEmpty()) { 138 if (!parentMessageId.isEmpty() && !msgIdIndex.lookup(parentMessageId).isEmpty()) {
81 thread = msgIdThreadIdIndex.lookup(parentMessageId); 139 thread = msgIdThreadIdIndex.lookup(parentMessageId);
82 msgIdThreadIdIndex.add(messageId, thread); 140 msgIdThreadIdIndex.add(messageId, thread);
141 subjectThreadIdIndex.add(normalizedSubject, thread);
83 } else { 142 } else {
84 thread = QUuid::createUuid().toByteArray(); 143 //Try to lookup the thread by subject:
85 if (!parentMessageId.isEmpty()) { 144 thread = subjectThreadIdIndex.lookup(normalizedSubject);
86 //Register parent with thread for when it becomes available 145 if (!thread.isEmpty()) {
87 msgIdThreadIdIndex.add(parentMessageId, thread); 146 msgIdThreadIdIndex.add(messageId, thread);
147 } else {
148 thread = QUuid::createUuid().toByteArray();
149 subjectThreadIdIndex.add(normalizedSubject, thread);
150 if (!parentMessageId.isEmpty()) {
151 //Register parent with thread for when it becomes available
152 msgIdThreadIdIndex.add(parentMessageId, thread);
153 }
88 } 154 }
89 } 155 }
90 Q_ASSERT(!thread.isEmpty()); 156 Q_ASSERT(!thread.isEmpty());
91 msgIdThreadIdIndex.add(messageId, thread); 157 msgIdThreadIdIndex.add(messageId, thread);
92
93 //Look for parentMessageId and resolve to local id if available
94} 158}
95 159
96void TypeImplementation<Mail>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction) 160void TypeImplementation<Mail>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction)
@@ -173,6 +237,7 @@ protected:
173 if (rootCollection->contains(thread)) { 237 if (rootCollection->contains(thread)) {
174 auto date = rootCollection->value(thread); 238 auto date = rootCollection->value(thread);
175 //The mail we have in our result already is newer, so we can ignore this one 239 //The mail we have in our result already is newer, so we can ignore this one
240 //This is always true during the initial query if the set has been sorted by date.
176 if (date > getProperty(entity.entity(), ApplicationDomain::Mail::Date::name).toDateTime()) { 241 if (date > getProperty(entity.entity(), ApplicationDomain::Mail::Date::name).toDateTime()) {
177 return false; 242 return false;
178 } 243 }