00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kateundo.h"
00022
00023 #include "katedocument.h"
00024 #include "kateview.h"
00025 #include "katecursor.h"
00026
00030 class KateUndo
00031 {
00032 public:
00041 KateUndo (KateUndoGroup::UndoType type, uint line, uint col, uint len, const QString &text);
00042
00046 ~KateUndo ();
00047
00048 public:
00055 bool isValid() const;
00056
00063 bool merge(KateUndo* u);
00064
00069 void undo (KateDocument *doc);
00070
00075 void redo (KateDocument *doc);
00076
00081 inline KateUndoGroup::UndoType type() const { return m_type; }
00082
00087 inline uint line () const { return m_line; }
00088
00093 inline uint col () const { return m_col; }
00094
00099 inline uint len() const { return m_len; }
00100
00105 inline const QString& text() const { return m_text; }
00106
00107 private:
00111 KateUndoGroup::UndoType m_type;
00112
00116 uint m_line;
00117
00121 uint m_col;
00122
00126 uint m_len;
00127
00131 QString m_text;
00132 };
00133
00134 KateUndo::KateUndo (KateUndoGroup::UndoType type, uint line, uint col, uint len, const QString &text)
00135 : m_type (type),
00136 m_line (line),
00137 m_col (col),
00138 m_len (len),
00139 m_text (text)
00140 {
00141 }
00142
00143 KateUndo::~KateUndo ()
00144 {
00145 }
00146
00147 bool KateUndo::isValid() const
00148 {
00149 if (m_type == KateUndoGroup::editInsertText || m_type == KateUndoGroup::editRemoveText)
00150 if (len() == 0)
00151 return false;
00152
00153 return true;
00154 }
00155
00156 bool KateUndo::merge(KateUndo* u)
00157 {
00158 if (m_type != u->type())
00159 return false;
00160
00161 if (m_type == KateUndoGroup::editInsertText
00162 && m_line == u->line()
00163 && (m_col + m_len) == u->col())
00164 {
00165 m_text += u->text();
00166 m_len += u->len();
00167 return true;
00168 }
00169 else if (m_type == KateUndoGroup::editRemoveText
00170 && m_line == u->line()
00171 && m_col == (u->col() + u->len()))
00172 {
00173 m_text.prepend(u->text());
00174 m_col = u->col();
00175 m_len += u->len();
00176 return true;
00177 }
00178
00179 return false;
00180 }
00181
00182 void KateUndo::undo (KateDocument *doc)
00183 {
00184 switch(m_type) {
00185 case KateUndoGroup::editInsertText:
00186 doc->editRemoveText (m_line, m_col, m_len);
00187 break;
00188 case KateUndoGroup::editRemoveText:
00189 doc->editInsertText (m_line, m_col, m_text);
00190 break;
00191 case KateUndoGroup::editWrapLine:
00192 doc->editUnWrapLine (m_line, (m_text == "1"), m_len);
00193 break;
00194 case KateUndoGroup::editUnWrapLine:
00195 doc->editWrapLine (m_line, m_col, (m_text == "1"));
00196 break;
00197 case KateUndoGroup::editInsertLine:
00198 doc->editRemoveLine (m_line);
00199 break;
00200 case KateUndoGroup::editRemoveLine:
00201 doc->editInsertLine (m_line, m_text);
00202 break;
00203 case KateUndoGroup::editMarkLineAutoWrapped:
00204 doc->editMarkLineAutoWrapped (m_line, m_col == 0);
00205 break;
00206 default:
00207 kDebug(13020) << "Unknown KateUndoGroup enum:" << static_cast<int>(m_type);
00208 break;
00209 }
00210 }
00211
00212 void KateUndo::redo (KateDocument *doc)
00213 {
00214 switch(m_type) {
00215 case KateUndoGroup::editRemoveText:
00216 doc->editRemoveText (m_line, m_col, m_len);
00217 break;
00218 case KateUndoGroup::editInsertText:
00219 doc->editInsertText (m_line, m_col, m_text);
00220 break;
00221 case KateUndoGroup::editUnWrapLine:
00222 doc->editUnWrapLine (m_line, (m_text == "1"), m_len);
00223 break;
00224 case KateUndoGroup::editWrapLine:
00225 doc->editWrapLine (m_line, m_col, (m_text == "1"));
00226 break;
00227 case KateUndoGroup::editRemoveLine:
00228 doc->editRemoveLine (m_line);
00229 break;
00230 case KateUndoGroup::editInsertLine:
00231 doc->editInsertLine (m_line, m_text);
00232 break;
00233 case KateUndoGroup::editMarkLineAutoWrapped:
00234 doc->editMarkLineAutoWrapped (m_line, m_col == 1);
00235 break;
00236 default:
00237 kDebug(13020) << "Unknown KateUndoGroup enum:" << static_cast<int>(m_type);
00238 break;
00239 }
00240 }
00241
00242 KateUndoGroup::KateUndoGroup (KateDocument *doc)
00243 : m_doc (doc)
00244 , m_safePoint(false)
00245 , m_undoSelection(-1, -1, -1, -1)
00246 , m_redoSelection(-1, -1, -1, -1)
00247 , m_undoCursor(-1, -1)
00248 , m_redoCursor(-1, -1)
00249 {
00250 }
00251
00252 KateUndoGroup::~KateUndoGroup ()
00253 {
00254 qDeleteAll (m_items);
00255 }
00256
00257 void KateUndoGroup::undo ()
00258 {
00259 if (m_items.isEmpty())
00260 return;
00261
00262 m_doc->editStart (false);
00263
00264 for (int i=m_items.size()-1; i >= 0; --i)
00265 m_items[i]->undo(m_doc);
00266
00267 if (KateView *view = m_doc->activeKateView()) {
00268 if (m_undoSelection.isValid())
00269 view->setSelection(m_undoSelection);
00270 else
00271 view->clearSelection();
00272
00273 if (m_undoCursor.isValid())
00274 view->editSetCursor(m_undoCursor);
00275 }
00276
00277 m_doc->editEnd ();
00278 }
00279
00280 void KateUndoGroup::redo ()
00281 {
00282 if (m_items.isEmpty())
00283 return;
00284
00285 m_doc->editStart (false);
00286
00287 for (int i=0; i < m_items.size(); ++i)
00288 m_items[i]->redo(m_doc);
00289
00290 if (KateView *view = m_doc->activeKateView()) {
00291 if (m_redoSelection.isValid())
00292 view->setSelection(m_redoSelection);
00293 else
00294 view->clearSelection();
00295
00296 if (m_redoCursor.isValid())
00297 view->editSetCursor(m_redoCursor);
00298 }
00299
00300 m_doc->editEnd ();
00301 }
00302
00303 void KateUndoGroup::addItem (KateUndoGroup::UndoType type, uint line, uint col, uint len, const QString &text)
00304 {
00305 addItem(new KateUndo(type, line, col, len, text));
00306 }
00307
00308 void KateUndoGroup::setUndoSelection(const KTextEditor::Range &selection)
00309 {
00310 m_undoSelection = selection;
00311 }
00312
00313 void KateUndoGroup::setRedoSelection(const KTextEditor::Range &selection)
00314 {
00315 m_redoSelection = selection;
00316 }
00317
00318 void KateUndoGroup::setUndoCursor(const KTextEditor::Cursor &cursor)
00319 {
00320 m_undoCursor = cursor;
00321 }
00322
00323 void KateUndoGroup::setRedoCursor(const KTextEditor::Cursor &cursor)
00324 {
00325 m_redoCursor = cursor;
00326 }
00327
00328 void KateUndoGroup::addItem(KateUndo* u)
00329 {
00330 if (!u->isValid())
00331 delete u;
00332 else if (!m_items.isEmpty() && m_items.last()->merge(u))
00333 delete u;
00334 else
00335 m_items.append(u);
00336 }
00337
00338 bool KateUndoGroup::merge(KateUndoGroup* newGroup,bool complex)
00339 {
00340 if (m_safePoint) return false;
00341 if (newGroup->isOnlyType(singleType()) || complex) {
00342
00343 KateUndo* u = newGroup->m_items.isEmpty() ? 0 : newGroup->m_items.takeFirst ();
00344 while (u) {
00345 addItem(u);
00346 u = newGroup->m_items.isEmpty() ? 0 : newGroup->m_items.takeFirst ();
00347 }
00348 if (newGroup->m_safePoint) safePoint();
00349 m_redoCursor = newGroup->m_redoCursor;
00350 m_redoSelection = newGroup->m_redoSelection;
00351 return true;
00352 }
00353 return false;
00354 }
00355
00356 void KateUndoGroup::safePoint (bool safePoint)
00357 {
00358 m_safePoint=safePoint;
00359 }
00360
00361 KateUndoGroup::UndoType KateUndoGroup::singleType() const
00362 {
00363 KateUndoGroup::UndoType ret = editInvalid;
00364
00365 Q_FOREACH(const KateUndo *item, m_items) {
00366 if (ret == editInvalid)
00367 ret = item->type();
00368 else if (ret != item->type())
00369 return editInvalid;
00370 }
00371
00372 return ret;
00373 }
00374
00375 bool KateUndoGroup::isOnlyType(KateUndoGroup::UndoType type) const
00376 {
00377 if (type == editInvalid) return false;
00378
00379 Q_FOREACH(const KateUndo *item, m_items)
00380 if (item->type() != type)
00381 return false;
00382
00383 return true;
00384 }
00385
00386