mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 03:23:54 +00:00
20da0892ef
Slowly moving through the open-cs errors Good progress in openCS Very good progress on openCS Getting closer with openCS OpenCS compiles and runs! Didn't have time to test it all though ix openMW everything compiles on windows?? Fix gcc Fix Clang
2459 lines
94 KiB
C++
2459 lines
94 KiB
C++
#ifndef CSM_WOLRD_REFIDADAPTERIMP_H
|
|
#define CSM_WOLRD_REFIDADAPTERIMP_H
|
|
|
|
#include <algorithm>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include <QVariant>
|
|
|
|
#include <components/esm/defs.hpp>
|
|
#include <components/esm/esmcommon.hpp>
|
|
#include <components/esm3/aipackage.hpp>
|
|
#include <components/esm3/loadalch.hpp>
|
|
#include <components/esm3/loadappa.hpp>
|
|
#include <components/esm3/loadarmo.hpp>
|
|
#include <components/esm3/loadbook.hpp>
|
|
#include <components/esm3/loadclot.hpp>
|
|
#include <components/esm3/loadcont.hpp>
|
|
#include <components/esm3/loadcrea.hpp>
|
|
#include <components/esm3/loaddoor.hpp>
|
|
#include <components/esm3/loadingr.hpp>
|
|
#include <components/esm3/loadlevlist.hpp>
|
|
#include <components/esm3/loadligh.hpp>
|
|
#include <components/esm3/loadmisc.hpp>
|
|
#include <components/esm3/loadnpc.hpp>
|
|
#include <components/esm3/loadweap.hpp>
|
|
#include <components/esm3/transport.hpp>
|
|
|
|
#include "columnbase.hpp"
|
|
#include "nestedtablewrapper.hpp"
|
|
#include "record.hpp"
|
|
#include "refidadapter.hpp"
|
|
#include "refiddata.hpp"
|
|
#include "universalid.hpp"
|
|
|
|
namespace CSMWorld
|
|
{
|
|
class RefIdColumn;
|
|
struct BaseColumns
|
|
{
|
|
const RefIdColumn* mId;
|
|
const RefIdColumn* mModified;
|
|
const RefIdColumn* mType;
|
|
const RefIdColumn* mBlocked;
|
|
|
|
BaseColumns()
|
|
: mId(nullptr)
|
|
, mModified(nullptr)
|
|
, mType(nullptr)
|
|
, mBlocked(nullptr)
|
|
{
|
|
}
|
|
};
|
|
|
|
/// \brief Base adapter for all refereceable record types
|
|
/// Adapters that can handle nested tables, needs to return valid qvariant for parent columns
|
|
template <typename RecordT>
|
|
class BaseRefIdAdapter : public RefIdAdapter
|
|
{
|
|
UniversalId::Type mType;
|
|
BaseColumns mBase;
|
|
|
|
public:
|
|
BaseRefIdAdapter(UniversalId::Type type, const BaseColumns& base);
|
|
|
|
ESM::RefId getId(const RecordBase& record) const override;
|
|
|
|
void setId(RecordBase& record, const std::string& id) override;
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
|
|
UniversalId::Type getType() const;
|
|
};
|
|
|
|
template <typename RecordT>
|
|
BaseRefIdAdapter<RecordT>::BaseRefIdAdapter(UniversalId::Type type, const BaseColumns& base)
|
|
: mType(type)
|
|
, mBase(base)
|
|
{
|
|
}
|
|
|
|
template <typename RecordT>
|
|
void BaseRefIdAdapter<RecordT>::setId(RecordBase& record, const std::string& id)
|
|
{
|
|
(dynamic_cast<Record<RecordT>&>(record).get().mId) = ESM::RefId::stringRefId(id);
|
|
}
|
|
|
|
template <typename RecordT>
|
|
ESM::RefId BaseRefIdAdapter<RecordT>::getId(const RecordBase& record) const
|
|
{
|
|
return dynamic_cast<const Record<RecordT>&>(record).get().mId;
|
|
}
|
|
|
|
template <typename RecordT>
|
|
QVariant BaseRefIdAdapter<RecordT>::getData(const RefIdColumn* column, const RefIdData& data, int index) const
|
|
{
|
|
const Record<RecordT>& record
|
|
= static_cast<const Record<RecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
if (column == mBase.mId)
|
|
return QString::fromUtf8(record.get().mId.getRefIdString().c_str());
|
|
|
|
if (column == mBase.mModified)
|
|
{
|
|
if (record.mState == Record<RecordT>::State_Erased)
|
|
return static_cast<int>(Record<RecordT>::State_Deleted);
|
|
|
|
return static_cast<int>(record.mState);
|
|
}
|
|
|
|
if (column == mBase.mType)
|
|
return static_cast<int>(mType);
|
|
|
|
if (column == mBase.mBlocked)
|
|
return (record.get().mRecordFlags & ESM::FLAG_Blocked) != 0;
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
template <typename RecordT>
|
|
void BaseRefIdAdapter<RecordT>::setData(
|
|
const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const
|
|
{
|
|
Record<RecordT>& record = static_cast<Record<RecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
if (column == mBase.mModified)
|
|
record.mState = static_cast<RecordBase::State>(value.toInt());
|
|
else if (column == mBase.mBlocked)
|
|
{
|
|
RecordT record2 = record.get();
|
|
|
|
if (value.toInt() != 0)
|
|
record2.mRecordFlags |= ESM::FLAG_Blocked;
|
|
else
|
|
record2.mRecordFlags &= ~ESM::FLAG_Blocked;
|
|
|
|
record.setModified(record2);
|
|
}
|
|
}
|
|
|
|
template <typename RecordT>
|
|
UniversalId::Type BaseRefIdAdapter<RecordT>::getType() const
|
|
{
|
|
return mType;
|
|
}
|
|
|
|
// NOTE: Body Part should not have persistence (but BodyPart is not listed in the Objects
|
|
// table at the moment).
|
|
//
|
|
// Spellmaking - not persistent - currently not part of objects table
|
|
// Enchanting - not persistent - currently not part of objects table
|
|
//
|
|
// Leveled Creature - no model, so not persistent
|
|
// Leveled Item - no model, so not persistent
|
|
|
|
struct ModelColumns : public BaseColumns
|
|
{
|
|
const RefIdColumn* mModel;
|
|
const RefIdColumn* mPersistence;
|
|
|
|
ModelColumns(const BaseColumns& base)
|
|
: BaseColumns(base)
|
|
, mModel(nullptr)
|
|
, mPersistence(nullptr)
|
|
{
|
|
}
|
|
};
|
|
|
|
/// \brief Adapter for IDs with models (all but levelled lists)
|
|
template <typename RecordT>
|
|
class ModelRefIdAdapter : public BaseRefIdAdapter<RecordT>
|
|
{
|
|
ModelColumns mModel;
|
|
|
|
public:
|
|
ModelRefIdAdapter(UniversalId::Type type, const ModelColumns& columns);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
template <typename RecordT>
|
|
ModelRefIdAdapter<RecordT>::ModelRefIdAdapter(UniversalId::Type type, const ModelColumns& columns)
|
|
: BaseRefIdAdapter<RecordT>(type, columns)
|
|
, mModel(columns)
|
|
{
|
|
}
|
|
|
|
template <typename RecordT>
|
|
QVariant ModelRefIdAdapter<RecordT>::getData(const RefIdColumn* column, const RefIdData& data, int index) const
|
|
{
|
|
const Record<RecordT>& record = static_cast<const Record<RecordT>&>(
|
|
data.getRecord(RefIdData::LocalIndex(index, BaseRefIdAdapter<RecordT>::getType())));
|
|
|
|
if (column == mModel.mModel)
|
|
return QString::fromUtf8(record.get().mModel.c_str());
|
|
|
|
if (column == mModel.mPersistence)
|
|
return (record.get().mRecordFlags & ESM::FLAG_Persistent) != 0;
|
|
|
|
return BaseRefIdAdapter<RecordT>::getData(column, data, index);
|
|
}
|
|
|
|
template <typename RecordT>
|
|
void ModelRefIdAdapter<RecordT>::setData(
|
|
const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const
|
|
{
|
|
Record<RecordT>& record = static_cast<Record<RecordT>&>(
|
|
data.getRecord(RefIdData::LocalIndex(index, BaseRefIdAdapter<RecordT>::getType())));
|
|
|
|
RecordT record2 = record.get();
|
|
if (column == mModel.mModel)
|
|
record2.mModel = value.toString().toUtf8().constData();
|
|
else if (column == mModel.mPersistence)
|
|
{
|
|
if (value.toInt() != 0)
|
|
record2.mRecordFlags |= ESM::FLAG_Persistent;
|
|
else
|
|
record2.mRecordFlags &= ~ESM::FLAG_Persistent;
|
|
}
|
|
else
|
|
{
|
|
BaseRefIdAdapter<RecordT>::setData(column, data, index, value);
|
|
return;
|
|
}
|
|
|
|
record.setModified(record2);
|
|
}
|
|
|
|
struct NameColumns : public ModelColumns
|
|
{
|
|
const RefIdColumn* mName;
|
|
const RefIdColumn* mScript;
|
|
|
|
NameColumns(const ModelColumns& base)
|
|
: ModelColumns(base)
|
|
, mName(nullptr)
|
|
, mScript(nullptr)
|
|
{
|
|
}
|
|
};
|
|
|
|
/// \brief Adapter for IDs with names (all but levelled lists and statics)
|
|
template <typename RecordT>
|
|
class NameRefIdAdapter : public ModelRefIdAdapter<RecordT>
|
|
{
|
|
NameColumns mName;
|
|
|
|
public:
|
|
NameRefIdAdapter(UniversalId::Type type, const NameColumns& columns);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
template <typename RecordT>
|
|
NameRefIdAdapter<RecordT>::NameRefIdAdapter(UniversalId::Type type, const NameColumns& columns)
|
|
: ModelRefIdAdapter<RecordT>(type, columns)
|
|
, mName(columns)
|
|
{
|
|
}
|
|
|
|
template <typename RecordT>
|
|
QVariant NameRefIdAdapter<RecordT>::getData(const RefIdColumn* column, const RefIdData& data, int index) const
|
|
{
|
|
const Record<RecordT>& record = static_cast<const Record<RecordT>&>(
|
|
data.getRecord(RefIdData::LocalIndex(index, BaseRefIdAdapter<RecordT>::getType())));
|
|
|
|
if (column == mName.mName)
|
|
return QString::fromUtf8(record.get().mName.c_str());
|
|
|
|
if (column == mName.mScript)
|
|
return QString::fromUtf8(record.get().mScript.getRefIdString().c_str());
|
|
|
|
return ModelRefIdAdapter<RecordT>::getData(column, data, index);
|
|
}
|
|
|
|
template <typename RecordT>
|
|
void NameRefIdAdapter<RecordT>::setData(
|
|
const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const
|
|
{
|
|
Record<RecordT>& record = static_cast<Record<RecordT>&>(
|
|
data.getRecord(RefIdData::LocalIndex(index, BaseRefIdAdapter<RecordT>::getType())));
|
|
|
|
RecordT record2 = record.get();
|
|
if (column == mName.mName)
|
|
record2.mName = value.toString().toUtf8().constData();
|
|
else if (column == mName.mScript)
|
|
record2.mScript = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
|
|
else
|
|
{
|
|
ModelRefIdAdapter<RecordT>::setData(column, data, index, value);
|
|
return;
|
|
}
|
|
|
|
record.setModified(record2);
|
|
}
|
|
|
|
struct InventoryColumns : public NameColumns
|
|
{
|
|
const RefIdColumn* mIcon;
|
|
const RefIdColumn* mWeight;
|
|
const RefIdColumn* mValue;
|
|
|
|
InventoryColumns(const NameColumns& base)
|
|
: NameColumns(base)
|
|
, mIcon(nullptr)
|
|
, mWeight(nullptr)
|
|
, mValue(nullptr)
|
|
{
|
|
}
|
|
};
|
|
|
|
/// \brief Adapter for IDs that can go into an inventory
|
|
template <typename RecordT>
|
|
class InventoryRefIdAdapter : public NameRefIdAdapter<RecordT>
|
|
{
|
|
InventoryColumns mInventory;
|
|
|
|
public:
|
|
InventoryRefIdAdapter(UniversalId::Type type, const InventoryColumns& columns);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
template <typename RecordT>
|
|
InventoryRefIdAdapter<RecordT>::InventoryRefIdAdapter(UniversalId::Type type, const InventoryColumns& columns)
|
|
: NameRefIdAdapter<RecordT>(type, columns)
|
|
, mInventory(columns)
|
|
{
|
|
}
|
|
|
|
template <typename RecordT>
|
|
QVariant InventoryRefIdAdapter<RecordT>::getData(const RefIdColumn* column, const RefIdData& data, int index) const
|
|
{
|
|
const Record<RecordT>& record = static_cast<const Record<RecordT>&>(
|
|
data.getRecord(RefIdData::LocalIndex(index, BaseRefIdAdapter<RecordT>::getType())));
|
|
|
|
if (column == mInventory.mIcon)
|
|
return QString::fromUtf8(record.get().mIcon.c_str());
|
|
|
|
if (column == mInventory.mWeight)
|
|
return record.get().mData.mWeight;
|
|
|
|
if (column == mInventory.mValue)
|
|
return record.get().mData.mValue;
|
|
|
|
return NameRefIdAdapter<RecordT>::getData(column, data, index);
|
|
}
|
|
|
|
template <typename RecordT>
|
|
void InventoryRefIdAdapter<RecordT>::setData(
|
|
const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const
|
|
{
|
|
Record<RecordT>& record = static_cast<Record<RecordT>&>(
|
|
data.getRecord(RefIdData::LocalIndex(index, BaseRefIdAdapter<RecordT>::getType())));
|
|
|
|
RecordT record2 = record.get();
|
|
if (column == mInventory.mIcon)
|
|
record2.mIcon = value.toString().toUtf8().constData();
|
|
else if (column == mInventory.mWeight)
|
|
record2.mData.mWeight = value.toFloat();
|
|
else if (column == mInventory.mValue)
|
|
record2.mData.mValue = value.toInt();
|
|
else
|
|
{
|
|
NameRefIdAdapter<RecordT>::setData(column, data, index, value);
|
|
return;
|
|
}
|
|
|
|
record.setModified(record2);
|
|
}
|
|
|
|
struct PotionColumns : public InventoryColumns
|
|
{
|
|
const RefIdColumn* mEffects;
|
|
|
|
PotionColumns(const InventoryColumns& columns);
|
|
};
|
|
|
|
class PotionRefIdAdapter : public InventoryRefIdAdapter<ESM::Potion>
|
|
{
|
|
PotionColumns mColumns;
|
|
const RefIdColumn* mAutoCalc;
|
|
|
|
public:
|
|
PotionRefIdAdapter(const PotionColumns& columns, const RefIdColumn* autoCalc);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
struct IngredientColumns : public InventoryColumns
|
|
{
|
|
const RefIdColumn* mEffects;
|
|
|
|
IngredientColumns(const InventoryColumns& columns);
|
|
};
|
|
|
|
class IngredientRefIdAdapter : public InventoryRefIdAdapter<ESM::Ingredient>
|
|
{
|
|
IngredientColumns mColumns;
|
|
|
|
public:
|
|
IngredientRefIdAdapter(const IngredientColumns& columns);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
class IngredEffectRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
UniversalId::Type mType;
|
|
|
|
// not implemented
|
|
IngredEffectRefIdAdapter(const IngredEffectRefIdAdapter&);
|
|
IngredEffectRefIdAdapter& operator=(const IngredEffectRefIdAdapter&);
|
|
|
|
public:
|
|
IngredEffectRefIdAdapter();
|
|
|
|
~IngredEffectRefIdAdapter() override;
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override;
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override;
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override;
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override;
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
};
|
|
|
|
struct EnchantableColumns : public InventoryColumns
|
|
{
|
|
const RefIdColumn* mEnchantment;
|
|
const RefIdColumn* mEnchantmentPoints;
|
|
|
|
EnchantableColumns(const InventoryColumns& base)
|
|
: InventoryColumns(base)
|
|
, mEnchantment(nullptr)
|
|
, mEnchantmentPoints(nullptr)
|
|
{
|
|
}
|
|
};
|
|
|
|
/// \brief Adapter for enchantable IDs
|
|
template <typename RecordT>
|
|
class EnchantableRefIdAdapter : public InventoryRefIdAdapter<RecordT>
|
|
{
|
|
EnchantableColumns mEnchantable;
|
|
|
|
public:
|
|
EnchantableRefIdAdapter(UniversalId::Type type, const EnchantableColumns& columns);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
template <typename RecordT>
|
|
EnchantableRefIdAdapter<RecordT>::EnchantableRefIdAdapter(UniversalId::Type type, const EnchantableColumns& columns)
|
|
: InventoryRefIdAdapter<RecordT>(type, columns)
|
|
, mEnchantable(columns)
|
|
{
|
|
}
|
|
|
|
template <typename RecordT>
|
|
QVariant EnchantableRefIdAdapter<RecordT>::getData(
|
|
const RefIdColumn* column, const RefIdData& data, int index) const
|
|
{
|
|
const Record<RecordT>& record = static_cast<const Record<RecordT>&>(
|
|
data.getRecord(RefIdData::LocalIndex(index, BaseRefIdAdapter<RecordT>::getType())));
|
|
|
|
if (column == mEnchantable.mEnchantment)
|
|
return QString::fromUtf8(record.get().mEnchant.getRefIdString().c_str());
|
|
|
|
if (column == mEnchantable.mEnchantmentPoints)
|
|
return static_cast<int>(record.get().mData.mEnchant);
|
|
|
|
return InventoryRefIdAdapter<RecordT>::getData(column, data, index);
|
|
}
|
|
|
|
template <typename RecordT>
|
|
void EnchantableRefIdAdapter<RecordT>::setData(
|
|
const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const
|
|
{
|
|
Record<RecordT>& record = static_cast<Record<RecordT>&>(
|
|
data.getRecord(RefIdData::LocalIndex(index, BaseRefIdAdapter<RecordT>::getType())));
|
|
|
|
RecordT record2 = record.get();
|
|
if (column == mEnchantable.mEnchantment)
|
|
record2.mEnchant = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
|
|
else if (column == mEnchantable.mEnchantmentPoints)
|
|
record2.mData.mEnchant = value.toInt();
|
|
else
|
|
{
|
|
InventoryRefIdAdapter<RecordT>::setData(column, data, index, value);
|
|
return;
|
|
}
|
|
|
|
record.setModified(record2);
|
|
}
|
|
|
|
struct ToolColumns : public InventoryColumns
|
|
{
|
|
const RefIdColumn* mQuality;
|
|
const RefIdColumn* mUses;
|
|
|
|
ToolColumns(const InventoryColumns& base)
|
|
: InventoryColumns(base)
|
|
, mQuality(nullptr)
|
|
, mUses(nullptr)
|
|
{
|
|
}
|
|
};
|
|
|
|
/// \brief Adapter for tools with limited uses IDs (lockpick, repair, probes)
|
|
template <typename RecordT>
|
|
class ToolRefIdAdapter : public InventoryRefIdAdapter<RecordT>
|
|
{
|
|
ToolColumns mTools;
|
|
|
|
public:
|
|
ToolRefIdAdapter(UniversalId::Type type, const ToolColumns& columns);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
template <typename RecordT>
|
|
ToolRefIdAdapter<RecordT>::ToolRefIdAdapter(UniversalId::Type type, const ToolColumns& columns)
|
|
: InventoryRefIdAdapter<RecordT>(type, columns)
|
|
, mTools(columns)
|
|
{
|
|
}
|
|
|
|
template <typename RecordT>
|
|
QVariant ToolRefIdAdapter<RecordT>::getData(const RefIdColumn* column, const RefIdData& data, int index) const
|
|
{
|
|
const Record<RecordT>& record = static_cast<const Record<RecordT>&>(
|
|
data.getRecord(RefIdData::LocalIndex(index, BaseRefIdAdapter<RecordT>::getType())));
|
|
|
|
if (column == mTools.mQuality)
|
|
return record.get().mData.mQuality;
|
|
|
|
if (column == mTools.mUses)
|
|
return record.get().mData.mUses;
|
|
|
|
return InventoryRefIdAdapter<RecordT>::getData(column, data, index);
|
|
}
|
|
|
|
template <typename RecordT>
|
|
void ToolRefIdAdapter<RecordT>::setData(
|
|
const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const
|
|
{
|
|
Record<RecordT>& record = static_cast<Record<RecordT>&>(
|
|
data.getRecord(RefIdData::LocalIndex(index, BaseRefIdAdapter<RecordT>::getType())));
|
|
|
|
RecordT record2 = record.get();
|
|
if (column == mTools.mQuality)
|
|
record2.mData.mQuality = value.toFloat();
|
|
else if (column == mTools.mUses)
|
|
record2.mData.mUses = value.toInt();
|
|
else
|
|
{
|
|
InventoryRefIdAdapter<RecordT>::setData(column, data, index, value);
|
|
return;
|
|
}
|
|
|
|
record.setModified(record2);
|
|
}
|
|
|
|
struct ActorColumns : public NameColumns
|
|
{
|
|
const RefIdColumn* mHello;
|
|
const RefIdColumn* mFlee;
|
|
const RefIdColumn* mFight;
|
|
const RefIdColumn* mAlarm;
|
|
const RefIdColumn* mInventory;
|
|
const RefIdColumn* mSpells;
|
|
const RefIdColumn* mDestinations;
|
|
const RefIdColumn* mAiPackages;
|
|
std::map<const RefIdColumn*, unsigned int> mServices;
|
|
|
|
ActorColumns(const NameColumns& base)
|
|
: NameColumns(base)
|
|
, mHello(nullptr)
|
|
, mFlee(nullptr)
|
|
, mFight(nullptr)
|
|
, mAlarm(nullptr)
|
|
, mInventory(nullptr)
|
|
, mSpells(nullptr)
|
|
, mDestinations(nullptr)
|
|
, mAiPackages(nullptr)
|
|
{
|
|
}
|
|
};
|
|
|
|
/// \brief Adapter for actor IDs (handles common AI functionality)
|
|
template <typename RecordT>
|
|
class ActorRefIdAdapter : public NameRefIdAdapter<RecordT>
|
|
{
|
|
ActorColumns mActors;
|
|
|
|
public:
|
|
ActorRefIdAdapter(UniversalId::Type type, const ActorColumns& columns);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
template <typename RecordT>
|
|
ActorRefIdAdapter<RecordT>::ActorRefIdAdapter(UniversalId::Type type, const ActorColumns& columns)
|
|
: NameRefIdAdapter<RecordT>(type, columns)
|
|
, mActors(columns)
|
|
{
|
|
}
|
|
|
|
template <typename RecordT>
|
|
QVariant ActorRefIdAdapter<RecordT>::getData(const RefIdColumn* column, const RefIdData& data, int index) const
|
|
{
|
|
const Record<RecordT>& record = static_cast<const Record<RecordT>&>(
|
|
data.getRecord(RefIdData::LocalIndex(index, BaseRefIdAdapter<RecordT>::getType())));
|
|
|
|
if (column == mActors.mHello)
|
|
return record.get().mAiData.mHello;
|
|
|
|
if (column == mActors.mFlee)
|
|
return record.get().mAiData.mFlee;
|
|
|
|
if (column == mActors.mFight)
|
|
return record.get().mAiData.mFight;
|
|
|
|
if (column == mActors.mAlarm)
|
|
return record.get().mAiData.mAlarm;
|
|
|
|
if (column == mActors.mInventory)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
|
|
|
if (column == mActors.mSpells)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
|
|
|
if (column == mActors.mDestinations)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
|
|
|
if (column == mActors.mAiPackages)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
|
|
|
std::map<const RefIdColumn*, unsigned int>::const_iterator iter = mActors.mServices.find(column);
|
|
|
|
if (iter != mActors.mServices.end())
|
|
return (record.get().mAiData.mServices & iter->second) != 0;
|
|
|
|
return NameRefIdAdapter<RecordT>::getData(column, data, index);
|
|
}
|
|
|
|
template <typename RecordT>
|
|
void ActorRefIdAdapter<RecordT>::setData(
|
|
const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const
|
|
{
|
|
Record<RecordT>& record = static_cast<Record<RecordT>&>(
|
|
data.getRecord(RefIdData::LocalIndex(index, BaseRefIdAdapter<RecordT>::getType())));
|
|
|
|
RecordT record2 = record.get();
|
|
if (column == mActors.mHello)
|
|
record2.mAiData.mHello = value.toInt();
|
|
else if (column == mActors.mFlee) // Flee, Fight and Alarm ratings are probabilities.
|
|
record2.mAiData.mFlee = std::min(100, value.toInt());
|
|
else if (column == mActors.mFight)
|
|
record2.mAiData.mFight = std::min(100, value.toInt());
|
|
else if (column == mActors.mAlarm)
|
|
record2.mAiData.mAlarm = std::min(100, value.toInt());
|
|
else
|
|
{
|
|
typename std::map<const RefIdColumn*, unsigned int>::const_iterator iter = mActors.mServices.find(column);
|
|
if (iter != mActors.mServices.end())
|
|
{
|
|
if (value.toInt() != 0)
|
|
record2.mAiData.mServices |= iter->second;
|
|
else
|
|
record2.mAiData.mServices &= ~iter->second;
|
|
}
|
|
else
|
|
{
|
|
NameRefIdAdapter<RecordT>::setData(column, data, index, value);
|
|
return;
|
|
}
|
|
}
|
|
|
|
record.setModified(record2);
|
|
}
|
|
|
|
class ApparatusRefIdAdapter : public InventoryRefIdAdapter<ESM::Apparatus>
|
|
{
|
|
const RefIdColumn* mType;
|
|
const RefIdColumn* mQuality;
|
|
|
|
public:
|
|
ApparatusRefIdAdapter(const InventoryColumns& columns, const RefIdColumn* type, const RefIdColumn* quality);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
class ArmorRefIdAdapter : public EnchantableRefIdAdapter<ESM::Armor>
|
|
{
|
|
const RefIdColumn* mType;
|
|
const RefIdColumn* mHealth;
|
|
const RefIdColumn* mArmor;
|
|
const RefIdColumn* mPartRef;
|
|
|
|
public:
|
|
ArmorRefIdAdapter(const EnchantableColumns& columns, const RefIdColumn* type, const RefIdColumn* health,
|
|
const RefIdColumn* armor, const RefIdColumn* partRef);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
class BookRefIdAdapter : public EnchantableRefIdAdapter<ESM::Book>
|
|
{
|
|
const RefIdColumn* mBookType;
|
|
const RefIdColumn* mSkill;
|
|
const RefIdColumn* mText;
|
|
|
|
public:
|
|
BookRefIdAdapter(const EnchantableColumns& columns, const RefIdColumn* bookType, const RefIdColumn* skill,
|
|
const RefIdColumn* text);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
class ClothingRefIdAdapter : public EnchantableRefIdAdapter<ESM::Clothing>
|
|
{
|
|
const RefIdColumn* mType;
|
|
const RefIdColumn* mPartRef;
|
|
|
|
public:
|
|
ClothingRefIdAdapter(const EnchantableColumns& columns, const RefIdColumn* type, const RefIdColumn* partRef);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
class ContainerRefIdAdapter : public NameRefIdAdapter<ESM::Container>
|
|
{
|
|
const RefIdColumn* mWeight;
|
|
const RefIdColumn* mOrganic;
|
|
const RefIdColumn* mRespawn;
|
|
const RefIdColumn* mContent;
|
|
|
|
public:
|
|
ContainerRefIdAdapter(const NameColumns& columns, const RefIdColumn* weight, const RefIdColumn* organic,
|
|
const RefIdColumn* respawn, const RefIdColumn* content);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
struct CreatureColumns : public ActorColumns
|
|
{
|
|
std::map<const RefIdColumn*, unsigned int> mFlags;
|
|
const RefIdColumn* mType;
|
|
const RefIdColumn* mScale;
|
|
const RefIdColumn* mOriginal;
|
|
const RefIdColumn* mAttributes;
|
|
const RefIdColumn* mAttacks;
|
|
const RefIdColumn* mMisc;
|
|
const RefIdColumn* mBloodType;
|
|
|
|
CreatureColumns(const ActorColumns& actorColumns);
|
|
};
|
|
|
|
class CreatureRefIdAdapter : public ActorRefIdAdapter<ESM::Creature>
|
|
{
|
|
CreatureColumns mColumns;
|
|
|
|
public:
|
|
CreatureRefIdAdapter(const CreatureColumns& columns);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
class DoorRefIdAdapter : public NameRefIdAdapter<ESM::Door>
|
|
{
|
|
const RefIdColumn* mOpenSound;
|
|
const RefIdColumn* mCloseSound;
|
|
|
|
public:
|
|
DoorRefIdAdapter(const NameColumns& columns, const RefIdColumn* openSound, const RefIdColumn* closeSound);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
struct LightColumns : public InventoryColumns
|
|
{
|
|
const RefIdColumn* mTime;
|
|
const RefIdColumn* mRadius;
|
|
const RefIdColumn* mColor;
|
|
const RefIdColumn* mSound;
|
|
const RefIdColumn* mEmitterType;
|
|
std::map<const RefIdColumn*, unsigned int> mFlags;
|
|
|
|
LightColumns(const InventoryColumns& columns);
|
|
};
|
|
|
|
class LightRefIdAdapter : public InventoryRefIdAdapter<ESM::Light>
|
|
{
|
|
LightColumns mColumns;
|
|
|
|
public:
|
|
LightRefIdAdapter(const LightColumns& columns);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
class MiscRefIdAdapter : public InventoryRefIdAdapter<ESM::Miscellaneous>
|
|
{
|
|
const RefIdColumn* mKey;
|
|
|
|
public:
|
|
MiscRefIdAdapter(const InventoryColumns& columns, const RefIdColumn* key);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
struct NpcColumns : public ActorColumns
|
|
{
|
|
std::map<const RefIdColumn*, unsigned int> mFlags;
|
|
const RefIdColumn* mRace;
|
|
const RefIdColumn* mClass;
|
|
const RefIdColumn* mFaction;
|
|
const RefIdColumn* mHair;
|
|
const RefIdColumn* mHead;
|
|
const RefIdColumn* mAttributes; // depends on npc type
|
|
const RefIdColumn* mSkills; // depends on npc type
|
|
const RefIdColumn* mMisc; // may depend on npc type, e.g. FactionID
|
|
const RefIdColumn* mBloodType;
|
|
const RefIdColumn* mGender;
|
|
|
|
NpcColumns(const ActorColumns& actorColumns);
|
|
};
|
|
|
|
class NpcRefIdAdapter : public ActorRefIdAdapter<ESM::NPC>
|
|
{
|
|
NpcColumns mColumns;
|
|
|
|
public:
|
|
NpcRefIdAdapter(const NpcColumns& columns);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
struct WeaponColumns : public EnchantableColumns
|
|
{
|
|
const RefIdColumn* mType;
|
|
const RefIdColumn* mHealth;
|
|
const RefIdColumn* mSpeed;
|
|
const RefIdColumn* mReach;
|
|
const RefIdColumn* mChop[2];
|
|
const RefIdColumn* mSlash[2];
|
|
const RefIdColumn* mThrust[2];
|
|
std::map<const RefIdColumn*, unsigned int> mFlags;
|
|
|
|
WeaponColumns(const EnchantableColumns& columns);
|
|
};
|
|
|
|
class WeaponRefIdAdapter : public EnchantableRefIdAdapter<ESM::Weapon>
|
|
{
|
|
WeaponColumns mColumns;
|
|
|
|
public:
|
|
WeaponRefIdAdapter(const WeaponColumns& columns);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
class NpcAttributesRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
public:
|
|
NpcAttributesRefIdAdapter();
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override;
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override;
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override;
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override;
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
};
|
|
|
|
class NpcSkillsRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
public:
|
|
NpcSkillsRefIdAdapter();
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override;
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override;
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override;
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override;
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
};
|
|
|
|
class NpcMiscRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
NpcMiscRefIdAdapter(const NpcMiscRefIdAdapter&);
|
|
NpcMiscRefIdAdapter& operator=(const NpcMiscRefIdAdapter&);
|
|
|
|
public:
|
|
NpcMiscRefIdAdapter();
|
|
~NpcMiscRefIdAdapter() override;
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override;
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override;
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override;
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override;
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
};
|
|
|
|
class CreatureAttributesRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
public:
|
|
CreatureAttributesRefIdAdapter();
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override;
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override;
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override;
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override;
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
};
|
|
|
|
class CreatureAttackRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
public:
|
|
CreatureAttackRefIdAdapter();
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override;
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override;
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override;
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override;
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
};
|
|
|
|
class CreatureMiscRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
CreatureMiscRefIdAdapter(const CreatureMiscRefIdAdapter&);
|
|
CreatureMiscRefIdAdapter& operator=(const CreatureMiscRefIdAdapter&);
|
|
|
|
public:
|
|
CreatureMiscRefIdAdapter();
|
|
~CreatureMiscRefIdAdapter() override;
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override;
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override;
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override;
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override;
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override;
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
};
|
|
|
|
template <typename ESXRecordT>
|
|
class EffectsListAdapter;
|
|
|
|
template <typename ESXRecordT>
|
|
class EffectsRefIdAdapter : public EffectsListAdapter<ESXRecordT>, public NestedRefIdAdapterBase
|
|
{
|
|
UniversalId::Type mType;
|
|
|
|
// not implemented
|
|
EffectsRefIdAdapter(const EffectsRefIdAdapter&);
|
|
EffectsRefIdAdapter& operator=(const EffectsRefIdAdapter&);
|
|
|
|
public:
|
|
EffectsRefIdAdapter(UniversalId::Type type)
|
|
: mType(type)
|
|
{
|
|
}
|
|
|
|
virtual ~EffectsRefIdAdapter() {}
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
EffectsListAdapter<ESXRecordT>::addRow(record, position);
|
|
}
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
EffectsListAdapter<ESXRecordT>::removeRow(record, rowToRemove);
|
|
}
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
EffectsListAdapter<ESXRecordT>::setTable(record, nestedTable);
|
|
}
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
return EffectsListAdapter<ESXRecordT>::table(record);
|
|
}
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
return EffectsListAdapter<ESXRecordT>::getData(record, subRowIndex, subColIndex);
|
|
}
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(row, mType)));
|
|
EffectsListAdapter<ESXRecordT>::setData(record, value, subRowIndex, subColIndex);
|
|
}
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override
|
|
{
|
|
const Record<ESXRecordT> record; // not used, just a dummy
|
|
return EffectsListAdapter<ESXRecordT>::getColumnsCount(record);
|
|
}
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
return EffectsListAdapter<ESXRecordT>::getRowsCount(record);
|
|
}
|
|
};
|
|
|
|
template <typename ESXRecordT>
|
|
class NestedInventoryRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
UniversalId::Type mType;
|
|
|
|
// not implemented
|
|
NestedInventoryRefIdAdapter(const NestedInventoryRefIdAdapter&);
|
|
NestedInventoryRefIdAdapter& operator=(const NestedInventoryRefIdAdapter&);
|
|
|
|
public:
|
|
NestedInventoryRefIdAdapter(UniversalId::Type type)
|
|
: mType(type)
|
|
{
|
|
}
|
|
|
|
virtual ~NestedInventoryRefIdAdapter() {}
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT container = record.get();
|
|
|
|
std::vector<ESM::ContItem>& list = container.mInventory.mList;
|
|
|
|
ESM::ContItem newRow = ESM::ContItem();
|
|
|
|
if (position >= (int)list.size())
|
|
list.push_back(newRow);
|
|
else
|
|
list.insert(list.begin() + position, newRow);
|
|
|
|
record.setModified(container);
|
|
}
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT container = record.get();
|
|
|
|
std::vector<ESM::ContItem>& list = container.mInventory.mList;
|
|
|
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
list.erase(list.begin() + rowToRemove);
|
|
|
|
record.setModified(container);
|
|
}
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT container = record.get();
|
|
|
|
container.mInventory.mList
|
|
= static_cast<const NestedTableWrapper<std::vector<typename ESM::ContItem>>&>(nestedTable).mNestedTable;
|
|
|
|
record.setModified(container);
|
|
}
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<typename ESM::ContItem>>(record.get().mInventory.mList);
|
|
}
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
const std::vector<ESM::ContItem>& list = record.get().mInventory.mList;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
const ESM::ContItem& content = list.at(subRowIndex);
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
return QString::fromUtf8(content.mItem.getRefIdString().c_str());
|
|
case 1:
|
|
return content.mCount;
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
}
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(row, mType)));
|
|
ESXRecordT container = record.get();
|
|
std::vector<ESM::ContItem>& list = container.mInventory.mList;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
list.at(subRowIndex).mItem = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
|
|
break;
|
|
|
|
case 1:
|
|
list.at(subRowIndex).mCount = value.toInt();
|
|
break;
|
|
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
|
|
record.setModified(container);
|
|
}
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override { return 2; }
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
return static_cast<int>(record.get().mInventory.mList.size());
|
|
}
|
|
};
|
|
|
|
template <typename ESXRecordT>
|
|
class NestedSpellRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
UniversalId::Type mType;
|
|
|
|
// not implemented
|
|
NestedSpellRefIdAdapter(const NestedSpellRefIdAdapter&);
|
|
NestedSpellRefIdAdapter& operator=(const NestedSpellRefIdAdapter&);
|
|
|
|
public:
|
|
NestedSpellRefIdAdapter(UniversalId::Type type)
|
|
: mType(type)
|
|
{
|
|
}
|
|
|
|
virtual ~NestedSpellRefIdAdapter() {}
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT caster = record.get();
|
|
|
|
std::vector<ESM::RefId>& list = caster.mSpells.mList;
|
|
|
|
ESM::RefId newString;
|
|
|
|
if (position >= (int)list.size())
|
|
list.push_back(newString);
|
|
else
|
|
list.insert(list.begin() + position, newString);
|
|
|
|
record.setModified(caster);
|
|
}
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT caster = record.get();
|
|
|
|
std::vector<ESM::RefId>& list = caster.mSpells.mList;
|
|
|
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
list.erase(list.begin() + rowToRemove);
|
|
|
|
record.setModified(caster);
|
|
}
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT caster = record.get();
|
|
|
|
caster.mSpells.mList
|
|
= static_cast<const NestedTableWrapper<std::vector<typename ESM::RefId>>&>(nestedTable).mNestedTable;
|
|
|
|
record.setModified(caster);
|
|
}
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<typename ESM::RefId>>(record.get().mSpells.mList);
|
|
}
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
const std::vector<ESM::RefId>& list = record.get().mSpells.mList;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
const ESM::RefId& content = list.at(subRowIndex);
|
|
|
|
if (subColIndex == 0)
|
|
return QString::fromUtf8(content.getRefIdString().c_str());
|
|
else
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(row, mType)));
|
|
ESXRecordT caster = record.get();
|
|
std::vector<ESM::RefId>& list = caster.mSpells.mList;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
if (subColIndex == 0)
|
|
list.at(subRowIndex) = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
|
|
else
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
|
|
record.setModified(caster);
|
|
}
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override { return 1; }
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
return static_cast<int>(record.get().mSpells.mList.size());
|
|
}
|
|
};
|
|
|
|
template <typename ESXRecordT>
|
|
class NestedTravelRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
UniversalId::Type mType;
|
|
|
|
// not implemented
|
|
NestedTravelRefIdAdapter(const NestedTravelRefIdAdapter&);
|
|
NestedTravelRefIdAdapter& operator=(const NestedTravelRefIdAdapter&);
|
|
|
|
public:
|
|
NestedTravelRefIdAdapter(UniversalId::Type type)
|
|
: mType(type)
|
|
{
|
|
}
|
|
|
|
virtual ~NestedTravelRefIdAdapter() {}
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT traveller = record.get();
|
|
|
|
std::vector<ESM::Transport::Dest>& list = traveller.mTransport.mList;
|
|
|
|
ESM::Position newPos;
|
|
for (unsigned i = 0; i < 3; ++i)
|
|
{
|
|
newPos.pos[i] = 0;
|
|
newPos.rot[i] = 0;
|
|
}
|
|
|
|
ESM::Transport::Dest newRow;
|
|
newRow.mPos = newPos;
|
|
newRow.mCellName = ESM::RefId::sEmpty;
|
|
|
|
if (position >= (int)list.size())
|
|
list.push_back(newRow);
|
|
else
|
|
list.insert(list.begin() + position, newRow);
|
|
|
|
record.setModified(traveller);
|
|
}
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT traveller = record.get();
|
|
|
|
std::vector<ESM::Transport::Dest>& list = traveller.mTransport.mList;
|
|
|
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
list.erase(list.begin() + rowToRemove);
|
|
|
|
record.setModified(traveller);
|
|
}
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT traveller = record.get();
|
|
|
|
traveller.mTransport.mList
|
|
= static_cast<const NestedTableWrapper<std::vector<typename ESM::Transport::Dest>>&>(nestedTable)
|
|
.mNestedTable;
|
|
|
|
record.setModified(traveller);
|
|
}
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<typename ESM::Transport::Dest>>(record.get().mTransport.mList);
|
|
}
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
const std::vector<ESM::Transport::Dest>& list = record.get().mTransport.mList;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
const ESM::Transport::Dest& content = list.at(subRowIndex);
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
return QString::fromUtf8(content.mCellName.getRefIdString().c_str());
|
|
case 1:
|
|
return content.mPos.pos[0];
|
|
case 2:
|
|
return content.mPos.pos[1];
|
|
case 3:
|
|
return content.mPos.pos[2];
|
|
case 4:
|
|
return content.mPos.rot[0];
|
|
case 5:
|
|
return content.mPos.rot[1];
|
|
case 6:
|
|
return content.mPos.rot[2];
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
}
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(row, mType)));
|
|
ESXRecordT traveller = record.get();
|
|
std::vector<ESM::Transport::Dest>& list = traveller.mTransport.mList;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
list.at(subRowIndex).mCellName = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
|
|
break;
|
|
case 1:
|
|
list.at(subRowIndex).mPos.pos[0] = value.toFloat();
|
|
break;
|
|
case 2:
|
|
list.at(subRowIndex).mPos.pos[1] = value.toFloat();
|
|
break;
|
|
case 3:
|
|
list.at(subRowIndex).mPos.pos[2] = value.toFloat();
|
|
break;
|
|
case 4:
|
|
list.at(subRowIndex).mPos.rot[0] = value.toFloat();
|
|
break;
|
|
case 5:
|
|
list.at(subRowIndex).mPos.rot[1] = value.toFloat();
|
|
break;
|
|
case 6:
|
|
list.at(subRowIndex).mPos.rot[2] = value.toFloat();
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
|
|
record.setModified(traveller);
|
|
}
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override { return 7; }
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
return static_cast<int>(record.get().mTransport.mList.size());
|
|
}
|
|
};
|
|
|
|
template <typename ESXRecordT>
|
|
class ActorAiRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
UniversalId::Type mType;
|
|
|
|
// not implemented
|
|
ActorAiRefIdAdapter(const ActorAiRefIdAdapter&);
|
|
ActorAiRefIdAdapter& operator=(const ActorAiRefIdAdapter&);
|
|
|
|
public:
|
|
ActorAiRefIdAdapter(UniversalId::Type type)
|
|
: mType(type)
|
|
{
|
|
}
|
|
|
|
virtual ~ActorAiRefIdAdapter() {}
|
|
|
|
// FIXME: should check if the AI package type is already in the list and use a default
|
|
// that wasn't used already (in extreme case do not add anything at all?
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT actor = record.get();
|
|
|
|
std::vector<ESM::AIPackage>& list = actor.mAiPackage.mList;
|
|
|
|
ESM::AIPackage newRow;
|
|
newRow.mType = ESM::AI_Wander;
|
|
newRow.mWander.mDistance = 0;
|
|
newRow.mWander.mDuration = 0;
|
|
newRow.mWander.mTimeOfDay = 0;
|
|
for (int i = 0; i < 8; ++i)
|
|
newRow.mWander.mIdle[i] = 0;
|
|
newRow.mWander.mShouldRepeat = 1;
|
|
newRow.mCellName.clear();
|
|
|
|
if (position >= (int)list.size())
|
|
list.push_back(newRow);
|
|
else
|
|
list.insert(list.begin() + position, newRow);
|
|
|
|
record.setModified(actor);
|
|
}
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT actor = record.get();
|
|
|
|
std::vector<ESM::AIPackage>& list = actor.mAiPackage.mList;
|
|
|
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
list.erase(list.begin() + rowToRemove);
|
|
|
|
record.setModified(actor);
|
|
}
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT actor = record.get();
|
|
|
|
actor.mAiPackage.mList
|
|
= static_cast<const NestedTableWrapper<std::vector<typename ESM::AIPackage>>&>(nestedTable)
|
|
.mNestedTable;
|
|
|
|
record.setModified(actor);
|
|
}
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<typename ESM::AIPackage>>(record.get().mAiPackage.mList);
|
|
}
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
const std::vector<ESM::AIPackage>& list = record.get().mAiPackage.mList;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
const ESM::AIPackage& content = list.at(subRowIndex);
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
// FIXME: should more than one AI package type be allowed? Check vanilla
|
|
switch (content.mType)
|
|
{
|
|
case ESM::AI_Wander:
|
|
return 0;
|
|
case ESM::AI_Travel:
|
|
return 1;
|
|
case ESM::AI_Follow:
|
|
return 2;
|
|
case ESM::AI_Escort:
|
|
return 3;
|
|
case ESM::AI_Activate:
|
|
return 4;
|
|
default:
|
|
return QVariant();
|
|
}
|
|
case 1: // wander dist
|
|
if (content.mType == ESM::AI_Wander)
|
|
return content.mWander.mDistance;
|
|
else
|
|
return QVariant();
|
|
case 2: // wander/follow dur
|
|
if (content.mType == ESM::AI_Wander)
|
|
return content.mWander.mDuration;
|
|
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
return content.mTarget.mDuration;
|
|
else
|
|
return QVariant();
|
|
case 3: // wander ToD
|
|
if (content.mType == ESM::AI_Wander)
|
|
return content.mWander.mTimeOfDay; // FIXME: not sure of the format
|
|
else
|
|
return QVariant();
|
|
case 4: // wander idle
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
case 11:
|
|
if (content.mType == ESM::AI_Wander)
|
|
return static_cast<int>(content.mWander.mIdle[subColIndex - 4]);
|
|
else
|
|
return QVariant();
|
|
case 12: // repeat
|
|
if (content.mType == ESM::AI_Wander)
|
|
return content.mWander.mShouldRepeat != 0;
|
|
else if (content.mType == ESM::AI_Travel)
|
|
return content.mTravel.mShouldRepeat != 0;
|
|
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
return content.mTarget.mShouldRepeat != 0;
|
|
else if (content.mType == ESM::AI_Activate)
|
|
return content.mActivate.mShouldRepeat != 0;
|
|
else
|
|
return QVariant();
|
|
case 13: // activate name
|
|
if (content.mType == ESM::AI_Activate)
|
|
return QString(content.mActivate.mName.toString().c_str());
|
|
else
|
|
return QVariant();
|
|
case 14: // target id
|
|
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
return QString(content.mTarget.mId.toString().c_str());
|
|
else
|
|
return QVariant();
|
|
case 15: // target cell
|
|
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
return QString::fromUtf8(content.mCellName.c_str());
|
|
else
|
|
return QVariant();
|
|
case 16:
|
|
if (content.mType == ESM::AI_Travel)
|
|
return content.mTravel.mX;
|
|
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
return content.mTarget.mX;
|
|
else
|
|
return QVariant();
|
|
case 17:
|
|
if (content.mType == ESM::AI_Travel)
|
|
return content.mTravel.mY;
|
|
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
return content.mTarget.mY;
|
|
else
|
|
return QVariant();
|
|
case 18:
|
|
if (content.mType == ESM::AI_Travel)
|
|
return content.mTravel.mZ;
|
|
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
return content.mTarget.mZ;
|
|
else
|
|
return QVariant();
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
}
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(row, mType)));
|
|
ESXRecordT actor = record.get();
|
|
std::vector<ESM::AIPackage>& list = actor.mAiPackage.mList;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
ESM::AIPackage& content = list.at(subRowIndex);
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0: // ai package type
|
|
switch (value.toInt())
|
|
{
|
|
case 0:
|
|
content.mType = ESM::AI_Wander;
|
|
break;
|
|
case 1:
|
|
content.mType = ESM::AI_Travel;
|
|
break;
|
|
case 2:
|
|
content.mType = ESM::AI_Follow;
|
|
break;
|
|
case 3:
|
|
content.mType = ESM::AI_Escort;
|
|
break;
|
|
case 4:
|
|
content.mType = ESM::AI_Activate;
|
|
break;
|
|
default:
|
|
return; // return without saving
|
|
}
|
|
break; // always save
|
|
|
|
case 1:
|
|
if (content.mType == ESM::AI_Wander)
|
|
content.mWander.mDistance = static_cast<short>(value.toInt());
|
|
else
|
|
return; // return without saving
|
|
|
|
break; // always save
|
|
case 2:
|
|
if (content.mType == ESM::AI_Wander)
|
|
content.mWander.mDuration = static_cast<short>(value.toInt());
|
|
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
content.mTarget.mDuration = static_cast<short>(value.toInt());
|
|
else
|
|
return; // return without saving
|
|
break;
|
|
case 3:
|
|
if (content.mType == ESM::AI_Wander)
|
|
content.mWander.mTimeOfDay = static_cast<unsigned char>(value.toInt());
|
|
else
|
|
return; // return without saving
|
|
|
|
break; // always save
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
case 11:
|
|
if (content.mType == ESM::AI_Wander)
|
|
content.mWander.mIdle[subColIndex - 4] = static_cast<unsigned char>(value.toInt());
|
|
else
|
|
return; // return without saving
|
|
|
|
break; // always save
|
|
case 12:
|
|
if (content.mType == ESM::AI_Wander)
|
|
content.mWander.mShouldRepeat = static_cast<unsigned char>(value.toInt());
|
|
else if (content.mType == ESM::AI_Travel)
|
|
content.mTravel.mShouldRepeat = static_cast<unsigned char>(value.toInt());
|
|
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
content.mTarget.mShouldRepeat = static_cast<unsigned char>(value.toInt());
|
|
else if (content.mType == ESM::AI_Activate)
|
|
content.mActivate.mShouldRepeat = static_cast<unsigned char>(value.toInt());
|
|
else
|
|
return; // return without saving
|
|
|
|
break; // always save
|
|
case 13: // NAME32
|
|
if (content.mType == ESM::AI_Activate)
|
|
{
|
|
const QByteArray name = value.toString().toUtf8();
|
|
content.mActivate.mName.assign(std::string_view(name.constData(), name.size()));
|
|
}
|
|
else
|
|
return; // return without saving
|
|
|
|
break; // always save
|
|
case 14: // NAME32
|
|
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
{
|
|
const QByteArray id = value.toString().toUtf8();
|
|
content.mTarget.mId.assign(std::string_view(id.constData(), id.size()));
|
|
}
|
|
else
|
|
return; // return without saving
|
|
|
|
break; // always save
|
|
case 15:
|
|
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
content.mCellName = std::string(value.toString().toUtf8().constData());
|
|
else
|
|
return; // return without saving
|
|
|
|
break; // always save
|
|
case 16:
|
|
if (content.mType == ESM::AI_Travel)
|
|
content.mTravel.mX = value.toFloat();
|
|
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
content.mTarget.mX = value.toFloat();
|
|
else
|
|
return; // return without saving
|
|
|
|
break; // always save
|
|
case 17:
|
|
if (content.mType == ESM::AI_Travel)
|
|
content.mTravel.mY = value.toFloat();
|
|
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
content.mTarget.mY = value.toFloat();
|
|
else
|
|
return; // return without saving
|
|
|
|
break; // always save
|
|
case 18:
|
|
if (content.mType == ESM::AI_Travel)
|
|
content.mTravel.mZ = value.toFloat();
|
|
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
|
content.mTarget.mZ = value.toFloat();
|
|
else
|
|
return; // return without saving
|
|
|
|
break; // always save
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
|
|
record.setModified(actor);
|
|
}
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override { return 19; }
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
return static_cast<int>(record.get().mAiPackage.mList.size());
|
|
}
|
|
};
|
|
|
|
template <typename ESXRecordT>
|
|
class BodyPartRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
UniversalId::Type mType;
|
|
|
|
// not implemented
|
|
BodyPartRefIdAdapter(const BodyPartRefIdAdapter&);
|
|
BodyPartRefIdAdapter& operator=(const BodyPartRefIdAdapter&);
|
|
|
|
public:
|
|
BodyPartRefIdAdapter(UniversalId::Type type)
|
|
: mType(type)
|
|
{
|
|
}
|
|
|
|
virtual ~BodyPartRefIdAdapter() {}
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT apparel = record.get();
|
|
|
|
std::vector<ESM::PartReference>& list = apparel.mParts.mParts;
|
|
|
|
ESM::PartReference newPart;
|
|
newPart.mPart = 0; // 0 == head
|
|
newPart.mMale = ESM::RefId::sEmpty;
|
|
newPart.mFemale = ESM::RefId::sEmpty;
|
|
|
|
if (position >= (int)list.size())
|
|
list.push_back(newPart);
|
|
else
|
|
list.insert(list.begin() + position, newPart);
|
|
|
|
record.setModified(apparel);
|
|
}
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT apparel = record.get();
|
|
|
|
std::vector<ESM::PartReference>& list = apparel.mParts.mParts;
|
|
|
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
list.erase(list.begin() + rowToRemove);
|
|
|
|
record.setModified(apparel);
|
|
}
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT apparel = record.get();
|
|
|
|
apparel.mParts.mParts
|
|
= static_cast<const NestedTableWrapper<std::vector<typename ESM::PartReference>>&>(nestedTable)
|
|
.mNestedTable;
|
|
|
|
record.setModified(apparel);
|
|
}
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<typename ESM::PartReference>>(record.get().mParts.mParts);
|
|
}
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
const std::vector<ESM::PartReference>& list = record.get().mParts.mParts;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
const ESM::PartReference& content = list.at(subRowIndex);
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
{
|
|
if (content.mPart < ESM::PRT_Count)
|
|
return content.mPart;
|
|
else
|
|
throw std::runtime_error("Part Reference Type unexpected value");
|
|
}
|
|
case 1:
|
|
return QString(content.mMale.getRefIdString().c_str());
|
|
case 2:
|
|
return QString(content.mFemale.getRefIdString().c_str());
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
}
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(row, mType)));
|
|
ESXRecordT apparel = record.get();
|
|
std::vector<ESM::PartReference>& list = apparel.mParts.mParts;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
list.at(subRowIndex).mPart = static_cast<unsigned char>(value.toInt());
|
|
break;
|
|
case 1:
|
|
list.at(subRowIndex).mMale = ESM::RefId::stringRefId(value.toString().toStdString());
|
|
break;
|
|
case 2:
|
|
list.at(subRowIndex).mFemale = ESM::RefId::stringRefId(value.toString().toStdString());
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
|
|
record.setModified(apparel);
|
|
}
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override { return 3; }
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
return static_cast<int>(record.get().mParts.mParts.size());
|
|
}
|
|
};
|
|
|
|
struct LevListColumns : public BaseColumns
|
|
{
|
|
const RefIdColumn* mLevList;
|
|
const RefIdColumn* mNestedListLevList;
|
|
|
|
LevListColumns(const BaseColumns& base)
|
|
: BaseColumns(base)
|
|
, mLevList(nullptr)
|
|
, mNestedListLevList(nullptr)
|
|
{
|
|
}
|
|
};
|
|
|
|
template <typename RecordT>
|
|
class LevelledListRefIdAdapter : public BaseRefIdAdapter<RecordT>
|
|
{
|
|
LevListColumns mLevList;
|
|
|
|
public:
|
|
LevelledListRefIdAdapter(UniversalId::Type type, const LevListColumns& columns);
|
|
|
|
QVariant getData(const RefIdColumn* column, const RefIdData& data, int index) const override;
|
|
|
|
void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const override;
|
|
///< If the data type does not match an exception is thrown.
|
|
};
|
|
|
|
template <typename RecordT>
|
|
LevelledListRefIdAdapter<RecordT>::LevelledListRefIdAdapter(UniversalId::Type type, const LevListColumns& columns)
|
|
: BaseRefIdAdapter<RecordT>(type, columns)
|
|
, mLevList(columns)
|
|
{
|
|
}
|
|
|
|
template <typename RecordT>
|
|
QVariant LevelledListRefIdAdapter<RecordT>::getData(
|
|
const RefIdColumn* column, const RefIdData& data, int index) const
|
|
{
|
|
if (column == mLevList.mLevList || column == mLevList.mNestedListLevList)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
|
|
|
return BaseRefIdAdapter<RecordT>::getData(column, data, index);
|
|
}
|
|
|
|
template <typename RecordT>
|
|
void LevelledListRefIdAdapter<RecordT>::setData(
|
|
const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const
|
|
{
|
|
BaseRefIdAdapter<RecordT>::setData(column, data, index, value);
|
|
return;
|
|
}
|
|
|
|
// for non-tables
|
|
template <typename ESXRecordT>
|
|
class NestedListLevListRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
UniversalId::Type mType;
|
|
|
|
// not implemented
|
|
NestedListLevListRefIdAdapter(const NestedListLevListRefIdAdapter&);
|
|
NestedListLevListRefIdAdapter& operator=(const NestedListLevListRefIdAdapter&);
|
|
|
|
public:
|
|
NestedListLevListRefIdAdapter(UniversalId::Type type)
|
|
: mType(type)
|
|
{
|
|
}
|
|
|
|
virtual ~NestedListLevListRefIdAdapter() {}
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override
|
|
{
|
|
throw std::logic_error("cannot add a row to a fixed table");
|
|
}
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override
|
|
{
|
|
throw std::logic_error("cannot remove a row to a fixed table");
|
|
}
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override
|
|
{
|
|
throw std::logic_error("table operation not supported");
|
|
}
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
throw std::logic_error("table operation not supported");
|
|
}
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
if (mType == UniversalId::Type_CreatureLevelledList)
|
|
{
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
return QVariant(); // disable the checkbox editor
|
|
case 1:
|
|
return record.get().mFlags & ESM::CreatureLevList::AllLevels;
|
|
case 2:
|
|
return static_cast<int>(record.get().mChanceNone);
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in levelled creatues!");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
return record.get().mFlags & ESM::ItemLevList::Each;
|
|
case 1:
|
|
return record.get().mFlags & ESM::ItemLevList::AllLevels;
|
|
case 2:
|
|
return static_cast<int>(record.get().mChanceNone);
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in levelled items!");
|
|
}
|
|
}
|
|
}
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(row, mType)));
|
|
ESXRecordT leveled = record.get();
|
|
|
|
if (mType == UniversalId::Type_CreatureLevelledList)
|
|
{
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
return; // return without saving
|
|
case 1:
|
|
{
|
|
if (value.toBool())
|
|
{
|
|
leveled.mFlags |= ESM::CreatureLevList::AllLevels;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
leveled.mFlags &= ~ESM::CreatureLevList::AllLevels;
|
|
break;
|
|
}
|
|
}
|
|
case 2:
|
|
leveled.mChanceNone = static_cast<unsigned char>(value.toInt());
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Trying to set non-existing column in levelled creatures!");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
{
|
|
if (value.toBool())
|
|
{
|
|
leveled.mFlags |= ESM::ItemLevList::Each;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
leveled.mFlags &= ~ESM::ItemLevList::Each;
|
|
break;
|
|
}
|
|
}
|
|
case 1:
|
|
{
|
|
if (value.toBool())
|
|
{
|
|
leveled.mFlags |= ESM::ItemLevList::AllLevels;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
leveled.mFlags &= ~ESM::ItemLevList::AllLevels;
|
|
break;
|
|
}
|
|
}
|
|
case 2:
|
|
leveled.mChanceNone = static_cast<unsigned char>(value.toInt());
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Trying to set non-existing column in levelled items!");
|
|
}
|
|
}
|
|
|
|
record.setModified(leveled);
|
|
}
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override { return 3; }
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
return 1; // fixed at size 1
|
|
}
|
|
};
|
|
|
|
// for tables
|
|
template <typename ESXRecordT>
|
|
class NestedLevListRefIdAdapter : public NestedRefIdAdapterBase
|
|
{
|
|
UniversalId::Type mType;
|
|
|
|
// not implemented
|
|
NestedLevListRefIdAdapter(const NestedLevListRefIdAdapter&);
|
|
NestedLevListRefIdAdapter& operator=(const NestedLevListRefIdAdapter&);
|
|
|
|
public:
|
|
NestedLevListRefIdAdapter(UniversalId::Type type)
|
|
: mType(type)
|
|
{
|
|
}
|
|
|
|
virtual ~NestedLevListRefIdAdapter() {}
|
|
|
|
void addNestedRow(const RefIdColumn* column, RefIdData& data, int index, int position) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT leveled = record.get();
|
|
|
|
std::vector<ESM::LevelledListBase::LevelItem>& list = leveled.mList;
|
|
|
|
ESM::LevelledListBase::LevelItem newItem;
|
|
newItem.mId = ESM::RefId::sEmpty;
|
|
newItem.mLevel = 0;
|
|
|
|
if (position >= (int)list.size())
|
|
list.push_back(newItem);
|
|
else
|
|
list.insert(list.begin() + position, newItem);
|
|
|
|
record.setModified(leveled);
|
|
}
|
|
|
|
void removeNestedRow(const RefIdColumn* column, RefIdData& data, int index, int rowToRemove) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT leveled = record.get();
|
|
|
|
std::vector<ESM::LevelledListBase::LevelItem>& list = leveled.mList;
|
|
|
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
list.erase(list.begin() + rowToRemove);
|
|
|
|
record.setModified(leveled);
|
|
}
|
|
|
|
void setNestedTable(const RefIdColumn* column, RefIdData& data, int index,
|
|
const NestedTableWrapperBase& nestedTable) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
ESXRecordT leveled = record.get();
|
|
|
|
leveled.mList
|
|
= static_cast<const NestedTableWrapper<std::vector<typename ESM::LevelledListBase::LevelItem>>&>(
|
|
nestedTable)
|
|
.mNestedTable;
|
|
|
|
record.setModified(leveled);
|
|
}
|
|
|
|
NestedTableWrapperBase* nestedTable(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<typename ESM::LevelledListBase::LevelItem>>(record.get().mList);
|
|
}
|
|
|
|
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
const std::vector<ESM::LevelledListBase::LevelItem>& list = record.get().mList;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
const ESM::LevelledListBase::LevelItem& content = list.at(subRowIndex);
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
return QString(content.mId.getRefIdString().c_str());
|
|
case 1:
|
|
return content.mLevel;
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
}
|
|
|
|
void setNestedData(const RefIdColumn* column, RefIdData& data, int row, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const override
|
|
{
|
|
Record<ESXRecordT>& record
|
|
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(row, mType)));
|
|
ESXRecordT leveled = record.get();
|
|
std::vector<ESM::LevelledListBase::LevelItem>& list = leveled.mList;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
|
|
throw std::runtime_error("index out of range");
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
list.at(subRowIndex).mId = ESM::RefId::stringRefId(value.toString().toStdString());
|
|
break;
|
|
case 1:
|
|
list.at(subRowIndex).mLevel = static_cast<short>(value.toInt());
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
|
|
record.setModified(leveled);
|
|
}
|
|
|
|
int getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const override { return 2; }
|
|
|
|
int getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const override
|
|
{
|
|
const Record<ESXRecordT>& record
|
|
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
|
|
|
|
return static_cast<int>(record.get().mList.size());
|
|
}
|
|
};
|
|
}
|
|
|
|
#endif
|