File indexing completed on 2025-01-05 04:58:19

0001 /*
0002   This file is part of libkdepim.
0003 
0004   SPDX-FileCopyrightText: 2006 Christian Schaarschmidt <schaarsc@gmx.de>
0005   SPDX-FileCopyrightText: 2017-2024 Laurent Montel <montel@kde.org>
0006 
0007   SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #include "kmailcompletion.h"
0011 #include <QRegularExpression>
0012 #include <QSet>
0013 
0014 using namespace PimCommon;
0015 
0016 KMailCompletion::KMailCompletion()
0017 {
0018     setIgnoreCase(true);
0019 }
0020 
0021 void KMailCompletion::clear()
0022 {
0023     m_keyMap.clear();
0024     KCompletion::clear();
0025 }
0026 
0027 QString KMailCompletion::makeCompletion(const QString &string)
0028 {
0029     QString match = KCompletion::makeCompletion(string);
0030 
0031     static const QRegularExpression emailRegularExpression{QRegularExpression(QStringLiteral("(@)|(<.*>)"))};
0032     // this should be in postProcessMatch, but postProcessMatch is const and will not allow nextMatch
0033     if (!match.isEmpty()) {
0034         const QString firstMatch(match);
0035         while (match.indexOf(emailRegularExpression) == -1) {
0036             /* local email do not require @domain part, if match is an address we'll
0037              * find last+first <match> in m_keyMap and we'll know that match is
0038              * already a valid email.
0039              *
0040              * Distribution list do not have last+first <match> entry, they will be
0041              * in mailAddr
0042              */
0043             const QStringList &mailAddr = m_keyMap[match]; // get all mailAddr for this keyword
0044             bool isEmail = false;
0045             for (QStringList::ConstIterator sit(mailAddr.begin()), sEnd(mailAddr.end()); sit != sEnd; ++sit) {
0046                 if ((*sit).indexOf(QLatin1Char('<') + match + QLatin1Char('>')) != -1 || (*sit) == match) {
0047                     isEmail = true;
0048                     break;
0049                 }
0050             }
0051 
0052             if (!isEmail) {
0053                 // match is a keyword, skip it and try to find match <email@domain>
0054                 match = nextMatch();
0055                 if (firstMatch == match) {
0056                     match.clear();
0057                     break;
0058                 }
0059             } else {
0060                 break;
0061             }
0062         }
0063     }
0064     return match;
0065 }
0066 
0067 void KMailCompletion::addItemWithKeys(const QString &email, int weight, const QStringList *keyWords)
0068 {
0069     Q_ASSERT(keyWords != nullptr);
0070     QStringList::ConstIterator end = keyWords->constEnd();
0071     for (QStringList::ConstIterator it(keyWords->constBegin()); it != end; ++it) {
0072         QStringList &emailList = m_keyMap[(*it)]; // lookup email-list for given keyword
0073         if (!emailList.contains(email)) { // add email if not there
0074             emailList.append(email);
0075         }
0076         addItem((*it), weight); // inform KCompletion about keyword
0077     }
0078 }
0079 
0080 void KMailCompletion::postProcessMatches(QStringList *pMatches) const
0081 {
0082     Q_ASSERT(pMatches != nullptr);
0083     if (pMatches->isEmpty()) {
0084         return;
0085     }
0086 
0087     // KCompletion has found the keywords for us, we can now map them to mail-addr
0088     QSet<QString> mailAddrDistinct;
0089     for (QStringList::ConstIterator sit2(pMatches->begin()), sEnd2(pMatches->end()); sit2 != sEnd2; ++sit2) {
0090         const QStringList &mailAddr = m_keyMap[(*sit2)]; // get all mailAddr for this keyword
0091         if (mailAddr.isEmpty()) {
0092             mailAddrDistinct.insert(*sit2);
0093         } else {
0094             for (QStringList::ConstIterator sit(mailAddr.begin()), sEnd(mailAddr.end()); sit != sEnd; ++sit) {
0095                 mailAddrDistinct.insert(*sit); // store mailAddr, QSet will make them unique
0096             }
0097         }
0098     }
0099     pMatches->clear(); // delete keywords
0100     (*pMatches) += mailAddrDistinct.values(); // add emailAddr
0101 }
0102 
0103 #include "moc_kmailcompletion.cpp"