cleanup the mess...

This commit is contained in:
cc9cii 2014-02-27 23:59:23 +11:00
parent 1ab5948f19
commit 2421f23c2f
20 changed files with 3571 additions and 3557 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

@ -240,17 +240,21 @@ namespace MWMechanics
//target is at far distance: build path to target OR follow target (if previously actor had reached it once) //target is at far distance: build path to target OR follow target (if previously actor had reached it once)
mFollowTarget = false; mFollowTarget = false;
buildNewPath(actor); buildNewPath(actor); //may fail to build a path, check before use
//delete visited path node //delete visited path node
mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]); mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]);
//try shortcut //if no new path leave mTargetAngle unchanged
if(vDir.length() < mPathFinder.getDistToNext(pos.pos[0],pos.pos[1],pos.pos[2]) && MWBase::Environment::get().getWorld()->getLOS(actor, mTarget)) if(!mPathFinder.getPath().empty())
mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / vDir.length()) * sgn(Ogre::Math::ASin(vDir.x / vDir.length())) ).valueDegrees(); {
else //try shortcut
mTargetAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); if(vDir.length() < mPathFinder.getDistToNext(pos.pos[0],pos.pos[1],pos.pos[2]) && MWBase::Environment::get().getWorld()->getLOS(actor, mTarget))
mRotate = true; mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / vDir.length()) * sgn(Ogre::Math::ASin(vDir.x / vDir.length())) ).valueDegrees();
else
mTargetAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
mRotate = true;
}
mMovement.mPosition[1] = 1; mMovement.mPosition[1] = 1;
mReadyToAttack = false; mReadyToAttack = false;
@ -300,9 +304,13 @@ namespace MWMechanics
dest.mZ = mTarget.getRefData().getPosition().pos[2]; dest.mZ = mTarget.getRefData().getPosition().pos[2];
Ogre::Vector3 newPathTarget = Ogre::Vector3(dest.mX, dest.mY, dest.mZ); Ogre::Vector3 newPathTarget = Ogre::Vector3(dest.mX, dest.mY, dest.mZ);
ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); float dist = -1; //hack to indicate first time, to construct a new path
Ogre::Vector3 currPathTarget(lastPt.mX, lastPt.mY, lastPt.mZ); if(!mPathFinder.getPath().empty())
float dist = Ogre::Math::Abs((newPathTarget - currPathTarget).length()); {
ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back();
Ogre::Vector3 currPathTarget(lastPt.mX, lastPt.mY, lastPt.mZ);
dist = Ogre::Math::Abs((newPathTarget - currPathTarget).length());
}
float targetPosThreshold; float targetPosThreshold;
bool isOutside = actor.getCell()->mCell->isExterior(); bool isOutside = actor.getCell()->mCell->isExterior();
@ -311,7 +319,7 @@ namespace MWMechanics
else else
targetPosThreshold = 100; targetPosThreshold = 100;
if(dist > targetPosThreshold) if((dist < 0) || (dist > targetPosThreshold))
{ {
//construct new path only if target has moved away more than on <targetPosThreshold> //construct new path only if target has moved away more than on <targetPosThreshold>
ESM::Position pos = actor.getRefData().getPosition(); ESM::Position pos = actor.getRefData().getPosition();
@ -332,8 +340,11 @@ namespace MWMechanics
//maybe here is a mistake (?): PathFinder::getPathSize() returns number of grid points in the path, //maybe here is a mistake (?): PathFinder::getPathSize() returns number of grid points in the path,
//not the actual path length. Here we should know if the new path is actually more effective. //not the actual path length. Here we should know if the new path is actually more effective.
//if(pathFinder2.getPathSize() < mPathFinder.getPathSize()) //if(pathFinder2.getPathSize() < mPathFinder.getPathSize())
newPathFinder.syncStart(mPathFinder.getPath()); if(!mPathFinder.getPath().empty())
mPathFinder = newPathFinder; {
newPathFinder.syncStart(mPathFinder.getPath());
mPathFinder = newPathFinder;
}
} }
} }
} }

View file

@ -391,6 +391,8 @@ namespace MWMechanics
void PathFinder::syncStart(const std::list<ESM::Pathgrid::Point> &path) void PathFinder::syncStart(const std::list<ESM::Pathgrid::Point> &path)
{ {
if (mPath.size() < 2)
return; //nothing to pop
std::list<ESM::Pathgrid::Point>::const_iterator oldStart = path.begin(); std::list<ESM::Pathgrid::Point>::const_iterator oldStart = path.begin();
std::list<ESM::Pathgrid::Point>::iterator iter = ++mPath.begin(); std::list<ESM::Pathgrid::Point>::iterator iter = ++mPath.begin();

View file

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

View file

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

View file

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

View file

@ -20,6 +20,7 @@ Artem Kotsynyak (greye)
athile athile
Britt Mathis (galdor557) Britt Mathis (galdor557)
BrotherBrick BrotherBrick
cc9cii
Chris Robinson (KittyCat) Chris Robinson (KittyCat)
Cory F. Cohen (cfcohen) Cory F. Cohen (cfcohen)
Cris Mihalache (Mirceam) Cris Mihalache (Mirceam)

1902
readme.txt

File diff suppressed because it is too large Load diff