proper implementation of gmst type column

This commit is contained in:
Marc Zinnschlag 2013-02-17 17:27:25 +01:00
parent eb6590f7d8
commit 50d61a5b6e
10 changed files with 342 additions and 9 deletions

View file

@ -59,7 +59,7 @@ opencs_units (view/world
)
opencs_units_noqt (view/world
dialoguesubview util subviews
dialoguesubview util subviews enumdelegate vartypedelegate
)

View file

@ -29,7 +29,8 @@ namespace CSMWorld
Display_String,
Display_Integer,
Display_Float,
Display_Var
Display_Var,
Display_VarType
};
std::string mTitle;

View file

@ -79,7 +79,7 @@ namespace CSMWorld
int mType;
FixedRecordTypeColumn (int type)
: Column<ESXRecordT> ("Type", ColumnBase::Display_Integer, 0), mType (type) {}
: Column<ESXRecordT> ("Record Type", ColumnBase::Display_Integer, 0), mType (type) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
@ -92,10 +92,11 @@ namespace CSMWorld
}
};
/// \attention A var type column must be immediately followed by a suitable value column.
template<typename ESXRecordT>
struct VarTypeColumn : public Column<ESXRecordT>
{
VarTypeColumn() : Column<ESXRecordT> ("Type", ColumnBase::Display_Integer) {}
VarTypeColumn() : Column<ESXRecordT> ("Type", ColumnBase::Display_VarType) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{

View file

@ -7,6 +7,8 @@
#include "../../model/doc/document.hpp"
#include "../world/util.hpp"
#include "../world/enumdelegate.hpp"
#include "../world/vartypedelegate.hpp"
#include "view.hpp"
@ -32,6 +34,9 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
: mDocumentManager (documentManager)
{
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
mDelegateFactories->add (CSMWorld::ColumnBase::Display_VarType,
new CSVWorld::VarTypeDelegateFactory (ESM::VT_None, ESM::VT_String, ESM::VT_Int, ESM::VT_Float));
}
CSVDoc::ViewManager::~ViewManager()

View file

@ -0,0 +1,101 @@
#include "enumdelegate.hpp"
#include <stdexcept>
#include <QComboBox>
#include <QApplication>
#include <QUndoStack>
#include "../../model/world/commands.hpp"
void CSVWorld::EnumDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const
{
if (QComboBox *comboBox = dynamic_cast<QComboBox *> (editor))
{
QString value = comboBox->currentText();
for (std::vector<std::pair<int, QString> >::const_iterator iter (mValues.begin());
iter!=mValues.end(); ++iter)
if (iter->second==value)
{
addCommands (model, index, iter->first);
break;
}
}
}
void CSVWorld::EnumDelegate::addCommands (QAbstractItemModel *model,
const QModelIndex& index, int type) const
{
getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, type));
}
CSVWorld::EnumDelegate::EnumDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent)
: CommandDelegate (undoStack, parent), mValues (values)
{
}
QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const
{
QComboBox *comboBox = new QComboBox (parent);
for (std::vector<std::pair<int, QString> >::const_iterator iter (mValues.begin());
iter!=mValues.end(); ++iter)
comboBox->addItem (iter->second);
return comboBox;
}
void CSVWorld::EnumDelegate::setEditorData (QWidget *editor, const QModelIndex& index) const
{
if (QComboBox *comboBox = dynamic_cast<QComboBox *> (editor))
{
int value = index.data (Qt::EditRole).toInt();
std::size_t size = mValues.size();
for (std::size_t i=0; i<size; ++i)
if (mValues[i].first==value)
{
comboBox->setCurrentIndex (i);
break;
}
}
}
void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const
{
QStyleOptionViewItemV4 option2 (option);
int value = index.data().toInt();
for (std::vector<std::pair<int, QString> >::const_iterator iter (mValues.begin());
iter!=mValues.end(); ++iter)
if (iter->first==value)
{
option2.text = iter->second;
QApplication::style()->drawControl (QStyle::CE_ItemViewItem, &option2, painter);
break;
}
}
CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
{
return new EnumDelegate (mValues, undoStack, parent);
}
void CSVWorld::EnumDelegateFactory::add (int value, const QString& name)
{
mValues.push_back (std::make_pair (value, name));
}

View file

@ -0,0 +1,57 @@
#ifndef CSV_WORLD_ENUMDELEGATE_H
#define CSV_WORLD_ENUMDELEGATE_H
#include <vector>
#include <QString>
#include <components/esm/defs.hpp>
#include "util.hpp"
namespace CSVWorld
{
/// \brief Integer value that represents an enum and is interacted with via a combobox
class EnumDelegate : public CommandDelegate
{
std::vector<std::pair<int, QString> > mValues;
private:
virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const;
virtual void addCommands (QAbstractItemModel *model,
const QModelIndex& index, int type) const;
public:
EnumDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent);
virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const;
virtual void setEditorData (QWidget *editor, const QModelIndex& index) const;
virtual void paint (QPainter *painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const;
};
class EnumDelegateFactory : public CommandDelegateFactory
{
std::vector<std::pair<int, QString> > mValues;
public:
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
void add (int value, const QString& name);
};
}
#endif

View file

@ -88,6 +88,19 @@ const CSVWorld::CommandDelegateFactoryCollection& CSVWorld::CommandDelegateFacto
}
QUndoStack& CSVWorld::CommandDelegate::getUndoStack() const
{
return mUndoStack;
}
void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const
{
NastyTableModelHack hack (*model);
QStyledItemDelegate::setModelData (editor, &hack, index);
mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData()));
}
CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent)
: QStyledItemDelegate (parent), mUndoStack (undoStack), mEditLock (false)
{}
@ -97,14 +110,18 @@ void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemMode
{
if (!mEditLock)
{
NastyTableModelHack hack (*model);
QStyledItemDelegate::setModelData (editor, &hack, index);
mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData()));
setModelDataImp (editor, model, index);
}
///< \todo provide some kind of feedback to the user, indicating that editing is currently not possible.
}
void CSVWorld::CommandDelegate::setEditLock (bool locked)
void CSVWorld::CommandDelegate::setEditLock (bool locked)
{
mEditLock = locked;
}
bool CSVWorld::CommandDelegate::isEditLocked() const
{
return mEditLock;
}

View file

@ -85,13 +85,23 @@ namespace CSVWorld
QUndoStack& mUndoStack;
bool mEditLock;
protected:
QUndoStack& getUndoStack() const;
virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const;
public:
CommandDelegate (QUndoStack& undoStack, QObject *parent);
void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const;
virtual void setModelData (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const;
void setEditLock (bool locked);
bool isEditLocked() const;
};
}

View file

@ -0,0 +1,103 @@
#include "vartypedelegate.hpp"
#include <QUndoStack>
#include "../../model/world/commands.hpp"
void CSVWorld::VarTypeDelegate::addCommands (QAbstractItemModel *model, const QModelIndex& index, int type)
const
{
QModelIndex next = model->index (index.row(), index.column()+1);
QVariant old = model->data (next);
QVariant value;
switch (type)
{
case ESM::VT_Short:
case ESM::VT_Int:
case ESM::VT_Long:
value = old.toInt();
break;
case ESM::VT_Float:
value = old.toFloat();
break;
case ESM::VT_String:
value = old.toString();
break;
default: break; // ignore the rest
}
getUndoStack().beginMacro (
"Modify " + model->headerData (index.column(), Qt::Horizontal, Qt::DisplayRole).toString());
getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, type));
getUndoStack().push (new CSMWorld::ModifyCommand (*model, next, value));
getUndoStack().endMacro();
}
CSVWorld::VarTypeDelegate::VarTypeDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent)
: EnumDelegate (values, undoStack, parent)
{}
CSVWorld::VarTypeDelegateFactory::VarTypeDelegateFactory (ESM::VarType type0,
ESM::VarType type1, ESM::VarType type2, ESM::VarType type3)
{
if (type0!=ESM::VT_Unknown)
add (type0);
if (type1!=ESM::VT_Unknown)
add (type1);
if (type2!=ESM::VT_Unknown)
add (type2);
if (type3!=ESM::VT_Unknown)
add (type3);
}
CSVWorld::CommandDelegate *CSVWorld::VarTypeDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
{
return new VarTypeDelegate (mValues, undoStack, parent);
}
void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type)
{
struct Name
{
ESM::VarType mType;
const char *mName;
};
static const Name sNames[] =
{
{ ESM::VT_None, "empty" },
{ ESM::VT_Short, "short" },
{ ESM::VT_Int, "long" },
{ ESM::VT_Long, "long" },
{ ESM::VT_Float, "float" },
{ ESM::VT_String, "string" },
{ ESM::VT_Unknown, 0 } // end marker
};
for (int i=0; sNames[i].mName; ++i)
if (sNames[i].mType==type)
{
mValues.push_back (std::make_pair (type, sNames[i].mName));
return;
}
throw std::logic_error ("Unsupported variable type");
}

View file

@ -0,0 +1,38 @@
#ifndef CSV_WORLD_VARTYPEDELEGATE_H
#define CSV_WORLD_VARTYPEDELEGATE_H
#include "enumdelegate.hpp"
namespace CSVWorld
{
class VarTypeDelegate : public EnumDelegate
{
private:
virtual void addCommands (QAbstractItemModel *model,
const QModelIndex& index, int type) const;
public:
VarTypeDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent);
};
class VarTypeDelegateFactory : public CommandDelegateFactory
{
std::vector<std::pair<int, QString> > mValues;
public:
VarTypeDelegateFactory (ESM::VarType type0 = ESM::VT_Unknown,
ESM::VarType type1 = ESM::VT_Unknown, ESM::VarType type2 = ESM::VT_Unknown,
ESM::VarType type3 = ESM::VT_Unknown);
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
void add (ESM::VarType type);
};
}
#endif