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_selection(-1, -1, -1, -1)
00246 , m_cursor(-1, -1)
00247 {
00248 }
00249
00250 KateUndoGroup::~KateUndoGroup ()
00251 {
00252 qDeleteAll (m_items);
00253 }
00254
00255 void KateUndoGroup::undo ()
00256 {
00257 if (m_items.isEmpty())
00258 return;
00259
00260 m_doc->editStart (false);
00261
00262 for (int i=m_items.size()-1; i >= 0; --i)
00263 m_items[i]->undo(m_doc);
00264
00265 if (KateView *view = m_doc->activeKateView()) {
00266 if (m_selection.isValid())
00267 view->setSelection(m_selection);
00268 if (m_cursor.isValid())
00269 view->editSetCursor(m_cursor);
00270 }
00271
00272 m_doc->editEnd ();
00273 }
00274
00275 void KateUndoGroup::redo ()
00276 {
00277 if (m_items.isEmpty())
00278 return;
00279
00280 m_doc->editStart (false);
00281
00282 for (int i=0; i < m_items.size(); ++i)
00283 m_items[i]->redo(m_doc);
00284
00285 if (KateView *view = m_doc->activeKateView()) {
00286 if (m_selection.isValid())
00287 view->setSelection(m_selection);
00288 if (m_cursor.isValid())
00289 view->editSetCursor(m_cursor);
00290 }
00291
00292 m_doc->editEnd ();
00293 }
00294
00295 void KateUndoGroup::addItem (KateUndoGroup::UndoType type, uint line, uint col, uint len, const QString &text)
00296 {
00297 addItem(new KateUndo(type, line, col, len, text));
00298 }
00299
00300 void KateUndoGroup::setSelection(const KTextEditor::Range &selection)
00301 {
00302 if (!m_selection.isValid())
00303 m_selection = selection;
00304 }
00305
00306 void KateUndoGroup::setCursorPosition(const KTextEditor::Cursor &cursor)
00307 {
00308 if (!m_cursor.isValid())
00309 m_cursor = cursor;
00310 }
00311
00312 void KateUndoGroup::addItem(KateUndo* u)
00313 {
00314 if (!u->isValid())
00315 delete u;
00316 else if (!m_items.isEmpty() && m_items.last()->merge(u))
00317 delete u;
00318 else
00319 m_items.append(u);
00320 }
00321
00322 bool KateUndoGroup::merge(KateUndoGroup* newGroup,bool complex)
00323 {
00324 if (m_safePoint) return false;
00325 if (newGroup->isOnlyType(singleType()) || complex) {
00326
00327 KateUndo* u = newGroup->m_items.isEmpty() ? 0 : newGroup->m_items.takeFirst ();
00328 while (u) {
00329 addItem(u);
00330 u = newGroup->m_items.isEmpty() ? 0 : newGroup->m_items.takeFirst ();
00331 }
00332 if (newGroup->m_safePoint) safePoint();
00333 return true;
00334 }
00335 return false;
00336 }
00337
00338 void KateUndoGroup::safePoint (bool safePoint)
00339 {
00340 m_safePoint=safePoint;
00341 }
00342
00343 KateUndoGroup::UndoType KateUndoGroup::singleType() const
00344 {
00345 KateUndoGroup::UndoType ret = editInvalid;
00346
00347 Q_FOREACH(const KateUndo *item, m_items) {
00348 if (ret == editInvalid)
00349 ret = item->type();
00350 else if (ret != item->type())
00351 return editInvalid;
00352 }
00353
00354 return ret;
00355 }
00356
00357 bool KateUndoGroup::isOnlyType(KateUndoGroup::UndoType type) const
00358 {
00359 if (type == editInvalid) return false;
00360
00361 Q_FOREACH(const KateUndo *item, m_items)
00362 if (item->type() != type)
00363 return false;
00364
00365 return true;
00366 }
00367
00368