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