summaryrefslogtreecommitdiffstats
path: root/kolourpaint/kpcommandhistory.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit47d455dd55be855e4cc691c32f687f723d9247ee (patch)
tree52e236aaa2576bdb3840ebede26619692fed6d7d /kolourpaint/kpcommandhistory.cpp
downloadtdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.tar.gz
tdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegraphics@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kolourpaint/kpcommandhistory.cpp')
-rw-r--r--kolourpaint/kpcommandhistory.cpp939
1 files changed, 939 insertions, 0 deletions
diff --git a/kolourpaint/kpcommandhistory.cpp b/kolourpaint/kpcommandhistory.cpp
new file mode 100644
index 00000000..33010918
--- /dev/null
+++ b/kolourpaint/kpcommandhistory.cpp
@@ -0,0 +1,939 @@
+
+/*
+ Copyright (c) 2003,2004,2005 Clarence Dang <[email protected]>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#define DEBUG_KP_COMMAND_HISTORY 0
+
+
+#include <kpcommandhistory.h>
+
+#include <limits.h>
+
+#include <qdatetime.h>
+
+#include <kactionclasses.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kstdaccel.h>
+#include <kstdaction.h>
+
+#include <kpdefs.h>
+#include <kpdocument.h>
+#include <kpmainwindow.h>
+#include <kptool.h>
+
+
+//template <typename T>
+static void clearPointerList (QValueList <kpCommand *> *listPtr)
+{
+ if (!listPtr)
+ return;
+
+ for (QValueList <kpCommand *>::iterator it = listPtr->begin ();
+ it != listPtr->end ();
+ it++)
+ {
+ delete (*it);
+ }
+
+ listPtr->clear ();
+}
+
+
+//
+// kpCommand
+//
+
+kpCommand::kpCommand (kpMainWindow *mainWindow)
+ : m_mainWindow (mainWindow)
+{
+ if (!mainWindow)
+ kdError () << "kpCommand::kpCommand() passed 0 mainWindow" << endl;
+}
+
+kpCommand::~kpCommand ()
+{
+}
+
+
+// protected
+kpMainWindow *kpCommand::mainWindow () const
+{
+ return m_mainWindow;
+}
+
+
+// protected
+kpDocument *kpCommand::document () const
+{
+ return m_mainWindow ? m_mainWindow->document () : 0;
+}
+
+// protected
+kpSelection *kpCommand::selection () const
+{
+ kpDocument *doc = document ();
+ if (!doc)
+ return 0;
+
+ return doc->selection ();
+}
+
+
+// protected
+kpViewManager *kpCommand::viewManager () const
+{
+ return m_mainWindow ? m_mainWindow->viewManager () : 0;
+}
+
+
+//
+// kpNamedCommand
+//
+
+kpNamedCommand::kpNamedCommand (const QString &name, kpMainWindow *mainWindow)
+ : kpCommand (mainWindow),
+ m_name (name)
+{
+}
+
+kpNamedCommand::~kpNamedCommand ()
+{
+}
+
+
+// public virtual [base kpCommand]
+QString kpNamedCommand::name () const
+{
+ return m_name;
+}
+
+
+//
+// kpMacroCommand
+//
+
+struct kpMacroCommandPrivate
+{
+};
+
+kpMacroCommand::kpMacroCommand (const QString &name, kpMainWindow *mainWindow)
+ : kpNamedCommand (name, mainWindow),
+ d (new kpMacroCommandPrivate ())
+{
+}
+
+kpMacroCommand::~kpMacroCommand ()
+{
+ clearPointerList (&m_commandList);
+ delete d;
+}
+
+
+// public virtual [base kpCommand]
+int kpMacroCommand::size () const
+{
+#if DEBUG_KP_COMMAND_HISTORY && 0
+ kdDebug () << "kpMacroCommand::size()" << endl;
+#endif
+ int s = 0;
+
+#if DEBUG_KP_COMMAND_HISTORY && 0
+ kdDebug () << "\tcalculating:" << endl;
+#endif
+ for (QValueList <kpCommand *>::const_iterator it = m_commandList.begin ();
+ it != m_commandList.end ();
+ it++)
+ {
+ #if DEBUG_KP_COMMAND_HISTORY && 0
+ kdDebug () << "\t\tcurrentSize=" << s << " + "
+ << (*it)->name () << ".size=" << (*it)->size ()
+ << endl;
+ #endif
+ if (s > INT_MAX - (*it)->size ())
+ {
+ #if DEBUG_KP_COMMAND_HISTORY && 0
+ kdDebug () << "\t\t\toverflow" << endl;
+ #endif
+ s = INT_MAX;
+ break;
+ }
+ else
+ {
+ s += (*it)->size ();
+ }
+ }
+
+#if DEBUG_KP_COMMAND_HISTORY && 0
+ kdDebug () << "\treturning " << s << endl;
+#endif
+ return s;
+}
+
+
+// public virtual [base kpCommand]
+void kpMacroCommand::execute ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpMacroCommand::execute()" << endl;
+#endif
+ for (QValueList <kpCommand *>::const_iterator it = m_commandList.begin ();
+ it != m_commandList.end ();
+ it++)
+ {
+ #if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\texecuting " << (*it)->name () << endl;
+ #endif
+ (*it)->execute ();
+ }
+}
+
+// public virtual [base kpCommand]
+void kpMacroCommand::unexecute ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpMacroCommand::unexecute()" << endl;
+#endif
+ QValueList <kpCommand *>::const_iterator it = m_commandList.end ();
+ it--;
+
+ while (it != m_commandList.end ())
+ {
+ #if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\tunexecuting " << (*it)->name () << endl;
+ #endif
+ (*it)->unexecute ();
+
+ it--;
+ }
+}
+
+
+// public
+void kpMacroCommand::addCommand (kpCommand *command)
+{
+ m_commandList.push_back (command);
+}
+
+
+//
+// kpCommandHistoryBase
+//
+
+struct kpCommandHistoryBasePrivate
+{
+};
+
+
+kpCommandHistoryBase::kpCommandHistoryBase (bool doReadConfig,
+ KActionCollection *ac)
+ : d (new kpCommandHistoryBasePrivate ())
+{
+ m_actionUndo = new KToolBarPopupAction (undoActionText (),
+ QString::fromLatin1 ("undo"),
+ KStdAccel::shortcut (KStdAccel::Undo),
+ this, SLOT (undo ()),
+ ac, KStdAction::name (KStdAction::Undo));
+
+ m_actionRedo = new KToolBarPopupAction (redoActionText (),
+ QString::fromLatin1 ("redo"),
+ KStdAccel::shortcut (KStdAccel::Redo),
+ this, SLOT (redo ()),
+ ac, KStdAction::name (KStdAction::Redo));
+
+
+ m_actionUndo->setEnabled (false);
+ m_actionRedo->setEnabled (false);
+
+
+ connect (m_actionUndo->popupMenu (), SIGNAL (activated (int)),
+ this, SLOT (undoUpToNumber (int)));
+ connect (m_actionRedo->popupMenu (), SIGNAL (activated (int)),
+ this, SLOT (redoUpToNumber (int)));
+
+
+ m_undoMinLimit = 10;
+ m_undoMaxLimit = 500;
+ m_undoMaxLimitSizeLimit = 16 * 1048576;
+
+
+ m_documentRestoredPosition = 0;
+
+
+ if (doReadConfig)
+ readConfig ();
+}
+
+kpCommandHistoryBase::~kpCommandHistoryBase ()
+{
+ clearPointerList (&m_undoCommandList);
+ clearPointerList (&m_redoCommandList);
+
+ delete d;
+}
+
+
+// public
+int kpCommandHistoryBase::undoLimit () const
+{
+ return undoMinLimit ();
+}
+
+// public
+void kpCommandHistoryBase::setUndoLimit (int limit)
+{
+ setUndoMinLimit (limit);
+}
+
+
+// public
+int kpCommandHistoryBase::undoMinLimit () const
+{
+ return m_undoMinLimit;
+}
+
+// public
+void kpCommandHistoryBase::setUndoMinLimit (int limit)
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::setUndoMinLimit("
+ << limit << ")"
+ << endl;
+#endif
+
+ if (limit < 1 || limit > 5000/*"ought to be enough for anybody"*/)
+ {
+ kdError () << "kpCommandHistoryBase::setUndoMinLimit("
+ << limit << ")"
+ << endl;
+ return;
+ }
+
+ if (limit == m_undoMinLimit)
+ return;
+
+ m_undoMinLimit = limit;
+ trimCommandListsUpdateActions ();
+}
+
+
+// public
+int kpCommandHistoryBase::undoMaxLimit () const
+{
+ return m_undoMaxLimit;
+}
+
+// public
+void kpCommandHistoryBase::setUndoMaxLimit (int limit)
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::setUndoMaxLimit("
+ << limit << ")"
+ << endl;
+#endif
+
+ if (limit < 1 || limit > 5000/*"ought to be enough for anybody"*/)
+ {
+ kdError () << "kpCommandHistoryBase::setUndoMaxLimit("
+ << limit << ")"
+ << endl;
+ return;
+ }
+
+ if (limit == m_undoMaxLimit)
+ return;
+
+ m_undoMaxLimit = limit;
+ trimCommandListsUpdateActions ();
+}
+
+
+// public
+int kpCommandHistoryBase::undoMaxLimitSizeLimit () const
+{
+ return m_undoMaxLimitSizeLimit;
+}
+
+// public
+void kpCommandHistoryBase::setUndoMaxLimitSizeLimit (int sizeLimit)
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::setUndoMaxLimitSizeLimit("
+ << sizeLimit << ")"
+ << endl;
+#endif
+
+ if (sizeLimit < 0 ||
+ sizeLimit > (500 * 1048576)/*"ought to be enough for anybody"*/)
+ {
+ kdError () << "kpCommandHistoryBase::setUndoMaxLimitSizeLimit("
+ << sizeLimit << ")"
+ << endl;
+ return;
+ }
+
+ if (sizeLimit == m_undoMaxLimitSizeLimit)
+ return;
+
+ m_undoMaxLimitSizeLimit = sizeLimit;
+ trimCommandListsUpdateActions ();
+}
+
+
+// public
+void kpCommandHistoryBase::readConfig ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::readConfig()" << endl;
+#endif
+ KConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupUndoRedo);
+ KConfigBase *cfg = cfgGroupSaver.config ();
+
+ setUndoMinLimit (cfg->readNumEntry (kpSettingUndoMinLimit, undoMinLimit ()));
+ setUndoMaxLimit (cfg->readNumEntry (kpSettingUndoMaxLimit, undoMaxLimit ()));
+ setUndoMaxLimitSizeLimit (cfg->readNumEntry (kpSettingUndoMaxLimitSizeLimit,
+ undoMaxLimitSizeLimit ()));
+
+ trimCommandListsUpdateActions ();
+}
+
+// public
+void kpCommandHistoryBase::writeConfig ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::writeConfig()" << endl;
+#endif
+ KConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupUndoRedo);
+ KConfigBase *cfg = cfgGroupSaver.config ();
+
+ cfg->writeEntry (kpSettingUndoMinLimit, undoMinLimit ());
+ cfg->writeEntry (kpSettingUndoMaxLimit, undoMaxLimit ());
+ cfg->writeEntry (kpSettingUndoMaxLimitSizeLimit, undoMaxLimitSizeLimit ());
+
+ cfg->sync ();
+}
+
+
+// public
+void kpCommandHistoryBase::addCommand (kpCommand *command, bool execute)
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::addCommand("
+ << command
+ << ",execute=" << execute << ")"
+ << endl;
+#endif
+
+ if (execute)
+ command->execute ();
+
+ m_undoCommandList.push_front (command);
+ clearPointerList (&m_redoCommandList);
+
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\tdocumentRestoredPosition=" << m_documentRestoredPosition
+ << endl;
+#endif
+ if (m_documentRestoredPosition != INT_MAX)
+ {
+ if (m_documentRestoredPosition > 0)
+ m_documentRestoredPosition = INT_MAX;
+ else
+ m_documentRestoredPosition--;
+ #if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\t\tdocumentRestoredPosition=" << m_documentRestoredPosition
+ << endl;
+ #endif
+ }
+
+ trimCommandListsUpdateActions ();
+}
+
+// public
+void kpCommandHistoryBase::clear ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::clear()" << endl;
+#endif
+
+ clearPointerList (&m_undoCommandList);
+ clearPointerList (&m_redoCommandList);
+
+ m_documentRestoredPosition = 0;
+
+ updateActions ();
+}
+
+
+// protected slot
+void kpCommandHistoryBase::undoInternal ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::undoInternal()" << endl;
+#endif
+
+ kpCommand *undoCommand = nextUndoCommand ();
+ if (!undoCommand)
+ return;
+
+ undoCommand->unexecute ();
+
+
+ m_undoCommandList.erase (m_undoCommandList.begin ());
+ m_redoCommandList.push_front (undoCommand);
+
+
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\tdocumentRestoredPosition=" << m_documentRestoredPosition
+ << endl;
+#endif
+ if (m_documentRestoredPosition != INT_MAX)
+ {
+ m_documentRestoredPosition++;
+ if (m_documentRestoredPosition == 0)
+ emit documentRestored ();
+ #if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\t\tdocumentRestoredPosition=" << m_documentRestoredPosition
+ << endl;
+ #endif
+ }
+}
+
+// protected slot
+void kpCommandHistoryBase::redoInternal ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::redoInternal()" << endl;
+#endif
+
+ kpCommand *redoCommand = nextRedoCommand ();
+ if (!redoCommand)
+ return;
+
+ redoCommand->execute ();
+
+
+ m_redoCommandList.erase (m_redoCommandList.begin ());
+ m_undoCommandList.push_front (redoCommand);
+
+
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\tdocumentRestoredPosition=" << m_documentRestoredPosition
+ << endl;
+#endif
+ if (m_documentRestoredPosition != INT_MAX)
+ {
+ m_documentRestoredPosition--;
+ if (m_documentRestoredPosition == 0)
+ emit documentRestored ();
+ #if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\t\tdocumentRestoredPosition=" << m_documentRestoredPosition
+ << endl;
+ #endif
+ }
+}
+
+
+// public slot virtual
+void kpCommandHistoryBase::undo ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::undo()" << endl;
+#endif
+
+ undoInternal ();
+ trimCommandListsUpdateActions ();
+}
+
+// public slot virtual
+void kpCommandHistoryBase::redo ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::redo()" << endl;
+#endif
+
+ redoInternal ();
+ trimCommandListsUpdateActions ();
+}
+
+
+// public slot virtual
+void kpCommandHistoryBase::undoUpToNumber (int which)
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::undoUpToNumber(" << which << ")" << endl;
+#endif
+
+ for (int i = 0;
+ i <= which && !m_undoCommandList.isEmpty ();
+ i++)
+ {
+ undoInternal ();
+ }
+
+ trimCommandListsUpdateActions ();
+}
+
+// public slot virtual
+void kpCommandHistoryBase::redoUpToNumber (int which)
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::redoUpToNumber(" << which << ")" << endl;
+#endif
+
+ for (int i = 0;
+ i <= which && !m_redoCommandList.isEmpty ();
+ i++)
+ {
+ redoInternal ();
+ }
+
+ trimCommandListsUpdateActions ();
+}
+
+
+// protected
+QString kpCommandHistoryBase::undoActionText () const
+{
+ kpCommand *undoCommand = nextUndoCommand ();
+
+ if (undoCommand)
+ return i18n ("&Undo: %1").arg (undoCommand->name ());
+ else
+ return i18n ("&Undo");
+}
+
+// protected
+QString kpCommandHistoryBase::redoActionText () const
+{
+ kpCommand *redoCommand = nextRedoCommand ();
+
+ if (redoCommand)
+ return i18n ("&Redo: %1").arg (redoCommand->name ());
+ else
+ return i18n ("&Redo");
+}
+
+
+// protected
+void kpCommandHistoryBase::trimCommandListsUpdateActions ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::trimCommandListsUpdateActions()" << endl;
+#endif
+
+ trimCommandLists ();
+ updateActions ();
+}
+
+// protected
+void kpCommandHistoryBase::trimCommandList (QValueList <kpCommand *> *commandList)
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::trimCommandList()" << endl;
+ QTime timer; timer.start ();
+#endif
+
+ if (!commandList)
+ {
+ kdError () << "kpCommandHistoryBase::trimCommandList() passed 0 commandList"
+ << endl;
+ return;
+ }
+
+
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\tsize=" << commandList->size ()
+ << " undoMinLimit=" << m_undoMinLimit
+ << " undoMaxLimit=" << m_undoMaxLimit
+ << " undoMaxLimitSizeLimit=" << m_undoMaxLimitSizeLimit
+ << endl;
+#endif
+ if ((int) commandList->size () <= m_undoMinLimit)
+ {
+ #if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\t\tsize under undoMinLimit - done" << endl;
+ #endif
+ return;
+ }
+
+
+#if DEBUG_KP_COMMAND_HISTORY && 0
+ kdDebug () << "\tsize over undoMinLimit - iterating thru cmds:" << endl;
+#endif
+
+ QValueList <kpCommand *>::iterator it = commandList->begin ();
+ int upto = 0;
+
+ int sizeSoFar = 0;
+
+ while (it != commandList->end ())
+ {
+ bool advanceIt = true;
+
+ if (sizeSoFar <= m_undoMaxLimitSizeLimit)
+ {
+ if (sizeSoFar > INT_MAX - (*it)->size ())
+ sizeSoFar = INT_MAX;
+ else
+ sizeSoFar += (*it)->size ();
+ }
+
+ #if DEBUG_KP_COMMAND_HISTORY && 0
+ kdDebug () << "\t\t" << upto << ":"
+ << " name='" << (*it)->name ()
+ << "' size=" << (*it)->size ()
+ << " sizeSoFar=" << sizeSoFar
+ << endl;
+ #endif
+
+ if (upto >= m_undoMinLimit)
+ {
+ if (upto >= m_undoMaxLimit ||
+ sizeSoFar > m_undoMaxLimitSizeLimit)
+ {
+ #if DEBUG_KP_COMMAND_HISTORY && 0
+ kdDebug () << "\t\t\tkill" << endl;
+ #endif
+ delete (*it);
+ it = m_undoCommandList.erase (it);
+ advanceIt = false;
+ }
+ }
+
+ if (advanceIt)
+ it++;
+ upto++;
+ }
+
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\ttook " << timer.elapsed () << "ms" << endl;
+#endif
+}
+
+// protected
+void kpCommandHistoryBase::trimCommandLists ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::trimCommandLists()" << endl;
+#endif
+
+ trimCommandList (&m_undoCommandList);
+ trimCommandList (&m_redoCommandList);
+
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\tdocumentRestoredPosition=" << m_documentRestoredPosition
+ << endl;
+#endif
+ if (m_documentRestoredPosition != INT_MAX)
+ {
+ #if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\t\tundoCmdList.size=" << m_undoCommandList.size ()
+ << " redoCmdList.size=" << m_redoCommandList.size ()
+ << endl;
+ #endif
+ if (m_documentRestoredPosition > (int) m_redoCommandList.size () ||
+ -m_documentRestoredPosition > (int) m_undoCommandList.size ())
+ {
+ #if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\t\t\tinvalidate documentRestoredPosition" << endl;
+ #endif
+ m_documentRestoredPosition = INT_MAX;
+ }
+ }
+}
+
+
+static void populatePopupMenu (KPopupMenu *popupMenu,
+ const QString &undoOrRedo,
+ const QValueList <kpCommand *> &commandList)
+{
+ if (!popupMenu)
+ return;
+
+ popupMenu->clear ();
+
+ QValueList <kpCommand *>::const_iterator it = commandList.begin ();
+ int i = 0;
+ while (i < 10 && it != commandList.end ())
+ {
+ popupMenu->insertItem (i18n ("%1: %2").arg (undoOrRedo).arg ((*it)->name ()), i/*id*/);
+ i++, it++;
+ }
+
+ if (it != commandList.end ())
+ {
+ // TODO: maybe have a scrollview show all the items instead
+ KPopupTitle *title = new KPopupTitle (popupMenu);
+ title->setTitle (i18n ("%n more item", "%n more items",
+ commandList.size () - i));
+
+ popupMenu->insertItem (title);
+ }
+}
+
+
+// protected
+void kpCommandHistoryBase::updateActions ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::updateActions()" << endl;
+#endif
+
+ m_actionUndo->setEnabled ((bool) nextUndoCommand ());
+ m_actionUndo->setText (undoActionText ());
+#if DEBUG_KP_COMMAND_HISTORY
+ QTime timer; timer.start ();
+#endif
+ populatePopupMenu (m_actionUndo->popupMenu (),
+ i18n ("Undo"),
+ m_undoCommandList);
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\tpopuplatePopupMenu undo=" << timer.elapsed ()
+ << "ms" << endl;;
+#endif
+
+ m_actionRedo->setEnabled ((bool) nextRedoCommand ());
+ m_actionRedo->setText (redoActionText ());
+#if DEBUG_KP_COMMAND_HISTORY
+ timer.restart ();
+#endif
+ populatePopupMenu (m_actionRedo->popupMenu (),
+ i18n ("Redo"),
+ m_redoCommandList);
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\tpopuplatePopupMenu redo=" << timer.elapsed ()
+ << "ms" << endl;
+#endif
+}
+
+
+// public
+kpCommand *kpCommandHistoryBase::nextUndoCommand () const
+{
+ if (m_undoCommandList.isEmpty ())
+ return 0;
+
+ return m_undoCommandList.first ();
+}
+
+// public
+kpCommand *kpCommandHistoryBase::nextRedoCommand () const
+{
+ if (m_redoCommandList.isEmpty ())
+ return 0;
+
+ return m_redoCommandList.first ();
+}
+
+
+// public
+void kpCommandHistoryBase::setNextUndoCommand (kpCommand *command)
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::setNextUndoCommand("
+ << command
+ << ")"
+ << endl;
+#endif
+
+ if (m_undoCommandList.isEmpty ())
+ return;
+
+
+ delete m_undoCommandList [0];
+ m_undoCommandList [0] = command;
+
+
+ trimCommandListsUpdateActions ();
+}
+
+
+// public slot virtual
+void kpCommandHistoryBase::documentSaved ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistoryBase::documentSaved()" << endl;
+#endif
+
+ m_documentRestoredPosition = 0;
+}
+
+
+//
+// kpCommandHistory
+//
+
+kpCommandHistory::kpCommandHistory (bool doReadConfig, kpMainWindow *mainWindow)
+ : kpCommandHistoryBase (doReadConfig, mainWindow->actionCollection ()),
+ m_mainWindow (mainWindow)
+{
+}
+
+kpCommandHistory::~kpCommandHistory ()
+{
+}
+
+
+// public slot virtual [base KCommandHistory]
+void kpCommandHistory::undo ()
+{
+#if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "kpCommandHistory::undo() CALLED!" << endl;
+#endif
+ if (m_mainWindow && m_mainWindow->toolHasBegunShape ())
+ {
+ #if DEBUG_KP_COMMAND_HISTORY
+ kdDebug () << "\thas begun shape - cancel draw" << endl;
+ #endif
+ m_mainWindow->tool ()->cancelShapeInternal ();
+ }
+ else
+ kpCommandHistoryBase::undo ();
+}
+
+// public slot virtual [base KCommandHistory]
+void kpCommandHistory::redo ()
+{
+ if (m_mainWindow && m_mainWindow->toolHasBegunShape ())
+ {
+ // Not completely obvious but what else can we do?
+ //
+ // Ignoring the request would not be intuitive for tools like
+ // Polygon & Polyline (where it's not always apparent to the user
+ // that s/he's still drawing a shape even though the mouse isn't
+ // down).
+ m_mainWindow->tool ()->cancelShapeInternal ();
+ }
+ else
+ kpCommandHistoryBase::redo ();
+}
+
+#include <kpcommandhistory.moc>