TDE graphics utilities
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

kpcommandhistory.cpp 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  1. /*
  2. Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org>
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions
  6. are met:
  7. 1. Redistributions of source code must retain the above copyright
  8. notice, this list of conditions and the following disclaimer.
  9. 2. Redistributions in binary form must reproduce the above copyright
  10. notice, this list of conditions and the following disclaimer in the
  11. documentation and/or other materials provided with the distribution.
  12. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  13. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  14. OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  15. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  16. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  17. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  18. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  19. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  20. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  21. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22. */
  23. #define DEBUG_KP_COMMAND_HISTORY 0
  24. #include <kpcommandhistory.h>
  25. #include <limits.h>
  26. #include <tqdatetime.h>
  27. #include <tdeactionclasses.h>
  28. #include <tdeapplication.h>
  29. #include <tdeconfig.h>
  30. #include <kdebug.h>
  31. #include <tdelocale.h>
  32. #include <tdepopupmenu.h>
  33. #include <tdestdaccel.h>
  34. #include <kstdaction.h>
  35. #include <kpdefs.h>
  36. #include <kpdocument.h>
  37. #include <kpmainwindow.h>
  38. #include <kptool.h>
  39. //template <typename T>
  40. static void clearPointerList (TQValueList <kpCommand *> *listPtr)
  41. {
  42. if (!listPtr)
  43. return;
  44. for (TQValueList <kpCommand *>::iterator it = listPtr->begin ();
  45. it != listPtr->end ();
  46. it++)
  47. {
  48. delete (*it);
  49. }
  50. listPtr->clear ();
  51. }
  52. //
  53. // kpCommand
  54. //
  55. kpCommand::kpCommand (kpMainWindow *mainWindow)
  56. : m_mainWindow (mainWindow)
  57. {
  58. if (!mainWindow)
  59. kdError () << "kpCommand::kpCommand() passed 0 mainWindow" << endl;
  60. }
  61. kpCommand::~kpCommand ()
  62. {
  63. }
  64. // protected
  65. kpMainWindow *kpCommand::mainWindow () const
  66. {
  67. return m_mainWindow;
  68. }
  69. // protected
  70. kpDocument *kpCommand::document () const
  71. {
  72. return m_mainWindow ? m_mainWindow->document () : 0;
  73. }
  74. // protected
  75. kpSelection *kpCommand::selection () const
  76. {
  77. kpDocument *doc = document ();
  78. if (!doc)
  79. return 0;
  80. return doc->selection ();
  81. }
  82. // protected
  83. kpViewManager *kpCommand::viewManager () const
  84. {
  85. return m_mainWindow ? m_mainWindow->viewManager () : 0;
  86. }
  87. //
  88. // kpNamedCommand
  89. //
  90. kpNamedCommand::kpNamedCommand (const TQString &name, kpMainWindow *mainWindow)
  91. : kpCommand (mainWindow),
  92. m_name (name)
  93. {
  94. }
  95. kpNamedCommand::~kpNamedCommand ()
  96. {
  97. }
  98. // public virtual [base kpCommand]
  99. TQString kpNamedCommand::name () const
  100. {
  101. return m_name;
  102. }
  103. //
  104. // kpMacroCommand
  105. //
  106. struct kpMacroCommandPrivate
  107. {
  108. };
  109. kpMacroCommand::kpMacroCommand (const TQString &name, kpMainWindow *mainWindow)
  110. : kpNamedCommand (name, mainWindow),
  111. d (new kpMacroCommandPrivate ())
  112. {
  113. }
  114. kpMacroCommand::~kpMacroCommand ()
  115. {
  116. clearPointerList (&m_commandList);
  117. delete d;
  118. }
  119. // public virtual [base kpCommand]
  120. int kpMacroCommand::size () const
  121. {
  122. #if DEBUG_KP_COMMAND_HISTORY && 0
  123. kdDebug () << "kpMacroCommand::size()" << endl;
  124. #endif
  125. int s = 0;
  126. #if DEBUG_KP_COMMAND_HISTORY && 0
  127. kdDebug () << "\tcalculating:" << endl;
  128. #endif
  129. for (TQValueList <kpCommand *>::const_iterator it = m_commandList.begin ();
  130. it != m_commandList.end ();
  131. it++)
  132. {
  133. #if DEBUG_KP_COMMAND_HISTORY && 0
  134. kdDebug () << "\t\tcurrentSize=" << s << " + "
  135. << (*it)->name () << ".size=" << (*it)->size ()
  136. << endl;
  137. #endif
  138. if (s > INT_MAX - (*it)->size ())
  139. {
  140. #if DEBUG_KP_COMMAND_HISTORY && 0
  141. kdDebug () << "\t\t\toverflow" << endl;
  142. #endif
  143. s = INT_MAX;
  144. break;
  145. }
  146. else
  147. {
  148. s += (*it)->size ();
  149. }
  150. }
  151. #if DEBUG_KP_COMMAND_HISTORY && 0
  152. kdDebug () << "\treturning " << s << endl;
  153. #endif
  154. return s;
  155. }
  156. // public virtual [base kpCommand]
  157. void kpMacroCommand::execute ()
  158. {
  159. #if DEBUG_KP_COMMAND_HISTORY
  160. kdDebug () << "kpMacroCommand::execute()" << endl;
  161. #endif
  162. for (TQValueList <kpCommand *>::const_iterator it = m_commandList.begin ();
  163. it != m_commandList.end ();
  164. it++)
  165. {
  166. #if DEBUG_KP_COMMAND_HISTORY
  167. kdDebug () << "\texecuting " << (*it)->name () << endl;
  168. #endif
  169. (*it)->execute ();
  170. }
  171. }
  172. // public virtual [base kpCommand]
  173. void kpMacroCommand::unexecute ()
  174. {
  175. #if DEBUG_KP_COMMAND_HISTORY
  176. kdDebug () << "kpMacroCommand::unexecute()" << endl;
  177. #endif
  178. TQValueList <kpCommand *>::const_iterator it = m_commandList.end ();
  179. it--;
  180. while (it != m_commandList.end ())
  181. {
  182. #if DEBUG_KP_COMMAND_HISTORY
  183. kdDebug () << "\tunexecuting " << (*it)->name () << endl;
  184. #endif
  185. (*it)->unexecute ();
  186. it--;
  187. }
  188. }
  189. // public
  190. void kpMacroCommand::addCommand (kpCommand *command)
  191. {
  192. m_commandList.push_back (command);
  193. }
  194. //
  195. // kpCommandHistoryBase
  196. //
  197. struct kpCommandHistoryBasePrivate
  198. {
  199. };
  200. kpCommandHistoryBase::kpCommandHistoryBase (bool doReadConfig,
  201. TDEActionCollection *ac)
  202. : d (new kpCommandHistoryBasePrivate ())
  203. {
  204. m_actionUndo = new TDEToolBarPopupAction (undoActionText (),
  205. TQString::fromLatin1 ("edit-undo"),
  206. TDEStdAccel::shortcut (TDEStdAccel::Undo),
  207. this, TQT_SLOT (undo ()),
  208. ac, KStdAction::name (KStdAction::Undo));
  209. m_actionRedo = new TDEToolBarPopupAction (redoActionText (),
  210. TQString::fromLatin1 ("edit-redo"),
  211. TDEStdAccel::shortcut (TDEStdAccel::Redo),
  212. this, TQT_SLOT (redo ()),
  213. ac, KStdAction::name (KStdAction::Redo));
  214. m_actionUndo->setEnabled (false);
  215. m_actionRedo->setEnabled (false);
  216. connect (m_actionUndo->popupMenu (), TQT_SIGNAL (activated (int)),
  217. this, TQT_SLOT (undoUpToNumber (int)));
  218. connect (m_actionRedo->popupMenu (), TQT_SIGNAL (activated (int)),
  219. this, TQT_SLOT (redoUpToNumber (int)));
  220. m_undoMinLimit = 10;
  221. m_undoMaxLimit = 500;
  222. m_undoMaxLimitSizeLimit = 16 * 1048576;
  223. m_documentRestoredPosition = 0;
  224. if (doReadConfig)
  225. readConfig ();
  226. }
  227. kpCommandHistoryBase::~kpCommandHistoryBase ()
  228. {
  229. clearPointerList (&m_undoCommandList);
  230. clearPointerList (&m_redoCommandList);
  231. delete d;
  232. }
  233. // public
  234. int kpCommandHistoryBase::undoLimit () const
  235. {
  236. return undoMinLimit ();
  237. }
  238. // public
  239. void kpCommandHistoryBase::setUndoLimit (int limit)
  240. {
  241. setUndoMinLimit (limit);
  242. }
  243. // public
  244. int kpCommandHistoryBase::undoMinLimit () const
  245. {
  246. return m_undoMinLimit;
  247. }
  248. // public
  249. void kpCommandHistoryBase::setUndoMinLimit (int limit)
  250. {
  251. #if DEBUG_KP_COMMAND_HISTORY
  252. kdDebug () << "kpCommandHistoryBase::setUndoMinLimit("
  253. << limit << ")"
  254. << endl;
  255. #endif
  256. if (limit < 1 || limit > 5000/*"ought to be enough for anybody"*/)
  257. {
  258. kdError () << "kpCommandHistoryBase::setUndoMinLimit("
  259. << limit << ")"
  260. << endl;
  261. return;
  262. }
  263. if (limit == m_undoMinLimit)
  264. return;
  265. m_undoMinLimit = limit;
  266. trimCommandListsUpdateActions ();
  267. }
  268. // public
  269. int kpCommandHistoryBase::undoMaxLimit () const
  270. {
  271. return m_undoMaxLimit;
  272. }
  273. // public
  274. void kpCommandHistoryBase::setUndoMaxLimit (int limit)
  275. {
  276. #if DEBUG_KP_COMMAND_HISTORY
  277. kdDebug () << "kpCommandHistoryBase::setUndoMaxLimit("
  278. << limit << ")"
  279. << endl;
  280. #endif
  281. if (limit < 1 || limit > 5000/*"ought to be enough for anybody"*/)
  282. {
  283. kdError () << "kpCommandHistoryBase::setUndoMaxLimit("
  284. << limit << ")"
  285. << endl;
  286. return;
  287. }
  288. if (limit == m_undoMaxLimit)
  289. return;
  290. m_undoMaxLimit = limit;
  291. trimCommandListsUpdateActions ();
  292. }
  293. // public
  294. int kpCommandHistoryBase::undoMaxLimitSizeLimit () const
  295. {
  296. return m_undoMaxLimitSizeLimit;
  297. }
  298. // public
  299. void kpCommandHistoryBase::setUndoMaxLimitSizeLimit (int sizeLimit)
  300. {
  301. #if DEBUG_KP_COMMAND_HISTORY
  302. kdDebug () << "kpCommandHistoryBase::setUndoMaxLimitSizeLimit("
  303. << sizeLimit << ")"
  304. << endl;
  305. #endif
  306. if (sizeLimit < 0 ||
  307. sizeLimit > (500 * 1048576)/*"ought to be enough for anybody"*/)
  308. {
  309. kdError () << "kpCommandHistoryBase::setUndoMaxLimitSizeLimit("
  310. << sizeLimit << ")"
  311. << endl;
  312. return;
  313. }
  314. if (sizeLimit == m_undoMaxLimitSizeLimit)
  315. return;
  316. m_undoMaxLimitSizeLimit = sizeLimit;
  317. trimCommandListsUpdateActions ();
  318. }
  319. // public
  320. void kpCommandHistoryBase::readConfig ()
  321. {
  322. #if DEBUG_KP_COMMAND_HISTORY
  323. kdDebug () << "kpCommandHistoryBase::readConfig()" << endl;
  324. #endif
  325. TDEConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupUndoRedo);
  326. TDEConfigBase *cfg = cfgGroupSaver.config ();
  327. setUndoMinLimit (cfg->readNumEntry (kpSettingUndoMinLimit, undoMinLimit ()));
  328. setUndoMaxLimit (cfg->readNumEntry (kpSettingUndoMaxLimit, undoMaxLimit ()));
  329. setUndoMaxLimitSizeLimit (cfg->readNumEntry (kpSettingUndoMaxLimitSizeLimit,
  330. undoMaxLimitSizeLimit ()));
  331. trimCommandListsUpdateActions ();
  332. }
  333. // public
  334. void kpCommandHistoryBase::writeConfig ()
  335. {
  336. #if DEBUG_KP_COMMAND_HISTORY
  337. kdDebug () << "kpCommandHistoryBase::writeConfig()" << endl;
  338. #endif
  339. TDEConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupUndoRedo);
  340. TDEConfigBase *cfg = cfgGroupSaver.config ();
  341. cfg->writeEntry (kpSettingUndoMinLimit, undoMinLimit ());
  342. cfg->writeEntry (kpSettingUndoMaxLimit, undoMaxLimit ());
  343. cfg->writeEntry (kpSettingUndoMaxLimitSizeLimit, undoMaxLimitSizeLimit ());
  344. cfg->sync ();
  345. }
  346. // public
  347. void kpCommandHistoryBase::addCommand (kpCommand *command, bool execute)
  348. {
  349. #if DEBUG_KP_COMMAND_HISTORY
  350. kdDebug () << "kpCommandHistoryBase::addCommand("
  351. << command
  352. << ",execute=" << execute << ")"
  353. << endl;
  354. #endif
  355. if (execute)
  356. command->execute ();
  357. m_undoCommandList.push_front (command);
  358. clearPointerList (&m_redoCommandList);
  359. #if DEBUG_KP_COMMAND_HISTORY
  360. kdDebug () << "\tdocumentRestoredPosition=" << m_documentRestoredPosition
  361. << endl;
  362. #endif
  363. if (m_documentRestoredPosition != INT_MAX)
  364. {
  365. if (m_documentRestoredPosition > 0)
  366. m_documentRestoredPosition = INT_MAX;
  367. else
  368. m_documentRestoredPosition--;
  369. #if DEBUG_KP_COMMAND_HISTORY
  370. kdDebug () << "\t\tdocumentRestoredPosition=" << m_documentRestoredPosition
  371. << endl;
  372. #endif
  373. }
  374. trimCommandListsUpdateActions ();
  375. }
  376. // public
  377. void kpCommandHistoryBase::clear ()
  378. {
  379. #if DEBUG_KP_COMMAND_HISTORY
  380. kdDebug () << "kpCommandHistoryBase::clear()" << endl;
  381. #endif
  382. clearPointerList (&m_undoCommandList);
  383. clearPointerList (&m_redoCommandList);
  384. m_documentRestoredPosition = 0;
  385. updateActions ();
  386. }
  387. // protected slot
  388. void kpCommandHistoryBase::undoInternal ()
  389. {
  390. #if DEBUG_KP_COMMAND_HISTORY
  391. kdDebug () << "kpCommandHistoryBase::undoInternal()" << endl;
  392. #endif
  393. kpCommand *undoCommand = nextUndoCommand ();
  394. if (!undoCommand)
  395. return;
  396. undoCommand->unexecute ();
  397. m_undoCommandList.erase (m_undoCommandList.begin ());
  398. m_redoCommandList.push_front (undoCommand);
  399. #if DEBUG_KP_COMMAND_HISTORY
  400. kdDebug () << "\tdocumentRestoredPosition=" << m_documentRestoredPosition
  401. << endl;
  402. #endif
  403. if (m_documentRestoredPosition != INT_MAX)
  404. {
  405. m_documentRestoredPosition++;
  406. if (m_documentRestoredPosition == 0)
  407. emit documentRestored ();
  408. #if DEBUG_KP_COMMAND_HISTORY
  409. kdDebug () << "\t\tdocumentRestoredPosition=" << m_documentRestoredPosition
  410. << endl;
  411. #endif
  412. }
  413. }
  414. // protected slot
  415. void kpCommandHistoryBase::redoInternal ()
  416. {
  417. #if DEBUG_KP_COMMAND_HISTORY
  418. kdDebug () << "kpCommandHistoryBase::redoInternal()" << endl;
  419. #endif
  420. kpCommand *redoCommand = nextRedoCommand ();
  421. if (!redoCommand)
  422. return;
  423. redoCommand->execute ();
  424. m_redoCommandList.erase (m_redoCommandList.begin ());
  425. m_undoCommandList.push_front (redoCommand);
  426. #if DEBUG_KP_COMMAND_HISTORY
  427. kdDebug () << "\tdocumentRestoredPosition=" << m_documentRestoredPosition
  428. << endl;
  429. #endif
  430. if (m_documentRestoredPosition != INT_MAX)
  431. {
  432. m_documentRestoredPosition--;
  433. if (m_documentRestoredPosition == 0)
  434. emit documentRestored ();
  435. #if DEBUG_KP_COMMAND_HISTORY
  436. kdDebug () << "\t\tdocumentRestoredPosition=" << m_documentRestoredPosition
  437. << endl;
  438. #endif
  439. }
  440. }
  441. // public slot virtual
  442. void kpCommandHistoryBase::undo ()
  443. {
  444. #if DEBUG_KP_COMMAND_HISTORY
  445. kdDebug () << "kpCommandHistoryBase::undo()" << endl;
  446. #endif
  447. undoInternal ();
  448. trimCommandListsUpdateActions ();
  449. }
  450. // public slot virtual
  451. void kpCommandHistoryBase::redo ()
  452. {
  453. #if DEBUG_KP_COMMAND_HISTORY
  454. kdDebug () << "kpCommandHistoryBase::redo()" << endl;
  455. #endif
  456. redoInternal ();
  457. trimCommandListsUpdateActions ();
  458. }
  459. // public slot virtual
  460. void kpCommandHistoryBase::undoUpToNumber (int which)
  461. {
  462. #if DEBUG_KP_COMMAND_HISTORY
  463. kdDebug () << "kpCommandHistoryBase::undoUpToNumber(" << which << ")" << endl;
  464. #endif
  465. for (int i = 0;
  466. i <= which && !m_undoCommandList.isEmpty ();
  467. i++)
  468. {
  469. undoInternal ();
  470. }
  471. trimCommandListsUpdateActions ();
  472. }
  473. // public slot virtual
  474. void kpCommandHistoryBase::redoUpToNumber (int which)
  475. {
  476. #if DEBUG_KP_COMMAND_HISTORY
  477. kdDebug () << "kpCommandHistoryBase::redoUpToNumber(" << which << ")" << endl;
  478. #endif
  479. for (int i = 0;
  480. i <= which && !m_redoCommandList.isEmpty ();
  481. i++)
  482. {
  483. redoInternal ();
  484. }
  485. trimCommandListsUpdateActions ();
  486. }
  487. // protected
  488. TQString kpCommandHistoryBase::undoActionText () const
  489. {
  490. kpCommand *undoCommand = nextUndoCommand ();
  491. if (undoCommand)
  492. return i18n ("&Undo: %1").arg (undoCommand->name ());
  493. else
  494. return i18n ("&Undo");
  495. }
  496. // protected
  497. TQString kpCommandHistoryBase::redoActionText () const
  498. {
  499. kpCommand *redoCommand = nextRedoCommand ();
  500. if (redoCommand)
  501. return i18n ("&Redo: %1").arg (redoCommand->name ());
  502. else
  503. return i18n ("&Redo");
  504. }
  505. // protected
  506. void kpCommandHistoryBase::trimCommandListsUpdateActions ()
  507. {
  508. #if DEBUG_KP_COMMAND_HISTORY
  509. kdDebug () << "kpCommandHistoryBase::trimCommandListsUpdateActions()" << endl;
  510. #endif
  511. trimCommandLists ();
  512. updateActions ();
  513. }
  514. // protected
  515. void kpCommandHistoryBase::trimCommandList (TQValueList <kpCommand *> *commandList)
  516. {
  517. #if DEBUG_KP_COMMAND_HISTORY
  518. kdDebug () << "kpCommandHistoryBase::trimCommandList()" << endl;
  519. TQTime timer; timer.start ();
  520. #endif
  521. if (!commandList)
  522. {
  523. kdError () << "kpCommandHistoryBase::trimCommandList() passed 0 commandList"
  524. << endl;
  525. return;
  526. }
  527. #if DEBUG_KP_COMMAND_HISTORY
  528. kdDebug () << "\tsize=" << commandList->size ()
  529. << " undoMinLimit=" << m_undoMinLimit
  530. << " undoMaxLimit=" << m_undoMaxLimit
  531. << " undoMaxLimitSizeLimit=" << m_undoMaxLimitSizeLimit
  532. << endl;
  533. #endif
  534. if ((int) commandList->size () <= m_undoMinLimit)
  535. {
  536. #if DEBUG_KP_COMMAND_HISTORY
  537. kdDebug () << "\t\tsize under undoMinLimit - done" << endl;
  538. #endif
  539. return;
  540. }
  541. #if DEBUG_KP_COMMAND_HISTORY && 0
  542. kdDebug () << "\tsize over undoMinLimit - iterating thru cmds:" << endl;
  543. #endif
  544. TQValueList <kpCommand *>::iterator it = commandList->begin ();
  545. int upto = 0;
  546. int sizeSoFar = 0;
  547. while (it != commandList->end ())
  548. {
  549. bool advanceIt = true;
  550. if (sizeSoFar <= m_undoMaxLimitSizeLimit)
  551. {
  552. if (sizeSoFar > INT_MAX - (*it)->size ())
  553. sizeSoFar = INT_MAX;
  554. else
  555. sizeSoFar += (*it)->size ();
  556. }
  557. #if DEBUG_KP_COMMAND_HISTORY && 0
  558. kdDebug () << "\t\t" << upto << ":"
  559. << " name='" << (*it)->name ()
  560. << "' size=" << (*it)->size ()
  561. << " sizeSoFar=" << sizeSoFar
  562. << endl;
  563. #endif
  564. if (upto >= m_undoMinLimit)
  565. {
  566. if (upto >= m_undoMaxLimit ||
  567. sizeSoFar > m_undoMaxLimitSizeLimit)
  568. {
  569. #if DEBUG_KP_COMMAND_HISTORY && 0
  570. kdDebug () << "\t\t\tkill" << endl;
  571. #endif
  572. delete (*it);
  573. it = m_undoCommandList.erase (it);
  574. advanceIt = false;
  575. }
  576. }
  577. if (advanceIt)
  578. it++;
  579. upto++;
  580. }
  581. #if DEBUG_KP_COMMAND_HISTORY
  582. kdDebug () << "\ttook " << timer.elapsed () << "ms" << endl;
  583. #endif
  584. }
  585. // protected
  586. void kpCommandHistoryBase::trimCommandLists ()
  587. {
  588. #if DEBUG_KP_COMMAND_HISTORY
  589. kdDebug () << "kpCommandHistoryBase::trimCommandLists()" << endl;
  590. #endif
  591. trimCommandList (&m_undoCommandList);
  592. trimCommandList (&m_redoCommandList);
  593. #if DEBUG_KP_COMMAND_HISTORY
  594. kdDebug () << "\tdocumentRestoredPosition=" << m_documentRestoredPosition
  595. << endl;
  596. #endif
  597. if (m_documentRestoredPosition != INT_MAX)
  598. {
  599. #if DEBUG_KP_COMMAND_HISTORY
  600. kdDebug () << "\t\tundoCmdList.size=" << m_undoCommandList.size ()
  601. << " redoCmdList.size=" << m_redoCommandList.size ()
  602. << endl;
  603. #endif
  604. if (m_documentRestoredPosition > (int) m_redoCommandList.size () ||
  605. -m_documentRestoredPosition > (int) m_undoCommandList.size ())
  606. {
  607. #if DEBUG_KP_COMMAND_HISTORY
  608. kdDebug () << "\t\t\tinvalidate documentRestoredPosition" << endl;
  609. #endif
  610. m_documentRestoredPosition = INT_MAX;
  611. }
  612. }
  613. }
  614. static void populatePopupMenu (TDEPopupMenu *popupMenu,
  615. const TQString &undoOrRedo,
  616. const TQValueList <kpCommand *> &commandList)
  617. {
  618. if (!popupMenu)
  619. return;
  620. popupMenu->clear ();
  621. TQValueList <kpCommand *>::const_iterator it = commandList.begin ();
  622. int i = 0;
  623. while (i < 10 && it != commandList.end ())
  624. {
  625. popupMenu->insertItem (i18n ("%1: %2").arg (undoOrRedo).arg ((*it)->name ()), i/*id*/);
  626. i++, it++;
  627. }
  628. if (it != commandList.end ())
  629. {
  630. // TODO: maybe have a scrollview show all the items instead
  631. TDEPopupTitle *title = new TDEPopupTitle (popupMenu);
  632. title->setTitle (i18n ("%n more item", "%n more items",
  633. commandList.size () - i));
  634. popupMenu->insertItem (title);
  635. }
  636. }
  637. // protected
  638. void kpCommandHistoryBase::updateActions ()
  639. {
  640. #if DEBUG_KP_COMMAND_HISTORY
  641. kdDebug () << "kpCommandHistoryBase::updateActions()" << endl;
  642. #endif
  643. m_actionUndo->setEnabled ((bool) nextUndoCommand ());
  644. m_actionUndo->setText (undoActionText ());
  645. #if DEBUG_KP_COMMAND_HISTORY
  646. TQTime timer; timer.start ();
  647. #endif
  648. populatePopupMenu (m_actionUndo->popupMenu (),
  649. i18n ("Undo"),
  650. m_undoCommandList);
  651. #if DEBUG_KP_COMMAND_HISTORY
  652. kdDebug () << "\tpopuplatePopupMenu undo=" << timer.elapsed ()
  653. << "ms" << endl;;
  654. #endif
  655. m_actionRedo->setEnabled ((bool) nextRedoCommand ());
  656. m_actionRedo->setText (redoActionText ());
  657. #if DEBUG_KP_COMMAND_HISTORY
  658. timer.restart ();
  659. #endif
  660. populatePopupMenu (m_actionRedo->popupMenu (),
  661. i18n ("Redo"),
  662. m_redoCommandList);
  663. #if DEBUG_KP_COMMAND_HISTORY
  664. kdDebug () << "\tpopuplatePopupMenu redo=" << timer.elapsed ()
  665. << "ms" << endl;
  666. #endif
  667. }
  668. // public
  669. kpCommand *kpCommandHistoryBase::nextUndoCommand () const
  670. {
  671. if (m_undoCommandList.isEmpty ())
  672. return 0;
  673. return m_undoCommandList.first ();
  674. }
  675. // public
  676. kpCommand *kpCommandHistoryBase::nextRedoCommand () const
  677. {
  678. if (m_redoCommandList.isEmpty ())
  679. return 0;
  680. return m_redoCommandList.first ();
  681. }
  682. // public
  683. void kpCommandHistoryBase::setNextUndoCommand (kpCommand *command)
  684. {
  685. #if DEBUG_KP_COMMAND_HISTORY
  686. kdDebug () << "kpCommandHistoryBase::setNextUndoCommand("
  687. << command
  688. << ")"
  689. << endl;
  690. #endif
  691. if (m_undoCommandList.isEmpty ())
  692. return;
  693. delete m_undoCommandList [0];
  694. m_undoCommandList [0] = command;
  695. trimCommandListsUpdateActions ();
  696. }
  697. // public slot virtual
  698. void kpCommandHistoryBase::documentSaved ()
  699. {
  700. #if DEBUG_KP_COMMAND_HISTORY
  701. kdDebug () << "kpCommandHistoryBase::documentSaved()" << endl;
  702. #endif
  703. m_documentRestoredPosition = 0;
  704. }
  705. //
  706. // kpCommandHistory
  707. //
  708. kpCommandHistory::kpCommandHistory (bool doReadConfig, kpMainWindow *mainWindow)
  709. : kpCommandHistoryBase (doReadConfig, mainWindow->actionCollection ()),
  710. m_mainWindow (mainWindow)
  711. {
  712. }
  713. kpCommandHistory::~kpCommandHistory ()
  714. {
  715. }
  716. // public slot virtual [base KCommandHistory]
  717. void kpCommandHistory::undo ()
  718. {
  719. #if DEBUG_KP_COMMAND_HISTORY
  720. kdDebug () << "kpCommandHistory::undo() CALLED!" << endl;
  721. #endif
  722. if (m_mainWindow && m_mainWindow->toolHasBegunShape ())
  723. {
  724. #if DEBUG_KP_COMMAND_HISTORY
  725. kdDebug () << "\thas begun shape - cancel draw" << endl;
  726. #endif
  727. m_mainWindow->tool ()->cancelShapeInternal ();
  728. }
  729. else
  730. kpCommandHistoryBase::undo ();
  731. }
  732. // public slot virtual [base KCommandHistory]
  733. void kpCommandHistory::redo ()
  734. {
  735. if (m_mainWindow && m_mainWindow->toolHasBegunShape ())
  736. {
  737. // Not completely obvious but what else can we do?
  738. //
  739. // Ignoring the request would not be intuitive for tools like
  740. // Polygon & Polyline (where it's not always apparent to the user
  741. // that s/he's still drawing a shape even though the mouse isn't
  742. // down).
  743. m_mainWindow->tool ()->cancelShapeInternal ();
  744. }
  745. else
  746. kpCommandHistoryBase::redo ();
  747. }
  748. #include <kpcommandhistory.moc>