basic (non-editable) subview for global variables

actorid
Marc Zinnschlag 12 years ago
parent 1dd63e9fb6
commit ef9575498f

@ -4,11 +4,11 @@ set (OPENCS_SRC
model/doc/documentmanager.cpp model/doc/document.cpp
model/world/universalid.cpp
model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp
view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp
view/world/subview.cpp
view/world/subview.cpp view/world/globals.cpp
)
set (OPENCS_HDR
@ -16,11 +16,12 @@ set (OPENCS_HDR
model/doc/documentmanager.hpp model/doc/document.hpp
model/world/universalid.hpp
model/world/universalid.hpp model/world/record.hpp model/world/idcollection.hpp model/world/data.hpp
model/world/idtable.hpp model/world/columns.hpp
view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp
view/world/subview.hpp
view/world/subview.hpp view/world/globals.hpp
)
set (OPENCS_US

@ -5,6 +5,9 @@
#include <QtGui/QApplication>
#include "model/doc/document.hpp"
#include "model/world/data.hpp"
CS::Editor::Editor() : mViewManager (mDocumentManager), mNewDocumentIndex (0)
{
connect (&mViewManager, SIGNAL (newDocumentRequest ()), this, SLOT (createDocument ()));
@ -17,6 +20,21 @@ void CS::Editor::createDocument()
stream << "NewDocument" << (++mNewDocumentIndex);
CSMDoc::Document *document = mDocumentManager.addDocument (stream.str());
static const char *sGlobals[] =
{
"Day", "DaysPassed", "GameHour", "Month", "PCRace", "PCVampire", "PCWerewolf", "PCYear", 0
};
for (int i=0; sGlobals[i]; ++i)
{
ESM::Global record;
record.mId = sGlobals[i];
record.mValue = i==0 ? 1 : 0;
record.mType = ESM::VT_Float;
document->getData().getGlobals().add (record);
}
mViewManager.addView (document);
}

@ -104,4 +104,14 @@ void CSMDoc::Document::verifying()
mVerifyTimer.stop();
emit stateChanged (getState(), this);
}
}
const CSMWorld::Data& CSMDoc::Document::getData() const
{
return mData;
}
CSMWorld::Data& CSMDoc::Document::getData()
{
return mData;
}

@ -7,6 +7,8 @@
#include <QObject>
#include <QTimer>
#include "../world/data.hpp"
namespace CSMDoc
{
class Document : public QObject
@ -25,8 +27,11 @@ namespace CSMDoc
State_Searching = 32 // not implemented yet
};
private:
std::string mName; ///< \todo replace name with ESX list
QUndoStack mUndoStack;
CSMWorld::Data mData;
int mSaveCount; ///< dummy implementation -> remove when proper save is implemented.
QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented.
@ -56,6 +61,10 @@ namespace CSMDoc
void abortOperation (int type);
const CSMWorld::Data& getData() const;
CSMWorld::Data& getData();
signals:
void stateChanged (int state, CSMDoc::Document *document);

@ -0,0 +1,21 @@
#ifndef CSM_WOLRD_COLUMNS_H
#define CSM_WOLRD_COLUMNS_H
#include "idcollection.hpp"
namespace CSMWorld
{
template<typename ESXRecordT>
struct FloatValueColumn : public Column<ESXRecordT>
{
FloatValueColumn() : Column<ESXRecordT> ("Value") {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mValue;
}
};
}
#endif

@ -0,0 +1,47 @@
#include "data.hpp"
#include <stdexcept>
#include <QAbstractTableModel>
#include <components/esm/loadglob.hpp>
#include "idtable.hpp"
#include "columns.hpp"
CSMWorld::Data::Data()
{
mGlobals.addColumn (new FloatValueColumn<ESM::Global>);
mModels.insert (std::make_pair (
UniversalId (UniversalId::Type_Globals),
new IdTable (&mGlobals)
));
}
CSMWorld::Data::~Data()
{
for (std::map<UniversalId, QAbstractTableModel *>::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter)
delete iter->second;
}
const CSMWorld::IdCollection<ESM::Global>& CSMWorld::Data::getGlobals() const
{
return mGlobals;
}
CSMWorld::IdCollection<ESM::Global>& CSMWorld::Data::getGlobals()
{
return mGlobals;
}
QAbstractTableModel *CSMWorld::Data::getTableModel (const UniversalId& id)
{
std::map<UniversalId, QAbstractTableModel *>::iterator iter = mModels.find (id);
if (iter==mModels.end())
throw std::logic_error ("No table model available for " + id.toString());
return iter->second;
}

@ -0,0 +1,39 @@
#ifndef CSM_WOLRD_IDLIST_H
#define CSM_WOLRD_IDLIST_H
#include <map>
#include <components/esm/loadglob.hpp>
#include "idcollection.hpp"
#include "universalid.hpp"
class QAbstractTableModel;
namespace CSMWorld
{
class Data
{
IdCollection<ESM::Global> mGlobals;
std::map<UniversalId, QAbstractTableModel *> mModels;
// not implemented
Data (const Data&);
Data& operator= (const Data&);
public:
Data();
~Data();
const IdCollection<ESM::Global>& getGlobals() const;
IdCollection<ESM::Global>& getGlobals();
QAbstractTableModel *getTableModel (const UniversalId& id);
///< If no table model is available for \æ id, an exception is thrown.
};
}
#endif

@ -0,0 +1,6 @@
#include "idcollection.hpp"
CSMWorld::IdCollectionBase::IdCollectionBase() {}
CSMWorld::IdCollectionBase::~IdCollectionBase() {}

@ -0,0 +1,158 @@
#ifndef CSM_WOLRD_IDCOLLECTION_H
#define CSM_WOLRD_IDCOLLECTION_H
#include <vector>
#include <map>
#include <string>
#include <algorithm>
#include <cctype>
#include <QVariant>
#include "record.hpp"
namespace CSMWorld
{
template<typename ESXRecordT>
struct Column
{
std::string mTitle;
Column (const std::string& title) : mTitle (title) {}
virtual ~Column() {}
virtual QVariant get (const Record<ESXRecordT>& record) const = 0;
};
class IdCollectionBase
{
// not implemented
IdCollectionBase (const IdCollectionBase&);
IdCollectionBase& operator= (const IdCollectionBase&);
public:
IdCollectionBase();
virtual ~IdCollectionBase();
virtual int getSize() const = 0;
virtual std::string getId (int index) const = 0;
virtual int getColumns() const = 0;
virtual std::string getTitle (int column) const = 0;
virtual QVariant getData (int index, int column) const = 0;
};
///< \brief Collection of ID-based records
template<typename ESXRecordT>
class IdCollection : public IdCollectionBase
{
std::vector<Record<ESXRecordT> > mRecords;
std::map<std::string, int> mIndex;
std::vector<Column<ESXRecordT> *> mColumns;
// not implemented
IdCollection (const IdCollection&);
IdCollection& operator= (const IdCollection&);
public:
IdCollection();
virtual ~IdCollection();
void add (const ESXRecordT& record);
///< Add a new record (modified)
virtual int getSize() const;
virtual std::string getId (int index) const;
virtual int getColumns() const;
virtual QVariant getData (int index, int column) const;
virtual std::string getTitle (int column) const;
virtual void addColumn (Column<ESXRecordT> *column);
};
template<typename ESXRecordT>
IdCollection<ESXRecordT>::IdCollection()
{}
template<typename ESXRecordT>
IdCollection<ESXRecordT>::~IdCollection()
{
for (typename std::vector<Column<ESXRecordT> *>::iterator iter (mColumns.begin()); iter!=mColumns.end(); ++iter)
delete *iter;
}
template<typename ESXRecordT>
void IdCollection<ESXRecordT>::add (const ESXRecordT& record)
{
std::string id;
std::transform (record.mId.begin(), record.mId.end(), std::back_inserter (id),
(int(*)(int)) std::tolower);
std::map<std::string, int>::iterator iter = mIndex.find (id);
if (iter==mIndex.end())
{
Record<ESXRecordT> record2;
record2.mState = Record<ESXRecordT>::State_ModifiedOnly;
record2.mModified = record;
mRecords.push_back (record2);
mIndex.insert (std::make_pair (id, mRecords.size()-1));
}
else
{
mRecords[iter->second].setModified (record);
}
}
template<typename ESXRecordT>
int IdCollection<ESXRecordT>::getSize() const
{
return mRecords.size();
}
template<typename ESXRecordT>
std::string IdCollection<ESXRecordT>::getId (int index) const
{
return mRecords.at (index).get().mId;
}
template<typename ESXRecordT>
int IdCollection<ESXRecordT>::getColumns() const
{
return mColumns.size();
}
template<typename ESXRecordT>
QVariant IdCollection<ESXRecordT>::getData (int index, int column) const
{
return mColumns.at (column)->get (mRecords.at (index));
}
template<typename ESXRecordT>
std::string IdCollection<ESXRecordT>::getTitle (int column) const
{
return mColumns.at (column)->mTitle;
}
template<typename ESXRecordT>
void IdCollection<ESXRecordT>::addColumn (Column<ESXRecordT> *column)
{
mColumns.push_back (column);
}
}
#endif

@ -0,0 +1,55 @@
#include "idtable.hpp"
#include "idcollection.hpp"
CSMWorld::IdTable::IdTable (IdCollectionBase *idCollection) : mIdCollection (idCollection)
{
}
CSMWorld::IdTable::~IdTable()
{
}
int CSMWorld::IdTable::rowCount (const QModelIndex & parent) const
{
if (parent.isValid())
return 0;
return mIdCollection->getSize();
}
int CSMWorld::IdTable::columnCount (const QModelIndex & parent) const
{
if (parent.isValid())
return 0;
return 1+mIdCollection->getColumns();
}
QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const
{
if (role!=Qt::DisplayRole)
return QVariant();
if (index.column()==0)
return QVariant (tr (mIdCollection->getId (index.row()).c_str()));
return mIdCollection->getData (index.row(), index.column()-1);
}
QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation, int role) const
{
if (role!=Qt::DisplayRole)
return QVariant();
if (orientation==Qt::Vertical)
return QVariant();
if (section==0)
return QVariant (tr ("ID"));
return tr (mIdCollection->getTitle (section-1).c_str());
}

@ -0,0 +1,37 @@
#ifndef CSM_WOLRD_IDTABLE_H
#define CSM_WOLRD_IDTABLE_H
#include <QAbstractTableModel>
namespace CSMWorld
{
class IdCollectionBase;
class IdTable : public QAbstractTableModel
{
Q_OBJECT
IdCollectionBase *mIdCollection;
// not implemented
IdTable (const IdTable&);
IdTable& operator= (const IdTable&);
public:
IdTable (IdCollectionBase *idCollection);
///< The ownership of \a idCollection is not transferred.
virtual ~IdTable();
int rowCount (const QModelIndex & parent = QModelIndex()) const;
int columnCount (const QModelIndex & parent = QModelIndex()) const;
QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const;
QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
};
}
#endif

@ -0,0 +1,76 @@
#ifndef CSM_WOLRD_RECORD_H
#define CSM_WOLRD_RECORD_H
#include <stdexcept>
namespace CSMWorld
{
template <typename ESXRecordT>
struct Record
{
enum state
{
State_BaseOnly, // defined in base only
State_Modified, // exists in base, but has been modified
State_ModifiedOnly, // newly created in modified
State_Deleted // exists in base, but has been deleted
};
ESXRecordT mBase;
ESXRecordT mModified;
state mState;
bool isDeleted() const;
bool isModified() const;
const ESXRecordT& get() const;
///< Throws an exception, if the record is deleted.
ESXRecordT& get();
///< Throws an exception, if the record is deleted.
void setModified (const ESXRecordT& modified);
};
template <typename ESXRecordT>
bool Record<ESXRecordT>::isDeleted() const
{
return mState==State_Deleted;
}
template <typename ESXRecordT>
bool Record<ESXRecordT>::isModified() const
{
return mState==State_Modified || mState==State_ModifiedOnly;
}
template <typename ESXRecordT>
const ESXRecordT& Record<ESXRecordT>::get() const
{
if (isDeleted())
throw std::logic_error ("attempt to access a deleted record");
return mState==State_BaseOnly ? mBase : mModified;
}
template <typename ESXRecordT>
ESXRecordT& Record<ESXRecordT>::get()
{
if (isDeleted())
throw std::logic_error ("attempt to access a deleted record");
return mState==State_BaseOnly ? mBase : mModified;
}
template <typename ESXRecordT>
void Record<ESXRecordT>::setModified (const ESXRecordT& modified)
{
mModified = modified;
if (mState!=State_ModifiedOnly)
mState = State_Modified;
}
}
#endif

@ -17,6 +17,7 @@ namespace
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_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
};
@ -117,6 +118,23 @@ bool CSMWorld::UniversalId::isEqual (const UniversalId& universalId) const
}
}
bool CSMWorld::UniversalId::isLess (const UniversalId& universalId) const
{
if (mType<universalId.mType)
return true;
if (mType>universalId.mType)
return false;
switch (mArgumentType)
{
case ArgumentType_Id: return mId<universalId.mId;
case ArgumentType_Index: return mIndex<universalId.mIndex;
default: return false;
}
}
std::string CSMWorld::UniversalId::getTypeName() const
{
const TypeData *typeData = mArgumentType==ArgumentType_None ? sNoArg :
@ -145,17 +163,22 @@ std::string CSMWorld::UniversalId::toString() const
return stream.str();
}
bool operator== (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right)
bool CSMWorld::operator== (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right)
{
return left.isEqual (right);
}
bool operator!= (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right)
bool CSMWorld::operator!= (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right)
{
return !left.isEqual (right);
}
std::ostream& operator< (std::ostream& stream, const CSMWorld::UniversalId& universalId)
bool CSMWorld::operator< (const UniversalId& left, const UniversalId& right)
{
return left.isLess (right);
}
std::ostream& CSMWorld::operator< (std::ostream& stream, const CSMWorld::UniversalId& universalId)
{
return stream << universalId.toString();
}

@ -30,7 +30,8 @@ namespace CSMWorld
enum Type
{
Type_None
Type_None,
Type_Globals
};
private:
@ -66,6 +67,8 @@ namespace CSMWorld
bool isEqual (const UniversalId& universalId) const;
bool isLess (const UniversalId& universalId) const;
std::string getTypeName() const;
std::string toString() const;
@ -74,6 +77,8 @@ namespace CSMWorld
bool operator== (const UniversalId& left, const UniversalId& right);
bool operator!= (const UniversalId& left, const UniversalId& right);
bool operator< (const UniversalId& left, const UniversalId& right);
std::ostream& operator< (std::ostream& stream, const UniversalId& universalId);
}

@ -2,6 +2,7 @@
#include "view.hpp"
#include <sstream>
#include <stdexcept>
#include <QCloseEvent>
#include <QMenuBar>
@ -10,6 +11,7 @@
#include "../../model/doc/document.hpp"
#include "../world/subview.hpp"
#include "../world/globals.hpp"
#include "viewmanager.hpp"
#include "operations.hpp"
@ -59,16 +61,16 @@ void CSVDoc::View::setupViewMenu()
QAction *newWindow = new QAction (tr ("&New View"), this);
connect (newWindow, SIGNAL (triggered()), this, SLOT (newView()));
view->addAction (newWindow);
QAction *test = new QAction (tr ("Add test Subview"), this);
connect (test, SIGNAL (triggered()), this, SLOT (addTestSubView()));
view->addAction (test);
}
void CSVDoc::View::setupWorldMenu()
{
QMenu *world = menuBar()->addMenu (tr ("&World"));
QAction *globals = new QAction (tr ("Globals"), this);
connect (globals, SIGNAL (triggered()), this, SLOT (addGlobalsSubView()));
world->addAction (globals);
mVerify = new QAction (tr ("&Verify"), this);
connect (mVerify, SIGNAL (triggered()), this, SLOT (verify()));
world->addAction (mVerify);
@ -124,6 +126,16 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to
updateTitle();
setupUi();
mSubViewFactories.insert (std::make_pair (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals),
new CSVWorld::SubViewFactory<CSVWorld::Globals>()));
}
CSVDoc::View::~View()
{
for (std::map<CSMWorld::UniversalId, CSVWorld::SubViewFactoryBase *>::iterator iter (mSubViewFactories.begin());
iter!=mSubViewFactories.end(); ++iter)
delete iter->second;
}
const CSMDoc::Document *CSVDoc::View::getDocument() const
@ -176,8 +188,13 @@ 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)
CSVWorld::SubView *view = new CSVWorld::SubView (id);
addDockWidget (Qt::RightDockWidgetArea, view);
std::map<CSMWorld::UniversalId, CSVWorld::SubViewFactoryBase *>::iterator iter = mSubViewFactories.find (id);
if (iter==mSubViewFactories.end())
throw std::logic_error ("can't create subview for " + id.toString());
CSVWorld::SubView *view = iter->second->makeSubView (id, mDocument->getData());
addDockWidget (Qt::TopDockWidgetArea, view);
view->show();
}
@ -201,7 +218,7 @@ void CSVDoc::View::verify()
mDocument->verify();
}
void CSVDoc::View::addTestSubView()
void CSVDoc::View::addGlobalsSubView()
{
addSubView (CSMWorld::UniversalId::Type_None);
addSubView (CSMWorld::UniversalId::Type_Globals);
}

@ -2,6 +2,7 @@
#define CSV_DOC_VIEW_H
#include <vector>
#include <map>
#include <QMainWindow>
@ -17,6 +18,11 @@ namespace CSMWorld
class UniversalId;
}
namespace CSVWorld
{
struct SubViewFactoryBase;
}
namespace CSVDoc
{
class ViewManager;
@ -36,6 +42,7 @@ namespace CSVDoc
QAction *mVerify;
std::vector<QAction *> mEditingActions;
Operations *mOperations;
std::map<CSMWorld::UniversalId, CSVWorld::SubViewFactoryBase *> mSubViewFactories;
// not implemented
View (const View&);
@ -64,6 +71,8 @@ namespace CSVDoc
View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews);
///< The ownership of \a document is not transferred to *this.
virtual ~View();
const CSMDoc::Document *getDocument() const;
CSMDoc::Document *getDocument();
@ -90,7 +99,7 @@ namespace CSVDoc
void verify();
void addTestSubView(); ///< \todo remove
void addGlobalsSubView();
};
}

@ -0,0 +1,26 @@
#include "globals.hpp"
#include <QTableView>
#include <QHeaderView>
#include <QSortFilterProxyModel>
#include "../../model/world/data.hpp"
CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data)
: SubView (id)
{
QTableView *table = new QTableView();
setWidget (table);
QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel (this);
proxyModel->setSourceModel (data.getTableModel (id));
table->setModel (proxyModel);
table->horizontalHeader()->setResizeMode (QHeaderView::Interactive);
table->verticalHeader()->hide();
table->setSortingEnabled (true);
/// \todo make initial layout fill the whole width of the table
}

@ -0,0 +1,17 @@
#ifndef CSV_WORLD_GLOBALS_H
#define CSV_WORLD_GLOBALS_H
#include "subview.hpp"
namespace CSVWorld
{
class Globals : public SubView
{
public:
Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data);
};
}
#endif

@ -5,6 +5,11 @@
#include <QDockWidget>
namespace CSMWorld
{
class Data;
}
namespace CSVWorld
{
class SubView : public QDockWidget
@ -23,6 +28,23 @@ namespace CSVWorld
CSMWorld::UniversalId getUniversalId() const;
};
struct SubViewFactoryBase
{
virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data) = 0;
};
template<class SubViewT>
struct SubViewFactory : public SubViewFactoryBase
{
virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data);
};
template<class SubViewT>
SubView *SubViewFactory<SubViewT>::makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data)
{
return new SubViewT (id, data);
}
}
#endif

@ -18,7 +18,7 @@ class ESMWriter;
struct Global
{
std::string mId;
unsigned mValue;
float mValue;
VarType mType;
void load(ESMReader &esm);

Loading…
Cancel
Save