Merge branch 'columns'

actorid
Marc Zinnschlag 12 years ago
commit bf839d19cf

@ -24,11 +24,11 @@ opencs_units (model/world
opencs_units_noqt (model/world
universalid data record commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns
)
opencs_hdrs_noqt (model/world
columns idcollection collection
columnimp idcollection collection
)
@ -107,6 +107,10 @@ opencs_units_noqt (model/settings
settingsitem
)
opencs_hdrs_noqt (model/filter
filter
)
set (OPENCS_US
)

@ -0,0 +1,26 @@
#ifndef CSM_FILTER_FILTER_H
#define CSM_FILTER_FILTER_H
#include <vector>
#include <string>
#include <components/esm/filter.hpp>
namespace CSMFilter
{
/// \brief Wrapper for Filter record
struct Filter : public ESM::Filter
{
enum scope
{
Global = 0,
Local = 1,
Session = 2,
Content = 3
};
scope mScope;
};
}
#endif

@ -1,8 +1,10 @@
#include "columnbase.hpp"
CSMWorld::ColumnBase::ColumnBase (const std::string& title, Display displayType, int flags)
: mTitle (title), mDisplayType (displayType), mFlags (flags)
#include "columns.hpp"
CSMWorld::ColumnBase::ColumnBase (int columnId, Display displayType, int flags)
: mColumnId (columnId), mDisplayType (displayType), mFlags (flags)
{}
CSMWorld::ColumnBase::~ColumnBase() {}
@ -10,4 +12,9 @@ CSMWorld::ColumnBase::~ColumnBase() {}
bool CSMWorld::ColumnBase::isUserEditable() const
{
return isEditable();
}
std::string CSMWorld::ColumnBase::getTitle() const
{
return Columns::getName (static_cast<Columns::ColumnId> (mColumnId));
}

@ -46,11 +46,11 @@ namespace CSMWorld
Display_RefRecordType
};
std::string mTitle;
int mColumnId;
int mFlags;
Display mDisplayType;
ColumnBase (const std::string& title, Display displayType, int flag);
ColumnBase (int columnId, Display displayType, int flag);
virtual ~ColumnBase();
@ -59,22 +59,22 @@ namespace CSMWorld
virtual bool isUserEditable() const;
///< Can this column be edited directly by the user?
virtual std::string getTitle() const;
};
template<typename ESXRecordT>
struct Column : public ColumnBase
{
std::string mTitle;
int mFlags;
Column (const std::string& title, Display displayType, int flags = Flag_Table | Flag_Dialogue)
: ColumnBase (title, displayType, flags) {}
Column (int columnId, Display displayType, int flags = Flag_Table | Flag_Dialogue)
: ColumnBase (columnId, displayType, flags) {}
virtual QVariant get (const Record<ESXRecordT>& record) const = 0;
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
throw std::logic_error ("Column " + mTitle + " is not editable");
throw std::logic_error ("Column " + getTitle() + " is not editable");
}
};
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,197 @@
#include "columns.hpp"
#include <components/misc/stringops.hpp>
namespace CSMWorld
{
namespace Columns
{
struct ColumnDesc
{
int mId;
const char *mName;
};
const ColumnDesc sNames[] =
{
{ ColumnId_Value, "Value" },
{ ColumnId_Id, "ID" },
{ ColumnId_Modification, "Modified" },
{ ColumnId_RecordType, "Record Type" },
{ ColumnId_ValueType, "Value Type" },
{ ColumnId_Description, "Description" },
{ ColumnId_Specialisation, "Specialisation" },
{ ColumnId_Attribute, "Attribute" },
{ ColumnId_Name, "Name" },
{ ColumnId_Playable, "Playable" },
{ ColumnId_Hidden, "Hidden" },
{ ColumnId_MaleWeight, "Male Weight" },
{ ColumnId_FemaleWeight, "Female Weight" },
{ ColumnId_MaleHeight, "Male Height" },
{ ColumnId_FemaleHeight, "Female Height" },
{ ColumnId_Volume, "Volume" },
{ ColumnId_MinRange, "Min Range" },
{ ColumnId_MaxRange, "Max Range" },
{ ColumnId_SoundFile, "Sound File" },
{ ColumnId_MapColour, "Map Colour" },
{ ColumnId_SleepEncounter, "Sleep Encounter" },
{ ColumnId_Texture, "Texture" },
{ ColumnId_SpellType, "Spell Type" },
{ ColumnId_Cost, "Cost" },
{ ColumnId_ScriptText, "Script Text" },
{ ColumnId_Region, "Region" },
{ ColumnId_Cell, "Cell" },
{ ColumnId_Scale, "Scale" },
{ ColumnId_Owner, "Owner" },
{ ColumnId_Soul, "Soul" },
{ ColumnId_Faction, "Faction" },
{ ColumnId_FactionIndex, "Faction Index" },
{ ColumnId_Charges, "Charges" },
{ ColumnId_Enchantment, "Enchantment" },
{ ColumnId_Value, "Coin Value" },
{ ColumnId_Teleport, "Teleport" },
{ ColumnId_TeleportCell, "Teleport Cell" },
{ ColumnId_LockLevel, "Lock Level" },
{ ColumnId_Key, "Key" },
{ ColumnId_Trap, "Trap" },
{ ColumnId_BeastRace, "Beast Race" },
{ ColumnId_AutoCalc, "Auto Calc" },
{ ColumnId_StarterSpell, "Starter Spell" },
{ ColumnId_AlwaysSucceeds, "Always Succeeds" },
{ ColumnId_SleepForbidden, "Sleep Forbidden" },
{ ColumnId_InteriorWater, "Interior Water" },
{ ColumnId_InteriorSky, "Interior Sky" },
{ ColumnId_Model, "Model" },
{ ColumnId_Script, "Script" },
{ ColumnId_Icon, "Icon" },
{ ColumnId_Weight, "Weight" },
{ ColumnId_EnchantmentPoints, "Enchantment Points" },
{ ColumnId_Quality, "Quality" },
{ ColumnId_Ai, "AI" },
{ ColumnId_AiHello, "AI Hello" },
{ ColumnId_AiFlee, "AI Flee" },
{ ColumnId_AiFight, "AI Fight" },
{ ColumnId_AiAlarm, "AI Alarm" },
{ ColumnId_BuysWeapons, "Buys Weapons" },
{ ColumnId_BuysArmor, "Buys Armor" },
{ ColumnId_BuysClothing, "Buys Clothing" },
{ ColumnId_BuysBooks, "Buys Books" },
{ ColumnId_BuysIngredients, "Buys Ingredients" },
{ ColumnId_BuysLockpicks, "Buys Lockpicks" },
{ ColumnId_BuysProbes, "Buys Probes" },
{ ColumnId_BuysLights, "Buys Lights" },
{ ColumnId_BuysApparati, "Buys Apparati" },
{ ColumnId_BuysRepairItems, "Buys Repair Items" },
{ ColumnId_BuysMiscItems, "Buys Misc Items" },
{ ColumnId_BuysPotions, "Buys Potions" },
{ ColumnId_BuysMagicItems, "Buys Magic Items" },
{ ColumnId_SellsSpells, "Sells Spells" },
{ ColumnId_Trainer, "Trainer" },
{ ColumnId_Spellmaking, "Spellmaking" },
{ ColumnId_EnchantingService, "Enchanting Service" },
{ ColumnId_RepairService, "Repair Serivce" },
{ ColumnId_ApparatusType, "Apparatus Type" },
{ ColumnId_ArmorType, "Armor Type" },
{ ColumnId_Health, "Health" },
{ ColumnId_ArmorValue, "Armor Value" },
{ ColumnId_Scroll, "Scroll" },
{ ColumnId_ClothingType, "Clothing Type" },
{ ColumnId_WeightCapacity, "Weight Capacity" },
{ ColumnId_OrganicContainer, "Organic Container" },
{ ColumnId_Respawn, "Respawn" },
{ ColumnId_CreatureType, "Creature Type" },
{ ColumnId_SoulPoints, "Soul Points" },
{ ColumnId_OriginalCreature, "Original Creature" },
{ ColumnId_Biped, "Biped" },
{ ColumnId_HasWeapon, "Has Weapon" },
{ ColumnId_NoMovement, "No Movement" },
{ ColumnId_Swims, "Swims" },
{ ColumnId_Flies, "Flies" },
{ ColumnId_Walks, "Walks" },
{ ColumnId_Essential, "Essential" },
{ ColumnId_SkeletonBlood, "Skeleton Blood" },
{ ColumnId_MetalBlood, "Metal Blood" },
{ ColumnId_OpenSound, "Open Sound" },
{ ColumnId_CloseSound, "Close Sound" },
{ ColumnId_Duration, "Duration" },
{ ColumnId_Radius, "Radius" },
{ ColumnId_Colour, "Colour" },
{ ColumnId_Sound, "Sound" },
{ ColumnId_Dynamic, "Dynamic" },
{ ColumnId_Portable, "Portable" },
{ ColumnId_NegativeLight, "Negative Light" },
{ ColumnId_Flickering, "Flickering" },
{ ColumnId_SlowFlickering, "Slow Flickering" },
{ ColumnId_Pulsing, "Pulsing" },
{ ColumnId_SlowPulsing, "Slow Pulsing" },
{ ColumnId_Fire, "Fire" },
{ ColumnId_OffByDefault, "Off by default" },
{ ColumnId_IsKey, "Is Key" },
{ ColumnId_Race, "Race" },
{ ColumnId_Class, "Class" },
{ Columnid_Hair, "Hair" },
{ ColumnId_Head, "Head" },
{ ColumnId_Female, "Female" },
{ ColumnId_WeaponType, "Weapon Type" },
{ ColumnId_WeaponSpeed, "Weapon Speed" },
{ ColumnId_WeaponReach, "Weapon Reach" },
{ ColumnId_MinChop, "Min Chop" },
{ ColumnId_MaxChip, "Max Chop" },
{ Columnid_MinSlash, "Min Slash" },
{ ColumnId_MaxSlash, "Max Slash" },
{ ColumnId_MinThrust, "Min Thrust" },
{ ColumnId_MaxThrust, "Max Thrust" },
{ ColumnId_Magical, "Magical" },
{ ColumnId_Silver, "Silver" },
{ ColumnId_UseValue1, "Use value 1" },
{ ColumnId_UseValue2, "Use value 2" },
{ ColumnId_UseValue3, "Use value 3" },
{ ColumnId_UseValue4, "Use value 4" },
{ ColumnId_Attribute1, "Attribute 1" },
{ ColumnId_Attribute2, "Attribute 2" },
{ ColumnId_MajorSkill1, "Major Skill 1" },
{ ColumnId_MajorSkill2, "Major Skill 2" },
{ ColumnId_MajorSkill3, "Major Skill 3" },
{ ColumnId_MajorSkill4, "Major Skill 4" },
{ ColumnId_MajorSkill5, "Major Skill 5" },
{ ColumnId_MinorSkill1, "Minor Skill 1" },
{ ColumnId_MinorSkill2, "Minor Skill 2" },
{ ColumnId_MinorSkill3, "Minor Skill 3" },
{ ColumnId_MinorSkill4, "Minor Skill 4" },
{ ColumnId_MinorSkill5, "Minor Skill 5" },
{ ColumnId_Skill1, "Skill 1" },
{ ColumnId_Skill1, "Skill 2" },
{ ColumnId_Skill1, "Skill 3" },
{ ColumnId_Skill1, "Skill 4" },
{ ColumnId_Skill1, "Skill 5" },
{ -1, 0 } // end marker
};
}
}
std::string CSMWorld::Columns::getName (ColumnId column)
{
for (int i=0; sNames[i].mName; ++i)
if (column==sNames[i].mId)
return sNames[i].mName;
return "";
}
int CSMWorld::Columns::getId (const std::string& name)
{
std::string name2 = Misc::StringUtils::lowerCase (name);
for (int i=0; sNames[i].mName; ++i)
if (name2==Misc::StringUtils::lowerCase (sNames[i].mName))
return sNames[i].mId;
return -1;
}

File diff suppressed because it is too large Load Diff

@ -10,8 +10,9 @@
#include <components/esm/loadglob.hpp>
#include "idtable.hpp"
#include "columns.hpp"
#include "columnimp.hpp"
#include "regionmap.hpp"
#include "columns.hpp"
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2)
@ -76,8 +77,8 @@ CSMWorld::Data::Data() : mRefs (mCells)
mRaces.addColumn (new FixedRecordTypeColumn<ESM::Race> (UniversalId::Type_Race));
mRaces.addColumn (new NameColumn<ESM::Race>);
mRaces.addColumn (new DescriptionColumn<ESM::Race>);
mRaces.addColumn (new FlagColumn<ESM::Race> ("Playable", 0x1));
mRaces.addColumn (new FlagColumn<ESM::Race> ("Beast Race", 0x2));
mRaces.addColumn (new FlagColumn<ESM::Race> (Columns::ColumnId_Playable, 0x1));
mRaces.addColumn (new FlagColumn<ESM::Race> (Columns::ColumnId_BeastRace, 0x2));
mRaces.addColumn (new WeightHeightColumn<ESM::Race> (true, true));
mRaces.addColumn (new WeightHeightColumn<ESM::Race> (true, false));
mRaces.addColumn (new WeightHeightColumn<ESM::Race> (false, true));
@ -116,17 +117,17 @@ CSMWorld::Data::Data() : mRefs (mCells)
mSpells.addColumn (new NameColumn<ESM::Spell>);
mSpells.addColumn (new SpellTypeColumn<ESM::Spell>);
mSpells.addColumn (new CostColumn<ESM::Spell>);
mSpells.addColumn (new FlagColumn<ESM::Spell> ("Autocalc", 0x1));
mSpells.addColumn (new FlagColumn<ESM::Spell> ("Starter Spell", 0x2));
mSpells.addColumn (new FlagColumn<ESM::Spell> ("Always Succeeds", 0x4));
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_AutoCalc, 0x1));
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_StarterSpell, 0x2));
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_AlwaysSucceeds, 0x4));
mCells.addColumn (new StringIdColumn<Cell>);
mCells.addColumn (new RecordStateColumn<Cell>);
mCells.addColumn (new FixedRecordTypeColumn<Cell> (UniversalId::Type_Cell));
mCells.addColumn (new NameColumn<Cell>);
mCells.addColumn (new FlagColumn<Cell> ("Sleep forbidden", ESM::Cell::NoSleep));
mCells.addColumn (new FlagColumn<Cell> ("Interior Water", ESM::Cell::HasWater));
mCells.addColumn (new FlagColumn<Cell> ("Interior Sky", ESM::Cell::QuasiEx));
mCells.addColumn (new FlagColumn<Cell> (Columns::ColumnId_SleepForbidden, ESM::Cell::NoSleep));
mCells.addColumn (new FlagColumn<Cell> (Columns::ColumnId_InteriorWater, ESM::Cell::HasWater));
mCells.addColumn (new FlagColumn<Cell> (Columns::ColumnId_InteriorSky, ESM::Cell::QuasiEx));
mCells.addColumn (new RegionColumn<Cell>);
mRefs.addColumn (new StringIdColumn<CellRef> (true));
@ -147,6 +148,9 @@ CSMWorld::Data::Data() : mRefs (mCells)
mRefs.addColumn (new KeyColumn<CellRef>);
mRefs.addColumn (new TrapColumn<CellRef>);
mFilters.addColumn (new StringIdColumn<CSMFilter::Filter>);
mFilters.addColumn (new RecordStateColumn<CSMFilter::Filter>);
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill);
@ -162,6 +166,7 @@ CSMWorld::Data::Data() : mRefs (mCells)
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables,
UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs), UniversalId::Type_References, UniversalId::Type_Reference);
addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter);
}
CSMWorld::Data::~Data()

@ -18,6 +18,8 @@
#include <components/esm/loadbsgn.hpp>
#include <components/esm/loadspel.hpp>
#include "../filter/filter.hpp"
#include "idcollection.hpp"
#include "universalid.hpp"
#include "cell.hpp"
@ -44,6 +46,7 @@ namespace CSMWorld
IdCollection<Cell> mCells;
RefIdCollection mReferenceables;
RefCollection mRefs;
IdCollection<CSMFilter::Filter> mFilters;
std::vector<QAbstractItemModel *> mModels;
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;

@ -47,7 +47,7 @@ QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation
return QVariant();
if (role==Qt::DisplayRole)
return tr (mIdCollection->getColumn (section).mTitle.c_str());
return tr (mIdCollection->getColumn (section).getTitle().c_str());
if (role==ColumnBase::Role_Flags)
return mIdCollection->getColumn (section).mFlags;
@ -157,4 +157,25 @@ void CSMWorld::IdTable::setRecord (const std::string& id, const RecordBase& reco
const CSMWorld::RecordBase& CSMWorld::IdTable::getRecord (const std::string& id) const
{
return mIdCollection->getRecord (id);
}
int CSMWorld::IdTable::searchColumnIndex (Columns::ColumnId id) const
{
int columns = mIdCollection->getColumns();
for (int i=0; i<columns; ++i)
if (mIdCollection->getColumn (i).mColumnId==id)
return i;
return -1;
}
int CSMWorld::IdTable::findColumnIndex (Columns::ColumnId id) const
{
int index = searchColumnIndex (id);
if (index==-1)
throw std::logic_error ("invalid column index");
return index;
}

@ -4,6 +4,7 @@
#include <QAbstractItemModel>
#include "universalid.hpp"
#include "columns.hpp"
namespace CSMWorld
{
@ -55,6 +56,13 @@ namespace CSMWorld
///< Add record or overwrite existing recrod.
const RecordBase& getRecord (const std::string& id) const;
int searchColumnIndex (Columns::ColumnId id) const;
///< Return index of column with the given \a id. If no such column exists, -1 is returned.
int findColumnIndex (Columns::ColumnId id) const;
///< Return index of column with the given \a id. If no such column exists, an exception is
/// thrown.
};
}

@ -7,10 +7,11 @@
#include "refidadapter.hpp"
#include "refidadapterimp.hpp"
#include "columns.hpp"
CSMWorld::RefIdColumn::RefIdColumn (const std::string& title, Display displayType, int flag,
CSMWorld::RefIdColumn::RefIdColumn (int columnId, Display displayType, int flag,
bool editable, bool userEditable)
: ColumnBase (title, displayType, flag), mEditable (editable), mUserEditable (userEditable)
: ColumnBase (columnId, displayType, flag), mEditable (editable), mUserEditable (userEditable)
{}
bool CSMWorld::RefIdColumn::isEditable() const
@ -38,157 +39,158 @@ CSMWorld::RefIdCollection::RefIdCollection()
{
BaseColumns baseColumns;
mColumns.push_back (RefIdColumn ("ID", ColumnBase::Display_String,
mColumns.push_back (RefIdColumn (Columns::ColumnId_Id, ColumnBase::Display_String,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
baseColumns.mId = &mColumns.back();
mColumns.push_back (RefIdColumn ("*", ColumnBase::Display_RecordState,
mColumns.push_back (RefIdColumn (Columns::ColumnId_Modification, ColumnBase::Display_RecordState,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
baseColumns.mModified = &mColumns.back();
mColumns.push_back (RefIdColumn ("Type", ColumnBase::Display_RefRecordType,
mColumns.push_back (RefIdColumn (Columns::ColumnId_RecordType, ColumnBase::Display_RefRecordType,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
baseColumns.mType = &mColumns.back();
ModelColumns modelColumns (baseColumns);
mColumns.push_back (RefIdColumn ("Model", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Model, ColumnBase::Display_String));
modelColumns.mModel = &mColumns.back();
NameColumns nameColumns (modelColumns);
mColumns.push_back (RefIdColumn ("Name", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Name, ColumnBase::Display_String));
nameColumns.mName = &mColumns.back();
mColumns.push_back (RefIdColumn ("Script", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Script, ColumnBase::Display_String));
nameColumns.mScript = &mColumns.back();
InventoryColumns inventoryColumns (nameColumns);
mColumns.push_back (RefIdColumn ("Icon", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Icon, ColumnBase::Display_String));
inventoryColumns.mIcon = &mColumns.back();
mColumns.push_back (RefIdColumn ("Weight", ColumnBase::Display_Float));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Weight, ColumnBase::Display_Float));
inventoryColumns.mWeight = &mColumns.back();
mColumns.push_back (RefIdColumn ("Value", ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_CoinValue, ColumnBase::Display_Integer));
inventoryColumns.mValue = &mColumns.back();
EnchantableColumns enchantableColumns (inventoryColumns);
mColumns.push_back (RefIdColumn ("Enchantment", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Enchantment, ColumnBase::Display_String));
enchantableColumns.mEnchantment = &mColumns.back();
mColumns.push_back (RefIdColumn ("Enchantment Points", ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_EnchantmentPoints, ColumnBase::Display_Integer));
enchantableColumns.mEnchantmentPoints = &mColumns.back();
ToolColumns toolsColumns (inventoryColumns);
mColumns.push_back (RefIdColumn ("Quality", ColumnBase::Display_Float));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Quality, ColumnBase::Display_Float));
toolsColumns.mQuality = &mColumns.back();
mColumns.push_back (RefIdColumn ("Uses", ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Charges, ColumnBase::Display_Integer));
toolsColumns.mUses = &mColumns.back();
ActorColumns actorsColumns (nameColumns);
mColumns.push_back (RefIdColumn ("AI", ColumnBase::Display_Boolean));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Ai, ColumnBase::Display_Boolean));
actorsColumns.mHasAi = &mColumns.back();
mColumns.push_back (RefIdColumn ("AI Hello", ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiHello, ColumnBase::Display_Integer));
actorsColumns.mHello = &mColumns.back();
mColumns.push_back (RefIdColumn ("AI Flee", ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiFlee, ColumnBase::Display_Integer));
actorsColumns.mFlee = &mColumns.back();
mColumns.push_back (RefIdColumn ("AI Fight", ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiFight, ColumnBase::Display_Integer));
actorsColumns.mFight = &mColumns.back();
mColumns.push_back (RefIdColumn ("AI Alarm", ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiAlarm, ColumnBase::Display_Integer));
actorsColumns.mAlarm = &mColumns.back();
static const struct
{
const char *mName;
int mName;
unsigned int mFlag;
} sServiceTable[] =
{
{ "Buys Weapons", ESM::NPC::Weapon},
{ "Buys Armor", ESM::NPC::Armor},
{ "Buys Clothing", ESM::NPC::Clothing},
{ "Buys Books", ESM::NPC::Books},
{ "Buys Ingredients", ESM::NPC::Ingredients},
{ "Buys Lockpicks", ESM::NPC::Picks},
{ "Buys Probes", ESM::NPC::Probes},
{ "Buys Lights", ESM::NPC::Lights},
{ "Buys Apparati", ESM::NPC::Apparatus},
{ "Buys Repair Items", ESM::NPC::RepairItem},
{ "Buys Misc Items", ESM::NPC::Misc},
{ "Buys Potions", ESM::NPC::Potions},
{ "Buys Magic Items", ESM::NPC::MagicItems},
{ "Sells Spells", ESM::NPC::Spells},
{ "Trainer", ESM::NPC::Training},
{ "Spellmaking", ESM::NPC::Spellmaking},
{ "Enchanting Service", ESM::NPC::Enchanting},
{ "Repair Serivce", ESM::NPC::Repair},
{ 0, 0 }
{ Columns::ColumnId_BuysWeapons, ESM::NPC::Weapon},
{ Columns::ColumnId_BuysArmor, ESM::NPC::Armor},
{ Columns::ColumnId_BuysClothing, ESM::NPC::Clothing},
{ Columns::ColumnId_BuysBooks, ESM::NPC::Books},
{ Columns::ColumnId_BuysIngredients, ESM::NPC::Ingredients},
{ Columns::ColumnId_BuysLockpicks, ESM::NPC::Picks},
{ Columns::ColumnId_BuysProbes, ESM::NPC::Probes},
{ Columns::ColumnId_BuysLights, ESM::NPC::Lights},
{ Columns::ColumnId_BuysApparati, ESM::NPC::Apparatus},
{ Columns::ColumnId_BuysRepairItems, ESM::NPC::RepairItem},
{ Columns::ColumnId_BuysMiscItems, ESM::NPC::Misc},
{ Columns::ColumnId_BuysPotions, ESM::NPC::Potions},
{ Columns::ColumnId_BuysMagicItems, ESM::NPC::MagicItems},
{ Columns::ColumnId_SellsSpells, ESM::NPC::Spells},
{ Columns::ColumnId_Trainer, ESM::NPC::Training},
{ Columns::ColumnId_Spellmaking, ESM::NPC::Spellmaking},
{ Columns::ColumnId_EnchantingService, ESM::NPC::Enchanting},
{ Columns::ColumnId_RepairService, ESM::NPC::Repair},
{ -1, 0 }
};
for (int i=0; sServiceTable[i].mName; ++i)
for (int i=0; sServiceTable[i].mName!=-1; ++i)
{
mColumns.push_back (RefIdColumn (sServiceTable[i].mName, ColumnBase::Display_Boolean));
actorsColumns.mServices.insert (std::make_pair (&mColumns.back(), sServiceTable[i].mFlag));
}
mColumns.push_back (RefIdColumn ("Auto Calc", ColumnBase::Display_Boolean));
mColumns.push_back (RefIdColumn (Columns::ColumnId_AutoCalc, ColumnBase::Display_Boolean));
const RefIdColumn *autoCalc = &mColumns.back();
mColumns.push_back (RefIdColumn ("Apparatus Type", ColumnBase::Display_ApparatusType));
mColumns.push_back (RefIdColumn (Columns::ColumnId_ApparatusType,
ColumnBase::Display_ApparatusType));
const RefIdColumn *apparatusType = &mColumns.back();
mColumns.push_back (RefIdColumn ("Armor Type", ColumnBase::Display_ArmorType));
mColumns.push_back (RefIdColumn (Columns::ColumnId_ArmorType, ColumnBase::Display_ArmorType));
const RefIdColumn *armorType = &mColumns.back();
mColumns.push_back (RefIdColumn ("Health", ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Health, ColumnBase::Display_Integer));
const RefIdColumn *health = &mColumns.back();
mColumns.push_back (RefIdColumn ("Armor Value", ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_ArmorValue, ColumnBase::Display_Integer));
const RefIdColumn *armor = &mColumns.back();
mColumns.push_back (RefIdColumn ("Scroll", ColumnBase::Display_Boolean));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Scroll, ColumnBase::Display_Boolean));
const RefIdColumn *scroll = &mColumns.back();
mColumns.push_back (RefIdColumn ("Attribute", ColumnBase::Display_Attribute));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute));
const RefIdColumn *attribute = &mColumns.back();
mColumns.push_back (RefIdColumn ("Clothing Type", ColumnBase::Display_ClothingType));
mColumns.push_back (RefIdColumn (Columns::ColumnId_ClothingType, ColumnBase::Display_ClothingType));
const RefIdColumn *clothingType = &mColumns.back();
mColumns.push_back (RefIdColumn ("Weight Capacity", ColumnBase::Display_Float));
mColumns.push_back (RefIdColumn (Columns::ColumnId_WeightCapacity, ColumnBase::Display_Float));
const RefIdColumn *weightCapacity = &mColumns.back();
mColumns.push_back (RefIdColumn ("Organic Container", ColumnBase::Display_Boolean));
mColumns.push_back (RefIdColumn (Columns::ColumnId_OrganicContainer, ColumnBase::Display_Boolean));
const RefIdColumn *organic = &mColumns.back();
mColumns.push_back (RefIdColumn ("Respawn", ColumnBase::Display_Boolean));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Respawn, ColumnBase::Display_Boolean));
const RefIdColumn *respawn = &mColumns.back();
CreatureColumns creatureColumns (actorsColumns);
mColumns.push_back (RefIdColumn ("Creature Type", ColumnBase::Display_CreatureType));
mColumns.push_back (RefIdColumn (Columns::ColumnId_CreatureType, ColumnBase::Display_CreatureType));
creatureColumns.mType = &mColumns.back();
mColumns.push_back (RefIdColumn ("Soul Points", ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_SoulPoints, ColumnBase::Display_Integer));
creatureColumns.mSoul = &mColumns.back();
mColumns.push_back (RefIdColumn ("Scale", ColumnBase::Display_Float));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Scale, ColumnBase::Display_Float));
creatureColumns.mScale = &mColumns.back();
mColumns.push_back (RefIdColumn ("Original Creature", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_OriginalCreature, ColumnBase::Display_String));
creatureColumns.mOriginal = &mColumns.back();
static const struct
{
const char *mName;
int mName;
unsigned int mFlag;
} sCreatureFlagTable[] =
{
{ "Biped", ESM::Creature::Biped },
{ "Has Weapon", ESM::Creature::Weapon },
{ "No Movement", ESM::Creature::None },
{ "Swims", ESM::Creature::Swims },
{ "Flies", ESM::Creature::Flies },
{ "Walks", ESM::Creature::Walks },
{ "Essential", ESM::Creature::Essential },
{ "Skeleton Blood", ESM::Creature::Skeleton },
{ "Metal Blood", ESM::Creature::Metal },
{ 0, 0 }
{ Columns::ColumnId_Biped, ESM::Creature::Biped },
{ Columns::ColumnId_HasWeapon, ESM::Creature::Weapon },
{ Columns::ColumnId_NoMovement, ESM::Creature::None },
{ Columns::ColumnId_Swims, ESM::Creature::Swims },
{ Columns::ColumnId_Flies, ESM::Creature::Flies },
{ Columns::ColumnId_Walks, ESM::Creature::Walks },
{ Columns::ColumnId_Essential, ESM::Creature::Essential },
{ Columns::ColumnId_SkeletonBlood, ESM::Creature::Skeleton },
{ Columns::ColumnId_MetalBlood, ESM::Creature::Metal },
{ -1, 0 }
};
// for re-use in NPC records
@ -196,7 +198,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
const RefIdColumn *skeletonBlood = 0;
const RefIdColumn *metalBlood = 0;
for (int i=0; sCreatureFlagTable[i].mName; ++i)
for (int i=0; sCreatureFlagTable[i].mName!=-1; ++i)
{
mColumns.push_back (RefIdColumn (sCreatureFlagTable[i].mName, ColumnBase::Display_Boolean));
creatureColumns.mFlags.insert (std::make_pair (&mColumns.back(), sCreatureFlagTable[i].mFlag));
@ -211,71 +213,71 @@ CSMWorld::RefIdCollection::RefIdCollection()
creatureColumns.mFlags.insert (std::make_pair (respawn, ESM::Creature::Respawn));
mColumns.push_back (RefIdColumn ("Open Sound", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_OpenSound, ColumnBase::Display_String));
const RefIdColumn *openSound = &mColumns.back();
mColumns.push_back (RefIdColumn ("Close Sound", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_CloseSound, ColumnBase::Display_String));
const RefIdColumn *closeSound = &mColumns.back();
LightColumns lightColumns (inventoryColumns);
mColumns.push_back (RefIdColumn ("Duration", ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Duration, ColumnBase::Display_Integer));
lightColumns.mTime = &mColumns.back();
mColumns.push_back (RefIdColumn ("Radius", ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Radius, ColumnBase::Display_Integer));
lightColumns.mRadius = &mColumns.back();
mColumns.push_back (RefIdColumn ("Colour", ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Colour, ColumnBase::Display_Integer));
lightColumns.mColor = &mColumns.back();
mColumns.push_back (RefIdColumn ("Sound", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Sound, ColumnBase::Display_String));
lightColumns.mSound = &mColumns.back();
static const struct
{
const char *mName;
int mName;
unsigned int mFlag;
} sLightFlagTable[] =
{
{ "Dynamic", ESM::Light::Dynamic },
{ "Portable", ESM::Light::Carry },
{ "Negative Light", ESM::Light::Negative },
{ "Flickering", ESM::Light::Flicker },
{ "Slow Flickering", ESM::Light::Flicker },
{ "Pulsing", ESM::Light::Pulse },
{ "Slow Pulsing", ESM::Light::PulseSlow },
{ "Fire", ESM::Light::Fire },
{ "Off by default", ESM::Light::OffDefault },
{ 0, 0 }
{ Columns::ColumnId_Dynamic, ESM::Light::Dynamic },
{ Columns::ColumnId_Portable, ESM::Light::Carry },
{ Columns::ColumnId_NegativeLight, ESM::Light::Negative },
{ Columns::ColumnId_Flickering, ESM::Light::Flicker },
{ Columns::ColumnId_SlowFlickering, ESM::Light::Flicker },
{ Columns::ColumnId_Pulsing, ESM::Light::Pulse },
{ Columns::ColumnId_SlowPulsing, ESM::Light::PulseSlow },
{ Columns::ColumnId_Fire, ESM::Light::Fire },
{ Columns::ColumnId_OffByDefault, ESM::Light::OffDefault },
{ -1, 0 }
};
for (int i=0; sLightFlagTable[i].mName; ++i)
for (int i=0; sLightFlagTable[i].mName!=-1; ++i)
{
mColumns.push_back (RefIdColumn (sLightFlagTable[i].mName, ColumnBase::Display_Boolean));
lightColumns.mFlags.insert (std::make_pair (&mColumns.back(), sLightFlagTable[i].mFlag));
}
mColumns.push_back (RefIdColumn ("Key", ColumnBase::Display_Boolean));
mColumns.push_back (RefIdColumn (Columns::ColumnId_IsKey, ColumnBase::Display_Boolean));
const RefIdColumn *key = &mColumns.back();
NpcColumns npcColumns (actorsColumns);
mColumns.push_back (RefIdColumn ("Race", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Race, ColumnBase::Display_String));
npcColumns.mRace = &mColumns.back();
mColumns.push_back (RefIdColumn ("Class", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Class, ColumnBase::Display_String));
npcColumns.mClass = &mColumns.back();
mColumns.push_back (RefIdColumn ("Faction", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Faction, ColumnBase::Display_String));
npcColumns.mFaction = &mColumns.back();
mColumns.push_back (RefIdColumn ("Hair", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::Columnid_Hair, ColumnBase::Display_String));
npcColumns.mHair = &mColumns.back();
mColumns.push_back (RefIdColumn ("Head", ColumnBase::Display_String));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Head, ColumnBase::Display_String));
npcColumns.mHead = &mColumns.back();
mColumns.push_back (RefIdColumn ("Female", ColumnBase::Display_Boolean));
mColumns.push_back (RefIdColumn (Columns::ColumnId_Female, ColumnBase::Display_Boolean));
npcColumns.mFlags.insert (std::make_pair (&mColumns.back(), ESM::NPC::Female));
npcColumns.mFlags.insert (std::make_pair (essential, ESM::NPC::Essential));
@ -290,43 +292,35 @@ CSMWorld::RefIdCollection::RefIdCollection()
WeaponColumns weaponColumns (enchantableColumns);
mColumns.push_back (RefIdColumn ("Weapon Type", ColumnBase::Display_WeaponType));
mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponType, ColumnBase::Display_WeaponType));
weaponColumns.mType = &mColumns.back();
weaponColumns.mHealth = health;
mColumns.push_back (RefIdColumn ("Weapon Speed", ColumnBase::Display_Float));
mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponSpeed, ColumnBase::Display_Float));
weaponColumns.mSpeed = &mColumns.back();
mColumns.push_back (RefIdColumn ("Weapon Reach", ColumnBase::Display_Float));
mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponReach, ColumnBase::Display_Float));
weaponColumns.mReach = &mColumns.back();
for (int i=0; i<2; ++i)
for (int i=0; i<6; ++i)
{
std::string suffix = i==0 ? "Min " : "Max ";
mColumns.push_back (RefIdColumn ("Chop" + suffix, ColumnBase::Display_Integer));
mColumns.push_back (RefIdColumn (Columns::ColumnId_MinChop + i, ColumnBase::Display_Integer));
weaponColumns.mChop[i] = &mColumns.back();
mColumns.push_back (RefIdColumn ("Slash" + suffix, ColumnBase::Display_Integer));
weaponColumns.mSlash[i] = &mColumns.back();
mColumns.push_back (RefIdColumn ("Thrust" + suffix, ColumnBase::Display_Integer));
weaponColumns.mThrust[i] = &mColumns.back();
}
static const struct
{
const char *mName;
int mName;
unsigned int mFlag;
} sWeaponFlagTable[] =
{
{ "Magical", ESM::Weapon::Magical },
{ "Silver", ESM::Weapon::Silver },
{ 0, 0 }
{ Columns::ColumnId_Magical, ESM::Weapon::Magical },
{ Columns::ColumnId_Silver, ESM::Weapon::Silver },
{ -1, 0 }
};
for (int i=0; sWeaponFlagTable[i].mName; ++i)
for (int i=0; sWeaponFlagTable[i].mName!=-1; ++i)
{
mColumns.push_back (RefIdColumn (sWeaponFlagTable[i].mName, ColumnBase::Display_Boolean));
weaponColumns.mFlags.insert (std::make_pair (&mColumns.back(), sWeaponFlagTable[i].mFlag));

@ -20,7 +20,7 @@ namespace CSMWorld
public:
RefIdColumn (const std::string& title, Display displayType,
RefIdColumn (int columnId, Display displayType,
int flag = Flag_Table | Flag_Dialogue, bool editable = true,
bool userEditable = true);

@ -36,6 +36,7 @@ namespace
"References", 0 },
{ CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap,
"Region Map", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};

@ -84,7 +84,9 @@ namespace CSMWorld
Type_Weapon,
Type_References,
Type_Reference,
Type_RegionMap
Type_RegionMap,
Type_Filter,
Type_Filters
};
private:

@ -83,6 +83,10 @@ void CSVDoc::View::setupViewMenu()
mShowStatusBar->setCheckable (true);
connect (mShowStatusBar, SIGNAL (toggled (bool)), this, SLOT (toggleShowStatusBar (bool)));
view->addAction (mShowStatusBar);
QAction *filters = new QAction (tr ("Filters"), this);
connect (filters, SIGNAL (triggered()), this, SLOT (addFiltersSubView()));
view->addAction (filters);
}
void CSVDoc::View::setupWorldMenu()
@ -390,6 +394,11 @@ void CSVDoc::View::addRegionMapSubView()
addSubView (CSMWorld::UniversalId::Type_RegionMap);
}
void CSVDoc::View::addFiltersSubView()
{
addSubView (CSMWorld::UniversalId::Type_Filters);
}
void CSVDoc::View::abortOperation (int type)
{
mDocument->abortOperation (type);

@ -158,6 +158,8 @@ namespace CSVDoc
void addRegionMapSubView();
void addFiltersSubView();
void showUserSettings();
void toggleShowStatusBar (bool show);

@ -46,14 +46,14 @@ std::string CSVWorld::GenericCreator::getId() const
void CSVWorld::GenericCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const {}
const CSMWorld::Data& CSVWorld::GenericCreator::getData() const
CSMWorld::Data& CSVWorld::GenericCreator::getData() const
{
return mData;
}
CSMWorld::Data& CSVWorld::GenericCreator::getData()
const CSMWorld::UniversalId& CSVWorld::GenericCreator::getCollectionId() const
{
return mData;
return mListId;
}
CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack,

@ -44,9 +44,9 @@ namespace CSVWorld
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
const CSMWorld::Data& getData() const;
CSMWorld::Data& getData() const;
CSMWorld::Data& getData();
const CSMWorld::UniversalId& getCollectionId() const;
public:

@ -6,6 +6,8 @@
#include "../../model/world/data.hpp"
#include "../../model/world/commands.hpp"
#include "../../model/world/columns.hpp"
#include "../../model/world/idtable.hpp"
std::string CSVWorld::ReferenceCreator::getId() const
{
@ -14,8 +16,11 @@ std::string CSVWorld::ReferenceCreator::getId() const
void CSVWorld::ReferenceCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
{
/// \todo avoid using hard-coded column numbers
command.addValue (2, mCell->text());
int index =
dynamic_cast<CSMWorld::IdTable&> (*getData().getTableModel (getCollectionId())).
findColumnIndex (CSMWorld::Columns::ColumnId_Cell);
command.addValue (index, mCell->text());
}
CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack,

@ -33,6 +33,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
CSMWorld::UniversalId::Type_Regions,
CSMWorld::UniversalId::Type_Birthsigns,
CSMWorld::UniversalId::Type_Spells,
CSMWorld::UniversalId::Type_Filters,
CSMWorld::UniversalId::Type_None // end marker
};

@ -44,7 +44,6 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
std::vector<std::string> CSVWorld::Table::listRevertableSelectedIds() const
{
/// \todo Do not use hardcoded column numbers
std::vector<std::string> revertableIds;
if (mProxyModel->columnCount()>0)
@ -62,7 +61,9 @@ std::vector<std::string> CSVWorld::Table::listRevertableSelectedIds() const
if (state!=CSMWorld::RecordBase::State_BaseOnly)
{
std::string id = mModel->data (mModel->index (index.row(), 0)).
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
std::string id = mModel->data (mModel->index (index.row(), columnIndex)).
toString().toUtf8().constData();
revertableIds.push_back (id);
@ -75,7 +76,6 @@ std::vector<std::string> CSVWorld::Table::listRevertableSelectedIds() const
std::vector<std::string> CSVWorld::Table::listDeletableSelectedIds() const
{
/// \todo Do not use hardcoded column numbers
std::vector<std::string> deletableIds;
if (mProxyModel->columnCount()>0)
@ -93,7 +93,9 @@ std::vector<std::string> CSVWorld::Table::listDeletableSelectedIds() const
if (state!=CSMWorld::RecordBase::State_Deleted)
{
std::string id = mModel->data (mModel->index (index.row(), 0)).
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
std::string id = mModel->data (mModel->index (index.row(), columnIndex)).
toString().toUtf8().constData();
deletableIds.push_back (id);
@ -263,8 +265,8 @@ void CSVWorld::Table::tableSizeUpdate()
{
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (i, 0));
/// \todo Do not use hardcoded column numbers
int state = mModel->data (mModel->index (index.row(), 1)).toInt();
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
int state = mModel->data (mModel->index (index.row(), columnIndex)).toInt();
switch (state)
{

@ -39,7 +39,7 @@ add_component_dir (esm
loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst
loadinfo loadingr loadland loadlevlist loadligh loadlock loadprob loadrepa loadltex loadmgef loadmisc loadnpcc
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
)
add_component_dir (misc

@ -0,0 +1,20 @@
#include "filter.hpp"
#include "esmreader.hpp"
#include "esmwriter.hpp"
void ESM::Filter::load (ESMReader& esm)
{
mFilter = esm.getHNString ("FILT");
}
void ESM::Filter::save (ESMWriter& esm)
{
esm.writeHNCString ("FILT", mFilter);
}
void ESM::Filter::blank()
{
mFilter.clear();
}

@ -0,0 +1,25 @@
#ifndef COMPONENTS_ESM_FILTER_H
#define COMPONENTS_ESM_FILTER_H
#include <string>
namespace ESM
{
class ESMReader;
class ESMWriter;
struct Filter
{
std::string mId;
std::string mFilter;
void load (ESMReader& esm);
void save (ESMWriter& esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif
Loading…
Cancel
Save