lib

KoTextCommand.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 David Faure <faure@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "KoTextCommand.h"
00021 #include "KoTextObject.h"
00022 #include "KoTextParag.h"
00023 #include "KoVariable.h"
00024 #include <kdebug.h>
00025 #include <klocale.h>
00026 
00027 // This is automatically called by KCommandHistory's redo action when redo is activated
00028 void KoTextCommand::execute()
00029 {
00030     m_textobj->redo();
00031 }
00032 
00033 // This is automatically called by KCommandHistory's undo action when undo is activated
00034 void KoTextCommand::unexecute()
00035 {
00036     m_textobj->undo();
00037 }
00038 
00039 KoTextDeleteCommand::KoTextDeleteCommand(
00040     KoTextDocument *d, int i, int idx, const QMemArray<KoTextStringChar> &str,
00041     const CustomItemsMap & customItemsMap,
00042     const QValueList<KoParagLayout> &oldParagLayouts )
00043     : KoTextDocDeleteCommand( d, i, idx, str ),
00044       m_oldParagLayouts( oldParagLayouts ),
00045       m_customItemsMap( customItemsMap )
00046 {
00047     Q_ASSERT( id >= 0 );
00048 }
00049 
00050 KoTextCursor * KoTextDeleteCommand::execute( KoTextCursor *c )
00051 {
00052     KoTextParag *s = doc ? doc->paragAt( id ) : parag;
00053     if ( !s ) {
00054         kdWarning() << "can't locate parag at " << id << ", last parag: " << doc->lastParag()->paragId() << endl;
00055         return 0;
00056     }
00057     cursor.setParag( s );
00058     cursor.setIndex( index );
00059     int len = text.size();
00060     // Detach from custom items. They are already in the map, and we don't
00061     // want them to be deleted
00062     for ( int i = 0; i < len; ++i )
00063     {
00064         KoTextStringChar * ch = cursor.parag()->at( cursor.index() );
00065         if ( ch->isCustom() )
00066         {
00067             ch->customItem()->setDeleted( true );
00068             cursor.parag()->removeCustomItem(cursor.index());
00069         }
00070         cursor.gotoRight();
00071     }
00072 
00073     return KoTextDocDeleteCommand::execute(c);
00074 }
00075 
00076 KoTextCursor * KoTextDeleteCommand::unexecute( KoTextCursor *c )
00077 {
00078     // Let QRichText re-create the text and formatting
00079     KoTextCursor * cr = KoTextDocDeleteCommand::unexecute(c);
00080 
00081     KoTextParag *s = doc ? doc->paragAt( id ) : parag;
00082     if ( !s ) {
00083         kdWarning() << "can't locate parag at " << id << ", last parag: " << (doc ? doc->lastParag()->paragId() : -1) << endl;
00084         return 0;
00085     }
00086     cursor.setParag( s );
00087     cursor.setIndex( index );
00088     // Set any custom item that we had
00089     m_customItemsMap.insertItems( cursor, text.size() );
00090 
00091     // Now restore the parag layouts (i.e. libkotext specific stuff)
00092     QValueList<KoParagLayout>::Iterator lit = m_oldParagLayouts.begin();
00093     kdDebug(32500) << "KoTextDeleteCommand::unexecute " << m_oldParagLayouts.count() << " parag layouts. First parag=" << s->paragId() << endl;
00094     Q_ASSERT( id == s->paragId() );
00095     KoTextParag *p = s;
00096     while ( p ) {
00097         if ( lit != m_oldParagLayouts.end() )
00098         {
00099             kdDebug(32500) << "KoTextDeleteCommand::unexecute applying paraglayout to parag " << p->paragId() << endl;
00100             p->setParagLayout( *lit );
00101         }
00102         else
00103             break;
00104         //if ( s == cr->parag() )
00105         //    break;
00106         p = p->next();
00107         ++lit;
00108     }
00109     return cr;
00110 }
00111 
00112 KoTextParagCommand::KoTextParagCommand( KoTextDocument *d, int fParag, int lParag,
00113                                         const QValueList<KoParagLayout> &oldParagLayouts,
00114                                         KoParagLayout newParagLayout,
00115                                         int flags,
00116                                         QStyleSheetItem::Margin margin )
00117     : KoTextDocCommand( d ), firstParag( fParag ), lastParag( lParag ), m_oldParagLayouts( oldParagLayouts ),
00118       m_newParagLayout( newParagLayout ), m_flags( flags ), m_margin( margin )
00119 {
00120     Q_ASSERT( fParag >= 0 );
00121     Q_ASSERT( lParag >= 0 );
00122 }
00123 
00124 KoTextCursor * KoTextParagCommand::execute( KoTextCursor *c )
00125 {
00126     //kdDebug(32500) << "KoTextParagCommand::execute" << endl;
00127     KoTextParag *p = doc->paragAt( firstParag );
00128     if ( !p )
00129     {
00130         kdWarning() << "KoTextParagCommand::execute paragraph " << firstParag << "not found" << endl;
00131         return c;
00132     }
00133     while ( p ) {
00134         if ( ( m_flags & KoParagLayout::Margins ) && m_margin != (QStyleSheetItem::Margin)-1 ) // all
00135             p->setMargin( static_cast<QStyleSheetItem::Margin>(m_margin), m_newParagLayout.margins[m_margin] );
00136         else
00137         {
00138             p->setParagLayout( m_newParagLayout, m_flags );
00139         }
00140         if ( p->paragId() == lastParag )
00141             break;
00142         p = p->next();
00143     }
00144     //kdDebug(32500) << "KoTextParagCommand::execute done" << endl;
00145     // Set cursor to end of selection. Like in KoTextFormatCommand::[un]execute...
00146     c->setParag( p );
00147     c->setIndex( p->length()-1 );
00148     return c;
00149 }
00150 
00151 KoTextCursor * KoTextParagCommand::unexecute( KoTextCursor *c )
00152 {
00153     kdDebug(32500) << "KoTextParagCommand::unexecute" << endl;
00154     KoTextParag *p = doc->paragAt( firstParag );
00155     if ( !p )
00156     {
00157         kdDebug(32500) << "KoTextParagCommand::unexecute paragraph " << firstParag << "not found" << endl;
00158         return c;
00159     }
00160     QValueList<KoParagLayout>::Iterator lit = m_oldParagLayouts.begin();
00161     while ( p ) {
00162         if ( lit == m_oldParagLayouts.end() )
00163         {
00164             kdDebug(32500) << "KoTextParagCommand::unexecute m_oldParagLayouts not big enough!" << endl;
00165             break;
00166         }
00167         if ( m_flags & KoParagLayout::Margins && m_margin != (QStyleSheetItem::Margin)-1 ) // just one
00168             p->setMargin( static_cast<QStyleSheetItem::Margin>(m_margin), (*lit).margins[m_margin] );
00169         else
00170         {
00171             p->setParagLayout( *lit, m_flags );
00172         }
00173         if ( p->paragId() == lastParag )
00174             break;
00175         p = p->next();
00176         ++lit;
00177     }
00178     // Set cursor to end of selection. Like in KoTextFormatCommand::[un]execute...
00179     c->setParag( p );
00180     c->setIndex( p->length()-1 );
00181     return c;
00182 }
00183 
00185 
00186 KoParagFormatCommand::KoParagFormatCommand( KoTextDocument *d, int fParag, int lParag,
00187                                                           const QValueList<KoTextFormat *> &oldFormats,
00188                                                           KoTextFormat * newFormat )
00189     : KoTextDocCommand( d ), firstParag( fParag ), lastParag( lParag ), m_oldFormats( oldFormats ),
00190       m_newFormat( newFormat )
00191 {
00192     QValueList<KoTextFormat *>::Iterator lit = m_oldFormats.begin();
00193     for ( ; lit != m_oldFormats.end() ; ++lit )
00194         (*lit)->addRef();
00195 }
00196 
00197 KoParagFormatCommand::~KoParagFormatCommand()
00198 {
00199     QValueList<KoTextFormat *>::Iterator lit = m_oldFormats.begin();
00200     for ( ; lit != m_oldFormats.end() ; ++lit )
00201         (*lit)->removeRef();
00202 }
00203 
00204 KoTextCursor * KoParagFormatCommand::execute( KoTextCursor *c )
00205 {
00206     KoTextParag *p = doc->paragAt( firstParag );
00207     if ( !p )
00208     {
00209         kdDebug(32500) << "KoTextParagCommand::execute paragraph " << firstParag << "not found" << endl;
00210         return c;
00211     }
00212     while ( p ) {
00213         p->setFormat( m_newFormat );
00214         p->invalidate(0);
00215         if ( p->paragId() == lastParag )
00216             break;
00217         p = p->next();
00218     }
00219     return c;
00220 }
00221 
00222 KoTextCursor * KoParagFormatCommand::unexecute( KoTextCursor *c )
00223 {
00224     kdDebug(32500) << "KoParagFormatCommand::unexecute" << endl;
00225     KoTextParag *p = doc->paragAt( firstParag );
00226     if ( !p )
00227     {
00228         kdDebug(32500) << "KoParagFormatCommand::unexecute paragraph " << firstParag << "not found" << endl;
00229         return c;
00230     }
00231     QValueList<KoTextFormat *>::Iterator lit = m_oldFormats.begin();
00232     while ( p ) {
00233         if ( lit == m_oldFormats.end() )
00234         {
00235             kdDebug(32500) << "KoParagFormatCommand::unexecute m_oldFormats not big enough!" << endl;
00236             break;
00237         }
00238         p->setFormat( (*lit) );
00239         if ( p->paragId() == lastParag )
00240             break;
00241         p = p->next();
00242         ++lit;
00243     }
00244     return c;
00245 }
00246 
00247 KoTextFormatCommand::KoTextFormatCommand(KoTextDocument *d, int sid, int sidx, int eid, int eidx, const QMemArray<KoTextStringChar> &old, const KoTextFormat *f, int fl )
00248     : KoTextDocFormatCommand(d, sid, sidx, eid, eidx, old, f, fl)
00249 {
00250 }
00251 
00252 
00253 KoTextFormatCommand::~KoTextFormatCommand()
00254 {
00255 }
00256 
00257 void KoTextFormatCommand::resizeCustomItems()
00258 {
00259     KoTextParag *sp = doc->paragAt( startId );
00260     KoTextParag *ep = doc->paragAt( endId );
00261     if ( !sp || !ep )
00262         return;
00263 
00264     KoTextCursor start( doc );
00265     start.setParag( sp );
00266     start.setIndex( startIndex );
00267     KoTextCursor end( doc );
00268     end.setParag( ep );
00269     end.setIndex( endIndex );
00270 
00271     doc->setSelectionStart( KoTextDocument::Temp, &start );
00272     doc->setSelectionEnd( KoTextDocument::Temp, &end );
00273 
00274     // TODO use the visitor pattern (some 'ResizeCustomItemVisitor')
00275 
00276     if ( start.parag() == end.parag() )
00277     {
00278         QString text = start.parag()->string()->toString().mid( start.index(), end.index() - start.index() );
00279         for ( int i = start.index(); i < end.index(); ++i )
00280         {
00281             if( start.parag()->at(i)->isCustom())
00282             {
00283                 start.parag()->at(i)->customItem()->resize();
00284             }
00285         }
00286     }
00287     else
00288     {
00289         int i;
00290         QString text = start.parag()->string()->toString().mid( start.index(), start.parag()->length() - 1 - start.index() );
00291         for ( i = start.index(); i < start.parag()->length(); ++i )
00292             if( start.parag()->at(i)->isCustom())
00293             {
00294                 start.parag()->at(i)->customItem()->resize();
00295             }
00296 
00297         KoTextParag *p = start.parag()->next();
00298         while ( p && p != end.parag() )
00299         {
00300             text = p->string()->toString().left( p->length() - 1 );
00301             for ( i = 0; i < p->length(); ++i )
00302             {
00303                if( p->at(i)->isCustom())
00304                {
00305                    p->at(i)->customItem()->resize();
00306                }
00307             }
00308             p = p->next();
00309         }
00310         text = end.parag()->string()->toString().left( end.index() );
00311         for ( i = 0; i < end.index(); ++i )
00312         {
00313             if( end.parag()->at(i)->isCustom())
00314             {
00315                 end.parag()->at(i)->customItem()->resize();
00316             }
00317         }
00318     }
00319 }
00320 
00321 KoTextCursor *KoTextFormatCommand::execute( KoTextCursor *c )
00322 {
00323     c = KoTextDocFormatCommand::execute( c );
00324     resizeCustomItems();
00325     return c;
00326 }
00327 
00328 KoTextCursor *KoTextFormatCommand::unexecute( KoTextCursor *c )
00329 {
00330     kdDebug(32500) << "KoTextFormatCommand::unexecute c:" << c << " index:" << c->index() << endl;
00331     c = KoTextDocFormatCommand::unexecute( c );
00332     kdDebug(32500) << "KoTextFormatCommand::unexecute after KoTextFormatCommand c:" << c << " index:" << c->index() << endl;
00333     resizeCustomItems();
00334     return c;
00335 }
00336 
00338 
00339 KoChangeVariableSubType::KoChangeVariableSubType(
00340                         short int _oldValue, short int _newValue,
00341                         KoVariable *var):
00342     KCommand(),
00343     m_newValue(_newValue),
00344     m_oldValue(_oldValue),
00345     m_var(var)
00346 {
00347 }
00348 
00349 void KoChangeVariableSubType::execute()
00350 {
00351     Q_ASSERT(m_var);
00352     m_var->setVariableSubType(m_newValue);
00353     m_var->recalcAndRepaint();
00354 }
00355 
00356 void KoChangeVariableSubType::unexecute()
00357 {
00358     Q_ASSERT(m_var);
00359     m_var->setVariableSubType(m_oldValue);
00360     m_var->recalcAndRepaint();
00361 }
00362 
00363 QString KoChangeVariableSubType::name() const
00364 {
00365     return i18n( "Change Variable Subtype" );
00366 }
00367 
00369 
00370 KoChangeVariableFormatProperties::KoChangeVariableFormatProperties(
00371     const QString &_oldValue, const QString &_newValue,
00372     KoVariable *var)
00373     : KCommand(),
00374       m_newValue(_newValue),
00375       m_oldValue(_oldValue),
00376       m_var(var)
00377 {
00378 }
00379 
00380 void KoChangeVariableFormatProperties::execute()
00381 {
00382     Q_ASSERT(m_var);
00383     // Wrong! m_var->variableFormat()->setFormatProperties( m_newValue );
00384     KoVariableFormatCollection* coll = m_var->variableColl()->formatCollection();
00385     m_var->setVariableFormat( coll->format( m_var->variableFormat()->getKey( m_newValue ) ) );
00386     m_var->recalcAndRepaint();
00387 }
00388 
00389 void KoChangeVariableFormatProperties::unexecute()
00390 {
00391     Q_ASSERT(m_var);
00392     // Wrong! m_var->variableFormat()->setFormatProperties( m_oldValue );
00393     KoVariableFormatCollection* coll = m_var->variableColl()->formatCollection();
00394     m_var->setVariableFormat( coll->format( m_var->variableFormat()->getKey( m_oldValue ) ) );
00395     m_var->recalcAndRepaint();
00396 }
00397 
00398 QString KoChangeVariableFormatProperties::name() const
00399 {
00400     return i18n( "Change Variable Format" );
00401 }
KDE Home | KDE Accessibility Home | Description of Access Keys