forked from qt-creator/qt-creator
Start with own undo/redo without depending on QTextEdit/QPlainTextEdit's undo/redo.
This commit is contained in:
@@ -102,6 +102,14 @@ enum SubSubMode
|
|||||||
static const QString ConfigStartOfLine = "startofline";
|
static const QString ConfigStartOfLine = "startofline";
|
||||||
static const QString ConfigOn = "on";
|
static const QString ConfigOn = "on";
|
||||||
|
|
||||||
|
struct EditOperation
|
||||||
|
{
|
||||||
|
enum EditType { EditInsert, EditRemove } m_type;
|
||||||
|
int m_position;
|
||||||
|
int m_length;
|
||||||
|
QString m_data;
|
||||||
|
};
|
||||||
|
|
||||||
class FakeVimHandler::Private
|
class FakeVimHandler::Private
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -167,9 +175,6 @@ public:
|
|||||||
QString m_mvcount;
|
QString m_mvcount;
|
||||||
QString m_opcount;
|
QString m_opcount;
|
||||||
|
|
||||||
QStack<QString> m_undoStack;
|
|
||||||
QStack<QString> m_redoStack;
|
|
||||||
|
|
||||||
bool m_fakeEnd;
|
bool m_fakeEnd;
|
||||||
|
|
||||||
QWidget *editor();
|
QWidget *editor();
|
||||||
@@ -185,6 +190,14 @@ public:
|
|||||||
bool m_lastSearchForward;
|
bool m_lastSearchForward;
|
||||||
QString m_lastInsertion;
|
QString m_lastInsertion;
|
||||||
|
|
||||||
|
// undo handling
|
||||||
|
void recordInsert(int position, const QString &data);
|
||||||
|
void recordRemove(int position, int length);
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
QStack<EditOperation> m_undoStack;
|
||||||
|
QStack<EditOperation> m_redoStack;
|
||||||
|
|
||||||
// extra data for '.'
|
// extra data for '.'
|
||||||
QString m_dotCount;
|
QString m_dotCount;
|
||||||
QString m_dotCommand;
|
QString m_dotCommand;
|
||||||
@@ -433,11 +446,11 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
|
|||||||
} else if (key == 'a') {
|
} else if (key == 'a') {
|
||||||
m_mode = InsertMode;
|
m_mode = InsertMode;
|
||||||
m_lastInsertion.clear();
|
m_lastInsertion.clear();
|
||||||
m_tc.beginEditBlock();
|
///m_tc.beginEditBlock();
|
||||||
m_tc.movePosition(Right, MoveAnchor, 1);
|
m_tc.movePosition(Right, MoveAnchor, 1);
|
||||||
} else if (key == 'A') {
|
} else if (key == 'A') {
|
||||||
m_mode = InsertMode;
|
m_mode = InsertMode;
|
||||||
m_tc.beginEditBlock();
|
///m_tc.beginEditBlock();
|
||||||
m_tc.movePosition(EndOfLine, MoveAnchor);
|
m_tc.movePosition(EndOfLine, MoveAnchor);
|
||||||
m_lastInsertion.clear();
|
m_lastInsertion.clear();
|
||||||
} else if (key == 'b') {
|
} else if (key == 'b') {
|
||||||
@@ -448,7 +461,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
|
|||||||
finishMovement();
|
finishMovement();
|
||||||
} else if (key == 'c') {
|
} else if (key == 'c') {
|
||||||
m_submode = ChangeSubMode;
|
m_submode = ChangeSubMode;
|
||||||
m_tc.beginEditBlock();
|
///m_tc.beginEditBlock();
|
||||||
} else if (key == 'C') {
|
} else if (key == 'C') {
|
||||||
m_submode = ChangeSubMode;
|
m_submode = ChangeSubMode;
|
||||||
//m_tc.beginEditBlock();
|
//m_tc.beginEditBlock();
|
||||||
@@ -501,7 +514,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
|
|||||||
finishMovement();
|
finishMovement();
|
||||||
} else if (key == 'i') {
|
} else if (key == 'i') {
|
||||||
m_mode = InsertMode;
|
m_mode = InsertMode;
|
||||||
//m_tc.beginEditBlock();
|
///m_tc.beginEditBlock();
|
||||||
m_lastInsertion.clear();
|
m_lastInsertion.clear();
|
||||||
} else if (key == 'I') {
|
} else if (key == 'I') {
|
||||||
m_mode = InsertMode;
|
m_mode = InsertMode;
|
||||||
@@ -510,13 +523,13 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
|
|||||||
else
|
else
|
||||||
moveToFirstNonBlankOnLine();
|
moveToFirstNonBlankOnLine();
|
||||||
m_tc.clearSelection();
|
m_tc.clearSelection();
|
||||||
//m_tc.beginEditBlock();
|
///m_tc.beginEditBlock();
|
||||||
m_lastInsertion.clear();
|
m_lastInsertion.clear();
|
||||||
} else if (key == 'j' || key == Key_Down) {
|
} else if (key == 'j' || key == Key_Down) {
|
||||||
m_tc.movePosition(Down, KeepAnchor, count());
|
m_tc.movePosition(Down, KeepAnchor, count());
|
||||||
finishMovement();
|
finishMovement();
|
||||||
} else if (key == 'J') {
|
} else if (key == 'J') {
|
||||||
m_tc.beginEditBlock();
|
///m_tc.beginEditBlock();
|
||||||
if (m_submode == NoSubMode) {
|
if (m_submode == NoSubMode) {
|
||||||
for (int i = qMax(count(), 2) - 1; --i >= 0; ) {
|
for (int i = qMax(count(), 2) - 1; --i >= 0; ) {
|
||||||
m_tc.movePosition(EndOfLine);
|
m_tc.movePosition(EndOfLine);
|
||||||
@@ -527,7 +540,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
|
|||||||
if (!m_gflag)
|
if (!m_gflag)
|
||||||
m_tc.movePosition(Left, MoveAnchor, 1);
|
m_tc.movePosition(Left, MoveAnchor, 1);
|
||||||
}
|
}
|
||||||
m_tc.endEditBlock();
|
///m_tc.endEditBlock();
|
||||||
} else if (key == 'k' || key == Key_Up) {
|
} else if (key == 'k' || key == Key_Up) {
|
||||||
m_tc.movePosition(Up, KeepAnchor, count());
|
m_tc.movePosition(Up, KeepAnchor, count());
|
||||||
finishMovement();
|
finishMovement();
|
||||||
@@ -576,7 +589,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
|
|||||||
m_tc.movePosition(Left);
|
m_tc.movePosition(Left);
|
||||||
}
|
}
|
||||||
} else if (key == control('r')) {
|
} else if (key == control('r')) {
|
||||||
EDITOR(redo());
|
redo();
|
||||||
} else if (key == 's') {
|
} else if (key == 's') {
|
||||||
m_submode = ChangeSubMode;
|
m_submode = ChangeSubMode;
|
||||||
//m_tc.beginEditBlock();
|
//m_tc.beginEditBlock();
|
||||||
@@ -585,7 +598,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
|
|||||||
m_subsubmode = FtSubSubMode;
|
m_subsubmode = FtSubSubMode;
|
||||||
m_subsubdata = key;
|
m_subsubdata = key;
|
||||||
} else if (key == 'u') {
|
} else if (key == 'u') {
|
||||||
EDITOR(undo());
|
undo();
|
||||||
} else if (key == 'V') {
|
} else if (key == 'V') {
|
||||||
enterVisualLineMode();
|
enterVisualLineMode();
|
||||||
} else if (key == 'w') {
|
} else if (key == 'w') {
|
||||||
@@ -638,11 +651,17 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
|
|||||||
void FakeVimHandler::Private::handleInsertMode(int key, const QString &text)
|
void FakeVimHandler::Private::handleInsertMode(int key, const QString &text)
|
||||||
{
|
{
|
||||||
if (key == Key_Escape) {
|
if (key == Key_Escape) {
|
||||||
for (int i = 1; i < count(); ++i)
|
// start with '1', as one instance was already physically inserted
|
||||||
|
// while typing
|
||||||
|
QString data = m_lastInsertion;
|
||||||
|
for (int i = 1; i < count(); ++i) {
|
||||||
m_tc.insertText(m_lastInsertion);
|
m_tc.insertText(m_lastInsertion);
|
||||||
|
data += m_lastInsertion;
|
||||||
|
}
|
||||||
|
recordInsert(m_tc.position() - m_lastInsertion.size(), data);
|
||||||
m_tc.movePosition(Left, MoveAnchor, qMin(1, leftDist()));
|
m_tc.movePosition(Left, MoveAnchor, qMin(1, leftDist()));
|
||||||
m_mode = CommandMode;
|
m_mode = CommandMode;
|
||||||
m_tc.endEditBlock();
|
///m_tc.endEditBlock();
|
||||||
} else if (key == Key_Left) {
|
} else if (key == Key_Left) {
|
||||||
m_tc.movePosition(Left, MoveAnchor, 1);
|
m_tc.movePosition(Left, MoveAnchor, 1);
|
||||||
m_lastInsertion.clear();
|
m_lastInsertion.clear();
|
||||||
@@ -657,7 +676,7 @@ void FakeVimHandler::Private::handleInsertMode(int key, const QString &text)
|
|||||||
m_lastInsertion.clear();
|
m_lastInsertion.clear();
|
||||||
} else if (key == Key_Return) {
|
} else if (key == Key_Return) {
|
||||||
m_tc.insertBlock();
|
m_tc.insertBlock();
|
||||||
m_lastInsertion.clear();
|
m_lastInsertion += "\n";
|
||||||
} else if (key == Key_Backspace) {
|
} else if (key == Key_Backspace) {
|
||||||
m_tc.deletePreviousChar();
|
m_tc.deletePreviousChar();
|
||||||
m_lastInsertion = m_lastInsertion.left(m_lastInsertion.size() - 1);
|
m_lastInsertion = m_lastInsertion.left(m_lastInsertion.size() - 1);
|
||||||
@@ -1109,6 +1128,73 @@ QWidget *FakeVimHandler::Private::editor()
|
|||||||
: static_cast<QWidget *>(m_plaintextedit);
|
: static_cast<QWidget *>(m_plaintextedit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FakeVimHandler::Private::undo()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
EDITOR(undo());
|
||||||
|
#else
|
||||||
|
if (m_undoStack.isEmpty())
|
||||||
|
return;
|
||||||
|
EditOperation op = m_undoStack.pop();
|
||||||
|
QTextCursor tc = m_tc;
|
||||||
|
tc.setPosition(op.m_position, MoveAnchor);
|
||||||
|
if (op.m_type == EditOperation::EditInsert) {
|
||||||
|
tc.setPosition(op.m_position + op.m_length, KeepAnchor);
|
||||||
|
tc.deleteChar();
|
||||||
|
} else {
|
||||||
|
tc.insertText(op.m_data);
|
||||||
|
}
|
||||||
|
m_redoStack.push(op);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FakeVimHandler::Private::redo()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
EDITOR(redo());
|
||||||
|
#else
|
||||||
|
if (m_redoStack.isEmpty())
|
||||||
|
return;
|
||||||
|
EditOperation op = m_redoStack.pop();
|
||||||
|
QTextCursor tc = m_tc;
|
||||||
|
tc.setPosition(op.m_position, MoveAnchor);
|
||||||
|
if (op.m_type == EditOperation::EditInsert) {
|
||||||
|
tc.insertText(op.m_data);
|
||||||
|
} else {
|
||||||
|
tc.setPosition(op.m_position + op.m_length, KeepAnchor);
|
||||||
|
tc.deleteChar();
|
||||||
|
}
|
||||||
|
m_undoStack.push(op);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FakeVimHandler::Private::recordInsert(int position, const QString &data)
|
||||||
|
{
|
||||||
|
qDebug() << "INSERT AT " << position << " DATA: " << data;
|
||||||
|
EditOperation op;
|
||||||
|
op.m_type = EditOperation::EditInsert;
|
||||||
|
op.m_position = position;
|
||||||
|
op.m_length = data.size();
|
||||||
|
op.m_data = data;
|
||||||
|
m_undoStack.push(op);
|
||||||
|
m_redoStack.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FakeVimHandler::Private::recordRemove(int position, int length)
|
||||||
|
{
|
||||||
|
qDebug() << "REMOVE AT " << position << " LEN: " << length;
|
||||||
|
QTextCursor tc = m_tc;
|
||||||
|
tc.setPosition(position, MoveAnchor);
|
||||||
|
tc.setPosition(position + length, KeepAnchor);
|
||||||
|
EditOperation op;
|
||||||
|
op.m_type = EditOperation::EditRemove;
|
||||||
|
op.m_position = position;
|
||||||
|
op.m_length = length;
|
||||||
|
op.m_data = tc.selection().toPlainText();
|
||||||
|
m_undoStack.push(op);
|
||||||
|
m_redoStack.clear();
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// FakeVimHandler
|
// FakeVimHandler
|
||||||
|
|||||||
Reference in New Issue
Block a user