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 | |
14 | namespace KContacts |
15 | { |
16 | class PicturePrivate : public QSharedData |
17 | { |
18 | public: |
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 | |
42 | Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<KContacts::PicturePrivate>, s_sharedEmpty, (new KContacts::PicturePrivate)) |
43 | |
44 | using namespace KContacts; |
45 | |
46 | Picture::Picture() |
47 | : d(*s_sharedEmpty()) |
48 | { |
49 | } |
50 | |
51 | Picture::Picture(const QString &url) |
52 | : d(new PicturePrivate) |
53 | { |
54 | d->mUrl = url; |
55 | } |
56 | |
57 | Picture::Picture(const QImage &data) |
58 | : d(new PicturePrivate) |
59 | { |
60 | setData(data); |
61 | } |
62 | |
63 | Picture::Picture(const Picture &other) |
64 | : d(other.d) |
65 | { |
66 | } |
67 | |
68 | Picture::~Picture() |
69 | { |
70 | } |
71 | |
72 | Picture &Picture::operator=(const Picture &other) |
73 | { |
74 | if (this != &other) { |
75 | d = other.d; |
76 | } |
77 | |
78 | return *this; |
79 | } |
80 | |
81 | bool 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 | |
118 | bool Picture::operator!=(const Picture &p) const |
119 | { |
120 | return !(p == *this); |
121 | } |
122 | |
123 | bool Picture::isEmpty() const |
124 | { |
125 | return (!d->mIntern && d->mUrl.isEmpty()) // |
126 | || (d->mIntern && d->mData.isNull() && d->mRawData.isEmpty()); |
127 | } |
128 | |
129 | void Picture::setUrl(const QString &url) |
130 | { |
131 | d->mUrl = url; |
132 | d->mType.clear(); |
133 | d->mIntern = false; |
134 | } |
135 | |
136 | void Picture::setUrl(const QString &url, const QString &type) |
137 | { |
138 | d->mUrl = url; |
139 | d->mType = type; |
140 | d->mIntern = false; |
141 | } |
142 | |
143 | void 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 | |
157 | void 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 | |
165 | bool Picture::isIntern() const |
166 | { |
167 | return d->mIntern; |
168 | } |
169 | |
170 | QString Picture::url() const |
171 | { |
172 | return d->mUrl; |
173 | } |
174 | |
175 | QImage 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 | |
184 | QByteArray 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 | |
197 | QString Picture::type() const |
198 | { |
199 | return d->mType; |
200 | } |
201 | |
202 | QString 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 | |
217 | QDataStream &KContacts::operator<<(QDataStream &s, const Picture &picture) |
218 | { |
219 | return s << picture.d->mIntern << picture.d->mUrl << picture.d->mType << picture.data(); |
220 | } |
221 | |
222 | QDataStream &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 | |