You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegraphics/kpovmodeler/pmdeletecommand.cpp

282 lines
8.5 KiB

/*
**************************************************************************
description
--------------------
copyright : (C) 2000-2001 by Andreas Zehender
email : zehender@kde.org
**************************************************************************
**************************************************************************
* *
* 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. *
* *
**************************************************************************/
#include "pmdeletecommand.h"
#include "pmcommandmanager.h"
#include "pmdeclare.h"
#include "pmrecursiveobjectiterator.h"
#include "pmmemento.h"
#include <klocale.h>
#include <kmessagebox.h>
#include <tqptrdict.h>
PMDeleteCommand::PMDeleteCommand( PMObject* obj )
: PMCommand( i18n( "Delete %1" ).tqarg( obj->name( ) ) )
{
// the scene can not be deleted!
if( obj->parent( ) )
m_infoList.append( new PMDeleteInfo( obj ) );
else
{
// object has no parent!
// top level objects can't be moved, move all child items
PMObject* tmp;
for( tmp = obj->firstChild( ); tmp; tmp = tmp->nextSibling( ) )
m_infoList.append( new PMDeleteInfo( tmp ) );
}
m_executed = false;
m_firstExecution = true;
m_linksCreated = false;
}
PMDeleteCommand::PMDeleteCommand( const PMObjectList& list )
: PMCommand( i18n( "Delete Objects" ) )
{
PMObjectListIterator it( list );
PMObject* obj;
for( ; it.current( ); ++it )
{
obj = it.current( );
if( obj->parent( ) )
m_infoList.append( new PMDeleteInfo( obj ) );
else
{
// object has no parent!
// top level objects can't be moved, move all child items
PMObject* tmp;
for( tmp = obj->firstChild( ); tmp; tmp = tmp->nextSibling( ) )
m_infoList.append( new PMDeleteInfo( tmp ) );
}
}
m_infoList.setAutoDelete( true );
m_executed = false;
m_firstExecution = true;
m_linksCreated = false;
}
PMDeleteCommand::~PMDeleteCommand( )
{
if( m_executed )
{
PMDeleteInfoListIterator it( m_infoList );
for( ; it.current( ); ++it )
delete ( it.current( )->deletedObject( ) );
}
m_infoList.clear( );
}
void PMDeleteCommand::execute( PMCommandManager* theManager )
{
if( !m_executed )
{
PMDeleteInfoListIterator it( m_infoList );
PMDeleteInfo* info = 0;
PMObject* parent;
if( !m_linksCreated )
{
PMDeclare* decl;
for( ; it.current( ); ++it )
{
PMRecursiveObjectIterator oit( it.current( )->deletedObject( ) );
for( ; oit.current( ); ++oit )
{
decl = oit.current( )->linkedObject( );
if( decl )
{
m_links.append( oit.current( ) );
if( !m_linkedDeclares.containsRef( decl ) )
m_linkedDeclares.append( decl );
}
}
}
m_linksCreated = true;
}
PMObjectListIterator lit( m_links );
for( ; lit.current( ); ++lit )
lit.current( )->linkedObject( )->removeLinkedObject( lit.current( ) );
for( it.toLast( ); it.current( ); --it )
{
info = it.current( );
parent = info->parent( );
// signal has to be emitted before the item is removed
theManager->cmdObjectChanged( info->deletedObject( ), PMCRemove );
if( m_firstExecution )
if( parent->dataChangeOnInsertRemove( )
&& !parent->mementoCreated( ) )
parent->createMemento( );
parent->takeChild( info->deletedObject( ) );
}
if( m_firstExecution )
{
for( it.toLast( ); it.current( ); --it )
{
parent = it.current( )->parent( );
if( parent->mementoCreated( ) )
m_dataChanges.append( parent->takeMemento( ) );
}
}
TQPtrListIterator<PMMemento> mit( m_dataChanges );
for( ; mit.current( ); ++mit )
{
PMObjectChangeListIterator change = mit.current( )->changedObjects( );
for( ; change.current( ); ++change )
theManager->cmdObjectChanged( change.current( )->object( ),
change.current( )->mode( ) );
}
PMObjectListIterator dit( m_linkedDeclares );
for( ; dit.current( ); ++dit )
theManager->cmdObjectChanged( dit.current( ), PMCData );
m_executed = true;
m_firstExecution = false;
}
}
void PMDeleteCommand::undo( PMCommandManager* theManager )
{
if( m_executed )
{
PMDeleteInfoListIterator it( m_infoList );
for( ; it.current( ); ++it )
{
if( it.current( )->prevSibling( ) )
it.current( )->parent( )
->insertChildAfter( it.current( )->deletedObject( ),
it.current( )->prevSibling( ) );
else
it.current( )->parent( )
->insertChild( it.current( )->deletedObject( ), 0 );
theManager->cmdObjectChanged( it.current( )->deletedObject( ), PMCAdd );
}
PMObjectListIterator lit( m_links );
for( ; lit.current( ); ++lit )
lit.current( )->linkedObject( )->addLinkedObject( lit.current( ) );
PMObjectListIterator dit( m_linkedDeclares );
for( ; dit.current( ); ++dit )
theManager->cmdObjectChanged( dit.current( ), PMCData );
TQPtrListIterator<PMMemento> mit( m_dataChanges );
for( ; mit.current( ); ++mit )
{
mit.current( )->originator( )->restoreMemento( mit.current( ) );
PMObjectChangeListIterator change = mit.current( )->changedObjects( );
for( ; change.current( ); ++change )
theManager->cmdObjectChanged( change.current( )->object( ),
change.current( )->mode( ) );
}
m_executed = false;
}
}
int PMDeleteCommand::errorFlags( PMPart* )
{
PMDeleteInfo* info;
PMDeclare* decl = 0;
PMObject* obj;
bool insideSelection;
bool ok = true;
bool error = false;
// dictionary of deleted objects
TQPtrDict<bool> m_deletedObjects( 1009 );
m_deletedObjects.setAutoDelete( true );
PMDeleteInfoListIterator it( m_infoList );
for( ; it.current( ); ++it )
m_deletedObjects.insert( it.current( )->deletedObject( ),
new bool( true ) );
// declares can only be deleted, if all linked
// objects are deleted as well
info = m_infoList.last( );
while( info )
{
ok = true;
if( info->deletedObject( )->isA( "Declare" ) )
{
decl = ( PMDeclare* ) ( info->deletedObject( ) );
PMObjectListIterator links = decl->linkedObjects( );
for( ; links.current( ) && ok; ++links )
{
insideSelection = false;
for( obj = links.current( ); obj && !insideSelection;
obj = obj->parent( ) )
{
if( m_deletedObjects.find( obj ) )
insideSelection = true;
}
if( insideSelection )
{
bool stop = false;
for( obj = links.current( ); obj && !stop; obj = obj->parent( ) )
{
if( m_deletedObjects.find( obj ) )
stop = true;
else
m_deletedObjects.insert( obj, new bool( true ) );
}
}
else
ok = false;
}
}
if( !ok )
{
m_errors.prepend( i18n( "The declare \"%1\" can't be removed "
"because of some remaining links." )
.tqarg( decl->id( ) ) );
PMDeleteInfo* tmp = info;
info = m_infoList.prev( );
m_deletedObjects.remove( decl );
m_infoList.removeRef( tmp );
error = true;
}
else
info = m_infoList.prev( );
}
if( error )
{
if( m_infoList.count( ) == 0 )
return PMEError | PMEFatal;
else
return PMEError;
}
return PMENone;
}