1 /***************************************************************************
2     File                 : aspectcommands.h
3     Project              : SciDAVis
4     --------------------------------------------------------------------
5     Copyright            : (C) 2007-2009 by Knut Franke, Tilman Benkert
6     Email (use @ for *)  : knut.franke*gmx.de, thzs*gmx.net
7     Description          : Undo commands used by AbstractAspect.
8                            Only meant to be used within AbstractAspect.cpp
9 
10  ***************************************************************************/
11 
12 /***************************************************************************
13  *                                                                         *
14  *  This program is free software; you can redistribute it and/or modify   *
15  *  it under the terms of the GNU General Public License as published by   *
16  *  the Free Software Foundation; either version 2 of the License, or      *
17  *  (at your option) any later version.                                    *
18  *                                                                         *
19  *  This program is distributed in the hope that it will be useful,        *
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
22  *  GNU General Public License for more details.                           *
23  *                                                                         *
24  *   You should have received a copy of the GNU General Public License     *
25  *   along with this program; if not, write to the Free Software           *
26  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
27  *   Boston, MA  02110-1301  USA                                           *
28  *                                                                         *
29  ***************************************************************************/
30 
31 #include "AspectPrivate.h"
32 
33 #include <QUndoCommand>
34 
35 class AspectNameChangeCmd : public QUndoCommand
36 {
37 public:
AspectNameChangeCmd(AbstractAspect::Private * target,const QString & new_name)38     AspectNameChangeCmd(AbstractAspect::Private *target, const QString &new_name)
39         : d_target(target), d_other_name(new_name)
40     {
41         setText(QObject::tr("%1: rename to %2").arg(d_target->name()).arg(new_name));
42     }
43 
redo()44     virtual void redo()
45     {
46         QString tmp = d_target->name();
47         d_target->setName(d_other_name);
48         d_other_name = tmp;
49     }
50 
undo()51     virtual void undo() { redo(); }
52 
53 private:
54     AbstractAspect::Private *d_target;
55     QString d_other_name;
56 };
57 
58 class AspectCommentChangeCmd : public QUndoCommand
59 {
60 public:
AspectCommentChangeCmd(AbstractAspect::Private * target,const QString & new_comment)61     AspectCommentChangeCmd(AbstractAspect::Private *target, const QString &new_comment)
62         : d_target(target), d_other_comment(new_comment)
63     {
64         setText(QObject::tr("%1: change comment").arg(d_target->name()));
65     }
66 
redo()67     virtual void redo()
68     {
69         QString tmp = d_target->comment();
70         d_target->setComment(d_other_comment);
71         d_other_comment = tmp;
72     }
73 
undo()74     virtual void undo() { redo(); }
75 
76 private:
77     AbstractAspect::Private *d_target;
78     QString d_other_comment;
79 };
80 
81 class AspectCaptionSpecChangeCmd : public QUndoCommand
82 {
83 public:
AspectCaptionSpecChangeCmd(AbstractAspect::Private * target,const QString & new_caption_spec)84     AspectCaptionSpecChangeCmd(AbstractAspect::Private *target, const QString &new_caption_spec)
85         : d_target(target), d_other_caption_spec(new_caption_spec)
86     {
87         setText(QObject::tr("%1: change caption").arg(d_target->name()));
88     }
89 
redo()90     virtual void redo()
91     {
92         QString tmp = d_target->captionSpec();
93         d_target->setCaptionSpec(d_other_caption_spec);
94         d_other_caption_spec = tmp;
95     }
96 
undo()97     virtual void undo() { redo(); }
98 
99 private:
100     AbstractAspect::Private *d_target;
101     QString d_other_caption_spec;
102 };
103 
104 class AspectCreationTimeChangeCmd : public QUndoCommand
105 {
106 public:
AspectCreationTimeChangeCmd(AbstractAspect::Private * target,const QDateTime & new_creation_time)107     AspectCreationTimeChangeCmd(AbstractAspect::Private *target, const QDateTime &new_creation_time)
108         : d_target(target), d_other_creation_time(new_creation_time)
109     {
110         setText(QObject::tr("%1: set creation time").arg(d_target->name()));
111     }
112 
redo()113     virtual void redo()
114     {
115         QDateTime tmp = d_target->creationTime();
116         d_target->setCreationTime(d_other_creation_time);
117         d_other_creation_time = tmp;
118     }
119 
undo()120     virtual void undo() { redo(); }
121 
122 private:
123     AbstractAspect::Private *d_target;
124     QDateTime d_other_creation_time;
125 };
126 
127 class AspectChildRemoveCmd : public QUndoCommand
128 {
129 public:
AspectChildRemoveCmd(AbstractAspect::Private * target,AbstractAspect * child,bool detach)130     AspectChildRemoveCmd(AbstractAspect::Private *target, AbstractAspect *child, bool detach)
131         : d_target(target), d_child(child), d_index(-1), d_removed(false), d_detach(detach)
132     {
133         setText(QObject::tr("%1: remove %2").arg(d_target->name()).arg(d_child->name()));
134     }
~AspectChildRemoveCmd()135     ~AspectChildRemoveCmd()
136     {
137         if (d_removed && !d_detach)
138             delete d_child;
139     }
140 
141     // calling redo transfers ownership of d_child to the undo command
redo()142     virtual void redo()
143     {
144         d_index = d_target->removeChild(d_child);
145         d_removed = true;
146     }
147 
148     // calling undo transfers ownership of d_child back to its parent aspect
undo()149     virtual void undo()
150     {
151         Q_ASSERT(d_index != -1); // d_child must be a child of d_target->owner()
152         d_target->insertChild(d_index, d_child);
153         d_removed = false;
154     }
155 
156 protected:
157     AbstractAspect::Private *d_target;
158     AbstractAspect *d_child;
159     int d_index;
160     bool d_removed, d_detach;
161 };
162 
163 class AspectChildAddCmd : public AspectChildRemoveCmd
164 {
165 public:
AspectChildAddCmd(AbstractAspect::Private * target,AbstractAspect * child,int index)166     AspectChildAddCmd(AbstractAspect::Private *target, AbstractAspect *child, int index)
167         : AspectChildRemoveCmd(target, child, false)
168     {
169         setText(QObject::tr("%1: add %2").arg(d_target->name()).arg(d_child->name()));
170         d_index = index;
171     }
172 
redo()173     virtual void redo() { AspectChildRemoveCmd::undo(); }
174 
undo()175     virtual void undo() { AspectChildRemoveCmd::redo(); }
176 };
177 
178 class AspectChildMoveCmd : public QUndoCommand
179 {
180 public:
AspectChildMoveCmd(AbstractAspect::Private * target,int from,int to)181     AspectChildMoveCmd(AbstractAspect::Private *target, int from, int to)
182         : d_target(target), d_from(from), d_to(to)
183     {
184         setText(QObject::tr("%1: move child from position %2 to %3.")
185                         .arg(d_target->name())
186                         .arg(d_from + 1)
187                         .arg(d_to + 1));
188     }
189 
redo()190     virtual void redo()
191     {
192         // Moving in one go confuses QTreeView, so we would need another two signals
193         // to be mapped to QAbstractItemModel::layoutAboutToBeChanged() and ::layoutChanged().
194         AbstractAspect *child = d_target->child(d_from);
195         d_target->removeChild(child);
196         d_target->insertChild(d_to, child);
197     }
198 
undo()199     virtual void undo()
200     {
201         AbstractAspect *child = d_target->child(d_to);
202         d_target->removeChild(child);
203         d_target->insertChild(d_from, child);
204     }
205 
206 private:
207     AbstractAspect::Private *d_target;
208     int d_from, d_to;
209 };
210 
211 class AspectChildReparentCmd : public QUndoCommand
212 {
213 public:
AspectChildReparentCmd(AbstractAspect::Private * target,AbstractAspect::Private * new_parent,AbstractAspect * child,int new_index)214     AspectChildReparentCmd(AbstractAspect::Private *target, AbstractAspect::Private *new_parent,
215                            AbstractAspect *child, int new_index)
216         : d_target(target),
217           d_new_parent(new_parent),
218           d_child(child),
219           d_index(-1),
220           d_new_index(new_index)
221     {
222         setText(QObject::tr("%1: move %2 to %3.")
223                         .arg(d_target->name())
224                         .arg(d_child->name())
225                         .arg(d_new_parent->name()));
226     }
~AspectChildReparentCmd()227     ~AspectChildReparentCmd() { }
228 
229     // calling redo transfers ownership of d_child to the new parent aspect
redo()230     virtual void redo()
231     {
232         d_index = d_target->removeChild(d_child);
233         d_new_parent->insertChild(d_new_index, d_child);
234     }
235 
236     // calling undo transfers ownership of d_child back to its previous parent aspect
undo()237     virtual void undo()
238     {
239         Q_ASSERT(d_index != -1);
240         d_new_parent->removeChild(d_child);
241         d_target->insertChild(d_index, d_child);
242     }
243 
244 protected:
245     AbstractAspect::Private *d_target;
246     AbstractAspect::Private *d_new_parent;
247     AbstractAspect *d_child;
248     int d_index;
249     int d_new_index;
250 };
251