lib Library API Documentation

kocommandhistory.cpp

00001 /* This file is part of the KDE project 00002 Copyright (C) 2000 Werner Trobin <trobin@kde.org> 00003 Copyright (C) 2000 David Faure <faure@kde.org> 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., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 00021 #include "kocommandhistory.h" 00022 #include <kcommand.h> 00023 #include <kaction.h> 00024 #include <kstdaccel.h> 00025 #include <kstdaction.h> 00026 #include <kdebug.h> 00027 #include <klocale.h> 00028 #include <kpopupmenu.h> 00029 #include <qlistbox.h> 00030 #include <kshortcutlist.h> 00031 #include <qlabel.h> 00032 00033 KoListBox::KoListBox( QWidget *parent , const char *name , WFlags f) 00034 : QListBox( parent, name, f) 00035 { 00036 setVScrollBarMode( AlwaysOn ); 00037 } 00038 00039 void KoListBox::contentsMouseMoveEvent ( QMouseEvent * e) 00040 { 00041 QListBoxItem *item_p = itemAt( contentsToViewport(e->pos())); 00042 if ( item_p ) 00043 { 00044 int itemIndex = index( item_p ); 00045 for ( int i = 0; i<=itemIndex;i++) 00046 setSelected ( i, true ); 00047 for ( int i = itemIndex+1; i<(int)count();i++) 00048 setSelected ( i, false ); 00049 emit changeNumberOfSelectedItem( itemIndex); 00050 } 00051 } 00052 00053 class KoCommandHistory::KoCommandHistoryPrivate { 00054 public: 00055 KoCommandHistoryPrivate() { 00056 m_savedAt=-1; 00057 m_present=0; 00058 } 00059 ~KoCommandHistoryPrivate() {} 00060 int m_savedAt; 00061 KCommand *m_present; 00062 KoListBox *m_undoListBox; 00063 KoListBox *m_redoListBox; 00064 QLabel *m_undoLabel; 00065 QLabel *m_redoLabel; 00066 }; 00067 00069 00070 KoCommandHistory::KoCommandHistory() : 00071 m_undo(0), m_redo(0), m_undoLimit(50), m_redoLimit(30), m_first(false) 00072 { 00073 d=new KoCommandHistoryPrivate(); 00074 m_commands.setAutoDelete(true); 00075 clear(); 00076 } 00077 00078 KoCommandHistory::KoCommandHistory(KActionCollection * actionCollection, bool withMenus) : 00079 m_undoLimit(50), m_redoLimit(30), m_first(false) 00080 { 00081 d=new KoCommandHistoryPrivate(); 00082 if (withMenus) 00083 { 00084 KToolBarPopupAction * undo = new KToolBarPopupAction( i18n("&Undo"), "undo", 00085 KStdAccel::undo(), this, SLOT( undo() ), 00086 actionCollection, /*KStdAction::stdName( KStdAction::Undo )*/"koffice_undo" ); 00087 connect( undo->popupMenu(), SIGNAL( aboutToShow() ), this, SLOT( slotUndoAboutToShow() ) ); 00088 connect( undo->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( slotUndoActivated( int ) ) ); 00089 m_undo = undo; 00090 m_undoPopup = undo->popupMenu(); 00091 d->m_undoListBox = new KoListBox( m_undoPopup ); 00092 d->m_undoListBox->resize( 200, 200);//todo fix me 00093 d->m_undoListBox->setSelectionMode( QListBox::Multi ); 00094 00095 m_undoPopup->insertItem(d->m_undoListBox); 00096 d->m_undoLabel = new QLabel( m_undoPopup); 00097 m_undoPopup->insertItem(d->m_undoLabel); 00098 00099 connect( d->m_undoListBox, SIGNAL( selected( int ) ), this, SLOT( slotUndoActivated( int ) ) ); 00100 connect( d->m_undoListBox, SIGNAL(clicked ( QListBoxItem *)), this, SLOT( slotUndoActivated( QListBoxItem * ) ) ); 00101 00102 connect( d->m_undoListBox, SIGNAL( changeNumberOfSelectedItem( int )), this, SLOT( slotChangeUndoNumberOfSelectedItem( int ))); 00103 00104 KToolBarPopupAction * redo = new KToolBarPopupAction( i18n("&Redo"), "redo", 00105 KStdAccel::redo(), this, SLOT( redo() ), 00106 actionCollection, /*KStdAction::stdName( KStdAction::Redo )*/ 00107 "koffice_redo"); 00108 connect( redo->popupMenu(), SIGNAL( aboutToShow() ), this, SLOT( slotRedoAboutToShow() ) ); 00109 connect( redo->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( slotRedoActivated( int ) ) ); 00110 m_redo = redo; 00111 m_redoPopup = redo->popupMenu(); 00112 d->m_redoListBox = new KoListBox( m_redoPopup ); 00113 d->m_redoListBox->setSelectionMode( QListBox::Multi ); 00114 d->m_redoListBox->resize( 200, 200);//todo fix me 00115 m_redoPopup->insertItem(d->m_redoListBox); 00116 00117 d->m_redoLabel = new QLabel( m_redoPopup); 00118 m_redoPopup->insertItem(d->m_redoLabel); 00119 00120 00121 connect( d->m_redoListBox, SIGNAL( selected( int ) ), this, SLOT( slotRedoActivated( int ) ) ); 00122 connect( d->m_redoListBox, SIGNAL(clicked ( QListBoxItem *)), this, SLOT( slotRedoActivated( QListBoxItem * ) ) ); 00123 connect( d->m_redoListBox, SIGNAL( changeNumberOfSelectedItem( int )), this, SLOT( slotChangeRedoNumberOfSelectedItem( int ))); 00124 00125 } 00126 else 00127 { 00128 m_undo = KStdAction::undo( this, SLOT( undo() ), actionCollection, "koffice_undo"); 00129 m_redo = KStdAction::redo( this, SLOT( redo() ), actionCollection, "koffice_redo"); 00130 m_undoPopup = 0L; 00131 m_redoPopup = 0L; 00132 d->m_redoListBox = 0L; 00133 d->m_undoListBox = 0L; 00134 d->m_redoLabel = 0L; 00135 d->m_undoLabel = 0L; 00136 } 00137 m_commands.setAutoDelete(true); 00138 clear(); 00139 } 00140 00141 KoCommandHistory::~KoCommandHistory() { 00142 delete d; 00143 } 00144 00145 void KoCommandHistory::clear() { 00146 if (m_undo != 0) { 00147 m_undo->setEnabled(false); 00148 m_undo->setText(i18n("&Undo")); 00149 } 00150 if (m_redo != 0) { 00151 m_redo->setEnabled(false); 00152 m_redo->setText(i18n("&Redo")); 00153 } 00154 d->m_present = 0L; 00155 d->m_savedAt=-42; 00156 } 00157 00158 void KoCommandHistory::addCommand(KCommand *command, bool execute) { 00159 00160 if(command==0L) 00161 return; 00162 00163 int index; 00164 if(d->m_present!=0L && (index=m_commands.findRef(d->m_present))!=-1) { 00165 if (m_first) 00166 --index; 00167 m_commands.insert(index+1, command); 00168 // truncate history 00169 unsigned int count=m_commands.count(); 00170 for(unsigned int i=index+2; i<count; ++i) 00171 m_commands.removeLast(); 00172 // check whether we still can reach savedAt 00173 if(index<d->m_savedAt) 00174 d->m_savedAt=-1; 00175 d->m_present=command; 00176 m_first=false; 00177 if (m_undo != 0) { 00178 m_undo->setEnabled(true); 00179 m_undo->setText(i18n("&Undo: %1").arg(d->m_present->name())); 00180 } 00181 if((m_redo != 0) && m_redo->isEnabled()) { 00182 m_redo->setEnabled(false); 00183 m_redo->setText(i18n("&Redo")); 00184 } 00185 clipCommands(); 00186 } 00187 else { // either this is the first time we add a Command or something has gone wrong 00188 kdDebug(230) << "Initializing the Command History" << endl; 00189 m_commands.clear(); 00190 m_commands.append(command); 00191 d->m_present=command; 00192 if (m_undo != 0) { 00193 m_undo->setEnabled(true); 00194 m_undo->setText(i18n("&Undo: %1").arg(d->m_present->name())); 00195 } 00196 if (m_redo != 0) { 00197 m_redo->setEnabled(false); 00198 m_redo->setText(i18n("&Redo")); 00199 } 00200 m_first=false; // Michael B: yes, that *is* correct :-) 00201 } 00202 if ( execute ) 00203 { 00204 command->execute(); 00205 emit commandExecuted(); 00206 } 00207 } 00208 00209 void KoCommandHistory::undo() { 00210 00211 if (m_first || (d->m_present == 0L)) 00212 return; 00213 00214 d->m_present->unexecute(); 00215 emit commandExecuted(); 00216 if (m_redo != 0) { 00217 m_redo->setEnabled(true); 00218 m_redo->setText(i18n("&Redo: %1").arg(d->m_present->name())); 00219 } 00220 int index; 00221 if((index=m_commands.findRef(d->m_present))!=-1 && m_commands.prev()!=0) { 00222 d->m_present=m_commands.current(); 00223 if (m_undo != 0) { 00224 m_undo->setEnabled(true); 00225 m_undo->setText(i18n("&Undo: %1").arg(d->m_present->name())); 00226 } 00227 --index; 00228 if(index==d->m_savedAt) 00229 emit documentRestored(); 00230 } 00231 else { 00232 if (m_undo != 0) { 00233 m_undo->setEnabled(false); 00234 m_undo->setText(i18n("&Undo")); 00235 } 00236 if(d->m_savedAt==-42) 00237 emit documentRestored(); 00238 m_first=true; 00239 } 00240 clipCommands(); // only needed here and in addCommand, NOT in redo 00241 } 00242 00243 void KoCommandHistory::redo() { 00244 00245 int index; 00246 if(m_first) { 00247 d->m_present->execute(); 00248 emit commandExecuted(); 00249 m_first=false; 00250 m_commands.first(); 00251 if(d->m_savedAt==0) 00252 emit documentRestored(); 00253 } 00254 else if((index=m_commands.findRef(d->m_present))!=-1 && m_commands.next()!=0) { 00255 d->m_present=m_commands.current(); 00256 d->m_present->execute(); 00257 emit commandExecuted(); 00258 ++index; 00259 if(index==d->m_savedAt) 00260 emit documentRestored(); 00261 } 00262 00263 if (m_undo != 0) { 00264 m_undo->setEnabled(true); 00265 m_undo->setText(i18n("&Undo: %1").arg(d->m_present->name())); 00266 } 00267 00268 if(m_commands.next()!=0) { 00269 if (m_redo != 0) { 00270 m_redo->setEnabled(true); 00271 m_redo->setText(i18n("&Redo: %1").arg(m_commands.current()->name())); 00272 } 00273 } 00274 else { 00275 if((m_redo != 0) && m_redo->isEnabled()) { 00276 m_redo->setEnabled(false); 00277 m_redo->setText(i18n("&Redo")); 00278 } 00279 } 00280 } 00281 00282 void KoCommandHistory::documentSaved() { 00283 if(d->m_present!=0 && !m_first) 00284 d->m_savedAt=m_commands.findRef(d->m_present); 00285 else if(d->m_present==0 && !m_first) 00286 d->m_savedAt=-42; // this value signals that the document has 00287 // been saved with an empty history. 00288 else if(m_first) 00289 d->m_savedAt=-42; 00290 } 00291 00292 void KoCommandHistory::setUndoLimit(int limit) { 00293 00294 if(limit>0 && limit!=m_undoLimit) { 00295 m_undoLimit=limit; 00296 clipCommands(); 00297 } 00298 } 00299 00300 void KoCommandHistory::setRedoLimit(int limit) { 00301 00302 if(limit>0 && limit!=m_redoLimit) { 00303 m_redoLimit=limit; 00304 clipCommands(); 00305 } 00306 } 00307 00308 void KoCommandHistory::clipCommands() { 00309 00310 int count=m_commands.count(); 00311 if(count<=m_undoLimit && count<=m_redoLimit) 00312 return; 00313 00314 int index=m_commands.findRef(d->m_present); 00315 if(index>=m_undoLimit) { 00316 for(int i=0; i<=(index-m_undoLimit); ++i) { 00317 m_commands.removeFirst(); 00318 --d->m_savedAt; 00319 if(d->m_savedAt==-1) 00320 d->m_savedAt=-42; 00321 } 00322 index=m_commands.findRef(d->m_present); // calculate the new 00323 count=m_commands.count(); // values (for the redo-branch :) 00324 // make it easier for us... d->m_savedAt==-1 -> invalid 00325 if(d->m_savedAt!=-42 && d->m_savedAt<-1) 00326 d->m_savedAt=-1; 00327 } 00328 // adjust the index if it's the first command 00329 if(m_first) 00330 index=-1; 00331 if((index+m_redoLimit+1)<count) { 00332 if(d->m_savedAt>(index+m_redoLimit)) 00333 d->m_savedAt=-1; 00334 for(int i=0; i<(count-(index+m_redoLimit+1)); ++i) 00335 m_commands.removeLast(); 00336 } 00337 } 00338 00339 void KoCommandHistory::slotUndoAboutToShow() 00340 { 00341 d->m_undoListBox->clear(); 00342 slotChangeUndoNumberOfSelectedItem( -1 ); 00343 int i = 0; 00344 QStringList lst; 00345 if (m_commands.findRef(d->m_present)!=-1) 00346 while ( m_commands.current() && i<10 ) // TODO make number of items configurable ? 00347 { 00348 lst.append(i18n("Undo: %1").arg(m_commands.current()->name())); 00349 m_commands.prev(); 00350 } 00351 d->m_undoListBox->insertStringList( lst ); 00352 } 00353 00354 void KoCommandHistory::slotUndoActivated( int pos ) 00355 { 00356 kdDebug(230) << "KoCommandHistory::slotUndoActivated " << pos << endl; 00357 for ( int i = 0 ; i < pos+1; ++i ) 00358 undo(); 00359 m_undoPopup->hide(); 00360 } 00361 00362 void KoCommandHistory::slotUndoActivated( QListBoxItem * item) 00363 { 00364 if ( item ) 00365 slotUndoActivated( item->listBox()->index(item)); 00366 } 00367 00368 void KoCommandHistory::slotRedoActivated( QListBoxItem * item) 00369 { 00370 if ( item ) 00371 slotRedoActivated( item->listBox()->index(item)); 00372 } 00373 00374 void KoCommandHistory::slotChangeUndoNumberOfSelectedItem( int pos) 00375 { 00376 d->m_undoLabel->setText( i18n("Undo %n action", "Undo %n actions", pos+1) ); 00377 } 00378 00379 void KoCommandHistory::slotChangeRedoNumberOfSelectedItem( int pos) 00380 { 00381 d->m_redoLabel->setText( i18n("Redo %n action", "Redo %n actions", pos+1) ); 00382 } 00383 00384 00385 void KoCommandHistory::slotRedoAboutToShow() 00386 { 00387 d->m_redoListBox->clear(); 00388 slotChangeRedoNumberOfSelectedItem( -1 ); 00389 QStringList lst; 00390 int i = 0; 00391 if (m_first) 00392 { 00393 d->m_present = m_commands.first(); 00394 lst.append(i18n("Redo: %1").arg(d->m_present->name())); 00395 } 00396 if (m_commands.findRef(d->m_present)!=-1 && m_commands.next()) 00397 while ( m_commands.current() && i<10 ) // TODO make number of items configurable ? 00398 { 00399 lst.append(i18n("Redo: %1").arg(m_commands.current()->name())); 00400 m_commands.next(); 00401 } 00402 d->m_redoListBox->insertStringList( lst ); 00403 00404 } 00405 00406 void KoCommandHistory::slotRedoActivated( int pos ) 00407 { 00408 kdDebug(230) << "KoCommandHistory::slotRedoActivated " << pos << endl; 00409 for ( int i = 0 ; i < pos+1; ++i ) 00410 redo(); 00411 m_redoPopup->hide(); 00412 } 00413 00414 void KoCommandHistory::updateActions() 00415 { 00416 if ( m_undo && m_redo ) 00417 { 00418 m_undo->setEnabled( !m_first && ( d->m_present != 0L ) ); 00419 m_redo->setEnabled(m_first || (m_commands.findRef(d->m_present)!=-1 && m_commands.next()!=0)); 00420 } 00421 } 00422 00423 void KoCommandHistory::virtual_hook( int, void* ) 00424 { /*BASE::virtual_hook( id, data );*/ } 00425 00426 #include "kocommandhistory.moc"
KDE Logo
This file is part of the documentation for lib Library Version 1.3.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Sep 24 18:22:23 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003