karbon

vcommand.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001, The Karbon Developers
00003    Copyright (C) 2002, The Karbon Developers
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 
00022 #include "kaction.h"
00023 #include "klocale.h"
00024 
00025 #include "vcommand.h"
00026 #include "karbon_part.h"
00027 
00028 
00029 VCommandHistory::VCommandHistory( KarbonPart* part )
00030     : m_part( part ), m_undoLimit( 50 ), m_redoLimit( 30 ), m_savedPos( 0 )
00031 {
00032     m_commands.setAutoDelete( true );
00033 
00034     m_undo = KStdAction::undo( this, SLOT( undo() ), m_part->actionCollection(), "koffice_undo" );
00035     m_redo = KStdAction::redo( this, SLOT( redo() ), m_part->actionCollection(), "koffice_redo" );
00036 
00037     clear();
00038 }
00039 
00040 VCommandHistory::~VCommandHistory()
00041 {
00042 }
00043 
00044 void
00045 VCommandHistory::clear()
00046 {
00047     if( m_savedPos != int( m_commands.count() - 1 ) )
00048         m_savedPos = -1;
00049     else
00050         m_savedPos = 0;
00051 
00052     m_commands.clear();
00053 
00054     emit historyCleared();
00055 
00056     if( m_undo != 0 )
00057     {
00058         m_undo->setEnabled( false );
00059         m_undo->setText( i18n( "&Undo" ) );
00060     }
00061 
00062     if( m_redo != 0 )
00063     {
00064         m_redo->setEnabled( false );
00065         m_redo->setText( i18n( "&Redo" ) );
00066     }
00067 }
00068 
00069 void
00070 VCommandHistory::addCommand( VCommand* command, bool execute )
00071 {
00072     if( command == 0L )
00073         return;
00074 
00075     if( !m_commands.isEmpty() )
00076     {
00077         while( m_commands.last() && !m_commands.last()->success() )
00078         {
00079             m_commands.removeLast();
00080             emit lastCommandRemoved();
00081         }
00082     }
00083 
00084     m_commands.append( command );
00085     kdDebug(38000) << "History: new command: " << m_commands.findRef( command ) << endl;
00086 
00087     if( execute )
00088     {
00089         command->execute();
00090         emit commandExecuted( command );
00091     }
00092 
00093     updateActions();
00094 
00095     emit commandAdded( command );
00096 }
00097 
00098 void
00099 VCommandHistory::setUndoLimit( unsigned int limit )
00100 {
00101     m_undoLimit = limit;
00102     clipCommands();
00103 }
00104 
00105 void
00106 VCommandHistory::setRedoLimit( unsigned int limit )
00107 {
00108     m_redoLimit = limit;
00109     clipCommands();
00110 }
00111 
00112 void
00113 VCommandHistory::undo()
00114 {
00115     int i = m_commands.count() - 1;
00116 
00117     if( i == -1 )
00118         return;
00119 
00120     while( ( i >= 0 ) && !( m_commands.at( i )->success() ) )
00121     {
00122         i--;
00123     }
00124 
00125     if( i < 0 )
00126         return;
00127 
00128     VCommand* cmd = m_commands.at( i );
00129 
00130     cmd->unexecute();
00131 
00132     emit commandExecuted( cmd );
00133 
00134     emit commandExecuted();
00135 
00136     clipCommands();
00137 
00138     updateActions();
00139 
00140     m_part->repaintAllViews();
00141 }
00142 
00143 void
00144 VCommandHistory::redo()
00145 {
00146     int i = m_commands.count() - 1;
00147 
00148     if( i == -1 )
00149         return;
00150 
00151     while( ( i >= 0 ) && !( m_commands.at( i )->success() ) )
00152     {
00153         i--;
00154     }
00155 
00156     i++;
00157 
00158     if( i >= int( m_commands.count() ) )
00159         return;
00160 
00161     VCommand* cmd;
00162 
00163     if( ( cmd = m_commands.at( i ) ) == 0L )
00164         return;
00165 
00166     cmd->execute();
00167 
00168     emit commandExecuted( cmd );
00169     emit commandExecuted();
00170 
00171     updateActions();
00172 
00173     m_part->repaintAllViews();
00174 }
00175 
00176 void
00177 VCommandHistory::undo( VCommand* command )
00178 {
00179     if( ( m_commands.findRef( command ) == -1 ) || ( !command->success() ) )
00180         return;
00181 
00182     command->unexecute();
00183 
00184     emit commandExecuted( command );
00185     emit commandExecuted();
00186 
00187     updateActions();
00188 
00189     m_part->repaintAllViews();
00190 }
00191 
00192 void
00193 VCommandHistory::redo( VCommand* command )
00194 {
00195     if( ( m_commands.findRef( command ) == -1 ) || ( command->success() ) )
00196         return;
00197 
00198     command->execute();
00199 
00200     emit commandExecuted( command );
00201     emit commandExecuted();
00202 
00203     updateActions();
00204 
00205     m_part->repaintAllViews();
00206 }
00207 
00208 void
00209 VCommandHistory::undoAllTo( VCommand* command )
00210 {
00211     int to;
00212 
00213     if( ( to = m_commands.findRef( command ) ) == -1 )
00214         return;
00215 
00216     int i = m_commands.count() - 1;
00217 
00218     VCommand* cmd;
00219 
00220     while( i > to )
00221     {
00222         cmd = m_commands.at( i-- );
00223 
00224         if( cmd->success() )
00225         {
00226             cmd->unexecute();
00227             emit commandExecuted( cmd );
00228         }
00229     }
00230 
00231     emit commandExecuted();
00232     updateActions();
00233 
00234     m_part->repaintAllViews();
00235 }
00236 
00237 void
00238 VCommandHistory::redoAllTo( VCommand* command )
00239 {
00240     int to;
00241 
00242     if( ( to = m_commands.findRef( command ) ) == -1 )
00243         return;
00244 
00245     int i = 0;
00246 
00247     VCommand* cmd;
00248 
00249     while( i <= to )
00250     {
00251         cmd = m_commands.at( i++ );
00252 
00253         if( !cmd->success() )
00254         {
00255             cmd->execute();
00256             emit commandExecuted( cmd );
00257         }
00258     }
00259 
00260     emit commandExecuted();
00261     updateActions();
00262 
00263     m_part->repaintAllViews();
00264 }
00265 
00266 void
00267 VCommandHistory::documentSaved()
00268 {
00269     // I don't know how to make this work... This is a temporary hack...
00270     // Maybe remove all undone commands before the current one ?
00271     int i = m_commands.count() - 1;
00272 
00273     while( ( i >= 0 ) && !( m_commands.at( i )->success() ) )
00274     {
00275         i--;
00276     }
00277 
00278     i++;
00279 
00280     m_savedPos = i;
00281 }
00282 
00283 void
00284 VCommandHistory::clipCommands()
00285 {
00286     while( m_commands.count() > m_undoLimit )
00287     {
00288         if( m_commands.removeFirst() )
00289             m_savedPos--, emit firstCommandRemoved();
00290     }
00291 
00292     int i = 0;
00293 
00294     int c = m_commands.count();
00295 
00296     while( ( i < c ) && ( !m_commands.at( c - 1 - i )->success() ) )
00297     {
00298         i++;
00299     }
00300 
00301     i = i - m_redoLimit;
00302 
00303     for( int j = 0; j < i; j++ )
00304     {
00305         if( m_commands.removeLast() )
00306             emit lastCommandRemoved();
00307     }
00308 }
00309 
00310 void
00311 VCommandHistory::updateActions()
00312 {
00313     if( m_commands.count() == 0 )
00314     {
00315         if( m_undo != 0 )
00316         {
00317             m_undo->setEnabled( false );
00318             m_undo->setText( i18n( "&Undo" ) );
00319         }
00320 
00321         if( m_redo != 0 )
00322         {
00323             m_redo->setEnabled( false );
00324             m_redo->setText( i18n( "&Redo" ) );
00325         }
00326 
00327         return;
00328     }
00329 
00330     int i = m_commands.count() - 1;
00331 
00332     while( ( i >= 0 ) && !( m_commands.at( i )->success() ) )
00333     {
00334         i--;
00335     }
00336 
00337     if( m_undo != 0 )
00338     {
00339         if( i < 0 )
00340         {
00341             m_undo->setEnabled( false );
00342             m_undo->setText( i18n( "&Undo" ) );
00343         }
00344         else
00345         {
00346             m_undo->setEnabled( true );
00347             m_undo->setText( i18n( "&Undo: " ) + m_commands.at( i )->name() );
00348         }
00349     }
00350 
00351     if( m_redo != 0 )
00352     {
00353         if( ++i == int( m_commands.count() ) )
00354         {
00355             m_redo->setEnabled( false );
00356             m_redo->setText( i18n( "&Redo" ) );
00357         }
00358         else
00359         {
00360             m_redo->setEnabled( true );
00361             m_redo->setText( i18n( "&Redo: " ) + m_commands.at( i )->name() );
00362         }
00363     }
00364 
00365     if( m_savedPos >= 0 )
00366     {
00367         for( i = 0; i < m_savedPos; i++ )
00368         {
00369             if( !m_commands.at( i )->success() )
00370                 return;
00371         }
00372 
00373         for( i = m_savedPos; i < int( m_commands.count() ); i++ )
00374         {
00375             if( m_commands.at( i )->success() )
00376                 return;
00377         }
00378 
00379         emit documentRestored();
00380     }
00381 }
00382 
00383 #include "vcommand.moc"
00384 
KDE Home | KDE Accessibility Home | Description of Access Keys