1/*
2 This file is part of the KContacts framework.
3 SPDX-FileCopyrightText: 2002 Tobias Koenig <tokoe@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "picture.h"
9
10#include <QBuffer>
11#include <QSharedData>
12
13
14namespace KContacts
15{
16class PicturePrivate : public QSharedData
17{
18public:
19 PicturePrivate()
20 : mIntern(false)
21 {
22 }
23
24 PicturePrivate(const PicturePrivate &other)
25 : QSharedData(other)
26 , mUrl(other.mUrl)
27 , mType(other.mType)
28 , mData(other.mData)
29 , mIntern(other.mIntern)
30 {
31 }
32
33 QString mUrl;
34 QString mType;
35 mutable QImage mData;
36 mutable QByteArray mRawData;
37
38 bool mIntern;
39};
40}
41
42Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<KContacts::PicturePrivate>, s_sharedEmpty, (new KContacts::PicturePrivate))
43
44using namespace KContacts;
45
46Picture::Picture()
47 : d(*s_sharedEmpty())
48{
49}
50
51Picture::Picture(const QString &url)
52 : d(new PicturePrivate)
53{
54 d->mUrl = url;
55}
56
57Picture::Picture(const QImage &data)
58 : d(new PicturePrivate)
59{
60 setData(data);
61}
62
63Picture::Picture(const Picture &other)
64 : d(other.d)
65{
66}
67
68Picture::~Picture() = default;
69
70Picture &Picture::operator=(const Picture &other)
71{
72 if (this != &other) {
73 d = other.d;
74 }
75
76 return *this;
77}
78
79bool Picture::operator==(const Picture &p) const
80{
81 if (d->mIntern != p.d->mIntern) {
82 return false;
83 }
84
85 if (d->mType != p.d->mType) {
86 return false;
87 }
88
89 if (d->mIntern) {
90 if (!d->mData.isNull() && !p.d->mData.isNull()) {
91 if (d->mData != p.d->mData) {
92 return false;
93 }
94 } else if (!d->mRawData.isEmpty() && !p.d->mRawData.isEmpty()) {
95 if (d->mRawData != p.d->mRawData) {
96 return false;
97 }
98 } else if ((!d->mData.isNull() || !d->mRawData.isEmpty()) //
99 && (!p.d->mData.isNull() || !p.d->mRawData.isEmpty())) {
100 if (data() != p.data()) {
101 return false;
102 }
103 } else {
104 // if one picture is empty and the other is not
105 return false;
106 }
107 } else {
108 if (d->mUrl != p.d->mUrl) {
109 return false;
110 }
111 }
112
113 return true;
114}
115
116bool Picture::operator!=(const Picture &p) const
117{
118 return !(p == *this);
119}
120
121bool Picture::isEmpty() const
122{
123 return (!d->mIntern && d->mUrl.isEmpty()) //
124 || (d->mIntern && d->mData.isNull() && d->mRawData.isEmpty());
125}
126
127void Picture::setUrl(const QString &url)
128{
129 d->mUrl = url;
130 d->mType.clear();
131 d->mIntern = false;
132}
133
134void Picture::setUrl(const QString &url, const QString &type)
135{
136 d->mUrl = url;
137 d->mType = type;
138 d->mIntern = false;
139}
140
141void Picture::setData(const QImage &data)
142{
143 d->mRawData.clear();
144 d->mData = data;
145 d->mIntern = true;
146
147 // set the type, the raw data will have when accessed through Picture::rawData()
148 if (!d->mData.hasAlphaChannel()) {
149 d->mType = QStringLiteral("jpeg");
150 } else {
151 d->mType = QStringLiteral("png");
152 }
153}
154
155void Picture::setRawData(const QByteArray &rawData, const QString &type)
156{
157 d->mRawData = rawData;
158 d->mType = type;
159 d->mData = QImage();
160 d->mIntern = true;
161}
162
163bool Picture::isIntern() const
164{
165 return d->mIntern;
166}
167
168QString Picture::url() const
169{
170 return d->mUrl;
171}
172
173QImage Picture::data() const
174{
175 if (d->mData.isNull() && !d->mRawData.isEmpty()) {
176 d->mData.loadFromData(data: d->mRawData);
177 }
178
179 return d->mData;
180}
181
182QByteArray Picture::rawData() const
183{
184 if (d->mRawData.isEmpty() && !d->mData.isNull()) {
185 QBuffer buffer(&d->mRawData);
186 buffer.open(openMode: QIODevice::WriteOnly);
187
188 // d->mType was already set accordingly by Picture::setData()
189 d->mData.save(device: &buffer, format: d->mType.toUpper().toLatin1().data());
190 }
191
192 return d->mRawData;
193}
194
195QString Picture::type() const
196{
197 return d->mType;
198}
199
200QString Picture::toString() const
201{
202 QString str = QLatin1String("Picture {\n");
203 str += QStringLiteral(" Type: %1\n").arg(a: d->mType);
204 str += QStringLiteral(" IsIntern: %1\n").arg(a: d->mIntern ? QStringLiteral("true") : QStringLiteral("false"));
205 if (d->mIntern) {
206 str += QStringLiteral(" Data: %1\n").arg(a: QString::fromLatin1(ba: rawData().toBase64()));
207 } else {
208 str += QStringLiteral(" Url: %1\n").arg(a: d->mUrl);
209 }
210 str += QLatin1String("}\n");
211
212 return str;
213}
214
215QDataStream &KContacts::operator<<(QDataStream &s, const Picture &picture)
216{
217 return s << picture.d->mIntern << picture.d->mUrl << picture.d->mType << picture.data();
218}
219
220QDataStream &KContacts::operator>>(QDataStream &s, Picture &picture)
221{
222 s >> picture.d->mIntern >> picture.d->mUrl >> picture.d->mType >> picture.d->mData;
223
224 return s;
225}
226
227#include "moc_picture.cpp"
228

source code of kcontacts/src/picture.cpp