|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tundo.h"
|
|
Toshihiro Shimizu |
890ddd |
#include <deque></deque>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using std::for_each;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void deleteUndo(const TUndo *undo) { delete undo; }
|
|
Toshihiro Shimizu |
890ddd |
void callUndo(const TUndo *undo) { undo->undo(); }
|
|
Toshihiro Shimizu |
890ddd |
void callRedo(const TUndo *undo) { undo->redo(); }
|
|
Toshihiro Shimizu |
890ddd |
// void callRepeat(const TUndo* undo) {undo->repeat(); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class TUndoBlock : public TUndo
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
vector<tundo *=""> m_undos;</tundo>
|
|
Toshihiro Shimizu |
890ddd |
typedef std::vector<tundo *="">::const_iterator Iterator;</tundo>
|
|
Toshihiro Shimizu |
890ddd |
typedef std::vector<tundo *="">::const_reverse_iterator ReverseIterator;</tundo>
|
|
Toshihiro Shimizu |
890ddd |
mutable bool m_deleted, m_undoing;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
TUndoBlock() : m_deleted(false), m_undoing(false) {}
|
|
Toshihiro Shimizu |
890ddd |
~TUndoBlock()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(m_undoing == false);
|
|
Toshihiro Shimizu |
890ddd |
assert(m_deleted == false);
|
|
Toshihiro Shimizu |
890ddd |
m_deleted = true;
|
|
Toshihiro Shimizu |
890ddd |
for_each(m_undos.begin(), m_undos.end(), deleteUndo);
|
|
Toshihiro Shimizu |
890ddd |
m_undos.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int getSize() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int size = sizeof(*this);
|
|
Toshihiro Shimizu |
890ddd |
for (Iterator cit = m_undos.begin(); cit != m_undos.end(); ++cit)
|
|
Toshihiro Shimizu |
890ddd |
size += (*cit)->getSize();
|
|
Toshihiro Shimizu |
890ddd |
size += (m_undos.capacity() - m_undos.size()) * sizeof(TUndo *);
|
|
Toshihiro Shimizu |
890ddd |
return size;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
int getUndoCount() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return (int)m_undos.size();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
void setLast()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
for (UINT i = 1; i < m_undos.size(); i++)
|
|
Toshihiro Shimizu |
890ddd |
m_undos[i]->m_isLastInBlock = false;
|
|
Toshihiro Shimizu |
890ddd |
m_undos[0]->m_isLastInBlock = true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void undo() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(!m_deleted);
|
|
Toshihiro Shimizu |
890ddd |
assert(!m_undoing);
|
|
Toshihiro Shimizu |
890ddd |
m_undoing = true;
|
|
Toshihiro Shimizu |
890ddd |
//VERSIONE CORRETTA
|
|
Toshihiro Shimizu |
890ddd |
for_each(m_undos.rbegin(), m_undos.rend(), callUndo);
|
|
Toshihiro Shimizu |
890ddd |
//VERSIONE SBAGLIATA
|
|
Toshihiro Shimizu |
890ddd |
//for_each(m_undos.begin(), m_undos.end(), callUndo);
|
|
Toshihiro Shimizu |
890ddd |
m_undoing = false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
void redo() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(!m_deleted);
|
|
Toshihiro Shimizu |
890ddd |
//VERSIONE CORRETTA
|
|
Toshihiro Shimizu |
890ddd |
for_each(m_undos.begin(), m_undos.end(), callRedo);
|
|
Toshihiro Shimizu |
890ddd |
//VERSIONE SBAGLIATA
|
|
Toshihiro Shimizu |
890ddd |
//for_each(m_undos.rbegin(), m_undos.rend(), callRedo);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//void repeat() const {
|
|
Toshihiro Shimizu |
890ddd |
// for_each(m_undos.begin(), m_undos.end(), callRepeat);
|
|
Toshihiro Shimizu |
890ddd |
//}
|
|
Toshihiro Shimizu |
890ddd |
void onAdd() {}
|
|
Toshihiro Shimizu |
890ddd |
void add(TUndo *undo)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
undo->m_isLastInBlock = true;
|
|
Toshihiro Shimizu |
890ddd |
m_undos.push_back(undo);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void popUndo(int n)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (n == -1)
|
|
Toshihiro Shimizu |
890ddd |
n = m_undos.size();
|
|
Toshihiro Shimizu |
890ddd |
if (m_undos.empty() || n <= 0)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
while (n > 0 && !m_undos.empty()) {
|
|
Toshihiro Shimizu |
890ddd |
TUndo *undo = m_undos.back();
|
|
Toshihiro Shimizu |
890ddd |
m_undos.pop_back();
|
|
Toshihiro Shimizu |
890ddd |
delete undo;
|
|
Toshihiro Shimizu |
890ddd |
n--;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
virtual QString getHistoryString()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_undos.empty())
|
|
Toshihiro Shimizu |
890ddd |
return TUndo::getHistoryString();
|
|
Toshihiro Shimizu |
890ddd |
else if ((int)m_undos.size() == 1)
|
|
Toshihiro Shimizu |
890ddd |
return m_undos.back()->getHistoryString();
|
|
Toshihiro Shimizu |
890ddd |
else {
|
|
Toshihiro Shimizu |
890ddd |
return QString("%1 etc..").arg(m_undos.back()->getHistoryString());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
virtual int getHistoryType()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_undos.empty())
|
|
Toshihiro Shimizu |
890ddd |
return TUndo::getHistoryType();
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
return m_undos.back()->getHistoryType();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef std::deque<tundo *=""> UndoList;</tundo>
|
|
Toshihiro Shimizu |
890ddd |
typedef UndoList::iterator UndoListIterator;
|
|
Toshihiro Shimizu |
890ddd |
typedef UndoList::const_iterator UndoListConstIterator;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct TUndoManager::TUndoManagerImp {
|
|
Toshihiro Shimizu |
890ddd |
UndoList m_undoList;
|
|
Toshihiro Shimizu |
890ddd |
UndoListIterator m_current;
|
|
Toshihiro Shimizu |
890ddd |
bool m_skipped;
|
|
Toshihiro Shimizu |
890ddd |
int m_undoMemorySize; // in bytes
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
vector<tundoblock *=""> m_blockStack;</tundoblock>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
TUndoManagerImp() : m_skipped(false), m_undoMemorySize(0) { m_current = m_undoList.end(); }
|
|
Toshihiro Shimizu |
890ddd |
~TUndoManagerImp() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void add(TUndo *undo);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
static struct ManagerPtr {
|
|
Toshihiro Shimizu |
890ddd |
TUndoManager *m_ptr;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
ManagerPtr() : m_ptr(0) {}
|
|
Toshihiro Shimizu |
890ddd |
~ManagerPtr()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_ptr)
|
|
Toshihiro Shimizu |
890ddd |
delete m_ptr;
|
|
Toshihiro Shimizu |
890ddd |
m_ptr = 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} theManager;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Toshihiro Shimizu |
890ddd |
void doAdd(TUndo *undo);
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TUndoManager::TUndoManagerImp::ManagerPtr TUndoManager::TUndoManagerImp::theManager;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TUndoManager *TUndoManager::manager()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!TUndoManagerImp::theManager.m_ptr)
|
|
Toshihiro Shimizu |
890ddd |
TUndoManagerImp::theManager.m_ptr = new TUndoManager;
|
|
Toshihiro Shimizu |
890ddd |
return TUndoManagerImp::theManager.m_ptr;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TUndoManager::TUndoManager()
|
|
Toshihiro Shimizu |
890ddd |
: m_imp(new TUndoManagerImp)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// cout << "Creato undo manager" << endl;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TUndoManager::~TUndoManager()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//cout << "Distrutto undo manager" << endl;
|
|
Toshihiro Shimizu |
890ddd |
assert(m_imp->m_blockStack.empty());
|
|
Toshihiro Shimizu |
890ddd |
reset();
|
|
Toshihiro Shimizu |
890ddd |
delete m_imp;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TUndoManager::TUndoManagerImp::add(TUndo *undo)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(undo);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!m_blockStack.empty()) {
|
|
Toshihiro Shimizu |
890ddd |
assert(m_current == m_undoList.end());
|
|
Toshihiro Shimizu |
890ddd |
m_blockStack.back()->add(undo);
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
doAdd(undo);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TUndoManager::TUndoManagerImp::doAdd(TUndo *undo)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_current != m_undoList.end()) {
|
|
Toshihiro Shimizu |
890ddd |
for_each(m_current, m_undoList.end(), deleteUndo);
|
|
Toshihiro Shimizu |
890ddd |
m_undoList.erase(m_current, m_undoList.end());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int i, memorySize = 0, count = m_undoList.size();
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < count; i++)
|
|
Toshihiro Shimizu |
890ddd |
memorySize += m_undoList[i]->getSize();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
while (count > 100 || (count != 0 && memorySize + undo->getSize() > m_undoMemorySize)) //20MB
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
--count;
|
|
Toshihiro Shimizu |
890ddd |
TUndo *undo = m_undoList.front();
|
|
Toshihiro Shimizu |
890ddd |
m_undoList.pop_front();
|
|
Toshihiro Shimizu |
890ddd |
memorySize -= undo->getSize();
|
|
Toshihiro Shimizu |
890ddd |
delete undo;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
undo->m_isLastInBlock = true;
|
|
Toshihiro Shimizu |
890ddd |
m_undoList.push_back(undo);
|
|
Toshihiro Shimizu |
890ddd |
m_current = m_undoList.end();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TUndoManager::beginBlock()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_imp->m_current != m_imp->m_undoList.end()) {
|
|
Toshihiro Shimizu |
890ddd |
for_each(m_imp->m_current, m_imp->m_undoList.end(), deleteUndo);
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_undoList.erase(m_imp->m_current, m_imp->m_undoList.end());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TUndoBlock *undoBlock = new TUndoBlock;
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_blockStack.push_back(undoBlock);
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_current = m_imp->m_undoList.end();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TUndoManager::endBlock()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//vogliamo fare anche resize del vector ???
|
|
Toshihiro Shimizu |
890ddd |
assert(m_imp->m_blockStack.empty() == false);
|
|
Toshihiro Shimizu |
890ddd |
TUndoBlock *undoBlock = m_imp->m_blockStack.back();
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_blockStack.pop_back();
|
|
Toshihiro Shimizu |
890ddd |
if (undoBlock->getUndoCount() > 0) {
|
|
Toshihiro Shimizu |
890ddd |
undoBlock->setLast();
|
|
Toshihiro Shimizu |
890ddd |
m_imp->add(undoBlock);
|
|
Toshihiro Shimizu |
890ddd |
emit historyChanged();
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
delete undoBlock;
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_current = m_imp->m_undoList.end();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool TUndoManager::undo()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(m_imp->m_blockStack.empty());
|
|
Toshihiro Shimizu |
890ddd |
UndoListIterator &it = m_imp->m_current;
|
|
Toshihiro Shimizu |
890ddd |
if (it != m_imp->m_undoList.begin()) {
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_skipped = false;
|
|
Toshihiro Shimizu |
890ddd |
--it;
|
|
Toshihiro Shimizu |
890ddd |
(*it)->undo();
|
|
Toshihiro Shimizu |
890ddd |
emit historyChanged();
|
|
Toshihiro Shimizu |
890ddd |
if (m_imp->m_skipped) {
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_skipped = false;
|
|
Toshihiro Shimizu |
890ddd |
return undo();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool TUndoManager::redo()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(m_imp->m_blockStack.empty());
|
|
Toshihiro Shimizu |
890ddd |
UndoListIterator &it = m_imp->m_current;
|
|
Toshihiro Shimizu |
890ddd |
if (it != m_imp->m_undoList.end()) {
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_skipped = false;
|
|
Toshihiro Shimizu |
890ddd |
(*it)->redo();
|
|
Toshihiro Shimizu |
890ddd |
++it;
|
|
Toshihiro Shimizu |
890ddd |
emit historyChanged();
|
|
Toshihiro Shimizu |
890ddd |
if (m_imp->m_skipped) {
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_skipped = false;
|
|
Toshihiro Shimizu |
890ddd |
return redo();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//repeat e' come redo ma non sposta il puntatore al corrente
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
void TUndoManager::repeat()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(m_imp->m_blockStack.empty());
|
|
Toshihiro Shimizu |
890ddd |
UndoListIterator &it = m_imp->m_current;
|
|
Toshihiro Shimizu |
890ddd |
if (it != m_imp->m_undoList.end())
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
(*it)->repeat();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TUndoManager::skip()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_skipped = true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TUndoManager::setUndoMemorySize(int memorySyze)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_undoMemorySize = 1048576 * memorySyze;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TUndoManager::add(TUndo *undo)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(undo);
|
|
Toshihiro Shimizu |
890ddd |
if (!undo)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_imp->add(undo);
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT historyChanged();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
undo->onAdd();
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT somethingChanged();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TUndoManager::reset()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(m_imp->m_blockStack.empty());
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_blockStack.clear();
|
|
Toshihiro Shimizu |
890ddd |
UndoList &lst = m_imp->m_undoList;
|
|
Toshihiro Shimizu |
890ddd |
for_each(lst.begin(), lst.end(), deleteUndo);
|
|
Toshihiro Shimizu |
890ddd |
lst.clear();
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_current = m_imp->m_undoList.end();
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT historyChanged();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TUndoManager::popUndo(int n, bool forward)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!forward) {
|
|
Toshihiro Shimizu |
890ddd |
if (m_imp->m_blockStack.empty()) {
|
|
Toshihiro Shimizu |
890ddd |
if (n == -1) {
|
|
Toshihiro Shimizu |
890ddd |
UndoListIterator start = m_imp->m_undoList.begin();
|
|
Toshihiro Shimizu |
890ddd |
n = 0;
|
|
Toshihiro Shimizu |
890ddd |
while (start != m_imp->m_current)
|
|
Toshihiro Shimizu |
890ddd |
++n;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
if (m_imp->m_undoList.empty() || n <= 0)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
if (m_imp->m_current == m_imp->m_undoList.end()) {
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < n && m_imp->m_current != m_imp->m_undoList.begin(); i++) {
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_current--;
|
|
Toshihiro Shimizu |
890ddd |
delete (*m_imp->m_current);
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_undoList.erase(m_imp->m_current);
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_current = m_imp->m_undoList.end();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
TUndo *undo = *m_imp->m_current;
|
|
Toshihiro Shimizu |
890ddd |
UndoListIterator start, end = m_imp->m_current;
|
|
Toshihiro Shimizu |
890ddd |
if (end == m_imp->m_undoList.begin())
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < n && m_imp->m_current != m_imp->m_undoList.begin(); i++)
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_current--;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
start = m_imp->m_current;
|
|
Toshihiro Shimizu |
890ddd |
UndoListIterator _end = end;
|
|
Toshihiro Shimizu |
890ddd |
while (_end != start) {
|
|
Toshihiro Shimizu |
890ddd |
_end--;
|
|
Toshihiro Shimizu |
890ddd |
delete (*_end);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_undoList.erase(start, end);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_current = m_imp->m_undoList.begin();
|
|
Toshihiro Shimizu |
890ddd |
while (*m_imp->m_current != undo)
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_current++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_blockStack.back()->popUndo(n);
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_imp->m_current == m_imp->m_undoList.end())
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
if (m_imp->m_blockStack.empty()) {
|
|
Toshihiro Shimizu |
890ddd |
UndoListIterator end, start = m_imp->m_current++;
|
|
Toshihiro Shimizu |
890ddd |
if (n == -1)
|
|
Toshihiro Shimizu |
890ddd |
end = m_imp->m_undoList.end();
|
|
Toshihiro Shimizu |
890ddd |
else {
|
|
Toshihiro Shimizu |
890ddd |
UndoListIterator it = start;
|
|
Toshihiro Shimizu |
890ddd |
end = it;
|
|
Toshihiro Shimizu |
890ddd |
int i = 0;
|
|
Toshihiro Shimizu |
890ddd |
while (i != n && end != m_imp->m_undoList.end()) {
|
|
Toshihiro Shimizu |
890ddd |
++end;
|
|
Toshihiro Shimizu |
890ddd |
i++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
for_each(start, end, deleteUndo);
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_undoList.erase(start, end);
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_current = m_imp->m_undoList.end();
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
m_imp->m_blockStack.back()->popUndo(n);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int TUndoManager::getHistoryCount()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return (int)m_imp->m_undoList.size();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int TUndoManager::getCurrentHistoryIndex()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int index = 0;
|
|
Toshihiro Shimizu |
890ddd |
UndoListIterator it = m_imp->m_undoList.begin();
|
|
Toshihiro Shimizu |
890ddd |
while (1) {
|
|
Toshihiro Shimizu |
890ddd |
if (it == m_imp->m_current)
|
|
Toshihiro Shimizu |
890ddd |
return index;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (it == m_imp->m_undoList.end())
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
index++;
|
|
Toshihiro Shimizu |
890ddd |
it++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TUndo *TUndoManager::getUndoItem(int index)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (index > (int)m_imp->m_undoList.size() || index <= 0)
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return m_imp->m_undoList.at(index - 1);
|
|
Toshihiro Shimizu |
890ddd |
}
|