File indexing completed on 2025-01-19 04:52:00

0001 /*
0002     Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
0003 
0004     This library is free software; you can redistribute it and/or modify it
0005     under the terms of the GNU Library General Public License as published by
0006     the Free Software Foundation; either version 2 of the License, or (at your
0007     option) any later version.
0008 
0009     This library is distributed in the hope that it will be useful, but WITHOUT
0010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
0012     License for more details.
0013 
0014     You should have received a copy of the GNU Library General Public License
0015     along with this library; see the file COPYING.LIB.  If not, write to the
0016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0017     02110-1301, USA.
0018 */
0019 #include "recepientautocompletionmodel.h"
0020 
0021 #include <QStandardItemModel>
0022 #include <QSettings>
0023 #include <QStandardPaths>
0024 #include <QSet>
0025 #include <QDebug>
0026 #include <QTimer>
0027 #include <KMime/Message>
0028 #include <sink/store.h>
0029 #include <sink/applicationdomaintype.h>
0030 
0031 using namespace Sink::ApplicationDomain;
0032 
0033 RecipientAutocompletionModel::RecipientAutocompletionModel(QObject *parent)
0034     : QSortFilterProxyModel(parent),
0035     mSourceModel(new QStandardItemModel),
0036     mTimer(new QTimer)
0037 {
0038     setSourceModel(mSourceModel.data());
0039     setDynamicSortFilter(true);
0040     setFilterCaseSensitivity(Qt::CaseInsensitive);
0041     mTimer->setSingleShot(true);
0042     QObject::connect(mTimer.data(), &QTimer::timeout, this, &RecipientAutocompletionModel::save);
0043 
0044     load();
0045 }
0046 
0047 RecipientAutocompletionModel::~RecipientAutocompletionModel()
0048 {
0049     save();
0050 }
0051 
0052 static QString getPath()
0053 {
0054     return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/kube/recepientautocompletion.ini";
0055 }
0056 
0057 void RecipientAutocompletionModel::save()
0058 {
0059     QSet<QString> list;
0060     for (int row = 0; row < mSourceModel->rowCount(); row++) {
0061         list << mSourceModel->item(row)->data(Text).toString();
0062     }
0063 
0064     QSettings settings(getPath(), QSettings::IniFormat);
0065     settings.setValue("list", QStringList{list.values()});
0066 }
0067 
0068 void RecipientAutocompletionModel::load()
0069 {
0070     QSettings settings(getPath(), QSettings::IniFormat);
0071     auto list = settings.value("list").toStringList();
0072     auto add = [] (const QString &n) {
0073         auto item = new QStandardItem{n};
0074         item->setData(n, Text);
0075         return item;
0076     };
0077     for (const auto &entry : list) {
0078         //Validate entries because we used to write unquoted nonsense like "Doe, John doe@example.com"
0079         KMime::Types::Mailbox mb;
0080         mb.fromUnicodeString(entry);
0081         if (mb.address().isEmpty()) {
0082             continue;
0083         }
0084         mSourceModel->appendRow(add(entry));
0085     }
0086     Sink::Query query;
0087     query.request<Contact::Fn>();
0088     query.request<Contact::Emails>();
0089     Sink::Store::fetchAll<Contact>(query)
0090         .then([this] (const QList<Contact::Ptr> &list) {
0091             for (const auto &c : list) {
0092                 for (const auto &email : c->getEmails()) {
0093                     addToModel(email.email, c->getFn());
0094                 }
0095             }
0096         }).exec();
0097 }
0098 
0099 QHash< int, QByteArray > RecipientAutocompletionModel::roleNames() const
0100 {
0101     QHash<int, QByteArray> roles;
0102     roles[Text] = "text";
0103     roles[Color] = "color";
0104     return roles;
0105 }
0106 
0107 
0108 bool RecipientAutocompletionModel::addToModel(const QString &address, const QString &name)
0109 {
0110     auto add = [] (const QString &n) {
0111         auto item = new QStandardItem{n};
0112         item->setData(n, Text);
0113         return item;
0114     };
0115     auto formattedName = [&] () {
0116         if (name.isEmpty()) {
0117             return address;
0118         }
0119         KMime::Types::Mailbox mb;
0120         mb.setName(name);
0121         mb.setAddress(address.toUtf8());
0122         return mb.prettyAddress(KMime::Types::Mailbox::QuoteWhenNecessary);
0123     }();
0124     auto matches = mSourceModel->findItems(formattedName);
0125     if (matches.isEmpty()) {
0126         mSourceModel->appendRow(add(formattedName));
0127         return true;
0128     }
0129     return false;
0130 }
0131 
0132 void RecipientAutocompletionModel::addEntry(const QByteArray &address, const QByteArray &name)
0133 {
0134     if (addToModel(address, name)) {
0135         mTimer->start(100);
0136     }
0137 }
0138 
0139 void RecipientAutocompletionModel::setFilter(const QString &filter)
0140 {
0141     setFilterWildcard("*" + filter +"*");
0142 }