Merge branch 'records'

deque
Marc Zinnschlag 10 years ago
commit 9d316a8745

@ -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<int>::const_iterator iter (references->second.begin());
iter!=references->second.end(); ++iter)
{
const CSMWorld::Record<CSMWorld::CellRef>& 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<int>::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)
{

@ -1918,6 +1918,70 @@ namespace CSMWorld
return true;
}
};
template<typename ESXRecordT>
struct RefNumCounterColumn : public Column<ESXRecordT>
{
RefNumCounterColumn()
: Column<ESXRecordT> (Columns::ColumnId_RefNumCounter, ColumnBase::Display_Integer, 0)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mRefNumCounter);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mRefNumCounter = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
virtual bool isUserEditable() const
{
return false;
}
};
template<typename ESXRecordT>
struct RefNumColumn : public Column<ESXRecordT>
{
RefNumColumn()
: Column<ESXRecordT> (Columns::ColumnId_RefNum, ColumnBase::Display_Integer, 0)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mRefNum.mIndex);
}
virtual void set (Record<ESXRecordT>& 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;
}
};
}
#endif

@ -184,6 +184,8 @@ namespace CSMWorld
{ ColumnId_DefaultProfile, "Default Profile" },
{ 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" },

@ -177,6 +177,8 @@ namespace CSMWorld
ColumnId_DefaultProfile = 165,
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.

@ -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);
}
@ -25,6 +24,13 @@ void CSMWorld::ModifyCommand::undo()
mModel.setData (mIndex, mOld);
}
void CSMWorld::CreateCommand::applyModifications()
{
for (std::map<int, QVariant>::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)
{
@ -44,9 +50,7 @@ void CSMWorld::CreateCommand::setType (UniversalId::Type type)
void CSMWorld::CreateCommand::redo()
{
mModel.addRecord (mId, mType);
for (std::map<int, QVariant>::const_iterator iter (mValues.begin()); iter!=mValues.end(); ++iter)
mModel.setData (mModel.getModelIndex (mId, iter->first), iter->second);
applyModifications();
}
void CSMWorld::CreateCommand::undo()
@ -148,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<int, QVariant>::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());
}

@ -39,40 +39,44 @@ namespace CSMWorld
virtual void undo();
};
class CloneCommand : public QUndoCommand
class CreateCommand : public QUndoCommand
{
std::map<int, QVariant> mValues;
protected:
IdTable& mModel;
std::string mIdOrigin;
std::string mIdDestination;
std::string mId;
UniversalId::Type mType;
std::map<int, QVariant> mValues;
protected:
/// Apply modifications set via addValue.
void applyModifications();
public:
CloneCommand (IdTable& model, const std::string& idOrigin,
const std::string& IdDestination,
const UniversalId::Type type,
QUndoCommand* parent = 0);
CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0);
void setType (UniversalId::Type type);
void addValue (int column, const QVariant& value);
virtual void redo();
virtual void undo();
};
class CreateCommand : public QUndoCommand
class CloneCommand : public CreateCommand
{
IdTable& mModel;
std::string mId;
UniversalId::Type mType;
std::map<int, QVariant> mValues;
std::string mIdOrigin;
public:
CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0);
void setType (UniversalId::Type type);
void addValue (int column, const QVariant& value);
CloneCommand (IdTable& model, const std::string& idOrigin,
const std::string& IdDestination,
const UniversalId::Type type,
QUndoCommand* parent = 0);
virtual void redo();

@ -200,6 +200,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mCells.addColumn (new FlagColumn<Cell> (Columns::ColumnId_InteriorWater, ESM::Cell::HasWater));
mCells.addColumn (new FlagColumn<Cell> (Columns::ColumnId_InteriorSky, ESM::Cell::QuasiEx));
mCells.addColumn (new RegionColumn<Cell>);
mCells.addColumn (new RefNumCounterColumn<Cell>);
mEnchantments.addColumn (new StringIdColumn<ESM::Enchantment>);
mEnchantments.addColumn (new RecordStateColumn<ESM::Enchantment>);
@ -251,6 +252,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mRefs.addColumn (new KeyColumn<CellRef>);
mRefs.addColumn (new TrapColumn<CellRef>);
mRefs.addColumn (new OwnerGlobalColumn<CellRef>);
mRefs.addColumn (new RefNumColumn<CellRef>);
mFilters.addColumn (new StringIdColumn<ESM::Filter>);
mFilters.addColumn (new RecordStateColumn<ESM::Filter>);

@ -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;
}

@ -50,11 +50,22 @@ std::string CSVWorld::GenericCreator::getId() const
void CSVWorld::GenericCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const {}
void CSVWorld::GenericCreator::pushCommand (std::auto_ptr<CSMWorld::CreateCommand> command,
const std::string& id)
{
mUndoStack.push (command.release());
}
CSMWorld::Data& CSVWorld::GenericCreator::getData() const
{
return mData;
}
QUndoStack& CSVWorld::GenericCreator::getUndoStack()
{
return mUndoStack;
}
const CSMWorld::UniversalId& CSVWorld::GenericCreator::getCollectionId() const
{
return mListId;
@ -173,24 +184,23 @@ void CSVWorld::GenericCreator::create()
{
std::string id = getId();
std::auto_ptr<CSMWorld::CreateCommand> command;
if (mCloneMode)
{
std::auto_ptr<CSMWorld::CloneCommand> command (new CSMWorld::CloneCommand (
command.reset (new CSMWorld::CloneCommand (
dynamic_cast<CSMWorld::IdTable&> (*mData.getTableModel(mListId)), mClonedId, id, mClonedType));
mUndoStack.push(command.release());
}
else
{
std::auto_ptr<CSMWorld::CreateCommand> command (new CSMWorld::CreateCommand (
dynamic_cast<CSMWorld::IdTable&> (*mData.getTableModel (mListId)), id));
command.reset (new CSMWorld::CreateCommand (
dynamic_cast<CSMWorld::IdTable&> (*mData.getTableModel (mListId)), id));
configureCreateCommand (*command);
mUndoStack.push (command.release());
}
configureCreateCommand (*command);
pushCommand (command, id);
emit done();
emit requestFocus(id);
}

@ -1,6 +1,12 @@
#ifndef CSV_WORLD_GENERICCREATOR_H
#define CSV_WORLD_GENERICCREATOR_H
#include <memory>
#include "../../model/world/universalid.hpp"
#include "creator.hpp"
class QString;
class QPushButton;
class QLineEdit;
@ -8,10 +14,6 @@ class QHBoxLayout;
class QComboBox;
class QLabel;
#include "creator.hpp"
#include "../../model/world/universalid.hpp"
namespace CSMWorld
{
class CreateCommand;
@ -56,10 +58,18 @@ namespace CSVWorld
virtual std::string getId() const;
/// Allow subclasses to add additional data to \a command.
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
/// Allow subclasses to wrap the create command together with additional commands
/// into a macro.
virtual void pushCommand (std::auto_ptr<CSMWorld::CreateCommand> command,
const std::string& id);
CSMWorld::Data& getData() const;
QUndoStack& getUndoStack();
const CSMWorld::UniversalId& getCollectionId() const;
std::string getNamespace() const;

@ -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<CSMWorld::IdTable&> (*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 ("");

@ -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;

@ -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<int> (type)));
}
void CSVWorld::ReferenceableCreator::toggleWidgets(bool active)
{
CSVWorld::GenericCreator::toggleWidgets(active);

@ -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);
};

@ -16,11 +16,58 @@ std::string CSVWorld::ReferenceCreator::getId() const
void CSVWorld::ReferenceCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
{
int index =
// Set cellID
int cellIdColumn =
dynamic_cast<CSMWorld::IdTable&> (*getData().getTableModel (getCollectionId())).
findColumnIndex (CSMWorld::Columns::ColumnId_Cell);
command.addValue (index, mCell->text());
command.addValue (cellIdColumn, mCell->text());
// Set RefNum
int refNumColumn = dynamic_cast<CSMWorld::IdTable&> (
*getData().getTableModel (CSMWorld::UniversalId::Type_References)).
findColumnIndex (CSMWorld::Columns::ColumnId_RefNum);
command.addValue (refNumColumn, getRefNumCount());
}
void CSVWorld::ReferenceCreator::pushCommand (std::auto_ptr<CSMWorld::CreateCommand> command,
const std::string& id)
{
// get the old count
std::string cellId = mCell->text().toUtf8().constData();
CSMWorld::IdTable& cellTable = dynamic_cast<CSMWorld::IdTable&> (
*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 incrementing counter
std::auto_ptr<CSMWorld::ModifyCommand> increment (new CSMWorld::ModifyCommand
(cellTable, countIndex, count+1));
getUndoStack().beginMacro (command->text());
GenericCreator::pushCommand (command, id);
getUndoStack().push (increment.release());
getUndoStack().endMacro();
}
int CSVWorld::ReferenceCreator::getRefNumCount() const
{
std::string cellId = mCell->text().toUtf8().constData();
CSMWorld::IdTable& cellTable = dynamic_cast<CSMWorld::IdTable&> (
*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,
@ -47,12 +94,9 @@ void CSVWorld::ReferenceCreator::reset()
std::string CSVWorld::ReferenceCreator::getErrors() const
{
std::string errors = GenericCreator::getErrors();
if (mCloneMode)
{
return errors;
}
// 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;
std::string cell = mCell->text().toUtf8().constData();
@ -79,15 +123,17 @@ 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)
{
CSMWorld::IdTable& referenceTable = dynamic_cast<CSMWorld::IdTable&> (
*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
}

@ -20,16 +20,20 @@ namespace CSVWorld
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
virtual void pushCommand (std::auto_ptr<CSMWorld::CreateCommand> command,
const std::string& id);
int getRefNumCount() const;
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();
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

Loading…
Cancel
Save