00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "kateundomanager.h"
00019
00020 #include "katedocument.h"
00021 #include "kateview.h"
00022 #include "katesearchbar.h"
00023 #include "kateundo.h"
00024
00025 KateUndoManager::KateUndoManager (KateDocument *doc)
00026 : QObject (doc)
00027 , m_document (doc)
00028 , m_undoComplexMerge (false)
00029 , m_isUndoTrackingEnabled (true)
00030 , m_editCurrentUndo (0)
00031 , m_undoDontMerge (false)
00032 , lastUndoGroupWhenSaved(0)
00033 , lastRedoGroupWhenSaved(0)
00034 , docWasSavedWhenUndoWasEmpty(true)
00035 , docWasSavedWhenRedoWasEmpty(true)
00036 {
00037 connect(this, SIGNAL(undoChanged()), m_document, SIGNAL(undoChanged()));
00038 connect(doc, SIGNAL(viewCreated(KTextEditor::Document*, KTextEditor::View*)), SLOT(viewCreated(KTextEditor::Document*, KTextEditor::View*)));
00039 }
00040
00041 KateUndoManager::~KateUndoManager()
00042 {
00043 delete m_editCurrentUndo;
00044
00045
00046 qDeleteAll(undoItems);
00047 undoItems.clear();
00048 qDeleteAll(redoItems);
00049 redoItems.clear();
00050 }
00051
00052 KateDocument *KateUndoManager::document()
00053 {
00054 return m_document;
00055 }
00056
00057 void KateUndoManager::viewCreated (KTextEditor::Document *, KTextEditor::View *newView)
00058 {
00059 connect(newView, SIGNAL(cursorPositionChanged(KTextEditor::View*, const KTextEditor::Cursor&)), SLOT(undoCancel()));
00060 }
00061
00062 void KateUndoManager::editStart()
00063 {
00064 if (!m_isUndoTrackingEnabled)
00065 return;
00066
00067
00068 Q_ASSERT(m_editCurrentUndo == 0);
00069
00070
00071 m_editCurrentUndo = new KateUndoGroup(this);
00072
00073 Q_ASSERT(m_editCurrentUndo != 0);
00074 }
00075
00076 void KateUndoManager::editEnd()
00077 {
00078 if (!m_isUndoTrackingEnabled)
00079 return;
00080
00081
00082 Q_ASSERT(m_editCurrentUndo != 0);
00083
00084 bool changedUndo = false;
00085
00086 m_editCurrentUndo->editEnd();
00087
00088 if (m_editCurrentUndo->isEmpty()) {
00089 delete m_editCurrentUndo;
00090 } else if (!m_undoDontMerge
00091 && !undoItems.isEmpty()
00092 && undoItems.last()->merge(m_editCurrentUndo, m_undoComplexMerge)) {
00093 delete m_editCurrentUndo;
00094 } else {
00095 undoItems.append(m_editCurrentUndo);
00096 changedUndo = true;
00097 }
00098
00099 m_undoDontMerge = false;
00100
00101 m_editCurrentUndo = 0L;
00102
00103 if (changedUndo)
00104 emit undoChanged();
00105
00106 Q_ASSERT(m_editCurrentUndo == 0);
00107 }
00108
00109 void KateUndoManager::inputMethodStart()
00110 {
00111 setUndoTrackingEnabled(false);
00112 m_document->editStart();
00113 }
00114
00115 void KateUndoManager::inputMethodEnd()
00116 {
00117 m_document->editEnd();
00118 setUndoTrackingEnabled(true);
00119 }
00120
00121 void KateUndoManager::undoStart()
00122 {
00123 setUndoTrackingEnabled(false);
00124 m_document->editStart();
00125 }
00126
00127 void KateUndoManager::undoEnd()
00128 {
00129 m_document->editEnd();
00130 setUndoTrackingEnabled(true);
00131 }
00132
00133 void KateUndoManager::slotTextInserted(int line, int col, const QString &s)
00134 {
00135 if (m_editCurrentUndo != 0)
00136 addUndoItem(new KateEditInsertTextUndo(m_document, line, col, s));
00137 }
00138
00139 void KateUndoManager::slotTextRemoved(int line, int col, const QString &s)
00140 {
00141 if (m_editCurrentUndo != 0)
00142 addUndoItem(new KateEditRemoveTextUndo(m_document, line, col, s));
00143 }
00144
00145 void KateUndoManager::slotMarkLineAutoWrapped(int line, bool autowrapped)
00146 {
00147 if (m_editCurrentUndo != 0)
00148 addUndoItem(new KateEditMarkLineAutoWrappedUndo(m_document, line, autowrapped));
00149 }
00150
00151 void KateUndoManager::slotLineWrapped(int line, int col, int pos, bool newLine)
00152 {
00153 if (m_editCurrentUndo != 0)
00154 addUndoItem(new KateEditWrapLineUndo(m_document, line, col, pos, newLine));
00155 }
00156
00157 void KateUndoManager::slotLineUnWrapped(int line, int col, int length, bool lineRemoved)
00158 {
00159 if (m_editCurrentUndo != 0)
00160 addUndoItem(new KateEditUnWrapLineUndo(m_document, line, col, length, lineRemoved));
00161 }
00162
00163 void KateUndoManager::slotLineInserted(int line, const QString &s)
00164 {
00165 if (m_editCurrentUndo != 0)
00166 addUndoItem(new KateEditInsertLineUndo(m_document, line, s));
00167 }
00168
00169 void KateUndoManager::slotLineRemoved(int line, const QString &s)
00170 {
00171 if (m_editCurrentUndo != 0)
00172 addUndoItem(new KateEditRemoveLineUndo(m_document, line, s));
00173 }
00174
00175 void KateUndoManager::undoCancel()
00176 {
00177
00178 if (m_document->isEditRunning())
00179 return;
00180
00181 m_undoDontMerge = true;
00182
00183 Q_ASSERT(m_editCurrentUndo == 0);
00184 }
00185
00186 void KateUndoManager::undoSafePoint() {
00187 Q_ASSERT(m_editCurrentUndo != 0);
00188
00189 m_editCurrentUndo->safePoint();
00190 }
00191
00192 void KateUndoManager::addUndoItem(KateUndo *undo)
00193 {
00194 Q_ASSERT(undo != 0);
00195 Q_ASSERT(m_editCurrentUndo != 0);
00196
00197 m_editCurrentUndo->addItem(undo);
00198
00199
00200 qDeleteAll(redoItems);
00201 redoItems.clear();
00202 }
00203
00204 void KateUndoManager::setUndoTrackingEnabled(bool enabled)
00205 {
00206 Q_ASSERT(m_editCurrentUndo == 0);
00207 Q_ASSERT(m_isUndoTrackingEnabled != enabled);
00208
00209 m_isUndoTrackingEnabled = enabled;
00210
00211 emit undoTrackingEnabledChanged(enabled);
00212 }
00213
00214 uint KateUndoManager::undoCount () const
00215 {
00216 return undoItems.count ();
00217 }
00218
00219 uint KateUndoManager::redoCount () const
00220 {
00221 return redoItems.count ();
00222 }
00223
00224 void KateUndoManager::undo()
00225 {
00226 Q_ASSERT(m_editCurrentUndo == 0);
00227
00228 if (undoItems.count() > 0)
00229 {
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 foreach (KTextEditor::View *v, m_document->views()) {
00240 KateView *view = qobject_cast<KateView*>(v);
00241
00242 if (view->searchBar(false))
00243 view->searchBar(false)->enableHighlights(false);
00244 }
00245
00246 undoItems.last()->undo();
00247 redoItems.append (undoItems.last());
00248 undoItems.removeLast ();
00249 updateModified();
00250 emit undoChanged ();
00251 }
00252 }
00253
00254 void KateUndoManager::redo()
00255 {
00256 Q_ASSERT(m_editCurrentUndo == 0);
00257
00258 if (redoItems.count() > 0)
00259 {
00260
00261
00262 foreach (KTextEditor::View *v, m_document->views()) {
00263 KateView *view = qobject_cast<KateView*>(v);
00264
00265 if (view->searchBar(false))
00266 view->searchBar(false)->enableHighlights(false);
00267 }
00268
00269 redoItems.last()->redo();
00270 undoItems.append (redoItems.last());
00271 redoItems.removeLast ();
00272 updateModified();
00273
00274 emit undoChanged ();
00275 }
00276 }
00277
00278 void KateUndoManager::updateModified()
00279 {
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 unsigned char currentPattern = 0;
00304 const unsigned char patterns[] = {5,16,21,24,26,88,90,93,133,144,149,165};
00305 const unsigned char patternCount = sizeof(patterns);
00306 KateUndoGroup* undoLast = 0;
00307 KateUndoGroup* redoLast = 0;
00308
00309 if (undoItems.isEmpty())
00310 {
00311 currentPattern |= 1;
00312 }
00313 else
00314 {
00315 undoLast = undoItems.last();
00316 }
00317
00318 if (redoItems.isEmpty())
00319 {
00320 currentPattern |= 2;
00321 }
00322 else
00323 {
00324 redoLast = redoItems.last();
00325 }
00326
00327 if (docWasSavedWhenUndoWasEmpty) currentPattern |= 4;
00328 if (docWasSavedWhenRedoWasEmpty) currentPattern |= 8;
00329 if (lastUndoGroupWhenSaved == undoLast) currentPattern |= 16;
00330 if (lastUndoGroupWhenSaved == redoLast) currentPattern |= 32;
00331 if (lastRedoGroupWhenSaved == undoLast) currentPattern |= 64;
00332 if (lastRedoGroupWhenSaved == redoLast) currentPattern |= 128;
00333
00334
00335
00336 kDebug() << "Pattern:" << static_cast<unsigned int>(currentPattern);
00337
00338 for (uint patternIndex = 0; patternIndex < patternCount; ++patternIndex)
00339 {
00340 if ( currentPattern == patterns[patternIndex] )
00341 {
00342 m_document->setModified( false );
00343
00344
00345 setUndoDontMerge(true);
00346 kDebug() << "setting modified to false!";
00347 break;
00348 }
00349 }
00350 }
00351
00352 void KateUndoManager::clearUndo()
00353 {
00354 qDeleteAll(undoItems);
00355 undoItems.clear ();
00356
00357 lastUndoGroupWhenSaved = 0;
00358 docWasSavedWhenUndoWasEmpty = false;
00359
00360 emit undoChanged ();
00361 }
00362
00363 void KateUndoManager::clearRedo()
00364 {
00365 qDeleteAll(redoItems);
00366 redoItems.clear ();
00367
00368 lastRedoGroupWhenSaved = 0;
00369 docWasSavedWhenRedoWasEmpty = false;
00370
00371 emit undoChanged ();
00372 }
00373
00374 void KateUndoManager::setModified(bool m) {
00375 if ( m == false )
00376 {
00377 if ( ! undoItems.isEmpty() )
00378 {
00379 lastUndoGroupWhenSaved = undoItems.last();
00380 }
00381
00382 if ( ! redoItems.isEmpty() )
00383 {
00384 lastRedoGroupWhenSaved = redoItems.last();
00385 }
00386
00387 docWasSavedWhenUndoWasEmpty = undoItems.isEmpty();
00388 docWasSavedWhenRedoWasEmpty = redoItems.isEmpty();
00389 }
00390 }
00391
00392 void KateUndoManager::updateConfig ()
00393 {
00394 emit undoChanged ();
00395 }
00396
00397 bool KateUndoManager::undoDontMerge( ) const
00398 {
00399 return m_undoDontMerge;
00400 }
00401
00402 void KateUndoManager::setAllowComplexMerge(bool allow)
00403 {
00404 m_undoComplexMerge = allow;
00405 }
00406
00407 bool KateUndoManager::allowComplexMerge() const
00408 {
00409 return m_undoComplexMerge;
00410 }
00411
00412 void KateUndoManager::setUndoDontMerge(bool dontMerge)
00413 {
00414 m_undoDontMerge = dontMerge;
00415 }
00416
00417