1
2 /*
3 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28
29 #define DEBUG_KP_DOCUMENT 0
30
31
32 #include "kpDocument.h"
33 #include "kpDocumentPrivate.h"
34
35 #include "layers/selections/kpAbstractSelection.h"
36 #include "layers/selections/image/kpAbstractImageSelection.h"
37 #include "imagelib/kpColor.h"
38 #include "widgets/toolbars/kpColorToolBar.h"
39 #include "kpDefs.h"
40 #include "environments/document/kpDocumentEnvironment.h"
41 #include "document/kpDocumentSaveOptions.h"
42 #include "imagelib/kpDocumentMetaInfo.h"
43 #include "imagelib/effects/kpEffectReduceColors.h"
44 #include "tools/kpTool.h"
45 #include "widgets/toolbars/kpToolToolBar.h"
46 #include "lgpl/generic/kpUrlFormatter.h"
47
48
49 #include "kpLogCategories.h"
50 #include <KJobWidgets>
51 #include <KLocalizedString>
52 #include <KIO/StatJob>
53
54 #include <QColor>
55 #include <QBrush>
56 #include <QFile>
57 #include <QImage>
58 #include <QList>
59 #include <QPainter>
60 #include <QRect>
61 #include <QSize>
62 #include <QTransform>
63
64 //---------------------------------------------------------------------
65
kpDocument(int w,int h,kpDocumentEnvironment * environ)66 kpDocument::kpDocument (int w, int h,
67 kpDocumentEnvironment *environ)
68 : QObject (),
69 m_constructorWidth (w), m_constructorHeight (h),
70 m_isFromExistingURL (false),
71 m_savedAtLeastOnceBefore (false),
72 m_saveOptions (new kpDocumentSaveOptions ()),
73 m_metaInfo (new kpDocumentMetaInfo ()),
74 m_modified (false),
75 m_selection (nullptr),
76 m_oldWidth (-1), m_oldHeight (-1),
77 d (new kpDocumentPrivate ())
78 {
79 #if DEBUG_KP_DOCUMENT && 0
80 qCDebug(kpLogDocument) << "kpDocument::kpDocument (" << w << "," << h << ")";
81 #endif
82
83 m_image = new kpImage(w, h, QImage::Format_ARGB32_Premultiplied);
84 m_image->fill(QColor(Qt::white).rgb());
85
86 d->environ = environ;
87 }
88
89 //---------------------------------------------------------------------
90
~kpDocument()91 kpDocument::~kpDocument ()
92 {
93 delete d;
94
95 delete m_image;
96
97 delete m_saveOptions;
98 delete m_metaInfo;
99
100 delete m_selection;
101 }
102
103 //---------------------------------------------------------------------
104
105 // public
environ() const106 kpDocumentEnvironment *kpDocument::environ () const
107 {
108 return d->environ;
109 }
110
111 //---------------------------------------------------------------------
112
113 // public
setEnviron(kpDocumentEnvironment * environ)114 void kpDocument::setEnviron (kpDocumentEnvironment *environ)
115 {
116 d->environ = environ;
117 }
118
119 //---------------------------------------------------------------------
120
121 // public
savedAtLeastOnceBefore() const122 bool kpDocument::savedAtLeastOnceBefore () const
123 {
124 return m_savedAtLeastOnceBefore;
125 }
126
127 //---------------------------------------------------------------------
128
129 // public
url() const130 QUrl kpDocument::url () const
131 {
132 return m_url;
133 }
134
135 //---------------------------------------------------------------------
136
137 // public
setURL(const QUrl & url,bool isFromExistingURL)138 void kpDocument::setURL (const QUrl &url, bool isFromExistingURL)
139 {
140 m_url = url;
141 m_isFromExistingURL = isFromExistingURL;
142 }
143
144 //---------------------------------------------------------------------
145
146 // public
isFromExistingURL() const147 bool kpDocument::isFromExistingURL () const
148 {
149 return m_isFromExistingURL;
150 }
151
152 //---------------------------------------------------------------------
153
154 // public
urlExists(const QUrl & url) const155 bool kpDocument::urlExists (const QUrl &url) const
156 {
157 if (url.isEmpty()) {
158 return false;
159 }
160 KIO::StatJob *job = KIO::statDetails(url, KIO::StatJob::SourceSide, KIO::StatNoDetails);
161 KJobWidgets::setWindow (job, d->environ->dialogParent ());
162 return job->exec();
163 }
164
165 //---------------------------------------------------------------------
166
167 // public
prettyUrl() const168 QString kpDocument::prettyUrl () const
169 {
170 return kpUrlFormatter::PrettyUrl (m_url);
171 }
172
173 //---------------------------------------------------------------------
174
175 // public
prettyFilename() const176 QString kpDocument::prettyFilename () const
177 {
178 return kpUrlFormatter::PrettyFilename (m_url);
179 }
180
181 //---------------------------------------------------------------------
182
183 // public
saveOptions() const184 const kpDocumentSaveOptions *kpDocument::saveOptions () const
185 {
186 return m_saveOptions;
187 }
188
189 //---------------------------------------------------------------------
190
191 // public
setSaveOptions(const kpDocumentSaveOptions & saveOptions)192 void kpDocument::setSaveOptions (const kpDocumentSaveOptions &saveOptions)
193 {
194 *m_saveOptions = saveOptions;
195 }
196
197 //---------------------------------------------------------------------
198
199 // public
metaInfo() const200 const kpDocumentMetaInfo *kpDocument::metaInfo () const
201 {
202 return m_metaInfo;
203 }
204
205 //---------------------------------------------------------------------
206
207 // public
setMetaInfo(const kpDocumentMetaInfo & metaInfo)208 void kpDocument::setMetaInfo (const kpDocumentMetaInfo &metaInfo)
209 {
210 *m_metaInfo = metaInfo;
211 }
212
213 //---------------------------------------------------------------------
214
215 /*
216 * Properties
217 */
218
setModified(bool yes)219 void kpDocument::setModified (bool yes)
220 {
221 if (yes == m_modified) {
222 return;
223 }
224
225 m_modified = yes;
226
227 if (yes) {
228 emit documentModified ();
229 }
230 }
231
232 //---------------------------------------------------------------------
233
isModified() const234 bool kpDocument::isModified () const
235 {
236 return m_modified;
237 }
238
239 //---------------------------------------------------------------------
240
isEmpty() const241 bool kpDocument::isEmpty () const
242 {
243 return url ().isEmpty () && !isModified ();
244 }
245
246 //---------------------------------------------------------------------
247
constructorWidth() const248 int kpDocument::constructorWidth () const
249 {
250 return m_constructorWidth;
251 }
252
253 //---------------------------------------------------------------------
254
width(bool ofSelection) const255 int kpDocument::width (bool ofSelection) const
256 {
257 return (ofSelection && m_selection) ? m_selection->width() : m_image->width();
258 }
259
260 //---------------------------------------------------------------------
261
oldWidth() const262 int kpDocument::oldWidth () const
263 {
264 return m_oldWidth;
265 }
266
267 //---------------------------------------------------------------------
268
setWidth(int w,const kpColor & backgroundColor)269 void kpDocument::setWidth (int w, const kpColor &backgroundColor)
270 {
271 resize (w, height (), backgroundColor);
272 }
273
274 //---------------------------------------------------------------------
275
constructorHeight() const276 int kpDocument::constructorHeight () const
277 {
278 return m_constructorHeight;
279 }
280
281 //---------------------------------------------------------------------
282
height(bool ofSelection) const283 int kpDocument::height (bool ofSelection) const
284 {
285 return (ofSelection && m_selection) ? m_selection->height() : m_image->height();
286 }
287
288 //---------------------------------------------------------------------
289
oldHeight() const290 int kpDocument::oldHeight () const
291 {
292 return m_oldHeight;
293 }
294
295 //---------------------------------------------------------------------
296
setHeight(int h,const kpColor & backgroundColor)297 void kpDocument::setHeight (int h, const kpColor &backgroundColor)
298 {
299 resize (width (), h, backgroundColor);
300 }
301
302 //---------------------------------------------------------------------
303
rect(bool ofSelection) const304 QRect kpDocument::rect (bool ofSelection) const
305 {
306 return (ofSelection && m_selection) ? m_selection->boundingRect() : m_image->rect();
307 }
308
309 //---------------------------------------------------------------------
310
311 // public
getImageAt(const QRect & rect) const312 kpImage kpDocument::getImageAt (const QRect &rect) const
313 {
314 return kpPixmapFX::getPixmapAt (*m_image, rect);
315 }
316
317 //---------------------------------------------------------------------
318
319 // public
setImageAt(const kpImage & image,const QPoint & at)320 void kpDocument::setImageAt (const kpImage &image, const QPoint &at)
321 {
322 #if DEBUG_KP_DOCUMENT && 0
323 qCDebug(kpLogDocument) << "kpDocument::setImageAt (image (w="
324 << image.width ()
325 << ",h=" << image.height ()
326 << "), x=" << at.x ()
327 << ",y=" << at.y ();
328 #endif
329
330 kpPixmapFX::setPixmapAt (m_image, at, image);
331 slotContentsChanged (QRect (at.x (), at.y (), image.width (), image.height ()));
332 }
333
334 //---------------------------------------------------------------------
335
336 // public
image(bool ofSelection) const337 kpImage kpDocument::image (bool ofSelection) const
338 {
339 kpImage ret;
340
341 if (ofSelection)
342 {
343 kpAbstractImageSelection *imageSel = imageSelection ();
344 Q_ASSERT (imageSel);
345
346 ret = imageSel->baseImage ();
347 }
348 else {
349 ret = *m_image;
350 }
351
352 return ret;
353 }
354
355 //---------------------------------------------------------------------
356
357 // public
imagePointer() const358 kpImage *kpDocument::imagePointer () const
359 {
360 return m_image;
361 }
362
363 //---------------------------------------------------------------------
364
365 // public
setImage(const kpImage & image)366 void kpDocument::setImage (const kpImage &image)
367 {
368 m_oldWidth = width ();
369 m_oldHeight = height ();
370
371 *m_image = image;
372
373 if (m_oldWidth == width () && m_oldHeight == height ()) {
374 slotContentsChanged (image.rect ());
375 }
376 else {
377 slotSizeChanged (QSize (width (), height ()));
378 }
379 }
380
381 //---------------------------------------------------------------------
382
383 // public
setImage(bool ofSelection,const kpImage & image)384 void kpDocument::setImage (bool ofSelection, const kpImage &image)
385 {
386 if (ofSelection)
387 {
388 kpAbstractImageSelection *imageSel = imageSelection ();
389
390 // Have to have an image selection in order to set its pixmap.
391 Q_ASSERT (imageSel);
392
393 imageSel->setBaseImage (image);
394 }
395 else {
396 setImage (image);
397 }
398 }
399
400 //---------------------------------------------------------------------
401
fill(const kpColor & color)402 void kpDocument::fill (const kpColor &color)
403 {
404 #if DEBUG_KP_DOCUMENT
405 qCDebug(kpLogDocument) << "kpDocument::fill ()";
406 #endif
407
408 m_image->fill(color.toQRgb());
409 slotContentsChanged (m_image->rect ());
410 }
411
412 //---------------------------------------------------------------------
413
resize(int w,int h,const kpColor & backgroundColor)414 void kpDocument::resize (int w, int h, const kpColor &backgroundColor)
415 {
416 #if DEBUG_KP_DOCUMENT
417 qCDebug(kpLogDocument) << "kpDocument::resize (" << w << "," << h << ")";
418 #endif
419
420 m_oldWidth = width ();
421 m_oldHeight = height ();
422
423 #if DEBUG_KP_DOCUMENT && 1
424 qCDebug(kpLogDocument) << "\toldWidth=" << m_oldWidth
425 << " oldHeight=" << m_oldHeight;
426 #endif
427
428 if (w == m_oldWidth && h == m_oldHeight) {
429 return;
430 }
431
432 kpPixmapFX::resize (m_image, w, h, backgroundColor);
433
434 slotSizeChanged (QSize (width (), height ()));
435 }
436
437 //---------------------------------------------------------------------
438
slotContentsChanged(const QRect & rect)439 void kpDocument::slotContentsChanged (const QRect &rect)
440 {
441 setModified ();
442 emit contentsChanged (rect);
443 }
444
445 //---------------------------------------------------------------------
446
slotSizeChanged(const QSize & newSize)447 void kpDocument::slotSizeChanged (const QSize &newSize)
448 {
449 setModified ();
450 emit sizeChanged (newSize.width(), newSize.height());
451 emit sizeChanged (newSize);
452 }
453
454 //---------------------------------------------------------------------
455
456
457
458