From 41834c7b363dd3d44f0b7e5dd3f4a5bdff143141 Mon Sep 17 00:00:00 2001
From: dismine <dismine@gmail.com>
Date: Thu, 17 Jul 2014 15:41:48 +0300
Subject: [PATCH] New undo command "rename pattern piece".

--HG--
branch : develop
---
 src/app/dialogs/app/dialoghistory.cpp |  2 +-
 src/app/mainwindow.cpp                | 17 ++---
 src/app/tools/drawTools/vdrawtool.cpp |  2 +-
 src/app/tools/vabstracttool.cpp       |  4 +-
 src/app/undocommands/addtocalc.cpp    |  2 +-
 src/app/undocommands/renamepp.cpp     | 91 +++++++++++++++++++++++++++
 src/app/undocommands/renamepp.h       | 68 ++++++++++++++++++++
 src/app/undocommands/undocommands.pri |  6 +-
 src/app/undocommands/vundocommand.h   |  3 +-
 src/app/xml/vpattern.cpp              | 71 +++++++++++++--------
 src/app/xml/vpattern.h                | 25 ++++----
 11 files changed, 234 insertions(+), 57 deletions(-)
 create mode 100644 src/app/undocommands/renamepp.cpp
 create mode 100644 src/app/undocommands/renamepp.h

diff --git a/src/app/dialogs/app/dialoghistory.cpp b/src/app/dialogs/app/dialoghistory.cpp
index fe0f51806..2b563e297 100644
--- a/src/app/dialogs/app/dialoghistory.cpp
+++ b/src/app/dialogs/app/dialoghistory.cpp
@@ -159,7 +159,7 @@ void DialogHistory::FillTable()
     for (qint32 i = 0; i< history->size(); ++i)
     {
         const VToolRecord tool = history->at(i);
-        if (tool.getNameDraw() != doc->GetNameActivDraw())
+        if (tool.getNameDraw() != doc->GetNameActivPP())
         {
             continue;
         }
diff --git a/src/app/mainwindow.cpp b/src/app/mainwindow.cpp
index 8393184ef..1aa1fa82d 100644
--- a/src/app/mainwindow.cpp
+++ b/src/app/mainwindow.cpp
@@ -40,6 +40,7 @@
 #include "xml/vindividualmeasurements.h"
 #include "widgets/vapplication.h"
 #include "widgets/undoevent.h"
+#include "undocommands/renamepp.h"
 
 #include <QInputDialog>
 #include <QDebug>
@@ -222,24 +223,18 @@ void MainWindow::ActionNewPP()
 
 //---------------------------------------------------------------------------------------------------------------------
 /**
- * @brief OptionDraw help change name of pattern peace.
+ * @brief OptionDraw help change name of pattern piece.
  */
 void MainWindow::OptionDraw()
 {
-    const QString activDraw = doc->GetNameActivDraw();
+    const QString activDraw = doc->GetNameActivPP();
     const QString nameDraw = PatternPieceName(activDraw);
     if (nameDraw.isEmpty())
     {
         return;
     }
-    if (doc->SetNameDraw(nameDraw))
-    {
-        comboBoxDraws->setItemText(comboBoxDraws->findText(activDraw), nameDraw);
-    }
-    else
-    {
-        QMessageBox::warning(this, tr("Error saving change!!!"), tr("Can't save new label of pattern piece"));
-    }
+    RenamePP *renamePP = new RenamePP(doc, nameDraw, comboBoxDraws);
+    qApp->getUndoStack()->push(renamePP);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -2157,7 +2152,7 @@ QString MainWindow::PatternPieceName(const QString &text)
         }
         if (comboBoxDraws->findText(nameDraw) == -1)
         {
-            break;
+            break;//repeate show dialog
         }
     }
     delete dlg;
diff --git a/src/app/tools/drawTools/vdrawtool.cpp b/src/app/tools/drawTools/vdrawtool.cpp
index 41ff393c2..2de9b874d 100644
--- a/src/app/tools/drawTools/vdrawtool.cpp
+++ b/src/app/tools/drawTools/vdrawtool.cpp
@@ -47,7 +47,7 @@ qreal VDrawTool::factor = 1;
  */
 VDrawTool::VDrawTool(VPattern *doc, VContainer *data, quint32 id)
     :VAbstractTool(doc, data, id), ignoreContextMenuEvent(false), ignoreFullUpdate(false),
-      nameActivDraw(doc->GetNameActivDraw()), dialog(nullptr)
+      nameActivDraw(doc->GetNameActivPP()), dialog(nullptr)
 {
     connect(this->doc, &VPattern::ChangedActivPP, this, &VDrawTool::ChangedActivDraw);
     connect(this->doc, &VPattern::ChangedNameDraw, this, &VDrawTool::ChangedNameDraw);
diff --git a/src/app/tools/vabstracttool.cpp b/src/app/tools/vabstracttool.cpp
index c81dbca55..2d71ce587 100644
--- a/src/app/tools/vabstracttool.cpp
+++ b/src/app/tools/vabstracttool.cpp
@@ -345,7 +345,7 @@ void VAbstractTool::AddRecord(const quint32 id, const Tool &toolType, VPattern *
     QVector<VToolRecord> *history = doc->getHistory();
     if (cursor <= 0)
     {
-        history->append(VToolRecord(id, toolType, doc->GetNameActivDraw()));
+        history->append(VToolRecord(id, toolType, doc->GetNameActivPP()));
     }
     else
     {
@@ -359,6 +359,6 @@ void VAbstractTool::AddRecord(const quint32 id, const Tool &toolType, VPattern *
                 break;
             }
         }
-        history->insert(index+1, VToolRecord(id, toolType, doc->GetNameActivDraw()));
+        history->insert(index+1, VToolRecord(id, toolType, doc->GetNameActivPP()));
     }
 }
diff --git a/src/app/undocommands/addtocalc.cpp b/src/app/undocommands/addtocalc.cpp
index 1da22a24a..a6f78144b 100644
--- a/src/app/undocommands/addtocalc.cpp
+++ b/src/app/undocommands/addtocalc.cpp
@@ -31,7 +31,7 @@
 
 //---------------------------------------------------------------------------------------------------------------------
 AddToCalc::AddToCalc(const QDomElement &xml, VPattern *doc, QUndoCommand *parent)
-    : VUndoCommand(xml, doc, parent), nameActivDraw(doc->GetNameActivDraw()), cursor(doc->getCursor())
+    : VUndoCommand(xml, doc, parent), nameActivDraw(doc->GetNameActivPP()), cursor(doc->getCursor())
 {
     setText(tr("Add object"));
     nodeId = doc->GetParametrId(xml);
diff --git a/src/app/undocommands/renamepp.cpp b/src/app/undocommands/renamepp.cpp
new file mode 100644
index 000000000..2937597f7
--- /dev/null
+++ b/src/app/undocommands/renamepp.cpp
@@ -0,0 +1,91 @@
+/************************************************************************
+ **
+ **  @file   renamepp.cpp
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   17 7, 2014
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2014 Valentina project
+ **  <https://bitbucket.org/dismine/valentina> All Rights Reserved.
+ **
+ **  Valentina is free software: you can redistribute it and/or modify
+ **  it under the terms of the GNU General Public License as published by
+ **  the Free Software Foundation, either version 3 of the License, or
+ **  (at your option) any later version.
+ **
+ **  Valentina is distributed in the hope that it will be useful,
+ **  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ **  GNU General Public License for more details.
+ **
+ **  You should have received a copy of the GNU General Public License
+ **  along with Valentina.  If not, see <http://www.gnu.org/licenses/>.
+ **
+ *************************************************************************/
+
+#include "renamepp.h"
+
+#include <QComboBox>
+#include "../options.h"
+#include "../xml/vpattern.h"
+
+
+//---------------------------------------------------------------------------------------------------------------------
+RenamePP::RenamePP(VPattern *doc, const QString &newPPname, QComboBox *combo, QUndoCommand *parent)
+    :VUndoCommand(QDomElement(), doc, parent), combo(combo), newPPname(newPPname), oldPPname(QString())
+{
+    setText(tr("Rename pattern piece"));
+    SCASSERT(combo != nullptr);
+    oldPPname = doc->GetNameActivPP();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+RenamePP::~RenamePP()
+{}
+
+void RenamePP::undo()
+{
+    ChangeName(newPPname, oldPPname);
+}
+
+void RenamePP::redo()
+{
+    ChangeName(oldPPname, newPPname);
+}
+
+bool RenamePP::mergeWith(const QUndoCommand *command)
+{
+    const RenamePP *renameCommand = static_cast<const RenamePP *>(command);
+    SCASSERT(renameCommand != nullptr);
+
+    const QString oldName = renameCommand->getOldPPname();
+    if (newPPname != oldName)
+    {
+        return false;
+    }
+
+    newPPname = renameCommand->getNewPPname();
+    return true;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+int RenamePP::id() const
+{
+    return static_cast<int>(UndoCommand::RenamePP);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void RenamePP::ChangeName(const QString &oldName, const QString &newName)
+{
+    if (doc->ChangeNamePP(oldName, newName))
+    {
+        combo->setItemText(combo->findText(oldName), newName);
+    }
+    else
+    {
+        qWarning()<<"Can't change pattern piece name";
+    }
+}
diff --git a/src/app/undocommands/renamepp.h b/src/app/undocommands/renamepp.h
new file mode 100644
index 000000000..36183986f
--- /dev/null
+++ b/src/app/undocommands/renamepp.h
@@ -0,0 +1,68 @@
+/************************************************************************
+ **
+ **  @file   renamepp.h
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   17 7, 2014
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2014 Valentina project
+ **  <https://bitbucket.org/dismine/valentina> All Rights Reserved.
+ **
+ **  Valentina is free software: you can redistribute it and/or modify
+ **  it under the terms of the GNU General Public License as published by
+ **  the Free Software Foundation, either version 3 of the License, or
+ **  (at your option) any later version.
+ **
+ **  Valentina is distributed in the hope that it will be useful,
+ **  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ **  GNU General Public License for more details.
+ **
+ **  You should have received a copy of the GNU General Public License
+ **  along with Valentina.  If not, see <http://www.gnu.org/licenses/>.
+ **
+ *************************************************************************/
+
+#ifndef RENAMEPP_H
+#define RENAMEPP_H
+
+#include "vundocommand.h"
+class QComboBox;
+
+class RenamePP :public VUndoCommand
+{
+    Q_OBJECT
+public:
+    RenamePP(VPattern *doc, const QString &newPPname, QComboBox *combo, QUndoCommand *parent = 0);
+    virtual ~RenamePP();
+
+    virtual void undo();
+    virtual void redo();
+    virtual bool mergeWith(const QUndoCommand *command);
+    virtual int  id() const;
+    QString      getNewPPname() const;
+    QString      getOldPPname() const;
+private:
+    Q_DISABLE_COPY(RenamePP)
+    QComboBox *combo;
+    QString   newPPname;
+    QString   oldPPname;
+    void      ChangeName(const QString &oldName, const QString &newName);
+};
+
+//---------------------------------------------------------------------------------------------------------------------
+inline QString RenamePP::getNewPPname() const
+{
+    return newPPname;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+inline QString RenamePP::getOldPPname() const
+{
+    return oldPPname;
+}
+
+#endif // RENAMEPP_H
diff --git a/src/app/undocommands/undocommands.pri b/src/app/undocommands/undocommands.pri
index 8e0987448..09dba7baa 100644
--- a/src/app/undocommands/undocommands.pri
+++ b/src/app/undocommands/undocommands.pri
@@ -13,7 +13,8 @@ HEADERS += \
     undocommands/adddet.h \
     undocommands/adduniondetails.h \
     undocommands/deletedetail.h \
-    undocommands/vundocommand.h
+    undocommands/vundocommand.h \
+    undocommands/renamepp.h
     
 
 SOURCES += \
@@ -31,5 +32,6 @@ SOURCES += \
     undocommands/adddet.cpp \
     undocommands/adduniondetails.cpp \
     undocommands/deletedetail.cpp \
-    undocommands/vundocommand.cpp
+    undocommands/vundocommand.cpp \
+    undocommands/renamepp.cpp
     
diff --git a/src/app/undocommands/vundocommand.h b/src/app/undocommands/vundocommand.h
index b99be4a3e..c087e5958 100644
--- a/src/app/undocommands/vundocommand.h
+++ b/src/app/undocommands/vundocommand.h
@@ -41,7 +41,8 @@ enum class UndoCommand: char { AddPatternPiece,
                                SaveDetailOptions,
                                MoveDetail,
                                DeleteTool,
-                               DeletePatternPiece
+                               DeletePatternPiece,
+                               RenamePP
                              };
 
 class VPattern;
diff --git a/src/app/xml/vpattern.cpp b/src/app/xml/vpattern.cpp
index 62ee02e81..114196813 100644
--- a/src/app/xml/vpattern.cpp
+++ b/src/app/xml/vpattern.cpp
@@ -75,7 +75,7 @@ const QString VPattern::IncrementDescription = QStringLiteral("description");
 //---------------------------------------------------------------------------------------------------------------------
 VPattern::VPattern(VContainer *data, Draw *mode, VMainGraphicsScene *sceneDraw,
                    VMainGraphicsScene *sceneDetail, QObject *parent)
-    : QObject(parent), VDomDocument(data), nameActivDraw(QString()), tools(QHash<quint32, VDataTool*>()),
+    : QObject(parent), VDomDocument(data), nameActivPP(QString()), tools(QHash<quint32, VDataTool*>()),
       history(QVector<VToolRecord>()), cursor(0), patternPieces(QStringList()), mode(mode), sceneDraw(sceneDraw),
       sceneDetail(sceneDetail)
 {
@@ -129,9 +129,9 @@ void VPattern::CreateEmptyFile(const QString &tablePath)
 void VPattern::ChangeActivPP(const QString &name, const Document &parse)
 {
     Q_ASSERT_X(name.isEmpty() == false, "ChangeActivPP", "name pattern piece is empty");
-    if (CheckNamePP(name))
+    if (CheckExistNamePP(name) && this->nameActivPP != name)
     {
-        this->nameActivDraw = name;
+        this->nameActivPP = name;
         if (parse == Document::FullParse)
         {
             emit ChangedActivPP(name);
@@ -147,7 +147,7 @@ void VPattern::ChangeActivPP(const QString &name, const Document &parse)
  */
 bool VPattern::GetActivDrawElement(QDomElement &element) const
 {
-    if (nameActivDraw.isEmpty() == false)
+    if (nameActivPP.isEmpty() == false)
     {
         const QDomNodeList elements = this->documentElement().elementsByTagName( TagDraw );
         if (elements.size() == 0)
@@ -160,7 +160,7 @@ bool VPattern::GetActivDrawElement(QDomElement &element) const
             if (element.isNull() == false)
             {
                 const QString fieldName = element.attribute( AttrName );
-                if ( fieldName == nameActivDraw )
+                if ( fieldName == nameActivPP )
                 {
                     return true;
                 }
@@ -186,15 +186,15 @@ bool VPattern::appendPP(const QString &name)
     {
         return false;
     }
-    if (CheckNamePP(name) == false)
+    if (CheckExistNamePP(name) == false)
     {
-        if (nameActivDraw.isEmpty())
+        if (nameActivPP.isEmpty())
         {
             SetActivPP(name);
         }
         else
         {
-            this->nameActivDraw = name;
+            this->nameActivPP = name;
             emit ChangedActivPP(name);
         }
         return true;
@@ -204,26 +204,43 @@ bool VPattern::appendPP(const QString &name)
 
 //---------------------------------------------------------------------------------------------------------------------
 /**
- * @brief SetNameDraw change current pattern peace.
- * @param name pattern peace name.
+ * @brief ChangeNamePP change pattern piece name.
+ * @param oldName old pattern piece name.
+ * @param newName new pattern piece name.
  * @return true if success.
  */
-bool VPattern::SetNameDraw(const QString &name)
+bool VPattern::ChangeNamePP(const QString& oldName, const QString &newName)
 {
-    Q_ASSERT_X(name.isEmpty() == false, "SetNameDraw", "name draw is empty");
-    const QString oldName = nameActivDraw;
-    QDomElement element;
-    if (GetActivDrawElement(element))
+    Q_ASSERT_X(newName.isEmpty() == false, "SetNamePP", "new name pattern piece is empty");
+    Q_ASSERT_X(oldName.isEmpty() == false, "SetNamePP", "old name pattern piece is empty");
+
+    if (CheckExistNamePP(oldName) == false)
     {
-        nameActivDraw = name;
-        element.setAttribute(AttrName, nameActivDraw);
-        emit patternChanged(false);
-        emit ChangedNameDraw(oldName, nameActivDraw);
+        qDebug()<<"Do not exist pattern piece with name"<<oldName;
+        return false;
+    }
+
+    if (CheckExistNamePP(newName))
+    {
+        qDebug()<<"Already exist pattern piece with name"<<newName;
+        return false;
+    }
+
+    QDomElement ppElement = GetPPElement(oldName);
+    if (ppElement.isElement())
+    {
+        if (nameActivPP == oldName)
+        {
+            nameActivPP = newName;
+        }
+        ppElement.setAttribute(AttrName, newName);
+        emit patternChanged(false);//For situation when we change name directly, without undocommands.
+        emit ChangedNameDraw(oldName, newName);
         return true;
     }
     else
     {
-        qDebug()<<"Can't find activ draw"<<Q_FUNC_INFO;
+        qDebug()<<"Can't find pattern piece node with name"<<oldName<<Q_FUNC_INFO;
         return false;
     }
 }
@@ -254,7 +271,7 @@ void VPattern::Parse(const Document &parse)
                     case 0: // TagDraw
                         if (parse == Document::FullParse)
                         {
-                            if (nameActivDraw.isEmpty())
+                            if (nameActivPP.isEmpty())
                             {
                                 SetActivPP(GetParametrString(domElement, AttrName));
                             }
@@ -349,7 +366,7 @@ void VPattern::setCurrentData()
             for (qint32 i = 0; i < history.size(); ++i)
             {
                 const VToolRecord tool = history.at(i);
-                if (tool.getNameDraw() == nameActivDraw)
+                if (tool.getNameDraw() == nameActivPP)
                 {
                     id = tool.getId();
                 }
@@ -469,7 +486,7 @@ quint32 VPattern::SPointActiveDraw()
  * @param name pattern peace name.
  * @return true if exist.
  */
-bool VPattern::CheckNamePP(const QString &name) const
+bool VPattern::CheckExistNamePP(const QString &name) const
 {
     Q_ASSERT_X(name.isEmpty() == false, "CheckNameDraw", "name draw is empty");
     const QDomNodeList elements = this->documentElement().elementsByTagName( TagDraw );
@@ -499,7 +516,7 @@ bool VPattern::CheckNamePP(const QString &name) const
 void VPattern::SetActivPP(const QString &name)
 {
     Q_ASSERT_X(name.isEmpty() == false, "SetActivPP", "name pattern piece is empty");
-    this->nameActivDraw = name;
+    this->nameActivPP = name;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1019,7 +1036,7 @@ void VPattern::ParsePointElement(VMainGraphicsScene *scene, QDomElement &domElem
                 }
                 if (parse == Document::FullParse)
                 {
-                    spoint = new VToolSinglePoint(this, data, id, Source::FromFile, nameActivDraw, MPath());
+                    spoint = new VToolSinglePoint(this, data, id, Source::FromFile, nameActivPP, MPath());
                     scene->addItem(spoint);
                     connect(spoint, &VToolSinglePoint::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
                     connect(scene, &VMainGraphicsScene::NewFactor, spoint, &VToolSinglePoint::SetFactor);
@@ -1806,7 +1823,7 @@ void VPattern::PrepareForParse(const Document &parse)
         TestUniqueId();
         data->Clear();
         UpdateMeasurements();
-        nameActivDraw.clear();
+        nameActivPP.clear();
         sceneDraw->clear();
         sceneDetail->clear();
         patternPieces.clear();
@@ -1913,7 +1930,7 @@ QRectF VPattern::ActiveDrawBoundingRect() const
     for (qint32 i = 0; i< history.size(); ++i)
     {
         const VToolRecord tool = history.at(i);
-        if (tool.getNameDraw() == nameActivDraw)
+        if (tool.getNameDraw() == nameActivPP)
         {
             switch ( tool.getTypeTool() )
             {
diff --git a/src/app/xml/vpattern.h b/src/app/xml/vpattern.h
index 4c7a6f54b..9880aeda4 100644
--- a/src/app/xml/vpattern.h
+++ b/src/app/xml/vpattern.h
@@ -56,12 +56,17 @@ class VPattern : public QObject, public VDomDocument
 public:
     VPattern(VContainer *data, Draw *mode, VMainGraphicsScene *sceneDraw, VMainGraphicsScene *sceneDetail,
              QObject *parent = nullptr);
+
     void           CreateEmptyFile(const QString &tablePath);
     void           ChangeActivPP(const QString& name, const Document &parse = Document::FullParse);
-    QString        GetNameActivDraw() const;
+    QString        GetNameActivPP() const;
     bool           GetActivDrawElement(QDomElement &element) const;
     bool           appendPP(const QString& name);
-    bool           SetNameDraw(const QString& name);
+    bool           ChangeNamePP(const QString& oldName, const QString &newName);
+    QDomElement    GetPPElement(const QString &name);
+    bool           CheckExistNamePP(const QString& name) const;
+    int            CountPP() const;
+
     void           Parse(const Document &parse);
     QHash<quint32, VDataTool*>* getTools();
     VDataTool*     getTool(const quint32 &id);
@@ -108,9 +113,6 @@ public:
     static const QString IncrementDescription;
     virtual bool   SaveDocument(const QString &fileName);
     QStringList    getPatternPieces() const;
-    QDomElement    GetPPElement(const QString &name);
-    bool           CheckNamePP(const QString& name) const;
-    int            CountPP() const;
     QRectF         ActiveDrawBoundingRect() const;
     quint32        GetParametrId(const QDomElement& domElement) const;
 signals:
@@ -120,7 +122,7 @@ signals:
      */
     void           ChangedActivPP(const QString &newName);
     /**
-     * @brief ChangedNameDraw save new name active pattern peace.
+     * @brief ChangedNameDraw save new name pattern peace.
      * @param oldName old name.
      * @param newName new name.
      */
@@ -160,7 +162,7 @@ private:
     Q_DISABLE_COPY(VPattern)
 
     /** @brief nameActivDraw name current pattern peace. */
-    QString        nameActivDraw;
+    QString        nameActivPP;
 
     /** @brief tools list with pointer on tools. */
     QHash<quint32, VDataTool*> tools;
@@ -171,6 +173,7 @@ private:
     /** @brief cursor cursor keep id tool after which we will add new tool in file. */
     quint32        cursor;
 
+    /** @brief patternPieces list of patern pieces names for combobox*/
     QStringList    patternPieces;
 
     /** @brief mode current draw mode. */
@@ -214,12 +217,12 @@ private:
 
 //---------------------------------------------------------------------------------------------------------------------
 /**
- * @brief GetNameActivDraw return current pattern peace name.
- * @return pattern peace name.
+ * @brief GetNameActivPP return current pattern piece name.
+ * @return pattern piece name.
  */
-inline QString VPattern::GetNameActivDraw() const
+inline QString VPattern::GetNameActivPP() const
 {
-    return nameActivDraw;
+    return nameActivPP;
 }
 
 //---------------------------------------------------------------------------------------------------------------------