3 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
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 #include <kpMainWindow.h>
30 #include <kpMainWindowPrivate.h>
32 #include <qapplication.h>
33 #include <qclipboard.h>
34 #include <qdatetime.h>
35 #include <qfontmetrics.h>
44 #include <kmessagebox.h>
45 #include <kstandardaction.h>
46 #include <kactioncollection.h>
47 #include <kxmlguifactory.h>
49 #include <kpAbstractImageSelection.h>
50 #include <kpColorToolBar.h>
51 #include <kpCommandHistory.h>
52 #include <kpDocument.h>
53 #include <kpDocumentMetaInfo.h>
54 #include <kpDocumentSaveOptions.h>
55 #include <kpImageSelectionTransparency.h>
56 #include <kpMacroCommand.h>
57 #include <kpPixmapFX.h>
58 #include <kpRectangularImageSelection.h>
59 #include <kpSelectionDrag.h>
60 #include <kpSetOverrideCursorSaver.h>
61 #include <kpTextSelection.h>
63 #include <kpToolTextGiveContentCommand.h>
64 #include <kpToolSelectionCreateCommand.h>
65 #include <kpToolSelectionDestroyCommand.h>
66 #include <kpToolTextEnterCommand.h>
67 #include <kpToolTextInsertCommand.h>
68 #include <kpTransformCrop.h>
69 #include <kpTransformResizeScaleCommand.h>
70 #include <kpViewManager.h>
71 #include <kpViewScrollableContainer.h>
72 #include <kpZoomedView.h>
76 kpPixmapFX::WarnAboutLossInfo
kpMainWindow::pasteWarnAboutLossInfo ()
78 return kpPixmapFX::WarnAboutLossInfo (
79 ki18n ("<qt><p>The image to be pasted"
80 " may have more colors than the current screen mode can support."
81 " In order to display it, some color information may be removed.</p>"
83 "<p><b>If you save this image, any color loss will become"
86 "<p>To avoid this issue, increase your screen depth to at"
87 " least %1bpp and then restart KolourPaint.</p>"
93 " contains translucency which is not fully"
94 " supported. The translucency data will be"
95 " approximated with a 1-bit transparency mask.</p>"
97 "<p><b>If you save this image, this loss of translucency will"
98 " become permanent.</b></p></qt>"),
99 ki18n ("<qt><p>The image to be pasted"
100 " may have more colors than the current screen mode can support."
101 " In order to display it, some color information may be removed.</p>"
103 "<p><b>If you save this image, any color loss will become"
104 " permanent.</b></p>"
106 "<p>To avoid this issue, increase your screen depth to at"
107 " least %1bpp and then restart KolourPaint.</p></qt>"),
108 i18n ("<qt><p>The image to be pasted"
109 " contains translucency which is not fully"
110 " supported. The translucency data will be"
111 " approximated with a 1-bit transparency mask.</p>"
113 "<p><b>If you save this image, this loss of translucency will"
114 " become permanent.</b></p></qt>"),
121 void kpMainWindow::setupEditMenuActions ()
123 KActionCollection
*ac
= actionCollection ();
127 // CONFIG: Need GUI for config history size.
128 d
->commandHistory
= new kpCommandHistory (true/*read config*/, this);
130 if (d
->configFirstTime
)
132 // (so that cfg-file-editing user can modify in the meantime)
133 d
->commandHistory
->writeConfig ();
137 d
->actionCut
= KStandardAction::cut (this, SLOT (slotCut ()), ac
);
138 d
->actionCopy
= KStandardAction::copy (this, SLOT (slotCopy ()), ac
);
139 d
->actionPaste
= KStandardAction::paste (this, SLOT (slotPaste ()), ac
);
140 d
->actionPasteInNewWindow
= ac
->addAction ("edit_paste_in_new_window");
141 d
->actionPasteInNewWindow
->setText (i18n ("Paste in &New Window"));
142 connect (d
->actionPasteInNewWindow
, SIGNAL (triggered (bool)),
143 SLOT (slotPasteInNewWindow ()));
144 d
->actionPasteInNewWindow
->setShortcut(Qt::CTRL
+ Qt::SHIFT
+ Qt::Key_V
);
146 //d->actionDelete = KStandardAction::clear (this, SLOT (slotDelete ()), ac);
147 d
->actionDelete
= ac
->addAction ("edit_clear");
148 d
->actionDelete
->setText (i18n ("&Delete Selection"));
149 connect (d
->actionDelete
, SIGNAL (triggered (bool)), SLOT (slotDelete ()));
151 d
->actionSelectAll
= KStandardAction::selectAll (this, SLOT (slotSelectAll ()), ac
);
152 d
->actionDeselect
= KStandardAction::deselect (this, SLOT (slotDeselect ()), ac
);
155 d
->actionCopyToFile
= ac
->addAction ("edit_copy_to_file");
156 d
->actionCopyToFile
->setText (i18n ("C&opy to File..."));
157 connect (d
->actionCopyToFile
, SIGNAL (triggered (bool)),
158 SLOT (slotCopyToFile ()));
159 d
->actionPasteFromFile
= ac
->addAction ("edit_paste_from_file");
160 d
->actionPasteFromFile
->setText (i18n ("Paste &From File..."));
161 connect (d
->actionPasteFromFile
, SIGNAL (triggered (bool)),
162 SLOT (slotPasteFromFile ()));
165 d
->editMenuDocumentActionsEnabled
= false;
166 enableEditMenuDocumentActions (false);
168 // Paste should always be enabled, as long as there is something paste
169 // (independent of whether we have a document or not)
170 connect (QApplication::clipboard (), SIGNAL (dataChanged ()),
171 this, SLOT (slotEnablePaste ()));
176 void kpMainWindow::enableEditMenuDocumentActions (bool enable
)
181 // d->actionPasteInNewWindow
185 d
->actionSelectAll
->setEnabled (enable
);
188 d
->editMenuDocumentActionsEnabled
= enable
;
190 // d->actionCopyToFile
192 // Unlike d->actionPaste, we disable this if there is no document.
193 // This is because "File / Open" would do the same thing, if there is
195 d
->actionPasteFromFile
->setEnabled (enable
);
200 QMenu
*kpMainWindow::selectionToolRMBMenu ()
202 return qobject_cast
<QMenu
*> (guiFactory ()->container ("selectionToolRMBMenu", this));
207 void kpMainWindow::slotCut ()
209 #if DEBUG_KP_MAIN_WINDOW && 1
210 kDebug () << "kpMainWindow::slotCut() CALLED";
213 kpSetOverrideCursorSaver
cursorSaver (Qt::WaitCursor
);
215 Q_ASSERT (d
->document
&& d
->document
->selection ());
223 static QMimeData
*NewTextMimeData (const QString
&text
)
225 QMimeData
*md
= new QMimeData ();
231 void kpMainWindow::slotCopy ()
233 #if DEBUG_KP_MAIN_WINDOW && 1
234 kDebug () << "kpMainWindow::slotCopy() CALLED";
237 kpSetOverrideCursorSaver
cursorSaver (Qt::WaitCursor
);
239 Q_ASSERT (d
->document
&& d
->document
->selection ());
243 kpAbstractSelection
*sel
= d
->document
->selection ()->clone ();
245 if (dynamic_cast <kpTextSelection
*> (sel
))
247 kpTextSelection
*textSel
= static_cast <kpTextSelection
*> (sel
);
248 if (!textSel
->text ().isEmpty ())
250 QApplication::clipboard ()->setMimeData (
251 ::NewTextMimeData (textSel
->text ()),
252 QClipboard::Clipboard
);
254 // SYNC: Normally, users highlight text and press CTRL+C.
255 // Highlighting text copies it to the X11 "middle
256 // mouse button" clipboard. CTRL+C copies it to the
257 // separate, Windows-like "CTRL+V" clipboard.
259 // However, KolourPaint doesn't support highlighting.
260 // So when they press CTRL+C to copy all text, simulate
261 // the highlighting by copying the text to the "middle
262 // mouse button" clipboard. We don't do this for images
263 // as no one ever middle-mouse-pastes images.
265 // Note that we don't share the QMimeData pointer with
266 // the above in case Qt doesn't expect it.
268 // Once we change KolourPaint to support highlighted text
269 // and CTRL+C to copy only the highlighted text, delete
271 QApplication::clipboard ()->setMimeData (
272 ::NewTextMimeData (textSel
->text ()),
273 QClipboard::Selection
);
276 else if (dynamic_cast <kpAbstractImageSelection
*> (sel
))
278 kpAbstractImageSelection
*imageSel
=
279 static_cast <kpAbstractImageSelection
*> (sel
);
281 // Transparency doesn't get sent across the aether so nuke it now
282 // so that transparency mask doesn't get needlessly recalculated
283 // if we ever call sel.setBaseImage().
284 imageSel
->setTransparency (kpImageSelectionTransparency ());
288 if (imageSel
->hasContent ())
289 rawImage
= imageSel
->baseImage ();
291 rawImage
= d
->document
->getSelectedBaseImage ();
293 // Some apps, such as OpenOffice.org 2.0.4, ignore the image mask
294 // when pasting. For transparent pixels, the uninitialized RGB
295 // values are used. Fix this by initializing those values to a
296 // neutral color -- white.
298 // Strangely enough, OpenOffice.org respects the mask when inserting
299 // an image from a file, as opposed to pasting one from the clipboard.
301 // REFACTOR: This logic should be moved into kpSelectionDrag as that
302 // would centralize this responsibility.
304 // TODO: This does not work under Qt4 (we get black, instead of white,
305 // which is still OK, just not intended).
306 // See kpPixmapFX::pixmapWithDefinedTransparentPixels() API Doc.
307 imageSel
->setBaseImage (
308 kpPixmapFX::pixmapWithDefinedTransparentPixels (
310 Qt::white
)); // CONFIG
312 QApplication::clipboard ()->setMimeData (
313 new kpSelectionDrag (*imageSel
),
314 QClipboard::Clipboard
);
317 Q_ASSERT (!"Unknown selection type");
323 static bool HasSomethingToPaste (kpMainWindow
*mw
)
325 #if DEBUG_KP_MAIN_WINDOW
326 kDebug () << "kpMainWindow(" << mw
->objectName () << "):HasSomethingToPaste()";
333 const QMimeData
*md
=
334 QApplication::clipboard ()->mimeData (QClipboard::Clipboard
);
337 // It's faster to test for QMimeData::hasText() first due to the
338 // lazy evaluation of the '||' operator.
339 const bool hasSomething
=
340 (md
->hasText () || kpSelectionDrag::canDecode (md
));
341 #if DEBUG_KP_MAIN_WINDOW
342 kDebug () << "\t" << mw
->objectName () << "***canDecode=" << hasSomething
343 << "(time=" << timer
.restart () << ")"
344 << "formats=" << md
->formats ();
350 // HACK: SYNC: Non-Qt apps do not cause QApplication::clipboard() to
351 // emit dataChanged(). We don't want to have our paste
352 // action disabled when we can actually paste something.
354 // So we make sure the paste action is always enabled and
355 // before any paste, we check if there's actually something
356 // to paste (HasSomethingToPasteWithDialogIfNot ()).
358 #if 1 // Hack code path
361 // Call before any paste only.
362 static bool HasSomethingToPasteWithDialogIfNot (kpMainWindow
*mw
)
364 if (::HasSomethingToPaste (mw
))
367 kpSetOverrideCursorSaver
cursorSaver (Qt::ArrowCursor
);
369 KMessageBox::sorry (mw
,
370 i18n ("<qt><p>There is nothing in the clipboard to paste.</p></qt>"),
371 i18n ("Cannot Paste"));
376 void kpMainWindow::slotEnablePaste ()
378 const bool shouldEnable
= true;
379 d
->actionPasteInNewWindow
->setEnabled (shouldEnable
);
380 d
->actionPaste
->setEnabled (shouldEnable
);
387 // Call before any paste only.
388 static bool HasSomethingToPasteWithDialogIfNot (kpMainWindow
*)
390 // We will not be called if there's nothing to paste, as the paste
391 // action would have been disabled. But do _not_ assert that
392 // (see the slotPaste() "data unexpectedly disappeared" KMessageBox).
397 void kpMainWindow::slotEnablePaste ()
399 const bool shouldEnable
= ::HasSomethingToPaste (this);
400 d
->actionPasteInNewWindow
->setEnabled (shouldEnable
);
401 d
->actionPaste
->setEnabled (shouldEnable
);
409 QRect
kpMainWindow::calcUsefulPasteRect (int imageWidth
, int imageHeight
)
411 #if DEBUG_KP_MAIN_WINDOW && 1
412 kDebug () << "kpMainWindow::calcUsefulPasteRect("
413 << imageWidth
<< "," << imageHeight
417 Q_ASSERT (d
->document
);
419 // TODO: 1st choice is to paste sel near but not overlapping last deselect point
421 if (d
->mainView
&& d
->scrollView
)
423 const QPoint
viewTopLeft (d
->scrollView
->contentsX (),
424 d
->scrollView
->contentsY ());
426 const QPoint docTopLeft
= d
->mainView
->transformViewToDoc (viewTopLeft
);
428 if ((docTopLeft
.x () + imageWidth
<= d
->document
->width () &&
429 docTopLeft
.y () + imageHeight
<= d
->document
->height ()) ||
430 imageWidth
<= docTopLeft
.x () ||
431 imageHeight
<= docTopLeft
.y ())
433 return QRect (docTopLeft
.x (), docTopLeft
.y (),
434 imageWidth
, imageHeight
);
438 return QRect (0, 0, imageWidth
, imageHeight
);
442 void kpMainWindow::paste (const kpAbstractSelection
&sel
, bool forceTopLeft
)
444 #if DEBUG_KP_MAIN_WINDOW && 1
445 kDebug () << "kpMainWindow::paste(forceTopLeft=" << forceTopLeft
<< ")"
449 kpSetOverrideCursorSaver
cursorSaver (Qt::WaitCursor
);
455 // Make sure we've got a document (esp. with File/Close)
460 kpDocument
*newDoc
= new kpDocument (
461 sel
.width (), sel
.height (), documentEnvironment ());
463 // will also create viewManager
464 setDocument (newDoc
);
469 // Paste as new selection
472 const kpAbstractImageSelection
*imageSel
=
473 dynamic_cast <const kpAbstractImageSelection
*> (&sel
);
474 if (imageSel
&& imageSel
->hasContent () && imageSel
->transparency ().isTransparent ())
476 d
->colorToolBar
->flashColorSimilarityToolBarItem ();
479 kpAbstractSelection
*selInUsefulPos
= sel
.clone ();
481 selInUsefulPos
->moveTo (calcUsefulPasteRect (sel
.width (), sel
.height ()).topLeft ());
482 // TODO: Should use kpCommandHistory::addCreateSelectionCommand(),
483 // as well, to really support pasting selection borders.
484 addDeselectFirstCommand (new kpToolSelectionCreateCommand (
485 dynamic_cast <kpTextSelection
*> (selInUsefulPos
) ?
486 i18n ("Text: Create Box") :
487 i18n ("Selection: Create"),
489 commandEnvironment ()));
490 delete selInUsefulPos
;
493 #if DEBUG_KP_MAIN_WINDOW && 1
494 kDebug () << "sel.size=" << QSize (sel
.width (), sel
.height ())
496 << QSize (d
->document
->width (), d
->document
->height ())
500 // If the selection is bigger than the document, automatically
501 // resize the document (with the option of Undo'ing) to fit
504 // No annoying dialog necessary.
506 if (sel
.width () > d
->document
->width () ||
507 sel
.height () > d
->document
->height ())
509 d
->commandHistory
->addCommand (
510 new kpTransformResizeScaleCommand (
511 false/*act on doc, not sel*/,
512 qMax (sel
.width (), d
->document
->width ()),
513 qMax (sel
.height (), d
->document
->height ()),
514 kpTransformResizeScaleCommand::Resize
,
515 commandEnvironment ()));
520 void kpMainWindow::pasteText (const QString
&text
,
521 bool forceNewTextSelection
,
522 const QPoint
&newTextSelectionTopLeft
)
524 #if DEBUG_KP_MAIN_WINDOW && 1
525 kDebug () << "kpMainWindow::pasteText(" << text
526 << ",forceNewTextSelection=" << forceNewTextSelection
527 << ",newTextSelectionTopLeft=" << newTextSelectionTopLeft
535 kpSetOverrideCursorSaver
cursorSaver (Qt::WaitCursor
);
540 QList
<QString
> textLines
;
541 textLines
.append (QString ());
543 for (int i
= 0; i
< (int) text
.length (); i
++)
545 if (text
[i
] == '\n')
546 textLines
.push_back (QString::null
); //krazy:exclude=nullstrassign for old broken gcc
548 textLines
[textLines
.size () - 1].append (text
[i
]);
552 if (!forceNewTextSelection
&&
553 d
->document
&& d
->document
->textSelection () &&
554 d
->commandHistory
&& d
->viewManager
)
556 #if DEBUG_KP_MAIN_WINDOW && 1
557 kDebug () << "\treusing existing Text Selection";
560 kpTextSelection
*textSel
= d
->document
->textSelection ();
561 if (!textSel
->hasContent ())
563 #if DEBUG_KP_MAIN_WINDOW && 1
564 kDebug () << "\t\tneeds content";
566 commandHistory ()->addCreateSelectionCommand (
567 new kpToolSelectionCreateCommand (
568 i18n ("Text: Create Box"),
570 commandEnvironment ()),
574 kpMacroCommand
*macroCmd
= new kpMacroCommand (i18n ("Text: Paste"),
575 commandEnvironment ());
576 // (yes, this is the same check as the previous "if")
577 if (!textSel
->hasContent ())
579 kpCommand
*giveContentCmd
= new kpToolTextGiveContentCommand (
581 QString ()/*uninteresting child of macro cmd*/,
582 commandEnvironment ());
583 giveContentCmd
->execute ();
585 macroCmd
->addCommand (giveContentCmd
);
588 for (int i
= 0; i
< (int) textLines
.size (); i
++)
592 macroCmd
->addCommand (
593 new kpToolTextEnterCommand (
594 QString::null
/*uninteresting child of macroCmd*/, //krazy:exclude=nullstrassign for old broken gcc
595 d
->viewManager
->textCursorRow (),
596 d
->viewManager
->textCursorCol (),
597 kpToolTextEnterCommand::AddEnterNow
,
598 commandEnvironment ()));
601 macroCmd
->addCommand (
602 new kpToolTextInsertCommand (
603 QString::null
/*uninteresting child of macroCmd*/, //krazy:exclude=nullstrassign for old broken gcc
604 d
->viewManager
->textCursorRow (),
605 d
->viewManager
->textCursorCol (),
607 commandEnvironment ()));
610 d
->commandHistory
->addCommand (macroCmd
, false/*no exec*/);
614 #if DEBUG_KP_MAIN_WINDOW && 1
615 kDebug () << "\tcreating Text Selection";
618 const kpTextStyle ts
= textStyle ();
619 const QFontMetrics fontMetrics
= ts
.fontMetrics ();
621 int height
= textLines
.size () * fontMetrics
.height ();
622 if (textLines
.size () >= 1)
623 height
+= (textLines
.size () - 1) * fontMetrics
.leading ();
626 for (QList
<QString
>::const_iterator it
= textLines
.constBegin ();
627 it
!= textLines
.constEnd ();
630 const int w
= fontMetrics
.width (*it
);
636 const int selWidth
= qMax (kpTextSelection::MinimumWidthForTextStyle (ts
),
637 width
+ kpTextSelection::TextBorderSize () * 2);
638 const int selHeight
= qMax (kpTextSelection::MinimumHeightForTextStyle (ts
),
639 height
+ kpTextSelection::TextBorderSize () * 2);
640 kpTextSelection
newTextSel (QRect (0, 0, selWidth
, selHeight
),
644 if (newTextSelectionTopLeft
!= KP_INVALID_POINT
)
646 newTextSel
.moveTo (newTextSelectionTopLeft
);
647 paste (newTextSel
, true/*force topLeft*/);
657 void kpMainWindow::pasteTextAt (const QString
&text
, const QPoint
&point
,
658 bool allowNewTextSelectionPointShift
)
660 #if DEBUG_KP_MAIN_WINDOW && 1
661 kDebug () << "kpMainWindow::pasteTextAt(" << text
662 << ",point=" << point
663 << ",allowNewTextSelectionPointShift="
664 << allowNewTextSelectionPointShift
668 kpSetOverrideCursorSaver
cursorSaver (Qt::WaitCursor
);
674 d
->document
->textSelection () &&
675 d
->document
->textSelection ()->pointIsInTextArea (point
))
677 kpTextSelection
*textSel
= d
->document
->textSelection ();
681 if (textSel
->hasContent ())
683 row
= textSel
->closestTextRowForPoint (point
);
684 col
= textSel
->closestTextColForPoint (point
);
691 d
->viewManager
->setTextCursorPosition (row
, col
);
697 QPoint pointToUse
= point
;
699 if (allowNewTextSelectionPointShift
)
701 // TODO: In terms of doc pixels, would be inconsistent behaviour
702 // based on zoomLevel of view.
703 // pointToUse -= QPoint (-view->selectionResizeHandleAtomicSize (),
704 // -view->selectionResizeHandleAtomicSize ());
707 pasteText (text
, true/*force new text selection*/, pointToUse
);
712 void kpMainWindow::slotPaste ()
714 #if DEBUG_KP_MAIN_WINDOW && 1
715 kDebug () << "kpMainWindow::slotPaste() CALLED";
718 kpSetOverrideCursorSaver
cursorSaver (Qt::WaitCursor
);
723 if (!::HasSomethingToPasteWithDialogIfNot (this))
728 // Acquire the image.
731 const QMimeData
*md
= QApplication::clipboard ()->mimeData (QClipboard::Clipboard
);
734 kpAbstractImageSelection
*sel
= kpSelectionDrag::decode (md
,
735 pasteWarnAboutLossInfo ());
738 sel
->setTransparency (imageSelectionTransparency ());
742 else if (md
->hasText ())
744 pasteText (md
->text ());
748 kpSetOverrideCursorSaver
cursorSaver (Qt::ArrowCursor
);
750 kDebug () << "kpMainWindow::slotPaste() could not decode selection";
751 kDebug () << "\tFormats supported:" << md
->formats ();
754 KMessageBox::sorry (this,
755 i18n ("<qt><p>KolourPaint cannot paste the contents of"
756 " the clipboard as the data unexpectedly disappeared.</p>"
758 "<p>This usually occurs if the application which was"
760 " for the clipboard contents has been closed.</p></qt>"),
761 i18n ("Cannot Paste"));
763 // TODO: PROPAGATE: interprocess
764 // TODO: Is this loop safe since a KMainWindow later along in the list,
765 // could be closed as the code in the body almost certainly re-enters
766 // the event loop? Problem for KDE 3 as well, I think.
767 foreach (KMainWindow
*kmw
, KMainWindow::memberList ())
769 Q_ASSERT (dynamic_cast <kpMainWindow
*> (kmw
));
770 kpMainWindow
*mw
= static_cast <kpMainWindow
*> (kmw
);
772 #if DEBUG_KP_MAIN_WINDOW
773 kDebug () << "\t\tmw=" << mw
;
776 mw
->slotEnablePaste ();
784 void kpMainWindow::slotPasteInNewWindow ()
786 #if DEBUG_KP_MAIN_WINDOW && 1
787 kDebug () << "kpMainWindow::slotPasteInNewWindow() CALLED";
790 kpSetOverrideCursorSaver
cursorSaver (Qt::WaitCursor
);
795 if (!::HasSomethingToPasteWithDialogIfNot (this))
800 // Pasting must ensure that:
802 // Requirement 1. the document is the same size as the image to be pasted.
803 // Requirement 2. transparent pixels in the image must remain as transparent.
806 kpMainWindow
*win
= new kpMainWindow (0/*no document*/);
809 // Make "Edit / Paste in New Window" always paste white pixels as white.
810 // Don't let selection transparency get in the way and paste them as
812 kpImageSelectionTransparency transparency
= win
->imageSelectionTransparency ();
813 if (transparency
.isTransparent ())
815 #if DEBUG_KP_MAIN_WINDOW && 1
816 kDebug () << "\tchanging image selection transparency to opaque";
818 transparency
.setOpaque ();
819 // Since we are setting selection transparency programmatically
820 // -- as opposed to in response to user input -- this will not
821 // affect the selection transparency tool option widget's "last used"
823 win
->setImageSelectionTransparency (transparency
);
826 // (this handles Requirement 1. above)
829 // (this handles Requirement 2. above;
830 // slotDeselect() is not enough unless the document is filled with the
831 // transparent color in advance)
836 void kpMainWindow::slotDelete ()
838 #if DEBUG_KP_MAIN_WINDOW && 1
839 kDebug () << "kpMainWindow::slotDelete() CALLED";
841 if (!d
->actionDelete
->isEnabled ())
843 #if DEBUG_KP_MAIN_WINDOW && 1
844 kDebug () << "\taction not enabled - was probably called from kpTool::keyPressEvent()";
849 Q_ASSERT (d
->document
&& d
->document
->selection ());
853 addImageOrSelectionCommand (new kpToolSelectionDestroyCommand (
854 d
->document
->textSelection () ?
855 i18n ("Text: Delete Box") : // not to be confused with i18n ("Text: Delete")
856 i18n ("Selection: Delete"),
857 false/*no push onto doc*/,
858 commandEnvironment ()));
863 void kpMainWindow::slotSelectAll ()
865 #if DEBUG_KP_MAIN_WINDOW && 1
866 kDebug () << "kpMainWindow::slotSelectAll() CALLED";
868 Q_ASSERT (d
->document
);
872 if (d
->document
->selection ())
875 // just the border - don't actually pull image from doc yet
876 d
->document
->setSelection (
877 kpRectangularImageSelection (d
->document
->rect (),
878 imageSelectionTransparency ()));
881 tool ()->somethingBelowTheCursorChanged ();
886 void kpMainWindow::addDeselectFirstCommand (kpCommand
*cmd
)
888 #if DEBUG_KP_MAIN_WINDOW && 1
889 kDebug () << "kpMainWindow::addDeselectFirstCommand("
896 kpAbstractSelection
*sel
= d
->document
->selection ();
898 #if DEBUG_KP_MAIN_WINDOW && 1
899 kDebug () << "\tsel=" << sel
;
904 // if you just dragged out something with no action then
906 if (!sel
->hasContent ())
908 #if DEBUG_KP_MAIN_WINDOW && 1
909 kDebug () << "\tjust a fresh border - was nop - delete";
911 d
->document
->selectionDelete ();
913 tool ()->somethingBelowTheCursorChanged ();
916 d
->commandHistory
->addCommand (cmd
);
920 #if DEBUG_KP_MAIN_WINDOW && 1
921 kDebug () << "\treal selection with image - push onto doc cmd";
923 kpCommand
*deselectCommand
= new kpToolSelectionDestroyCommand (
924 dynamic_cast <kpTextSelection
*> (sel
) ?
925 i18n ("Text: Finish") :
926 i18n ("Selection: Deselect"),
927 true/*push onto document*/,
928 commandEnvironment ());
932 kpMacroCommand
*macroCmd
= new kpMacroCommand (cmd
->name (),
933 commandEnvironment ());
934 macroCmd
->addCommand (deselectCommand
);
935 macroCmd
->addCommand (cmd
);
936 d
->commandHistory
->addCommand (macroCmd
);
939 d
->commandHistory
->addCommand (deselectCommand
);
945 d
->commandHistory
->addCommand (cmd
);
951 void kpMainWindow::slotDeselect ()
953 #if DEBUG_KP_MAIN_WINDOW && 1
954 kDebug () << "kpMainWindow::slotDeselect() CALLED";
956 Q_ASSERT (d
->document
&& d
->document
->selection ());
960 addDeselectFirstCommand (0);
965 void kpMainWindow::slotCopyToFile ()
967 #if DEBUG_KP_MAIN_WINDOW
968 kDebug () << "kpMainWindow::slotCopyToFile()";
974 if (!d
->document
->selection ())
979 if (d
->document
->imageSelection ())
981 kpAbstractImageSelection
*imageSel
= d
->document
->imageSelection ();
982 if (!imageSel
->hasContent ())
984 // Not a floating selection - user has just selected a region;
985 // haven't pulled it off yet so probably don't expect and can't
986 // visualize selection transparency so give opaque, not transparent
988 imageToSave
= d
->document
->getSelectedBaseImage ();
991 imageToSave
= imageSel
->transparentImage ();
993 else if (d
->document
->textSelection ())
995 imageToSave
= d
->document
->textSelection ()->approximateImage ();
998 Q_ASSERT (!"Unknown selection type");
1001 kpDocumentSaveOptions chosenSaveOptions
;
1002 bool allowOverwritePrompt
, allowLossyPrompt
;
1003 KUrl chosenURL
= askForSaveURL (i18n ("Copy to File"),
1004 d
->lastCopyToURL
.url (),
1006 d
->lastCopyToSaveOptions
,
1007 kpDocumentMetaInfo (),
1008 kpSettingsGroupEditCopyTo
,
1009 false/*allow remote files*/,
1012 &allowOverwritePrompt
,
1015 if (chosenURL
.isEmpty ())
1019 if (!kpDocument::savePixmapToFile (imageToSave
,
1021 chosenSaveOptions
, kpDocumentMetaInfo (),
1022 allowOverwritePrompt
,
1030 addRecentURL (chosenURL
);
1033 d
->lastCopyToURL
= chosenURL
;
1034 d
->lastCopyToSaveOptions
= chosenSaveOptions
;
1036 d
->copyToFirstTime
= false;
1040 void kpMainWindow::slotPasteFromFile ()
1042 #if DEBUG_KP_MAIN_WINDOW
1043 kDebug () << "kpMainWindow::slotPasteFromFile()";
1049 KUrl::List urls
= askForOpenURLs (i18n ("Paste From File"),
1050 d
->lastPasteFromURL
.url (),
1051 false/*only 1 URL*/);
1053 if (urls
.count () != 1)
1056 KUrl url
= urls
.first ();
1057 d
->lastPasteFromURL
= url
;
1060 kpImage image
= kpDocument::getPixmapFromFile (url
,
1061 false/*show error message if doesn't exist*/,
1065 if (image
.isNull ())
1071 paste (kpRectangularImageSelection (
1072 QRect (0, 0, image
.width (), image
.height ()),
1074 imageSelectionTransparency ()));