1 /*******************************************************************
2
3 Part of the Fritzing project - http://fritzing.org
4 Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de
5
6 Fritzing is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 Fritzing is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Fritzing. If not, see <http://www.gnu.org/licenses/>.
18
19 ********************************************************************
20
21 $Revision: 6904 $:
22 $Author: irascibl@gmail.com $:
23 $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $
24
25 ********************************************************************/
26
27 #include "waitpushundostack.h"
28 #include "utils/misc.h"
29 #include "utils/folderutils.h"
30 #include "commands.h"
31
32 #include <QCoreApplication>
33 #include <QTextStream>
34
CommandTimer(QUndoCommand * command,int delayMS,WaitPushUndoStack * undoStack)35 CommandTimer::CommandTimer(QUndoCommand * command, int delayMS, WaitPushUndoStack * undoStack) : QTimer()
36 {
37 m_undoStack = undoStack;
38 m_command = command;
39 m_undoStack->addTimer(this);
40 setSingleShot(true);
41 setInterval(delayMS);
42 connect(this, SIGNAL(timeout()), this, SLOT(timedout()));
43 start();
44 }
45
timedout()46 void CommandTimer::timedout() {
47 if (m_undoStack) {
48 m_undoStack->push(m_command);
49 m_undoStack->deleteTimer(this);
50 }
51 }
52
53 /////////////////////////////////
54
WaitPushUndoStack(QObject * parent)55 WaitPushUndoStack::WaitPushUndoStack(QObject * parent) :
56 QUndoStack(parent)
57 {
58 m_temporary = NULL;
59 #ifndef QT_NO_DEBUG
60 QString path = FolderUtils::getUserDataStorePath("");
61 path += "/undostack.txt";
62
63 m_file.setFileName(path);
64 m_file.remove();
65 #endif
66 }
67
~WaitPushUndoStack()68 WaitPushUndoStack::~WaitPushUndoStack() {
69 clearLiveTimers();
70 clearDeadTimers();
71 }
72
push(QUndoCommand * cmd)73 void WaitPushUndoStack::push(QUndoCommand * cmd)
74 {
75 #ifndef QT_NO_DEBUG
76 writeUndo(cmd, 0, NULL);
77 #endif
78 if (m_temporary == cmd) {
79 m_temporary->redo();
80 return;
81 }
82
83 QUndoStack::push(cmd);
84 }
85
86
waitPush(QUndoCommand * command,int delayMS)87 void WaitPushUndoStack::waitPush(QUndoCommand * command, int delayMS) {
88 clearDeadTimers();
89 if (delayMS <= 0) {
90 push(command);
91 return;
92 }
93
94 new CommandTimer(command, delayMS, this);
95 }
96
97
waitPushTemporary(QUndoCommand * command,int delayMS)98 void WaitPushUndoStack::waitPushTemporary(QUndoCommand * command, int delayMS) {
99 m_temporary = command;
100 waitPush(command, delayMS);
101 }
102
clearDeadTimers()103 void WaitPushUndoStack::clearDeadTimers() {
104 clearTimers(m_deadTimers);
105 }
106
clearLiveTimers()107 void WaitPushUndoStack::clearLiveTimers() {
108 clearTimers(m_liveTimers);
109 }
110
clearTimers(QList<QTimer * > & timers)111 void WaitPushUndoStack::clearTimers(QList<QTimer *> & timers) {
112 QMutexLocker locker(&m_mutex);
113 foreach (QTimer * timer, timers) {
114 delete timer;
115 }
116 timers.clear();
117 }
118
deleteTimer(QTimer * timer)119 void WaitPushUndoStack::deleteTimer(QTimer * timer) {
120 QMutexLocker locker(&m_mutex);
121 m_deadTimers.append(timer);
122 m_liveTimers.removeOne(timer);
123 }
124
addTimer(QTimer * timer)125 void WaitPushUndoStack::addTimer(QTimer * timer) {
126 QMutexLocker locker(&m_mutex);
127 m_liveTimers.append(timer);
128 }
129
hasTimers()130 bool WaitPushUndoStack::hasTimers() {
131 QMutexLocker locker(&m_mutex);
132 return m_liveTimers.count() > 0;
133 }
134
resolveTemporary()135 void WaitPushUndoStack::resolveTemporary() {
136 TemporaryCommand * tc = dynamic_cast<TemporaryCommand *>(m_temporary);
137 m_temporary = NULL;
138 if (tc) {
139 tc->setEnabled(false);
140 push(tc);
141 tc->setEnabled(true);
142 }
143 }
144
deleteTemporary()145 void WaitPushUndoStack::deleteTemporary() {
146 if (m_temporary != NULL) {
147 delete m_temporary;
148 m_temporary = NULL;
149 }
150 }
151
152 #ifndef QT_NO_DEBUG
writeUndo(const QUndoCommand * cmd,int indent,const BaseCommand * parent)153 void WaitPushUndoStack::writeUndo(const QUndoCommand * cmd, int indent, const BaseCommand * parent)
154 {
155 const BaseCommand * bcmd = dynamic_cast<const BaseCommand *>(cmd);
156 QString cmdString;
157 QString indexString;
158 if (bcmd == NULL) {
159 cmdString = cmd->text();
160 }
161 else {
162 cmdString = bcmd->getDebugString();
163 indexString = QString::number(bcmd->index()) + " ";
164 }
165
166 if (m_file.open(QIODevice::Append | QIODevice::Text)) {
167 QTextStream out(&m_file);
168 QString indentString(indent, QChar(' '));
169 if (parent) {
170 indentString += QString("(%1) ").arg(parent->index());
171 }
172 indentString += indexString;
173 out << indentString << cmdString << "\n";
174 m_file.close();
175 }
176
177 for (int i = 0; i < cmd->childCount(); i++) {
178 writeUndo(cmd->child(i), indent + 4, NULL);
179 }
180
181 if (bcmd) {
182 for (int i = 0; i < bcmd->subCommandCount(); i++) {
183 writeUndo(bcmd->subCommand(i), indent + 4, bcmd);
184 }
185 }
186 }
187 #endif
188
189