1 /************************************************************************
2  **
3  **  @file   undogroup.cpp
4  **  @author Roman Telezhynskyi <dismine(at)gmail.com>
5  **  @date   18 3, 2020
6  **
7  **  @brief
8  **  @copyright
9  **  This source code is part of the Valentina project, a pattern making
10  **  program, whose allow create and modeling patterns of clothing.
11  **  Copyright (C) 2020 Valentina project
12  **  <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
13  **
14  **  Valentina 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 3 of the License, or
17  **  (at your option) any later version.
18  **
19  **  Valentina 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 Valentina.  If not, see <http://www.gnu.org/licenses/>.
26  **
27  *************************************************************************/
28 
29 #include "undogroup.h"
30 
31 #include <QDomNode>
32 #include <QDomNodeList>
33 
34 #include "../vmisc/vabstractvalapplication.h"
35 #include "../vmisc/def.h"
36 #include "../vwidgets/vmaingraphicsview.h"
37 #include "../ifc/xml/vabstractpattern.h"
38 #include "vundocommand.h"
39 #include "../vtools/tools/vdatatool.h"
40 
41 //AddGroup
42 //---------------------------------------------------------------------------------------------------------------------
AddGroup(const QDomElement & xml,VAbstractPattern * doc,QUndoCommand * parent)43 AddGroup::AddGroup(const QDomElement &xml, VAbstractPattern *doc, QUndoCommand *parent)
44     : VUndoCommand(xml, doc, parent), nameActivDraw(doc->GetNameActivPP())
45 {
46     setText(tr("add group"));
47     nodeId = doc->GetParametrId(xml);
48 }
49 
50 //---------------------------------------------------------------------------------------------------------------------
undo()51 void AddGroup::undo()
52 {
53     qCDebug(vUndo, "Undo.");
54 
55     doc->ChangeActivPP(nameActivDraw);//Without this user will not see this change
56 
57     QDomElement groups = doc->CreateGroups();
58     if (not groups.isNull())
59     {
60         QDomElement group = doc->elementById(nodeId, VAbstractPattern::TagGroup);
61         if (group.isElement())
62         {
63             group.setAttribute(VAbstractPattern::AttrVisible, trueStr);
64             doc->ParseGroups(groups);
65             if (groups.removeChild(group).isNull())
66             {
67                 qCDebug(vUndo, "Can't delete group.");
68                 return;
69             }
70             emit UpdateGroups();
71         }
72         else
73         {
74             if (groups.childNodes().isEmpty())
75             {
76                 QDomNode parent = groups.parentNode();
77                 parent.removeChild(groups);
78             }
79 
80             qCDebug(vUndo, "Can't get group by id = %u.", nodeId);
81             return;
82         }
83     }
84     else
85     {
86         qCDebug(vUndo, "Can't get tag Groups.");
87         return;
88     }
89 
90     VMainGraphicsView::NewSceneRect(VAbstractValApplication::VApp()->getCurrentScene(),
91                                     VAbstractValApplication::VApp()->getSceneView());
92     if (VAbstractValApplication::VApp()->GetDrawMode() == Draw::Calculation)
93     {
94         emit doc->SetCurrentPP(nameActivDraw);//Return current pattern piece after undo
95     }
96 }
97 
98 //---------------------------------------------------------------------------------------------------------------------
redo()99 void AddGroup::redo()
100 {
101     qCDebug(vUndo, "Redo.");
102 
103     doc->ChangeActivPP(nameActivDraw);//Without this user will not see this change
104 
105     QDomElement groups = doc->CreateGroups();
106     if (not groups.isNull())
107     {
108         groups.appendChild(xml);
109         doc->ParseGroups(groups);
110         emit UpdateGroups();
111     }
112     else
113     {
114         qCDebug(vUndo, "Can't get tag Groups.");
115         return;
116     }
117 
118     VMainGraphicsView::NewSceneRect(VAbstractValApplication::VApp()->getCurrentScene(),
119                                     VAbstractValApplication::VApp()->getSceneView());
120 }
121 
122 //RenameGroup
123 //---------------------------------------------------------------------------------------------------------------------
RenameGroup(VAbstractPattern * doc,quint32 id,const QString & name,QUndoCommand * parent)124 RenameGroup::RenameGroup(VAbstractPattern *doc, quint32 id, const QString &name, QUndoCommand *parent)
125     : VUndoCommand(QDomElement(), doc, parent),
126       newName(name)
127 {
128     setText(tr("rename group"));
129     nodeId = id;
130     oldName = doc->GetGroupName(nodeId);
131 }
132 
133 //---------------------------------------------------------------------------------------------------------------------
undo()134 void RenameGroup::undo()
135 {
136     qCDebug(vUndo, "Undo.");
137     doc->SetGroupName(nodeId, oldName);
138     emit UpdateGroups();
139     emit doc->UpdateToolTip();
140 }
141 
142 //---------------------------------------------------------------------------------------------------------------------
redo()143 void RenameGroup::redo()
144 {
145     qCDebug(vUndo, "Redo.");
146 
147     doc->SetGroupName(nodeId, newName);
148     emit UpdateGroups();
149     emit doc->UpdateToolTip();
150 }
151 
152 //ChangeGroupOptions
153 //---------------------------------------------------------------------------------------------------------------------
ChangeGroupOptions(VAbstractPattern * doc,quint32 id,const QString & name,const QStringList & tags,QUndoCommand * parent)154 ChangeGroupOptions::ChangeGroupOptions(VAbstractPattern *doc, quint32 id, const QString &name, const QStringList &tags,
155                                        QUndoCommand *parent)
156     : VUndoCommand(QDomElement(), doc, parent),
157       newName(name),
158       newTags(tags)
159 {
160     setText(tr("rename group"));
161     nodeId = id;
162     oldName = doc->GetGroupName(nodeId);
163     oldTags = doc->GetGroupTags(nodeId);
164 }
165 
166 //---------------------------------------------------------------------------------------------------------------------
undo()167 void ChangeGroupOptions::undo()
168 {
169     qCDebug(vUndo, "Undo.");
170     doc->SetGroupName(nodeId, oldName);
171     doc->SetGroupTags(nodeId, oldTags);
172     emit UpdateGroups();
173     emit doc->UpdateToolTip();
174 }
175 
176 //---------------------------------------------------------------------------------------------------------------------
redo()177 void ChangeGroupOptions::redo()
178 {
179     qCDebug(vUndo, "Redo.");
180     doc->SetGroupName(nodeId, newName);
181     doc->SetGroupTags(nodeId, newTags);
182     emit UpdateGroups();
183     emit doc->UpdateToolTip();
184 }
185 
186 //AddItemToGroup
187 //---------------------------------------------------------------------------------------------------------------------
AddItemToGroup(const QDomElement & xml,VAbstractPattern * doc,quint32 groupId,QUndoCommand * parent)188 AddItemToGroup::AddItemToGroup(const QDomElement &xml, VAbstractPattern *doc, quint32 groupId, QUndoCommand *parent)
189     : VUndoCommand(xml, doc, parent), nameActivDraw(doc->GetNameActivPP())
190 {
191     setText(tr("Add item to group"));
192     nodeId = groupId;
193 }
194 
195 //---------------------------------------------------------------------------------------------------------------------
undo()196 void AddItemToGroup::undo()
197 {
198     qCDebug(vUndo, "Undo the add item to group");
199     performUndoRedo(true);
200 }
201 
202 //---------------------------------------------------------------------------------------------------------------------
redo()203 void AddItemToGroup::redo()
204 {
205     qCDebug(vUndo, "Redo the add item to group");
206     performUndoRedo(false);
207 }
208 
209 //---------------------------------------------------------------------------------------------------------------------
performUndoRedo(bool isUndo)210 void AddItemToGroup::performUndoRedo(bool isUndo)
211 {
212     doc->ChangeActivPP(nameActivDraw);//Without this user will not see this change
213 
214     QDomElement group = doc->elementById(nodeId, VAbstractPattern::TagGroup);
215     if (group.isElement())
216     {
217         if(isUndo)
218         {
219             if (group.removeChild(xml).isNull())
220             {
221                 qCDebug(vUndo, "Can't delete item.");
222                 return;
223             }
224 
225             // set the item visible. Because if the undo is done when unvisible and it's not in any group after the
226             // undo, it stays unvisible until the entire drawing is completly rerendered.
227             quint32 objectId = doc->GetParametrUInt(xml, QStringLiteral("object"), NULL_ID_STR);
228             quint32 toolId = doc->GetParametrUInt(xml, QStringLiteral("tool"), NULL_ID_STR);
229             VDataTool* tool = VAbstractPattern::getTool(toolId);
230             tool->GroupVisibility(objectId,true);
231         }
232         else // is redo
233         {
234 
235             if (group.appendChild(xml).isNull())
236             {
237                 qCDebug(vUndo, "Can't add item.");
238                 return;
239             }
240         }
241 
242         doc->SetModified(true);
243         emit VAbstractValApplication::VApp()->getCurrentDocument()->patternChanged(false);
244 
245         QDomElement groups = doc->CreateGroups();
246         if (not groups.isNull())
247         {
248             doc->ParseGroups(groups);
249         } else
250         {
251             qCDebug(vUndo, "Can't get tag Groups.");
252             return;
253         }
254 
255         emit UpdateGroups();
256     }
257     else
258     {
259         qCDebug(vUndo, "Can't get group by id = %u.", nodeId);
260         return;
261     }
262 
263     VMainGraphicsView::NewSceneRect(VAbstractValApplication::VApp()->getCurrentScene(),
264                                     VAbstractValApplication::VApp()->getSceneView());
265     if (VAbstractValApplication::VApp()->GetDrawMode() == Draw::Calculation)
266     {
267         emit doc->SetCurrentPP(nameActivDraw);//Return current pattern piece after undo
268     }
269 }
270 
271 //RemoveItemFromGroup
272 //---------------------------------------------------------------------------------------------------------------------
RemoveItemFromGroup(const QDomElement & xml,VAbstractPattern * doc,quint32 groupId,QUndoCommand * parent)273 RemoveItemFromGroup::RemoveItemFromGroup(const QDomElement &xml, VAbstractPattern *doc, quint32 groupId,
274                                          QUndoCommand *parent)
275     : VUndoCommand(xml, doc, parent), nameActivDraw(doc->GetNameActivPP())
276 {
277     setText(tr("Remove item from group"));
278     nodeId = groupId;
279 }
280 
281 //---------------------------------------------------------------------------------------------------------------------
undo()282 void RemoveItemFromGroup::undo()
283 {
284     qCDebug(vUndo, "Undo the remove item from group");
285     performUndoRedo(true);
286 }
287 
288 //---------------------------------------------------------------------------------------------------------------------
redo()289 void RemoveItemFromGroup::redo()
290 {
291     qCDebug(vUndo, "Redo the add item to group");
292     performUndoRedo(false);
293 }
294 
295 //---------------------------------------------------------------------------------------------------------------------
performUndoRedo(bool isUndo)296 void RemoveItemFromGroup::performUndoRedo(bool isUndo)
297 {
298     doc->ChangeActivPP(nameActivDraw);//Without this user will not see this change
299 
300     QDomElement group = doc->elementById(nodeId, VAbstractPattern::TagGroup);
301     if (group.isElement())
302     {
303         if(isUndo)
304         {
305             if (group.appendChild(xml).isNull())
306             {
307                 qCDebug(vUndo, "Can't add the item.");
308                 return;
309             }
310         }
311         else // is redo
312         {
313             if (group.removeChild(xml).isNull())
314             {
315                 qCDebug(vUndo, "Can't delete item.");
316                 return;
317             }
318 
319             // set the item visible. Because if the undo is done when unvisibile and it's not in any group after the
320             // undo, it stays unvisible until the entire drawing is completly rerendered.
321             quint32 objectId = doc->GetParametrUInt(xml, QStringLiteral("object"), NULL_ID_STR);
322             quint32 toolId = doc->GetParametrUInt(xml, QStringLiteral("tool"), NULL_ID_STR);
323             VDataTool* tool = VAbstractPattern::getTool(toolId);
324             tool->GroupVisibility(objectId,true);
325         }
326 
327         doc->SetModified(true);
328         emit VAbstractValApplication::VApp()->getCurrentDocument()->patternChanged(false);
329 
330         QDomElement groups = doc->CreateGroups();
331         if (not groups.isNull())
332         {
333             doc->ParseGroups(groups);
334         } else
335         {
336             qCDebug(vUndo, "Can't get tag Groups.");
337             return;
338         }
339 
340         emit UpdateGroups();
341     }
342     else
343     {
344         qCDebug(vUndo, "Can't get group by id = %u.", nodeId);
345         return;
346     }
347 
348     VMainGraphicsView::NewSceneRect(VAbstractValApplication::VApp()->getCurrentScene(),
349                                     VAbstractValApplication::VApp()->getSceneView());
350 
351     if (VAbstractValApplication::VApp()->GetDrawMode() == Draw::Calculation)
352     {
353         emit doc->SetCurrentPP(nameActivDraw);//Return current pattern piece after undo
354     }
355 }
356 
357 //ChangeGroupVisibility
358 //---------------------------------------------------------------------------------------------------------------------
ChangeGroupVisibility(VAbstractPattern * doc,vidtype id,bool visible,QUndoCommand * parent)359 ChangeGroupVisibility::ChangeGroupVisibility(VAbstractPattern *doc, vidtype id, bool visible, QUndoCommand *parent)
360     : VUndoCommand(QDomElement(), doc, parent),
361     m_newVisibility(visible),
362     m_nameActivDraw(doc->GetNameActivPP())
363 {
364     setText(tr("change group visibility"));
365     nodeId = id;
366     QDomElement group = doc->elementById(nodeId, VAbstractPattern::TagGroup);
367     if (group.isElement())
368     {
369         m_oldVisibility = doc->GetParametrBool(group, VAbstractPattern::AttrVisible, trueStr);
370     }
371     else
372     {
373         qDebug("Can't get group by id = %u.", id);
374     }
375 }
376 
377 //---------------------------------------------------------------------------------------------------------------------
undo()378 void ChangeGroupVisibility::undo()
379 {
380     qCDebug(vUndo, "Undo.");
381 
382     Do(m_oldVisibility);
383 }
384 
385 //---------------------------------------------------------------------------------------------------------------------
redo()386 void ChangeGroupVisibility::redo()
387 {
388     qCDebug(vUndo, "Redo.");
389 
390     Do(m_newVisibility);
391 }
392 
393 //---------------------------------------------------------------------------------------------------------------------
Do(bool visible)394 void ChangeGroupVisibility::Do(bool visible)
395 {
396     doc->ChangeActivPP(m_nameActivDraw);//Without this user will not see this change
397 
398     QDomElement group = doc->elementById(nodeId, VAbstractPattern::TagGroup);
399     if (group.isElement())
400     {
401         doc->SetAttribute(group, VAbstractPattern::AttrVisible, visible);
402 
403         QDomElement groups = doc->CreateGroups();
404         if (not groups.isNull())
405         {
406             doc->ParseGroups(groups);
407         }
408 
409         emit UpdateGroup(nodeId, visible);
410 
411         VMainGraphicsView::NewSceneRect(VAbstractValApplication::VApp()->getCurrentScene(),
412                                         VAbstractValApplication::VApp()->getSceneView());
413     }
414     else
415     {
416         qDebug("Can't get group by id = %u.", nodeId);
417     }
418 }
419 
420 //ChangeMultipleGroupsVisibility
421 //---------------------------------------------------------------------------------------------------------------------
ChangeMultipleGroupsVisibility(VAbstractPattern * doc,const QVector<vidtype> & groups,bool visible,QUndoCommand * parent)422 ChangeMultipleGroupsVisibility::ChangeMultipleGroupsVisibility(VAbstractPattern *doc, const QVector<vidtype> &groups,
423                                                                bool visible, QUndoCommand *parent)
424     : VUndoCommand(QDomElement(), doc, parent),
425     m_groups(groups),
426     m_newVisibility(visible),
427     m_nameActivDraw(doc->GetNameActivPP())
428 {
429     setText(tr("change multiple groups visibility"));
430 
431     for(auto & groupId : m_groups)
432     {
433         QDomElement group = doc->elementById(groupId, VAbstractPattern::TagGroup);
434         if (group.isElement())
435         {
436             m_oldVisibility.insert(groupId, doc->GetParametrBool(group, VAbstractPattern::AttrVisible, trueStr));
437         }
438         else
439         {
440             qDebug("Can't get group by id = %u.", groupId);
441         }
442     }
443 
444 }
445 
446 //---------------------------------------------------------------------------------------------------------------------
undo()447 void ChangeMultipleGroupsVisibility::undo()
448 {
449     qCDebug(vUndo, "Undo.");
450 
451     doc->ChangeActivPP(m_nameActivDraw);//Without this user will not see this change
452 
453     QMap<vidtype, bool> groupsState;
454 
455     QMap<vidtype, bool>::const_iterator i = m_oldVisibility.constBegin();
456     while (i != m_oldVisibility.constEnd())
457     {
458         QDomElement group = doc->elementById(i.key(), VAbstractPattern::TagGroup);
459         if (group.isElement())
460         {
461             doc->SetAttribute(group, VAbstractPattern::AttrVisible, i.value());
462             groupsState.insert(i.key(), i.value());
463         }
464         else
465         {
466             qDebug("Can't get group by id = %u.", i.key());
467         }
468         ++i;
469     }
470 
471     if (not groupsState.isEmpty())
472     {
473         QDomElement groups = doc->CreateGroups();
474         if (not groups.isNull())
475         {
476             doc->ParseGroups(groups);
477         }
478 
479         VMainGraphicsView::NewSceneRect(VAbstractValApplication::VApp()->getCurrentScene(),
480                                         VAbstractValApplication::VApp()->getSceneView());
481 
482         emit UpdateMultipleGroups(groupsState);
483     }
484 }
485 
486 //---------------------------------------------------------------------------------------------------------------------
redo()487 void ChangeMultipleGroupsVisibility::redo()
488 {
489     qCDebug(vUndo, "ChangeMultipleGroupsVisibility::redo");
490 
491     doc->ChangeActivPP(m_nameActivDraw);//Without this user will not see this change
492 
493     QMap<vidtype, bool> groupsState;
494 
495     for (auto& groupId : m_groups)
496     {
497         QDomElement group = doc->elementById(groupId, VAbstractPattern::TagGroup);
498         if (group.isElement())
499         {
500             doc->SetAttribute(group, VAbstractPattern::AttrVisible, m_newVisibility);
501             groupsState.insert(groupId, m_newVisibility);
502         }
503         else
504         {
505             qDebug("Can't get group by id = %u.", groupId);
506         }
507     }
508 
509     if (not groupsState.isEmpty())
510     {
511         QDomElement groups = doc->CreateGroups();
512         if (not groups.isNull())
513         {
514             doc->ParseGroups(groups);
515         }
516 
517         VMainGraphicsView::NewSceneRect(VAbstractValApplication::VApp()->getCurrentScene(),
518                                         VAbstractValApplication::VApp()->getSceneView());
519 
520         emit UpdateMultipleGroups(groupsState);
521     }
522 }
523 
524 //DelGroup
525 //---------------------------------------------------------------------------------------------------------------------
DelGroup(VAbstractPattern * doc,quint32 id,QUndoCommand * parent)526 DelGroup::DelGroup(VAbstractPattern *doc, quint32 id, QUndoCommand *parent)
527     : VUndoCommand(QDomElement(), doc, parent), nameActivDraw(doc->GetNameActivPP())
528 {
529     setText(tr("delete group"));
530     nodeId = id;
531     xml = doc->CloneNodeById(nodeId);
532 }
533 
534 //---------------------------------------------------------------------------------------------------------------------
undo()535 void DelGroup::undo()
536 {
537     qCDebug(vUndo, "Undo.");
538 
539     if (VAbstractValApplication::VApp()->GetDrawMode() == Draw::Calculation)
540     {
541         emit doc->SetCurrentPP(nameActivDraw);//Without this user will not see this change
542     }
543 
544     QDomElement groups = doc->CreateGroups();
545     if (not groups.isNull())
546     {
547         groups.appendChild(xml);
548         doc->ParseGroups(groups);
549         emit UpdateGroups();
550     }
551     else
552     {
553         qCDebug(vUndo, "Can't get tag Groups.");
554         return;
555     }
556 
557     VMainGraphicsView::NewSceneRect(VAbstractValApplication::VApp()->getCurrentScene(),
558                                     VAbstractValApplication::VApp()->getSceneView());
559 }
560 
561 //---------------------------------------------------------------------------------------------------------------------
redo()562 void DelGroup::redo()
563 {
564     qCDebug(vUndo, "Redo.");
565 
566     if (VAbstractValApplication::VApp()->GetDrawMode() == Draw::Calculation)
567     {//Keep first!
568         emit doc->SetCurrentPP(nameActivDraw);//Without this user will not see this change
569     }
570     QDomElement groups = doc->CreateGroups();
571     if (not groups.isNull())
572     {
573         QDomElement group = doc->elementById(nodeId, VAbstractPattern::TagGroup);
574         if (group.isElement())
575         {
576             group.setAttribute(VAbstractPattern::AttrVisible, trueStr);
577             doc->ParseGroups(groups);
578             if (groups.removeChild(group).isNull())
579             {
580                 qCDebug(vUndo, "Can't delete group.");
581                 return;
582             }
583             emit UpdateGroups();
584 
585             if (groups.childNodes().isEmpty())
586             {
587                 QDomNode parent = groups.parentNode();
588                 parent.removeChild(groups);
589             }
590         }
591         else
592         {
593             qCDebug(vUndo, "Can't get group by id = %u.", nodeId);
594             return;
595         }
596     }
597     else
598     {
599         qCDebug(vUndo, "Can't get tag Groups.");
600         return;
601     }
602 
603     VMainGraphicsView::NewSceneRect(VAbstractValApplication::VApp()->getCurrentScene(),
604                                     VAbstractValApplication::VApp()->getSceneView());
605 }
606