1 /*
2     encodedimagepicker.cpp
3 
4     KMail, the KDE mail client.
5     SPDX-FileCopyrightText: 2021 the KMail authors.
6     See file AUTHORS for details
7 
8     SPDX-License-Identifier: GPL-2.0-only
9 */
10 
11 #include "encodedimagepicker.h"
12 #include "ui_encodedimagepicker.h"
13 
14 #include <Akonadi/Contact/ContactSearchJob>
15 #include <KIdentityManagement/Identity>
16 #include <KIdentityManagement/IdentityManager>
17 #include <KPIMTextEdit/PlainTextEditor>
18 
19 #include <KIO/StoredTransferJob>
20 #include <KJobWidgets>
21 #include <KLocalizedString>
22 #include <KMessageBox>
23 
24 #include <QFileDialog>
25 #include <QImageReader>
26 
27 using namespace KMail;
28 using KContacts::Addressee;
29 
EncodedImagePicker(QWidget * parent)30 EncodedImagePicker::EncodedImagePicker(QWidget *parent)
31     : QGroupBox(parent)
32     , mUi(new Ui::EncodedImagePicker)
33 {
34     mUi->setupUi(this);
35 
36     mUi->source->editor()->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
37 
38     // wrap anywhere, these contain encoded data
39     mUi->source->editor()->setWordWrapMode(QTextOption::WrapAnywhere);
40 
41     connect(mUi->openImageButton, &QAbstractButton::clicked, this, &EncodedImagePicker::selectFile);
42     connect(mUi->selectContactsButton, &QPushButton::released, this, &EncodedImagePicker::selectFromAddressBook);
43     connect(mUi->source->editor(), &KPIMTextEdit::PlainTextEditor::textChanged, this, &EncodedImagePicker::sourceChanged);
44 }
45 
46 EncodedImagePicker::~EncodedImagePicker() = default;
47 
setInfo(const QString & info)48 void EncodedImagePicker::setInfo(const QString &info)
49 {
50     mUi->infoLabel->setText(info);
51 }
52 
source() const53 QString EncodedImagePicker::source() const
54 {
55     return mUi->source->editor()->toPlainText();
56 }
57 
setSource(const QString & source)58 void EncodedImagePicker::setSource(const QString &source)
59 {
60     mUi->source->editor()->setPlainText(source);
61 }
62 
setImage(const QImage & image)63 void EncodedImagePicker::setImage(const QImage &image)
64 {
65     if (image.isNull()) {
66         mUi->image->clear();
67     } else {
68         const QPixmap p = QPixmap::fromImage(image);
69         mUi->image->setPixmap(p);
70     }
71 }
72 
selectFile()73 void EncodedImagePicker::selectFile()
74 {
75     QString filter;
76     const QList<QByteArray> supportedImage = QImageReader::supportedImageFormats();
77     for (const QByteArray &ba : supportedImage) {
78         if (!filter.isEmpty()) {
79             filter += QLatin1Char(' ');
80         }
81         filter += QLatin1String("*.") + QString::fromLatin1(ba);
82     }
83 
84     filter = QStringLiteral("%1 (%2)").arg(i18n("Image"), filter);
85     const QUrl url = QFileDialog::getOpenFileUrl(this, QString(), QUrl(), filter);
86 
87     if (!url.isEmpty()) {
88         setFromFile(url);
89     }
90 }
91 
setFromFile(const QUrl & url)92 void EncodedImagePicker::setFromFile(const QUrl &url)
93 {
94     auto job = KIO::storedGet(url);
95     KJobWidgets::setWindow(job, this);
96     connect(job, &KJob::result, this, &EncodedImagePicker::setFromFileDone);
97     job->start();
98 }
99 
setFromFileDone(KJob * job)100 void EncodedImagePicker::setFromFileDone(KJob *job)
101 {
102     const KIO::StoredTransferJob *kioJob = qobject_cast<KIO::StoredTransferJob *>(job);
103 
104     if (kioJob->error() == 0) {
105         const QImage image = QImage::fromData(kioJob->data());
106 
107         Q_EMIT imageSelected(image);
108     } else {
109         KMessageBox::error(this, kioJob->errorString());
110     }
111 }
112 
selectFromAddressBook()113 void EncodedImagePicker::selectFromAddressBook()
114 {
115     using namespace KIdentityManagement;
116 
117     const IdentityManager manager(true);
118     const Identity defaultIdentity = manager.defaultIdentity();
119     const QString email = defaultIdentity.primaryEmailAddress().toLower();
120 
121     auto job = new Akonadi::ContactSearchJob(this);
122     job->setLimit(1);
123     job->setQuery(Akonadi::ContactSearchJob::Email, email, Akonadi::ContactSearchJob::ExactMatch);
124     connect(job, &KJob::result, this, &EncodedImagePicker::selectFromAddressBookDone);
125 }
126 
selectFromAddressBookDone(KJob * job)127 void EncodedImagePicker::selectFromAddressBookDone(KJob *job)
128 {
129     const Akonadi::ContactSearchJob *searchJob = qobject_cast<Akonadi::ContactSearchJob *>(job);
130 
131     if (searchJob->contacts().isEmpty()) {
132         KMessageBox::information(this, i18n("You do not have your own contact defined in the address book."), i18n("No Picture"));
133         return;
134     }
135 
136     const Addressee contact = searchJob->contacts().at(0);
137 
138     if (contact.photo().isIntern()) {
139         const QImage photo = contact.photo().data();
140 
141         if (photo.isNull()) {
142             KMessageBox::information(this, i18n("No picture set for your address book entry."), i18n("No Picture"));
143         } else {
144             Q_EMIT imageSelected(photo);
145         }
146     } else {
147         const QUrl url(contact.photo().url());
148 
149         if (url.isEmpty()) {
150             KMessageBox::information(this, i18n("No picture set for your address book entry."), i18n("No Picture"));
151         } else {
152             setFromFile(url);
153         }
154     }
155 }
156