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()
69{
70}
71
72Picture &Picture::operator=(const Picture &other)
73{
74 if (this != &other) {
75 d = other.d;
76 }
77
78 return *this;
79}
80
81bool Picture::operator==(const Picture &p) const
82{
83 if (d->mIntern != p.d->mIntern) {
84 return false;
85 }
86
87 if (d->mType != p.d->mType) {
88 return false;
89 }
90
91 if (d->mIntern) {
92 if (!d->mData.isNull() && !p.d->mData.isNull()) {
93 if (d->mData != p.d->mData) {
94 return false;
95 }
96 } else if (!d->mRawData.isEmpty() && !p.d->mRawData.isEmpty()) {
97 if (d->mRawData != p.d->mRawData) {
98 return false;
99 }
100 } else if ((!d->mData.isNull() || !d->mRawData.isEmpty()) //
101 && (!p.d->mData.isNull() || !p.d->mRawData.isEmpty())) {
102 if (data() != p.data()) {
103 return false;
104 }
105 } else {
106 // if one picture is empty and the other is not
107 return false;
108 }
109 } else {
110 if (d->mUrl != p.d->mUrl) {
111 return false;
112 }
113 }
114
115 return true;
116}
117
118bool Picture::operator!=(const Picture &p) const
119{
120 return !(p == *this);
121}
122
123bool Picture::isEmpty() const
124{
125 return (!d->mIntern && d->mUrl.isEmpty()) //
126 || (d->mIntern && d->mData.isNull() && d->mRawData.isEmpty());
127}
128
129void Picture::setUrl(const QString &url)
130{
131 d->mUrl = url;
132 d->mType.clear();
133 d->mIntern = false;
134}
135
136void Picture::setUrl(const QString &url, const QString &type)
137{
138 d->mUrl = url;
139 d->mType = type;
140 d->mIntern = false;
141}
142
143void Picture::setData(const QImage &data)
144{
145 d->mRawData.clear();
146 d->mData = data;
147 d->mIntern = true;
148
149 // set the type, the raw data will have when accessed through Picture::rawData()
150 if (!d->mData.hasAlphaChannel()) {
151 d->mType = QStringLiteral("jpeg");
152 } else {
153 d->mType = QStringLiteral("png");
154 }
155}
156
157void Picture::setRawData(const QByteArray &rawData, const QString &type)
158{
159 d->mRawData = rawData;
160 d->mType = type;
161 d->mData = QImage();
162 d->mIntern = true;
163}
164
165bool Picture::isIntern() const
166{
167 return d->mIntern;
168}
169
170QString Picture::url() const
171{
172 return d->mUrl;
173}
174
175QImage Picture::data() const
176{
177 if (d->mData.isNull() && !d->mRawData.isEmpty()) {
178 d->mData.loadFromData(data: d->mRawData);
179 }
180
181 return d->mData;
182}
183
184QByteArray Picture::rawData() const
185{
186 if (d->mRawData.isEmpty() && !d->mData.isNull()) {
187 QBuffer buffer(&d->mRawData);
188 buffer.open(openMode: QIODevice::WriteOnly);
189
190 // d->mType was already set accordingly by Picture::setData()
191 d->mData.save(device: &buffer, format: d->mType.toUpper().toLatin1().data());
192 }
193
194 return d->mRawData;
195}
196
197QString Picture::type() const
198{
199 return d->mType;
200}
201
202QString Picture::toString() const
203{
204 QString str = QLatin1String("Picture {\n");
205 str += QStringLiteral(" Type: %1\n").arg(a: d->mType);
206 str += QStringLiteral(" IsIntern: %1\n").arg(a: d->mIntern ? QStringLiteral("true") : QStringLiteral("false"));
207 if (d->mIntern) {
208 str += QStringLiteral(" Data: %1\n").arg(a: QString::fromLatin1(ba: rawData().toBase64()));
209 } else {
210 str += QStringLiteral(" Url: %1\n").arg(a: d->mUrl);
211 }
212 str += QLatin1String("}\n");
213
214 return str;
215}
216
217QDataStream &KContacts::operator<<(QDataStream &s, const Picture &picture)
218{
219 return s << picture.d->mIntern << picture.d->mUrl << picture.d->mType << picture.data();
220}
221
222QDataStream &KContacts::operator>>(QDataStream &s, Picture &picture)
223{
224 s >> picture.d->mIntern >> picture.d->mUrl >> picture.d->mType >> picture.d->mData;
225
226 return s;
227}
228
229#include "moc_picture.cpp"
230

source code of kcontacts/src/picture.cpp