mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 13:23:53 +00:00
Merge branch 'bottombar'
This commit is contained in:
commit
2e667f1d94
38 changed files with 1298 additions and 176 deletions
|
@ -57,13 +57,14 @@ opencs_hdrs_noqt (view/doc
|
|||
|
||||
|
||||
opencs_units (view/world
|
||||
table tablesubview scriptsubview util regionmapsubview
|
||||
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
|
||||
cellcreator referenceablecreator referencecreator
|
||||
)
|
||||
|
||||
opencs_units_noqt (view/world
|
||||
dialoguesubview subviews
|
||||
enumdelegate vartypedelegate recordstatusdelegate refidtypedelegate datadisplaydelegate
|
||||
scripthighlighter
|
||||
scripthighlighter idvalidator
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
#include "idtableproxymodel.hpp"
|
||||
#include "idtable.hpp"
|
||||
#include "idtable.hpp"
|
||||
|
||||
CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index,
|
||||
|
@ -25,15 +25,28 @@ void CSMWorld::ModifyCommand::undo()
|
|||
mModel.setData (mIndex, mOld);
|
||||
}
|
||||
|
||||
CSMWorld::CreateCommand::CreateCommand (IdTableProxyModel& model, const std::string& id, QUndoCommand *parent)
|
||||
: QUndoCommand (parent), mModel (model), mId (id)
|
||||
CSMWorld::CreateCommand::CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent)
|
||||
: QUndoCommand (parent), mModel (model), mId (id), mType (UniversalId::Type_None)
|
||||
{
|
||||
setText (("Create record " + id).c_str());
|
||||
}
|
||||
|
||||
void CSMWorld::CreateCommand::addValue (int column, const QVariant& value)
|
||||
{
|
||||
mValues[column] = value;
|
||||
}
|
||||
|
||||
void CSMWorld::CreateCommand::setType (UniversalId::Type type)
|
||||
{
|
||||
mType = type;
|
||||
}
|
||||
|
||||
void CSMWorld::CreateCommand::redo()
|
||||
{
|
||||
mModel.addRecord (mId);
|
||||
mModel.addRecord (mId, mType);
|
||||
|
||||
for (std::map<int, QVariant>::const_iterator iter (mValues.begin()); iter!=mValues.end(); ++iter)
|
||||
mModel.setData (mModel.getModelIndex (mId, iter->first), iter->second);
|
||||
}
|
||||
|
||||
void CSMWorld::CreateCommand::undo()
|
||||
|
|
|
@ -4,17 +4,20 @@
|
|||
#include "record.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include <QVariant>
|
||||
#include <QUndoCommand>
|
||||
#include <QModelIndex>
|
||||
|
||||
#include "universalid.hpp"
|
||||
|
||||
class QModelIndex;
|
||||
class QAbstractItemModel;
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class IdTableProxyModel;
|
||||
class IdTable;
|
||||
class IdTable;
|
||||
class RecordBase;
|
||||
|
||||
|
@ -37,12 +40,18 @@ namespace CSMWorld
|
|||
|
||||
class CreateCommand : public QUndoCommand
|
||||
{
|
||||
IdTableProxyModel& mModel;
|
||||
IdTable& mModel;
|
||||
std::string mId;
|
||||
UniversalId::Type mType;
|
||||
std::map<int, QVariant> mValues;
|
||||
|
||||
public:
|
||||
|
||||
CreateCommand (IdTableProxyModel& model, const std::string& id, QUndoCommand *parent = 0);
|
||||
CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0);
|
||||
|
||||
void setType (UniversalId::Type type);
|
||||
|
||||
void addValue (int column, const QVariant& value);
|
||||
|
||||
virtual void redo();
|
||||
|
||||
|
|
|
@ -300,6 +300,16 @@ CSMWorld::RefIdCollection& CSMWorld::Data::getReferenceables()
|
|||
return mReferenceables;
|
||||
}
|
||||
|
||||
const CSMWorld::RefCollection& CSMWorld::Data::getReferences() const
|
||||
{
|
||||
return mRefs;
|
||||
}
|
||||
|
||||
CSMWorld::RefCollection& CSMWorld::Data::getReferences()
|
||||
{
|
||||
return mRefs;
|
||||
}
|
||||
|
||||
QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
|
||||
{
|
||||
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
|
||||
|
@ -394,4 +404,22 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
|
|||
reader.skipRecord();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CSMWorld::Data::hasId (const std::string& id) const
|
||||
{
|
||||
return
|
||||
getGlobals().searchId (id)!=-1 ||
|
||||
getGmsts().searchId (id)!=-1 ||
|
||||
getSkills().searchId (id)!=-1 ||
|
||||
getClasses().searchId (id)!=-1 ||
|
||||
getFactions().searchId (id)!=-1 ||
|
||||
getRaces().searchId (id)!=-1 ||
|
||||
getSounds().searchId (id)!=-1 ||
|
||||
getScripts().searchId (id)!=-1 ||
|
||||
getRegions().searchId (id)!=-1 ||
|
||||
getBirthsigns().searchId (id)!=-1 ||
|
||||
getSpells().searchId (id)!=-1 ||
|
||||
getCells().searchId (id)!=-1 ||
|
||||
getReferenceables().searchId (id)!=-1;
|
||||
}
|
||||
|
|
|
@ -112,6 +112,10 @@ namespace CSMWorld
|
|||
|
||||
RefIdCollection& getReferenceables();
|
||||
|
||||
const RefCollection& getReferences() const;
|
||||
|
||||
RefCollection& getReferences();
|
||||
|
||||
QAbstractItemModel *getTableModel (const UniversalId& id);
|
||||
///< If no table model is available for \a id, an exception is thrown.
|
||||
///
|
||||
|
@ -123,6 +127,8 @@ namespace CSMWorld
|
|||
|
||||
void loadFile (const boost::filesystem::path& path, bool base);
|
||||
///< Merging content of a file into base or modified.
|
||||
|
||||
bool hasId (const std::string& id) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -116,13 +116,13 @@ QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const
|
|||
return QModelIndex();
|
||||
}
|
||||
|
||||
void CSMWorld::IdTable::addRecord (const std::string& id)
|
||||
void CSMWorld::IdTable::addRecord (const std::string& id, UniversalId::Type type)
|
||||
{
|
||||
int index = mIdCollection->getAppendIndex();
|
||||
|
||||
beginInsertRows (QModelIndex(), index, index);
|
||||
|
||||
mIdCollection->appendBlankRecord (id);
|
||||
mIdCollection->appendBlankRecord (id, type);
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
#include "universalid.hpp"
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class CollectionBase;
|
||||
|
@ -44,7 +46,8 @@ namespace CSMWorld
|
|||
|
||||
virtual QModelIndex parent (const QModelIndex& index) const;
|
||||
|
||||
void addRecord (const std::string& id);
|
||||
void addRecord (const std::string& id, UniversalId::Type type = UniversalId::Type_None);
|
||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
||||
|
||||
QModelIndex getModelIndex (const std::string& id, int column) const;
|
||||
|
||||
|
|
|
@ -7,11 +7,6 @@ CSMWorld::IdTableProxyModel::IdTableProxyModel (QObject *parent)
|
|||
: QSortFilterProxyModel (parent)
|
||||
{}
|
||||
|
||||
void CSMWorld::IdTableProxyModel::addRecord (const std::string& id)
|
||||
{
|
||||
dynamic_cast<IdTable&> (*sourceModel()).addRecord (id);
|
||||
}
|
||||
|
||||
QModelIndex CSMWorld::IdTableProxyModel::getModelIndex (const std::string& id, int column) const
|
||||
{
|
||||
return mapFromSource (dynamic_cast<IdTable&> (*sourceModel()).getModelIndex (id, column));
|
||||
|
|
|
@ -15,8 +15,6 @@ namespace CSMWorld
|
|||
|
||||
IdTableProxyModel (QObject *parent = 0);
|
||||
|
||||
virtual void addRecord (const std::string& id);
|
||||
|
||||
virtual QModelIndex getModelIndex (const std::string& id, int column) const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -21,10 +21,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
|
|||
while (cell2.getNextRef (reader, ref))
|
||||
{
|
||||
/// \todo handle deleted and moved references
|
||||
std::ostringstream stream;
|
||||
stream << "ref#" << mNextId++;
|
||||
|
||||
ref.load (reader, cell2, stream.str());
|
||||
ref.load (reader, cell2, getNewId());
|
||||
|
||||
Record<CellRef> record2;
|
||||
record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
|
||||
|
@ -34,4 +31,11 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
|
|||
}
|
||||
|
||||
mCells.setRecord (cellIndex, cell);
|
||||
}
|
||||
|
||||
std::string CSMWorld::RefCollection::getNewId()
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << "ref#" << mNextId++;
|
||||
return stream.str();
|
||||
}
|
|
@ -21,6 +21,8 @@ namespace CSMWorld
|
|||
|
||||
void load (ESM::ESMReader& reader, int cellIndex, bool base);
|
||||
///< Load a sequence of references.
|
||||
|
||||
std::string getNewId();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -12,81 +12,82 @@ namespace
|
|||
CSMWorld::UniversalId::Class mClass;
|
||||
CSMWorld::UniversalId::Type mType;
|
||||
const char *mName;
|
||||
const char *mIcon;
|
||||
};
|
||||
|
||||
static const TypeData sNoArg[] =
|
||||
{
|
||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells" },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells" },
|
||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables,
|
||||
"Referenceables" },
|
||||
"Referenceables", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References,
|
||||
"References" },
|
||||
"References", 0 },
|
||||
{ CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap,
|
||||
"Region Map" },
|
||||
"Region Map", 0 },
|
||||
|
||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
|
||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
|
||||
};
|
||||
|
||||
static const TypeData sIdArg[] =
|
||||
{
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Activator, "Activator" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Potion, "Potion" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Apparatus, "Apparatus" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Armor, "Armor" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Book, "Book" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Clothing, "Clothing" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Container, "Container" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Creature, "Creature" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Door, "Door" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Ingredient, "Ingredient" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_CreatureLevelledList,
|
||||
"Creature Levelled List" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_ItemLevelledList,
|
||||
"Item Levelled List" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Light, "Light" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Lockpick, "Lockpick" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Miscellaneous,
|
||||
"Miscellaneous" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Npc, "NPC" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Probe, "Probe" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Repair, "Repair" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Static, "Static" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Weapon, "Weapon" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Reference, "Reference" },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Apparatus, "Apparatus", ":./apparatus.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Armor, "Armor", ":./armor.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Book, "Book", ":./book.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Clothing, "Clothing", ":./clothing.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Container, "Container", ":./container.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Creature, "Creature", ":./creature.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Door, "Door", ":./door.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Ingredient, "Ingredient", ":./ingredient.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_CreatureLevelledList,
|
||||
"Creature Levelled List", ":./creature.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_ItemLevelledList,
|
||||
"Item Levelled List", ":./leveled-item.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Light, "Light", ":./light.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Lockpick, "Lockpick", ":./lockpick.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Miscellaneous,
|
||||
"Miscellaneous", ":./miscellaneous.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Npc, "NPC", ":./npc.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Probe, "Probe", ":./probe.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Repair, "Repair", ":./repair.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" },
|
||||
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 },
|
||||
|
||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
|
||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
|
||||
};
|
||||
|
||||
static const TypeData sIndexArg[] =
|
||||
{
|
||||
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results" },
|
||||
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 },
|
||||
|
||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
|
||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
|
||||
};
|
||||
|
||||
static const unsigned int IDARG_SIZE = sizeof (sIdArg) / sizeof (TypeData);
|
||||
|
@ -268,6 +269,28 @@ std::string CSMWorld::UniversalId::toString() const
|
|||
return stream.str();
|
||||
}
|
||||
|
||||
std::string CSMWorld::UniversalId::getIcon() const
|
||||
{
|
||||
const TypeData *typeData = mArgumentType==ArgumentType_None ? sNoArg :
|
||||
(mArgumentType==ArgumentType_Id ? sIdArg : sIndexArg);
|
||||
|
||||
for (int i=0; typeData[i].mName; ++i)
|
||||
if (typeData[i].mType==mType)
|
||||
return typeData[i].mIcon ? typeData[i].mIcon : "";
|
||||
|
||||
throw std::logic_error ("failed to retrieve UniversalId type icon");
|
||||
}
|
||||
|
||||
std::vector<CSMWorld::UniversalId::Type> CSMWorld::UniversalId::listReferenceableTypes()
|
||||
{
|
||||
std::vector<CSMWorld::UniversalId::Type> list;
|
||||
|
||||
for (int i=0; sIdArg[i].mName; ++i)
|
||||
if (sIdArg[i].mClass==Class_RefRecord)
|
||||
list.push_back (sIdArg[i].mType);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
std::pair<int, const char *> CSMWorld::UniversalId::getIdArgPair (unsigned int index)
|
||||
{
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
#include <vector>
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
|
@ -14,13 +15,14 @@ namespace CSMWorld
|
|||
|
||||
enum Class
|
||||
{
|
||||
Class_None = 0,
|
||||
Class_Record,
|
||||
Class_SubRecord,
|
||||
Class_RecordList,
|
||||
Class_Collection, // multiple types of records combined
|
||||
Class_Transient, // not part of the world data or the project data
|
||||
Class_NonRecord // record like data that is not part of the world
|
||||
Class_None = 0,
|
||||
Class_Record,
|
||||
Class_RefRecord, // referenceable record
|
||||
Class_SubRecord,
|
||||
Class_RecordList,
|
||||
Class_Collection, // multiple types of records combined
|
||||
Class_Transient, // not part of the world data or the project data
|
||||
Class_NonRecord // record like data that is not part of the world
|
||||
};
|
||||
|
||||
enum ArgumentType
|
||||
|
@ -126,6 +128,11 @@ namespace CSMWorld
|
|||
|
||||
std::string toString() const;
|
||||
|
||||
std::string getIcon() const;
|
||||
///< Will return an empty string, if no icon is available.
|
||||
|
||||
static std::vector<Type> listReferenceableTypes();
|
||||
|
||||
static std::pair<int, const char *> getIdArgPair (unsigned int index);
|
||||
static unsigned int getIdArgSize ();
|
||||
};
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
#include "subview.hpp"
|
||||
|
||||
|
||||
CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id)
|
||||
{
|
||||
/// \todo add a button to the title bar that clones this sub view
|
||||
|
||||
setWindowTitle (mUniversalId.toString().c_str());
|
||||
|
||||
/// \todo remove (for testing only)
|
||||
setMinimumWidth (100);
|
||||
setMinimumHeight (60);
|
||||
}
|
||||
|
||||
CSMWorld::UniversalId CSVDoc::SubView::getUniversalId() const
|
||||
|
@ -20,3 +15,5 @@ CSMWorld::UniversalId CSVDoc::SubView::getUniversalId() const
|
|||
void CSVDoc::SubView::updateEditorSetting (const QString &settingName, const QString &settingValue)
|
||||
{
|
||||
}
|
||||
|
||||
void CSVDoc::SubView::setStatusBar (bool show) {}
|
|
@ -37,6 +37,9 @@ namespace CSVDoc
|
|||
virtual void setEditLock (bool locked) = 0;
|
||||
virtual void updateEditorSetting (const QString &, const QString &);
|
||||
|
||||
virtual void setStatusBar (bool show);
|
||||
///< Default implementation: ignored
|
||||
|
||||
signals:
|
||||
|
||||
void focusId (const CSMWorld::UniversalId& universalId);
|
||||
|
|
|
@ -22,28 +22,20 @@ namespace CSVDoc
|
|||
return new SubViewT (id, document);
|
||||
}
|
||||
|
||||
template<class SubViewT>
|
||||
class SubViewFactoryWithCreateFlag : public SubViewFactoryBase
|
||||
|
||||
template<class SubViewT, class CreatorFactoryT>
|
||||
class SubViewFactoryWithCreator : public SubViewFactoryBase
|
||||
{
|
||||
bool mCreateAndDelete;
|
||||
|
||||
public:
|
||||
|
||||
SubViewFactoryWithCreateFlag (bool createAndDelete);
|
||||
|
||||
virtual CSVDoc::SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document);
|
||||
};
|
||||
|
||||
template<class SubViewT>
|
||||
SubViewFactoryWithCreateFlag<SubViewT>::SubViewFactoryWithCreateFlag (bool createAndDelete)
|
||||
: mCreateAndDelete (createAndDelete)
|
||||
{}
|
||||
|
||||
template<class SubViewT>
|
||||
CSVDoc::SubView *SubViewFactoryWithCreateFlag<SubViewT>::makeSubView (const CSMWorld::UniversalId& id,
|
||||
CSMDoc::Document& document)
|
||||
template<class SubViewT, class CreatorFactoryT>
|
||||
CSVDoc::SubView *SubViewFactoryWithCreator<SubViewT, CreatorFactoryT>::makeSubView (
|
||||
const CSMWorld::UniversalId& id, CSMDoc::Document& document)
|
||||
{
|
||||
return new SubViewT (id, document, mCreateAndDelete);
|
||||
return new SubViewT (id, document, CreatorFactoryT());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,11 @@ void CSVDoc::View::setupViewMenu()
|
|||
QAction *newWindow = new QAction (tr ("&New View"), this);
|
||||
connect (newWindow, SIGNAL (triggered()), this, SLOT (newView()));
|
||||
view->addAction (newWindow);
|
||||
|
||||
mShowStatusBar = new QAction (tr ("Show Status Bar"), this);
|
||||
mShowStatusBar->setCheckable (true);
|
||||
connect (mShowStatusBar, SIGNAL (toggled (bool)), this, SLOT (toggleShowStatusBar (bool)));
|
||||
view->addAction (mShowStatusBar);
|
||||
}
|
||||
|
||||
void CSVDoc::View::setupWorldMenu()
|
||||
|
@ -282,6 +287,9 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id)
|
|||
/// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis)
|
||||
|
||||
SubView *view = mSubViewFactory.makeSubView (id, *mDocument);
|
||||
|
||||
view->setStatusBar (mShowStatusBar->isChecked());
|
||||
|
||||
mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view);
|
||||
|
||||
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this,
|
||||
|
@ -436,3 +444,12 @@ void CSVDoc::View::updateEditorSetting (const QString &settingName, const QStrin
|
|||
else if (settingName == "Height")
|
||||
resizeViewHeight (settingValue.toInt());
|
||||
}
|
||||
|
||||
void CSVDoc::View::toggleShowStatusBar (bool show)
|
||||
{
|
||||
foreach (QObject *view, mSubViewWindow.children())
|
||||
{
|
||||
if (CSVDoc::SubView *subView = dynamic_cast<CSVDoc::SubView *> (view))
|
||||
subView->setStatusBar (show);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace CSVDoc
|
|||
QAction *mRedo;
|
||||
QAction *mSave;
|
||||
QAction *mVerify;
|
||||
QAction *mShowStatusBar;
|
||||
std::vector<QAction *> mEditingActions;
|
||||
Operations *mOperations;
|
||||
SubViewFactoryManager mSubViewFactory;
|
||||
|
@ -158,6 +159,8 @@ namespace CSVDoc
|
|||
void addRegionMapSubView();
|
||||
|
||||
void showUserSettings();
|
||||
|
||||
void toggleShowStatusBar (bool show);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
81
apps/opencs/view/world/cellcreator.cpp
Normal file
81
apps/opencs/view/world/cellcreator.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
|
||||
#include "cellcreator.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QSpinBox>
|
||||
#include <QLabel>
|
||||
|
||||
std::string CSVWorld::CellCreator::getId() const
|
||||
{
|
||||
if (mType->currentIndex()==0)
|
||||
return GenericCreator::getId();
|
||||
|
||||
std::ostringstream stream;
|
||||
|
||||
stream << "#" << mX->value() << " " << mY->value();
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
CSVWorld::CellCreator::CellCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id)
|
||||
: GenericCreator (data, undoStack, id)
|
||||
{
|
||||
mY = new QSpinBox (this);
|
||||
mY->setVisible (false);
|
||||
mY->setMinimum (std::numeric_limits<int>::min());
|
||||
mY->setMaximum (std::numeric_limits<int>::max());
|
||||
connect (mY, SIGNAL (valueChanged (int)), this, SLOT (valueChanged (int)));
|
||||
insertAtBeginning (mY, true);
|
||||
|
||||
mYLabel = new QLabel ("Y", this);
|
||||
mYLabel->setVisible (false);
|
||||
insertAtBeginning (mYLabel, false);
|
||||
|
||||
mX = new QSpinBox (this);
|
||||
mX->setVisible (false);
|
||||
mX->setMinimum (std::numeric_limits<int>::min());
|
||||
mX->setMaximum (std::numeric_limits<int>::max());
|
||||
connect (mX, SIGNAL (valueChanged (int)), this, SLOT (valueChanged (int)));
|
||||
insertAtBeginning (mX, true);
|
||||
|
||||
mXLabel = new QLabel ("X", this);
|
||||
mXLabel->setVisible (false);
|
||||
insertAtBeginning (mXLabel, false);
|
||||
|
||||
mType = new QComboBox (this);
|
||||
|
||||
mType->addItem ("Interior Cell");
|
||||
mType->addItem ("Exterior Cell");
|
||||
|
||||
connect (mType, SIGNAL (currentIndexChanged (int)), this, SLOT (setType (int)));
|
||||
|
||||
insertAtBeginning (mType, false);
|
||||
}
|
||||
|
||||
void CSVWorld::CellCreator::reset()
|
||||
{
|
||||
mX->setValue (0);
|
||||
mY->setValue (0);
|
||||
mType->setCurrentIndex (0);
|
||||
GenericCreator::reset();
|
||||
}
|
||||
|
||||
void CSVWorld::CellCreator::setType (int index)
|
||||
{
|
||||
setManualEditing (index==0);
|
||||
mXLabel->setVisible (index==1);
|
||||
mX->setVisible (index==1);
|
||||
mYLabel->setVisible (index==1);
|
||||
mY->setVisible (index==1);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void CSVWorld::CellCreator::valueChanged (int index)
|
||||
{
|
||||
update();
|
||||
}
|
40
apps/opencs/view/world/cellcreator.hpp
Normal file
40
apps/opencs/view/world/cellcreator.hpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef CSV_WORLD_CELLCREATOR_H
|
||||
#define CSV_WORLD_CELLCREATOR_H
|
||||
|
||||
class QLabel;
|
||||
class QSpinBox;
|
||||
class QComboBox;
|
||||
|
||||
#include "genericcreator.hpp"
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class CellCreator : public GenericCreator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QComboBox *mType;
|
||||
QLabel *mXLabel;
|
||||
QSpinBox *mX;
|
||||
QLabel *mYLabel;
|
||||
QSpinBox *mY;
|
||||
|
||||
protected:
|
||||
|
||||
virtual std::string getId() const;
|
||||
|
||||
public:
|
||||
|
||||
CellCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id);
|
||||
|
||||
virtual void reset();
|
||||
|
||||
private slots:
|
||||
|
||||
void setType (int index);
|
||||
|
||||
void valueChanged (int index);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
13
apps/opencs/view/world/creator.cpp
Normal file
13
apps/opencs/view/world/creator.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
#include "creator.hpp"
|
||||
|
||||
CSVWorld::Creator:: ~Creator() {}
|
||||
|
||||
CSVWorld::CreatorFactoryBase::~CreatorFactoryBase() {}
|
||||
|
||||
|
||||
CSVWorld::Creator *CSVWorld::NullCreatorFactory::makeCreator (CSMWorld::Data& data,
|
||||
QUndoStack& undoStack, const CSMWorld::UniversalId& id) const
|
||||
{
|
||||
return 0;
|
||||
}
|
86
apps/opencs/view/world/creator.hpp
Normal file
86
apps/opencs/view/world/creator.hpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
#ifndef CSV_WORLD_CREATOR_H
|
||||
#define CSV_WORLD_CREATOR_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QUndoStack;
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class Data;
|
||||
class UniversalId;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
/// \brief Record creator UI base class
|
||||
class Creator : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Creator();
|
||||
|
||||
virtual void reset() = 0;
|
||||
|
||||
virtual void setEditLock (bool locked) = 0;
|
||||
|
||||
signals:
|
||||
|
||||
void done();
|
||||
|
||||
void requestFocus (const std::string& id);
|
||||
///< Request owner of this creator to focus the just created \a id. The owner may
|
||||
/// ignore this request.
|
||||
};
|
||||
|
||||
/// \brief Base class for Creator factory
|
||||
class CreatorFactoryBase
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~CreatorFactoryBase();
|
||||
|
||||
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const = 0;
|
||||
///< The ownership of the returned Creator is transferred to the caller.
|
||||
///
|
||||
/// \note The function can return a 0-pointer, which means no UI for creating/deleting
|
||||
/// records should be provided.
|
||||
};
|
||||
|
||||
/// \brief Creator factory that does not produces any creator
|
||||
class NullCreatorFactory : public CreatorFactoryBase
|
||||
{
|
||||
public:
|
||||
|
||||
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const;
|
||||
///< The ownership of the returned Creator is transferred to the caller.
|
||||
///
|
||||
/// \note The function always returns 0.
|
||||
};
|
||||
|
||||
template<class CreatorT>
|
||||
class CreatorFactory : public CreatorFactoryBase
|
||||
{
|
||||
public:
|
||||
|
||||
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const;
|
||||
///< The ownership of the returned Creator is transferred to the caller.
|
||||
///
|
||||
/// \note The function can return a 0-pointer, which means no UI for creating/deleting
|
||||
/// records should be provided.
|
||||
};
|
||||
|
||||
template<class CreatorT>
|
||||
Creator *CreatorFactory<CreatorT>::makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const
|
||||
{
|
||||
return new CreatorT (data, undoStack, id);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
135
apps/opencs/view/world/genericcreator.cpp
Normal file
135
apps/opencs/view/world/genericcreator.cpp
Normal file
|
@ -0,0 +1,135 @@
|
|||
|
||||
#include "genericcreator.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QLineEdit>
|
||||
#include <QUndoStack>
|
||||
|
||||
#include "../../model/world/commands.hpp"
|
||||
#include "../../model/world/data.hpp"
|
||||
#include "../../model/world/idtable.hpp"
|
||||
|
||||
#include "idvalidator.hpp"
|
||||
|
||||
void CSVWorld::GenericCreator::update()
|
||||
{
|
||||
mErrors = getErrors();
|
||||
|
||||
mCreate->setToolTip (QString::fromUtf8 (mErrors.c_str()));
|
||||
mId->setToolTip (QString::fromUtf8 (mErrors.c_str()));
|
||||
|
||||
mCreate->setEnabled (mErrors.empty() && !mLocked);
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::setManualEditing (bool enabled)
|
||||
{
|
||||
mId->setVisible (enabled);
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::insertAtBeginning (QWidget *widget, bool stretched)
|
||||
{
|
||||
mLayout->insertWidget (0, widget, stretched ? 1 : 0);
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::insertBeforeButtons (QWidget *widget, bool stretched)
|
||||
{
|
||||
mLayout->insertWidget (mLayout->count()-2, widget, stretched ? 1 : 0);
|
||||
}
|
||||
|
||||
std::string CSVWorld::GenericCreator::getId() const
|
||||
{
|
||||
return mId->text().toUtf8().constData();
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const {}
|
||||
|
||||
const CSMWorld::Data& CSVWorld::GenericCreator::getData() const
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
|
||||
CSMWorld::Data& CSVWorld::GenericCreator::getData()
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
|
||||
CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id)
|
||||
: mData (data), mUndoStack (undoStack), mListId (id), mLocked (false)
|
||||
{
|
||||
mLayout = new QHBoxLayout;
|
||||
mLayout->setContentsMargins (0, 0, 0, 0);
|
||||
|
||||
mId = new QLineEdit;
|
||||
mId->setValidator (new IdValidator (this));
|
||||
mLayout->addWidget (mId, 1);
|
||||
|
||||
mCreate = new QPushButton ("Create");
|
||||
mLayout->addWidget (mCreate);
|
||||
|
||||
QPushButton *cancelButton = new QPushButton ("Cancel");
|
||||
mLayout->addWidget (cancelButton);
|
||||
|
||||
setLayout (mLayout);
|
||||
|
||||
connect (cancelButton, SIGNAL (clicked (bool)), this, SIGNAL (done()));
|
||||
connect (mCreate, SIGNAL (clicked (bool)), this, SLOT (create()));
|
||||
|
||||
connect (mId, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&)));
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::setEditLock (bool locked)
|
||||
{
|
||||
mLocked = locked;
|
||||
update();
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::reset()
|
||||
{
|
||||
mId->setText ("");
|
||||
update();
|
||||
}
|
||||
|
||||
std::string CSVWorld::GenericCreator::getErrors() const
|
||||
{
|
||||
std::string errors;
|
||||
|
||||
std::string id = getId();
|
||||
|
||||
if (id.empty())
|
||||
{
|
||||
errors = "Missing ID";
|
||||
}
|
||||
else if (mData.hasId (id))
|
||||
{
|
||||
errors = "ID is already in use";
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::textChanged (const QString& text)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::create()
|
||||
{
|
||||
if (!mLocked)
|
||||
{
|
||||
std::string id = getId();
|
||||
|
||||
std::auto_ptr<CSMWorld::CreateCommand> command (new CSMWorld::CreateCommand (
|
||||
dynamic_cast<CSMWorld::IdTable&> (*mData.getTableModel (mListId)), id));
|
||||
|
||||
configureCreateCommand (*command);
|
||||
|
||||
mUndoStack.push (command.release());
|
||||
|
||||
emit done();
|
||||
emit requestFocus (id);
|
||||
}
|
||||
}
|
73
apps/opencs/view/world/genericcreator.hpp
Normal file
73
apps/opencs/view/world/genericcreator.hpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
#ifndef CSV_WORLD_GENERICCREATOR_H
|
||||
#define CSV_WORLD_GENERICCREATOR_H
|
||||
|
||||
class QPushButton;
|
||||
class QLineEdit;
|
||||
class QHBoxLayout;
|
||||
|
||||
#include "creator.hpp"
|
||||
|
||||
#include "../../model/world/universalid.hpp"
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class CreateCommand;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class GenericCreator : public Creator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
CSMWorld::Data& mData;
|
||||
QUndoStack& mUndoStack;
|
||||
CSMWorld::UniversalId mListId;
|
||||
QPushButton *mCreate;
|
||||
QLineEdit *mId;
|
||||
std::string mErrors;
|
||||
QHBoxLayout *mLayout;
|
||||
bool mLocked;
|
||||
|
||||
protected:
|
||||
|
||||
void update();
|
||||
|
||||
virtual void setManualEditing (bool enabled);
|
||||
///< Enable/disable manual ID editing (enabled by default).
|
||||
|
||||
void insertAtBeginning (QWidget *widget, bool stretched);
|
||||
|
||||
void insertBeforeButtons (QWidget *widget, bool stretched);
|
||||
|
||||
virtual std::string getId() const;
|
||||
|
||||
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
|
||||
|
||||
const CSMWorld::Data& getData() const;
|
||||
|
||||
CSMWorld::Data& getData();
|
||||
|
||||
public:
|
||||
|
||||
GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id);
|
||||
|
||||
virtual void setEditLock (bool locked);
|
||||
|
||||
virtual void reset();
|
||||
|
||||
virtual std::string getErrors() const;
|
||||
///< Return formatted error descriptions for the current state of the creator. if an empty
|
||||
/// string is returned, there is no error.
|
||||
|
||||
|
||||
private slots:
|
||||
|
||||
void textChanged (const QString& text);
|
||||
|
||||
void create();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
26
apps/opencs/view/world/idvalidator.cpp
Normal file
26
apps/opencs/view/world/idvalidator.cpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
|
||||
#include "idvalidator.hpp"
|
||||
|
||||
bool CSVWorld::IdValidator::isValid (const QChar& c, bool first) const
|
||||
{
|
||||
if (c.isLetter() || c=='_')
|
||||
return true;
|
||||
|
||||
if (!first && (c.isDigit() || c.isSpace()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CSVWorld::IdValidator::IdValidator (QObject *parent) : QValidator (parent) {}
|
||||
|
||||
QValidator::State CSVWorld::IdValidator::validate (QString& input, int& pos) const
|
||||
{
|
||||
bool first = true;
|
||||
|
||||
for (QString::const_iterator iter (input.begin()); iter!=input.end(); ++iter, first = false)
|
||||
if (!isValid (*iter, first))
|
||||
return QValidator::Invalid;
|
||||
|
||||
return QValidator::Acceptable;
|
||||
}
|
23
apps/opencs/view/world/idvalidator.hpp
Normal file
23
apps/opencs/view/world/idvalidator.hpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef CSV_WORLD_IDVALIDATOR_H
|
||||
#define CSV_WORLD_IDVALIDATOR_H
|
||||
|
||||
#include <QValidator>
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class IdValidator : public QValidator
|
||||
{
|
||||
private:
|
||||
|
||||
bool isValid (const QChar& c, bool first) const;
|
||||
|
||||
public:
|
||||
|
||||
IdValidator (QObject *parent = 0);
|
||||
|
||||
virtual State validate (QString& input, int& pos) const;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
43
apps/opencs/view/world/referenceablecreator.cpp
Normal file
43
apps/opencs/view/world/referenceablecreator.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
|
||||
#include "referenceablecreator.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QLabel>
|
||||
|
||||
#include "../../model/world/universalid.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
|
||||
void CSVWorld::ReferenceableCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
|
||||
{
|
||||
command.setType (
|
||||
static_cast<CSMWorld::UniversalId::Type> (mType->itemData (mType->currentIndex()).toInt()));
|
||||
}
|
||||
|
||||
CSVWorld::ReferenceableCreator::ReferenceableCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id)
|
||||
: GenericCreator (data, undoStack, id)
|
||||
{
|
||||
QLabel *label = new QLabel ("Type", this);
|
||||
insertBeforeButtons (label, false);
|
||||
|
||||
std::vector<CSMWorld::UniversalId::Type> types = CSMWorld::UniversalId::listReferenceableTypes();
|
||||
|
||||
mType = new QComboBox (this);
|
||||
|
||||
for (std::vector<CSMWorld::UniversalId::Type>::const_iterator iter (types.begin());
|
||||
iter!=types.end(); ++iter)
|
||||
{
|
||||
CSMWorld::UniversalId id (*iter, "");
|
||||
|
||||
mType->addItem (QIcon (id.getIcon().c_str()), id.getTypeName().c_str(),
|
||||
static_cast<int> (id.getType()));
|
||||
}
|
||||
|
||||
insertBeforeButtons (mType, false);
|
||||
}
|
||||
|
||||
void CSVWorld::ReferenceableCreator::reset()
|
||||
{
|
||||
mType->setCurrentIndex (0);
|
||||
GenericCreator::reset();
|
||||
}
|
30
apps/opencs/view/world/referenceablecreator.hpp
Normal file
30
apps/opencs/view/world/referenceablecreator.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef CSV_WORLD_REFERENCEABLECREATOR_H
|
||||
#define CSV_WORLD_REFERENCEABLECREATOR_H
|
||||
|
||||
class QComboBox;
|
||||
|
||||
#include "genericcreator.hpp"
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class ReferenceableCreator : public GenericCreator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QComboBox *mType;
|
||||
|
||||
private:
|
||||
|
||||
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
|
||||
|
||||
public:
|
||||
|
||||
ReferenceableCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id);
|
||||
|
||||
virtual void reset();
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
70
apps/opencs/view/world/referencecreator.cpp
Normal file
70
apps/opencs/view/world/referencecreator.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
|
||||
#include "referencecreator.hpp"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "../../model/world/data.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
|
||||
std::string CSVWorld::ReferenceCreator::getId() const
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
void CSVWorld::ReferenceCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
|
||||
{
|
||||
/// \todo avoid using hard-coded column numbers
|
||||
command.addValue (2, mCell->text());
|
||||
}
|
||||
|
||||
CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id)
|
||||
: GenericCreator (data, undoStack, id)
|
||||
{
|
||||
QLabel *label = new QLabel ("Cell", this);
|
||||
insertBeforeButtons (label, false);
|
||||
|
||||
mCell = new QLineEdit (this);
|
||||
insertBeforeButtons (mCell, true);
|
||||
|
||||
setManualEditing (false);
|
||||
|
||||
connect (mCell, SIGNAL (textChanged (const QString&)), this, SLOT (cellChanged()));
|
||||
}
|
||||
|
||||
void CSVWorld::ReferenceCreator::reset()
|
||||
{
|
||||
mCell->setText ("");
|
||||
mId = getData().getReferences().getNewId();
|
||||
GenericCreator::reset();
|
||||
}
|
||||
|
||||
std::string CSVWorld::ReferenceCreator::getErrors() const
|
||||
{
|
||||
std::string errors = GenericCreator::getErrors();
|
||||
|
||||
std::string cell = mCell->text().toUtf8().constData();
|
||||
|
||||
if (cell.empty())
|
||||
{
|
||||
if (!errors.empty())
|
||||
errors += "<br>";
|
||||
|
||||
errors += "Missing Cell ID";
|
||||
}
|
||||
else if (getData().getCells().searchId (cell)==-1)
|
||||
{
|
||||
if (!errors.empty())
|
||||
errors += "<br>";
|
||||
|
||||
errors += "Invalid Cell ID";
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
void CSVWorld::ReferenceCreator::cellChanged()
|
||||
{
|
||||
update();
|
||||
}
|
40
apps/opencs/view/world/referencecreator.hpp
Normal file
40
apps/opencs/view/world/referencecreator.hpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef CSV_WORLD_REFERENCECREATOR_H
|
||||
#define CSV_WORLD_REFERENCECREATOR_H
|
||||
|
||||
#include "genericcreator.hpp"
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class ReferenceCreator : public GenericCreator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QLineEdit *mCell;
|
||||
std::string mId;
|
||||
|
||||
private:
|
||||
|
||||
virtual std::string getId() const;
|
||||
|
||||
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
|
||||
|
||||
public:
|
||||
|
||||
ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id);
|
||||
|
||||
virtual void reset();
|
||||
|
||||
virtual std::string getErrors() const;
|
||||
///< Return formatted error descriptions for the current state of the creator. if an empty
|
||||
/// string is returned, there is no error.
|
||||
|
||||
private slots:
|
||||
|
||||
void cellChanged();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -27,26 +27,15 @@ CSVWorld::RefIdTypeDelegateFactory::UidTypeList CSVWorld::RefIdTypeDelegateFacto
|
|||
{
|
||||
UidTypeList list;
|
||||
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Activator, ":./activator.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Potion, ":./potion.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Apparatus, ":./apparatus.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Armor, ":./armor.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Book, ":./book.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Clothing, ":./clothing.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Container, ":./container.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Creature, ":./creature.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Door, ":./door.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Ingredient, ":./ingredient.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_CreatureLevelledList, ":./creature.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_ItemLevelledList, ":./item.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Light, ":./light.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Lockpick, ":./lockpick.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Miscellaneous, ":./misc.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Npc, ":./npc.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Probe, ":./probe.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Repair, ":./repair.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Static, ":./static.png"));
|
||||
list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Weapon, ":./weapon.png"));
|
||||
std::vector<CSMWorld::UniversalId::Type> types = CSMWorld::UniversalId::listReferenceableTypes();
|
||||
|
||||
for (std::vector<CSMWorld::UniversalId::Type>::const_iterator iter (types.begin());
|
||||
iter!=types.end(); ++iter)
|
||||
{
|
||||
CSMWorld::UniversalId id (*iter, "");
|
||||
|
||||
list.push_back (std::make_pair (id.getType(), id.getIcon().c_str()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -7,14 +7,20 @@
|
|||
#include "dialoguesubview.hpp"
|
||||
#include "scriptsubview.hpp"
|
||||
#include "regionmapsubview.hpp"
|
||||
#include "genericcreator.hpp"
|
||||
#include "cellcreator.hpp"
|
||||
#include "referenceablecreator.hpp"
|
||||
#include "referencecreator.hpp"
|
||||
|
||||
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
||||
{
|
||||
// Regular record tables (including references which are actually sub-records, but are promoted
|
||||
// to top-level records within the editor)
|
||||
manager.add (CSMWorld::UniversalId::Type_Gmsts,
|
||||
new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (false));
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, NullCreatorFactory>);
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Skills,
|
||||
new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (false));
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, NullCreatorFactory>);
|
||||
|
||||
static const CSMWorld::UniversalId::Type sTableTypes[] =
|
||||
{
|
||||
|
@ -27,20 +33,26 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
|||
CSMWorld::UniversalId::Type_Regions,
|
||||
CSMWorld::UniversalId::Type_Birthsigns,
|
||||
CSMWorld::UniversalId::Type_Spells,
|
||||
CSMWorld::UniversalId::Type_Cells,
|
||||
CSMWorld::UniversalId::Type_Referenceables,
|
||||
CSMWorld::UniversalId::Type_References,
|
||||
|
||||
CSMWorld::UniversalId::Type_None // end marker
|
||||
};
|
||||
|
||||
for (int i=0; sTableTypes[i]!=CSMWorld::UniversalId::Type_None; ++i)
|
||||
manager.add (sTableTypes[i], new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (true));
|
||||
manager.add (sTableTypes[i],
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<GenericCreator> >);
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Cells,
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<CellCreator> >);
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Referenceables,
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<ReferenceableCreator> >);
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_References,
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<ReferenceCreator> >);
|
||||
|
||||
// Subviews for editing/viewing individual records
|
||||
manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory<ScriptSubView>);
|
||||
|
||||
// Other stuff (combined record tables)
|
||||
manager.add (CSMWorld::UniversalId::Type_RegionMap, new CSVDoc::SubViewFactory<RegionMapSubView>);
|
||||
|
||||
// manager.add (CSMWorld::UniversalId::Type_Global,
|
||||
// new CSVDoc::SubViewFactoryWithCreateFlag<DialogueSubView> (true));
|
||||
}
|
|
@ -44,19 +44,30 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||
|
||||
std::vector<std::string> CSVWorld::Table::listRevertableSelectedIds() const
|
||||
{
|
||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||
|
||||
/// \todo Do not use hardcoded column numbers
|
||||
std::vector<std::string> revertableIds;
|
||||
|
||||
for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter)
|
||||
if (mProxyModel->columnCount()>0)
|
||||
{
|
||||
std::string id = mProxyModel->data (*iter).toString().toStdString();
|
||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||
|
||||
CSMWorld::RecordBase::State state =
|
||||
static_cast<CSMWorld::RecordBase::State> (mModel->data (mModel->getModelIndex (id, 1)).toInt());
|
||||
for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end();
|
||||
++iter)
|
||||
{
|
||||
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0));
|
||||
|
||||
if (state!=CSMWorld::RecordBase::State_BaseOnly)
|
||||
revertableIds.push_back (id);
|
||||
CSMWorld::RecordBase::State state =
|
||||
static_cast<CSMWorld::RecordBase::State> (
|
||||
mModel->data (mModel->index (index.row(), 1)).toInt());
|
||||
|
||||
if (state!=CSMWorld::RecordBase::State_BaseOnly)
|
||||
{
|
||||
std::string id = mModel->data (mModel->index (index.row(), 0)).
|
||||
toString().toUtf8().constData();
|
||||
|
||||
revertableIds.push_back (id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return revertableIds;
|
||||
|
@ -64,19 +75,30 @@ std::vector<std::string> CSVWorld::Table::listRevertableSelectedIds() const
|
|||
|
||||
std::vector<std::string> CSVWorld::Table::listDeletableSelectedIds() const
|
||||
{
|
||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||
|
||||
/// \todo Do not use hardcoded column numbers
|
||||
std::vector<std::string> deletableIds;
|
||||
|
||||
for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter)
|
||||
if (mProxyModel->columnCount()>0)
|
||||
{
|
||||
std::string id = mProxyModel->data (*iter).toString().toStdString();
|
||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||
|
||||
CSMWorld::RecordBase::State state =
|
||||
static_cast<CSMWorld::RecordBase::State> (mModel->data (mModel->getModelIndex (id, 1)).toInt());
|
||||
for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end();
|
||||
++iter)
|
||||
{
|
||||
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0));
|
||||
|
||||
if (state!=CSMWorld::RecordBase::State_Deleted)
|
||||
deletableIds.push_back (id);
|
||||
CSMWorld::RecordBase::State state =
|
||||
static_cast<CSMWorld::RecordBase::State> (
|
||||
mModel->data (mModel->index (index.row(), 1)).toInt());
|
||||
|
||||
if (state!=CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
std::string id = mModel->data (mModel->index (index.row(), 0)).
|
||||
toString().toUtf8().constData();
|
||||
|
||||
deletableIds.push_back (id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return deletableIds;
|
||||
|
@ -126,7 +148,7 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q
|
|||
if (createAndDelete)
|
||||
{
|
||||
mCreateAction = new QAction (tr ("Add Record"), this);
|
||||
connect (mCreateAction, SIGNAL (triggered()), this, SLOT (createRecord()));
|
||||
connect (mCreateAction, SIGNAL (triggered()), this, SIGNAL (createRequest()));
|
||||
addAction (mCreateAction);
|
||||
}
|
||||
|
||||
|
@ -137,6 +159,17 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q
|
|||
mDeleteAction = new QAction (tr ("Delete Record"), this);
|
||||
connect (mDeleteAction, SIGNAL (triggered()), this, SLOT (deleteRecord()));
|
||||
addAction (mDeleteAction);
|
||||
|
||||
connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||
this, SLOT (tableSizeUpdate()));
|
||||
|
||||
/// \note This signal could instead be connected to a slot that filters out changes not affecting
|
||||
/// the records status column (for permanence reasons)
|
||||
connect (mProxyModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||
this, SLOT (tableSizeUpdate()));
|
||||
|
||||
connect (selectionModel(), SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)),
|
||||
this, SLOT (selectionSizeUpdate ()));
|
||||
}
|
||||
|
||||
void CSVWorld::Table::setEditLock (bool locked)
|
||||
|
@ -154,22 +187,6 @@ CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const
|
|||
mProxyModel->data (mProxyModel->index (row, 0)).toString().toStdString());
|
||||
}
|
||||
|
||||
#include <sstream> /// \todo remove
|
||||
void CSVWorld::Table::createRecord()
|
||||
{
|
||||
if (!mEditLock)
|
||||
{
|
||||
/// \todo ask the user for an ID instead.
|
||||
static int index = 0;
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << "id" << index++;
|
||||
|
||||
mUndoStack.push (new CSMWorld::CreateCommand (*mProxyModel, stream.str()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CSVWorld::Table::revertRecord()
|
||||
{
|
||||
if (!mEditLock)
|
||||
|
@ -231,3 +248,46 @@ void CSVWorld::Table::updateEditorSetting (const QString &settingName, const QSt
|
|||
updateEditorSetting (settingName, settingValue))
|
||||
emit dataChanged (mModel->index (0, i), mModel->index (mModel->rowCount()-1, i));
|
||||
}
|
||||
|
||||
void CSVWorld::Table::tableSizeUpdate()
|
||||
{
|
||||
int size = 0;
|
||||
int deleted = 0;
|
||||
int modified = 0;
|
||||
|
||||
if (mModel->columnCount()>0)
|
||||
{
|
||||
int rows = mModel->rowCount();
|
||||
|
||||
for (int i=0; i<rows; ++i)
|
||||
{
|
||||
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (i, 0));
|
||||
|
||||
/// \todo Do not use hardcoded column numbers
|
||||
int state = mModel->data (mModel->index (index.row(), 1)).toInt();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case CSMWorld::RecordBase::State_BaseOnly: ++size; break;
|
||||
case CSMWorld::RecordBase::State_Modified: ++size; ++modified; break;
|
||||
case CSMWorld::RecordBase::State_ModifiedOnly: ++size; ++modified; break;
|
||||
case CSMWorld::RecordBase:: State_Deleted: ++deleted; ++modified; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tableSizeChanged (size, deleted, modified);
|
||||
}
|
||||
|
||||
void CSVWorld::Table::selectionSizeUpdate()
|
||||
{
|
||||
selectionSizeChanged (selectionModel()->selectedRows().size());
|
||||
}
|
||||
|
||||
void CSVWorld::Table::requestFocus (const std::string& id)
|
||||
{
|
||||
QModelIndex index = mProxyModel->getModelIndex (id, 0);
|
||||
|
||||
if (index.isValid())
|
||||
scrollTo (index, QAbstractItemView::PositionAtTop);
|
||||
}
|
|
@ -60,15 +60,31 @@ namespace CSVWorld
|
|||
|
||||
void editRequest (int row);
|
||||
|
||||
private slots:
|
||||
void selectionSizeChanged (int size);
|
||||
|
||||
void createRecord();
|
||||
void tableSizeChanged (int size, int deleted, int modified);
|
||||
///< \param size Number of not deleted records
|
||||
/// \param deleted Number of deleted records
|
||||
/// \param modified Number of added and modified records
|
||||
|
||||
void createRequest();
|
||||
|
||||
private slots:
|
||||
|
||||
void revertRecord();
|
||||
|
||||
void deleteRecord();
|
||||
|
||||
void editRecord();
|
||||
|
||||
public slots:
|
||||
|
||||
void tableSizeUpdate();
|
||||
|
||||
void selectionSizeUpdate();
|
||||
|
||||
void requestFocus (const std::string& id);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
156
apps/opencs/view/world/tablebottombox.cpp
Normal file
156
apps/opencs/view/world/tablebottombox.cpp
Normal file
|
@ -0,0 +1,156 @@
|
|||
|
||||
#include "tablebottombox.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <QStatusBar>
|
||||
#include <QStackedLayout>
|
||||
#include <QLabel>
|
||||
|
||||
#include "creator.hpp"
|
||||
|
||||
void CSVWorld::TableBottomBox::updateStatus()
|
||||
{
|
||||
if (mShowStatusBar)
|
||||
{
|
||||
static const char *sLabels[4] = { "record", "deleted", "touched", "selected" };
|
||||
static const char *sLabelsPlural[4] = { "records", "deleted", "touched", "selected" };
|
||||
|
||||
std::ostringstream stream;
|
||||
|
||||
bool first = true;
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
{
|
||||
if (mStatusCount[i]>0)
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
stream << ", ";
|
||||
|
||||
stream
|
||||
<< mStatusCount[i] << ' '
|
||||
<< (mStatusCount[i]==1 ? sLabels[i] : sLabelsPlural[i]);
|
||||
}
|
||||
}
|
||||
|
||||
mStatus->setText (QString::fromUtf8 (stream.str().c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFactory,
|
||||
CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, QWidget *parent)
|
||||
: QWidget (parent), mShowStatusBar (false), mCreating (false)
|
||||
{
|
||||
for (int i=0; i<4; ++i)
|
||||
mStatusCount[i] = 0;
|
||||
|
||||
setVisible (false);
|
||||
|
||||
mLayout = new QStackedLayout;
|
||||
mLayout->setContentsMargins (0, 0, 0, 0);
|
||||
|
||||
mStatus = new QLabel;
|
||||
|
||||
mStatusBar = new QStatusBar;
|
||||
|
||||
mStatusBar->addWidget (mStatus);
|
||||
|
||||
mLayout->addWidget (mStatusBar);
|
||||
|
||||
setLayout (mLayout);
|
||||
|
||||
mCreator = creatorFactory.makeCreator (data, undoStack, id);
|
||||
|
||||
mLayout->addWidget (mCreator);
|
||||
|
||||
connect (mCreator, SIGNAL (done()), this, SLOT (createRequestDone()));
|
||||
|
||||
connect (mCreator, SIGNAL (requestFocus (const std::string&)),
|
||||
this, SIGNAL (requestFocus (const std::string&)));
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::setEditLock (bool locked)
|
||||
{
|
||||
if (mCreator)
|
||||
mCreator->setEditLock (locked);
|
||||
}
|
||||
|
||||
CSVWorld::TableBottomBox::~TableBottomBox()
|
||||
{
|
||||
delete mCreator;
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::setStatusBar (bool show)
|
||||
{
|
||||
if (show!=mShowStatusBar)
|
||||
{
|
||||
setVisible (show || mCreating);
|
||||
|
||||
mShowStatusBar = show;
|
||||
|
||||
if (show)
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
bool CSVWorld::TableBottomBox::canCreateAndDelete() const
|
||||
{
|
||||
return mCreator;
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::createRequestDone()
|
||||
{
|
||||
if (!mShowStatusBar)
|
||||
setVisible (false);
|
||||
else
|
||||
updateStatus();
|
||||
|
||||
mLayout->setCurrentWidget (mStatusBar);
|
||||
|
||||
mCreating = false;
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::selectionSizeChanged (int size)
|
||||
{
|
||||
if (mStatusCount[3]!=size)
|
||||
{
|
||||
mStatusCount[3] = size;
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::tableSizeChanged (int size, int deleted, int modified)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (mStatusCount[0]!=size)
|
||||
{
|
||||
mStatusCount[0] = size;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (mStatusCount[1]!=deleted)
|
||||
{
|
||||
mStatusCount[1] = deleted;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (mStatusCount[2]!=modified)
|
||||
{
|
||||
mStatusCount[2] = modified;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::createRequest()
|
||||
{
|
||||
mCreator->reset();
|
||||
mLayout->setCurrentWidget (mCreator);
|
||||
setVisible (true);
|
||||
mCreating = true;
|
||||
}
|
82
apps/opencs/view/world/tablebottombox.hpp
Normal file
82
apps/opencs/view/world/tablebottombox.hpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
#ifndef CSV_WORLD_BOTTOMBOX_H
|
||||
#define CSV_WORLD_BOTTOMBOX_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QLabel;
|
||||
class QStackedLayout;
|
||||
class QStatusBar;
|
||||
class QUndoStack;
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class Data;
|
||||
class UniversalId;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class CreatorFactoryBase;
|
||||
class Creator;
|
||||
|
||||
class TableBottomBox : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
bool mShowStatusBar;
|
||||
QLabel *mStatus;
|
||||
QStatusBar *mStatusBar;
|
||||
int mStatusCount[4];
|
||||
Creator *mCreator;
|
||||
bool mCreating;
|
||||
QStackedLayout *mLayout;
|
||||
|
||||
private:
|
||||
|
||||
// not implemented
|
||||
TableBottomBox (const TableBottomBox&);
|
||||
TableBottomBox& operator= (const TableBottomBox&);
|
||||
|
||||
void updateStatus();
|
||||
|
||||
public:
|
||||
|
||||
TableBottomBox (const CreatorFactoryBase& creatorFactory, CSMWorld::Data& data,
|
||||
QUndoStack& undoStack, const CSMWorld::UniversalId& id, QWidget *parent = 0);
|
||||
|
||||
virtual ~TableBottomBox();
|
||||
|
||||
void setEditLock (bool locked);
|
||||
|
||||
void setStatusBar (bool show);
|
||||
|
||||
bool canCreateAndDelete() const;
|
||||
///< Is record creation and deletion supported?
|
||||
///
|
||||
/// \note The BotomBox does not partake in the deletion of records.
|
||||
|
||||
signals:
|
||||
|
||||
void requestFocus (const std::string& id);
|
||||
///< Request owner of this box to focus the just created \a id. The owner may
|
||||
/// ignore this request.
|
||||
|
||||
private slots:
|
||||
|
||||
void createRequestDone();
|
||||
///< \note This slot being called does not imply success.
|
||||
|
||||
public slots:
|
||||
|
||||
void selectionSizeChanged (int size);
|
||||
|
||||
void tableSizeChanged (int size, int deleted, int modified);
|
||||
///< \param size Number of not deleted records
|
||||
/// \param deleted Number of deleted records
|
||||
/// \param modified Number of added and modified records
|
||||
|
||||
void createRequest();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,22 +1,55 @@
|
|||
|
||||
#include "tablesubview.hpp"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "../../model/doc/document.hpp"
|
||||
|
||||
#include "table.hpp"
|
||||
#include "tablebottombox.hpp"
|
||||
#include "creator.hpp"
|
||||
|
||||
CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
|
||||
bool createAndDelete)
|
||||
const CreatorFactoryBase& creatorFactory)
|
||||
: SubView (id)
|
||||
{
|
||||
setWidget (mTable = new Table (id, document.getData(), document.getUndoStack(), createAndDelete));
|
||||
QVBoxLayout *layout = new QVBoxLayout;
|
||||
|
||||
layout->setContentsMargins (QMargins (0, 0, 0, 0));
|
||||
|
||||
layout->addWidget (mBottom =
|
||||
new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this), 0);
|
||||
|
||||
layout->insertWidget (0, mTable =
|
||||
new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete()), 2);
|
||||
|
||||
QWidget *widget = new QWidget;
|
||||
|
||||
widget->setLayout (layout);
|
||||
|
||||
setWidget (widget);
|
||||
|
||||
connect (mTable, SIGNAL (editRequest (int)), this, SLOT (editRequest (int)));
|
||||
|
||||
connect (mTable, SIGNAL (selectionSizeChanged (int)),
|
||||
mBottom, SLOT (selectionSizeChanged (int)));
|
||||
connect (mTable, SIGNAL (tableSizeChanged (int, int, int)),
|
||||
mBottom, SLOT (tableSizeChanged (int, int, int)));
|
||||
|
||||
mTable->tableSizeUpdate();
|
||||
mTable->selectionSizeUpdate();
|
||||
|
||||
if (mBottom->canCreateAndDelete())
|
||||
connect (mTable, SIGNAL (createRequest()), mBottom, SLOT (createRequest()));
|
||||
|
||||
connect (mBottom, SIGNAL (requestFocus (const std::string&)),
|
||||
mTable, SLOT (requestFocus (const std::string&)));
|
||||
}
|
||||
|
||||
void CSVWorld::TableSubView::setEditLock (bool locked)
|
||||
{
|
||||
mTable->setEditLock (locked);
|
||||
mBottom->setEditLock (locked);
|
||||
}
|
||||
|
||||
void CSVWorld::TableSubView::editRequest (int row)
|
||||
|
@ -28,3 +61,8 @@ void CSVWorld::TableSubView::updateEditorSetting(const QString &settingName, con
|
|||
{
|
||||
mTable->updateEditorSetting(settingName, settingValue);
|
||||
}
|
||||
|
||||
void CSVWorld::TableSubView::setStatusBar (bool show)
|
||||
{
|
||||
mBottom->setStatusBar (show);
|
||||
}
|
|
@ -13,18 +13,26 @@ namespace CSMDoc
|
|||
namespace CSVWorld
|
||||
{
|
||||
class Table;
|
||||
class TableBottomBox;
|
||||
class CreatorFactoryBase;
|
||||
|
||||
class TableSubView : public CSVDoc::SubView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Table *mTable;
|
||||
TableBottomBox *mBottom;
|
||||
|
||||
public:
|
||||
|
||||
TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete);
|
||||
TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
|
||||
const CreatorFactoryBase& creatorFactory);
|
||||
|
||||
virtual void setEditLock (bool locked);
|
||||
void updateEditorSetting (const QString &, const QString &);
|
||||
|
||||
virtual void updateEditorSetting (const QString& key, const QString& value);
|
||||
|
||||
virtual void setStatusBar (bool show);
|
||||
|
||||
private slots:
|
||||
|
||||
|
|
Loading…
Reference in a new issue