From f5483e76cf4cce7018e502afde9e8e2253f534ef Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 16 Sep 2014 12:30:17 +0200 Subject: [PATCH 01/12] added refnum counter column to cells table --- apps/opencs/model/world/columnimp.hpp | 27 +++++++++++++++++++++++++++ apps/opencs/model/world/columns.cpp | 1 + apps/opencs/model/world/columns.hpp | 1 + apps/opencs/model/world/data.cpp | 1 + 4 files changed, 30 insertions(+) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 73dfc9ac0..2e6812636 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -1918,6 +1918,33 @@ namespace CSMWorld return true; } }; + + template + struct RefNumCounterColumn : public Column + { + RefNumCounterColumn() + : Column (Columns::ColumnId_RefNumCounter, ColumnBase::Display_Integer, 0) + {} + + virtual QVariant get (const Record& record) const + { + return static_cast (record.get().mRefNumCounter); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mRefNumCounter = data.toInt(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 7d789e2f7..2b34e6c7d 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -184,6 +184,7 @@ namespace CSMWorld { ColumnId_DefaultProfile, "Default Profile" }, { ColumnId_BypassNewGame, "Bypass New Game" }, { ColumnId_GlobalProfile, "Global Profile" }, + { ColumnId_RefNumCounter, "RefNum Counter" }, { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index a1ddaabec..369d53b9d 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -177,6 +177,7 @@ namespace CSMWorld ColumnId_DefaultProfile = 165, ColumnId_BypassNewGame = 166, ColumnId_GlobalProfile = 167, + ColumnId_RefNumCounter = 168, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index ec69b46bb..fbee1d538 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -200,6 +200,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mCells.addColumn (new FlagColumn (Columns::ColumnId_InteriorWater, ESM::Cell::HasWater)); mCells.addColumn (new FlagColumn (Columns::ColumnId_InteriorSky, ESM::Cell::QuasiEx)); mCells.addColumn (new RegionColumn); + mCells.addColumn (new RefNumCounterColumn); mEnchantments.addColumn (new StringIdColumn); mEnchantments.addColumn (new RecordStateColumn); From 90b45e09f7f0ec7f4584cfd3788f688186be2de9 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 16 Sep 2014 12:48:10 +0200 Subject: [PATCH 02/12] added refnum column to references tables --- apps/opencs/model/world/columnimp.hpp | 37 +++++++++++++++++++++++++++ apps/opencs/model/world/columns.cpp | 1 + apps/opencs/model/world/columns.hpp | 1 + apps/opencs/model/world/data.cpp | 1 + 4 files changed, 40 insertions(+) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 2e6812636..b93deccb7 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -1944,6 +1944,43 @@ namespace CSMWorld { return true; } + + virtual bool isUserEditable() const + { + return false; + } + }; + + template + struct RefNumColumn : public Column + { + RefNumColumn() + : Column (Columns::ColumnId_RefNum, ColumnBase::Display_Integer, 0) + {} + + virtual QVariant get (const Record& record) const + { + return static_cast (record.get().mRefNum.mIndex); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mRefNum.mIndex = data.toInt(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + + virtual bool isUserEditable() const + { + return false; + } }; } diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 2b34e6c7d..90af20059 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -185,6 +185,7 @@ namespace CSMWorld { ColumnId_BypassNewGame, "Bypass New Game" }, { ColumnId_GlobalProfile, "Global Profile" }, { ColumnId_RefNumCounter, "RefNum Counter" }, + { ColumnId_RefNum, "RefNum" }, { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 369d53b9d..5da1765a4 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -178,6 +178,7 @@ namespace CSMWorld ColumnId_BypassNewGame = 166, ColumnId_GlobalProfile = 167, ColumnId_RefNumCounter = 168, + ColumnId_RefNum = 169, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index fbee1d538..bb4fa0b43 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -252,6 +252,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mRefs.addColumn (new KeyColumn); mRefs.addColumn (new TrapColumn); mRefs.addColumn (new OwnerGlobalColumn); + mRefs.addColumn (new RefNumColumn); mFilters.addColumn (new StringIdColumn); mFilters.addColumn (new RecordStateColumn); From 70275350de7daaac8a131895513f8acdaef07ff8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 16 Sep 2014 13:28:11 +0200 Subject: [PATCH 03/12] rewrote command generation in GenericCreator --- apps/opencs/view/world/genericcreator.cpp | 23 ++++++++++++++--------- apps/opencs/view/world/genericcreator.hpp | 15 +++++++++++---- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index e905cfef6..afddda454 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -50,6 +50,12 @@ std::string CSVWorld::GenericCreator::getId() const void CSVWorld::GenericCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const {} +void CSVWorld::GenericCreator::pushCommand (std::auto_ptr command, + const std::string& id) +{ + mUndoStack.push (command.release()); +} + CSMWorld::Data& CSVWorld::GenericCreator::getData() const { return mData; @@ -173,24 +179,23 @@ void CSVWorld::GenericCreator::create() { std::string id = getId(); + std::auto_ptr command; + if (mCloneMode) { - std::auto_ptr command (new CSMWorld::CloneCommand ( + command.reset (new CSMWorld::CloneCommand ( dynamic_cast (*mData.getTableModel(mListId)), mClonedId, id, mClonedType)); - - mUndoStack.push(command.release()); - } else { - std::auto_ptr command (new CSMWorld::CreateCommand ( - dynamic_cast (*mData.getTableModel (mListId)), id)); + command.reset (new CSMWorld::CreateCommand ( + dynamic_cast (*mData.getTableModel (mListId)), id)); - configureCreateCommand (*command); - - mUndoStack.push (command.release()); + configureCreateCommand (dynamic_cast (*command)); } + pushCommand (command, id); + emit done(); emit requestFocus(id); } diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index ea099248e..4cd2fce2f 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -1,16 +1,19 @@ #ifndef CSV_WORLD_GENERICCREATOR_H #define CSV_WORLD_GENERICCREATOR_H +#include + +#include "../../model/world/universalid.hpp" + +#include "creator.hpp" + class QString; class QPushButton; class QLineEdit; class QHBoxLayout; class QComboBox; class QLabel; - -#include "creator.hpp" - -#include "../../model/world/universalid.hpp" +class QUndoCommand; namespace CSMWorld { @@ -56,8 +59,12 @@ namespace CSVWorld virtual std::string getId() const; + /// \note This function is not called in case of a clone operation. virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; + virtual void pushCommand (std::auto_ptr command, + const std::string& id); + CSMWorld::Data& getData() const; const CSMWorld::UniversalId& getCollectionId() const; From 33243c8c16dca89fc02af3a114401597d1e2767b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 18 Sep 2014 11:37:23 +0200 Subject: [PATCH 04/12] move code for storing old value from ModifyCommand constructor to redo function (allows use of the command on records that haven't been created at the time of construction) --- apps/opencs/model/world/commands.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index b60ffeb29..d7bce5da9 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -10,13 +10,12 @@ CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelI const QVariant& new_, QUndoCommand* parent) : QUndoCommand (parent), mModel (model), mIndex (index), mNew (new_) { - mOld = mModel.data (mIndex, Qt::EditRole); - setText ("Modify " + mModel.headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString()); } void CSMWorld::ModifyCommand::redo() { + mOld = mModel.data (mIndex, Qt::EditRole); mModel.setData (mIndex, mNew); } From e93ab383eaa9ccfe46bf141573f2de191103a872 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 18 Sep 2014 12:25:17 +0200 Subject: [PATCH 05/12] set refnum and increment refnum counter when creating a new reference --- apps/opencs/model/doc/savingstages.cpp | 29 +---------------- apps/opencs/model/world/ref.cpp | 4 +-- apps/opencs/view/world/genericcreator.cpp | 5 +++ apps/opencs/view/world/genericcreator.hpp | 2 ++ apps/opencs/view/world/referencecreator.cpp | 35 +++++++++++++++++++++ apps/opencs/view/world/referencecreator.hpp | 5 ++- 6 files changed, 48 insertions(+), 32 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 17c2b4dca..d62947df6 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -284,20 +284,6 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) // write references if (references!=mState.getSubRecords().end()) { - // first pass: find highest RefNum - int lastRefNum = -1; - - for (std::vector::const_iterator iter (references->second.begin()); - iter!=references->second.end(); ++iter) - { - const CSMWorld::Record& ref = - mDocument.getData().getReferences().getRecord (*iter); - - if (ref.get().mRefNum.mContentFile==0 && ref.get().mRefNum.mIndex>lastRefNum) - lastRefNum = ref.get().mRefNum.mIndex; - } - - // second pass: write for (std::vector::const_iterator iter (references->second.begin()); iter!=references->second.end(); ++iter) { @@ -307,20 +293,7 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) if (ref.mState==CSMWorld::RecordBase::State_Modified || ref.mState==CSMWorld::RecordBase::State_ModifiedOnly) { - if (ref.get().mRefNum.mContentFile==-2) - { - if (lastRefNum>=0xffffff) - throw std::runtime_error ( - "RefNums exhausted in cell: " + cell.get().mId); - - ESM::CellRef ref2 = ref.get(); - ref2.mRefNum.mContentFile = 0; - ref2.mRefNum.mIndex = ++lastRefNum; - - ref2.save (mState.getWriter()); - } - else - ref.get().save (mState.getWriter()); + ref.get().save (mState.getWriter()); } else if (ref.mState==CSMWorld::RecordBase::State_Deleted) { diff --git a/apps/opencs/model/world/ref.cpp b/apps/opencs/model/world/ref.cpp index d1bd771f8..f3c1b0b73 100644 --- a/apps/opencs/model/world/ref.cpp +++ b/apps/opencs/model/world/ref.cpp @@ -4,7 +4,5 @@ CSMWorld::CellRef::CellRef() { mRefNum.mIndex = 0; - - // special marker: This reference does not have a RefNum assign to it yet. - mRefNum.mContentFile = -2; + mRefNum.mContentFile = 0; } \ No newline at end of file diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index afddda454..099fdd09c 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -61,6 +61,11 @@ CSMWorld::Data& CSVWorld::GenericCreator::getData() const return mData; } +QUndoStack& CSVWorld::GenericCreator::getUndoStack() +{ + return mUndoStack; +} + const CSMWorld::UniversalId& CSVWorld::GenericCreator::getCollectionId() const { return mListId; diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index 4cd2fce2f..a9ef87749 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -67,6 +67,8 @@ namespace CSVWorld CSMWorld::Data& getData() const; + QUndoStack& getUndoStack(); + const CSMWorld::UniversalId& getCollectionId() const; std::string getNamespace() const; diff --git a/apps/opencs/view/world/referencecreator.cpp b/apps/opencs/view/world/referencecreator.cpp index 6b8e02da0..46d759ff2 100644 --- a/apps/opencs/view/world/referencecreator.cpp +++ b/apps/opencs/view/world/referencecreator.cpp @@ -23,6 +23,41 @@ void CSVWorld::ReferenceCreator::configureCreateCommand (CSMWorld::CreateCommand command.addValue (index, mCell->text()); } +void CSVWorld::ReferenceCreator::pushCommand (std::auto_ptr command, + const std::string& id) +{ + // get the old count + std::string cellId = mCell->text().toUtf8().constData(); + + CSMWorld::IdTable& cellTable = dynamic_cast ( + *getData().getTableModel (CSMWorld::UniversalId::Type_Cells)); + + int countColumn = cellTable.findColumnIndex (CSMWorld::Columns::ColumnId_RefNumCounter); + + QModelIndex countIndex = cellTable.getModelIndex (cellId, countColumn); + + int count = cellTable.data (countIndex).toInt(); + + // command for setting the refnum in the newly created reference + CSMWorld::IdTable& referenceTable = dynamic_cast ( + *getData().getTableModel (CSMWorld::UniversalId::Type_References)); + + int refNumColumn = referenceTable.findColumnIndex (CSMWorld::Columns::ColumnId_RefNum); + + std::auto_ptr setRefNum (new CSMWorld::ModifyCommand + (referenceTable, referenceTable.getModelIndex (id, refNumColumn), count)); + + // command for incrementing counter + std::auto_ptr increment (new CSMWorld::ModifyCommand + (cellTable, countIndex, count+1)); + + getUndoStack().beginMacro (command->text()); + GenericCreator::pushCommand (command, id); + getUndoStack().push (setRefNum.release()); + getUndoStack().push (increment.release()); + getUndoStack().endMacro(); +} + CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id) : GenericCreator (data, undoStack, id) diff --git a/apps/opencs/view/world/referencecreator.hpp b/apps/opencs/view/world/referencecreator.hpp index 12fb12dd9..a0e98a9a4 100644 --- a/apps/opencs/view/world/referencecreator.hpp +++ b/apps/opencs/view/world/referencecreator.hpp @@ -20,12 +20,15 @@ namespace CSVWorld virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; + virtual void pushCommand (std::auto_ptr command, + const std::string& id); + public: ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id); - virtual void cloneMode(const std::string& originId, + virtual void cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type); virtual void reset(); From 6fbffdb98f314695a937e38a836b6c4724bd627a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 18 Sep 2014 12:39:29 +0200 Subject: [PATCH 06/12] fixed reference creator error handling --- apps/opencs/view/world/referencecreator.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/world/referencecreator.cpp b/apps/opencs/view/world/referencecreator.cpp index 46d759ff2..5e680b97d 100644 --- a/apps/opencs/view/world/referencecreator.cpp +++ b/apps/opencs/view/world/referencecreator.cpp @@ -82,7 +82,9 @@ void CSVWorld::ReferenceCreator::reset() std::string CSVWorld::ReferenceCreator::getErrors() const { - std::string errors = GenericCreator::getErrors(); + // We are ignoring errors coming from GenericCreator here, because the ID of the new + // record is internal and requires neither user input nor verification. + std::string errors; if (mCloneMode) { From 3add4bdf358cfe10419cf988e10feb52afd56b9f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 18 Sep 2014 13:41:29 +0200 Subject: [PATCH 07/12] rewrote refnum handling code (fixes broken reference creation, but not reference cloning yet) --- apps/opencs/view/world/referencecreator.cpp | 36 ++++++++++++++------- apps/opencs/view/world/referencecreator.hpp | 3 ++ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/apps/opencs/view/world/referencecreator.cpp b/apps/opencs/view/world/referencecreator.cpp index 5e680b97d..561ac87da 100644 --- a/apps/opencs/view/world/referencecreator.cpp +++ b/apps/opencs/view/world/referencecreator.cpp @@ -16,11 +16,19 @@ std::string CSVWorld::ReferenceCreator::getId() const void CSVWorld::ReferenceCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const { - int index = + // Set cellID + int cellIdColumn = dynamic_cast (*getData().getTableModel (getCollectionId())). findColumnIndex (CSMWorld::Columns::ColumnId_Cell); - command.addValue (index, mCell->text()); + command.addValue (cellIdColumn, mCell->text()); + + // Set RefNum + int refNumColumn = dynamic_cast ( + *getData().getTableModel (CSMWorld::UniversalId::Type_References)). + findColumnIndex (CSMWorld::Columns::ColumnId_RefNum); + + command.addValue (refNumColumn, getRefNumCount()); } void CSVWorld::ReferenceCreator::pushCommand (std::auto_ptr command, @@ -38,26 +46,30 @@ void CSVWorld::ReferenceCreator::pushCommand (std::auto_ptr comman int count = cellTable.data (countIndex).toInt(); - // command for setting the refnum in the newly created reference - CSMWorld::IdTable& referenceTable = dynamic_cast ( - *getData().getTableModel (CSMWorld::UniversalId::Type_References)); - - int refNumColumn = referenceTable.findColumnIndex (CSMWorld::Columns::ColumnId_RefNum); - - std::auto_ptr setRefNum (new CSMWorld::ModifyCommand - (referenceTable, referenceTable.getModelIndex (id, refNumColumn), count)); - // command for incrementing counter std::auto_ptr increment (new CSMWorld::ModifyCommand (cellTable, countIndex, count+1)); getUndoStack().beginMacro (command->text()); GenericCreator::pushCommand (command, id); - getUndoStack().push (setRefNum.release()); getUndoStack().push (increment.release()); getUndoStack().endMacro(); } +int CSVWorld::ReferenceCreator::getRefNumCount() const +{ + std::string cellId = mCell->text().toUtf8().constData(); + + CSMWorld::IdTable& cellTable = dynamic_cast ( + *getData().getTableModel (CSMWorld::UniversalId::Type_Cells)); + + int countColumn = cellTable.findColumnIndex (CSMWorld::Columns::ColumnId_RefNumCounter); + + QModelIndex countIndex = cellTable.getModelIndex (cellId, countColumn); + + return cellTable.data (countIndex).toInt(); +} + CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id) : GenericCreator (data, undoStack, id) diff --git a/apps/opencs/view/world/referencecreator.hpp b/apps/opencs/view/world/referencecreator.hpp index a0e98a9a4..c463469e4 100644 --- a/apps/opencs/view/world/referencecreator.hpp +++ b/apps/opencs/view/world/referencecreator.hpp @@ -23,6 +23,9 @@ namespace CSVWorld virtual void pushCommand (std::auto_ptr command, const std::string& id); + /// Return next available RefNum for the cell the creator is currently operating on + int getRefNumCount() const; + public: ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack, From 7733df239efee09ea2abfb46583342a8aae94bab Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Sep 2014 10:36:43 +0200 Subject: [PATCH 08/12] made CloneCommand a subclass of CreateCommand --- apps/opencs/model/world/commands.cpp | 32 +++++++++---------- apps/opencs/model/world/commands.hpp | 46 +++++++++++++++------------- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index d7bce5da9..de0e9a4e5 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -24,6 +24,13 @@ void CSMWorld::ModifyCommand::undo() mModel.setData (mIndex, mOld); } + +void CSMWorld::CreateCommand::applyModifications() +{ + for (std::map::const_iterator iter (mValues.begin()); iter!=mValues.end(); ++iter) + mModel.setData (mModel.getModelIndex (mId, iter->first), iter->second); +} + CSMWorld::CreateCommand::CreateCommand (IdTable& model, const std::string& id, QUndoCommand* parent) : QUndoCommand (parent), mModel (model), mId (id), mType (UniversalId::Type_None) { @@ -43,9 +50,7 @@ void CSMWorld::CreateCommand::setType (UniversalId::Type type) void CSMWorld::CreateCommand::redo() { mModel.addRecord (mId, mType); - - for (std::map::const_iterator iter (mValues.begin()); iter!=mValues.end(); ++iter) - mModel.setData (mModel.getModelIndex (mId, iter->first), iter->second); + applyModifications(); } void CSMWorld::CreateCommand::undo() @@ -147,27 +152,22 @@ void CSMWorld::ReorderRowsCommand::undo() CSMWorld::CloneCommand::CloneCommand (CSMWorld::IdTable& model, const std::string& idOrigin, - const std::string& IdDestination, + const std::string& idDestination, const CSMWorld::UniversalId::Type type, - QUndoCommand* parent) : - QUndoCommand (parent), - mModel (model), - mIdOrigin (idOrigin), - mIdDestination (Misc::StringUtils::lowerCase (IdDestination)), - mType (type) + QUndoCommand* parent) +: CreateCommand (model, idDestination, parent), mIdOrigin (idOrigin) { - setText ( ("Clone record " + idOrigin + " to the " + IdDestination).c_str()); + setType (type); + setText ( ("Clone record " + idOrigin + " to the " + idDestination).c_str()); } void CSMWorld::CloneCommand::redo() { - mModel.cloneRecord (mIdOrigin, mIdDestination, mType); - - for (std::map::const_iterator iter (mValues.begin()); iter != mValues.end(); ++iter) - mModel.setData (mModel.getModelIndex (mIdDestination, iter->first), iter->second); + mModel.cloneRecord (mIdOrigin, mId, mType); + applyModifications(); } void CSMWorld::CloneCommand::undo() { - mModel.removeRow (mModel.getModelIndex (mIdDestination, 0).row()); + mModel.removeRow (mModel.getModelIndex (mId, 0).row()); } \ No newline at end of file diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index 947be68fd..a15c071a8 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -39,32 +39,20 @@ namespace CSMWorld virtual void undo(); }; - class CloneCommand : public QUndoCommand - { - IdTable& mModel; - std::string mIdOrigin; - std::string mIdDestination; - UniversalId::Type mType; - std::map mValues; - - public: - - CloneCommand (IdTable& model, const std::string& idOrigin, - const std::string& IdDestination, - const UniversalId::Type type, - QUndoCommand* parent = 0); - - virtual void redo(); - - virtual void undo(); - }; - class CreateCommand : public QUndoCommand { + std::map mValues; + + protected: + IdTable& mModel; std::string mId; UniversalId::Type mType; - std::map mValues; + + protected: + + /// Apply modifications set via addValue. + void applyModifications(); public: @@ -79,6 +67,22 @@ namespace CSMWorld virtual void undo(); }; + class CloneCommand : public CreateCommand + { + std::string mIdOrigin; + + public: + + CloneCommand (IdTable& model, const std::string& idOrigin, + const std::string& IdDestination, + const UniversalId::Type type, + QUndoCommand* parent = 0); + + virtual void redo(); + + virtual void undo(); + }; + class RevertCommand : public QUndoCommand { IdTable& mModel; From 90ad3f332a44b60465346bfef56966828dd8d13c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Sep 2014 12:37:25 +0200 Subject: [PATCH 09/12] extending refnum functionality to cloning (and also enable cloning of references to a different cell) --- apps/opencs/view/world/genericcreator.cpp | 6 +++--- apps/opencs/view/world/genericcreator.hpp | 7 ++++--- apps/opencs/view/world/referencecreator.cpp | 13 +------------ apps/opencs/view/world/referencecreator.hpp | 4 +--- 4 files changed, 9 insertions(+), 21 deletions(-) diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index 099fdd09c..7beaf9c67 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -50,7 +50,7 @@ std::string CSVWorld::GenericCreator::getId() const void CSVWorld::GenericCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const {} -void CSVWorld::GenericCreator::pushCommand (std::auto_ptr command, +void CSVWorld::GenericCreator::pushCommand (std::auto_ptr command, const std::string& id) { mUndoStack.push (command.release()); @@ -184,7 +184,7 @@ void CSVWorld::GenericCreator::create() { std::string id = getId(); - std::auto_ptr command; + std::auto_ptr command; if (mCloneMode) { @@ -196,9 +196,9 @@ void CSVWorld::GenericCreator::create() command.reset (new CSMWorld::CreateCommand ( dynamic_cast (*mData.getTableModel (mListId)), id)); - configureCreateCommand (dynamic_cast (*command)); } + configureCreateCommand (*command); pushCommand (command, id); emit done(); diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index a9ef87749..8d9e32966 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -13,7 +13,6 @@ class QLineEdit; class QHBoxLayout; class QComboBox; class QLabel; -class QUndoCommand; namespace CSMWorld { @@ -59,10 +58,12 @@ namespace CSVWorld virtual std::string getId() const; - /// \note This function is not called in case of a clone operation. + /// Allow subclasses to add additional data to \a command. virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; - virtual void pushCommand (std::auto_ptr command, + /// Allow subclasses to wrap the create command together with additional commands + /// into a macro. + virtual void pushCommand (std::auto_ptr command, const std::string& id); CSMWorld::Data& getData() const; diff --git a/apps/opencs/view/world/referencecreator.cpp b/apps/opencs/view/world/referencecreator.cpp index 561ac87da..5eec9df6d 100644 --- a/apps/opencs/view/world/referencecreator.cpp +++ b/apps/opencs/view/world/referencecreator.cpp @@ -31,7 +31,7 @@ void CSVWorld::ReferenceCreator::configureCreateCommand (CSMWorld::CreateCommand command.addValue (refNumColumn, getRefNumCount()); } -void CSVWorld::ReferenceCreator::pushCommand (std::auto_ptr command, +void CSVWorld::ReferenceCreator::pushCommand (std::auto_ptr command, const std::string& id) { // get the old count @@ -98,11 +98,6 @@ std::string CSVWorld::ReferenceCreator::getErrors() const // record is internal and requires neither user input nor verification. std::string errors; - if (mCloneMode) - { - return errors; - } - std::string cell = mCell->text().toUtf8().constData(); if (cell.empty()) @@ -128,12 +123,6 @@ void CSVWorld::ReferenceCreator::cellChanged() update(); } -void CSVWorld::ReferenceCreator::toggleWidgets(bool active) -{ - CSVWorld::GenericCreator::toggleWidgets(active); - mCell->setEnabled(active); -} - void CSVWorld::ReferenceCreator::cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type) { diff --git a/apps/opencs/view/world/referencecreator.hpp b/apps/opencs/view/world/referencecreator.hpp index c463469e4..002a62d87 100644 --- a/apps/opencs/view/world/referencecreator.hpp +++ b/apps/opencs/view/world/referencecreator.hpp @@ -20,10 +20,9 @@ namespace CSVWorld virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; - virtual void pushCommand (std::auto_ptr command, + virtual void pushCommand (std::auto_ptr command, const std::string& id); - /// Return next available RefNum for the cell the creator is currently operating on int getRefNumCount() const; public: @@ -35,7 +34,6 @@ namespace CSVWorld const CSMWorld::UniversalId::Type type); virtual void reset(); - virtual void toggleWidgets(bool active = true); virtual std::string getErrors() const; ///< Return formatted error descriptions for the current state of the creator. if an empty From b39cdb7645ba0e6f5d62028165463927a522bcb0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Sep 2014 12:48:51 +0200 Subject: [PATCH 10/12] fixed referenceable cloning (and as a side-effect enabled showing the type of the refereceable in the clone UI) --- apps/opencs/view/world/referenceablecreator.cpp | 7 +++++++ apps/opencs/view/world/referenceablecreator.hpp | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/apps/opencs/view/world/referenceablecreator.cpp b/apps/opencs/view/world/referenceablecreator.cpp index 7a5fca853..e8055ed31 100644 --- a/apps/opencs/view/world/referenceablecreator.cpp +++ b/apps/opencs/view/world/referenceablecreator.cpp @@ -42,6 +42,13 @@ void CSVWorld::ReferenceableCreator::reset() GenericCreator::reset(); } +void CSVWorld::ReferenceableCreator::cloneMode (const std::string& originId, + const CSMWorld::UniversalId::Type type) +{ + GenericCreator::cloneMode (originId, type); + mType->setCurrentIndex (mType->findData (static_cast (type))); +} + void CSVWorld::ReferenceableCreator::toggleWidgets(bool active) { CSVWorld::GenericCreator::toggleWidgets(active); diff --git a/apps/opencs/view/world/referenceablecreator.hpp b/apps/opencs/view/world/referenceablecreator.hpp index 88545575e..14ad24b29 100644 --- a/apps/opencs/view/world/referenceablecreator.hpp +++ b/apps/opencs/view/world/referenceablecreator.hpp @@ -23,6 +23,10 @@ namespace CSVWorld const CSMWorld::UniversalId& id); virtual void reset(); + + virtual void cloneMode (const std::string& originId, + const CSMWorld::UniversalId::Type type); + virtual void toggleWidgets(bool active = true); }; From 8ce87803c48c7564352eaaa0b2e0daee91ec6698 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Sep 2014 12:54:25 +0200 Subject: [PATCH 11/12] set default value for cell when cloning references --- apps/opencs/view/world/referencecreator.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/opencs/view/world/referencecreator.cpp b/apps/opencs/view/world/referencecreator.cpp index 5eec9df6d..1e3cc00d7 100644 --- a/apps/opencs/view/world/referencecreator.cpp +++ b/apps/opencs/view/world/referencecreator.cpp @@ -126,6 +126,14 @@ void CSVWorld::ReferenceCreator::cellChanged() void CSVWorld::ReferenceCreator::cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type) { + CSMWorld::IdTable& referenceTable = dynamic_cast ( + *getData().getTableModel (CSMWorld::UniversalId::Type_References)); + + int cellIdColumn = referenceTable.findColumnIndex (CSMWorld::Columns::ColumnId_Cell); + + mCell->setText ( + referenceTable.data (referenceTable.getModelIndex (originId, cellIdColumn)).toString()); + CSVWorld::GenericCreator::cloneMode(originId, type); cellChanged(); //otherwise ok button will remain disabled } From 8499ceb35db4a71061a2f9450278c98d29552671 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Sep 2014 13:30:36 +0200 Subject: [PATCH 12/12] set default value for topic when cloning info records --- apps/opencs/view/world/infocreator.cpp | 16 ++++++++++++++++ apps/opencs/view/world/infocreator.hpp | 3 +++ 2 files changed, 19 insertions(+) diff --git a/apps/opencs/view/world/infocreator.cpp b/apps/opencs/view/world/infocreator.cpp index f09222930..1d914716b 100644 --- a/apps/opencs/view/world/infocreator.cpp +++ b/apps/opencs/view/world/infocreator.cpp @@ -53,6 +53,22 @@ CSVWorld::InfoCreator::InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack, connect (mTopic, SIGNAL (textChanged (const QString&)), this, SLOT (topicChanged())); } +void CSVWorld::InfoCreator::cloneMode (const std::string& originId, + const CSMWorld::UniversalId::Type type) +{ + CSMWorld::IdTable& infoTable = + dynamic_cast (*getData().getTableModel (getCollectionId())); + + int topicColumn = infoTable.findColumnIndex ( + getCollectionId().getType()==CSMWorld::UniversalId::Type_TopicInfos ? + CSMWorld::Columns::ColumnId_Topic : CSMWorld::Columns::ColumnId_Journal); + + mTopic->setText ( + infoTable.data (infoTable.getModelIndex (originId, topicColumn)).toString()); + + GenericCreator::cloneMode (originId, type); +} + void CSVWorld::InfoCreator::reset() { mTopic->setText (""); diff --git a/apps/opencs/view/world/infocreator.hpp b/apps/opencs/view/world/infocreator.hpp index e9cb7e596..2296a8297 100644 --- a/apps/opencs/view/world/infocreator.hpp +++ b/apps/opencs/view/world/infocreator.hpp @@ -27,6 +27,9 @@ namespace CSVWorld InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id); + virtual void cloneMode (const std::string& originId, + const CSMWorld::UniversalId::Type type); + virtual void reset(); virtual std::string getErrors() const;