From 33620a001b802ed8c8ae8c61db9afcc4619ad20b Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Mon, 20 Jan 2014 13:59:00 +0100 Subject: [PATCH] Cloning works for single record type tables. Well, kinda. --- apps/opencs/model/world/collection.hpp | 27 ++++- apps/opencs/model/world/collectionbase.hpp | 5 + apps/opencs/model/world/commands.cpp | 126 +++++++++++--------- apps/opencs/model/world/commands.hpp | 6 +- apps/opencs/model/world/idtable.cpp | 5 +- apps/opencs/model/world/idtable.hpp | 5 +- apps/opencs/model/world/refidcollection.cpp | 8 ++ apps/opencs/model/world/refidcollection.hpp | 5 + apps/opencs/view/world/creator.hpp | 2 +- apps/opencs/view/world/genericcreator.cpp | 15 ++- apps/opencs/view/world/genericcreator.hpp | 6 +- apps/opencs/view/world/tablebottombox.cpp | 6 +- apps/opencs/view/world/tablebottombox.hpp | 2 +- apps/opencs/view/world/tablesubview.cpp | 6 +- apps/opencs/view/world/tablesubview.hpp | 4 +- 15 files changed, 150 insertions(+), 78 deletions(-) diff --git a/apps/opencs/model/world/collection.hpp b/apps/opencs/model/world/collection.hpp index df144ba7bf..0b9b44fa9a 100644 --- a/apps/opencs/model/world/collection.hpp +++ b/apps/opencs/model/world/collection.hpp @@ -97,7 +97,12 @@ namespace CSMWorld virtual void appendBlankRecord (const std::string& id, UniversalId::Type type = UniversalId::Type_None); ///< \param type Will be ignored, unless the collection supports multiple record types - + + virtual void cloneRecord(const std::string& origin, + const std::string& destination, + const UniversalId::Type type, + const UniversalId::ArgumentType argumentType); + virtual int searchId (const std::string& id) const; ////< Search record with \a id. /// \return index of record (if found) or -1 (not found) @@ -193,6 +198,26 @@ namespace CSMWorld return true; } + template + void Collection::cloneRecord(const std::string& origin, + const std::string& destination, + const UniversalId::Type type, + const UniversalId::ArgumentType argumentType) + { + Record copy = getRecord(origin); + if (copy.isDeleted()) + { + return; + } + + if (argumentType == UniversalId::ArgumentType_Id) + { + copy.get().mId = Misc::StringUtils::lowerCase(destination); + } + + insertRecord(copy, getAppendIndex(destination, type)); + } + template Collection::Collection() {} diff --git a/apps/opencs/model/world/collectionbase.hpp b/apps/opencs/model/world/collectionbase.hpp index ab7a9ebecb..d32847490b 100644 --- a/apps/opencs/model/world/collectionbase.hpp +++ b/apps/opencs/model/world/collectionbase.hpp @@ -74,6 +74,11 @@ namespace CSMWorld UniversalId::Type type = UniversalId::Type_None) = 0; ///< If the record type does not match, an exception is thrown. + virtual void cloneRecord(const std::string& origin, + const std::string& destination, + const UniversalId::Type type, + const UniversalId::ArgumentType argumentType) = 0; + virtual const RecordBase& getRecord (const std::string& id) const = 0; virtual const RecordBase& getRecord (int index) const = 0; diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 281afb15ff..75b88766aa 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -6,81 +6,88 @@ #include "idtable.hpp" #include "idtable.hpp" -CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, - const QVariant& new_, QUndoCommand *parent) -: QUndoCommand (parent), mModel (model), mIndex (index), mNew (new_) +CSMWorld::ModifyCommand::ModifyCommand(QAbstractItemModel& model, const QModelIndex& index, + const QVariant& new_, QUndoCommand* parent) + : QUndoCommand(parent), mModel(model), mIndex(index), mNew(new_) { - mOld = mModel.data (mIndex, Qt::EditRole); + mOld = mModel.data(mIndex, Qt::EditRole); - setText ("Modify " + mModel.headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString()); + setText("Modify " + mModel.headerData(mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString()); } void CSMWorld::ModifyCommand::redo() { - mModel.setData (mIndex, mNew); + mModel.setData(mIndex, mNew); } void CSMWorld::ModifyCommand::undo() { - mModel.setData (mIndex, mOld); + mModel.setData(mIndex, mOld); } -CSMWorld::CloneCommand::CloneCommand (CSMWorld::IdTable& model, - const std::string& idOrigin, - const std::string& IdDestination, - CSMWorld::UniversalId::Type type, - QUndoCommand* parent) : - QUndoCommand(parent), - mModel(model), - mIdOrigin(idOrigin), +CSMWorld::CloneCommand::CloneCommand(CSMWorld::IdTable& model, + const std::string& idOrigin, + const std::string& IdDestination, + const CSMWorld::UniversalId::Type type, + const CSMWorld::UniversalId::ArgumentType argumentType, + QUndoCommand* parent) : + QUndoCommand(parent), + mModel(model), + mIdOrigin(idOrigin), mIdDestination(IdDestination), + mArgumentType(argumentType), mType(type) { - setText (("Clone record " + idOrigin + " to the " + IdDestination).c_str()); + setText(("Clone record " + idOrigin + " to the " + IdDestination).c_str()); } void CSMWorld::CloneCommand::redo() { - mModel.cloneRecord(mIdOrigin, mIdDestination, mType); + mModel.cloneRecord(mIdOrigin, mIdDestination, mArgumentType, mType); } - -CSMWorld::CreateCommand::CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent) -: QUndoCommand (parent), mModel (model), mId (id), mType (UniversalId::Type_None) +void CSMWorld::CloneCommand::undo() { - setText (("Create record " + id).c_str()); + mModel.removeRow(mModel.getModelIndex(mIdDestination, 0).row()); } -void CSMWorld::CreateCommand::addValue (int column, const QVariant& value) + +CSMWorld::CreateCommand::CreateCommand(IdTable& model, const std::string& id, QUndoCommand* parent) + : QUndoCommand(parent), mModel(model), mId(id), mType(UniversalId::Type_None) +{ + setText(("Create record " + id).c_str()); +} + +void CSMWorld::CreateCommand::addValue(int column, const QVariant& value) { mValues[column] = value; } -void CSMWorld::CreateCommand::setType (UniversalId::Type type) +void CSMWorld::CreateCommand::setType(UniversalId::Type type) { mType = type; } void CSMWorld::CreateCommand::redo() { - mModel.addRecord (mId, mType); + 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); + for (std::map::const_iterator iter(mValues.begin()); iter != mValues.end(); ++iter) + mModel.setData(mModel.getModelIndex(mId, iter->first), iter->second); } void CSMWorld::CreateCommand::undo() { - mModel.removeRow (mModel.getModelIndex (mId, 0).row()); + mModel.removeRow(mModel.getModelIndex(mId, 0).row()); } -CSMWorld::RevertCommand::RevertCommand (IdTable& model, const std::string& id, QUndoCommand *parent) -: QUndoCommand (parent), mModel (model), mId (id), mOld (0) +CSMWorld::RevertCommand::RevertCommand(IdTable& model, const std::string& id, QUndoCommand* parent) + : QUndoCommand(parent), mModel(model), mId(id), mOld(0) { - setText (("Revert record " + id).c_str()); + setText(("Revert record " + id).c_str()); - mOld = model.getRecord (id).clone(); + mOld = model.getRecord(id).clone(); } CSMWorld::RevertCommand::~RevertCommand() @@ -90,32 +97,32 @@ CSMWorld::RevertCommand::~RevertCommand() void CSMWorld::RevertCommand::redo() { - int column = mModel.findColumnIndex (Columns::ColumnId_Modification); + int column = mModel.findColumnIndex(Columns::ColumnId_Modification); - QModelIndex index = mModel.getModelIndex (mId, column); - RecordBase::State state = static_cast (mModel.data (index).toInt()); + QModelIndex index = mModel.getModelIndex(mId, column); + RecordBase::State state = static_cast(mModel.data(index).toInt()); - if (state==RecordBase::State_ModifiedOnly) + if (state == RecordBase::State_ModifiedOnly) { - mModel.removeRows (index.row(), 1); + mModel.removeRows(index.row(), 1); } else { - mModel.setData (index, static_cast (RecordBase::State_BaseOnly)); + mModel.setData(index, static_cast(RecordBase::State_BaseOnly)); } } void CSMWorld::RevertCommand::undo() { - mModel.setRecord (mId, *mOld); + mModel.setRecord(mId, *mOld); } -CSMWorld::DeleteCommand::DeleteCommand (IdTable& model, const std::string& id, QUndoCommand *parent) -: QUndoCommand (parent), mModel (model), mId (id), mOld (0) +CSMWorld::DeleteCommand::DeleteCommand(IdTable& model, const std::string& id, QUndoCommand* parent) + : QUndoCommand(parent), mModel(model), mId(id), mOld(0) { - setText (("Delete record " + id).c_str()); + setText(("Delete record " + id).c_str()); - mOld = model.getRecord (id).clone(); + mOld = model.getRecord(id).clone(); } CSMWorld::DeleteCommand::~DeleteCommand() @@ -125,44 +132,45 @@ CSMWorld::DeleteCommand::~DeleteCommand() void CSMWorld::DeleteCommand::redo() { - int column = mModel.findColumnIndex (Columns::ColumnId_Modification); + int column = mModel.findColumnIndex(Columns::ColumnId_Modification); - QModelIndex index = mModel.getModelIndex (mId, column); - RecordBase::State state = static_cast (mModel.data (index).toInt()); + QModelIndex index = mModel.getModelIndex(mId, column); + RecordBase::State state = static_cast(mModel.data(index).toInt()); - if (state==RecordBase::State_ModifiedOnly) + if (state == RecordBase::State_ModifiedOnly) { - mModel.removeRows (index.row(), 1); + mModel.removeRows(index.row(), 1); } else { - mModel.setData (index, static_cast (RecordBase::State_Deleted)); + mModel.setData(index, static_cast(RecordBase::State_Deleted)); } } void CSMWorld::DeleteCommand::undo() { - mModel.setRecord (mId, *mOld); + mModel.setRecord(mId, *mOld); } -CSMWorld::ReorderRowsCommand::ReorderRowsCommand (IdTable& model, int baseIndex, - const std::vector& newOrder) -: mModel (model), mBaseIndex (baseIndex), mNewOrder (newOrder) +CSMWorld::ReorderRowsCommand::ReorderRowsCommand(IdTable& model, int baseIndex, + const std::vector& newOrder) + : mModel(model), mBaseIndex(baseIndex), mNewOrder(newOrder) {} void CSMWorld::ReorderRowsCommand::redo() { - mModel.reorderRows (mBaseIndex, mNewOrder); + mModel.reorderRows(mBaseIndex, mNewOrder); } void CSMWorld::ReorderRowsCommand::undo() { - int size = static_cast (mNewOrder.size()); - std::vector reverse (size); + int size = static_cast(mNewOrder.size()); + std::vector reverse(size); - for (int i=0; i mValues; public: CloneCommand (IdTable& model, const std::string& idOrigin, const std::string& IdDestination, - UniversalId::Type type, + const UniversalId::Type type, + const UniversalId::ArgumentType argumentType, QUndoCommand* parent = 0); virtual void redo(); -// virtual void undo(); + virtual void undo(); }; class CreateCommand : public QUndoCommand diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index b90bf1a9bb..daa6bc51b3 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -124,11 +124,12 @@ void CSMWorld::IdTable::addRecord (const std::string& id, UniversalId::Type type endInsertRows(); } -void CSMWorld::IdTable::cloneRecord(const std::string& origin, +void CSMWorld::IdTable::cloneRecord(const std::string& origin, const std::string& destination, + CSMWorld::UniversalId::ArgumentType argumentType, CSMWorld::UniversalId::Type type) { - + mIdCollection->cloneRecord(origin, destination, type, argumentType); } diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index dfbc04134f..ce47307e3c 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -63,7 +63,10 @@ namespace CSMWorld void addRecord (const std::string& id, UniversalId::Type type = UniversalId::Type_None); ///< \param type Will be ignored, unless the collection supports multiple record types - void cloneRecord(const std::string& origin, const std::string& destination, UniversalId::Type type = UniversalId::Type_None); + void cloneRecord(const std::string& origin, + const std::string& destination, + UniversalId::ArgumentType argumentType, + UniversalId::Type type = UniversalId::Type_None); QModelIndex getModelIndex (const std::string& id, int column) const; diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 86a542c5c3..896ee90101 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -449,6 +449,14 @@ void CSMWorld::RefIdCollection::replace (int index, const RecordBase& record) mData.getRecord (mData.globalToLocalIndex (index)).assign (record); } +void CSMWorld::RefIdCollection::cloneRecord(const std::string& origin, + const std::string& destination, + const CSMWorld::UniversalId::Type type, + const CSMWorld::UniversalId::ArgumentType argumentType) +{ + +} + void CSMWorld::RefIdCollection::appendRecord (const RecordBase& record, UniversalId::Type type) { diff --git a/apps/opencs/model/world/refidcollection.hpp b/apps/opencs/model/world/refidcollection.hpp index 5ff4a70bf2..4ad181004f 100644 --- a/apps/opencs/model/world/refidcollection.hpp +++ b/apps/opencs/model/world/refidcollection.hpp @@ -69,6 +69,11 @@ namespace CSMWorld virtual void removeRows (int index, int count); + virtual void cloneRecord(const std::string& origin, + const std::string& destination, + const UniversalId::Type type, + const UniversalId::ArgumentType argumentType); + virtual void appendBlankRecord (const std::string& id, UniversalId::Type type); ///< \param type Will be ignored, unless the collection supports multiple record types diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index 58a5e21ad2..5eaf3e1781 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -25,7 +25,7 @@ namespace CSVWorld virtual void reset() = 0; - virtual void cloneMode(const std::string& originid, const CSMWorld::UniversalId::Type type) = 0; + virtual void cloneMode(const std::string& originid, const CSMWorld::UniversalId::Type type, const CSMWorld::UniversalId::ArgumentType argumentType) = 0; virtual void setEditLock (bool locked) = 0; diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index f21a62d979..efdd9ecafb 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -59,7 +59,8 @@ const CSMWorld::UniversalId& CSVWorld::GenericCreator::getCollectionId() const CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, bool relaxedIdRules) -: mData (data), mUndoStack (undoStack), mListId (id), mLocked (false), mCloneMode(false), mClonedType(CSMWorld::UniversalId::Type_None) +: mData (data), mUndoStack (undoStack), mListId (id), mLocked (false), mCloneMode(false), mClonedType(CSMWorld::UniversalId::Type_None), +mArgumentType(CSMWorld::UniversalId::ArgumentType_None) { mLayout = new QHBoxLayout; mLayout->setContentsMargins (0, 0, 0, 0); @@ -126,7 +127,12 @@ void CSVWorld::GenericCreator::create() { std::string id = getId(); std::auto_ptr command (new CSMWorld::CloneCommand ( - dynamic_cast (*mData.getTableModel(mListId)), mClonedId, id, mClonedType)); + dynamic_cast (*mData.getTableModel(mListId)), mClonedId, id, mClonedType, mArgumentType)); + + mUndoStack.push(command.release()); + + emit done(); + emit requestFocus(id); } else { std::string id = getId(); @@ -143,11 +149,14 @@ void CSVWorld::GenericCreator::create() } } -void CSVWorld::GenericCreator::cloneMode(const std::string& originid, const CSMWorld::UniversalId::Type type) +void CSVWorld::GenericCreator::cloneMode(const std::string& originid, + const CSMWorld::UniversalId::Type type, + const CSMWorld::UniversalId::ArgumentType argumentType) { mCloneMode = true; mClonedId = originid; mClonedType = type; + mArgumentType = argumentType; mId->setText(QString::fromStdString(mClonedId)); } diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index a1acb2e792..867595bb55 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -32,6 +32,7 @@ namespace CSVWorld bool mCloneMode; std::string mClonedId; CSMWorld::UniversalId::Type mClonedType; + CSMWorld::UniversalId::ArgumentType mArgumentType; protected: @@ -61,13 +62,14 @@ namespace CSVWorld virtual void reset(); - virtual void cloneMode(const std::string& originid, const CSMWorld::UniversalId::Type type); + virtual void cloneMode(const std::string& originid, + const CSMWorld::UniversalId::Type type, + const CSMWorld::UniversalId::ArgumentType argumentType); virtual std::string getErrors() const; ///< Return formatted error descriptions for the current state of the creator. if an empty /// string is returned, there is no error. - private slots: void textChanged (const QString& text); diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index b89f5180bf..60a206d0c2 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -158,10 +158,12 @@ void CSVWorld::TableBottomBox::createRequest() mCreating = true; } -void CSVWorld::TableBottomBox::cloneRequest(const std::string& id, const CSMWorld::UniversalId::Type type) +void CSVWorld::TableBottomBox::cloneRequest(const std::string& id, + const CSMWorld::UniversalId::Type type, + const CSMWorld::UniversalId::ArgumentType argumnetType) { mCreator->reset(); - mCreator->cloneMode(id, type); + mCreator->cloneMode(id, type, argumnetType); mLayout->setCurrentWidget(mCreator); setVisible (true); mCreating = true; diff --git a/apps/opencs/view/world/tablebottombox.hpp b/apps/opencs/view/world/tablebottombox.hpp index 58a6a5a2f3..29afa22772 100644 --- a/apps/opencs/view/world/tablebottombox.hpp +++ b/apps/opencs/view/world/tablebottombox.hpp @@ -77,7 +77,7 @@ namespace CSVWorld /// \param modified Number of added and modified records void createRequest(); - void cloneRequest(const std::string& id, const CSMWorld::UniversalId::Type type); + void cloneRequest(const std::string& id, const CSMWorld::UniversalId::Type type, const CSMWorld::UniversalId::ArgumentType argumentType); }; } diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 36200dbbcb..7bb852cbe5 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -50,8 +50,8 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D connect (mTable, SIGNAL (createRequest()), mBottom, SLOT (createRequest())); connect (mTable, SIGNAL (cloneRequest(int)), this, SLOT(cloneRequest(int))); - connect (this, SIGNAL(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type)), - mBottom, SLOT(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type))); + connect (this, SIGNAL(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type, const CSMWorld::UniversalId::ArgumentType)), + mBottom, SLOT(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type, const CSMWorld::UniversalId::ArgumentType))); } connect (mBottom, SIGNAL (requestFocus (const std::string&)), mTable, SLOT (requestFocus (const std::string&))); @@ -85,5 +85,5 @@ void CSVWorld::TableSubView::setStatusBar (bool show) void CSVWorld::TableSubView::cloneRequest(int row) { const CSMWorld::UniversalId& toClone(mTable->getUniversalId(row)); - emit cloneRequest(toClone.getId(), toClone.getType()); + emit cloneRequest(toClone.getId(), toClone.getType(), toClone.getArgumentType()); } diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp index 5b19110b6b..01df204def 100644 --- a/apps/opencs/view/world/tablesubview.hpp +++ b/apps/opencs/view/world/tablesubview.hpp @@ -35,7 +35,9 @@ namespace CSVWorld virtual void setStatusBar (bool show); signals: - void cloneRequest(const std::string& id, const CSMWorld::UniversalId::Type type); + void cloneRequest(const std::string& id, + const CSMWorld::UniversalId::Type type, + const CSMWorld::UniversalId::ArgumentType argumentType); private slots: