diff options
Diffstat (limited to 'src/commands.cpp')
-rw-r--r-- | src/commands.cpp | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/src/commands.cpp b/src/commands.cpp new file mode 100644 index 0000000..5b99cbf --- /dev/null +++ b/src/commands.cpp @@ -0,0 +1,168 @@ +#include "commands.h" +#include <QUndoCommand> + + +// Helper class to store single byte commands +class CharCommand : public QUndoCommand +{ +public: + enum CCmd {insert, removeAt, overwrite}; + + CharCommand(Chunks * chunks, CCmd cmd, qint64 charPos, char newChar, + QUndoCommand *parent=0); + + void undo(); + void redo(); + bool mergeWith(const QUndoCommand *command); + int id() const { return 1234; } + +private: + Chunks * _chunks; + qint64 _charPos; + bool _wasChanged; + char _newChar; + char _oldChar; + CCmd _cmd; +}; + +CharCommand::CharCommand(Chunks * chunks, CCmd cmd, qint64 charPos, char newChar, QUndoCommand *parent) + : QUndoCommand(parent) + , _chunks(chunks) + , _charPos(charPos) + , _wasChanged(false) + , _newChar(newChar) + , _oldChar('\0') + , _cmd(cmd) +{ +} + +bool CharCommand::mergeWith(const QUndoCommand *command) +{ + const CharCommand *nextCommand = static_cast<const CharCommand *>(command); + bool result = false; + + if (_cmd != CharCommand::removeAt) + { + if (nextCommand->_cmd == overwrite) + if (nextCommand->_charPos == _charPos) + { + _newChar = nextCommand->_newChar; + result = true; + } + } + return result; +} + +void CharCommand::undo() +{ + switch (_cmd) + { + case insert: + _chunks->removeAt(_charPos); + break; + case overwrite: + _chunks->overwrite(_charPos, _oldChar); + _chunks->setDataChanged(_charPos, _wasChanged); + break; + case removeAt: + _chunks->insert(_charPos, _oldChar); + _chunks->setDataChanged(_charPos, _wasChanged); + break; + } +} + +void CharCommand::redo() +{ + switch (_cmd) + { + case insert: + _chunks->insert(_charPos, _newChar); + break; + case overwrite: + _oldChar = (*_chunks)[_charPos]; + _wasChanged = _chunks->dataChanged(_charPos); + _chunks->overwrite(_charPos, _newChar); + break; + case removeAt: + _oldChar = (*_chunks)[_charPos]; + _wasChanged = _chunks->dataChanged(_charPos); + _chunks->removeAt(_charPos); + break; + } +} + +UndoStack::UndoStack(Chunks * chunks, QObject * parent) + : QUndoStack(parent) +{ + _chunks = chunks; + _parent = parent; + this->setUndoLimit(1000); +} + +void UndoStack::insert(qint64 pos, char c) +{ + if ((pos >= 0) && (pos <= _chunks->size())) + { + QUndoCommand *cc = new CharCommand(_chunks, CharCommand::insert, pos, c); + this->push(cc); + } +} + +void UndoStack::insert(qint64 pos, const QByteArray &ba) +{ + if ((pos >= 0) && (pos <= _chunks->size())) + { + QString txt = QString(tr("Inserting %1 bytes")).arg(ba.size()); + beginMacro(txt); + for (int idx=0; idx < ba.size(); idx++) + { + QUndoCommand *cc = new CharCommand(_chunks, CharCommand::insert, pos + idx, ba.at(idx)); + this->push(cc); + } + endMacro(); + } +} + +void UndoStack::removeAt(qint64 pos, qint64 len) +{ + if ((pos >= 0) && (pos < _chunks->size())) + { + if (len==1) + { + QUndoCommand *cc = new CharCommand(_chunks, CharCommand::removeAt, pos, char(0)); + this->push(cc); + } + else + { + QString txt = QString(tr("Delete %1 chars")).arg(len); + beginMacro(txt); + for (qint64 cnt=0; cnt<len; cnt++) + { + QUndoCommand *cc = new CharCommand(_chunks, CharCommand::removeAt, pos, char(0)); + push(cc); + } + endMacro(); + } + } +} + +void UndoStack::overwrite(qint64 pos, char c) +{ + if ((pos >= 0) && (pos < _chunks->size())) + { + QUndoCommand *cc = new CharCommand(_chunks, CharCommand::overwrite, pos, c); + this->push(cc); + } +} + +void UndoStack::overwrite(qint64 pos, int len, const QByteArray &ba) +{ + if ((pos >= 0) && (pos < _chunks->size())) + { + QString txt = QString(tr("Overwrite %1 chars")).arg(len); + beginMacro(txt); + removeAt(pos, len); + insert(pos, ba); + endMacro(); + } +} |