/*
Copyright ( c ) 2003 , 2004 , 2005 Clarence Dang < dang @ kde . org >
All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
documentation and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# include <kpmainwindow.h>
# include <tqapplication.h>
# include <tqclipboard.h>
# include <tqdatetime.h>
# include <tqfontmetrics.h>
# include <tqimage.h>
# include <tqpixmap.h>
# include <tqvaluevector.h>
# include <tdeaction.h>
# include <kdebug.h>
# include <tdelocale.h>
# include <tdemessagebox.h>
# include <kstdaction.h>
# include <kpcommandhistory.h>
# include <kpdocument.h>
# include <kpdocumentmetainfo.h>
# include <kpdocumentsaveoptions.h>
# include <kppixmapfx.h>
# include <kpselection.h>
# include <kpselectiondrag.h>
# include <kpselectiontransparency.h>
# include <kptool.h>
# include <kptoolcrop.h>
# include <kptoolresizescale.h>
# include <kptoolselection.h>
# include <kptooltext.h>
# include <kpviewmanager.h>
# include <kpviewscrollablecontainer.h>
# include <kpzoomedview.h>
// private
kpPixmapFX : : WarnAboutLossInfo kpMainWindow : : pasteWarnAboutLossInfo ( )
{
return kpPixmapFX : : WarnAboutLossInfo (
i18n ( " The image to be pasted "
" may have more colors than the current screen mode. "
" In order to display it, some colors may be changed. "
" Try increasing your screen depth to at least %1bpp. "
" \n It also "
" contains translucency which is not fully "
" supported. The translucency data will be "
" approximated with a 1-bit transparency mask. " ) ,
i18n ( " The image to be pasted "
" may have more colors than the current screen mode. "
" In order to display it, some colors may be changed. "
" Try increasing your screen depth to at least %1bpp. " ) ,
i18n ( " The image to be pasted "
" contains translucency which is not fully "
" supported. The translucency data will be "
" approximated with a 1-bit transparency mask. " ) ,
" paste " ,
this ) ;
}
// private
void kpMainWindow : : setupEditMenuActions ( )
{
TDEActionCollection * ac = actionCollection ( ) ;
// Undo/Redo
// CONFIG: need GUI
m_commandHistory = new kpCommandHistory ( true /*read config*/ , this ) ;
if ( m_configFirstTime )
{
// (so that cfg-file-editing user can modify in the meantime)
m_commandHistory - > writeConfig ( ) ;
}
m_actionCut = KStdAction : : cut ( this , TQ_SLOT ( slotCut ( ) ) , ac ) ;
m_actionCopy = KStdAction : : copy ( this , TQ_SLOT ( slotCopy ( ) ) , ac ) ;
m_actionPaste = KStdAction : : paste ( this , TQ_SLOT ( slotPaste ( ) ) , ac ) ;
m_actionPasteInNewWindow = new TDEAction ( i18n ( " Paste in &New Window " ) ,
TQt : : CTRL + TQt : : SHIFT + TQt : : Key_V ,
this , TQ_SLOT ( slotPasteInNewWindow ( ) ) , ac , " edit_paste_in_new_window " ) ;
//m_actionDelete = KStdAction::clear (this, TQ_SLOT (slotDelete ()), ac);
m_actionDelete = new TDEAction ( i18n ( " &Delete Selection " ) , 0 ,
this , TQ_SLOT ( slotDelete ( ) ) , ac , " edit_clear " ) ;
m_actionSelectAll = KStdAction : : selectAll ( this , TQ_SLOT ( slotSelectAll ( ) ) , ac ) ;
m_actionDeselect = KStdAction : : deselect ( this , TQ_SLOT ( slotDeselect ( ) ) , ac ) ;
m_actionCopyToFile = new TDEAction ( i18n ( " C&opy to File... " ) , 0 ,
this , TQ_SLOT ( slotCopyToFile ( ) ) , ac , " edit_copy_to_file " ) ;
m_actionPasteFromFile = new TDEAction ( i18n ( " Paste &From File... " ) , 0 ,
this , TQ_SLOT ( slotPasteFromFile ( ) ) , ac , " edit_paste_from_file " ) ;
m_editMenuDocumentActionsEnabled = false ;
enableEditMenuDocumentActions ( false ) ;
// Paste should always be enabled, as long as there is something paste
// (independent of whether we have a document or not)
connect ( TQApplication : : clipboard ( ) , TQ_SIGNAL ( dataChanged ( ) ) ,
this , TQ_SLOT ( slotEnablePaste ( ) ) ) ;
slotEnablePaste ( ) ;
}
// private
void kpMainWindow : : enableEditMenuDocumentActions ( bool enable )
{
// m_actionCut
// m_actionCopy
// m_actionPaste
// m_actionPasteInNewWindow
// m_actionDelete
m_actionSelectAll - > setEnabled ( enable ) ;
// m_actionDeselect
m_editMenuDocumentActionsEnabled = enable ;
// m_actionCopyToFile
// Unlike m_actionPaste, we disable this if there is no document.
// This is because "File / Open" would do the same thing, if there is
// no document.
m_actionPasteFromFile - > setEnabled ( enable ) ;
}
// public
TQPopupMenu * kpMainWindow : : selectionToolRMBMenu ( )
{
return ( TQPopupMenu * ) guiFactory ( ) - > container ( " selectionToolRMBMenu " , this ) ;
}
// private slot
void kpMainWindow : : slotCut ( )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " kpMainWindow::slotCut() CALLED " < < endl ;
# endif
if ( ! m_document | | ! m_document - > selection ( ) )
{
kdError ( ) < < " kpMainWindow::slotCut () doc= " < < m_document
< < " sel= " < < ( m_document ? m_document - > selection ( ) : 0 )
< < endl ;
return ;
}
TQApplication : : setOverrideCursor ( TQt : : waitCursor ) ;
if ( toolHasBegunShape ( ) )
tool ( ) - > endShapeInternal ( ) ;
slotCopy ( ) ;
slotDelete ( ) ;
TQApplication : : restoreOverrideCursor ( ) ;
}
// private slot
void kpMainWindow : : slotCopy ( )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " kpMainWindow::slotCopy() CALLED " < < endl ;
# endif
if ( ! m_document | | ! m_document - > selection ( ) )
{
kdError ( ) < < " kpMainWindow::slotCopy () doc= " < < m_document
< < " sel= " < < ( m_document ? m_document - > selection ( ) : 0 )
< < endl ;
return ;
}
TQApplication : : setOverrideCursor ( TQt : : waitCursor ) ;
if ( toolHasBegunShape ( ) )
tool ( ) - > endShapeInternal ( ) ;
kpSelection sel = * m_document - > selection ( ) ;
// Transparency doesn't get sent across the aether so nuke it now
// so that transparency mask doesn't get needlessly recalculated
// if we ever call sel.setPixmap().
sel . setTransparency ( kpSelectionTransparency ( ) ) ;
if ( sel . isText ( ) )
{
if ( ! sel . text ( ) . isEmpty ( ) )
{
TQApplication : : clipboard ( ) - > setData ( new TQTextDrag ( sel . text ( ) ) ,
TQClipboard : : Clipboard ) ;
// SYNC: Normally, users highlight text and press CTRL+C.
// Highlighting text copies it to the X11 "middle
// mouse button" clipboard. CTRL+C copies it to the
// separate, Windows-like "CTRL+V" clipboard.
//
// However, KolourPaint doesn't support highlighting.
// So when they press CTRL+C to copy all text, simulate
// the highlighting by copying the text to the "middle
// mouse button" clipboard. We don't do this for images
// as no one ever middle-mouse-pastes images.
//
// Note that we don't share the TQTextDrag pointer with
// the above in case TQt doesn't expect it.
//
// Once we change KolourPaint to support highlighted text
// and CTRL+C to copy only the highlighted text, delete
// this code.
TQApplication : : clipboard ( ) - > setData ( new TQTextDrag ( sel . text ( ) ) ,
TQClipboard : : Selection ) ;
}
}
else
{
TQPixmap rawPixmap ;
if ( sel . pixmap ( ) )
rawPixmap = * sel . pixmap ( ) ;
else
rawPixmap = m_document - > getSelectedPixmap ( ) ;
// Some apps, such as OpenOffice.org 2.0.4, ignore the image mask
// when pasting. For transparent pixels, the uninitialized RGB
// values are used. Fix this by initializing those values to a
// neutral color -- white.
//
// Strangely enough, OpenOffice.org respects the mask when inserting
// an image from a file, as opposed to pasting one from the clipboard.
sel . setPixmap (
kpPixmapFX : : pixmapWithDefinedTransparentPixels (
rawPixmap ,
TQt : : white ) ) ; // CONFIG
TQApplication : : clipboard ( ) - > setData ( new kpSelectionDrag ( sel ) ,
TQClipboard : : Clipboard ) ;
}
TQApplication : : restoreOverrideCursor ( ) ;
}
static bool HasSomethingToPaste ( kpMainWindow * mw )
{
# if DEBUG_KP_MAIN_WINDOW
kdDebug ( ) < < " kpMainWindow( " < < mw - > name ( ) < < " ):HasSomethingToPaste() " < < endl ;
TQTime timer ;
timer . start ( ) ;
# else
( void ) mw ;
# endif
bool hasSomething = false ;
TQMimeSource * ms = TQApplication : : clipboard ( ) - > data ( TQClipboard : : Clipboard ) ;
if ( ms )
{
// It's faster to test for TQTextDrag::canDecode() first due to the
// lazy evaluation of the '||' operator.
hasSomething = ( TQTextDrag : : canDecode ( ms ) | |
kpSelectionDrag : : canDecode ( ms ) ) ;
# if DEBUG_KP_MAIN_WINDOW
kdDebug ( ) < < " \t " < < mw - > name ( ) < < " ***canDecode= " < < timer . restart ( ) < < endl ;
for ( int i = 0 ; ; i + + )
{
const char * fmt = ms - > format ( i ) ;
if ( ! fmt )
break ;
kdDebug ( ) < < " \t ' " < < fmt < < " ' " < < endl ;
}
# endif
}
return hasSomething ;
}
// HACK: SYNC: Non-TQt apps do not cause TQApplication::clipboard() to
// emit dataChanged(). We don't want to have our paste
// action disabled when we can actually paste something.
//
// So we make sure the paste action is always enabled and
// before any paste, we check if there's actually something
// to paste (HasSomethingToPasteWithDialogIfNot ()).
# if 1 // Hack code path
// Call before any paste only.
static bool HasSomethingToPasteWithDialogIfNot ( kpMainWindow * mw )
{
if ( : : HasSomethingToPaste ( mw ) )
return true ;
// STRING: Unfortunately, we are in a string freeze.
# if 1
( void ) mw ;
# else
TQApplication : : setOverrideCursor ( TQt : : arrowCursor ) ;
KMessageBox : : sorry ( mw ,
STRING_FREEZE_i18n ( " <qt><p>There is nothing in the clipboard to paste.</p></qt> " ) ,
STRING_FREEZE_i18n ( " Cannot Paste " ) ) ;
TQApplication : : restoreOverrideCursor ( ) ;
# endif
return false ;
}
// private slot
void kpMainWindow : : slotEnablePaste ( )
{
const bool shouldEnable = true ;
m_actionPasteInNewWindow - > setEnabled ( shouldEnable ) ;
m_actionPaste - > setEnabled ( shouldEnable ) ;
}
# else // No hack
// Call before any paste only.
static bool HasSomethingToPasteWithDialogIfNot ( kpMainWindow * )
{
// We will not be called if there's nothing to paste, as the paste
// action would have been disabled. But do _not_ assert that
// (see the slotPaste() "data unexpectedly disappeared" KMessageBox).
return true ;
}
// private slot
void kpMainWindow : : slotEnablePaste ( )
{
const bool shouldEnable = : : HasSomethingToPaste ( this ) ;
m_actionPasteInNewWindow - > setEnabled ( shouldEnable ) ;
m_actionPaste - > setEnabled ( shouldEnable ) ;
}
# endif
// private
TQRect kpMainWindow : : calcUsefulPasteRect ( int pixmapWidth , int pixmapHeight )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " kpMainWindow::calcUsefulPasteRect( "
< < pixmapWidth < < " , " < < pixmapHeight
< < " ) "
< < endl ;
# endif
if ( ! m_document )
{
kdError ( ) < < " kpMainWindow::calcUsefulPasteRect() without doc " < < endl ;
return TQRect ( ) ;
}
// TODO: 1st choice is to paste sel near but not overlapping last deselect point
if ( m_mainView & & m_scrollView )
{
const TQPoint viewTopLeft ( m_scrollView - > contentsX ( ) ,
m_scrollView - > contentsY ( ) ) ;
const TQPoint docTopLeft = m_mainView - > transformViewToDoc ( viewTopLeft ) ;
if ( ( docTopLeft . x ( ) + pixmapWidth < = m_document - > width ( ) & &
docTopLeft . y ( ) + pixmapHeight < = m_document - > height ( ) ) | |
pixmapWidth < = docTopLeft . x ( ) | |
pixmapHeight < = docTopLeft . y ( ) )
{
return TQRect ( docTopLeft . x ( ) , docTopLeft . y ( ) ,
pixmapWidth , pixmapHeight ) ;
}
}
return TQRect ( 0 , 0 , pixmapWidth , pixmapHeight ) ;
}
// private
void kpMainWindow : : paste ( const kpSelection & sel , bool forceTopLeft )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " kpMainWindow::paste(forceTopLeft= " < < forceTopLeft < < " ) "
< < endl ;
# endif
if ( ! sel . pixmap ( ) )
{
kdError ( ) < < " kpMainWindow::paste() with sel without pixmap " < < endl ;
return ;
}
TQApplication : : setOverrideCursor ( TQt : : waitCursor ) ;
if ( toolHasBegunShape ( ) )
tool ( ) - > endShapeInternal ( ) ;
//
// Make sure we've got a document (esp. with File/Close)
//
if ( ! m_document )
{
kpDocument * newDoc = new kpDocument (
sel . width ( ) , sel . height ( ) , this ) ;
// will also create viewManager
setDocument ( newDoc ) ;
}
//
// Paste as new selection
//
kpSelection selInUsefulPos = sel ;
if ( ! forceTopLeft )
selInUsefulPos . moveTo ( calcUsefulPasteRect ( sel . width ( ) , sel . height ( ) ) . topLeft ( ) ) ;
addDeselectFirstCommand ( new kpToolSelectionCreateCommand (
selInUsefulPos . isText ( ) ?
i18n ( " Text: Create Box " ) :
i18n ( " Selection: Create " ) ,
selInUsefulPos ,
this ) ) ;
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " sel.size= " < < TQSize ( sel . width ( ) , sel . height ( ) )
< < " document.size= "
< < TQSize ( m_document - > width ( ) , m_document - > height ( ) )
< < endl ;
# endif
// If the selection is bigger than the document, automatically
// resize the document (with the option of Undo'ing) to fit
// the selection.
//
// No annoying dialog necessary.
//
if ( sel . width ( ) > m_document - > width ( ) | |
sel . height ( ) > m_document - > height ( ) )
{
m_commandHistory - > addCommand (
new kpToolResizeScaleCommand (
false /*act on doc, not sel*/ ,
TQMAX ( sel . width ( ) , m_document - > width ( ) ) ,
TQMAX ( sel . height ( ) , m_document - > height ( ) ) ,
kpToolResizeScaleCommand : : Resize ,
this ) ) ;
}
TQApplication : : restoreOverrideCursor ( ) ;
}
// public
void kpMainWindow : : pasteText ( const TQString & text ,
bool forceNewTextSelection ,
const TQPoint & newTextSelectionTopLeft )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " kpMainWindow::pasteText( " < < text
< < " ,forceNewTextSelection= " < < forceNewTextSelection
< < " ,newTextSelectionTopLeft= " < < newTextSelectionTopLeft
< < " ) " < < endl ;
# endif
if ( text . isEmpty ( ) )
return ;
// sync: restoreOverrideCursor() in all exit paths
TQApplication : : setOverrideCursor ( TQt : : waitCursor ) ;
if ( toolHasBegunShape ( ) )
tool ( ) - > endShapeInternal ( ) ;
TQValueVector < TQString > textLines ( 1 , TQString ( ) ) ;
for ( int i = 0 ; i < ( int ) text . length ( ) ; i + + )
{
if ( text [ i ] = = ' \n ' )
textLines . push_back ( TQString ( ) ) ;
else
textLines [ textLines . size ( ) - 1 ] . append ( text [ i ] ) ;
}
if ( ! forceNewTextSelection & &
m_document & & m_document - > selection ( ) & &
m_document - > selection ( ) - > isText ( ) & &
m_commandHistory & & m_viewManager )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " \t reusing existing Text Selection " < < endl ;
# endif
kpMacroCommand * macroCmd = new kpMacroCommand ( i18n ( " Text: Paste " ) ,
this ) ;
for ( int i = 0 ; i < ( int ) textLines . size ( ) ; i + + )
{
if ( i > 0 )
{
macroCmd - > addCommand (
new kpToolTextEnterCommand (
TQString ( ) /*uninteresting child of macroCmd*/ ,
m_viewManager - > textCursorRow ( ) ,
m_viewManager - > textCursorCol ( ) ,
this ) ) ;
}
macroCmd - > addCommand (
new kpToolTextInsertCommand (
TQString ( ) /*uninteresting child of macroCmd*/ ,
m_viewManager - > textCursorRow ( ) ,
m_viewManager - > textCursorCol ( ) ,
textLines [ i ] ,
this ) ) ;
}
m_commandHistory - > addCommand ( macroCmd , false /*no exec*/ ) ;
}
else
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " \t creating Text Selection " < < endl ;
# endif
const kpTextStyle ts = textStyle ( ) ;
const TQFontMetrics fontMetrics = ts . fontMetrics ( ) ;
int height = textLines . size ( ) * fontMetrics . height ( ) ;
if ( textLines . size ( ) > = 1 )
height + = ( textLines . size ( ) - 1 ) * fontMetrics . leading ( ) ;
int width = 0 ;
for ( TQValueVector < TQString > : : const_iterator it = textLines . begin ( ) ;
it ! = textLines . end ( ) ;
it + + )
{
const int w = fontMetrics . width ( * it ) ;
if ( w > width )
width = w ;
}
const int selWidth = TQMAX ( kpSelection : : minimumWidthForTextStyle ( ts ) ,
width + kpSelection : : textBorderSize ( ) * 2 ) ;
const int selHeight = TQMAX ( kpSelection : : minimumHeightForTextStyle ( ts ) ,
height + kpSelection : : textBorderSize ( ) * 2 ) ;
kpSelection sel ( TQRect ( 0 , 0 , selWidth , selHeight ) ,
textLines ,
ts ) ;
if ( newTextSelectionTopLeft ! = KP_INVALID_POINT )
{
sel . moveTo ( newTextSelectionTopLeft ) ;
paste ( sel , true /*force topLeft*/ ) ;
}
else
{
paste ( sel ) ;
}
}
TQApplication : : restoreOverrideCursor ( ) ;
}
// public
void kpMainWindow : : pasteTextAt ( const TQString & text , const TQPoint & point ,
bool allowNewTextSelectionPointShift )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " kpMainWindow::pasteTextAt( " < < text
< < " ,point= " < < point
< < " ,allowNewTextSelectionPointShift= "
< < allowNewTextSelectionPointShift
< < " ) " < < endl ;
# endif
TQApplication : : setOverrideCursor ( TQt : : waitCursor ) ;
if ( toolHasBegunShape ( ) )
tool ( ) - > endShapeInternal ( ) ;
if ( m_document & &
m_document - > selection ( ) & &
m_document - > selection ( ) - > isText ( ) & &
m_document - > selection ( ) - > pointIsInTextArea ( point ) )
{
kpSelection * sel = m_document - > selection ( ) ;
const int row = sel - > textRowForPoint ( point ) ;
const int col = sel - > textColForPoint ( point ) ;
m_viewManager - > setTextCursorPosition ( row , col ) ;
pasteText ( text ) ;
}
else
{
TQPoint pointToUse = point ;
if ( allowNewTextSelectionPointShift )
{
// TODO: In terms of doc pixels, would be inconsistent behaviour
// based on zoomLevel of view.
// pointToUse -= TQPoint (-view->selectionResizeHandleAtomicSize (),
// -view->selectionResizeHandleAtomicSize ());
}
pasteText ( text , true /*force new text selection*/ , pointToUse ) ;
}
TQApplication : : restoreOverrideCursor ( ) ;
}
// public slot
void kpMainWindow : : slotPaste ( )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " kpMainWindow::slotPaste() CALLED " < < endl ;
# endif
// sync: restoreOverrideCursor() in all exit paths
TQApplication : : setOverrideCursor ( TQt : : waitCursor ) ;
if ( toolHasBegunShape ( ) )
tool ( ) - > endShapeInternal ( ) ;
if ( ! : : HasSomethingToPasteWithDialogIfNot ( this ) )
{
TQApplication : : restoreOverrideCursor ( ) ;
return ;
}
//
// Acquire the pixmap
//
TQMimeSource * ms = TQApplication : : clipboard ( ) - > data ( TQClipboard : : Clipboard ) ;
if ( ! ms )
{
kdError ( ) < < " kpMainWindow::slotPaste() without mimeSource " < < endl ;
TQApplication : : restoreOverrideCursor ( ) ;
return ;
}
kpSelection sel ;
TQString text ;
if ( kpSelectionDrag : : decode ( ms , sel /*ref*/ , pasteWarnAboutLossInfo ( ) ) )
{
sel . setTransparency ( selectionTransparency ( ) ) ;
paste ( sel ) ;
}
else if ( TQTextDrag : : decode ( ms , text /*ref*/ ) )
{
pasteText ( text ) ;
}
else
{
TQApplication : : restoreOverrideCursor ( ) ;
kdDebug ( ) < < " kpMainWindow::slotPaste() could not decode selection " < < endl ;
kdDebug ( ) < < " \t Formats supported: " < < endl ;
for ( int i = 0 ; ms - > format ( i ) ; i + + )
{
kdDebug ( ) < < " \t \t " < < i < < " : " < < ms - > format ( i ) < < endl ;
}
// TODO: fix Klipper
KMessageBox : : sorry ( this ,
i18n ( " <qt><p>KolourPaint cannot paste the contents of "
" the clipboard as the data unexpectedly disappeared.</p> "
" <p>This usually occurs if the application which was "
" responsible "
" for the clipboard contents has been closed.</p></qt> " ) ,
i18n ( " Cannot Paste " ) ) ;
// TODO: PROPAGATE: interprocess
if ( TDEMainWindow : : memberList )
{
# if DEBUG_KP_MAIN_WINDOW
kdDebug ( ) < < " \t have memberList " < < endl ;
# endif
for ( TQPtrList < TDEMainWindow > : : const_iterator it = TDEMainWindow : : memberList - > begin ( ) ;
it ! = TDEMainWindow : : memberList - > end ( ) ;
it + + )
{
kpMainWindow * mw = dynamic_cast < kpMainWindow * > ( * it ) ;
if ( ! mw )
{
kdError ( ) < < " kpMainWindow::slotPaste() given fake kpMainWindow: " < < ( * it ) < < endl ;
continue ;
}
# if DEBUG_KP_MAIN_WINDOW
kdDebug ( ) < < " \t \t mw= " < < mw < < endl ;
# endif
mw - > slotEnablePaste ( ) ;
}
}
return ;
}
TQApplication : : restoreOverrideCursor ( ) ;
}
// private slot
void kpMainWindow : : slotPasteInNewWindow ( )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " kpMainWindow::slotPasteInNewWindow() CALLED " < < endl ;
# endif
// sync: restoreOverrideCursor() in all exit paths
TQApplication : : setOverrideCursor ( TQt : : waitCursor ) ;
if ( toolHasBegunShape ( ) )
tool ( ) - > endShapeInternal ( ) ;
if ( ! : : HasSomethingToPasteWithDialogIfNot ( this ) )
{
TQApplication : : restoreOverrideCursor ( ) ;
return ;
}
//
// Pasting must ensure that:
//
// Requirement 1. the document is the same size as the image to be pasted.
// Requirement 2. transparent pixels in the image must remain as transparent.
//
kpMainWindow * win = new kpMainWindow ( 0 /*no document*/ ) ;
win - > show ( ) ;
// Make "Edit / Paste in New Window" always paste white pixels as white.
// Don't let selection transparency get in the way and paste them as
// transparent.
kpSelectionTransparency transparency = win - > selectionTransparency ( ) ;
if ( transparency . isTransparent ( ) )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " \t changing selection transparency to opaque " < < endl ;
# endif
transparency . setOpaque ( ) ;
// Since we are setting selection transparency programmatically
// -- as opposed to in response to user input -- this will not
// affect the selection transparency tool option widget's "last used"
// config setting.
win - > setSelectionTransparency ( transparency ) ;
}
// (this handles Requirement 1. above)
win - > slotPaste ( ) ;
// (this handles Requirement 2. above;
// slotDeselect() is not enough unless the document is filled with the
// transparent color in advance)
win - > slotCrop ( ) ;
TQApplication : : restoreOverrideCursor ( ) ;
}
// public slot
void kpMainWindow : : slotDelete ( )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " kpMainWindow::slotDelete() CALLED " < < endl ;
# endif
if ( ! m_actionDelete - > isEnabled ( ) )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " \t action not enabled - was probably called from kpTool::keyPressEvent() " < < endl ;
# endif
return ;
}
if ( ! m_document | | ! m_document - > selection ( ) )
{
kdError ( ) < < " kpMainWindow::slotDelete () doc= " < < m_document
< < " sel= " < < ( m_document ? m_document - > selection ( ) : 0 )
< < endl ;
return ;
}
if ( toolHasBegunShape ( ) )
tool ( ) - > endShapeInternal ( ) ;
addImageOrSelectionCommand ( new kpToolSelectionDestroyCommand (
m_document - > selection ( ) - > isText ( ) ?
i18n ( " Text: Delete Box " ) : // not to be confused with i18n ("Text: Delete")
i18n ( " Selection: Delete " ) ,
false /*no push onto doc*/ ,
this ) ) ;
}
// private slot
void kpMainWindow : : slotSelectAll ( )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " kpMainWindow::slotSelectAll() CALLED " < < endl ;
# endif
if ( ! m_document )
{
kdError ( ) < < " kpMainWindow::slotSelectAll() without doc " < < endl ;
return ;
}
if ( toolHasBegunShape ( ) )
tool ( ) - > endShapeInternal ( ) ;
if ( m_document - > selection ( ) )
slotDeselect ( ) ;
// just the border - don't actually pull pixmap from doc yet
m_document - > setSelection ( kpSelection ( kpSelection : : Rectangle , m_document - > rect ( ) , selectionTransparency ( ) ) ) ;
if ( tool ( ) )
tool ( ) - > somethingBelowTheCursorChanged ( ) ;
}
// private
void kpMainWindow : : addDeselectFirstCommand ( kpCommand * cmd )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " kpMainWindow::addDeselectFirstCommand( "
< < cmd
< < " ) "
< < endl ;
# endif
kpSelection * sel = m_document - > selection ( ) ;
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " \t sel= " < < sel < < endl ;
# endif
if ( sel )
{
// if you just dragged out something with no action then
// forget the drag
if ( ! sel - > pixmap ( ) )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " \t just a fresh border - was nop - delete " < < endl ;
# endif
m_document - > selectionDelete ( ) ;
if ( tool ( ) )
tool ( ) - > somethingBelowTheCursorChanged ( ) ;
if ( cmd )
m_commandHistory - > addCommand ( cmd ) ;
}
else
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " \t real selection with pixmap - push onto doc cmd " < < endl ;
# endif
kpCommand * deselectCommand = new kpToolSelectionDestroyCommand (
sel - > isText ( ) ?
i18n ( " Text: Finish " ) :
i18n ( " Selection: Deselect " ) ,
true /*push onto document*/ ,
this ) ;
if ( cmd )
{
kpMacroCommand * macroCmd = new kpMacroCommand ( cmd - > name ( ) , this ) ;
macroCmd - > addCommand ( deselectCommand ) ;
macroCmd - > addCommand ( cmd ) ;
m_commandHistory - > addCommand ( macroCmd ) ;
}
else
m_commandHistory - > addCommand ( deselectCommand ) ;
}
}
else
{
if ( cmd )
m_commandHistory - > addCommand ( cmd ) ;
}
}
// public slot
void kpMainWindow : : slotDeselect ( )
{
# if DEBUG_KP_MAIN_WINDOW && 1
kdDebug ( ) < < " kpMainWindow::slotDeselect() CALLED " < < endl ;
# endif
if ( ! m_document | | ! m_document - > selection ( ) )
{
kdError ( ) < < " kpMainWindow::slotDeselect() doc= " < < m_document
< < " sel= " < < ( m_document ? m_document - > selection ( ) : 0 )
< < endl ;
return ;
}
if ( toolHasBegunShape ( ) )
tool ( ) - > endShapeInternal ( ) ;
addDeselectFirstCommand ( 0 ) ;
}
// private slot
void kpMainWindow : : slotCopyToFile ( )
{
# if DEBUG_KP_MAIN_WINDOW
kdDebug ( ) < < " kpMainWindow::slotCopyToFile() " < < endl ;
# endif
if ( toolHasBegunShape ( ) )
tool ( ) - > endShapeInternal ( ) ;
if ( ! m_document - > selection ( ) )
return ;
kpSelection sel = * m_document - > selection ( ) ;
TQPixmap pixmapToSave ;
if ( ! sel . pixmap ( ) )
{
// Not a floating selection - user has just selected a region;
// haven't pulled it off yet so probably don't expect and can't
// visualise selection transparency so give opaque, not transparent
// pixmap.
pixmapToSave = m_document - > getSelectedPixmap ( ) ;
}
else
pixmapToSave = sel . transparentPixmap ( ) ;
kpDocumentSaveOptions chosenSaveOptions ;
bool allowOverwritePrompt , allowLossyPrompt ;
KURL chosenURL = askForSaveURL ( i18n ( " Copy to File " ) ,
m_lastCopyToURL . url ( ) ,
pixmapToSave ,
m_lastCopyToSaveOptions ,
kpDocumentMetaInfo ( ) ,
kpSettingsGroupEditCopyTo ,
false /*allow remote files*/ ,
& chosenSaveOptions ,
m_copyToFirstTime ,
& allowOverwritePrompt ,
& allowLossyPrompt ) ;
if ( chosenURL . isEmpty ( ) )
return ;
if ( ! kpDocument : : savePixmapToFile ( pixmapToSave ,
chosenURL ,
chosenSaveOptions , kpDocumentMetaInfo ( ) ,
allowOverwritePrompt ,
allowLossyPrompt ,
this ) )
{
return ;
}
addRecentURL ( chosenURL ) ;
m_lastCopyToURL = chosenURL ;
m_lastCopyToSaveOptions = chosenSaveOptions ;
m_copyToFirstTime = false ;
}
// private slot
void kpMainWindow : : slotPasteFromFile ( )
{
# if DEBUG_KP_MAIN_WINDOW
kdDebug ( ) < < " kpMainWindow::slotPasteFromFile() " < < endl ;
# endif
if ( toolHasBegunShape ( ) )
tool ( ) - > endShapeInternal ( ) ;
KURL : : List urls = askForOpenURLs ( i18n ( " Paste From File " ) ,
m_lastPasteFromURL . url ( ) ,
false /*only 1 URL*/ ) ;
if ( urls . count ( ) ! = 1 )
return ;
KURL url = urls . first ( ) ;
m_lastPasteFromURL = url ;
TQPixmap pixmap = kpDocument : : getPixmapFromFile ( url ,
false /*show error message if doesn't exist*/ ,
this ) ;
if ( pixmap . isNull ( ) )
return ;
addRecentURL ( url ) ;
paste ( kpSelection ( kpSelection : : Rectangle ,
TQRect ( 0 , 0 , pixmap . width ( ) , pixmap . height ( ) ) ,
pixmap ,
selectionTransparency ( ) ) ) ;
}