Merge remote-tracking branch 'cc9cii/npc-additional-data'

c++11
Marc Zinnschlag 10 years ago
commit 07ce7b95cf

@ -84,6 +84,7 @@ bool CSMWorld::ColumnBase::isId (Display display)
Display_InfoCondFunc,
Display_InfoCondVar,
Display_InfoCondComp,
Display_RaceSkill,
Display_None
};

@ -119,6 +119,7 @@ namespace CSMWorld
Display_InfoCondFunc,
Display_InfoCondVar,
Display_InfoCondComp,
Display_RaceSkill,
//top level columns that nest other columns
Display_NestedHeader

@ -176,7 +176,7 @@ namespace CSMWorld
{ ColumnId_ContainerContent, "Content" },
{ ColumnId_ItemCount, "Count" },
{ ColumnId_InventoryItemId, "ID"},
{ ColumnId_InventoryItemId, "Item ID"},
{ ColumnId_CombatState, "Combat" },
{ ColumnId_MagicState, "Magic" },
@ -188,10 +188,10 @@ namespace CSMWorld
{ ColumnId_ActorInventory, "Inventory" },
{ ColumnId_SpellList, "Spells" },
{ ColumnId_SpellId, "ID"},
{ ColumnId_SpellId, "Spell ID"},
{ ColumnId_NpcDestinations, "Destinations" },
{ ColumnId_DestinationCell, "Cell"},
{ ColumnId_DestinationCell, "Dest Cell"},
{ ColumnId_PosX, "Dest X"},
{ ColumnId_PosY, "Dest Y"},
{ ColumnId_PosZ, "Dest Z"},
@ -224,17 +224,17 @@ namespace CSMWorld
{ ColumnId_BoltSound, "Bolt Sound" },
{ ColumnId_PathgridPoints, "Points" },
{ ColumnId_PathgridIndex, "Index" },
{ ColumnId_PathgridIndex, "pIndex" },
{ ColumnId_PathgridPosX, "X" },
{ ColumnId_PathgridPosY, "Y" },
{ ColumnId_PathgridPosZ, "Z" },
{ ColumnId_PathgridEdges, "Edges" },
{ ColumnId_PathgridEdgeIndex, "Index" },
{ ColumnId_PathgridEdgeIndex, "eIndex" },
{ ColumnId_PathgridEdge0, "Point 0" },
{ ColumnId_PathgridEdge1, "Point 1" },
{ ColumnId_RegionSounds, "Sounds" },
{ ColumnId_SoundName, "Name" },
{ ColumnId_SoundName, "Sound Name" },
{ ColumnId_SoundChance, "Chance" },
{ ColumnId_FactionReactions, "Reactions" },
@ -250,7 +250,7 @@ namespace CSMWorld
{ ColumnId_AiPackageList, "Ai Packages" },
{ ColumnId_AiPackageType, "Package" },
{ ColumnId_AiWanderDist, "Wander Dist" },
{ ColumnId_AiDuration, "Duration" },
{ ColumnId_AiDuration, "Ai Duration" },
{ ColumnId_AiWanderToD, "Wander ToD" },
{ ColumnId_AiWanderIdle, "Wander Idle" },
{ ColumnId_AiWanderRepeat, "Wander Repeat" },
@ -260,11 +260,11 @@ namespace CSMWorld
{ ColumnId_PartRefList, "Part Reference" },
{ ColumnId_PartRefType, "Type" },
{ ColumnId_PartRefMale, "Male" },
{ ColumnId_PartRefFemale, "Female" },
{ ColumnId_PartRefMale, "Male Part" },
{ ColumnId_PartRefFemale, "Female Part" },
{ ColumnId_LevelledList,"Levelled List" },
{ ColumnId_LevelledItemId,"Item ID" },
{ ColumnId_LevelledItemId,"Levelled Item" },
{ ColumnId_LevelledItemLevel,"Level" },
{ ColumnId_LevelledItemType, "Calculate all levels <= player" },
{ ColumnId_LevelledItemTypeEach, "Select a new item each instance" },
@ -278,9 +278,39 @@ namespace CSMWorld
{ ColumnId_InfoCondFunc, "Function" },
{ ColumnId_InfoCondVar, "Func/Variable" },
{ ColumnId_InfoCondComp, "Comp" },
{ ColumnId_InfoCondValue, "Value" },
{ ColumnId_InfoCondValue, "Values" },
{ ColumnId_OriginalCell, "Original Cell" },
{ ColumnId_NpcAttributes, "Attributes" },
{ ColumnId_NpcSkills, "Skills" },
{ ColumnId_UChar, "Value [0..255]" },
{ ColumnId_NpcMisc, "Misc" },
{ ColumnId_NpcLevel, "Level" },
{ ColumnId_NpcFactionID, "Faction ID" },
{ ColumnId_NpcHealth, "Health" },
{ ColumnId_NpcMana, "Mana" },
{ ColumnId_NpcFatigue, "Fatigue" },
{ ColumnId_NpcDisposition, "Disposition" },
{ ColumnId_NpcReputation, "Reputation" },
{ ColumnId_NpcRank, "Rank" },
{ ColumnId_NpcGold, "Gold" },
{ ColumnId_NpcPersistence, "Persistent" },
{ ColumnId_RaceAttributes, "Attributes" },
{ ColumnId_RaceMaleValue, "Male" },
{ ColumnId_RaceFemaleValue, "Female" },
{ ColumnId_RaceSkillBonus, "Skill Bonus" },
{ ColumnId_RaceSkill, "Skills" },
{ ColumnId_RaceBonus, "Bonus" },
{ ColumnId_Interior, "Interior" },
{ ColumnId_Ambient, "Ambient" },
{ ColumnId_Sunlight, "Sunlight" },
{ ColumnId_Fog, "Fog" },
{ ColumnId_FogDensity, "Fog Density" },
{ ColumnId_WaterLevel, "Water Level" },
{ ColumnId_MapColor, "Map Color" },
{ ColumnId_UseValue1, "Use value 1" },
{ ColumnId_UseValue2, "Use value 2" },
{ ColumnId_UseValue3, "Use value 3" },
@ -551,6 +581,7 @@ namespace
// FIXME: don't have dynamic value enum delegate, use Display_String for now
//case CSMWorld::Columns::ColumnId_InfoCond: return sInfoCond;
case CSMWorld::Columns::ColumnId_InfoCondComp: return sInfoCondComp;
case CSMWorld::Columns::ColumnId_RaceSkill: return sSkills;
default: return 0;
}

@ -272,6 +272,36 @@ namespace CSMWorld
ColumnId_OriginalCell = 247,
ColumnId_NpcAttributes = 248,
ColumnId_NpcSkills = 249,
ColumnId_UChar = 250,
ColumnId_NpcMisc = 251,
ColumnId_NpcLevel = 252,
ColumnId_NpcFactionID = 253,
ColumnId_NpcHealth = 254,
ColumnId_NpcMana = 255,
ColumnId_NpcFatigue = 256,
ColumnId_NpcDisposition = 257,
ColumnId_NpcReputation = 258,
ColumnId_NpcRank = 259,
ColumnId_NpcGold = 260,
ColumnId_NpcPersistence = 261,
ColumnId_RaceAttributes = 262,
ColumnId_RaceMaleValue = 263,
ColumnId_RaceFemaleValue = 264,
ColumnId_RaceSkillBonus = 265,
ColumnId_RaceSkill = 266,
ColumnId_RaceBonus = 267,
ColumnId_Interior = 268,
ColumnId_Ambient = 269,
ColumnId_Sunlight = 270,
ColumnId_Fog = 271,
ColumnId_FogDensity = 272,
ColumnId_WaterLevel = 273,
ColumnId_MapColor = 274,
// Allocated to a separate value range, so we don't get a collision should we ever need
// to extend the number of use values.
ColumnId_UseValue1 = 0x10000,

@ -136,6 +136,24 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new SpellListAdapter<ESM::Race> ()));
mRaces.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_String));
// Race attributes
mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceAttributes));
index = mRaces.getColumns()-1;
mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceAttributeAdapter()));
mRaces.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_RaceAttributes, ColumnBase::Display_String, false));
mRaces.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_RaceMaleValue, ColumnBase::Display_Integer));
mRaces.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_RaceFemaleValue, ColumnBase::Display_Integer));
// Race skill bonus
mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceSkillBonus));
index = mRaces.getColumns()-1;
mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceSkillsBonusAdapter()));
mRaces.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_RaceSkill, ColumnBase::Display_RaceSkill));
mRaces.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_RaceBonus, ColumnBase::Display_Integer));
mSounds.addColumn (new StringIdColumn<ESM::Sound>);
mSounds.addColumn (new RecordStateColumn<ESM::Sound>);
@ -273,6 +291,25 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mCells.addColumn (new FlagColumn<Cell> (Columns::ColumnId_InteriorSky, ESM::Cell::QuasiEx));
mCells.addColumn (new RegionColumn<Cell>);
mCells.addColumn (new RefNumCounterColumn<Cell>);
// Misc Cell data
mCells.addColumn (new NestedParentColumn<Cell> (Columns::ColumnId_Cell,
ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List));
index = mCells.getColumns()-1;
mCells.addAdapter (std::make_pair(&mCells.getColumn(index), new CellListAdapter ()));
mCells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_Interior, ColumnBase::Display_Boolean));
mCells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_Ambient, ColumnBase::Display_Integer));
mCells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_Sunlight, ColumnBase::Display_Integer));
mCells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_Fog, ColumnBase::Display_Integer));
mCells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_FogDensity, ColumnBase::Display_Float));
mCells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_WaterLevel, ColumnBase::Display_Float));
mCells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_MapColor, ColumnBase::Display_Integer));
mEnchantments.addColumn (new StringIdColumn<ESM::Enchantment>);
mEnchantments.addColumn (new RecordStateColumn<ESM::Enchantment>);
@ -447,7 +484,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
addModel (new IdTree (&mTopicInfos, &mTopicInfos, IdTable::Feature_ReorderWithinTopic),
UniversalId::Type_TopicInfo);
addModel (new IdTable (&mJournalInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_JournalInfo);
addModel (new IdTable (&mCells, IdTable::Feature_ViewId), UniversalId::Type_Cell);
addModel (new IdTree (&mCells, &mCells, IdTable::Feature_ViewId), UniversalId::Type_Cell);
addModel (new IdTree (&mEnchantments, &mEnchantments), UniversalId::Type_Enchantment);
addModel (new IdTable (&mBodyParts), UniversalId::Type_BodyPart);
addModel (new IdTable (&mSoundGens), UniversalId::Type_SoundGen);

@ -88,7 +88,7 @@ namespace CSMWorld
IdCollection<ESM::StartScript> mStartScripts;
NestedInfoCollection mTopicInfos;
InfoCollection mJournalInfos;
IdCollection<Cell> mCells;
NestedIdCollection<Cell> mCells;
IdCollection<LandTexture> mLandTextures;
IdCollection<Land> mLand;
RefIdCollection mReferenceables;

@ -481,7 +481,7 @@ namespace CSMWorld
void InfoListAdapter::removeRow(Record<Info>& record, int rowToRemove) const
{
throw std::logic_error ("cannot add a row to a fixed table");
throw std::logic_error ("cannot remove a row to a fixed table");
}
void InfoListAdapter::setTable(Record<Info>& record,
@ -880,4 +880,315 @@ namespace CSMWorld
{
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<typename 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 QString(ESM::Attribute::sAttributeNames[subRowIndex].c_str());
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<typename 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 && !behaveLikeExterior && 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 && !behaveLikeExterior && 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
}
}

@ -8,9 +8,11 @@
#include <components/esm/loadmgef.hpp> // for converting magic effect id to string & back
#include <components/esm/loadskil.hpp> // for converting skill names
#include <components/esm/attr.hpp> // for converting attributes
#include <components/esm/loadrace.hpp>
#include "nestedcolumnadapter.hpp"
#include "nestedtablewrapper.hpp"
#include "cell.hpp"
namespace ESM
{
@ -437,6 +439,81 @@ namespace CSMWorld
virtual int getRowsCount(const Record<Info>& record) const;
};
class RaceAttributeAdapter : public NestedColumnAdapter<ESM::Race>
{
public:
RaceAttributeAdapter ();
virtual void addRow(Record<ESM::Race>& record, int position) const;
virtual void removeRow(Record<ESM::Race>& record, int rowToRemove) const;
virtual void setTable(Record<ESM::Race>& record,
const NestedTableWrapperBase& nestedTable) const;
virtual NestedTableWrapperBase* table(const Record<ESM::Race>& record) const;
virtual QVariant getData(const Record<ESM::Race>& record,
int subRowIndex, int subColIndex) const;
virtual void setData(Record<ESM::Race>& record,
const QVariant& value, int subRowIndex, int subColIndex) const;
virtual int getColumnsCount(const Record<ESM::Race>& record) const;
virtual int getRowsCount(const Record<ESM::Race>& record) const;
};
class RaceSkillsBonusAdapter : public NestedColumnAdapter<ESM::Race>
{
public:
RaceSkillsBonusAdapter ();
virtual void addRow(Record<ESM::Race>& record, int position) const;
virtual void removeRow(Record<ESM::Race>& record, int rowToRemove) const;
virtual void setTable(Record<ESM::Race>& record,
const NestedTableWrapperBase& nestedTable) const;
virtual NestedTableWrapperBase* table(const Record<ESM::Race>& record) const;
virtual QVariant getData(const Record<ESM::Race>& record,
int subRowIndex, int subColIndex) const;
virtual void setData(Record<ESM::Race>& record,
const QVariant& value, int subRowIndex, int subColIndex) const;
virtual int getColumnsCount(const Record<ESM::Race>& record) const;
virtual int getRowsCount(const Record<ESM::Race>& record) const;
};
class CellListAdapter : public NestedColumnAdapter<CSMWorld::Cell>
{
public:
CellListAdapter ();
virtual void addRow(Record<CSMWorld::Cell>& record, int position) const;
virtual void removeRow(Record<CSMWorld::Cell>& record, int rowToRemove) const;
virtual void setTable(Record<CSMWorld::Cell>& record,
const NestedTableWrapperBase& nestedTable) const;
virtual NestedTableWrapperBase* table(const Record<CSMWorld::Cell>& record) const;
virtual QVariant getData(const Record<CSMWorld::Cell>& record,
int subRowIndex, int subColIndex) const;
virtual void setData(Record<CSMWorld::Cell>& record,
const QVariant& value, int subRowIndex, int subColIndex) const;
virtual int getColumnsCount(const Record<CSMWorld::Cell>& record) const;
virtual int getRowsCount(const Record<CSMWorld::Cell>& record) const;
};
}
#endif // CSM_WOLRD_NESTEDCOLADAPTERIMP_H

@ -468,7 +468,10 @@ CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns)
mClass(NULL),
mFaction(NULL),
mHair(NULL),
mHead(NULL)
mHead(NULL),
mAttributes(NULL),
mSkills(NULL),
mMisc(NULL)
{}
CSMWorld::NpcRefIdAdapter::NpcRefIdAdapter (const NpcColumns& columns)
@ -496,6 +499,17 @@ QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const Re
if (column==mColumns.mHead)
return QString::fromUtf8 (record.get().mHead.c_str());
if (column==mColumns.mAttributes || column==mColumns.mSkills)
{
if ((record.get().mFlags & ESM::NPC::Autocalc) != 0)
return QVariant(QVariant::UserType);
else
return true;
}
if (column==mColumns.mMisc)
return true;
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
@ -538,6 +552,338 @@ void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& d
}
}
CSMWorld::NpcAttributesRefIdAdapter::NpcAttributesRefIdAdapter ()
{}
void CSMWorld::NpcAttributesRefIdAdapter::addNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int position) const
{
// Do nothing, this table cannot be changed by the user
}
void CSMWorld::NpcAttributesRefIdAdapter::removeNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int rowToRemove) const
{
// Do nothing, this table cannot be changed by the user
}
void CSMWorld::NpcAttributesRefIdAdapter::setNestedTable (const RefIdColumn* column,
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
{
Record<ESM::NPC>& record =
static_cast<Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
ESM::NPC npc = record.get();
// store the whole struct
npc.mNpdt52 =
static_cast<const NestedTableWrapper<std::vector<typename ESM::NPC::NPDTstruct52> > &>(nestedTable).mNestedTable.at(0);
record.setModified (npc);
}
CSMWorld::NestedTableWrapperBase* CSMWorld::NpcAttributesRefIdAdapter::nestedTable (const RefIdColumn* column,
const RefIdData& data, int index) const
{
const Record<ESM::NPC>& record =
static_cast<const Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
// return the whole struct
std::vector<typename ESM::NPC::NPDTstruct52> wrap;
wrap.push_back(record.get().mNpdt52);
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<std::vector<typename ESM::NPC::NPDTstruct52> >(wrap);
}
QVariant CSMWorld::NpcAttributesRefIdAdapter::getNestedData (const RefIdColumn *column,
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
{
const Record<ESM::NPC>& record =
static_cast<const Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
const ESM::NPC::NPDTstruct52& npcStruct = record.get().mNpdt52;
if (subColIndex == 0)
switch (subRowIndex)
{
case 0: return QString("Strength");
case 1: return QString("Intelligence");
case 2: return QString("Willpower");
case 3: return QString("Agility");
case 4: return QString("Speed");
case 5: return QString("Endurance");
case 6: return QString("Personality");
case 7: return QString("Luck");
default: return QVariant(); // throw an exception here?
}
else if (subColIndex == 1)
switch (subRowIndex)
{
case 0: return static_cast<int>(npcStruct.mStrength);
case 1: return static_cast<int>(npcStruct.mIntelligence);
case 2: return static_cast<int>(npcStruct.mWillpower);
case 3: return static_cast<int>(npcStruct.mAgility);
case 4: return static_cast<int>(npcStruct.mSpeed);
case 5: return static_cast<int>(npcStruct.mEndurance);
case 6: return static_cast<int>(npcStruct.mPersonality);
case 7: return static_cast<int>(npcStruct.mLuck);
default: return QVariant(); // throw an exception here?
}
else
return QVariant(); // throw an exception here?
}
void CSMWorld::NpcAttributesRefIdAdapter::setNestedData (const RefIdColumn *column,
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
{
Record<ESM::NPC>& record =
static_cast<Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Npc)));
ESM::NPC npc = record.get();
ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt52;
if (subColIndex == 1)
switch(subRowIndex)
{
case 0: npcStruct.mStrength = static_cast<unsigned char>(value.toInt()); break;
case 1: npcStruct.mIntelligence = static_cast<unsigned char>(value.toInt()); break;
case 2: npcStruct.mWillpower = static_cast<unsigned char>(value.toInt()); break;
case 3: npcStruct.mAgility = static_cast<unsigned char>(value.toInt()); break;
case 4: npcStruct.mSpeed = static_cast<unsigned char>(value.toInt()); break;
case 5: npcStruct.mEndurance = static_cast<unsigned char>(value.toInt()); break;
case 6: npcStruct.mPersonality = static_cast<unsigned char>(value.toInt()); break;
case 7: npcStruct.mLuck = static_cast<unsigned char>(value.toInt()); break;
default: return; // throw an exception here?
}
else
return; // throw an exception here?
record.setModified (npc);
}
int CSMWorld::NpcAttributesRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
{
return 2;
}
int CSMWorld::NpcAttributesRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
{
// There are 8 attributes
return 8;
}
CSMWorld::NpcSkillsRefIdAdapter::NpcSkillsRefIdAdapter ()
{}
void CSMWorld::NpcSkillsRefIdAdapter::addNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int position) const
{
// Do nothing, this table cannot be changed by the user
}
void CSMWorld::NpcSkillsRefIdAdapter::removeNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int rowToRemove) const
{
// Do nothing, this table cannot be changed by the user
}
void CSMWorld::NpcSkillsRefIdAdapter::setNestedTable (const RefIdColumn* column,
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
{
Record<ESM::NPC>& record =
static_cast<Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
ESM::NPC npc = record.get();
// store the whole struct
npc.mNpdt52 =
static_cast<const NestedTableWrapper<std::vector<typename ESM::NPC::NPDTstruct52> > &>(nestedTable).mNestedTable.at(0);
record.setModified (npc);
}
CSMWorld::NestedTableWrapperBase* CSMWorld::NpcSkillsRefIdAdapter::nestedTable (const RefIdColumn* column,
const RefIdData& data, int index) const
{
const Record<ESM::NPC>& record =
static_cast<const Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
// return the whole struct
std::vector<typename ESM::NPC::NPDTstruct52> wrap;
wrap.push_back(record.get().mNpdt52);
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<std::vector<typename ESM::NPC::NPDTstruct52> >(wrap);
}
QVariant CSMWorld::NpcSkillsRefIdAdapter::getNestedData (const RefIdColumn *column,
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
{
const Record<ESM::NPC>& record =
static_cast<const Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
const ESM::NPC::NPDTstruct52& npcStruct = record.get().mNpdt52;
if (subRowIndex < 0 || subRowIndex >= ESM::Skill::Length)
throw std::runtime_error ("index out of range");
if (subColIndex == 0)
return QString(ESM::Skill::sSkillNames[subRowIndex].c_str());
else if (subColIndex == 1)
return static_cast<int>(npcStruct.mSkills[subRowIndex]);
else
return QVariant(); // throw an exception here?
}
void CSMWorld::NpcSkillsRefIdAdapter::setNestedData (const RefIdColumn *column,
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
{
Record<ESM::NPC>& record =
static_cast<Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Npc)));
ESM::NPC npc = record.get();
ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt52;
if (subRowIndex < 0 || subRowIndex >= ESM::Skill::Length)
throw std::runtime_error ("index out of range");
if (subColIndex == 1)
npcStruct.mSkills[subRowIndex] = static_cast<unsigned char>(value.toInt());
else
return; // throw an exception here?
record.setModified (npc);
}
int CSMWorld::NpcSkillsRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
{
return 2;
}
int CSMWorld::NpcSkillsRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
{
// There are 27 skills
return ESM::Skill::Length;
}
CSMWorld::NpcMiscRefIdAdapter::NpcMiscRefIdAdapter ()
{}
CSMWorld::NpcMiscRefIdAdapter::~NpcMiscRefIdAdapter()
{}
void CSMWorld::NpcMiscRefIdAdapter::addNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int position) const
{
throw std::logic_error ("cannot add a row to a fixed table");
}
void CSMWorld::NpcMiscRefIdAdapter::removeNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int rowToRemove) const
{
throw std::logic_error ("cannot remove a row to a fixed table");
}
void CSMWorld::NpcMiscRefIdAdapter::setNestedTable (const RefIdColumn* column,
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
{
throw std::logic_error ("table operation not supported");
}
CSMWorld::NestedTableWrapperBase* CSMWorld::NpcMiscRefIdAdapter::nestedTable (const RefIdColumn* column,
const RefIdData& data, int index) const
{
throw std::logic_error ("table operation not supported");
}
QVariant CSMWorld::NpcMiscRefIdAdapter::getNestedData (const RefIdColumn *column,
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
{
const Record<ESM::NPC>& record =
static_cast<const Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
bool autoCalc = (record.get().mFlags & ESM::NPC::Autocalc) != 0;
if (autoCalc)
switch (subColIndex)
{
case 0: return static_cast<int>(record.get().mNpdt12.mLevel);
case 1: return QVariant(QVariant::UserType);
case 2: return QVariant(QVariant::UserType);
case 3: return QVariant(QVariant::UserType);
case 4: return QVariant(QVariant::UserType);
case 5: return static_cast<int>(record.get().mNpdt12.mDisposition);
case 6: return static_cast<int>(record.get().mNpdt12.mReputation);
case 7: return static_cast<int>(record.get().mNpdt12.mRank);
case 8: return record.get().mNpdt12.mGold;
case 9: return record.get().mPersistent == true;
default: return QVariant(); // throw an exception here?
}
else
switch (subColIndex)
{
case 0: return static_cast<int>(record.get().mNpdt52.mLevel);
case 1: return static_cast<int>(record.get().mNpdt52.mFactionID);
case 2: return static_cast<int>(record.get().mNpdt52.mHealth);
case 3: return static_cast<int>(record.get().mNpdt52.mMana);
case 4: return static_cast<int>(record.get().mNpdt52.mFatigue);
case 5: return static_cast<int>(record.get().mNpdt52.mDisposition);
case 6: return static_cast<int>(record.get().mNpdt52.mReputation);
case 7: return static_cast<int>(record.get().mNpdt52.mRank);
case 8: return record.get().mNpdt52.mGold;
case 9: return record.get().mPersistent == true;
default: return QVariant(); // throw an exception here?
}
}
void CSMWorld::NpcMiscRefIdAdapter::setNestedData (const RefIdColumn *column,
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
{
Record<ESM::NPC>& record =
static_cast<Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Npc)));
ESM::NPC npc = record.get();
bool autoCalc = (record.get().mFlags & ESM::NPC::Autocalc) != 0;
if (autoCalc)
switch(subColIndex)
{
case 0: npc.mNpdt12.mLevel = static_cast<short>(value.toInt()); break;
case 1: return;
case 2: return;
case 3: return;
case 4: return;
case 5: npc.mNpdt12.mDisposition = static_cast<signed char>(value.toInt()); break;
case 6: npc.mNpdt12.mReputation = static_cast<signed char>(value.toInt()); break;
case 7: npc.mNpdt12.mRank = static_cast<signed char>(value.toInt()); break;
case 8: npc.mNpdt12.mGold = value.toInt(); break;
case 9: npc.mPersistent = value.toBool(); break;
default: return; // throw an exception here?
}
else
switch(subColIndex)
{
case 0: npc.mNpdt52.mLevel = static_cast<short>(value.toInt()); break;
case 1: npc.mNpdt52.mFactionID = static_cast<char>(value.toInt()); break;
case 2: npc.mNpdt52.mHealth = static_cast<unsigned short>(value.toInt()); break;
case 3: npc.mNpdt52.mMana = static_cast<unsigned short>(value.toInt()); break;
case 4: npc.mNpdt52.mFatigue = static_cast<unsigned short>(value.toInt()); break;
case 5: npc.mNpdt52.mDisposition = static_cast<signed char>(value.toInt()); break;
case 6: npc.mNpdt52.mReputation = static_cast<signed char>(value.toInt()); break;
case 7: npc.mNpdt52.mRank = static_cast<signed char>(value.toInt()); break;
case 8: npc.mNpdt52.mGold = value.toInt(); break;
case 9: npc.mPersistent = value.toBool(); break;
default: return; // throw an exception here?
}
record.setModified (npc);
}
int CSMWorld::NpcMiscRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
{
return 10; // Level, FactionID, Health, Mana, Fatigue, Disposition, Reputation, Rank, Gold, Persist
}
int CSMWorld::NpcMiscRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
{
return 1; // fixed at size 1
}
CSMWorld::WeaponColumns::WeaponColumns (const EnchantableColumns& columns)
: EnchantableColumns (columns) {}

@ -792,6 +792,9 @@ namespace CSMWorld
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
NpcColumns (const ActorColumns& actorColumns);
};
@ -842,8 +845,100 @@ namespace CSMWorld
///< If the data type does not match an exception is thrown.
};
class NestedRefIdAdapterBase;
class NpcAttributesRefIdAdapter : public NestedRefIdAdapterBase
{
public:
NpcAttributesRefIdAdapter ();
virtual void addNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int position) const;
virtual void removeNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int rowToRemove) const;
virtual void setNestedTable (const RefIdColumn* column,
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const;
virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column,
const RefIdData& data, int index) const;
virtual QVariant getNestedData (const RefIdColumn *column,
const RefIdData& data, int index, int subRowIndex, int subColIndex) const;
virtual void setNestedData (const RefIdColumn *column,
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const;
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const;
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const;
};
class NpcSkillsRefIdAdapter : public NestedRefIdAdapterBase
{
public:
NpcSkillsRefIdAdapter ();
virtual void addNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int position) const;
virtual void removeNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int rowToRemove) const;
virtual void setNestedTable (const RefIdColumn* column,
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const;
virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column,
const RefIdData& data, int index) const;
virtual QVariant getNestedData (const RefIdColumn *column,
const RefIdData& data, int index, int subRowIndex, int subColIndex) const;
virtual void setNestedData (const RefIdColumn *column,
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const;
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const;
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const;
};
class NpcMiscRefIdAdapter : public NestedRefIdAdapterBase
{
NpcMiscRefIdAdapter (const NpcMiscRefIdAdapter&);
NpcMiscRefIdAdapter& operator= (const NpcMiscRefIdAdapter&);
public:
NpcMiscRefIdAdapter ();
virtual ~NpcMiscRefIdAdapter();
virtual void addNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int position) const;
virtual void removeNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int rowToRemove) const;
virtual void setNestedTable (const RefIdColumn* column,
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const;
virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column,
const RefIdData& data, int index) const;
virtual QVariant getNestedData (const RefIdColumn *column,
const RefIdData& data, int index, int subRowIndex, int subColIndex) const;
virtual void setNestedData (const RefIdColumn *column,
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const;
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const;
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const;
};
template<typename ESXRecordT>
class EffectsListAdapter;
@ -1881,7 +1976,7 @@ namespace CSMWorld
{
switch (subColIndex)
{
case 0: return QVariant(); // don't allow checkbox editor to be created
case 0: return QVariant(QVariant::UserType); // disable the checkbox editor
case 1: return record.get().mFlags & ESM::CreatureLevList::AllLevels;
case 2: return static_cast<int> (record.get().mChanceNone);
default:

@ -427,6 +427,62 @@ CSMWorld::RefIdCollection::RefIdCollection()
npcColumns.mFlags.insert (std::make_pair (metalBlood, ESM::NPC::Metal));
// Need a way to add a table of stats and values (rather than adding a long list of
// entries in the dialogue subview) E.g. attributes+stats(health, mana, fatigue), skills
// These needs to be driven from the autocalculated setting.
// Nested table
mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcAttributes,
ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue));
npcColumns.mAttributes = &mColumns.back();
std::map<UniversalId::Type, NestedRefIdAdapterBase*> attrMap;
attrMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcAttributesRefIdAdapter()));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), attrMap));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_NpcAttributes, CSMWorld::ColumnBase::Display_String, false, false));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_Integer));
// Nested table
mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcSkills,
ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue));
npcColumns.mSkills = &mColumns.back();
std::map<UniversalId::Type, NestedRefIdAdapterBase*> skillsMap;
skillsMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcSkillsRefIdAdapter()));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), skillsMap));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_NpcSkills, CSMWorld::ColumnBase::Display_String, false, false));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_Integer));
// Nested list
mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcMisc,
ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List));
npcColumns.mMisc = &mColumns.back();
std::map<UniversalId::Type, NestedRefIdAdapterBase*> miscMap;
miscMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcMiscRefIdAdapter()));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), miscMap));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_NpcLevel, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_NpcFactionID, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_NpcHealth, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_NpcMana, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_NpcFatigue, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_NpcDisposition, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_NpcReputation, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_NpcRank, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_NpcGold, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_NpcPersistence, CSMWorld::ColumnBase::Display_Boolean));
WeaponColumns weaponColumns (enchantableColumns);
mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponType, ColumnBase::Display_WeaponType));

@ -92,7 +92,8 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
{ CSMWorld::ColumnBase::Display_AiPackageType, CSMWorld::Columns::ColumnId_AiPackageType, false },
{ CSMWorld::ColumnBase::Display_YesNo, CSMWorld::Columns::ColumnId_AiWanderRepeat, false },
{ CSMWorld::ColumnBase::Display_InfoCondFunc, CSMWorld::Columns::ColumnId_InfoCondFunc, false },
{ CSMWorld::ColumnBase::Display_InfoCondComp, CSMWorld::Columns::ColumnId_InfoCondComp, false }
{ CSMWorld::ColumnBase::Display_InfoCondComp, CSMWorld::Columns::ColumnId_InfoCondComp, false },
{ CSMWorld::ColumnBase::Display_RaceSkill, CSMWorld::Columns::ColumnId_RaceSkill, true },
};
for (std::size_t i=0; i<sizeof (sMapping)/sizeof (Mapping); ++i)

@ -20,6 +20,7 @@
#include <QPushButton>
#include <QToolButton>
#include <QHeaderView>
#include <QScrollBar>
#include "../../model/world/nestedtableproxymodel.hpp"
#include "../../model/world/columnbase.hpp"
@ -347,10 +348,13 @@ CSVWorld::DialogueDelegateDispatcher::~DialogueDelegateDispatcher()
CSVWorld::EditWidget::~EditWidget()
{
for (unsigned i = 0; i < mNestedModels.size(); ++i)
{
delete mNestedModels[i];
}
delete mNestedTableDispatcher;
if (mDispatcher)
delete mDispatcher;
if (mNestedTableDispatcher)
delete mNestedTableDispatcher;
}
CSVWorld::EditWidget::EditWidget(QWidget *parent,
@ -359,7 +363,7 @@ CSVWorld::EditWidget::EditWidget(QWidget *parent,
QScrollArea(parent),
mWidgetMapper(NULL),
mNestedTableMapper(NULL),
mDispatcher(this, table, commandDispatcher, document),
mDispatcher(NULL),
mNestedTableDispatcher(NULL),
mMainWidget(NULL),
mTable(table),
@ -368,41 +372,41 @@ mDocument (document)
{
remake (row);
connect(&mDispatcher, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)),
connect(mDispatcher, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)),
this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
}
void CSVWorld::EditWidget::remake(int row)
{
for (unsigned i = 0; i < mNestedModels.size(); ++i)
{
delete mNestedModels[i];
}
mNestedModels.clear();
delete mNestedTableDispatcher;
if (mMainWidget)
{
delete mMainWidget;
mMainWidget = 0;
}
mMainWidget = new QWidget (this);
if (mDispatcher)
delete mDispatcher;
mDispatcher = new DialogueDelegateDispatcher(0/*this*/, mTable, mCommandDispatcher, mDocument);
if (mNestedTableDispatcher)
delete mNestedTableDispatcher;
//not sure if widget mapper can handle deleting the widgets that were mapped
if (mWidgetMapper)
{
delete mWidgetMapper;
mWidgetMapper = 0;
}
mWidgetMapper = new QDataWidgetMapper (this);
mWidgetMapper->setModel(mTable);
mWidgetMapper->setItemDelegate(mDispatcher);
if (mNestedTableMapper)
{
delete mNestedTableMapper;
mNestedTableMapper = 0;
}
mWidgetMapper = new QDataWidgetMapper (this);
mWidgetMapper->setModel(mTable);
mWidgetMapper->setItemDelegate(&mDispatcher);
if (mMainWidget)
{
QWidget *del = this->takeWidget();
del->deleteLater();
}
mMainWidget = new QWidget (this);
QFrame* line = new QFrame(mMainWidget);
line->setObjectName(QString::fromUtf8("line"));
@ -457,7 +461,14 @@ void CSVWorld::EditWidget::remake(int row)
NestedTable* table = new NestedTable(mDocument, id, mNestedModels.back(), this);
// FIXME: does not work well when enum delegates are used
//table->resizeColumnsToContents();
table->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::CurrentChanged);
if(mTable->index(row, i).data().type() == QVariant::UserType)
{
table->setEditTriggers(QAbstractItemView::NoEditTriggers);
table->setEnabled(false);
}
else
table->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::CurrentChanged);
int rows = mTable->rowCount(mTable->index(row, i));
int rowHeight = (rows == 0) ? table->horizontalHeader()->height() : table->rowHeight(0);
@ -469,14 +480,16 @@ void CSVWorld::EditWidget::remake(int row)
new QLabel (mTable->headerData (i, Qt::Horizontal, Qt::DisplayRole).toString(), mMainWidget);
label->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);
if(mTable->index(row, i).data().type() == QVariant::UserType)
label->setEnabled(false);
tablesLayout->addWidget(label);
tablesLayout->addWidget(table);
}
else if (!(flags & CSMWorld::ColumnBase::Flag_Dialogue_List))
{
mDispatcher.makeDelegate (display);
QWidget* editor = mDispatcher.makeEditor (display, (mTable->index (row, i)));
mDispatcher->makeDelegate (display);
QWidget* editor = mDispatcher->makeEditor (display, (mTable->index (row, i)));
if (editor)
{
@ -499,6 +512,12 @@ void CSVWorld::EditWidget::remake(int row)
unlockedLayout->addWidget (editor, unlocked, 1);
++unlocked;
}
if(mTable->index(row, i).data().type() == QVariant::UserType)
{
editor->setEnabled(false);
label->setEnabled(false);
}
}
}
else
@ -511,7 +530,7 @@ void CSVWorld::EditWidget::remake(int row)
mNestedTableMapper->setModel(mNestedModels.back());
// FIXME: lack MIME support?
mNestedTableDispatcher =
new DialogueDelegateDispatcher (this, mTable, mCommandDispatcher, mDocument, mNestedModels.back());
new DialogueDelegateDispatcher (0/*this*/, mTable, mCommandDispatcher, mDocument, mNestedModels.back());
mNestedTableMapper->setItemDelegate(mNestedTableDispatcher);
int columnCount =
@ -546,6 +565,12 @@ void CSVWorld::EditWidget::remake(int row)
unlockedLayout->addWidget (label, unlocked, 0);
unlockedLayout->addWidget (editor, unlocked, 1);
++unlocked;
if(mNestedModels.back()->index(0, col).data().type() == QVariant::UserType)
{
editor->setEnabled(false);
label->setEnabled(false);
}
}
}
mNestedTableMapper->setCurrentModelIndex(mNestedModels.back()->index(0, 0));
@ -763,6 +788,9 @@ void CSVWorld::DialogueSubView::dataChanged (const QModelIndex & index)
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (currentIndex.row(), 1)).toInt());
mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || mLocked);
int y = mEditWidget->verticalScrollBar()->value();
mEditWidget->remake (index.row());
mEditWidget->verticalScrollBar()->setValue(y);
}
}

@ -165,7 +165,7 @@ namespace CSVWorld
Q_OBJECT
QDataWidgetMapper *mWidgetMapper;
QDataWidgetMapper *mNestedTableMapper;
DialogueDelegateDispatcher mDispatcher;
DialogueDelegateDispatcher *mDispatcher;
DialogueDelegateDispatcher *mNestedTableDispatcher;
QWidget* mMainWidget;
CSMWorld::IdTable* mTable;

Loading…
Cancel
Save