1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-21 05:53:54 +00:00
openmw/apps/opencs/model/world/nestedcoladapterimp.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1289 lines
43 KiB
C++
Raw Normal View History

2015-04-12 03:48:23 +00:00
#include "nestedcoladapterimp.hpp"
2015-04-12 00:52:01 +00:00
2022-10-19 17:02:00 +00:00
#include <map>
#include <stdint.h>
#include <type_traits>
#include <utility>
#include <variant>
#include <apps/opencs/model/world/cell.hpp>
#include <apps/opencs/model/world/nestedtablewrapper.hpp>
#include <apps/opencs/model/world/record.hpp>
#include <components/esm/attr.hpp>
#include <components/esm3/loadcell.hpp>
#include <components/esm3/loadfact.hpp>
2022-10-19 17:02:00 +00:00
#include <components/esm3/loadinfo.hpp>
#include <components/esm3/loadpgrd.hpp>
#include <components/esm3/loadrace.hpp>
#include <components/esm3/loadregn.hpp>
2022-10-19 17:02:00 +00:00
#include <components/esm3/variant.hpp>
2015-04-12 00:52:01 +00:00
#include "info.hpp"
#include "infoselectwrapper.hpp"
2015-04-12 00:52:01 +00:00
#include "pathgrid.hpp"
namespace CSMWorld
{
PathgridPointListAdapter::PathgridPointListAdapter() {}
2015-04-18 22:58:52 +00:00
void PathgridPointListAdapter::addRow(Record<Pathgrid>& record, int position) const
2015-04-12 00:52:01 +00:00
{
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();
2015-04-12 00:52:01 +00:00
record.setModified(pathgrid);
}
2015-04-18 22:58:52 +00:00
void PathgridPointListAdapter::removeRow(Record<Pathgrid>& record, int rowToRemove) const
2015-04-12 00:52:01 +00:00
{
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?
2015-04-12 00:52:01 +00:00
points.erase(points.begin() + rowToRemove);
pathgrid.mData.mS2 = pathgrid.mPoints.size();
2015-04-12 00:52:01 +00:00
record.setModified(pathgrid);
}
2015-04-18 22:58:52 +00:00
void PathgridPointListAdapter::setTable(Record<Pathgrid>& record, const NestedTableWrapperBase& nestedTable) const
2015-04-12 00:52:01 +00:00
{
Pathgrid pathgrid = record.get();
pathgrid.mPoints = static_cast<const NestedTableWrapper<ESM::Pathgrid::PointList>&>(nestedTable).mNestedTable;
pathgrid.mData.mS2 = pathgrid.mPoints.size();
record.setModified(pathgrid);
2015-04-12 00:52:01 +00:00
}
2015-04-18 23:42:44 +00:00
NestedTableWrapperBase* PathgridPointListAdapter::table(const Record<Pathgrid>& record) const
2015-04-12 00:52:01 +00:00
{
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<ESM::Pathgrid::PointList>(record.get().mPoints);
2015-04-12 00:52:01 +00:00
}
2015-04-18 22:58:52 +00:00
QVariant PathgridPointListAdapter::getData(const Record<Pathgrid>& record, int subRowIndex, int subColIndex) const
2015-04-12 00:52:01 +00:00
{
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");
}
}
2015-04-18 22:58:52 +00:00
void PathgridPointListAdapter::setData(
2015-04-12 00:52:01 +00:00
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
2015-04-12 00:52:01 +00:00
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);
}
2015-04-18 22:58:52 +00:00
int PathgridPointListAdapter::getColumnsCount(const Record<Pathgrid>& record) const
2015-04-12 00:52:01 +00:00
{
return 4;
}
2015-04-18 22:58:52 +00:00
int PathgridPointListAdapter::getRowsCount(const Record<Pathgrid>& record) const
2015-04-12 00:52:01 +00:00
{
return static_cast<int>(record.get().mPoints.size());
}
PathgridEdgeListAdapter::PathgridEdgeListAdapter() {}
2015-04-18 22:58:52 +00:00
void PathgridEdgeListAdapter::addRow(Record<Pathgrid>& record, int position) const
2015-04-12 00:52:01 +00:00
{
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);
2015-04-12 00:52:01 +00:00
record.setModified(pathgrid);
}
2015-04-18 22:58:52 +00:00
void PathgridEdgeListAdapter::removeRow(Record<Pathgrid>& record, int rowToRemove) const
2015-04-12 00:52:01 +00:00
{
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);
}
2015-04-18 22:58:52 +00:00
void PathgridEdgeListAdapter::setTable(Record<Pathgrid>& record, const NestedTableWrapperBase& nestedTable) const
2015-04-12 00:52:01 +00:00
{
Pathgrid pathgrid = record.get();
pathgrid.mEdges = static_cast<const NestedTableWrapper<ESM::Pathgrid::EdgeList>&>(nestedTable).mNestedTable;
record.setModified(pathgrid);
2015-04-12 00:52:01 +00:00
}
2015-04-18 23:42:44 +00:00
NestedTableWrapperBase* PathgridEdgeListAdapter::table(const Record<Pathgrid>& record) const
2015-04-12 00:52:01 +00:00
{
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<ESM::Pathgrid::EdgeList>(record.get().mEdges);
2015-04-12 00:52:01 +00:00
}
2015-04-18 22:58:52 +00:00
QVariant PathgridEdgeListAdapter::getData(const Record<Pathgrid>& record, int subRowIndex, int subColIndex) const
2015-04-12 00:52:01 +00:00
{
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");
}
}
2015-04-18 22:58:52 +00:00
void PathgridEdgeListAdapter::setData(
2015-04-12 00:52:01 +00:00
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()))
2015-04-12 00:52:01 +00:00
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;
2015-04-12 00:52:01 +00:00
default:
throw std::runtime_error("Pathgrid edge subcolumn index out of range");
}
pathgrid.mEdges[subRowIndex] = edge;
2015-04-12 00:52:01 +00:00
record.setModified(pathgrid);
}
2015-04-18 22:58:52 +00:00
int PathgridEdgeListAdapter::getColumnsCount(const Record<Pathgrid>& record) const
2015-04-12 00:52:01 +00:00
{
return 3;
}
2015-04-18 22:58:52 +00:00
int PathgridEdgeListAdapter::getRowsCount(const Record<Pathgrid>& record) const
2015-04-12 00:52:01 +00:00
{
return static_cast<int>(record.get().mEdges.size());
}
FactionReactionsAdapter::FactionReactionsAdapter() {}
2015-04-18 22:58:52 +00:00
void FactionReactionsAdapter::addRow(Record<ESM::Faction>& record, int position) const
2015-04-12 00:52:01 +00:00
{
ESM::Faction faction = record.get();
std::map<ESM::RefId, int>& reactions = faction.mReactions;
2015-04-12 00:52:01 +00:00
// blank row
reactions.insert(std::make_pair(ESM::RefId::sEmpty, 0));
2015-04-12 00:52:01 +00:00
record.setModified(faction);
}
2015-04-18 22:58:52 +00:00
void FactionReactionsAdapter::removeRow(Record<ESM::Faction>& record, int rowToRemove) const
2015-04-12 00:52:01 +00:00
{
ESM::Faction faction = record.get();
std::map<ESM::RefId, int>& reactions = faction.mReactions;
2015-04-12 00:52:01 +00:00
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
auto iter = reactions.begin();
2015-04-12 00:52:01 +00:00
for (int i = 0; i < rowToRemove; ++i)
2016-01-03 17:20:34 +00:00
++iter;
2015-04-12 00:52:01 +00:00
reactions.erase(iter);
record.setModified(faction);
}
2015-04-18 22:58:52 +00:00
void FactionReactionsAdapter::setTable(
2015-04-12 00:52:01 +00:00
Record<ESM::Faction>& record, const NestedTableWrapperBase& nestedTable) const
{
ESM::Faction faction = record.get();
faction.mReactions
= static_cast<const NestedTableWrapper<std::map<ESM::RefId, int>>&>(nestedTable).mNestedTable;
record.setModified(faction);
2015-04-12 00:52:01 +00:00
}
2015-04-18 23:42:44 +00:00
NestedTableWrapperBase* FactionReactionsAdapter::table(const Record<ESM::Faction>& record) const
2015-04-12 00:52:01 +00:00
{
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<std::map<ESM::RefId, int>>(record.get().mReactions);
2015-04-12 00:52:01 +00:00
}
2015-04-18 22:58:52 +00:00
QVariant FactionReactionsAdapter::getData(
2015-04-12 00:52:01 +00:00
const Record<ESM::Faction>& record, int subRowIndex, int subColIndex) const
{
ESM::Faction faction = record.get();
std::map<ESM::RefId, int>& reactions = faction.mReactions;
2015-04-12 00:52:01 +00:00
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
auto iter = reactions.begin();
2015-04-12 00:52:01 +00:00
for (int i = 0; i < subRowIndex; ++i)
2016-01-03 17:20:34 +00:00
++iter;
2015-04-12 00:52:01 +00:00
switch (subColIndex)
{
case 0:
return QString((*iter).first.getRefIdString().c_str());
2015-04-12 00:52:01 +00:00
case 1:
return (*iter).second;
default:
throw std::runtime_error("Faction reactions subcolumn index out of range");
}
}
2015-04-18 22:58:52 +00:00
void FactionReactionsAdapter::setData(
2015-04-12 00:52:01 +00:00
Record<ESM::Faction>& record, const QVariant& value, int subRowIndex, int subColIndex) const
{
ESM::Faction faction = record.get();
std::map<ESM::RefId, int>& reactions = faction.mReactions;
2015-04-12 00:52:01 +00:00
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
auto iter = reactions.begin();
2015-04-12 00:52:01 +00:00
for (int i = 0; i < subRowIndex; ++i)
2016-01-03 17:20:34 +00:00
++iter;
2015-04-12 00:52:01 +00:00
ESM::RefId factionId = (*iter).first;
2015-04-12 00:52:01 +00:00
int reaction = (*iter).second;
switch (subColIndex)
{
case 0:
{
reactions.erase(iter);
reactions.insert(
std::make_pair(ESM::RefId::stringRefId(value.toString().toUtf8().constData()), reaction));
2015-04-12 00:52:01 +00:00
break;
}
case 1:
{
reactions[factionId] = value.toInt();
break;
}
default:
throw std::runtime_error("Faction reactions subcolumn index out of range");
}
record.setModified(faction);
}
2015-04-18 22:58:52 +00:00
int FactionReactionsAdapter::getColumnsCount(const Record<ESM::Faction>& record) const
2015-04-12 00:52:01 +00:00
{
return 2;
}
2015-04-18 22:58:52 +00:00
int FactionReactionsAdapter::getRowsCount(const Record<ESM::Faction>& record) const
2015-04-12 00:52:01 +00:00
{
return static_cast<int>(record.get().mReactions.size());
}
RegionSoundListAdapter::RegionSoundListAdapter() {}
2015-04-18 22:58:52 +00:00
void RegionSoundListAdapter::addRow(Record<ESM::Region>& record, int position) const
2015-04-12 00:52:01 +00:00
{
ESM::Region region = record.get();
std::vector<ESM::Region::SoundRef>& soundList = region.mSoundList;
// blank row
ESM::Region::SoundRef soundRef;
soundRef.mSound = ESM::RefId::sEmpty;
2015-04-12 00:52:01 +00:00
soundRef.mChance = 0;
soundList.insert(soundList.begin() + position, soundRef);
record.setModified(region);
}
2015-04-18 22:58:52 +00:00
void RegionSoundListAdapter::removeRow(Record<ESM::Region>& record, int rowToRemove) const
2015-04-12 00:52:01 +00:00
{
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);
}
2015-04-18 22:58:52 +00:00
void RegionSoundListAdapter::setTable(Record<ESM::Region>& record, const NestedTableWrapperBase& nestedTable) const
2015-04-12 00:52:01 +00:00
{
ESM::Region region = record.get();
region.mSoundList
2015-04-12 00:52:01 +00:00
= static_cast<const NestedTableWrapper<std::vector<ESM::Region::SoundRef>>&>(nestedTable).mNestedTable;
record.setModified(region);
2015-04-12 00:52:01 +00:00
}
2015-04-18 23:42:44 +00:00
NestedTableWrapperBase* RegionSoundListAdapter::table(const Record<ESM::Region>& record) const
2015-04-12 00:52:01 +00:00
{
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<std::vector<ESM::Region::SoundRef>>(record.get().mSoundList);
}
2015-04-18 22:58:52 +00:00
QVariant RegionSoundListAdapter::getData(const Record<ESM::Region>& record, int subRowIndex, int subColIndex) const
2015-04-12 00:52:01 +00:00
{
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.getRefIdString().c_str());
2015-04-12 00:52:01 +00:00
case 1:
return soundRef.mChance;
default:
throw std::runtime_error("Region sounds subcolumn index out of range");
}
}
2015-04-18 22:58:52 +00:00
void RegionSoundListAdapter::setData(
2015-04-12 00:52:01 +00:00
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 = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
2015-04-12 00:52:01 +00:00
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);
}
2015-04-18 22:58:52 +00:00
int RegionSoundListAdapter::getColumnsCount(const Record<ESM::Region>& record) const
2015-04-12 00:52:01 +00:00
{
return 2;
}
2015-04-18 22:58:52 +00:00
int RegionSoundListAdapter::getRowsCount(const Record<ESM::Region>& record) const
2015-04-12 00:52:01 +00:00
{
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)
{
2015-09-11 23:33:11 +00:00
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;
// While the ambient information is not necessarily valid if the subrecord wasn't loaded,
// the user should still be allowed to edit it
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());
cell.setHasAmbient(true);
}
else
return; // return without saving
break;
}
case 2:
{
if (isInterior && !behaveLikeExterior)
{
cell.mAmbi.mSunlight = static_cast<int32_t>(value.toInt());
cell.setHasAmbient(true);
}
else
return; // return without saving
break;
}
case 3:
{
if (isInterior && !behaveLikeExterior)
{
cell.mAmbi.mFog = static_cast<int32_t>(value.toInt());
cell.setHasAmbient(true);
}
else
return; // return without saving
break;
}
case 4:
{
if (isInterior && !behaveLikeExterior)
{
cell.mAmbi.mFogDensity = value.toFloat();
cell.setHasAmbient(true);
}
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.mSnow;
case 9:
return region.mData.mBlizzard;
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.mSnow = chance;
break;
case 9:
region.mData.mBlizzard = chance;
2022-09-22 18:26:05 +00:00
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;
}
FactionRanksAdapter::FactionRanksAdapter() {}
void FactionRanksAdapter::addRow(Record<ESM::Faction>& record, int position) const
{
throw std::logic_error("cannot add a row to a fixed table");
}
void FactionRanksAdapter::removeRow(Record<ESM::Faction>& record, int rowToRemove) const
{
throw std::logic_error("cannot remove a row from a fixed table");
}
void FactionRanksAdapter::setTable(Record<ESM::Faction>& record, const NestedTableWrapperBase& nestedTable) const
{
throw std::logic_error("table operation not supported");
}
NestedTableWrapperBase* FactionRanksAdapter::table(const Record<ESM::Faction>& record) const
{
throw std::logic_error("table operation not supported");
}
QVariant FactionRanksAdapter::getData(const Record<ESM::Faction>& record, int subRowIndex, int subColIndex) const
{
ESM::Faction faction = record.get();
if (subRowIndex < 0
|| subRowIndex >= static_cast<int>(sizeof(faction.mData.mRankData) / sizeof(faction.mData.mRankData[0])))
throw std::runtime_error("index out of range");
auto& rankData = faction.mData.mRankData[subRowIndex];
switch (subColIndex)
{
case 0:
return QString(faction.mRanks[subRowIndex].c_str());
case 1:
return rankData.mAttribute1;
case 2:
return rankData.mAttribute2;
case 3:
return rankData.mPrimarySkill;
case 4:
return rankData.mFavouredSkill;
case 5:
return rankData.mFactReaction;
default:
throw std::runtime_error("Rank subcolumn index out of range");
}
}
void FactionRanksAdapter::setData(
Record<ESM::Faction>& record, const QVariant& value, int subRowIndex, int subColIndex) const
{
ESM::Faction faction = record.get();
if (subRowIndex < 0
|| subRowIndex >= static_cast<int>(sizeof(faction.mData.mRankData) / sizeof(faction.mData.mRankData[0])))
throw std::runtime_error("index out of range");
auto& rankData = faction.mData.mRankData[subRowIndex];
switch (subColIndex)
{
case 0:
faction.mRanks[subRowIndex] = value.toString().toUtf8().constData();
break;
case 1:
rankData.mAttribute1 = value.toInt();
break;
case 2:
rankData.mAttribute2 = value.toInt();
break;
case 3:
rankData.mPrimarySkill = value.toInt();
break;
case 4:
rankData.mFavouredSkill = value.toInt();
break;
case 5:
rankData.mFactReaction = value.toInt();
2022-09-22 18:26:05 +00:00
break;
default:
throw std::runtime_error("Rank index out of range");
}
record.setModified(faction);
}
int FactionRanksAdapter::getColumnsCount(const Record<ESM::Faction>& record) const
{
return 6;
}
int FactionRanksAdapter::getRowsCount(const Record<ESM::Faction>& record) const
{
return 10;
}
2015-04-12 00:52:01 +00:00
}