merge upstream changes

actorid
cc9cii 11 years ago
parent d780364842
commit 1ab5948f19

@ -1,127 +1,127 @@
#ifndef CSM_WOLRD_COLUMNBASE_H
#define CSM_WOLRD_COLUMNBASE_H
#include <string>
#include <Qt>
#include <QVariant>
#include "record.hpp"
namespace CSMWorld
{
struct ColumnBase
{
enum Roles
{
Role_Flags = Qt::UserRole,
Role_Display = Qt::UserRole+1
};
enum Flags
{
Flag_Table = 1, // column should be displayed in table view
Flag_Dialogue = 2 // column should be displayed in dialogue view
};
enum Display
{
Display_None, //Do not use
Display_String,
//CONCRETE TYPES STARTS HERE
Display_Skill,
Display_Class,
Display_Faction,
Display_Race,
Display_Sound,
Display_Region,
Display_Birthsign,
Display_Spell,
Display_Cell,
Display_Referenceable,
Display_Activator,
Display_Potion,
Display_Apparatus,
Display_Armor,
Display_Book,
Display_Clothing,
Display_Container,
Display_Creature,
Display_Door,
Display_Ingredient,
Display_CreatureLevelledList,
Display_ItemLevelledList,
Display_Light,
Display_Lockpick,
Display_Miscellaneous,
Display_Npc,
Display_Probe,
Display_Repair,
Display_Static,
Display_Weapon,
Display_Reference,
Display_Filter,
Display_Topic,
Display_Journal,
Display_TopicInfo,
Display_JournalInfo,
Display_Scene,
//CONCRETE TYPES ENDS HERE
Display_Integer,
Display_Float,
Display_Var,
Display_GmstVarType,
Display_GlobalVarType,
Display_Specialisation,
Display_Attribute,
Display_Boolean,
Display_SpellType,
Display_Script,
Display_ApparatusType,
Display_ArmorType,
Display_ClothingType,
Display_CreatureType,
Display_WeaponType,
Display_RecordState,
Display_RefRecordType,
Display_DialogueType,
Display_QuestStatusType,
Display_Gender
};
int mColumnId;
int mFlags;
Display mDisplayType;
ColumnBase (int columnId, Display displayType, int flag);
virtual ~ColumnBase();
virtual bool isEditable() const = 0;
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
{
int mFlags;
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 " + getTitle() + " is not editable");
}
};
}
#endif
#ifndef CSM_WOLRD_COLUMNBASE_H
#define CSM_WOLRD_COLUMNBASE_H
#include <string>
#include <Qt>
#include <QVariant>
#include "record.hpp"
namespace CSMWorld
{
struct ColumnBase
{
enum Roles
{
Role_Flags = Qt::UserRole,
Role_Display = Qt::UserRole+1
};
enum Flags
{
Flag_Table = 1, // column should be displayed in table view
Flag_Dialogue = 2 // column should be displayed in dialogue view
};
enum Display
{
Display_None, //Do not use
Display_String,
//CONCRETE TYPES STARTS HERE
Display_Skill,
Display_Class,
Display_Faction,
Display_Race,
Display_Sound,
Display_Region,
Display_Birthsign,
Display_Spell,
Display_Cell,
Display_Referenceable,
Display_Activator,
Display_Potion,
Display_Apparatus,
Display_Armor,
Display_Book,
Display_Clothing,
Display_Container,
Display_Creature,
Display_Door,
Display_Ingredient,
Display_CreatureLevelledList,
Display_ItemLevelledList,
Display_Light,
Display_Lockpick,
Display_Miscellaneous,
Display_Npc,
Display_Probe,
Display_Repair,
Display_Static,
Display_Weapon,
Display_Reference,
Display_Filter,
Display_Topic,
Display_Journal,
Display_TopicInfo,
Display_JournalInfo,
Display_Scene,
//CONCRETE TYPES ENDS HERE
Display_Integer,
Display_Float,
Display_Var,
Display_GmstVarType,
Display_GlobalVarType,
Display_Specialisation,
Display_Attribute,
Display_Boolean,
Display_SpellType,
Display_Script,
Display_ApparatusType,
Display_ArmorType,
Display_ClothingType,
Display_CreatureType,
Display_WeaponType,
Display_RecordState,
Display_RefRecordType,
Display_DialogueType,
Display_QuestStatusType,
Display_Gender
};
int mColumnId;
int mFlags;
Display mDisplayType;
ColumnBase (int columnId, Display displayType, int flag);
virtual ~ColumnBase();
virtual bool isEditable() const = 0;
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
{
int mFlags;
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 " + getTitle() + " is not editable");
}
};
}
#endif

@ -1,446 +1,446 @@
#include "tablemimedata.hpp"
#include <string>
#include "universalid.hpp"
#include "columnbase.hpp"
CSMWorld::TableMimeData::TableMimeData (UniversalId id, const CSMDoc::Document& document) :
mDocument(document)
{
mUniversalId.push_back (id);
mObjectsFormats << QString::fromStdString ("tabledata/" + id.getTypeName());
}
CSMWorld::TableMimeData::TableMimeData (std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) :
mUniversalId (id), mDocument(document)
{
for (std::vector<UniversalId>::iterator it (mUniversalId.begin()); it != mUniversalId.end(); ++it)
{
mObjectsFormats << QString::fromStdString ("tabledata/" + it->getTypeName());
}
}
QStringList CSMWorld::TableMimeData::formats() const
{
return mObjectsFormats;
}
CSMWorld::TableMimeData::~TableMimeData()
{
}
std::string CSMWorld::TableMimeData::getIcon() const
{
if (mUniversalId.empty())
{
throw ("TableMimeData holds no UniversalId");
}
std::string tmpIcon;
bool firstIteration = true;
for (unsigned i = 0; i < mUniversalId.size(); ++i)
{
if (firstIteration)
{
firstIteration = false;
tmpIcon = mUniversalId[i].getIcon();
continue;
}
if (tmpIcon != mUniversalId[i].getIcon())
{
return ":/multitype.png"; //icon stolen from gnome
}
tmpIcon = mUniversalId[i].getIcon();
}
return mUniversalId.begin()->getIcon(); //All objects are of the same type;
}
std::vector< CSMWorld::UniversalId > CSMWorld::TableMimeData::getData() const
{
return mUniversalId;
}
bool CSMWorld::TableMimeData::holdsType (CSMWorld::UniversalId::Type type) const
{
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
{
if (it->getType() == type)
{
return true;
}
}
return false;
}
bool CSMWorld::TableMimeData::holdsType (CSMWorld::ColumnBase::Display type) const
{
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
{
if (it->getType() == convertEnums (type))
{
return true;
}
}
return false;
}
CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::UniversalId::Type type) const
{
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
{
if (it->getType() == type)
{
return *it;
}
}
throw ("TableMimeData object does not hold object of the seeked type");
}
CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::ColumnBase::Display type) const
{
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
{
if (it->getType() == convertEnums (type))
{
return *it;
}
}
throw ("TableMimeData object does not hold object of the seeked type");
}
bool CSMWorld::TableMimeData::fromDocument (const CSMDoc::Document& document) const
{
return &document == &mDocument;
}
CSMWorld::UniversalId::Type CSMWorld::TableMimeData::convertEnums (CSMWorld::ColumnBase::Display type)
{
switch (type)
{
case CSMWorld::ColumnBase::Display_Race:
return CSMWorld::UniversalId::Type_Race;
case CSMWorld::ColumnBase::Display_Skill:
return CSMWorld::UniversalId::Type_Skill;
case CSMWorld::ColumnBase::Display_Class:
return CSMWorld::UniversalId::Type_Class;
case CSMWorld::ColumnBase::Display_Faction:
return CSMWorld::UniversalId::Type_Faction;
case CSMWorld::ColumnBase::Display_Sound:
return CSMWorld::UniversalId::Type_Sound;
case CSMWorld::ColumnBase::Display_Region:
return CSMWorld::UniversalId::Type_Region;
case CSMWorld::ColumnBase::Display_Birthsign:
return CSMWorld::UniversalId::Type_Birthsign;
case CSMWorld::ColumnBase::Display_Spell:
return CSMWorld::UniversalId::Type_Spell;
case CSMWorld::ColumnBase::Display_Cell:
return CSMWorld::UniversalId::Type_Cell;
case CSMWorld::ColumnBase::Display_Referenceable:
return CSMWorld::UniversalId::Type_Referenceable;
case CSMWorld::ColumnBase::Display_Activator:
return CSMWorld::UniversalId::Type_Activator;
case CSMWorld::ColumnBase::Display_Potion:
return CSMWorld::UniversalId::Type_Potion;
case CSMWorld::ColumnBase::Display_Apparatus:
return CSMWorld::UniversalId::Type_Apparatus;
case CSMWorld::ColumnBase::Display_Armor:
return CSMWorld::UniversalId::Type_Armor;
case CSMWorld::ColumnBase::Display_Book:
return CSMWorld::UniversalId::Type_Book;
case CSMWorld::ColumnBase::Display_Clothing:
return CSMWorld::UniversalId::Type_Clothing;
case CSMWorld::ColumnBase::Display_Container:
return CSMWorld::UniversalId::Type_Container;
case CSMWorld::ColumnBase::Display_Creature:
return CSMWorld::UniversalId::Type_Creature;
case CSMWorld::ColumnBase::Display_Door:
return CSMWorld::UniversalId::Type_Door;
case CSMWorld::ColumnBase::Display_Ingredient:
return CSMWorld::UniversalId::Type_Ingredient;
case CSMWorld::ColumnBase::Display_CreatureLevelledList:
return CSMWorld::UniversalId::Type_CreatureLevelledList;
case CSMWorld::ColumnBase::Display_ItemLevelledList:
return CSMWorld::UniversalId::Type_ItemLevelledList;
case CSMWorld::ColumnBase::Display_Light:
return CSMWorld::UniversalId::Type_Light;
case CSMWorld::ColumnBase::Display_Lockpick:
return CSMWorld::UniversalId::Type_Lockpick;
case CSMWorld::ColumnBase::Display_Miscellaneous:
return CSMWorld::UniversalId::Type_Miscellaneous;
case CSMWorld::ColumnBase::Display_Npc:
return CSMWorld::UniversalId::Type_Npc;
case CSMWorld::ColumnBase::Display_Probe:
return CSMWorld::UniversalId::Type_Probe;
case CSMWorld::ColumnBase::Display_Repair:
return CSMWorld::UniversalId::Type_Repair;
case CSMWorld::ColumnBase::Display_Static:
return CSMWorld::UniversalId::Type_Static;
case CSMWorld::ColumnBase::Display_Weapon:
return CSMWorld::UniversalId::Type_Weapon;
case CSMWorld::ColumnBase::Display_Reference:
return CSMWorld::UniversalId::Type_Reference;
case CSMWorld::ColumnBase::Display_Filter:
return CSMWorld::UniversalId::Type_Filter;
case CSMWorld::ColumnBase::Display_Topic:
return CSMWorld::UniversalId::Type_Topic;
case CSMWorld::ColumnBase::Display_Journal:
return CSMWorld::UniversalId::Type_Journal;
case CSMWorld::ColumnBase::Display_TopicInfo:
return CSMWorld::UniversalId::Type_TopicInfo;
case CSMWorld::ColumnBase::Display_JournalInfo:
return CSMWorld::UniversalId::Type_JournalInfo;
case CSMWorld::ColumnBase::Display_Scene:
return CSMWorld::UniversalId::Type_Scene;
case CSMWorld::ColumnBase::Display_Script:
return CSMWorld::UniversalId::Type_Script;
default:
return CSMWorld::UniversalId::Type_None;
}
}
CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (CSMWorld::UniversalId::Type type)
{
switch (type)
{
case CSMWorld::UniversalId::Type_Race:
return CSMWorld::ColumnBase::Display_Race;
case CSMWorld::UniversalId::Type_Skill:
return CSMWorld::ColumnBase::Display_Skill;
case CSMWorld::UniversalId::Type_Class:
return CSMWorld::ColumnBase::Display_Class;
case CSMWorld::UniversalId::Type_Faction:
return CSMWorld::ColumnBase::Display_Faction;
case CSMWorld::UniversalId::Type_Sound:
return CSMWorld::ColumnBase::Display_Sound;
case CSMWorld::UniversalId::Type_Region:
return CSMWorld::ColumnBase::Display_Region;
case CSMWorld::UniversalId::Type_Birthsign:
return CSMWorld::ColumnBase::Display_Birthsign;
case CSMWorld::UniversalId::Type_Spell:
return CSMWorld::ColumnBase::Display_Spell;
case CSMWorld::UniversalId::Type_Cell:
return CSMWorld::ColumnBase::Display_Cell;
case CSMWorld::UniversalId::Type_Referenceable:
return CSMWorld::ColumnBase::Display_Referenceable;
case CSMWorld::UniversalId::Type_Activator:
return CSMWorld::ColumnBase::Display_Activator;
case CSMWorld::UniversalId::Type_Potion:
return CSMWorld::ColumnBase::Display_Potion;
case CSMWorld::UniversalId::Type_Apparatus:
return CSMWorld::ColumnBase::Display_Apparatus;
case CSMWorld::UniversalId::Type_Armor:
return CSMWorld::ColumnBase::Display_Armor;
case CSMWorld::UniversalId::Type_Book:
return CSMWorld::ColumnBase::Display_Book;
case CSMWorld::UniversalId::Type_Clothing:
return CSMWorld::ColumnBase::Display_Clothing;
case CSMWorld::UniversalId::Type_Container:
return CSMWorld::ColumnBase::Display_Container;
case CSMWorld::UniversalId::Type_Creature:
return CSMWorld::ColumnBase::Display_Creature;
case CSMWorld::UniversalId::Type_Door:
return CSMWorld::ColumnBase::Display_Door;
case CSMWorld::UniversalId::Type_Ingredient:
return CSMWorld::ColumnBase::Display_Ingredient;
case CSMWorld::UniversalId::Type_CreatureLevelledList:
return CSMWorld::ColumnBase::Display_CreatureLevelledList;
case CSMWorld::UniversalId::Type_ItemLevelledList:
return CSMWorld::ColumnBase::Display_ItemLevelledList;
case CSMWorld::UniversalId::Type_Light:
return CSMWorld::ColumnBase::Display_Light;
case CSMWorld::UniversalId::Type_Lockpick:
return CSMWorld::ColumnBase::Display_Lockpick;
case CSMWorld::UniversalId::Type_Miscellaneous:
return CSMWorld::ColumnBase::Display_Miscellaneous;
case CSMWorld::UniversalId::Type_Npc:
return CSMWorld::ColumnBase::Display_Npc;
case CSMWorld::UniversalId::Type_Probe:
return CSMWorld::ColumnBase::Display_Probe;
case CSMWorld::UniversalId::Type_Repair:
return CSMWorld::ColumnBase::Display_Repair;
case CSMWorld::UniversalId::Type_Static:
return CSMWorld::ColumnBase::Display_Static;
case CSMWorld::UniversalId::Type_Weapon:
return CSMWorld::ColumnBase::Display_Weapon;
case CSMWorld::UniversalId::Type_Reference:
return CSMWorld::ColumnBase::Display_Reference;
case CSMWorld::UniversalId::Type_Filter:
return CSMWorld::ColumnBase::Display_Filter;
case CSMWorld::UniversalId::Type_Topic:
return CSMWorld::ColumnBase::Display_Topic;
case CSMWorld::UniversalId::Type_Journal:
return CSMWorld::ColumnBase::Display_Journal;
case CSMWorld::UniversalId::Type_TopicInfo:
return CSMWorld::ColumnBase::Display_TopicInfo;
case CSMWorld::UniversalId::Type_JournalInfo:
return CSMWorld::ColumnBase::Display_JournalInfo;
case CSMWorld::UniversalId::Type_Scene:
return CSMWorld::ColumnBase::Display_Scene;
case CSMWorld::UniversalId::Type_Script:
return CSMWorld::ColumnBase::Display_Script;
default:
return CSMWorld::ColumnBase::Display_None;
}
#include "tablemimedata.hpp"
#include <string>
#include "universalid.hpp"
#include "columnbase.hpp"
CSMWorld::TableMimeData::TableMimeData (UniversalId id, const CSMDoc::Document& document) :
mDocument(document)
{
mUniversalId.push_back (id);
mObjectsFormats << QString::fromStdString ("tabledata/" + id.getTypeName());
}
CSMWorld::TableMimeData::TableMimeData (std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) :
mUniversalId (id), mDocument(document)
{
for (std::vector<UniversalId>::iterator it (mUniversalId.begin()); it != mUniversalId.end(); ++it)
{
mObjectsFormats << QString::fromStdString ("tabledata/" + it->getTypeName());
}
}
QStringList CSMWorld::TableMimeData::formats() const
{
return mObjectsFormats;
}
CSMWorld::TableMimeData::~TableMimeData()
{
}
std::string CSMWorld::TableMimeData::getIcon() const
{
if (mUniversalId.empty())
{
throw ("TableMimeData holds no UniversalId");
}
std::string tmpIcon;
bool firstIteration = true;
for (unsigned i = 0; i < mUniversalId.size(); ++i)
{
if (firstIteration)
{
firstIteration = false;
tmpIcon = mUniversalId[i].getIcon();
continue;
}
if (tmpIcon != mUniversalId[i].getIcon())
{
return ":/multitype.png"; //icon stolen from gnome
}
tmpIcon = mUniversalId[i].getIcon();
}
return mUniversalId.begin()->getIcon(); //All objects are of the same type;
}
std::vector< CSMWorld::UniversalId > CSMWorld::TableMimeData::getData() const
{
return mUniversalId;
}
bool CSMWorld::TableMimeData::holdsType (CSMWorld::UniversalId::Type type) const
{
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
{
if (it->getType() == type)
{
return true;
}
}
return false;
}
bool CSMWorld::TableMimeData::holdsType (CSMWorld::ColumnBase::Display type) const
{
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
{
if (it->getType() == convertEnums (type))
{
return true;
}
}
return false;
}
CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::UniversalId::Type type) const
{
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
{
if (it->getType() == type)
{
return *it;
}
}
throw ("TableMimeData object does not hold object of the seeked type");
}
CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::ColumnBase::Display type) const
{
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
{
if (it->getType() == convertEnums (type))
{
return *it;
}
}
throw ("TableMimeData object does not hold object of the seeked type");
}
bool CSMWorld::TableMimeData::fromDocument (const CSMDoc::Document& document) const
{
return &document == &mDocument;
}
CSMWorld::UniversalId::Type CSMWorld::TableMimeData::convertEnums (CSMWorld::ColumnBase::Display type)
{
switch (type)
{
case CSMWorld::ColumnBase::Display_Race:
return CSMWorld::UniversalId::Type_Race;
case CSMWorld::ColumnBase::Display_Skill:
return CSMWorld::UniversalId::Type_Skill;
case CSMWorld::ColumnBase::Display_Class:
return CSMWorld::UniversalId::Type_Class;
case CSMWorld::ColumnBase::Display_Faction:
return CSMWorld::UniversalId::Type_Faction;
case CSMWorld::ColumnBase::Display_Sound:
return CSMWorld::UniversalId::Type_Sound;
case CSMWorld::ColumnBase::Display_Region:
return CSMWorld::UniversalId::Type_Region;
case CSMWorld::ColumnBase::Display_Birthsign:
return CSMWorld::UniversalId::Type_Birthsign;
case CSMWorld::ColumnBase::Display_Spell:
return CSMWorld::UniversalId::Type_Spell;
case CSMWorld::ColumnBase::Display_Cell:
return CSMWorld::UniversalId::Type_Cell;
case CSMWorld::ColumnBase::Display_Referenceable:
return CSMWorld::UniversalId::Type_Referenceable;
case CSMWorld::ColumnBase::Display_Activator:
return CSMWorld::UniversalId::Type_Activator;
case CSMWorld::ColumnBase::Display_Potion:
return CSMWorld::UniversalId::Type_Potion;
case CSMWorld::ColumnBase::Display_Apparatus:
return CSMWorld::UniversalId::Type_Apparatus;
case CSMWorld::ColumnBase::Display_Armor:
return CSMWorld::UniversalId::Type_Armor;
case CSMWorld::ColumnBase::Display_Book:
return CSMWorld::UniversalId::Type_Book;
case CSMWorld::ColumnBase::Display_Clothing:
return CSMWorld::UniversalId::Type_Clothing;
case CSMWorld::ColumnBase::Display_Container:
return CSMWorld::UniversalId::Type_Container;
case CSMWorld::ColumnBase::Display_Creature:
return CSMWorld::UniversalId::Type_Creature;
case CSMWorld::ColumnBase::Display_Door:
return CSMWorld::UniversalId::Type_Door;
case CSMWorld::ColumnBase::Display_Ingredient:
return CSMWorld::UniversalId::Type_Ingredient;
case CSMWorld::ColumnBase::Display_CreatureLevelledList:
return CSMWorld::UniversalId::Type_CreatureLevelledList;
case CSMWorld::ColumnBase::Display_ItemLevelledList:
return CSMWorld::UniversalId::Type_ItemLevelledList;
case CSMWorld::ColumnBase::Display_Light:
return CSMWorld::UniversalId::Type_Light;
case CSMWorld::ColumnBase::Display_Lockpick:
return CSMWorld::UniversalId::Type_Lockpick;
case CSMWorld::ColumnBase::Display_Miscellaneous:
return CSMWorld::UniversalId::Type_Miscellaneous;
case CSMWorld::ColumnBase::Display_Npc:
return CSMWorld::UniversalId::Type_Npc;
case CSMWorld::ColumnBase::Display_Probe:
return CSMWorld::UniversalId::Type_Probe;
case CSMWorld::ColumnBase::Display_Repair:
return CSMWorld::UniversalId::Type_Repair;
case CSMWorld::ColumnBase::Display_Static:
return CSMWorld::UniversalId::Type_Static;
case CSMWorld::ColumnBase::Display_Weapon:
return CSMWorld::UniversalId::Type_Weapon;
case CSMWorld::ColumnBase::Display_Reference:
return CSMWorld::UniversalId::Type_Reference;
case CSMWorld::ColumnBase::Display_Filter:
return CSMWorld::UniversalId::Type_Filter;
case CSMWorld::ColumnBase::Display_Topic:
return CSMWorld::UniversalId::Type_Topic;
case CSMWorld::ColumnBase::Display_Journal:
return CSMWorld::UniversalId::Type_Journal;
case CSMWorld::ColumnBase::Display_TopicInfo:
return CSMWorld::UniversalId::Type_TopicInfo;
case CSMWorld::ColumnBase::Display_JournalInfo:
return CSMWorld::UniversalId::Type_JournalInfo;
case CSMWorld::ColumnBase::Display_Scene:
return CSMWorld::UniversalId::Type_Scene;
case CSMWorld::ColumnBase::Display_Script:
return CSMWorld::UniversalId::Type_Script;
default:
return CSMWorld::UniversalId::Type_None;
}
}
CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (CSMWorld::UniversalId::Type type)
{
switch (type)
{
case CSMWorld::UniversalId::Type_Race:
return CSMWorld::ColumnBase::Display_Race;
case CSMWorld::UniversalId::Type_Skill:
return CSMWorld::ColumnBase::Display_Skill;
case CSMWorld::UniversalId::Type_Class:
return CSMWorld::ColumnBase::Display_Class;
case CSMWorld::UniversalId::Type_Faction:
return CSMWorld::ColumnBase::Display_Faction;
case CSMWorld::UniversalId::Type_Sound:
return CSMWorld::ColumnBase::Display_Sound;
case CSMWorld::UniversalId::Type_Region:
return CSMWorld::ColumnBase::Display_Region;
case CSMWorld::UniversalId::Type_Birthsign:
return CSMWorld::ColumnBase::Display_Birthsign;
case CSMWorld::UniversalId::Type_Spell:
return CSMWorld::ColumnBase::Display_Spell;
case CSMWorld::UniversalId::Type_Cell:
return CSMWorld::ColumnBase::Display_Cell;
case CSMWorld::UniversalId::Type_Referenceable:
return CSMWorld::ColumnBase::Display_Referenceable;
case CSMWorld::UniversalId::Type_Activator:
return CSMWorld::ColumnBase::Display_Activator;
case CSMWorld::UniversalId::Type_Potion:
return CSMWorld::ColumnBase::Display_Potion;
case CSMWorld::UniversalId::Type_Apparatus:
return CSMWorld::ColumnBase::Display_Apparatus;
case CSMWorld::UniversalId::Type_Armor:
return CSMWorld::ColumnBase::Display_Armor;
case CSMWorld::UniversalId::Type_Book:
return CSMWorld::ColumnBase::Display_Book;
case CSMWorld::UniversalId::Type_Clothing:
return CSMWorld::ColumnBase::Display_Clothing;
case CSMWorld::UniversalId::Type_Container:
return CSMWorld::ColumnBase::Display_Container;
case CSMWorld::UniversalId::Type_Creature:
return CSMWorld::ColumnBase::Display_Creature;
case CSMWorld::UniversalId::Type_Door:
return CSMWorld::ColumnBase::Display_Door;
case CSMWorld::UniversalId::Type_Ingredient:
return CSMWorld::ColumnBase::Display_Ingredient;
case CSMWorld::UniversalId::Type_CreatureLevelledList:
return CSMWorld::ColumnBase::Display_CreatureLevelledList;
case CSMWorld::UniversalId::Type_ItemLevelledList:
return CSMWorld::ColumnBase::Display_ItemLevelledList;
case CSMWorld::UniversalId::Type_Light:
return CSMWorld::ColumnBase::Display_Light;
case CSMWorld::UniversalId::Type_Lockpick:
return CSMWorld::ColumnBase::Display_Lockpick;
case CSMWorld::UniversalId::Type_Miscellaneous:
return CSMWorld::ColumnBase::Display_Miscellaneous;
case CSMWorld::UniversalId::Type_Npc:
return CSMWorld::ColumnBase::Display_Npc;
case CSMWorld::UniversalId::Type_Probe:
return CSMWorld::ColumnBase::Display_Probe;
case CSMWorld::UniversalId::Type_Repair:
return CSMWorld::ColumnBase::Display_Repair;
case CSMWorld::UniversalId::Type_Static:
return CSMWorld::ColumnBase::Display_Static;
case CSMWorld::UniversalId::Type_Weapon:
return CSMWorld::ColumnBase::Display_Weapon;
case CSMWorld::UniversalId::Type_Reference:
return CSMWorld::ColumnBase::Display_Reference;
case CSMWorld::UniversalId::Type_Filter:
return CSMWorld::ColumnBase::Display_Filter;
case CSMWorld::UniversalId::Type_Topic:
return CSMWorld::ColumnBase::Display_Topic;
case CSMWorld::UniversalId::Type_Journal:
return CSMWorld::ColumnBase::Display_Journal;
case CSMWorld::UniversalId::Type_TopicInfo:
return CSMWorld::ColumnBase::Display_TopicInfo;
case CSMWorld::UniversalId::Type_JournalInfo:
return CSMWorld::ColumnBase::Display_JournalInfo;
case CSMWorld::UniversalId::Type_Scene:
return CSMWorld::ColumnBase::Display_Scene;
case CSMWorld::UniversalId::Type_Script:
return CSMWorld::ColumnBase::Display_Script;
default:
return CSMWorld::ColumnBase::Display_None;
}
}

@ -1,63 +1,63 @@
#ifndef TABLEMIMEDATA_H
#define TABLEMIMEDATA_H
#include <vector>
#include <QtCore/QMimeData>
#include <QStringList>
#include "universalid.hpp"
#include "columnbase.hpp"
namespace CSMDoc
{
class Document;
}
namespace CSMWorld
{
/// \brief Subclass of QmimeData, augmented to contain and transport UniversalIds.
///
/// This class provides way to construct mimedata object holding the universalid copy
/// Universalid is used in the majority of the tables to store type, id, argument types.
/// This way universalid grants a way to retrive record from the concrete table.
/// Please note, that tablemimedata object can hold multiple universalIds in the vector.
class TableMimeData : public QMimeData
{
public:
TableMimeData(UniversalId id, const CSMDoc::Document& document);
TableMimeData(std::vector<UniversalId>& id, const CSMDoc::Document& document);
~TableMimeData();
virtual QStringList formats() const;
std::string getIcon() const;
std::vector<UniversalId> getData() const;
bool holdsType(UniversalId::Type type) const;
bool holdsType(CSMWorld::ColumnBase::Display type) const;
bool fromDocument(const CSMDoc::Document& document) const;
UniversalId returnMatching(UniversalId::Type type) const;
UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const;
static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type);
static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type);
private:
std::vector<UniversalId> mUniversalId;
QStringList mObjectsFormats;
const CSMDoc::Document& mDocument;
};
}
#ifndef TABLEMIMEDATA_H
#define TABLEMIMEDATA_H
#include <vector>
#include <QtCore/QMimeData>
#include <QStringList>
#include "universalid.hpp"
#include "columnbase.hpp"
namespace CSMDoc
{
class Document;
}
namespace CSMWorld
{
/// \brief Subclass of QmimeData, augmented to contain and transport UniversalIds.
///
/// This class provides way to construct mimedata object holding the universalid copy
/// Universalid is used in the majority of the tables to store type, id, argument types.
/// This way universalid grants a way to retrive record from the concrete table.
/// Please note, that tablemimedata object can hold multiple universalIds in the vector.
class TableMimeData : public QMimeData
{
public:
TableMimeData(UniversalId id, const CSMDoc::Document& document);
TableMimeData(std::vector<UniversalId>& id, const CSMDoc::Document& document);
~TableMimeData();
virtual QStringList formats() const;
std::string getIcon() const;
std::vector<UniversalId> getData() const;
bool holdsType(UniversalId::Type type) const;
bool holdsType(CSMWorld::ColumnBase::Display type) const;
bool fromDocument(const CSMDoc::Document& document) const;
UniversalId returnMatching(UniversalId::Type type) const;
UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const;
static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type);
static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type);
private:
std::vector<UniversalId> mUniversalId;
QStringList mObjectsFormats;
const CSMDoc::Document& mDocument;
};
}
#endif // TABLEMIMEDATA_H

@ -1,203 +1,203 @@
#include "editwidget.hpp"
#include <QAbstractItemModel>
#include <QString>
#include <QApplication>
#include "../../model/world/data.hpp"
CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent)
: QLineEdit (parent), mParser (data)
{
mPalette = palette();
connect (this, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&)));
QAbstractItemModel *model = data.getTableModel (CSMWorld::UniversalId::Type_Filters);
connect (model, SIGNAL (dataChanged (const QModelIndex &, const QModelIndex&)),
this, SLOT (filterDataChanged (const QModelIndex &, const QModelIndex&)),
Qt::QueuedConnection);
connect (model, SIGNAL (rowsRemoved (const QModelIndex&, int, int)),
this, SLOT (filterRowsRemoved (const QModelIndex&, int, int)),
Qt::QueuedConnection);
connect (model, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (filterRowsInserted (const QModelIndex&, int, int)),
Qt::QueuedConnection);
}
void CSVFilter::EditWidget::textChanged (const QString& text)
{
if (mParser.parse (text.toUtf8().constData()))
{
setPalette (mPalette);
emit filterChanged (mParser.getFilter());
}
else
{
QPalette palette (mPalette);
palette.setColor (QPalette::Text, Qt::red);
setPalette (palette);
/// \todo improve error reporting; mark only the faulty part
}
}
void CSVFilter::EditWidget::filterDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{
textChanged (text());
}
void CSVFilter::EditWidget::filterRowsRemoved (const QModelIndex& parent, int start, int end)
{
textChanged (text());
}
void CSVFilter::EditWidget::filterRowsInserted (const QModelIndex& parent, int start, int end)
{
textChanged (text());
}
void CSVFilter::EditWidget::createFilterRequest (std::vector< std::pair< std::string, std::vector< std::string > > >& filterSource,
Qt::DropAction action)
{
const unsigned count = filterSource.size();
bool multipleElements = false;
switch (count) //setting multipleElements;
{
case 0: //empty
return; //nothing to do here
case 1: //only single
multipleElements = false;
break;
default:
multipleElements = true;
break;
}
Qt::KeyboardModifiers key = QApplication::keyboardModifiers();
QString oldContent (text());
bool replaceMode = false;
std::string orAnd;
switch (key) //setting replaceMode and string used to glue expressions
{
case Qt::ShiftModifier:
orAnd = "!or(";
replaceMode = false;
break;
case Qt::ControlModifier:
orAnd = "!and(";
replaceMode = false;
break;
default:
replaceMode = true;
break;
}
if (oldContent.isEmpty() || !oldContent.contains (QRegExp ("^!.*$", Qt::CaseInsensitive))) //if line edit is empty or it does not contain one shot filter go into replace mode
{
replaceMode = true;
}
if (!replaceMode)
{
oldContent.remove ('!');
}
std::stringstream ss;
if (multipleElements)
{
if (replaceMode)
{
ss<<"!or(";
} else {
ss << orAnd << oldContent.toStdString() << ',';
}
for (unsigned i = 0; i < count; ++i)
{
ss<<generateFilter (filterSource[i]);
if (i+1 != count)
{
ss<<", ";
}
}
ss<<')';
} else {
if (!replaceMode)
{
ss << orAnd << oldContent.toStdString() <<',';
} else {
ss<<'!';
}
ss << generateFilter (filterSource[0]);
if (!replaceMode)
{
ss<<')';
}
}
if (ss.str().length() >4)
{
clear();
insert (QString::fromUtf8(ss.str().c_str()));
}
}
std::string CSVFilter::EditWidget::generateFilter (std::pair< std::string, std::vector< std::string > >& seekedString) const
{
const unsigned columns = seekedString.second.size();
bool multipleColumns = false;
switch (columns)
{
case 0: //empty
return ""; //no column to filter
case 1: //one column to look for
multipleColumns = false;
break;
default:
multipleColumns = true;
break;
}
std::stringstream ss;
if (multipleColumns)
{
ss<<"or(";
for (unsigned i = 0; i < columns; ++i)
{
ss<<"string("<<'"'<<seekedString.second[i]<<'"'<<','<<'"'<<seekedString.first<<'"'<<')';
if (i+1 != columns)
ss<<',';
}
ss<<')';
} else {
ss<<"string"<<'('<<'"'<<seekedString.second[0]<<"\","<<'"'<<seekedString.first<<"\")";
}
return ss.str();
}
void CSVFilter::EditWidget::useFilterRequest (const std::string& idOfFilter)
{
clear();
insert(QString::fromUtf8(idOfFilter.c_str()));
}
#include "editwidget.hpp"
#include <QAbstractItemModel>
#include <QString>
#include <QApplication>
#include "../../model/world/data.hpp"
CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent)
: QLineEdit (parent), mParser (data)
{
mPalette = palette();
connect (this, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&)));
QAbstractItemModel *model = data.getTableModel (CSMWorld::UniversalId::Type_Filters);
connect (model, SIGNAL (dataChanged (const QModelIndex &, const QModelIndex&)),
this, SLOT (filterDataChanged (const QModelIndex &, const QModelIndex&)),
Qt::QueuedConnection);
connect (model, SIGNAL (rowsRemoved (const QModelIndex&, int, int)),
this, SLOT (filterRowsRemoved (const QModelIndex&, int, int)),
Qt::QueuedConnection);
connect (model, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (filterRowsInserted (const QModelIndex&, int, int)),
Qt::QueuedConnection);
}
void CSVFilter::EditWidget::textChanged (const QString& text)
{
if (mParser.parse (text.toUtf8().constData()))
{
setPalette (mPalette);
emit filterChanged (mParser.getFilter());
}
else
{
QPalette palette (mPalette);
palette.setColor (QPalette::Text, Qt::red);
setPalette (palette);
/// \todo improve error reporting; mark only the faulty part
}
}
void CSVFilter::EditWidget::filterDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{
textChanged (text());
}
void CSVFilter::EditWidget::filterRowsRemoved (const QModelIndex& parent, int start, int end)
{
textChanged (text());
}
void CSVFilter::EditWidget::filterRowsInserted (const QModelIndex& parent, int start, int end)
{
textChanged (text());
}
void CSVFilter::EditWidget::createFilterRequest (std::vector< std::pair< std::string, std::vector< std::string > > >& filterSource,
Qt::DropAction action)
{
const unsigned count = filterSource.size();
bool multipleElements = false;
switch (count) //setting multipleElements;
{
case 0: //empty
return; //nothing to do here
case 1: //only single
multipleElements = false;
break;
default:
multipleElements = true;
break;
}
Qt::KeyboardModifiers key = QApplication::keyboardModifiers();
QString oldContent (text());
bool replaceMode = false;
std::string orAnd;
switch (key) //setting replaceMode and string used to glue expressions
{
case Qt::ShiftModifier:
orAnd = "!or(";
replaceMode = false;
break;
case Qt::ControlModifier:
orAnd = "!and(";
replaceMode = false;
break;
default:
replaceMode = true;
break;
}
if (oldContent.isEmpty() || !oldContent.contains (QRegExp ("^!.*$", Qt::CaseInsensitive))) //if line edit is empty or it does not contain one shot filter go into replace mode
{
replaceMode = true;
}
if (!replaceMode)
{
oldContent.remove ('!');
}
std::stringstream ss;
if (multipleElements)
{
if (replaceMode)
{
ss<<"!or(";
} else {
ss << orAnd << oldContent.toStdString() << ',';
}
for (unsigned i = 0; i < count; ++i)
{
ss<<generateFilter (filterSource[i]);
if (i+1 != count)
{
ss<<", ";
}
}
ss<<')';
} else {
if (!replaceMode)
{
ss << orAnd << oldContent.toStdString() <<',';
} else {
ss<<'!';
}
ss << generateFilter (filterSource[0]);
if (!replaceMode)
{
ss<<')';
}
}
if (ss.str().length() >4)
{
clear();
insert (QString::fromUtf8(ss.str().c_str()));
}
}
std::string CSVFilter::EditWidget::generateFilter (std::pair< std::string, std::vector< std::string > >& seekedString) const
{
const unsigned columns = seekedString.second.size();
bool multipleColumns = false;
switch (columns)
{
case 0: //empty
return ""; //no column to filter
case 1: //one column to look for
multipleColumns = false;
break;
default:
multipleColumns = true;
break;
}
std::stringstream ss;
if (multipleColumns)
{
ss<<"or(";
for (unsigned i = 0; i < columns; ++i)
{
ss<<"string("<<'"'<<seekedString.second[i]<<'"'<<','<<'"'<<seekedString.first<<'"'<<')';
if (i+1 != columns)
ss<<',';
}
ss<<')';
} else {
ss<<"string"<<'('<<'"'<<seekedString.second[0]<<"\","<<'"'<<seekedString.first<<"\")";
}
return ss.str();
}
void CSVFilter::EditWidget::useFilterRequest (const std::string& idOfFilter)
{
clear();
insert(QString::fromUtf8(idOfFilter.c_str()));
}

@ -1,57 +1,57 @@
#ifndef CSV_FILTER_EDITWIDGET_H
#define CSV_FILTER_EDITWIDGET_H
#include <boost/shared_ptr.hpp>
#include <QLineEdit>
#include <QPalette>
#include <qt4/QtCore/qnamespace.h>
#include "../../model/filter/parser.hpp"
#include "../../model/filter/node.hpp"
class QModelIndex;
namespace CSMWorld
{
class Data;
}
namespace CSVFilter
{
class EditWidget : public QLineEdit
{
Q_OBJECT
CSMFilter::Parser mParser;
QPalette mPalette;
public:
EditWidget (CSMWorld::Data& data, QWidget *parent = 0);
signals:
void filterChanged (boost::shared_ptr<CSMFilter::Node> filter);
private:
std::string generateFilter(std::pair<std::string, std::vector<std::string> >& seekedString) const;
private slots:
void textChanged (const QString& text);
void filterDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void filterRowsRemoved (const QModelIndex& parent, int start, int end);
void filterRowsInserted (const QModelIndex& parent, int start, int end);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action);
void useFilterRequest(const std::string& idOfFilter);
};
}
#endif
#ifndef CSV_FILTER_EDITWIDGET_H
#define CSV_FILTER_EDITWIDGET_H
#include <boost/shared_ptr.hpp>
#include <QLineEdit>
#include <QPalette>
#include <qt4/QtCore/qnamespace.h>
#include "../../model/filter/parser.hpp"
#include "../../model/filter/node.hpp"
class QModelIndex;
namespace CSMWorld
{
class Data;
}
namespace CSVFilter
{
class EditWidget : public QLineEdit
{
Q_OBJECT
CSMFilter::Parser mParser;
QPalette mPalette;
public:
EditWidget (CSMWorld::Data& data, QWidget *parent = 0);
signals:
void filterChanged (boost::shared_ptr<CSMFilter::Node> filter);
private:
std::string generateFilter(std::pair<std::string, std::vector<std::string> >& seekedString) const;
private slots:
void textChanged (const QString& text);
void filterDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void filterRowsRemoved (const QModelIndex& parent, int start, int end);
void filterRowsInserted (const QModelIndex& parent, int start, int end);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action);
void useFilterRequest(const std::string& idOfFilter);
};
}
#endif

@ -1,50 +1,50 @@
#include "filterbox.hpp"
#include <QHBoxLayout>
#include <QDragEnterEvent>
#include "recordfilterbox.hpp"
#include <apps/opencs/model/world/tablemimedata.hpp>
CSVFilter::FilterBox::FilterBox (CSMWorld::Data& data, QWidget *parent)
: QWidget (parent)
{
QHBoxLayout *layout = new QHBoxLayout (this);
layout->setContentsMargins (0, 0, 0, 0);
RecordFilterBox *recordFilterBox = new RecordFilterBox (data, this);
layout->addWidget (recordFilterBox);
setLayout (layout);
connect (recordFilterBox,
SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)),
this, SIGNAL (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)));
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)),
recordFilterBox, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
connect(this, SIGNAL(useFilterRequest(const std::string&)), recordFilterBox, SIGNAL(useFilterRequest(const std::string&)));
setAcceptDrops(true);
}
void CSVFilter::FilterBox::dropEvent (QDropEvent* event)
{
std::vector<CSMWorld::UniversalId> data = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData())->getData();
emit recordDropped(data, event->proposedAction());
}
void CSVFilter::FilterBox::dragEnterEvent (QDragEnterEvent* event)
{
event->acceptProposedAction();
}
void CSVFilter::FilterBox::dragMoveEvent (QDragMoveEvent* event)
{
event->accept();
}
#include "filterbox.hpp"
#include <QHBoxLayout>
#include <QDragEnterEvent>
#include "recordfilterbox.hpp"
#include <apps/opencs/model/world/tablemimedata.hpp>
CSVFilter::FilterBox::FilterBox (CSMWorld::Data& data, QWidget *parent)
: QWidget (parent)
{
QHBoxLayout *layout = new QHBoxLayout (this);
layout->setContentsMargins (0, 0, 0, 0);
RecordFilterBox *recordFilterBox = new RecordFilterBox (data, this);
layout->addWidget (recordFilterBox);
setLayout (layout);
connect (recordFilterBox,
SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)),
this, SIGNAL (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)));
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)),
recordFilterBox, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
connect(this, SIGNAL(useFilterRequest(const std::string&)), recordFilterBox, SIGNAL(useFilterRequest(const std::string&)));
setAcceptDrops(true);
}
void CSVFilter::FilterBox::dropEvent (QDropEvent* event)
{
std::vector<CSMWorld::UniversalId> data = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData())->getData();
emit recordDropped(data, event->proposedAction());
}
void CSVFilter::FilterBox::dragEnterEvent (QDragEnterEvent* event)
{
event->acceptProposedAction();
}
void CSVFilter::FilterBox::dragMoveEvent (QDragMoveEvent* event)
{
event->accept();
}

@ -1,45 +1,45 @@
#ifndef CSV_FILTER_FILTERBOX_H
#define CSV_FILTER_FILTERBOX_H
#include <vector>
#include <QWidget>
#include <qt4/QtCore/qnamespace.h>
#include "../../model/filter/node.hpp"
#include "../../model/world/universalid.hpp"
namespace CSMWorld
{
class Data;
}
namespace CSVFilter
{
class FilterBox : public QWidget
{
Q_OBJECT
void dragEnterEvent (QDragEnterEvent* event);
void dropEvent (QDropEvent* event);
void dragMoveEvent(QDragMoveEvent *event);
public:
FilterBox (CSMWorld::Data& data, QWidget *parent = 0);
signals:
void recordFilterChanged (boost::shared_ptr<CSMFilter::Node> filter);
void recordDropped (std::vector<CSMWorld::UniversalId>& types, Qt::DropAction action);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action);
void useFilterRequest(const std::string& idOfFilter);
};
}
#endif
#ifndef CSV_FILTER_FILTERBOX_H
#define CSV_FILTER_FILTERBOX_H
#include <vector>
#include <QWidget>
#include <qt4/QtCore/qnamespace.h>
#include "../../model/filter/node.hpp"
#include "../../model/world/universalid.hpp"
namespace CSMWorld
{
class Data;
}
namespace CSVFilter
{
class FilterBox : public QWidget
{
Q_OBJECT
void dragEnterEvent (QDragEnterEvent* event);
void dropEvent (QDropEvent* event);
void dragMoveEvent(QDragMoveEvent *event);
public:
FilterBox (CSMWorld::Data& data, QWidget *parent = 0);
signals:
void recordFilterChanged (boost::shared_ptr<CSMFilter::Node> filter);
void recordDropped (std::vector<CSMWorld::UniversalId>& types, Qt::DropAction action);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action);
void useFilterRequest(const std::string& idOfFilter);
};
}
#endif

@ -1,32 +1,32 @@
#include "recordfilterbox.hpp"
#include <QHBoxLayout>
#include <QLabel>
#include "editwidget.hpp"
CSVFilter::RecordFilterBox::RecordFilterBox (CSMWorld::Data& data, QWidget *parent)
: QWidget (parent)
{
QHBoxLayout *layout = new QHBoxLayout (this);
layout->setContentsMargins (0, 0, 0, 0);
layout->addWidget (new QLabel ("Record Filter", this));
EditWidget *editWidget = new EditWidget (data, this);
layout->addWidget (editWidget);
setLayout (layout);
connect (
editWidget, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)),
this, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)));
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)),
editWidget, SLOT(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
connect(this, SIGNAL(useFilterRequest(const std::string&)), editWidget, SLOT(useFilterRequest(const std::string&)));
}
#include "recordfilterbox.hpp"
#include <QHBoxLayout>
#include <QLabel>
#include "editwidget.hpp"
CSVFilter::RecordFilterBox::RecordFilterBox (CSMWorld::Data& data, QWidget *parent)
: QWidget (parent)
{
QHBoxLayout *layout = new QHBoxLayout (this);
layout->setContentsMargins (0, 0, 0, 0);
layout->addWidget (new QLabel ("Record Filter", this));
EditWidget *editWidget = new EditWidget (data, this);
layout->addWidget (editWidget);
setLayout (layout);
connect (
editWidget, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)),
this, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)));
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)),
editWidget, SLOT(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
connect(this, SIGNAL(useFilterRequest(const std::string&)), editWidget, SLOT(useFilterRequest(const std::string&)));
}

@ -1,38 +1,38 @@
#ifndef CSV_FILTER_RECORDFILTERBOX_H
#define CSV_FILTER_RECORDFILTERBOX_H
#include <boost/shared_ptr.hpp>
#include <QWidget>
#include <qt4/QtCore/qnamespace.h>
#include <QHBoxLayout>
#include "../../model/filter/node.hpp"
namespace CSMWorld
{
class Data;
}
namespace CSVFilter
{
class RecordFilterBox : public QWidget
{
Q_OBJECT
public:
RecordFilterBox (CSMWorld::Data& data, QWidget *parent = 0);
signals:
void filterChanged (boost::shared_ptr<CSMFilter::Node> filter);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action);
void useFilterRequest(const std::string& idOfFilter);
};
}
#ifndef CSV_FILTER_RECORDFILTERBOX_H
#define CSV_FILTER_RECORDFILTERBOX_H
#include <boost/shared_ptr.hpp>
#include <QWidget>
#include <qt4/QtCore/qnamespace.h>
#include <QHBoxLayout>
#include "../../model/filter/node.hpp"
namespace CSMWorld
{
class Data;
}
namespace CSVFilter
{
class RecordFilterBox : public QWidget
{
Q_OBJECT
public:
RecordFilterBox (CSMWorld::Data& data, QWidget *parent = 0);
signals:
void filterChanged (boost::shared_ptr<CSMFilter::Node> filter);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action);
void useFilterRequest(const std::string& idOfFilter);
};
}
#endif

File diff suppressed because it is too large Load Diff

@ -1,127 +1,127 @@
#ifndef CSV_WORLD_TABLE_H
#define CSV_WORLD_TABLE_H
#include <vector>
#include <string>
#include <QTableView>
#include <QtGui/qevent.h>
#include "../../model/filter/node.hpp"
#include "../../model/world/columnbase.hpp"
namespace CSMDoc {
class Document;
}
class QUndoStack;
class QAction;
namespace CSMWorld
{
class Data;
class UniversalId;
class IdTableProxyModel;
class IdTable;
}
namespace CSVWorld
{
class CommandDelegate;
///< Table widget
class Table : public QTableView
{
Q_OBJECT
std::vector<CommandDelegate *> mDelegates;
QUndoStack& mUndoStack;
QAction *mEditAction;
QAction *mCreateAction;
QAction *mCloneAction;
QAction *mRevertAction;
QAction *mDeleteAction;
QAction *mMoveUpAction;
QAction *mMoveDownAction;
CSMWorld::IdTableProxyModel *mProxyModel;
CSMWorld::IdTable *mModel;
bool mEditLock;
int mRecordStatusDisplay;
/// \brief This variable is used exclusivly for checking if dropEvents came from the same document. Most likely you
/// should NOT use it for anything else.
const CSMDoc::Document& mDocument;
private:
void contextMenuEvent (QContextMenuEvent *event);
std::vector<std::string> listRevertableSelectedIds() const;
std::vector<std::string> listDeletableSelectedIds() const;
void mouseMoveEvent(QMouseEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
public:
Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete,
bool sorting, const CSMDoc::Document& document);
///< \param createAndDelete Allow creation and deletion of records.
/// \param sorting Allow changing order of rows in the view via column headers.
void setEditLock (bool locked);
CSMWorld::UniversalId getUniversalId (int row) const;
void updateEditorSetting (const QString &settingName, const QString &settingValue);
std::vector<std::string> getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const;
signals:
void editRequest (int row);
void selectionSizeChanged (int size);
void tableSizeChanged (int size, int deleted, int modified);
///< \param size Number of not deleted records
/// \param deleted Number of deleted records
/// \param modified Number of added and modified records
void createRequest();
void cloneRequest(const CSMWorld::UniversalId&);
private slots:
void revertRecord();
void deleteRecord();
void editRecord();
void cloneRecord();
void moveUpRecord();
void moveDownRecord();
public slots:
void tableSizeUpdate();
void selectionSizeUpdate();
void requestFocus (const std::string& id);
void recordFilterChanged (boost::shared_ptr<CSMFilter::Node> filter);
};
}
#endif
#ifndef CSV_WORLD_TABLE_H
#define CSV_WORLD_TABLE_H
#include <vector>
#include <string>
#include <QTableView>
#include <QtGui/qevent.h>
#include "../../model/filter/node.hpp"
#include "../../model/world/columnbase.hpp"
namespace CSMDoc {
class Document;
}
class QUndoStack;
class QAction;
namespace CSMWorld
{
class Data;
class UniversalId;
class IdTableProxyModel;
class IdTable;
}
namespace CSVWorld
{
class CommandDelegate;
///< Table widget
class Table : public QTableView
{
Q_OBJECT
std::vector<CommandDelegate *> mDelegates;
QUndoStack& mUndoStack;
QAction *mEditAction;
QAction *mCreateAction;
QAction *mCloneAction;
QAction *mRevertAction;
QAction *mDeleteAction;
QAction *mMoveUpAction;
QAction *mMoveDownAction;
CSMWorld::IdTableProxyModel *mProxyModel;
CSMWorld::IdTable *mModel;
bool mEditLock;
int mRecordStatusDisplay;
/// \brief This variable is used exclusivly for checking if dropEvents came from the same document. Most likely you
/// should NOT use it for anything else.
const CSMDoc::Document& mDocument;
private:
void contextMenuEvent (QContextMenuEvent *event);
std::vector<std::string> listRevertableSelectedIds() const;
std::vector<std::string> listDeletableSelectedIds() const;
void mouseMoveEvent(QMouseEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
public:
Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete,
bool sorting, const CSMDoc::Document& document);
///< \param createAndDelete Allow creation and deletion of records.
/// \param sorting Allow changing order of rows in the view via column headers.
void setEditLock (bool locked);
CSMWorld::UniversalId getUniversalId (int row) const;
void updateEditorSetting (const QString &settingName, const QString &settingValue);
std::vector<std::string> getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const;
signals:
void editRequest (int row);
void selectionSizeChanged (int size);
void tableSizeChanged (int size, int deleted, int modified);
///< \param size Number of not deleted records
/// \param deleted Number of deleted records
/// \param modified Number of added and modified records
void createRequest();
void cloneRequest(const CSMWorld::UniversalId&);
private slots:
void revertRecord();
void deleteRecord();
void editRecord();
void cloneRecord();
void moveUpRecord();
void moveDownRecord();
public slots:
void tableSizeUpdate();
void selectionSizeUpdate();
void requestFocus (const std::string& id);
void recordFilterChanged (boost::shared_ptr<CSMFilter::Node> filter);
};
}
#endif

@ -1,132 +1,132 @@
#include "tablesubview.hpp"
#include <QVBoxLayout>
#include <QEvent>
#include "../../model/doc/document.hpp"
#include "../../model/world/tablemimedata.hpp"
#include "../filter/filterbox.hpp"
#include "table.hpp"
#include "tablebottombox.hpp"
#include "creator.hpp"
CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory, bool sorting)
: SubView (id)
{
QVBoxLayout *layout = new QVBoxLayout;
layout->setContentsMargins (QMargins (0, 0, 0, 0));
layout->addWidget (mBottom =
new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this), 0);
layout->insertWidget (0, mTable =
new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete(), sorting, document), 2);
CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
layout->insertWidget (0, filterBox);
QWidget *widget = new QWidget;
widget->setLayout (layout);
setWidget (widget);
connect (mTable, SIGNAL (editRequest (int)), this, SLOT (editRequest (int)));
connect (mTable, SIGNAL (selectionSizeChanged (int)),
mBottom, SLOT (selectionSizeChanged (int)));
connect (mTable, SIGNAL (tableSizeChanged (int, int, int)),
mBottom, SLOT (tableSizeChanged (int, int, int)));
mTable->tableSizeUpdate();
mTable->selectionSizeUpdate();
mTable->viewport()->installEventFilter(this);
mBottom->installEventFilter(this);
filterBox->installEventFilter(this);
if (mBottom->canCreateAndDelete())
{
connect (mTable, SIGNAL (createRequest()), mBottom, SLOT (createRequest()));
connect (mTable, SIGNAL (cloneRequest(const CSMWorld::UniversalId&)), this,
SLOT(cloneRequest(const CSMWorld::UniversalId&)));
connect (this, SIGNAL(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type)),
mBottom, SLOT(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type)));
}
connect (mBottom, SIGNAL (requestFocus (const std::string&)),
mTable, SLOT (requestFocus (const std::string&)));
connect (filterBox,
SIGNAL (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)),
mTable, SLOT (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)));
connect(filterBox, SIGNAL(recordDropped(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)),
this, SLOT(createFilterRequest(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)));
connect(this, SIGNAL(useFilterRequest(const std::string&)), filterBox, SIGNAL(useFilterRequest(const std::string&)));
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)),
filterBox, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
}
void CSVWorld::TableSubView::setEditLock (bool locked)
{
mTable->setEditLock (locked);
mBottom->setEditLock (locked);
}
void CSVWorld::TableSubView::editRequest (int row)
{
focusId (mTable->getUniversalId (row));
}
void CSVWorld::TableSubView::updateEditorSetting(const QString &settingName, const QString &settingValue)
{
mTable->updateEditorSetting(settingName, settingValue);
}
void CSVWorld::TableSubView::setStatusBar (bool show)
{
mBottom->setStatusBar (show);
}
void CSVWorld::TableSubView::cloneRequest(const CSMWorld::UniversalId& toClone)
{
emit cloneRequest(toClone.getId(), toClone.getType());
}
void CSVWorld::TableSubView::createFilterRequest (std::vector< CSMWorld::UniversalId>& types, Qt::DropAction action)
{
std::vector<std::pair<std::string, std::vector<std::string> > > filterSource;
for (std::vector<CSMWorld::UniversalId>::iterator it = types.begin(); it != types.end(); ++it)
{
std::pair<std::string, std::vector<std::string> > pair( //splited long line
std::make_pair(it->getId(), mTable->getColumnsWithDisplay(CSMWorld::TableMimeData::convertEnums(it->getType()))));
filterSource.push_back(pair);
}
emit createFilterRequest(filterSource, action);
}
bool CSVWorld::TableSubView::eventFilter (QObject* object, QEvent* event)
{
if (event->type() == QEvent::Drop)
{
QDropEvent* drop = dynamic_cast<QDropEvent*>(event);
const CSMWorld::TableMimeData* data = dynamic_cast<const CSMWorld::TableMimeData*>(drop->mimeData());
bool handled = data->holdsType(CSMWorld::UniversalId::Type_Filter);
if (handled)
{
emit useFilterRequest(data->returnMatching(CSMWorld::UniversalId::Type_Filter).getId());
}
return handled;
}
return false;
#include "tablesubview.hpp"
#include <QVBoxLayout>
#include <QEvent>
#include "../../model/doc/document.hpp"
#include "../../model/world/tablemimedata.hpp"
#include "../filter/filterbox.hpp"
#include "table.hpp"
#include "tablebottombox.hpp"
#include "creator.hpp"
CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory, bool sorting)
: SubView (id)
{
QVBoxLayout *layout = new QVBoxLayout;
layout->setContentsMargins (QMargins (0, 0, 0, 0));
layout->addWidget (mBottom =
new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this), 0);
layout->insertWidget (0, mTable =
new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete(), sorting, document), 2);
CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
layout->insertWidget (0, filterBox);
QWidget *widget = new QWidget;
widget->setLayout (layout);
setWidget (widget);
connect (mTable, SIGNAL (editRequest (int)), this, SLOT (editRequest (int)));
connect (mTable, SIGNAL (selectionSizeChanged (int)),
mBottom, SLOT (selectionSizeChanged (int)));
connect (mTable, SIGNAL (tableSizeChanged (int, int, int)),
mBottom, SLOT (tableSizeChanged (int, int, int)));
mTable->tableSizeUpdate();
mTable->selectionSizeUpdate();
mTable->viewport()->installEventFilter(this);
mBottom->installEventFilter(this);
filterBox->installEventFilter(this);
if (mBottom->canCreateAndDelete())
{
connect (mTable, SIGNAL (createRequest()), mBottom, SLOT (createRequest()));
connect (mTable, SIGNAL (cloneRequest(const CSMWorld::UniversalId&)), this,
SLOT(cloneRequest(const CSMWorld::UniversalId&)));
connect (this, SIGNAL(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type)),
mBottom, SLOT(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type)));
}
connect (mBottom, SIGNAL (requestFocus (const std::string&)),
mTable, SLOT (requestFocus (const std::string&)));
connect (filterBox,
SIGNAL (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)),
mTable, SLOT (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)));
connect(filterBox, SIGNAL(recordDropped(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)),
this, SLOT(createFilterRequest(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)));
connect(this, SIGNAL(useFilterRequest(const std::string&)), filterBox, SIGNAL(useFilterRequest(const std::string&)));
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)),
filterBox, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
}
void CSVWorld::TableSubView::setEditLock (bool locked)
{
mTable->setEditLock (locked);
mBottom->setEditLock (locked);
}
void CSVWorld::TableSubView::editRequest (int row)
{
focusId (mTable->getUniversalId (row));
}
void CSVWorld::TableSubView::updateEditorSetting(const QString &settingName, const QString &settingValue)
{
mTable->updateEditorSetting(settingName, settingValue);
}
void CSVWorld::TableSubView::setStatusBar (bool show)
{
mBottom->setStatusBar (show);
}
void CSVWorld::TableSubView::cloneRequest(const CSMWorld::UniversalId& toClone)
{
emit cloneRequest(toClone.getId(), toClone.getType());
}
void CSVWorld::TableSubView::createFilterRequest (std::vector< CSMWorld::UniversalId>& types, Qt::DropAction action)
{
std::vector<std::pair<std::string, std::vector<std::string> > > filterSource;
for (std::vector<CSMWorld::UniversalId>::iterator it = types.begin(); it != types.end(); ++it)
{
std::pair<std::string, std::vector<std::string> > pair( //splited long line
std::make_pair(it->getId(), mTable->getColumnsWithDisplay(CSMWorld::TableMimeData::convertEnums(it->getType()))));
filterSource.push_back(pair);
}
emit createFilterRequest(filterSource, action);
}
bool CSVWorld::TableSubView::eventFilter (QObject* object, QEvent* event)
{
if (event->type() == QEvent::Drop)
{
QDropEvent* drop = dynamic_cast<QDropEvent*>(event);
const CSMWorld::TableMimeData* data = dynamic_cast<const CSMWorld::TableMimeData*>(drop->mimeData());
bool handled = data->holdsType(CSMWorld::UniversalId::Type_Filter);
if (handled)
{
emit useFilterRequest(data->returnMatching(CSMWorld::UniversalId::Type_Filter).getId());
}
return handled;
}
return false;
}

@ -1,63 +1,63 @@
#ifndef CSV_WORLD_TABLESUBVIEW_H
#define CSV_WORLD_TABLESUBVIEW_H
#include "../doc/subview.hpp"
#include <qt4/QtCore/qnamespace.h>
class QModelIndex;
namespace CSMWorld
{
class IdTable;
}
namespace CSMDoc
{
class Document;
}
namespace CSVWorld
{
class Table;
class TableBottomBox;
class CreatorFactoryBase;
class TableSubView : public CSVDoc::SubView
{
Q_OBJECT
Table *mTable;
TableBottomBox *mBottom;
public:
TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory, bool sorting);
virtual void setEditLock (bool locked);
virtual void updateEditorSetting (const QString& key, const QString& value);
virtual void setStatusBar (bool show);
protected:
bool eventFilter(QObject* object, QEvent *event);
signals:
void cloneRequest(const std::string&,
const CSMWorld::UniversalId::Type);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action);
void useFilterRequest(const std::string& idOfFilter);
private slots:
void editRequest (int row);
void cloneRequest (const CSMWorld::UniversalId& toClone);
void createFilterRequest(std::vector< CSMWorld::UniversalId >& types,
Qt::DropAction action);
};
}
#endif
#ifndef CSV_WORLD_TABLESUBVIEW_H
#define CSV_WORLD_TABLESUBVIEW_H
#include "../doc/subview.hpp"
#include <qt4/QtCore/qnamespace.h>
class QModelIndex;
namespace CSMWorld
{
class IdTable;
}
namespace CSMDoc
{
class Document;
}
namespace CSVWorld
{
class Table;
class TableBottomBox;
class CreatorFactoryBase;
class TableSubView : public CSVDoc::SubView
{
Q_OBJECT
Table *mTable;
TableBottomBox *mBottom;
public:
TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory, bool sorting);
virtual void setEditLock (bool locked);
virtual void updateEditorSetting (const QString& key, const QString& value);
virtual void setStatusBar (bool show);
protected:
bool eventFilter(QObject* object, QEvent *event);
signals:
void cloneRequest(const std::string&,
const CSMWorld::UniversalId::Type);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action);
void useFilterRequest(const std::string& idOfFilter);
private slots:
void editRequest (int row);
void cloneRequest (const CSMWorld::UniversalId& toClone);
void createFilterRequest(std::vector< CSMWorld::UniversalId >& types,
Qt::DropAction action);
};
}
#endif

@ -1,352 +1,352 @@
#include "statemanagerimp.hpp"
#include <components/esm/esmwriter.hpp>
#include <components/esm/esmreader.hpp>
#include <components/esm/cellid.hpp>
#include <components/esm/loadcell.hpp>
#include <components/misc/stringops.hpp>
#include <components/settings/settings.hpp>
#include <OgreImage.h>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/journal.hpp"
#include "../mwbase/dialoguemanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/scriptmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwscript/globalscripts.hpp"
void MWState::StateManager::cleanup (bool force)
{
if (mState!=State_NoGame || force)
{
MWBase::Environment::get().getSoundManager()->clear();
MWBase::Environment::get().getDialogueManager()->clear();
MWBase::Environment::get().getJournal()->clear();
MWBase::Environment::get().getScriptManager()->getGlobalScripts().clear();
MWBase::Environment::get().getWorld()->clear();
MWBase::Environment::get().getWindowManager()->clear();
mState = State_NoGame;
mCharacterManager.clearCurrentCharacter();
mTimePlayed = 0;
}
}
std::map<int, int> MWState::StateManager::buildContentFileIndexMap (const ESM::ESMReader& reader)
const
{
const std::vector<std::string>& current =
MWBase::Environment::get().getWorld()->getContentFiles();
const std::vector<ESM::Header::MasterData>& prev = reader.getGameFiles();
std::map<int, int> map;
for (int iPrev = 0; iPrev<static_cast<int> (prev.size()); ++iPrev)
{
std::string id = Misc::StringUtils::lowerCase (prev[iPrev].name);
for (int iCurrent = 0; iCurrent<static_cast<int> (current.size()); ++iCurrent)
if (id==Misc::StringUtils::lowerCase (current[iCurrent]))
{
map.insert (std::make_pair (iPrev, iCurrent));
break;
}
}
return map;
}
MWState::StateManager::StateManager (const boost::filesystem::path& saves, const std::string& game)
: mQuitRequest (false), mAskLoadRecent(false), mState (State_NoGame), mCharacterManager (saves, game), mTimePlayed (0)
{
}
void MWState::StateManager::requestQuit()
{
mQuitRequest = true;
}
bool MWState::StateManager::hasQuitRequest() const
{
return mQuitRequest;
}
void MWState::StateManager::askLoadRecent()
{
if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_MainMenu)
return;
if( !mAskLoadRecent )
{
if(getCurrentCharacter()->begin() == getCurrentCharacter()->end() )//no saves
{
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
}
else
{
MWState::Slot lastSave = *getCurrentCharacter()->begin();
std::vector<std::string> buttons;
buttons.push_back("#{sYes}");
buttons.push_back("#{sNo}");
std::string tag("%s");
std::string message = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLoadLastSaveMsg", tag);
size_t pos = message.find(tag);
message.replace(pos, tag.length(), lastSave.mProfile.mDescription);
MWBase::Environment::get().getWindowManager()->messageBox(message, buttons);
mAskLoadRecent = true;
}
}
}
MWState::StateManager::State MWState::StateManager::getState() const
{
return mState;
}
void MWState::StateManager::newGame (bool bypass)
{
cleanup();
if (!bypass)
{
MWBase::Environment::get().getWorld()->startNewGame();
MWBase::Environment::get().getWindowManager()->setNewGame (true);
}
else
MWBase::Environment::get().getWorld()->setGlobalInt ("chargenstate", -1);
MWBase::Environment::get().getScriptManager()->getGlobalScripts().addStartup();
mState = State_Running;
}
void MWState::StateManager::endGame()
{
mState = State_Ended;
MWBase::Environment::get().getWorld()->useDeathCamera();
}
void MWState::StateManager::saveGame (const std::string& description, const Slot *slot)
{
ESM::SavedGame profile;
MWBase::World& world = *MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world.getPlayer().getPlayer();
profile.mContentFiles = world.getContentFiles();
profile.mPlayerName = player.getClass().getName (player);
profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel();
profile.mPlayerClass = player.get<ESM::NPC>()->mBase->mClass;
profile.mPlayerCell = world.getCellName();
profile.mInGameTime.mGameHour = world.getTimeStamp().getHour();
profile.mInGameTime.mDay = world.getDay();
profile.mInGameTime.mMonth = world.getMonth();
profile.mInGameTime.mYear = world.getYear();
profile.mTimePlayed = mTimePlayed;
profile.mDescription = description;
int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing
Ogre::Image screenshot;
world.screenshot(screenshot, screenshotW, screenshotH);
Ogre::DataStreamPtr encoded = screenshot.encode("jpg");
profile.mScreenshot.resize(encoded->size());
encoded->read(&profile.mScreenshot[0], encoded->size());
if (!slot)
slot = mCharacterManager.getCurrentCharacter()->createSlot (profile);
else
slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile);
std::ofstream stream (slot->mPath.string().c_str(), std::ios::binary);
ESM::ESMWriter writer;
const std::vector<std::string>& current =
MWBase::Environment::get().getWorld()->getContentFiles();
for (std::vector<std::string>::const_iterator iter (current.begin()); iter!=current.end();
++iter)
writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0
writer.setFormat (ESM::Header::CurrentFormat);
writer.setRecordCount (
1 // saved game header
+MWBase::Environment::get().getJournal()->countSavedGameRecords()
+MWBase::Environment::get().getWorld()->countSavedGameRecords()
+MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
+MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
+1 // global map
);
writer.save (stream);
writer.startRecord (ESM::REC_SAVE);
slot->mProfile.save (writer);
writer.endRecord (ESM::REC_SAVE);
MWBase::Environment::get().getJournal()->write (writer);
MWBase::Environment::get().getDialogueManager()->write (writer);
MWBase::Environment::get().getWorld()->write (writer);
MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer);
MWBase::Environment::get().getWindowManager()->write(writer);
writer.close();
Settings::Manager::setString ("character", "Saves",
slot->mPath.parent_path().filename().string());
}
void MWState::StateManager::loadGame (const Character *character, const Slot *slot)
{
try
{
cleanup();
mTimePlayed = slot->mProfile.mTimePlayed;
ESM::ESMReader reader;
reader.open (slot->mPath.string());
std::map<int, int> contentFileMap = buildContentFileIndexMap (reader);
while (reader.hasMoreRecs())
{
ESM::NAME n = reader.getRecName();
reader.getRecHeader();
switch (n.val)
{
case ESM::REC_SAVE:
// don't need to read that here
reader.skipRecord();
break;
case ESM::REC_JOUR:
case ESM::REC_QUES:
MWBase::Environment::get().getJournal()->readRecord (reader, n.val);
break;
case ESM::REC_DIAS:
MWBase::Environment::get().getDialogueManager()->readRecord (reader, n.val);
break;
case ESM::REC_ALCH:
case ESM::REC_ARMO:
case ESM::REC_BOOK:
case ESM::REC_CLAS:
case ESM::REC_CLOT:
case ESM::REC_ENCH:
case ESM::REC_NPC_:
case ESM::REC_SPEL:
case ESM::REC_WEAP:
case ESM::REC_GLOB:
case ESM::REC_PLAY:
case ESM::REC_CSTA:
MWBase::Environment::get().getWorld()->readRecord (reader, n.val, contentFileMap);
break;
case ESM::REC_GSCR:
MWBase::Environment::get().getScriptManager()->getGlobalScripts().readRecord (reader, n.val);
break;
case ESM::REC_GMAP:
MWBase::Environment::get().getWindowManager()->readRecord(reader, n.val);
break;
default:
// ignore invalid records
/// \todo log error
reader.skipRecord();
}
}
mCharacterManager.setCurrentCharacter(character);
mState = State_Running;
Settings::Manager::setString ("character", "Saves",
slot->mPath.parent_path().filename().string());
MWBase::Environment::get().getWindowManager()->setNewGame(false);
MWBase::Environment::get().getWorld()->setupPlayer();
MWBase::Environment::get().getWorld()->renderPlayer();
MWBase::Environment::get().getWindowManager()->updatePlayer();
MWBase::Environment::get().getMechanicsManager()->playerLoaded();
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
ESM::CellId cellId = ptr.getCell()->mCell->getCellId();
MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition());
}
catch (const std::exception& e)
{
std::cerr << "failed to load saved game: " << e.what() << std::endl;
cleanup (true);
}
}
MWState::Character *MWState::StateManager::getCurrentCharacter (bool create)
{
return mCharacterManager.getCurrentCharacter (create);
}
MWState::StateManager::CharacterIterator MWState::StateManager::characterBegin()
{
return mCharacterManager.begin();
}
MWState::StateManager::CharacterIterator MWState::StateManager::characterEnd()
{
return mCharacterManager.end();
}
void MWState::StateManager::update (float duration)
{
mTimePlayed += duration;
// Note: It would be nicer to trigger this from InputManager, i.e. the very beginning of the frame update.
if (mAskLoadRecent)
{
int iButton = MWBase::Environment::get().getWindowManager()->readPressedButton();
if(iButton==0)
{
mAskLoadRecent = false;
//Load last saved game for current character
MWState::Character *curCharacter = getCurrentCharacter();
MWState::Slot lastSave = *curCharacter->begin();
loadGame(curCharacter, &lastSave);
}
else if(iButton==1)
{
mAskLoadRecent = false;
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
}
}
}
#include "statemanagerimp.hpp"
#include <components/esm/esmwriter.hpp>
#include <components/esm/esmreader.hpp>
#include <components/esm/cellid.hpp>
#include <components/esm/loadcell.hpp>
#include <components/misc/stringops.hpp>
#include <components/settings/settings.hpp>
#include <OgreImage.h>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/journal.hpp"
#include "../mwbase/dialoguemanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/scriptmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwscript/globalscripts.hpp"
void MWState::StateManager::cleanup (bool force)
{
if (mState!=State_NoGame || force)
{
MWBase::Environment::get().getSoundManager()->clear();
MWBase::Environment::get().getDialogueManager()->clear();
MWBase::Environment::get().getJournal()->clear();
MWBase::Environment::get().getScriptManager()->getGlobalScripts().clear();
MWBase::Environment::get().getWorld()->clear();
MWBase::Environment::get().getWindowManager()->clear();
mState = State_NoGame;
mCharacterManager.clearCurrentCharacter();
mTimePlayed = 0;
}
}
std::map<int, int> MWState::StateManager::buildContentFileIndexMap (const ESM::ESMReader& reader)
const
{
const std::vector<std::string>& current =
MWBase::Environment::get().getWorld()->getContentFiles();
const std::vector<ESM::Header::MasterData>& prev = reader.getGameFiles();
std::map<int, int> map;
for (int iPrev = 0; iPrev<static_cast<int> (prev.size()); ++iPrev)
{
std::string id = Misc::StringUtils::lowerCase (prev[iPrev].name);
for (int iCurrent = 0; iCurrent<static_cast<int> (current.size()); ++iCurrent)
if (id==Misc::StringUtils::lowerCase (current[iCurrent]))
{
map.insert (std::make_pair (iPrev, iCurrent));
break;
}
}
return map;
}
MWState::StateManager::StateManager (const boost::filesystem::path& saves, const std::string& game)
: mQuitRequest (false), mAskLoadRecent(false), mState (State_NoGame), mCharacterManager (saves, game), mTimePlayed (0)
{
}
void MWState::StateManager::requestQuit()
{
mQuitRequest = true;
}
bool MWState::StateManager::hasQuitRequest() const
{
return mQuitRequest;
}
void MWState::StateManager::askLoadRecent()
{
if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_MainMenu)
return;
if( !mAskLoadRecent )
{
if(getCurrentCharacter()->begin() == getCurrentCharacter()->end() )//no saves
{
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
}
else
{
MWState::Slot lastSave = *getCurrentCharacter()->begin();
std::vector<std::string> buttons;
buttons.push_back("#{sYes}");
buttons.push_back("#{sNo}");
std::string tag("%s");
std::string message = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLoadLastSaveMsg", tag);
size_t pos = message.find(tag);
message.replace(pos, tag.length(), lastSave.mProfile.mDescription);
MWBase::Environment::get().getWindowManager()->messageBox(message, buttons);
mAskLoadRecent = true;
}
}
}
MWState::StateManager::State MWState::StateManager::getState() const
{
return mState;
}
void MWState::StateManager::newGame (bool bypass)
{
cleanup();
if (!bypass)
{
MWBase::Environment::get().getWorld()->startNewGame();
MWBase::Environment::get().getWindowManager()->setNewGame (true);
}
else
MWBase::Environment::get().getWorld()->setGlobalInt ("chargenstate", -1);
MWBase::Environment::get().getScriptManager()->getGlobalScripts().addStartup();
mState = State_Running;
}
void MWState::StateManager::endGame()
{
mState = State_Ended;
MWBase::Environment::get().getWorld()->useDeathCamera();
}
void MWState::StateManager::saveGame (const std::string& description, const Slot *slot)
{
ESM::SavedGame profile;
MWBase::World& world = *MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world.getPlayer().getPlayer();
profile.mContentFiles = world.getContentFiles();
profile.mPlayerName = player.getClass().getName (player);
profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel();
profile.mPlayerClass = player.get<ESM::NPC>()->mBase->mClass;
profile.mPlayerCell = world.getCellName();
profile.mInGameTime.mGameHour = world.getTimeStamp().getHour();
profile.mInGameTime.mDay = world.getDay();
profile.mInGameTime.mMonth = world.getMonth();
profile.mInGameTime.mYear = world.getYear();
profile.mTimePlayed = mTimePlayed;
profile.mDescription = description;
int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing
Ogre::Image screenshot;
world.screenshot(screenshot, screenshotW, screenshotH);
Ogre::DataStreamPtr encoded = screenshot.encode("jpg");
profile.mScreenshot.resize(encoded->size());
encoded->read(&profile.mScreenshot[0], encoded->size());
if (!slot)
slot = mCharacterManager.getCurrentCharacter()->createSlot (profile);
else
slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile);
std::ofstream stream (slot->mPath.string().c_str(), std::ios::binary);
ESM::ESMWriter writer;
const std::vector<std::string>& current =
MWBase::Environment::get().getWorld()->getContentFiles();
for (std::vector<std::string>::const_iterator iter (current.begin()); iter!=current.end();
++iter)
writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0
writer.setFormat (ESM::Header::CurrentFormat);
writer.setRecordCount (
1 // saved game header
+MWBase::Environment::get().getJournal()->countSavedGameRecords()
+MWBase::Environment::get().getWorld()->countSavedGameRecords()
+MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
+MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
+1 // global map
);
writer.save (stream);
writer.startRecord (ESM::REC_SAVE);
slot->mProfile.save (writer);
writer.endRecord (ESM::REC_SAVE);
MWBase::Environment::get().getJournal()->write (writer);
MWBase::Environment::get().getDialogueManager()->write (writer);
MWBase::Environment::get().getWorld()->write (writer);
MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer);
MWBase::Environment::get().getWindowManager()->write(writer);
writer.close();
Settings::Manager::setString ("character", "Saves",
slot->mPath.parent_path().filename().string());
}
void MWState::StateManager::loadGame (const Character *character, const Slot *slot)
{
try
{
cleanup();
mTimePlayed = slot->mProfile.mTimePlayed;
ESM::ESMReader reader;
reader.open (slot->mPath.string());
std::map<int, int> contentFileMap = buildContentFileIndexMap (reader);
while (reader.hasMoreRecs())
{
ESM::NAME n = reader.getRecName();
reader.getRecHeader();
switch (n.val)
{
case ESM::REC_SAVE:
// don't need to read that here
reader.skipRecord();
break;
case ESM::REC_JOUR:
case ESM::REC_QUES:
MWBase::Environment::get().getJournal()->readRecord (reader, n.val);
break;
case ESM::REC_DIAS:
MWBase::Environment::get().getDialogueManager()->readRecord (reader, n.val);
break;
case ESM::REC_ALCH:
case ESM::REC_ARMO:
case ESM::REC_BOOK:
case ESM::REC_CLAS:
case ESM::REC_CLOT:
case ESM::REC_ENCH:
case ESM::REC_NPC_:
case ESM::REC_SPEL:
case ESM::REC_WEAP:
case ESM::REC_GLOB:
case ESM::REC_PLAY:
case ESM::REC_CSTA:
MWBase::Environment::get().getWorld()->readRecord (reader, n.val, contentFileMap);
break;
case ESM::REC_GSCR:
MWBase::Environment::get().getScriptManager()->getGlobalScripts().readRecord (reader, n.val);
break;
case ESM::REC_GMAP:
MWBase::Environment::get().getWindowManager()->readRecord(reader, n.val);
break;
default:
// ignore invalid records
/// \todo log error
reader.skipRecord();
}
}
mCharacterManager.setCurrentCharacter(character);
mState = State_Running;
Settings::Manager::setString ("character", "Saves",
slot->mPath.parent_path().filename().string());
MWBase::Environment::get().getWindowManager()->setNewGame(false);
MWBase::Environment::get().getWorld()->setupPlayer();
MWBase::Environment::get().getWorld()->renderPlayer();
MWBase::Environment::get().getWindowManager()->updatePlayer();
MWBase::Environment::get().getMechanicsManager()->playerLoaded();
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
ESM::CellId cellId = ptr.getCell()->mCell->getCellId();
MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition());
}
catch (const std::exception& e)
{
std::cerr << "failed to load saved game: " << e.what() << std::endl;
cleanup (true);
}
}
MWState::Character *MWState::StateManager::getCurrentCharacter (bool create)
{
return mCharacterManager.getCurrentCharacter (create);
}
MWState::StateManager::CharacterIterator MWState::StateManager::characterBegin()
{
return mCharacterManager.begin();
}
MWState::StateManager::CharacterIterator MWState::StateManager::characterEnd()
{
return mCharacterManager.end();
}
void MWState::StateManager::update (float duration)
{
mTimePlayed += duration;
// Note: It would be nicer to trigger this from InputManager, i.e. the very beginning of the frame update.
if (mAskLoadRecent)
{
int iButton = MWBase::Environment::get().getWindowManager()->readPressedButton();
if(iButton==0)
{
mAskLoadRecent = false;
//Load last saved game for current character
MWState::Character *curCharacter = getCurrentCharacter();
MWState::Slot lastSave = *curCharacter->begin();
loadGame(curCharacter, &lastSave);
}
else if(iButton==1)
{
mAskLoadRecent = false;
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
}
}
}

@ -1,203 +1,203 @@
#include "esmwriter.hpp"
#include <cassert>
#include <fstream>
#include <stdexcept>
namespace ESM
{
ESMWriter::ESMWriter() : mEncoder (0), mRecordCount (0), mCounting (true) {}
unsigned int ESMWriter::getVersion() const
{
return mHeader.mData.version;
}
void ESMWriter::setVersion(unsigned int ver)
{
mHeader.mData.version = ver;
}
void ESMWriter::setAuthor(const std::string& auth)
{
mHeader.mData.author.assign (auth);
}
void ESMWriter::setDescription(const std::string& desc)
{
mHeader.mData.desc.assign (desc);
}
void ESMWriter::setRecordCount (int count)
{
mHeader.mData.records = count;
}
void ESMWriter::setFormat (int format)
{
mHeader.mFormat = format;
}
void ESMWriter::clearMaster()
{
mHeader.mMaster.clear();
}
void ESMWriter::addMaster(const std::string& name, uint64_t size)
{
Header::MasterData d;
d.name = name;
d.size = size;
mHeader.mMaster.push_back(d);
}
void ESMWriter::save(std::ostream& file)
{
mRecordCount = 0;
mRecords.clear();
mCounting = true;
mStream = &file;
startRecord("TES3", 0);
mHeader.save (*this);
endRecord("TES3");
}
void ESMWriter::close()
{
if (!mRecords.empty())
throw std::runtime_error ("Unclosed record remaining");
}
void ESMWriter::startRecord(const std::string& name, uint32_t flags)
{
mRecordCount++;
writeName(name);
RecordData rec;
rec.name = name;
rec.position = mStream->tellp();
rec.size = 0;
writeT<uint32_t>(0); // Size goes here
writeT<uint32_t>(0); // Unused header?
writeT(flags);
mRecords.push_back(rec);
assert(mRecords.back().size == 0);
}
void ESMWriter::startRecord (uint32_t name, uint32_t flags)
{
std::string type;
for (int i=0; i<4; ++i)
/// \todo make endianess agnostic
type += reinterpret_cast<const char *> (&name)[i];
startRecord (type, flags);
}
void ESMWriter::startSubRecord(const std::string& name)
{
writeName(name);
RecordData rec;
rec.name = name;
rec.position = mStream->tellp();
rec.size = 0;
writeT<uint32_t>(0); // Size goes here
mRecords.push_back(rec);
assert(mRecords.back().size == 0);
}
void ESMWriter::endRecord(const std::string& name)
{
RecordData rec = mRecords.back();
assert(rec.name == name);
mRecords.pop_back();
mStream->seekp(rec.position);
mCounting = false;
write (reinterpret_cast<const char*> (&rec.size), sizeof(uint32_t));
mCounting = true;
mStream->seekp(0, std::ios::end);
}
void ESMWriter::endRecord (uint32_t name)
{
std::string type;
for (int i=0; i<4; ++i)
/// \todo make endianess agnostic
type += reinterpret_cast<const char *> (&name)[i];
endRecord (type);
}
void ESMWriter::writeHNString(const std::string& name, const std::string& data)
{
startSubRecord(name);
writeHString(data);
endRecord(name);
}
void ESMWriter::writeHNString(const std::string& name, const std::string& data, size_t size)
{
assert(data.size() <= size);
startSubRecord(name);
writeHString(data);
if (data.size() < size)
{
for (size_t i = data.size(); i < size; ++i)
write("\0",1);
}
endRecord(name);
}
void ESMWriter::writeHString(const std::string& data)
{
if (data.size() == 0)
write("\0", 1);
else
{
// Convert to UTF8 and return
std::string string = mEncoder ? mEncoder->getLegacyEnc(data) : data;
write(string.c_str(), string.size());
}
}
void ESMWriter::writeHCString(const std::string& data)
{
writeHString(data);
if (data.size() > 0 && data[data.size()-1] != '\0')
write("\0", 1);
}
void ESMWriter::writeName(const std::string& name)
{
assert((name.size() == 4 && name[3] != '\0'));
write(name.c_str(), name.size());
}
void ESMWriter::write(const char* data, size_t size)
{
if (mCounting && !mRecords.empty())
{
for (std::list<RecordData>::iterator it = mRecords.begin(); it != mRecords.end(); ++it)
it->size += size;
}
mStream->write(data, size);
}
void ESMWriter::setEncoder(ToUTF8::Utf8Encoder* encoder)
{
mEncoder = encoder;
}
}
#include "esmwriter.hpp"
#include <cassert>
#include <fstream>
#include <stdexcept>
namespace ESM
{
ESMWriter::ESMWriter() : mEncoder (0), mRecordCount (0), mCounting (true) {}
unsigned int ESMWriter::getVersion() const
{
return mHeader.mData.version;
}
void ESMWriter::setVersion(unsigned int ver)
{
mHeader.mData.version = ver;
}
void ESMWriter::setAuthor(const std::string& auth)
{
mHeader.mData.author.assign (auth);
}
void ESMWriter::setDescription(const std::string& desc)
{
mHeader.mData.desc.assign (desc);
}
void ESMWriter::setRecordCount (int count)
{
mHeader.mData.records = count;
}
void ESMWriter::setFormat (int format)
{
mHeader.mFormat = format;
}
void ESMWriter::clearMaster()
{
mHeader.mMaster.clear();
}
void ESMWriter::addMaster(const std::string& name, uint64_t size)
{
Header::MasterData d;
d.name = name;
d.size = size;
mHeader.mMaster.push_back(d);
}
void ESMWriter::save(std::ostream& file)
{
mRecordCount = 0;
mRecords.clear();
mCounting = true;
mStream = &file;
startRecord("TES3", 0);
mHeader.save (*this);
endRecord("TES3");
}
void ESMWriter::close()
{
if (!mRecords.empty())
throw std::runtime_error ("Unclosed record remaining");
}
void ESMWriter::startRecord(const std::string& name, uint32_t flags)
{
mRecordCount++;
writeName(name);
RecordData rec;
rec.name = name;
rec.position = mStream->tellp();
rec.size = 0;
writeT<uint32_t>(0); // Size goes here
writeT<uint32_t>(0); // Unused header?
writeT(flags);
mRecords.push_back(rec);
assert(mRecords.back().size == 0);
}
void ESMWriter::startRecord (uint32_t name, uint32_t flags)
{
std::string type;
for (int i=0; i<4; ++i)
/// \todo make endianess agnostic
type += reinterpret_cast<const char *> (&name)[i];
startRecord (type, flags);
}
void ESMWriter::startSubRecord(const std::string& name)
{
writeName(name);
RecordData rec;
rec.name = name;
rec.position = mStream->tellp();
rec.size = 0;
writeT<uint32_t>(0); // Size goes here
mRecords.push_back(rec);
assert(mRecords.back().size == 0);
}
void ESMWriter::endRecord(const std::string& name)
{
RecordData rec = mRecords.back();
assert(rec.name == name);
mRecords.pop_back();
mStream->seekp(rec.position);
mCounting = false;
write (reinterpret_cast<const char*> (&rec.size), sizeof(uint32_t));
mCounting = true;
mStream->seekp(0, std::ios::end);
}
void ESMWriter::endRecord (uint32_t name)
{
std::string type;
for (int i=0; i<4; ++i)
/// \todo make endianess agnostic
type += reinterpret_cast<const char *> (&name)[i];
endRecord (type);
}
void ESMWriter::writeHNString(const std::string& name, const std::string& data)
{
startSubRecord(name);
writeHString(data);
endRecord(name);
}
void ESMWriter::writeHNString(const std::string& name, const std::string& data, size_t size)
{
assert(data.size() <= size);
startSubRecord(name);
writeHString(data);
if (data.size() < size)
{
for (size_t i = data.size(); i < size; ++i)
write("\0",1);
}
endRecord(name);
}
void ESMWriter::writeHString(const std::string& data)
{
if (data.size() == 0)
write("\0", 1);
else
{
// Convert to UTF8 and return
std::string string = mEncoder ? mEncoder->getLegacyEnc(data) : data;
write(string.c_str(), string.size());
}
}
void ESMWriter::writeHCString(const std::string& data)
{
writeHString(data);
if (data.size() > 0 && data[data.size()-1] != '\0')
write("\0", 1);
}
void ESMWriter::writeName(const std::string& name)
{
assert((name.size() == 4 && name[3] != '\0'));
write(name.c_str(), name.size());
}
void ESMWriter::write(const char* data, size_t size)
{
if (mCounting && !mRecords.empty())
{
for (std::list<RecordData>::iterator it = mRecords.begin(); it != mRecords.end(); ++it)
it->size += size;
}
mStream->write(data, size);
}
void ESMWriter::setEncoder(ToUTF8::Utf8Encoder* encoder)
{
mEncoder = encoder;
}
}

@ -1,114 +1,114 @@
#ifndef OPENMW_ESM_WRITER_H
#define OPENMW_ESM_WRITER_H
#include <iosfwd>
#include <list>
#include <components/to_utf8/to_utf8.hpp>
#include "esmcommon.hpp"
#include "loadtes3.hpp"
namespace ESM {
class ESMWriter
{
struct RecordData
{
std::string name;
std::streampos position;
uint32_t size;
};
public:
ESMWriter();
unsigned int getVersion() const;
void setVersion(unsigned int ver = 0x3fa66666);
void setEncoder(ToUTF8::Utf8Encoder *encoding);
void setAuthor(const std::string& author);
void setDescription(const std::string& desc);
void setRecordCount (int count);
void setFormat (int format);
void clearMaster();
void addMaster(const std::string& name, uint64_t size);
void save(std::ostream& file);
///< Start saving a file by writing the TES3 header.
void close();
///< \note Does not close the stream.
void writeHNString(const std::string& name, const std::string& data);
void writeHNString(const std::string& name, const std::string& data, size_t size);
void writeHNCString(const std::string& name, const std::string& data)
{
startSubRecord(name);
writeHCString(data);
endRecord(name);
}
void writeHNOString(const std::string& name, const std::string& data)
{
if (!data.empty())
writeHNString(name, data);
}
void writeHNOCString(const std::string& name, const std::string& data)
{
if (!data.empty())
writeHNCString(name, data);
}
template<typename T>
void writeHNT(const std::string& name, const T& data)
{
startSubRecord(name);
writeT(data);
endRecord(name);
}
template<typename T>
void writeHNT(const std::string& name, const T& data, int size)
{
startSubRecord(name);
writeT(data, size);
endRecord(name);
}
template<typename T>
void writeT(const T& data)
{
write((char*)&data, sizeof(T));
}
template<typename T>
void writeT(const T& data, size_t size)
{
write((char*)&data, size);
}
void startRecord(const std::string& name, uint32_t flags = 0);
void startRecord(uint32_t name, uint32_t flags = 0);
void startSubRecord(const std::string& name);
void endRecord(const std::string& name);
void endRecord(uint32_t name);
void writeHString(const std::string& data);
void writeHCString(const std::string& data);
void writeName(const std::string& data);
void write(const char* data, size_t size);
private:
std::list<RecordData> mRecords;
std::ostream* mStream;
std::streampos mHeaderPos;
ToUTF8::Utf8Encoder* mEncoder;
int mRecordCount;
bool mCounting;
Header mHeader;
};
}
#endif
#ifndef OPENMW_ESM_WRITER_H
#define OPENMW_ESM_WRITER_H
#include <iosfwd>
#include <list>
#include <components/to_utf8/to_utf8.hpp>
#include "esmcommon.hpp"
#include "loadtes3.hpp"
namespace ESM {
class ESMWriter
{
struct RecordData
{
std::string name;
std::streampos position;
uint32_t size;
};
public:
ESMWriter();
unsigned int getVersion() const;
void setVersion(unsigned int ver = 0x3fa66666);
void setEncoder(ToUTF8::Utf8Encoder *encoding);
void setAuthor(const std::string& author);
void setDescription(const std::string& desc);
void setRecordCount (int count);
void setFormat (int format);
void clearMaster();
void addMaster(const std::string& name, uint64_t size);
void save(std::ostream& file);
///< Start saving a file by writing the TES3 header.
void close();
///< \note Does not close the stream.
void writeHNString(const std::string& name, const std::string& data);
void writeHNString(const std::string& name, const std::string& data, size_t size);
void writeHNCString(const std::string& name, const std::string& data)
{
startSubRecord(name);
writeHCString(data);
endRecord(name);
}
void writeHNOString(const std::string& name, const std::string& data)
{
if (!data.empty())
writeHNString(name, data);
}
void writeHNOCString(const std::string& name, const std::string& data)
{
if (!data.empty())
writeHNCString(name, data);
}
template<typename T>
void writeHNT(const std::string& name, const T& data)
{
startSubRecord(name);
writeT(data);
endRecord(name);
}
template<typename T>
void writeHNT(const std::string& name, const T& data, int size)
{
startSubRecord(name);
writeT(data, size);
endRecord(name);
}
template<typename T>
void writeT(const T& data)
{
write((char*)&data, sizeof(T));
}
template<typename T>
void writeT(const T& data, size_t size)
{
write((char*)&data, size);
}
void startRecord(const std::string& name, uint32_t flags = 0);
void startRecord(uint32_t name, uint32_t flags = 0);
void startSubRecord(const std::string& name);
void endRecord(const std::string& name);
void endRecord(uint32_t name);
void writeHString(const std::string& data);
void writeHCString(const std::string& data);
void writeName(const std::string& data);
void write(const char* data, size_t size);
private:
std::list<RecordData> mRecords;
std::ostream* mStream;
std::streampos mHeaderPos;
ToUTF8::Utf8Encoder* mEncoder;
int mRecordCount;
bool mCounting;
Header mHeader;
};
}
#endif

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save