/***************************************************************************
 *   Copyright (C) 2005 by SUZUKI Tasuku                                   *
 *   tasuku@linux-life.net                                                 *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "kkddoc.h"
#include "kkdpaper.h"
#include "kkdcmds.h"
#include "kkdtextitem.h"
#include "kkdaddressee.h"
#include "kkdaddress.h"
#include "kkdzipcode.h"

#include <qfile.h>

#include <kdebug.h>
#include <klocale.h>
#include <kmainwindow.h>
#include <kmessagebox.h>

using namespace KKDesigner;

KKDDoc::KKDDoc( QWidget* parent, const char* name )
	: QObject( parent, name )
	, m_currentIndex( -1 )
	, m_cmdHistory( NULL )
	, m_cmd( NULL )
{
}

KKDDoc::KKDDoc( KCommandHistory* cmdHistory, QWidget* parent, const char* name )
	: QObject( parent, name )
	, m_currentIndex( -1 )
	, m_cmdHistory( cmdHistory )
	, m_cmd( NULL )
{
	m_clipboard.setAutoDelete( true );
}

KKDDoc::~ KKDDoc()
{
}

bool KKDDoc::open( const QString& filename )
{
	QFile file( filename );
	if( !file.open( IO_ReadOnly ) )
	{
		KMessageBox::error( (QWidget*)parent(), i18n( "File open error\n%1" ).arg( filename ) );
		return false;
	}

	QDomDocument doc( "kreetingkard" );
	if( !doc.setContent( &file ) )
	{
		KMessageBox::error( (QWidget*)parent(), i18n( "File is not kreetingkard format" ) );
		file.close();
		return false;
	}
	file.close();

	clear();

	for( QDomNode n = doc.documentElement().lastChild(); !n.isNull(); n = n.previousSibling() )
	{
		KKDPaper* paper = new KKDPaper( n.toElement(), this );
		append( paper );
		if( paper->selected() )
		{
			m_selectedItems.append( paper );
		}
		else
		{
			for( KKDItemBase* item = paper->first(); item; item = paper->next() )
			{
				if( item->selected() ) m_selectedItems.append( item );
			}
		}
	}
	emit documentChanged();
	return true;
}

bool KKDDoc::save( const QString& filename )
{
	QFile file( filename );
	if( !file.open( IO_WriteOnly ) )
	{
		KMessageBox::error( (QWidget*)parent(), i18n( "File open error" ) );
		return false;
	}

	QDomDocument doc;
	doc.appendChild( doc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
	QDomElement elem = doc.createElement( "kreetingkard" );
	elem.setAttribute( "version", "0.2.0" );
	for( KKDPaper* paper = last(); paper; paper = prev() )
	{
		elem.appendChild( paper->toElement( doc ) );
	}
	doc.appendChild( elem );

	QTextStream str( &file );
	str << doc;
	file.close();
	return true;
}

void KKDDoc::close()
{
	clear();
	emit documentChanged();
}

void KKDDoc::print( QPainter& p, KKAddressBook::KKAContactData* d )
{
	KKDPaper* paper = current();
	paper->drawItem( p, KKDItemBase::PrintMode, d );
	for( KKDItemBase* item = paper->last(); item; item = paper->prev() )
	{
		item->drawItem( p, KKDItemBase::PrintMode, d );
	}
}

void KKDDoc::insertByCommand( KKDPaper* paper, KKDItemBase* item )
{
	emit inserted( item, paper );
}

void KKDDoc::removeByCommand( KKDPaper* paper, KKDItemBase* item )
{
	emit removed( item, paper );
}

void KKDDoc::setCurrentIndex( int i )
{
	if( m_currentIndex == i ) return;
	m_currentIndex = i;
	emit currentIndexChanged();
}

void KKDDoc::setCurrent( KKDPaper* p )
{
	for( uint i = 0; i != count(); i++ )
	{
		if( p == at( i ) )
		{
			setCurrentIndex( i );
		}
		else
		{
			//TODO
// 			at( i )->clearSelection();
		}
	}
	emit currentChanged( p );
}

void KKDDoc::terminate()
{
	if( m_cmd != NULL )
	{
		m_cmd->end();
		if( m_cmd->valid() )
		{
			kdDebug() << m_cmd->name() << endl;
		}
		delete m_cmd;
		m_cmd = NULL;
	}
}

void KKDDoc::clearSelection()
{
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		item->setSelected( false );
	}
	m_selectedItems.clear();
}

void KKDDoc::selectAll()
{
	KKDPaper* paper = at( currentIndex() );
	setSelected( paper, false, true, false );
	QPtrList<KKDItemBase> list( *paper );
	for( KKDItemBase* item = list.first(); item; item = list.next() )
	{
		setSelected( item, true, false, false );
	}
	emit selectedChanged();
}

void KKDDoc::deselect()
{
	setSelected( current(), true, true, true );
}

/**
 * @english
 * Select item(s) included @p rect.
 *
 * @param rect target rectangle
 * @param clearAll Clear all selection before select/deselect.
 * @endenglish
 */
void KKDDoc::selectRect( const QRect& rect, bool clearAll )
{
	if( clearAll )
	{
		clearSelection();
	}
	QPtrList<KKDItemBase> list( *current() );
	for( KKDItemBase* item = list.first(); item; item = list.next() )
	{
		if( rect.width() == 0 && rect.height() == 0 )
		{
			if( item->rect().contains( rect.x(), rect.y() ) )
			{
				setSelected( item, true, false, false );
			}
		}
		else
		{
			if( rect.intersects( item->rect() ) )
			{
				setSelected( item, true, false, false );
			}
		}
	}
	if( m_selectedItems.count() == 0 )
	{
		if( !current()->selected() )
		{
			setSelected( current(), true, false, false );
		}
	}
	emit selectedChanged();
}

//BEGIN Actions
//BEGIN Selected
/**
 * @english
 * Select/Deselect item<br>
 * it is called by click(mouseRelease) event or insert/remove action.
 *
 * @param item Item to select.
 * @param selected value
 * @param clearAll Clear all selection before select/deselect.
 * @param emitSignal this is internal parametor for selectRect.
 * @endenglish
 */
void KKDDoc::setSelected( KKDItemBase* item, bool selected, bool clearAll, bool emitSignal )
{
	if( clearAll )
	{
		clearSelection();
	}

	item->setSelected( selected );
	if( selected )
	{
		m_selectedItems.append( item );
	}
	else
	{
		m_selectedItems.remove( item );
	}
	if( emitSignal )
	{
		emit selectedChanged();
	}
}

/**
 * @english
 * Select/Deselect items<br>
 * it is called by actions.
 *
 * @param items Items to select/deselect.
 * @param selected value
 * @param clearAll Clear all selection before select/deselect.
 * @endenglish
 */
void KKDDoc::setSelected( QPtrList<KKDItemBase> items, bool selected, bool clearAll )
{
	if( clearAll )
	{
		clearSelection();
	}
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		setSelected( item, selected, false, false );
	}
	emit selectedChanged();
}
//END   Selected

//BEGIN Location
void KKDDoc::setLocation( int x, int y )
{
	terminate();
	m_cmd = new KKDCmdLocation( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		item->setLocation( x, y );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit locationChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}

void KKDDoc::moveStart()
{
	terminate();
	m_cmd = new KKDCmdLocation( this );
	m_cmd->begin();
}

void KKDDoc::moving()
{
	emit locationChanged();
}

void KKDDoc::moveEnd()
{
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit locationChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END   Location

//BEGIN Size
void KKDDoc::setSize( int width, int height )
{
	terminate();
	m_cmd = new KKDCmdSize( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		item->setSize( width == -1 ? item->size().width() : width, height == -1 ? item->size().height() : height );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit sizeChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}

void KKDDoc::resizeStart()
{
	terminate();
	m_cmd = new KKDCmdSize( this );
	m_cmd->begin();
}

void KKDDoc::resizing()
{
	emit sizeChanged();
}

void KKDDoc::resizeEnd()
{
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit sizeChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END   Size

//BEGIN Text
/**
 * \property KKDDoc::text
 *
 * @english
 * \brief text of selected item(s)
 *
 * It is called as default value for change.
 * @retval text when all text is same
 * @retval QString::null else.
 * @endenglish
 *
 * @japanese
 * \brief 選択されたアイテムのテキスト
 *
 * テキスト変更時のデフォルト値として使われます。
 * @retval テキスト 全てのテキストが同じ時
 * @retval QString::null そうじゃない時
 * @endjapanese
 */
QString KKDDoc::text() const
{
	QString t = QString::null;
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( !item->inherits( "KKDesigner::KKDTextItem" ) ) continue;
		if( t.isNull() )
		{
			t = ((KKDTextItem*)item)->text();
		}
		else if( t != ((KKDTextItem*)item)->text() )
		{
			return QString::null;
		}
	}
	return t;
}

void KKDDoc::setText( const QString& t )
{
	terminate();
	m_cmd = new KKDCmdText( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		((KKDTextItem*)item)->setText( t );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit textChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END   Text

//BEGIN Orientation
/**
 * @english
 * @retval Horizontal All selected items is horizontal
 * @retval Vertical All selected items is vertical
 * @retval -1 both horizontal and vertical
 * @retval -2 no item is selected
 * @endenglish
 */
Qt::Orientation KKDDoc::orientation() const
{
	int o = -2;
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( item->inherits( "KKDesigner::KKDAddressee" ) || item->inherits( "KKDesigner::KKDAddress" ))
		{
			if( o == -2 )
			{
				o = (int)((KKDTextBase*)item)->orientation();
			}
			else if( o != (int)((KKDTextBase*)item)->orientation() )
			{
				o = -1;
				break;
			}
		}
	}
	return (Orientation)o;
}

void KKDDoc::setOrientation( Orientation o )
{
	terminate();
	m_cmd = new KKDCmdOrientation( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		((KKDTextBase*)item)->setOrientation( o );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit orientationChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END   Orientation

//BEGIN Align
Qt::AlignmentFlags KKDDoc::align() const
{
	int i = -2;
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( item->inherits( "KKDesigner::KKDTextItem" ) )
		{
			if( i == -2 )
			{
				i = (int)((KKDTextItem*)item)->align();
			}
			else if( i != (int)((KKDTextItem*)item)->align() )
			{
				i = -1;
				break;
			}
		}
	}
	return (AlignmentFlags)i;
}

void KKDDoc::setAlign( AlignmentFlags a )
{
	terminate();
	m_cmd = new KKDCmdAlign( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		((KKDTextItem*)item)->setAlign( a );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit alignChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END   Align

//BEGIN Color
QColor KKDDoc::color() const
{
	QColor c;
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( item->inherits( "KKDesigner::KKDTextBase" ) )
		{
			if( c == QColor() )
			{
				c = ((KKDTextBase*)item)->color();
			}
			else if( c != ((KKDTextBase*)item)->color() )
			{
				c = QColor();
				break;
			}
		}
	}
	return c;
}

void KKDDoc::setColor( const QColor& c )
{
	terminate();
	m_cmd = new KKDCmdColor( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		((KKDTextBase*)item)->setColor( c );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit colorChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END   Color

//BEGIN FontFamily
/**
 * @english
 * @return fontFamily of selected items
 * @endenglish
 */
QString KKDDoc::fontFamily() const
{
	QString f = QString::null;
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( item->inherits( "KKDesigner::KKDTextBase" ) )
		{
			if( f.isNull() )
			{
				f = ((KKDTextBase*)item)->fontFamily();
			}
			else if( f != ((KKDTextBase*)item)->fontFamily() )
			{
				f = QString::null;
				break;
			}
		}
	}
	return f;
}

void KKDDoc::setFontFamily( const QString& f )
{
	terminate();
	m_cmd = new KKDCmdFontFamily( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		((KKDTextBase*)item)->setFontFamily( f );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit fontFamilyChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END   FontFamily

//BEGIN FontSize
int KKDDoc::fontSize() const
{
	int i = 0;
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( item->inherits( "KKDesigner::KKDTextBase" ) )
		{
			if( i == 0 )
			{
				i = ((KKDTextBase*)item)->fontSize();
			}
			else if( i != ((KKDTextBase*)item)->fontSize() )
			{
				i = 0;
				break;
			}
		}
	}
	return i;
}

void KKDDoc::setFontSize( int s )
{
	terminate();
	m_cmd = new KKDCmdFontSize( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		((KKDTextBase*)item)->setFontSize( s );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit fontSizeChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END   FontSize

//BEGIN FontBold
bool KKDDoc::fontBold() const
{
	bool b = false;
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( item->inherits( "KKDesigner::KKDTextBase" ) )
		{
			if( !((KKDTextBase*)item)->fontBold() ) return false;
			b = true;
		}
	}
	return b;
}

void KKDDoc::setFontBold( bool b )
{
	terminate();
	m_cmd = new KKDCmdFontBold( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		((KKDTextBase*)item)->setFontBold( b );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit fontBoldChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END   FontBold

//BEGIN FontItalic
bool KKDDoc::fontItalic() const
{
	bool i = false;
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( item->inherits( "KKDesigner::KKDTextBase" ) )
		{
			if( !((KKDTextBase*)item)->fontItalic() ) return false;
			i = true;
		}
	}
	return i;
}

void KKDDoc::setFontItalic( bool i )
{
	terminate();
	m_cmd = new KKDCmdFontItalic( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		((KKDTextBase*)item)->setFontItalic( i );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit fontItalicChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END   FontItalic

//BEGIN FontUnderline
bool KKDDoc::fontUnderline() const
{
	bool u = false;
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( item->inherits( "KKDesigner::KKDTextBase" ) )
		{
			if( !((KKDTextBase*)item)->fontUnderline() ) return false;
			u = true;
		}
	}
	return u;
}

void KKDDoc::setFontUnderline( bool u )
{
	terminate();
	m_cmd = new KKDCmdFontUnderline( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		((KKDTextBase*)item)->setFontUnderline( u );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit fontUnderlineChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END   FontUnderline

//BEGIN FontStrikeOut
bool KKDDoc::fontStrikeOut() const
{
	bool s = false;
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( item->inherits( "KKDesigner::KKDTextBase" ) )
		{
			if( !((KKDTextBase*)item)->fontStrikeOut() ) return false;
			s = true;
		}
	}
	return s;
}

void KKDDoc::setFontStrikeOut( bool s )
{
	terminate();
	m_cmd = new KKDCmdFontStrikeOut( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		((KKDTextBase*)item)->setFontStrikeOut( s );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit fontStrikeOutChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END   FontStrikeOut

//BEGIN Image
void KKDDoc::setImage( const QImage &i )
{
	terminate();
	m_cmd = new KKDCmdImage( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		((KKDImageItem*)item)->setImage( i );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit imageChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}

void KKDDoc::setImage( const QString& p )
{
	QImage img( p );
	setImage( img );
}

void KKDDoc::eraseImage()
{
	QImage img;
	setImage( img );
}
//END   Image

//BEGIN ImagePrint
bool KKDDoc::imagePrint()
{
	if( !current() ) return false;
	return current()->imagePrint();
}

void KKDDoc::setImagePrint( bool p )
{
	terminate();
	m_cmd = new KKDCmdImagePrint( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		((KKDPaper*)item)->setImagePrint( p );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit imagePrintChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END    ImagePrint

//BEGIN Locked
/**
 * @english
 * @return Whether the locked property of all selected items is true.<br>
 * @endenglish
 */
bool KKDDoc::locked() const
{
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( !item->locked() ) return false;
	}
	return ( m_selectedItems.count() != 0 );
}

void KKDDoc::setLocked( bool l )
{
	terminate();
	m_cmd = new KKDCmdLocked( this );
	m_cmd->begin();
	for( KKDItemBase* item = m_cmd->items().first(); item; item = m_cmd->items().next() )
	{
		item->setLocked( l );
	}
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit lockedChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}
//END   Locked

bool KKDDoc::imagePrintEnabled()
{
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( item->type() == KKDItemBase::Paper ) return true;
	}
	return false;
}

bool KKDDoc::imageEraseEnabled()
{
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( item->type() == KKDItemBase::Paper || item->type() == KKDItemBase::ImageItem ) return true;
	}
	return false;
}

void KKDDoc::insert()
{
	terminate();
	m_cmd = new KKDCmdInsert( this );
	m_cmd->begin();
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, false );
		emit inserted();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}

void KKDDoc::remove()
{
	terminate();
	m_cmd = new KKDCmdRemove( this );
	m_cmd->begin();
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, true );
		emit removed();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}

void KKDDoc::cut()
{
	copy();
	remove();
}

void KKDDoc::copy()
{
	m_clipboard.clear();
	KKDPaper* paper = at( currentIndex() );
	for( KKDItemBase* item = paper->first(); item; item = paper->next() )
	{
		if( !item->selected() ) continue;
		KKDItemBase* i = NULL;
		switch( item->type() )
		{
			case KKDItemBase::TextItem:
				i = new KKDTextItem( (KKDTextItem*)item );
				break;
			case KKDItemBase::ImageItem:
				i = new KKDImageItem( (KKDImageItem*)item );
				break;
			case KKDItemBase::Addressee:
				i = new KKDAddressee( (KKDAddressee*)item );
				break;
			case KKDItemBase::Address:
				i = new KKDAddress( (KKDAddress*)item );
				break;
			case KKDItemBase::Zipcode:
				i = new KKDZipcode( (KKDZipcode*)item );
				break;
		}
		if( i ) m_clipboard.append( i );
	}
	emit pasteEnabledChanged();
}

void KKDDoc::paste()
{
	clearSelection();
	KKDPaper* paper = at( currentIndex() );
	for( KKDItemBase* item = m_clipboard.first(); item; item = m_clipboard.next() )
	{
		KKDItemBase* i = NULL;
		switch( item->type() )
		{
			case KKDItemBase::TextItem:
				i = new KKDTextItem( (KKDTextItem*)item, paper );
				break;
			case KKDItemBase::ImageItem:
				i = new KKDImageItem( (KKDImageItem*)item, paper );
				break;
			case KKDItemBase::Addressee:
				i = new KKDAddressee( (KKDAddressee*)item, paper );
				break;
			case KKDItemBase::Address:
				i = new KKDAddress( (KKDAddress*)item, paper );
				break;
			case KKDItemBase::Zipcode:
				i = new KKDZipcode( (KKDZipcode*)item, paper );
				break;
		}
		if( !i ) continue;
		paper->append( i );
		i->setSelected( true );
		m_selectedItems.append( i );
		insertByCommand( paper, i );
	}
	insert();
	emit selectedChanged();
}

void KKDDoc::raise()
{
	terminate();
	m_cmd = new KKDCmdRaise( this );
	m_cmd->begin();
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, true );
		emit positionChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}

void KKDDoc::lower()
{
	terminate();
	m_cmd = new KKDCmdLower( this );
	m_cmd->begin();
	m_cmd->end();
	if( m_cmd->valid() )
	{
		m_cmdHistory->addCommand( m_cmd, true );
		emit positionChanged();
	}
	else
	{
		delete m_cmd;
	}
	m_cmd = NULL;
}


//END Actions

bool KKDDoc::cutable() const
{
	bool locked = false;
	QPtrList<KKDItemBase> items( m_selectedItems );
	for( KKDItemBase* item = items.first(); item; item = items.next() )
	{
		if( item->type() == KKDItemBase::Paper ) return false;
		if( item->locked() ) locked = true;
	}
	return !locked;
}

