use kDebug
[kdegraphics.git] / kolourpaint / document / kpDocument_Selection.cpp
blob946f72e67e2a8a74b662b9ff37530e15c8eff3d6
2 /*
3 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
4 All rights reserved.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
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.
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.
29 #define DEBUG_KP_DOCUMENT 0
32 #include <kpDocument.h>
33 #include <kpDocumentPrivate.h>
35 #include <math.h>
37 #include <qcolor.h>
38 #include <qbitmap.h>
39 #include <qbrush.h>
40 #include <qfile.h>
41 #include <qimage.h>
42 #include <qlist.h>
43 #include <qpixmap.h>
44 #include <qpainter.h>
45 #include <qrect.h>
46 #include <qsize.h>
47 #include <qmatrix.h>
49 #include <kdebug.h>
50 #include <kglobal.h>
51 #include <kimageio.h>
52 #include <kio/netaccess.h>
53 #include <klocale.h>
54 #include <kmessagebox.h>
55 #include <kmimetype.h> // LOTODO: isn't this in KIO?
56 #include <ktemporaryfile.h>
58 #include <kpColor.h>
59 #include <kpColorToolBar.h>
60 #include <kpDefs.h>
61 #include <kpDocumentEnvironment.h>
62 #include <kpDocumentSaveOptions.h>
63 #include <kpDocumentMetaInfo.h>
64 #include <kpEffectReduceColors.h>
65 #include <kpPixmapFX.h>
66 #include <kpAbstractSelection.h>
67 #include <kpAbstractImageSelection.h>
68 #include <kpTextSelection.h>
69 #include <kpTool.h>
70 #include <kpToolToolBar.h>
73 // public
74 kpAbstractSelection *kpDocument::selection () const
76 return m_selection;
79 // public
80 kpAbstractImageSelection *kpDocument::imageSelection () const
82 return dynamic_cast <kpAbstractImageSelection *> (m_selection);
85 // public
86 kpTextSelection *kpDocument::textSelection () const
88 return dynamic_cast <kpTextSelection *> (m_selection);
92 // public
93 void kpDocument::setSelection (const kpAbstractSelection &selection)
95 #if DEBUG_KP_DOCUMENT && 1
96 kDebug () << "kpDocument::setSelection() sel boundingRect="
97 << selection.boundingRect ()
98 << endl;
99 #endif
101 d->environ->setQueueViewUpdates ();
103 const bool hadSelection = (bool) m_selection;
104 kpAbstractSelection *oldSelection = m_selection;
107 // (must be called before giving the document a new selection, to
108 // avoid a potential mess where switchToCompatibleTool() ends
109 // the current selection tool, killing the new selection)
110 bool isTextChanged = false;
111 d->environ->switchToCompatibleTool (selection, &isTextChanged);
112 Q_ASSERT (m_selection == oldSelection);
115 m_selection = selection.clone ();
117 // There's no need to uninitialize the old selection
118 // (e.g. call disconnect()) since we delete it later.
119 connect (m_selection, SIGNAL (changed (const QRect &)),
120 this, SLOT (slotContentsChanged (const QRect &)));
124 // Now all kpDocument state has been set.
125 // We can _only_ change the environment after that, as the environment
126 // may access the document. Exception is above with
127 // switchToCompatibleTool().
130 d->environ->assertMatchingUIState (selection);
134 // Now all kpDocument and environment state has been set.
135 // We can _only_ fire signals after that, as the signal receivers (the
136 // "wider environment") may access the document and the environment.
139 #if DEBUG_KP_DOCUMENT && 1
140 kDebug () << "\tcheck sel " << (int *) m_selection
141 << " boundingRect=" << m_selection->boundingRect ()
142 << endl;
143 #endif
144 if (oldSelection)
146 if (oldSelection->hasContent ())
147 slotContentsChanged (oldSelection->boundingRect ());
148 else
149 emit contentsChanged (oldSelection->boundingRect ());
151 delete oldSelection;
152 oldSelection = 0;
155 if (m_selection->hasContent ())
156 slotContentsChanged (m_selection->boundingRect ());
157 else
158 emit contentsChanged (m_selection->boundingRect ());
161 if (!hadSelection)
162 emit selectionEnabled (true);
164 if (isTextChanged)
165 emit selectionIsTextChanged (textSelection ());
167 d->environ->restoreQueueViewUpdates ();
169 #if DEBUG_KP_DOCUMENT && 1
170 kDebug () << "\tkpDocument::setSelection() ended";
171 #endif
174 // public
175 kpImage kpDocument::getSelectedBaseImage () const
177 kpAbstractImageSelection *imageSel = imageSelection ();
178 Q_ASSERT (imageSel);
180 // Easy if we already have it :)
181 const kpImage image = imageSel->baseImage ();
182 if (!image.isNull ())
183 return image;
186 const QRect boundingRect = imageSel->boundingRect ();
187 Q_ASSERT (boundingRect.isValid ());
189 // OPT: This is very slow. Image / More Effects ... calls us twice
190 // unnecessarily.
191 return imageSel->givenImageMaskedByShape (getImageAt (boundingRect));
194 // public
195 void kpDocument::imageSelectionPullFromDocument (const kpColor &backgroundColor)
197 kpAbstractImageSelection *imageSel = imageSelection ();
198 Q_ASSERT (imageSel);
200 // Should not already have an image or we would not be pulling.
201 Q_ASSERT (!imageSel->hasContent ());
203 const QRect boundingRect = imageSel->boundingRect ();
204 Q_ASSERT (boundingRect.isValid ());
208 // Get selection pixmap from document
211 kpImage selectedImage = getSelectedBaseImage ();
213 d->environ->setQueueViewUpdates ();
215 imageSel->setBaseImage (selectedImage);
219 // Fill opaque bits of the hole in the document
222 #if !defined (QT_NO_DEBUG) && !defined (NDEBUG)
223 if (imageSel->transparency ().isTransparent ())
225 Q_ASSERT (backgroundColor == imageSel->transparency ().transparentColor ());
227 else
229 // If this method is begin called by a tool, the assert does not
230 // have to hold since transparentColor() might not be defined in Opaque
231 // Mode.
233 // If we were called by a tricky sequence of undo/redo commands, the assert
234 // does not have to hold for additional reason, which is that
235 // kpMainWindow::setImageSelectionTransparency() does not have to
236 // set <backgroundColor> in Opaque Mode.
238 // In practice, it probably does hold but I wouldn't bet on it.
240 #endif
242 const kpImage selTransparentImage = imageSel->transparentImage ();
244 if (backgroundColor.isOpaque ())
246 kpImage eraseImage (boundingRect.width (), boundingRect.height ());
247 eraseImage.fill (backgroundColor.toQColor ());
249 if (kpPixmapFX::hasMask (selTransparentImage))
250 eraseImage.setMask (selTransparentImage.mask ());
252 paintImageAt (eraseImage, boundingRect.topLeft ());
254 else
256 kpPixmapFX::paintMaskTransparentWithBrush (m_image,
257 boundingRect.topLeft (),
258 kpPixmapFX::getNonNullMask (selTransparentImage));
259 slotContentsChanged (boundingRect);
262 d->environ->restoreQueueViewUpdates ();
265 // public
266 void kpDocument::selectionDelete ()
268 Q_ASSERT (m_selection);
270 const QRect boundingRect = m_selection->boundingRect ();
271 Q_ASSERT (boundingRect.isValid ());
273 const bool selectionHadContent = m_selection->hasContent ();
275 delete m_selection;
276 m_selection = 0;
279 // HACK to prevent document from being modified when
280 // user cancels dragging out a new selection
281 // REFACTOR: Extract this out into a method.
282 if (selectionHadContent)
283 slotContentsChanged (boundingRect);
284 else
285 emit contentsChanged (boundingRect);
287 emit selectionEnabled (false);
290 // public
291 void kpDocument::selectionCopyOntoDocument (bool applySelTransparency)
293 Q_ASSERT (m_selection);
294 Q_ASSERT (m_selection->hasContent ());
296 const QRect boundingRect = m_selection->boundingRect ();
297 Q_ASSERT (boundingRect.isValid ());
299 if (imageSelection ())
301 if (applySelTransparency)
302 imageSelection ()->paint (m_image, rect ());
303 else
304 imageSelection ()->paintWithBaseImage (m_image, rect ());
306 else
308 // (for antialiasing with background)
309 m_selection->paint (m_image, rect ());
312 slotContentsChanged (boundingRect);
315 // public
316 void kpDocument::selectionPushOntoDocument (bool applySelTransparency)
318 selectionCopyOntoDocument (applySelTransparency);
319 selectionDelete ();
322 // public
323 kpImage kpDocument::imageWithSelection () const
325 #if DEBUG_KP_DOCUMENT && 1
326 kDebug () << "kpDocument::imageWithSelection()";
327 #endif
329 // Have selection?
331 // It need not have any content because e.g. a text box with an opaque
332 // background, but no content, is still visually there.
333 if (m_selection)
335 #if DEBUG_KP_DOCUMENT && 1
336 kDebug () << "\tselection @ " << m_selection->boundingRect ();
337 #endif
338 kpImage output = *m_image;
340 // (this is a NOP for image selections without content)
341 m_selection->paint (&output, rect ());
343 return output;
345 else
347 #if DEBUG_KP_DOCUMENT && 1
348 kDebug () << "\tno selection";
349 #endif
350 return *m_image;