You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1094 lines
37 KiB
C++
1094 lines
37 KiB
C++
#include "nestedcoladapterimp.hpp"
|
|
|
|
#include <components/esm/loadregn.hpp>
|
|
#include <components/esm/loadfact.hpp>
|
|
|
|
#include "idcollection.hpp"
|
|
#include "pathgrid.hpp"
|
|
#include "info.hpp"
|
|
#include "infoselectwrapper.hpp"
|
|
|
|
namespace CSMWorld
|
|
{
|
|
PathgridPointListAdapter::PathgridPointListAdapter () {}
|
|
|
|
void PathgridPointListAdapter::addRow(Record<Pathgrid>& record, int position) const
|
|
{
|
|
Pathgrid pathgrid = record.get();
|
|
|
|
ESM::Pathgrid::PointList& points = pathgrid.mPoints;
|
|
|
|
// blank row
|
|
ESM::Pathgrid::Point point;
|
|
point.mX = 0;
|
|
point.mY = 0;
|
|
point.mZ = 0;
|
|
point.mAutogenerated = 0;
|
|
point.mConnectionNum = 0;
|
|
point.mUnknown = 0;
|
|
|
|
points.insert(points.begin()+position, point);
|
|
pathgrid.mData.mS2 = pathgrid.mPoints.size();
|
|
|
|
record.setModified (pathgrid);
|
|
}
|
|
|
|
void PathgridPointListAdapter::removeRow(Record<Pathgrid>& record, int rowToRemove) const
|
|
{
|
|
Pathgrid pathgrid = record.get();
|
|
|
|
ESM::Pathgrid::PointList& points = pathgrid.mPoints;
|
|
|
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (points.size()))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
// Do not remove dangling edges, does not work with current undo mechanism
|
|
// Do not automatically adjust indices, what would be done with dangling edges?
|
|
points.erase(points.begin()+rowToRemove);
|
|
pathgrid.mData.mS2 = pathgrid.mPoints.size();
|
|
|
|
record.setModified (pathgrid);
|
|
}
|
|
|
|
void PathgridPointListAdapter::setTable(Record<Pathgrid>& record,
|
|
const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
Pathgrid pathgrid = record.get();
|
|
pathgrid.mPoints = static_cast<const NestedTableWrapper<ESM::Pathgrid::PointList> &>(nestedTable).mNestedTable;
|
|
pathgrid.mData.mS2 = pathgrid.mPoints.size();
|
|
|
|
record.setModified (pathgrid);
|
|
}
|
|
|
|
NestedTableWrapperBase* PathgridPointListAdapter::table(const Record<Pathgrid>& record) const
|
|
{
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<ESM::Pathgrid::PointList>(record.get().mPoints);
|
|
}
|
|
|
|
QVariant PathgridPointListAdapter::getData(const Record<Pathgrid>& record,
|
|
int subRowIndex, int subColIndex) const
|
|
{
|
|
ESM::Pathgrid::Point point = record.get().mPoints[subRowIndex];
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return subRowIndex;
|
|
case 1: return point.mX;
|
|
case 2: return point.mY;
|
|
case 3: return point.mZ;
|
|
default: throw std::runtime_error("Pathgrid point subcolumn index out of range");
|
|
}
|
|
}
|
|
|
|
void PathgridPointListAdapter::setData(Record<Pathgrid>& record,
|
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
Pathgrid pathgrid = record.get();
|
|
ESM::Pathgrid::Point point = pathgrid.mPoints[subRowIndex];
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return; // return without saving
|
|
case 1: point.mX = value.toInt(); break;
|
|
case 2: point.mY = value.toInt(); break;
|
|
case 3: point.mZ = value.toInt(); break;
|
|
default: throw std::runtime_error("Pathgrid point subcolumn index out of range");
|
|
}
|
|
|
|
pathgrid.mPoints[subRowIndex] = point;
|
|
|
|
record.setModified (pathgrid);
|
|
}
|
|
|
|
int PathgridPointListAdapter::getColumnsCount(const Record<Pathgrid>& record) const
|
|
{
|
|
return 4;
|
|
}
|
|
|
|
int PathgridPointListAdapter::getRowsCount(const Record<Pathgrid>& record) const
|
|
{
|
|
return static_cast<int>(record.get().mPoints.size());
|
|
}
|
|
|
|
PathgridEdgeListAdapter::PathgridEdgeListAdapter () {}
|
|
|
|
void PathgridEdgeListAdapter::addRow(Record<Pathgrid>& record, int position) const
|
|
{
|
|
Pathgrid pathgrid = record.get();
|
|
|
|
ESM::Pathgrid::EdgeList& edges = pathgrid.mEdges;
|
|
|
|
// blank row
|
|
ESM::Pathgrid::Edge edge;
|
|
edge.mV0 = 0;
|
|
edge.mV1 = 0;
|
|
|
|
// NOTE: inserting a blank edge does not really make sense, perhaps this should be a
|
|
// logic_error exception
|
|
//
|
|
// Currently the code assumes that the end user to know what he/she is doing.
|
|
// e.g. Edges come in pairs, from points a->b and b->a
|
|
edges.insert(edges.begin()+position, edge);
|
|
|
|
record.setModified (pathgrid);
|
|
}
|
|
|
|
void PathgridEdgeListAdapter::removeRow(Record<Pathgrid>& record, int rowToRemove) const
|
|
{
|
|
Pathgrid pathgrid = record.get();
|
|
|
|
ESM::Pathgrid::EdgeList& edges = pathgrid.mEdges;
|
|
|
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (edges.size()))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
edges.erase(edges.begin()+rowToRemove);
|
|
|
|
record.setModified (pathgrid);
|
|
}
|
|
|
|
void PathgridEdgeListAdapter::setTable(Record<Pathgrid>& record,
|
|
const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
Pathgrid pathgrid = record.get();
|
|
|
|
pathgrid.mEdges =
|
|
static_cast<const NestedTableWrapper<ESM::Pathgrid::EdgeList> &>(nestedTable).mNestedTable;
|
|
|
|
record.setModified (pathgrid);
|
|
}
|
|
|
|
NestedTableWrapperBase* PathgridEdgeListAdapter::table(const Record<Pathgrid>& record) const
|
|
{
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<ESM::Pathgrid::EdgeList>(record.get().mEdges);
|
|
}
|
|
|
|
QVariant PathgridEdgeListAdapter::getData(const Record<Pathgrid>& record,
|
|
int subRowIndex, int subColIndex) const
|
|
{
|
|
Pathgrid pathgrid = record.get();
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (pathgrid.mEdges.size()))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
ESM::Pathgrid::Edge edge = pathgrid.mEdges[subRowIndex];
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return subRowIndex;
|
|
case 1: return edge.mV0;
|
|
case 2: return edge.mV1;
|
|
default: throw std::runtime_error("Pathgrid edge subcolumn index out of range");
|
|
}
|
|
}
|
|
|
|
void PathgridEdgeListAdapter::setData(Record<Pathgrid>& record,
|
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
Pathgrid pathgrid = record.get();
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (pathgrid.mEdges.size()))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
ESM::Pathgrid::Edge edge = pathgrid.mEdges[subRowIndex];
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return; // return without saving
|
|
case 1: edge.mV0 = value.toInt(); break;
|
|
case 2: edge.mV1 = value.toInt(); break;
|
|
default: throw std::runtime_error("Pathgrid edge subcolumn index out of range");
|
|
}
|
|
|
|
pathgrid.mEdges[subRowIndex] = edge;
|
|
|
|
record.setModified (pathgrid);
|
|
}
|
|
|
|
int PathgridEdgeListAdapter::getColumnsCount(const Record<Pathgrid>& record) const
|
|
{
|
|
return 3;
|
|
}
|
|
|
|
int PathgridEdgeListAdapter::getRowsCount(const Record<Pathgrid>& record) const
|
|
{
|
|
return static_cast<int>(record.get().mEdges.size());
|
|
}
|
|
|
|
FactionReactionsAdapter::FactionReactionsAdapter () {}
|
|
|
|
void FactionReactionsAdapter::addRow(Record<ESM::Faction>& record, int position) const
|
|
{
|
|
ESM::Faction faction = record.get();
|
|
|
|
std::map<std::string, int>& reactions = faction.mReactions;
|
|
|
|
// blank row
|
|
reactions.insert(std::make_pair("", 0));
|
|
|
|
record.setModified (faction);
|
|
}
|
|
|
|
void FactionReactionsAdapter::removeRow(Record<ESM::Faction>& record, int rowToRemove) const
|
|
{
|
|
ESM::Faction faction = record.get();
|
|
|
|
std::map<std::string, int>& reactions = faction.mReactions;
|
|
|
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (reactions.size()))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
// FIXME: how to ensure that the map entries correspond to table indicies?
|
|
// WARNING: Assumed that the table view has the same order as std::map
|
|
std::map<std::string, int>::iterator iter = reactions.begin();
|
|
for(int i = 0; i < rowToRemove; ++i)
|
|
++iter;
|
|
reactions.erase(iter);
|
|
|
|
record.setModified (faction);
|
|
}
|
|
|
|
void FactionReactionsAdapter::setTable(Record<ESM::Faction>& record,
|
|
const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
ESM::Faction faction = record.get();
|
|
|
|
faction.mReactions =
|
|
static_cast<const NestedTableWrapper<std::map<std::string, int> >&>(nestedTable).mNestedTable;
|
|
|
|
record.setModified (faction);
|
|
}
|
|
|
|
NestedTableWrapperBase* FactionReactionsAdapter::table(const Record<ESM::Faction>& record) const
|
|
{
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::map<std::string, int> >(record.get().mReactions);
|
|
}
|
|
|
|
QVariant FactionReactionsAdapter::getData(const Record<ESM::Faction>& record,
|
|
int subRowIndex, int subColIndex) const
|
|
{
|
|
ESM::Faction faction = record.get();
|
|
|
|
std::map<std::string, int>& reactions = faction.mReactions;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (reactions.size()))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
// FIXME: how to ensure that the map entries correspond to table indicies?
|
|
// WARNING: Assumed that the table view has the same order as std::map
|
|
std::map<std::string, int>::const_iterator iter = reactions.begin();
|
|
for(int i = 0; i < subRowIndex; ++i)
|
|
++iter;
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return QString((*iter).first.c_str());
|
|
case 1: return (*iter).second;
|
|
default: throw std::runtime_error("Faction reactions subcolumn index out of range");
|
|
}
|
|
}
|
|
|
|
void FactionReactionsAdapter::setData(Record<ESM::Faction>& record,
|
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
ESM::Faction faction = record.get();
|
|
|
|
std::map<std::string, int>& reactions = faction.mReactions;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (reactions.size()))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
// FIXME: how to ensure that the map entries correspond to table indicies?
|
|
// WARNING: Assumed that the table view has the same order as std::map
|
|
std::map<std::string, int>::iterator iter = reactions.begin();
|
|
for(int i = 0; i < subRowIndex; ++i)
|
|
++iter;
|
|
|
|
std::string factionId = (*iter).first;
|
|
int reaction = (*iter).second;
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
{
|
|
reactions.erase(iter);
|
|
reactions.insert(std::make_pair(value.toString().toUtf8().constData(), reaction));
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
reactions[factionId] = value.toInt();
|
|
break;
|
|
}
|
|
default: throw std::runtime_error("Faction reactions subcolumn index out of range");
|
|
}
|
|
|
|
record.setModified (faction);
|
|
}
|
|
|
|
int FactionReactionsAdapter::getColumnsCount(const Record<ESM::Faction>& record) const
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
int FactionReactionsAdapter::getRowsCount(const Record<ESM::Faction>& record) const
|
|
{
|
|
return static_cast<int>(record.get().mReactions.size());
|
|
}
|
|
|
|
RegionSoundListAdapter::RegionSoundListAdapter () {}
|
|
|
|
void RegionSoundListAdapter::addRow(Record<ESM::Region>& record, int position) const
|
|
{
|
|
ESM::Region region = record.get();
|
|
|
|
std::vector<ESM::Region::SoundRef>& soundList = region.mSoundList;
|
|
|
|
// blank row
|
|
ESM::Region::SoundRef soundRef;
|
|
soundRef.mSound.assign("");
|
|
soundRef.mChance = 0;
|
|
|
|
soundList.insert(soundList.begin()+position, soundRef);
|
|
|
|
record.setModified (region);
|
|
}
|
|
|
|
void RegionSoundListAdapter::removeRow(Record<ESM::Region>& record, int rowToRemove) const
|
|
{
|
|
ESM::Region region = record.get();
|
|
|
|
std::vector<ESM::Region::SoundRef>& soundList = region.mSoundList;
|
|
|
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (soundList.size()))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
soundList.erase(soundList.begin()+rowToRemove);
|
|
|
|
record.setModified (region);
|
|
}
|
|
|
|
void RegionSoundListAdapter::setTable(Record<ESM::Region>& record,
|
|
const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
ESM::Region region = record.get();
|
|
|
|
region.mSoundList =
|
|
static_cast<const NestedTableWrapper<std::vector<ESM::Region::SoundRef> >&>(nestedTable).mNestedTable;
|
|
|
|
record.setModified (region);
|
|
}
|
|
|
|
NestedTableWrapperBase* RegionSoundListAdapter::table(const Record<ESM::Region>& record) const
|
|
{
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<ESM::Region::SoundRef> >(record.get().mSoundList);
|
|
}
|
|
|
|
QVariant RegionSoundListAdapter::getData(const Record<ESM::Region>& record,
|
|
int subRowIndex, int subColIndex) const
|
|
{
|
|
ESM::Region region = record.get();
|
|
|
|
std::vector<ESM::Region::SoundRef>& soundList = region.mSoundList;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (soundList.size()))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
ESM::Region::SoundRef soundRef = soundList[subRowIndex];
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return QString(soundRef.mSound.toString().c_str());
|
|
case 1: return soundRef.mChance;
|
|
default: throw std::runtime_error("Region sounds subcolumn index out of range");
|
|
}
|
|
}
|
|
|
|
void RegionSoundListAdapter::setData(Record<ESM::Region>& record,
|
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
ESM::Region region = record.get();
|
|
|
|
std::vector<ESM::Region::SoundRef>& soundList = region.mSoundList;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (soundList.size()))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
ESM::Region::SoundRef soundRef = soundList[subRowIndex];
|
|
switch (subColIndex)
|
|
{
|
|
case 0: soundRef.mSound.assign(value.toString().toUtf8().constData()); break;
|
|
case 1: soundRef.mChance = static_cast<unsigned char>(value.toInt()); break;
|
|
default: throw std::runtime_error("Region sounds subcolumn index out of range");
|
|
}
|
|
|
|
region.mSoundList[subRowIndex] = soundRef;
|
|
|
|
record.setModified (region);
|
|
}
|
|
|
|
int RegionSoundListAdapter::getColumnsCount(const Record<ESM::Region>& record) const
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
int RegionSoundListAdapter::getRowsCount(const Record<ESM::Region>& record) const
|
|
{
|
|
return static_cast<int>(record.get().mSoundList.size());
|
|
}
|
|
|
|
InfoListAdapter::InfoListAdapter () {}
|
|
|
|
void InfoListAdapter::addRow(Record<Info>& record, int position) const
|
|
{
|
|
throw std::logic_error ("cannot add a row to a fixed table");
|
|
}
|
|
|
|
void InfoListAdapter::removeRow(Record<Info>& record, int rowToRemove) const
|
|
{
|
|
throw std::logic_error ("cannot remove a row to a fixed table");
|
|
}
|
|
|
|
void InfoListAdapter::setTable(Record<Info>& record,
|
|
const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
throw std::logic_error ("table operation not supported");
|
|
}
|
|
|
|
NestedTableWrapperBase* InfoListAdapter::table(const Record<Info>& record) const
|
|
{
|
|
throw std::logic_error ("table operation not supported");
|
|
}
|
|
|
|
QVariant InfoListAdapter::getData(const Record<Info>& record,
|
|
int subRowIndex, int subColIndex) const
|
|
{
|
|
Info info = record.get();
|
|
|
|
if (subColIndex == 0)
|
|
return QString(info.mResultScript.c_str());
|
|
else
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
|
|
void InfoListAdapter::setData(Record<Info>& record,
|
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
Info info = record.get();
|
|
|
|
if (subColIndex == 0)
|
|
info.mResultScript = value.toString().toStdString();
|
|
else
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
|
|
record.setModified (info);
|
|
}
|
|
|
|
int InfoListAdapter::getColumnsCount(const Record<Info>& record) const
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
int InfoListAdapter::getRowsCount(const Record<Info>& record) const
|
|
{
|
|
return 1; // fixed at size 1
|
|
}
|
|
|
|
InfoConditionAdapter::InfoConditionAdapter () {}
|
|
|
|
void InfoConditionAdapter::addRow(Record<Info>& record, int position) const
|
|
{
|
|
Info info = record.get();
|
|
|
|
std::vector<ESM::DialInfo::SelectStruct>& conditions = info.mSelects;
|
|
|
|
// default row
|
|
ESM::DialInfo::SelectStruct condStruct;
|
|
condStruct.mSelectRule = "01000";
|
|
condStruct.mValue = ESM::Variant();
|
|
condStruct.mValue.setType(ESM::VT_Int);
|
|
|
|
conditions.insert(conditions.begin()+position, condStruct);
|
|
|
|
record.setModified (info);
|
|
}
|
|
|
|
void InfoConditionAdapter::removeRow(Record<Info>& record, int rowToRemove) const
|
|
{
|
|
Info info = record.get();
|
|
|
|
std::vector<ESM::DialInfo::SelectStruct>& conditions = info.mSelects;
|
|
|
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (conditions.size()))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
conditions.erase(conditions.begin()+rowToRemove);
|
|
|
|
record.setModified (info);
|
|
}
|
|
|
|
void InfoConditionAdapter::setTable(Record<Info>& record,
|
|
const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
Info info = record.get();
|
|
|
|
info.mSelects =
|
|
static_cast<const NestedTableWrapper<std::vector<ESM::DialInfo::SelectStruct> >&>(nestedTable).mNestedTable;
|
|
|
|
record.setModified (info);
|
|
}
|
|
|
|
NestedTableWrapperBase* InfoConditionAdapter::table(const Record<Info>& record) const
|
|
{
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<ESM::DialInfo::SelectStruct> >(record.get().mSelects);
|
|
}
|
|
|
|
QVariant InfoConditionAdapter::getData(const Record<Info>& record,
|
|
int subRowIndex, int subColIndex) const
|
|
{
|
|
Info info = record.get();
|
|
|
|
std::vector<ESM::DialInfo::SelectStruct>& conditions = info.mSelects;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (conditions.size()))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
ConstInfoSelectWrapper infoSelectWrapper(conditions[subRowIndex]);
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
{
|
|
return infoSelectWrapper.getFunctionName();
|
|
}
|
|
case 1:
|
|
{
|
|
if (infoSelectWrapper.hasVariable())
|
|
return QString(infoSelectWrapper.getVariableName().c_str());
|
|
else
|
|
return "";
|
|
}
|
|
case 2:
|
|
{
|
|
return infoSelectWrapper.getRelationType();
|
|
}
|
|
case 3:
|
|
{
|
|
switch (infoSelectWrapper.getVariant().getType())
|
|
{
|
|
case ESM::VT_Int:
|
|
{
|
|
return infoSelectWrapper.getVariant().getInteger();
|
|
}
|
|
case ESM::VT_Float:
|
|
{
|
|
return infoSelectWrapper.getVariant().getFloat();
|
|
}
|
|
default: return QVariant();
|
|
}
|
|
}
|
|
default: throw std::runtime_error("Info condition subcolumn index out of range");
|
|
}
|
|
}
|
|
|
|
void InfoConditionAdapter::setData(Record<Info>& record,
|
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
Info info = record.get();
|
|
|
|
std::vector<ESM::DialInfo::SelectStruct>& conditions = info.mSelects;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (conditions.size()))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
InfoSelectWrapper infoSelectWrapper(conditions[subRowIndex]);
|
|
bool conversionResult = false;
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0: // Function
|
|
{
|
|
infoSelectWrapper.setFunctionName(static_cast<ConstInfoSelectWrapper::FunctionName>(value.toInt()));
|
|
|
|
if (infoSelectWrapper.getComparisonType() != ConstInfoSelectWrapper::Comparison_Numeric &&
|
|
infoSelectWrapper.getVariant().getType() != ESM::VT_Int)
|
|
{
|
|
infoSelectWrapper.getVariant().setType(ESM::VT_Int);
|
|
}
|
|
|
|
infoSelectWrapper.update();
|
|
break;
|
|
}
|
|
case 1: // Variable
|
|
{
|
|
infoSelectWrapper.setVariableName(value.toString().toUtf8().constData());
|
|
infoSelectWrapper.update();
|
|
break;
|
|
}
|
|
case 2: // Relation
|
|
{
|
|
infoSelectWrapper.setRelationType(static_cast<ConstInfoSelectWrapper::RelationType>(value.toInt()));
|
|
infoSelectWrapper.update();
|
|
break;
|
|
}
|
|
case 3: // Value
|
|
{
|
|
switch (infoSelectWrapper.getComparisonType())
|
|
{
|
|
case ConstInfoSelectWrapper::Comparison_Numeric:
|
|
{
|
|
// QVariant seems to have issues converting 0
|
|
if ((value.toInt(&conversionResult) && conversionResult) || value.toString().compare("0") == 0)
|
|
{
|
|
infoSelectWrapper.getVariant().setType(ESM::VT_Int);
|
|
infoSelectWrapper.getVariant().setInteger(value.toInt());
|
|
}
|
|
else if (value.toFloat(&conversionResult) && conversionResult)
|
|
{
|
|
infoSelectWrapper.getVariant().setType(ESM::VT_Float);
|
|
infoSelectWrapper.getVariant().setFloat(value.toFloat());
|
|
}
|
|
break;
|
|
}
|
|
case ConstInfoSelectWrapper::Comparison_Boolean:
|
|
case ConstInfoSelectWrapper::Comparison_Integer:
|
|
{
|
|
if ((value.toInt(&conversionResult) && conversionResult) || value.toString().compare("0") == 0)
|
|
{
|
|
infoSelectWrapper.getVariant().setType(ESM::VT_Int);
|
|
infoSelectWrapper.getVariant().setInteger(value.toInt());
|
|
}
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
break;
|
|
}
|
|
default: throw std::runtime_error("Info condition subcolumn index out of range");
|
|
}
|
|
|
|
record.setModified (info);
|
|
}
|
|
|
|
int InfoConditionAdapter::getColumnsCount(const Record<Info>& record) const
|
|
{
|
|
return 4;
|
|
}
|
|
|
|
int InfoConditionAdapter::getRowsCount(const Record<Info>& record) const
|
|
{
|
|
return static_cast<int>(record.get().mSelects.size());
|
|
}
|
|
|
|
RaceAttributeAdapter::RaceAttributeAdapter () {}
|
|
|
|
void RaceAttributeAdapter::addRow(Record<ESM::Race>& record, int position) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void RaceAttributeAdapter::removeRow(Record<ESM::Race>& record, int rowToRemove) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void RaceAttributeAdapter::setTable(Record<ESM::Race>& record,
|
|
const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
ESM::Race race = record.get();
|
|
|
|
race.mData =
|
|
static_cast<const NestedTableWrapper<std::vector<ESM::Race::RADTstruct> >&>(nestedTable).mNestedTable.at(0);
|
|
|
|
record.setModified (race);
|
|
}
|
|
|
|
NestedTableWrapperBase* RaceAttributeAdapter::table(const Record<ESM::Race>& record) const
|
|
{
|
|
std::vector<ESM::Race::RADTstruct> wrap;
|
|
wrap.push_back(record.get().mData);
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<ESM::Race::RADTstruct> >(wrap);
|
|
}
|
|
|
|
QVariant RaceAttributeAdapter::getData(const Record<ESM::Race>& record,
|
|
int subRowIndex, int subColIndex) const
|
|
{
|
|
ESM::Race race = record.get();
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= ESM::Attribute::Length)
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return subRowIndex;
|
|
case 1: return race.mData.mAttributeValues[subRowIndex].mMale;
|
|
case 2: return race.mData.mAttributeValues[subRowIndex].mFemale;
|
|
default: throw std::runtime_error("Race Attribute subcolumn index out of range");
|
|
}
|
|
}
|
|
|
|
void RaceAttributeAdapter::setData(Record<ESM::Race>& record,
|
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
ESM::Race race = record.get();
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= ESM::Attribute::Length)
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return; // throw an exception here?
|
|
case 1: race.mData.mAttributeValues[subRowIndex].mMale = value.toInt(); break;
|
|
case 2: race.mData.mAttributeValues[subRowIndex].mFemale = value.toInt(); break;
|
|
default: throw std::runtime_error("Race Attribute subcolumn index out of range");
|
|
}
|
|
|
|
record.setModified (race);
|
|
}
|
|
|
|
int RaceAttributeAdapter::getColumnsCount(const Record<ESM::Race>& record) const
|
|
{
|
|
return 3; // attrib, male, female
|
|
}
|
|
|
|
int RaceAttributeAdapter::getRowsCount(const Record<ESM::Race>& record) const
|
|
{
|
|
return ESM::Attribute::Length; // there are 8 attributes
|
|
}
|
|
|
|
RaceSkillsBonusAdapter::RaceSkillsBonusAdapter () {}
|
|
|
|
void RaceSkillsBonusAdapter::addRow(Record<ESM::Race>& record, int position) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void RaceSkillsBonusAdapter::removeRow(Record<ESM::Race>& record, int rowToRemove) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void RaceSkillsBonusAdapter::setTable(Record<ESM::Race>& record,
|
|
const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
ESM::Race race = record.get();
|
|
|
|
race.mData =
|
|
static_cast<const NestedTableWrapper<std::vector<ESM::Race::RADTstruct> >&>(nestedTable).mNestedTable.at(0);
|
|
|
|
record.setModified (race);
|
|
}
|
|
|
|
NestedTableWrapperBase* RaceSkillsBonusAdapter::table(const Record<ESM::Race>& record) const
|
|
{
|
|
std::vector<ESM::Race::RADTstruct> wrap;
|
|
wrap.push_back(record.get().mData);
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<ESM::Race::RADTstruct> >(wrap);
|
|
}
|
|
|
|
QVariant RaceSkillsBonusAdapter::getData(const Record<ESM::Race>& record,
|
|
int subRowIndex, int subColIndex) const
|
|
{
|
|
ESM::Race race = record.get();
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(sizeof(race.mData.mBonus)/sizeof(race.mData.mBonus[0])))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return race.mData.mBonus[subRowIndex].mSkill; // can be -1
|
|
case 1: return race.mData.mBonus[subRowIndex].mBonus;
|
|
default: throw std::runtime_error("Race skill bonus subcolumn index out of range");
|
|
}
|
|
}
|
|
|
|
void RaceSkillsBonusAdapter::setData(Record<ESM::Race>& record,
|
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
ESM::Race race = record.get();
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(sizeof(race.mData.mBonus)/sizeof(race.mData.mBonus[0])))
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0: race.mData.mBonus[subRowIndex].mSkill = value.toInt(); break; // can be -1
|
|
case 1: race.mData.mBonus[subRowIndex].mBonus = value.toInt(); break;
|
|
default: throw std::runtime_error("Race skill bonus subcolumn index out of range");
|
|
}
|
|
|
|
record.setModified (race);
|
|
}
|
|
|
|
int RaceSkillsBonusAdapter::getColumnsCount(const Record<ESM::Race>& record) const
|
|
{
|
|
return 2; // skill, bonus
|
|
}
|
|
|
|
int RaceSkillsBonusAdapter::getRowsCount(const Record<ESM::Race>& record) const
|
|
{
|
|
// there are 7 skill bonuses
|
|
return static_cast<int>(sizeof(record.get().mData.mBonus)/sizeof(record.get().mData.mBonus[0]));
|
|
}
|
|
|
|
CellListAdapter::CellListAdapter () {}
|
|
|
|
void CellListAdapter::addRow(Record<CSMWorld::Cell>& record, int position) const
|
|
{
|
|
throw std::logic_error ("cannot add a row to a fixed table");
|
|
}
|
|
|
|
void CellListAdapter::removeRow(Record<CSMWorld::Cell>& record, int rowToRemove) const
|
|
{
|
|
throw std::logic_error ("cannot remove a row to a fixed table");
|
|
}
|
|
|
|
void CellListAdapter::setTable(Record<CSMWorld::Cell>& record,
|
|
const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
throw std::logic_error ("table operation not supported");
|
|
}
|
|
|
|
NestedTableWrapperBase* CellListAdapter::table(const Record<CSMWorld::Cell>& record) const
|
|
{
|
|
throw std::logic_error ("table operation not supported");
|
|
}
|
|
|
|
QVariant CellListAdapter::getData(const Record<CSMWorld::Cell>& record,
|
|
int subRowIndex, int subColIndex) const
|
|
{
|
|
CSMWorld::Cell cell = record.get();
|
|
|
|
bool isInterior = (cell.mData.mFlags & ESM::Cell::Interior) != 0;
|
|
bool behaveLikeExterior = (cell.mData.mFlags & ESM::Cell::QuasiEx) != 0;
|
|
bool interiorWater = (cell.mData.mFlags & ESM::Cell::HasWater) != 0;
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return isInterior;
|
|
case 1: return (isInterior && !behaveLikeExterior) ?
|
|
cell.mAmbi.mAmbient : QVariant(QVariant::UserType);
|
|
case 2: return (isInterior && !behaveLikeExterior) ?
|
|
cell.mAmbi.mSunlight : QVariant(QVariant::UserType);
|
|
case 3: return (isInterior && !behaveLikeExterior) ?
|
|
cell.mAmbi.mFog : QVariant(QVariant::UserType);
|
|
case 4: return (isInterior && !behaveLikeExterior) ?
|
|
cell.mAmbi.mFogDensity : QVariant(QVariant::UserType);
|
|
case 5:
|
|
{
|
|
if (isInterior && interiorWater)
|
|
return cell.mWater;
|
|
else
|
|
return QVariant(QVariant::UserType);
|
|
}
|
|
case 6: return isInterior ?
|
|
QVariant(QVariant::UserType) : cell.mMapColor; // TODO: how to select?
|
|
//case 7: return isInterior ?
|
|
//behaveLikeExterior : QVariant(QVariant::UserType);
|
|
default: throw std::runtime_error("Cell subcolumn index out of range");
|
|
}
|
|
}
|
|
|
|
void CellListAdapter::setData(Record<CSMWorld::Cell>& record,
|
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
CSMWorld::Cell cell = record.get();
|
|
|
|
bool isInterior = (cell.mData.mFlags & ESM::Cell::Interior) != 0;
|
|
bool behaveLikeExterior = (cell.mData.mFlags & ESM::Cell::QuasiEx) != 0;
|
|
bool interiorWater = (cell.mData.mFlags & ESM::Cell::HasWater) != 0;
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0:
|
|
{
|
|
if (value.toBool())
|
|
cell.mData.mFlags |= ESM::Cell::Interior;
|
|
else
|
|
cell.mData.mFlags &= ~ESM::Cell::Interior;
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
if (isInterior && !behaveLikeExterior)
|
|
cell.mAmbi.mAmbient = static_cast<int32_t>(value.toInt());
|
|
else
|
|
return; // return without saving
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
if (isInterior && !behaveLikeExterior)
|
|
cell.mAmbi.mSunlight = static_cast<int32_t>(value.toInt());
|
|
else
|
|
return; // return without saving
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
if (isInterior && !behaveLikeExterior)
|
|
cell.mAmbi.mFog = static_cast<int32_t>(value.toInt());
|
|
else
|
|
return; // return without saving
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
if (isInterior && !behaveLikeExterior)
|
|
cell.mAmbi.mFogDensity = value.toFloat();
|
|
else
|
|
return; // return without saving
|
|
break;
|
|
}
|
|
case 5:
|
|
{
|
|
if (isInterior && interiorWater)
|
|
cell.mWater = value.toFloat();
|
|
else
|
|
return; // return without saving
|
|
break;
|
|
}
|
|
case 6:
|
|
{
|
|
if (!isInterior)
|
|
cell.mMapColor = value.toInt();
|
|
else
|
|
return; // return without saving
|
|
break;
|
|
}
|
|
#if 0
|
|
// redundant since this flag is shown in the main table as "Interior Sky"
|
|
// keep here for documenting the logic based on vanilla
|
|
case 7:
|
|
{
|
|
if (isInterior)
|
|
{
|
|
if (value.toBool())
|
|
cell.mData.mFlags |= ESM::Cell::QuasiEx;
|
|
else
|
|
cell.mData.mFlags &= ~ESM::Cell::QuasiEx;
|
|
}
|
|
else
|
|
return; // return without saving
|
|
break;
|
|
}
|
|
#endif
|
|
default: throw std::runtime_error("Cell subcolumn index out of range");
|
|
}
|
|
|
|
record.setModified (cell);
|
|
}
|
|
|
|
int CellListAdapter::getColumnsCount(const Record<CSMWorld::Cell>& record) const
|
|
{
|
|
return 7;
|
|
}
|
|
|
|
int CellListAdapter::getRowsCount(const Record<CSMWorld::Cell>& record) const
|
|
{
|
|
return 1; // fixed at size 1
|
|
}
|
|
|
|
RegionWeatherAdapter::RegionWeatherAdapter () {}
|
|
|
|
void RegionWeatherAdapter::addRow(Record<ESM::Region>& record, int position) const
|
|
{
|
|
throw std::logic_error ("cannot add a row to a fixed table");
|
|
}
|
|
|
|
void RegionWeatherAdapter::removeRow(Record<ESM::Region>& record, int rowToRemove) const
|
|
{
|
|
throw std::logic_error ("cannot remove a row from a fixed table");
|
|
}
|
|
|
|
void RegionWeatherAdapter::setTable(Record<ESM::Region>& record, const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
throw std::logic_error ("table operation not supported");
|
|
}
|
|
|
|
NestedTableWrapperBase* RegionWeatherAdapter::table(const Record<ESM::Region>& record) const
|
|
{
|
|
throw std::logic_error ("table operation not supported");
|
|
}
|
|
|
|
QVariant RegionWeatherAdapter::getData(const Record<ESM::Region>& record, int subRowIndex, int subColIndex) const
|
|
{
|
|
const char* WeatherNames[] = {
|
|
"Clear",
|
|
"Cloudy",
|
|
"Fog",
|
|
"Overcast",
|
|
"Rain",
|
|
"Thunder",
|
|
"Ash",
|
|
"Blight",
|
|
"Snow",
|
|
"Blizzard"
|
|
};
|
|
|
|
const ESM::Region& region = record.get();
|
|
|
|
if (subColIndex == 0 && subRowIndex >= 0 && subRowIndex < 10)
|
|
{
|
|
return WeatherNames[subRowIndex];
|
|
}
|
|
else if (subColIndex == 1)
|
|
{
|
|
switch (subRowIndex)
|
|
{
|
|
case 0: return region.mData.mClear;
|
|
case 1: return region.mData.mCloudy;
|
|
case 2: return region.mData.mFoggy;
|
|
case 3: return region.mData.mOvercast;
|
|
case 4: return region.mData.mRain;
|
|
case 5: return region.mData.mThunder;
|
|
case 6: return region.mData.mAsh;
|
|
case 7: return region.mData.mBlight;
|
|
case 8: return region.mData.mA; // Snow
|
|
case 9: return region.mData.mB; // Blizzard
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
throw std::runtime_error("index out of range");
|
|
}
|
|
|
|
void RegionWeatherAdapter::setData(Record<ESM::Region>& record, const QVariant& value, int subRowIndex,
|
|
int subColIndex) const
|
|
{
|
|
ESM::Region region = record.get();
|
|
unsigned char chance = static_cast<unsigned char>(value.toInt());
|
|
|
|
if (subColIndex == 1)
|
|
{
|
|
switch (subRowIndex)
|
|
{
|
|
case 0: region.mData.mClear = chance; break;
|
|
case 1: region.mData.mCloudy = chance; break;
|
|
case 2: region.mData.mFoggy = chance; break;
|
|
case 3: region.mData.mOvercast = chance; break;
|
|
case 4: region.mData.mRain = chance; break;
|
|
case 5: region.mData.mThunder = chance; break;
|
|
case 6: region.mData.mAsh = chance; break;
|
|
case 7: region.mData.mBlight = chance; break;
|
|
case 8: region.mData.mA = chance; break;
|
|
case 9: region.mData.mB = chance; break;
|
|
default: throw std::runtime_error("index out of range");
|
|
}
|
|
|
|
record.setModified (region);
|
|
}
|
|
}
|
|
|
|
int RegionWeatherAdapter::getColumnsCount(const Record<ESM::Region>& record) const
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
int RegionWeatherAdapter::getRowsCount(const Record<ESM::Region>& record) const
|
|
{
|
|
return 10;
|
|
}
|
|
}
|