Merge branch 'master' into feature-cloning-enhancements

c++11
Stanislav Bas 10 years ago
commit 9d274ee156

@ -26,7 +26,7 @@ opencs_units_noqt (model/world
universalid record commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection
idcompletionmanager
idcompletionmanager metadata
)
opencs_hdrs_noqt (model/world
@ -64,7 +64,7 @@ opencs_units (view/world
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
cellcreator referenceablecreator referencecreator scenesubview
infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable
dialoguespinbox
dialoguespinbox recordbuttonbar
)
opencs_units_noqt (view/world

@ -2282,9 +2282,6 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
if (mNew)
{
mData.setDescription ("");
mData.setAuthor ("");
if (mContentFiles.size()==1)
createBase();
}

@ -53,18 +53,16 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages)
mState.getWriter().clearMaster();
mState.getWriter().setFormat (0);
if (mSimple)
{
mState.getWriter().setAuthor ("");
mState.getWriter().setDescription ("");
mState.getWriter().setRecordCount (0);
mState.getWriter().setFormat (ESM::Header::CurrentFormat);
}
else
{
mState.getWriter().setAuthor (mDocument.getData().getAuthor());
mState.getWriter().setDescription (mDocument.getData().getDescription());
mDocument.getData().getMetaData().save (mState.getWriter());
mState.getWriter().setRecordCount (
mDocument.getData().count (CSMWorld::RecordBase::State_Modified) +
mDocument.getData().count (CSMWorld::RecordBase::State_ModifiedOnly) +

@ -356,6 +356,14 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
formatId->setToolTip ("(Default: Blue) Use one of the following formats:" + tooltip);
}
declareSection ("general-input", "General Input");
{
Setting *cycle = createSetting (Type_CheckBox, "cycle", "Cyclic next/previous");
cycle->setDefaultValue ("false");
cycle->setToolTip ("When using next/previous functions at the last/first item of a "
"list go to the first/last item");
}
{
/******************************************************************
* There are three types of values:

@ -100,7 +100,8 @@ bool CSMWorld::ColumnBase::isId (Display display)
bool CSMWorld::ColumnBase::isText (Display display)
{
return display==Display_String || display==Display_LongString;
return display==Display_String || display==Display_LongString ||
display==Display_String32 || display==Display_LongString256;
}
bool CSMWorld::ColumnBase::isScript (Display display)

@ -123,6 +123,8 @@ namespace CSMWorld
Display_InfoCondVar,
Display_InfoCondComp,
Display_RaceSkill,
Display_String32,
Display_LongString256,
//top level columns that nest other columns
Display_NestedHeader

@ -2308,6 +2308,78 @@ namespace CSMWorld
return true;
}
};
template<typename ESXRecordT>
struct FormatColumn : public Column<ESXRecordT>
{
FormatColumn()
: Column<ESXRecordT> (Columns::ColumnId_FileFormat, ColumnBase::Display_Integer)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mFormat;
}
virtual bool isEditable() const
{
return false;
}
};
template<typename ESXRecordT>
struct AuthorColumn : public Column<ESXRecordT>
{
AuthorColumn()
: Column<ESXRecordT> (Columns::ColumnId_Author, ColumnBase::Display_String32)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mAuthor.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mAuthor = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct FileDescriptionColumn : public Column<ESXRecordT>
{
FileDescriptionColumn()
: Column<ESXRecordT> (Columns::ColumnId_FileDescription, ColumnBase::Display_LongString256)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mDescription.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mDescription = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
}
#endif

@ -311,6 +311,10 @@ namespace CSMWorld
{ ColumnId_WaterLevel, "Water Level" },
{ ColumnId_MapColor, "Map Color" },
{ ColumnId_FileFormat, "File Format" },
{ ColumnId_FileDescription, "File Description" },
{ ColumnId_Author, "Author" },
{ ColumnId_UseValue1, "Use value 1" },
{ ColumnId_UseValue2, "Use value 2" },
{ ColumnId_UseValue3, "Use value 3" },

@ -302,6 +302,10 @@ namespace CSMWorld
ColumnId_WaterLevel = 273,
ColumnId_MapColor = 274,
ColumnId_FileFormat = 275,
ColumnId_FileDescription = 276,
ColumnId_Author = 277,
// Allocated to a separate value range, so we don't get a collision should we ever need
// to extend the number of use values.
ColumnId_UseValue1 = 0x10000,

@ -475,6 +475,14 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mDebugProfiles.addColumn (new ScriptColumn<ESM::DebugProfile> (
ScriptColumn<ESM::DebugProfile>::Type_Lines));
mMetaData.appendBlankRecord ("sys::meta");
mMetaData.addColumn (new StringIdColumn<MetaData> (true));
mMetaData.addColumn (new RecordStateColumn<MetaData>);
mMetaData.addColumn (new FormatColumn<MetaData>);
mMetaData.addColumn (new AuthorColumn<MetaData>);
mMetaData.addColumn (new FileDescriptionColumn<MetaData>);
addModel (new IdTable (&mGlobals), UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst);
addModel (new IdTable (&mSkills), UniversalId::Type_Skill);
@ -515,6 +523,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
UniversalId::Type_Texture);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Videos)),
UniversalId::Type_Video);
addModel (new IdTable (&mMetaData), UniversalId::Type_MetaData);
mRefLoadCache.clear(); // clear here rather than startLoading() and continueLoading() for multiple content files
}
@ -803,6 +812,11 @@ const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id)
return mResourcesManager.get (id.getType());
}
const CSMWorld::MetaData& CSMWorld::Data::getMetaData() const
{
return mMetaData.getRecord (0).get();
}
QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id)
{
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
@ -847,9 +861,15 @@ int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base
mBase = base;
mProject = project;
mAuthor = mReader->getAuthor();
mDescription = mReader->getDesc();
if (!mProject && !mBase)
{
MetaData metaData;
metaData.mId = "sys::meta";
metaData.load (*mReader);
mMetaData.setRecord (0, Record<MetaData> (RecordBase::State_ModifiedOnly, 0, &metaData));
}
return mReader->getRecordCount();
}
@ -1103,26 +1123,6 @@ int CSMWorld::Data::count (RecordBase::State state) const
count (state, mPathgrids);
}
void CSMWorld::Data::setDescription (const std::string& description)
{
mDescription = description;
}
std::string CSMWorld::Data::getDescription() const
{
return mDescription;
}
void CSMWorld::Data::setAuthor (const std::string& author)
{
mAuthor = author;
}
std::string CSMWorld::Data::getAuthor() const
{
return mAuthor;
}
std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
{
std::vector<std::string> ids;

@ -44,6 +44,7 @@
#include "infocollection.hpp"
#include "nestedinfocollection.hpp"
#include "pathgrid.hpp"
#include "metadata.hpp"
#ifndef Q_MOC_RUN
#include "subcellcollection.hpp"
#endif
@ -94,11 +95,10 @@ namespace CSMWorld
RefIdCollection mReferenceables;
RefCollection mRefs;
IdCollection<ESM::Filter> mFilters;
Collection<MetaData> mMetaData;
const ResourcesManager& mResourcesManager;
std::vector<QAbstractItemModel *> mModels;
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
std::string mAuthor;
std::string mDescription;
ESM::ESMReader *mReader;
const ESM::Dialogue *mDialogue; // last loaded dialogue
bool mBase;
@ -238,6 +238,8 @@ namespace CSMWorld
/// Throws an exception, if \a id does not match a resources list.
const Resources& getResources (const UniversalId& id) const;
const MetaData& getMetaData() const;
QAbstractItemModel *getTableModel (const UniversalId& id);
///< If no table model is available for \a id, an exception is thrown.
///
@ -267,14 +269,6 @@ namespace CSMWorld
int count (RecordBase::State state) const;
///< Return number of top-level records with the given \a state.
void setDescription (const std::string& description);
std::string getDescription() const;
void setAuthor (const std::string& author);
std::string getAuthor() const;
signals:
void idListChanged();

@ -97,7 +97,8 @@ bool CSMWorld::InfoCollection::reorderRows (int baseIndex, const std::vector<int
return false;
// Check that topics match
if (getRecord (baseIndex).get().mTopicId!=getRecord (lastIndex).get().mTopicId)
if (!Misc::StringUtils::ciEqual(getRecord(baseIndex).get().mTopicId,
getRecord(lastIndex).get().mTopicId))
return false;
// reorder

@ -1,12 +1,24 @@
#include "infotableproxymodel.hpp"
#include <components/misc/stringops.hpp>
#include "idtablebase.hpp"
#include "columns.hpp"
namespace
{
QString toLower(const QString &str)
{
return QString::fromUtf8(Misc::StringUtils::lowerCase(str.toStdString()).c_str());
}
}
CSMWorld::InfoTableProxyModel::InfoTableProxyModel(CSMWorld::UniversalId::Type type, QObject *parent)
: IdTableProxyModel(parent),
mType(type),
mSourceModel(NULL)
mSourceModel(NULL),
mInfoColumnId(type == UniversalId::Type_TopicInfos ? Columns::ColumnId_Topic :
Columns::ColumnId_Journal)
{
Q_ASSERT(type == UniversalId::Type_TopicInfos || type == UniversalId::Type_JournalInfos);
}
@ -15,44 +27,53 @@ void CSMWorld::InfoTableProxyModel::setSourceModel(QAbstractItemModel *sourceMod
{
IdTableProxyModel::setSourceModel(sourceModel);
mSourceModel = dynamic_cast<IdTableBase *>(sourceModel);
connect(mSourceModel,
SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
this,
SLOT(modelDataChanged(const QModelIndex &, const QModelIndex &)));
mFirstRowCache.clear();
if (mSourceModel != NULL)
{
connect(mSourceModel,
SIGNAL(rowsInserted(const QModelIndex &, int, int)),
this,
SLOT(modelRowsChanged(const QModelIndex &, int, int)));
connect(mSourceModel,
SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
this,
SLOT(modelRowsChanged(const QModelIndex &, int, int)));
mFirstRowCache.clear();
}
}
bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
QModelIndex first = mSourceModel->index(getFirstInfoRow(left.row()), left.column());
QModelIndex second = mSourceModel->index(getFirstInfoRow(right.row()), right.column());
// If both indexes are belonged to the same Topic/Journal, compare their original rows only
if (first.row() == second.row())
{
return sortOrder() == Qt::AscendingOrder ? left.row() < right.row() : right.row() < left.row();
}
return IdTableProxyModel::lessThan(first, second);
}
int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const
{
Columns::ColumnId columnId = Columns::ColumnId_Topic;
if (mType == UniversalId::Type_JournalInfos)
{
columnId = Columns::ColumnId_Journal;
}
int column = mSourceModel->findColumnIndex(columnId);
QString info = mSourceModel->data(mSourceModel->index(currentRow, column)).toString();
int row = currentRow;
int column = mSourceModel->findColumnIndex(mInfoColumnId);
QString info = toLower(mSourceModel->data(mSourceModel->index(row, column)).toString());
if (mFirstRowCache.contains(info))
{
return mFirstRowCache[info];
}
while (--currentRow >= 0 &&
mSourceModel->data(mSourceModel->index(currentRow, column)) == info);
while (--row >= 0 &&
toLower(mSourceModel->data(mSourceModel->index(row, column)).toString()) == info);
++row;
mFirstRowCache[info] = currentRow + 1;
return currentRow + 1;
mFirstRowCache[info] = row;
return row;
}
void CSMWorld::InfoTableProxyModel::modelDataChanged(const QModelIndex &/*topLeft*/, const QModelIndex &/*bottomRight*/)
void CSMWorld::InfoTableProxyModel::modelRowsChanged(const QModelIndex &/*parent*/, int /*start*/, int /*end*/)
{
mFirstRowCache.clear();
}

@ -4,6 +4,7 @@
#include <QHash>
#include "idtableproxymodel.hpp"
#include "columns.hpp"
#include "universalid.hpp"
namespace CSMWorld
@ -16,6 +17,8 @@ namespace CSMWorld
UniversalId::Type mType;
IdTableBase *mSourceModel;
Columns::ColumnId mInfoColumnId;
///< Contains ID for Topic or Journal ID
mutable QHash<QString, int> mFirstRowCache;
@ -31,7 +34,7 @@ namespace CSMWorld
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
private slots:
void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
void modelRowsChanged(const QModelIndex &parent, int start, int end);
};
}

@ -0,0 +1,27 @@
#include "metadata.hpp"
#include <components/esm/loadtes3.hpp>
#include <components/esm/esmreader.hpp>
#include <components/esm/esmwriter.hpp>
void CSMWorld::MetaData::blank()
{
mFormat = ESM::Header::CurrentFormat;
mAuthor.clear();
mDescription.clear();
}
void CSMWorld::MetaData::load (ESM::ESMReader& esm)
{
mFormat = esm.getHeader().mFormat;
mAuthor = esm.getHeader().mData.author.toString();
mDescription = esm.getHeader().mData.desc.toString();
}
void CSMWorld::MetaData::save (ESM::ESMWriter& esm) const
{
esm.setFormat (mFormat);
esm.setAuthor (mAuthor);
esm.setDescription (mDescription);
}

@ -0,0 +1,29 @@
#ifndef CSM_WOLRD_METADATA_H
#define CSM_WOLRD_METADATA_H
#include <string>
namespace ESM
{
class ESMReader;
class ESMWriter;
}
namespace CSMWorld
{
struct MetaData
{
std::string mId;
int mFormat;
std::string mAuthor;
std::string mDescription;
void blank();
void load (ESM::ESMReader& esm);
void save (ESM::ESMWriter& esm) const;
};
}
#endif

@ -56,6 +56,7 @@ namespace
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Meta Data Table", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};
@ -120,6 +121,7 @@ namespace
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Meta Data", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};

@ -131,6 +131,8 @@ namespace CSMWorld
Type_StartScripts,
Type_StartScript,
Type_Search,
Type_MetaDatas,
Type_MetaData,
Type_RunLog
};

@ -45,6 +45,7 @@ void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id)
{
mUniversalId = id;
setWindowTitle (QString::fromUtf8(mUniversalId.toString().c_str()));
emit universalIdChanged (mUniversalId);
}
void CSVDoc::SubView::closeEvent (QCloseEvent *event)

@ -68,6 +68,8 @@ namespace CSVDoc
void updateSubViewIndicies (SubView *view = 0);
void universalIdChanged (const CSMWorld::UniversalId& universalId);
protected slots:
void closeRequest();

@ -70,6 +70,10 @@ void CSVDoc::View::setupFileMenu()
connect (loadErrors, SIGNAL (triggered()), this, SLOT (loadErrorLog()));
file->addAction (loadErrors);
QAction *meta = new QAction (tr ("Meta Data"), this);
connect (meta, SIGNAL (triggered()), this, SLOT (addMetaDataSubView()));
file->addAction (meta);
QAction *close = new QAction (tr ("&Close"), this);
connect (close, SIGNAL (triggered()), this, SLOT (close()));
file->addAction(close);
@ -813,6 +817,11 @@ void CSVDoc::View::addSearchSubView()
addSubView (mDocument->newSearch());
}
void CSVDoc::View::addMetaDataSubView()
{
addSubView (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_MetaData, "sys::meta"));
}
void CSVDoc::View::abortOperation (int type)
{
mDocument->abortOperation (type);

@ -224,6 +224,8 @@ namespace CSVDoc
void addSearchSubView();
void addMetaDataSubView();
void toggleShowStatusBar (bool show);
void loadErrorLog();

@ -17,8 +17,6 @@
#include <QLineEdit>
#include <QPlainTextEdit>
#include <QComboBox>
#include <QPushButton>
#include <QToolButton>
#include <QHeaderView>
#include <QScrollBar>
@ -40,6 +38,7 @@
#include "util.hpp"
#include "tablebottombox.hpp"
#include "nestedtable.hpp"
#include "recordbuttonbar.hpp"
/*
==============================NotEditableSubDelegate==========================================
*/
@ -64,16 +63,24 @@ void CSVWorld::NotEditableSubDelegate::setEditorData (QWidget* editor, const QMo
}
}
CSMWorld::Columns::ColumnId columnId = static_cast<CSMWorld::Columns::ColumnId> (
mTable->getColumnId (index.column()));
if (QVariant::String == v.type())
{
label->setText(v.toString());
}
else //else we are facing enums
else if (CSMWorld::Columns::hasEnums (columnId))
{
int data = v.toInt();
std::vector<std::string> enumNames (CSMWorld::Columns::getEnums (static_cast<CSMWorld::Columns::ColumnId> (mTable->getColumnId (index.column()))));
std::vector<std::string> enumNames (CSMWorld::Columns::getEnums (columnId));
label->setText(QString::fromUtf8(enumNames.at(data).c_str()));
}
else
{
label->setText (v.toString());
}
}
void CSVWorld::NotEditableSubDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
@ -548,17 +555,37 @@ void CSVWorld::EditWidget::remake(int row)
this->setWidgetResizable(true);
}
/*
==============================DialogueSubView==========================================
*/
CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory, bool sorting) :
QVBoxLayout& CSVWorld::SimpleDialogueSubView::getMainLayout()
{
return *mMainLayout;
}
CSMWorld::IdTable& CSVWorld::SimpleDialogueSubView::getTable()
{
return *mTable;
}
CSMWorld::CommandDispatcher& CSVWorld::SimpleDialogueSubView::getCommandDispatcher()
{
return mCommandDispatcher;
}
CSVWorld::EditWidget& CSVWorld::SimpleDialogueSubView::getEditWidget()
{
return *mEditWidget;
}
bool CSVWorld::SimpleDialogueSubView::isLocked() const
{
return mLocked;
}
CSVWorld::SimpleDialogueSubView::SimpleDialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) :
SubView (id),
mEditWidget(0),
mMainLayout(NULL),
mTable(dynamic_cast<CSMWorld::IdTable*>(document.getData().getTableModel(id))),
mUndoStack(document.getUndoStack()),
mLocked(false),
mDocument(document),
mCommandDispatcher (document, CSMWorld::UniversalId::getParentType (id.getType()))
@ -566,169 +593,29 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
connect(mTable, SIGNAL(dataChanged (const QModelIndex&, const QModelIndex&)), this, SLOT(dataChanged(const QModelIndex&)));
connect(mTable, SIGNAL(rowsAboutToBeRemoved(const QModelIndex&, int, int)), this, SLOT(rowsAboutToBeRemoved(const QModelIndex&, int, int)));
changeCurrentId(id.getId());
updateCurrentId();
QWidget *mainWidget = new QWidget(this);
QHBoxLayout *buttonsLayout = new QHBoxLayout;
QToolButton* prevButton = new QToolButton(mainWidget);
prevButton->setIcon(QIcon(":/go-previous.png"));
prevButton->setToolTip ("Switch to previous record");
QToolButton* nextButton = new QToolButton(mainWidget);
nextButton->setIcon(QIcon(":/go-next.png"));
nextButton->setToolTip ("Switch to next record");
buttonsLayout->addWidget(prevButton, 0);
buttonsLayout->addWidget(nextButton, 1);
buttonsLayout->addStretch(2);
QToolButton* cloneButton = new QToolButton(mainWidget);
cloneButton->setIcon(QIcon(":/edit-clone.png"));
cloneButton->setToolTip ("Clone record");
QToolButton* addButton = new QToolButton(mainWidget);
addButton->setIcon(QIcon(":/add.png"));
addButton->setToolTip ("Add new record");
QToolButton* deleteButton = new QToolButton(mainWidget);
deleteButton->setIcon(QIcon(":/edit-delete.png"));
deleteButton->setToolTip ("Delete record");
QToolButton* revertButton = new QToolButton(mainWidget);
revertButton->setIcon(QIcon(":/edit-undo.png"));
revertButton->setToolTip ("Revert record");
if (mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview)
{
QToolButton* previewButton = new QToolButton(mainWidget);
previewButton->setIcon(QIcon(":/edit-preview.png"));
previewButton->setToolTip ("Open a preview of this record");
buttonsLayout->addWidget(previewButton);
connect(previewButton, SIGNAL(clicked()), this, SLOT(showPreview()));
}
if (mTable->getFeatures() & CSMWorld::IdTable::Feature_View)
{
QToolButton* viewButton = new QToolButton(mainWidget);
viewButton->setIcon(QIcon(":/cell.png"));
viewButton->setToolTip ("Open a scene view of the cell this record is located in");
buttonsLayout->addWidget(viewButton);
connect(viewButton, SIGNAL(clicked()), this, SLOT(viewRecord()));
}
buttonsLayout->addWidget(cloneButton);
buttonsLayout->addWidget(addButton);
buttonsLayout->addWidget(deleteButton);
buttonsLayout->addWidget(revertButton);
connect(nextButton, SIGNAL(clicked()), this, SLOT(nextId()));
connect(prevButton, SIGNAL(clicked()), this, SLOT(prevId()));
connect(cloneButton, SIGNAL(clicked()), this, SLOT(cloneRequest()));
connect(revertButton, SIGNAL(clicked()), &mCommandDispatcher, SLOT(executeRevert()));
connect(deleteButton, SIGNAL(clicked()), &mCommandDispatcher, SLOT(executeDelete()));
mMainLayout = new QVBoxLayout(mainWidget);
setWidget (mainWidget);
mEditWidget = new EditWidget(mainWidget,
mTable->getModelIndex(mCurrentId, 0).row(), mTable, mCommandDispatcher, document, false);
mTable->getModelIndex(getUniversalId().getId(), 0).row(), mTable, mCommandDispatcher, document, false);
mMainLayout->addWidget(mEditWidget);
mEditWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
mMainLayout->addWidget (mBottom = new TableBottomBox (creatorFactory, document, id, this));
mBottom->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
connect(mBottom, SIGNAL(requestFocus(const std::string&)), this, SLOT(requestFocus(const std::string&)));
connect(addButton, SIGNAL(clicked()), mBottom, SLOT(createRequest()));
if(!mBottom->canCreateAndDelete())
{
cloneButton->setDisabled (true);
addButton->setDisabled (true);
deleteButton->setDisabled (true);
}
dataChanged(mTable->getModelIndex (mCurrentId, 0));
mMainLayout->addLayout (buttonsLayout);
setWidget (mainWidget);
}
void CSVWorld::DialogueSubView::prevId ()
{
int newRow = mTable->getModelIndex(mCurrentId, 0).row() - 1;
if (newRow < 0)
{
return;
}
while (newRow >= 0)
{
QModelIndex newIndex(mTable->index(newRow, 0));
if (!newIndex.isValid())
{
return;
}
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (newRow, 1)).toInt());
if (!(state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased))
{
mEditWidget->remake(newRow);
setUniversalId(CSMWorld::UniversalId (static_cast<CSMWorld::UniversalId::Type> (mTable->data (mTable->index (newRow, 2)).toInt()),
mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData()));
changeCurrentId(std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData()));
mEditWidget->setDisabled(mLocked);
return;
}
--newRow;
}
}
void CSVWorld::DialogueSubView::nextId ()
{
int newRow = mTable->getModelIndex(mCurrentId, 0).row() + 1;
if (newRow >= mTable->rowCount())
{
return;
}
while (newRow < mTable->rowCount())
{
QModelIndex newIndex(mTable->index(newRow, 0));
if (!newIndex.isValid())
{
return;
}
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (newRow, 1)).toInt());
if (!(state == CSMWorld::RecordBase::State_Deleted))
{
mEditWidget->remake(newRow);
setUniversalId(CSMWorld::UniversalId (static_cast<CSMWorld::UniversalId::Type> (mTable->data (mTable->index (newRow, 2)).toInt()),
mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData()));
changeCurrentId(std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData()));
mEditWidget->setDisabled(mLocked);
return;
}
++newRow;
}
dataChanged(mTable->getModelIndex (getUniversalId().getId(), 0));
}
void CSVWorld::DialogueSubView::setEditLock (bool locked)
void CSVWorld::SimpleDialogueSubView::setEditLock (bool locked)
{
if (!mEditWidget) // hack to indicate that mCurrentId is no longer valid
if (!mEditWidget) // hack to indicate that getUniversalId().getId() is no longer valid
return;
mLocked = locked;
QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0));
QModelIndex currentIndex(mTable->getModelIndex(getUniversalId().getId(), 0));
if (currentIndex.isValid())
{
@ -741,9 +628,9 @@ void CSVWorld::DialogueSubView::setEditLock (bool locked)
}
void CSVWorld::DialogueSubView::dataChanged (const QModelIndex & index)
void CSVWorld::SimpleDialogueSubView::dataChanged (const QModelIndex & index)
{
QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0));
QModelIndex currentIndex(mTable->getModelIndex(getUniversalId().getId(), 0));
if (currentIndex.isValid() &&
(index.parent().isValid() ? index.parent().row() : index.row()) == currentIndex.row())
@ -774,9 +661,9 @@ void CSVWorld::DialogueSubView::dataChanged (const QModelIndex & index)
}
}
void CSVWorld::DialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
void CSVWorld::SimpleDialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
{
QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0));
QModelIndex currentIndex(mTable->getModelIndex(getUniversalId().getId(), 0));
if (currentIndex.isValid() && currentIndex.row() >= start && currentIndex.row() <= end)
{
@ -789,49 +676,106 @@ void CSVWorld::DialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent,
}
}
void CSVWorld::DialogueSubView::requestFocus (const std::string& id)
void CSVWorld::SimpleDialogueSubView::updateCurrentId()
{
changeCurrentId(id);
std::vector<std::string> selection;
selection.push_back (getUniversalId().getId());
mCommandDispatcher.setSelection(selection);
}
CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id,
CSMDoc::Document& document, const CreatorFactoryBase& creatorFactory, bool sorting)
: SimpleDialogueSubView (id, document)
{
// bottom box
mBottom = new TableBottomBox (creatorFactory, document, id, this);
mBottom->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Fixed);
connect (mBottom, SIGNAL (requestFocus (const std::string&)),
this, SLOT (requestFocus (const std::string&)));
// button bar
mButtons = new RecordButtonBar (id, getTable(), mBottom,
&getCommandDispatcher(), this);
// layout
getMainLayout().addWidget (mButtons);
getMainLayout().addWidget (mBottom);
// connections
connect (mButtons, SIGNAL (showPreview()), this, SLOT (showPreview()));
connect (mButtons, SIGNAL (viewRecord()), this, SLOT (viewRecord()));
connect (mButtons, SIGNAL (switchToRow (int)), this, SLOT (switchToRow (int)));
connect (this, SIGNAL (universalIdChanged (const CSMWorld::UniversalId&)),
mButtons, SLOT (universalIdChanged (const CSMWorld::UniversalId&)));
}
mEditWidget->remake(mTable->getModelIndex (id, 0).row());
void CSVWorld::DialogueSubView::setEditLock (bool locked)
{
SimpleDialogueSubView::setEditLock (locked);
mButtons->setEditLock (locked);
}
void CSVWorld::DialogueSubView::cloneRequest ()
void CSVWorld::DialogueSubView::updateUserSetting (const QString& name, const QStringList& value)
{
mBottom->cloneRequest(mCurrentId, static_cast<CSMWorld::UniversalId::Type>(mTable->data(mTable->getModelIndex(mCurrentId, 2)).toInt()));
SimpleDialogueSubView::updateUserSetting (name, value);
mButtons->updateUserSetting (name, value);
}
void CSVWorld::DialogueSubView::showPreview ()
{
QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0));
QModelIndex currentIndex (getTable().getModelIndex (getUniversalId().getId(), 0));
if (currentIndex.isValid() &&
mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview &&
currentIndex.row() < mTable->rowCount())
getTable().getFeatures() & CSMWorld::IdTable::Feature_Preview &&
currentIndex.row() < getTable().rowCount())
{
emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, mCurrentId), "");
emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, getUniversalId().getId()), "");
}
}
void CSVWorld::DialogueSubView::viewRecord ()
{
QModelIndex currentIndex(mTable->getModelIndex (mCurrentId, 0));
QModelIndex currentIndex (getTable().getModelIndex (getUniversalId().getId(), 0));
if (currentIndex.isValid() &&
currentIndex.row() < mTable->rowCount())
currentIndex.row() < getTable().rowCount())
{
std::pair<CSMWorld::UniversalId, std::string> params = mTable->view (currentIndex.row());
std::pair<CSMWorld::UniversalId, std::string> params = getTable().view (currentIndex.row());
if (params.first.getType()!=CSMWorld::UniversalId::Type_None)
emit focusId (params.first, params.second);
}
}
void CSVWorld::DialogueSubView::changeCurrentId (const std::string& newId)
void CSVWorld::DialogueSubView::switchToRow (int row)
{
std::vector<std::string> selection;
mCurrentId = std::string(newId);
int idColumn = getTable().findColumnIndex (CSMWorld::Columns::ColumnId_Id);
std::string id = getTable().data (getTable().index (row, idColumn)).toString().toUtf8().constData();
selection.push_back(mCurrentId);
mCommandDispatcher.setSelection(selection);
int typeColumn = getTable().findColumnIndex (CSMWorld::Columns::ColumnId_RecordType);
CSMWorld::UniversalId::Type type = static_cast<CSMWorld::UniversalId::Type> (
getTable().data (getTable().index (row, typeColumn)).toInt());
setUniversalId (CSMWorld::UniversalId (type, id));
updateCurrentId();
getEditWidget().remake (row);
int stateColumn = getTable().findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State> (
getTable().data (getTable().index (row, stateColumn)).toInt());
getEditWidget().setDisabled (isLocked() || state==CSMWorld::RecordBase::State_Deleted);
}
void CSVWorld::DialogueSubView::requestFocus (const std::string& id)
{
QModelIndex index = getTable().getModelIndex (id, 0);
if (index.isValid())
switchToRow (index.row());
}

@ -173,50 +173,72 @@ namespace CSVWorld
void remake(int row);
};
class DialogueSubView : public CSVDoc::SubView
class SimpleDialogueSubView : public CSVDoc::SubView
{
Q_OBJECT
Q_OBJECT
EditWidget* mEditWidget;
QVBoxLayout* mMainLayout;
CSMWorld::IdTable* mTable;
bool mLocked;
const CSMDoc::Document& mDocument;
CSMWorld::CommandDispatcher mCommandDispatcher;
protected:
QVBoxLayout& getMainLayout();
CSMWorld::IdTable& getTable();
CSMWorld::CommandDispatcher& getCommandDispatcher();
EditWidget* mEditWidget;
QVBoxLayout* mMainLayout;
CSMWorld::IdTable* mTable;
QUndoStack& mUndoStack;
std::string mCurrentId;
bool mLocked;
const CSMDoc::Document& mDocument;
TableBottomBox* mBottom;
CSMWorld::CommandDispatcher mCommandDispatcher;
EditWidget& getEditWidget();
void updateCurrentId();
bool isLocked() const;
public:
DialogueSubView (const CSMWorld::UniversalId& id,
CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory,
bool sorting = false);
SimpleDialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document);
virtual void setEditLock (bool locked);
private:
void changeCurrentId(const std::string& newCurrent);
private slots:
void nextId();
void dataChanged(const QModelIndex & index);
///\brief we need to care for deleting currently edited record
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
};
class RecordButtonBar;
class DialogueSubView : public SimpleDialogueSubView
{
Q_OBJECT
TableBottomBox* mBottom;
RecordButtonBar *mButtons;
public:
DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory, bool sorting = false);
virtual void setEditLock (bool locked);
void prevId();
virtual void updateUserSetting (const QString& name, const QStringList& value);
private slots:
void showPreview();
void viewRecord();
void cloneRequest();
void dataChanged(const QModelIndex & index);
///\brief we need to care for deleting currently edited record
void switchToRow (int row);
void requestFocus (const std::string& id);
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
};
}

@ -0,0 +1,207 @@
#include "recordbuttonbar.hpp"
#include <QHBoxLayout>
#include <QToolButton>
#include "../../model/world/idtable.hpp"
#include "../../model/world/commanddispatcher.hpp"
#include "../../model/settings/usersettings.hpp"
#include "../world/tablebottombox.hpp"
void CSVWorld::RecordButtonBar::updateModificationButtons()
{
bool createAndDeleteDisabled = !mBottom || !mBottom->canCreateAndDelete() || mLocked;
mCloneButton->setDisabled (createAndDeleteDisabled);
mAddButton->setDisabled (createAndDeleteDisabled);
mDeleteButton->setDisabled (createAndDeleteDisabled);
bool commandDisabled = !mCommandDispatcher || mLocked;
mRevertButton->setDisabled (commandDisabled);
mDeleteButton->setDisabled (commandDisabled);
}
void CSVWorld::RecordButtonBar::updatePrevNextButtons()
{
int rows = mTable.rowCount();
if (rows<=1)
{
mPrevButton->setDisabled (true);
mNextButton->setDisabled (true);
}
else if (CSMSettings::UserSettings::instance().settingValue ("general-input/cycle")=="true")
{
mPrevButton->setDisabled (false);
mNextButton->setDisabled (false);
}
else
{
int row = mTable.getModelIndex (mId.getId(), 0).row();
mPrevButton->setDisabled (row<=0);
mNextButton->setDisabled (row>=rows-1);
}
}
CSVWorld::RecordButtonBar::RecordButtonBar (const CSMWorld::UniversalId& id,
CSMWorld::IdTable& table, TableBottomBox *bottomBox,
CSMWorld::CommandDispatcher *commandDispatcher, QWidget *parent)
: QWidget (parent), mId (id), mTable (table), mBottom (bottomBox),
mCommandDispatcher (commandDispatcher), mLocked (false)
{
QHBoxLayout *buttonsLayout = new QHBoxLayout;
buttonsLayout->setContentsMargins (0, 0, 0, 0);
// left section
mPrevButton = new QToolButton (this);
mPrevButton->setIcon(QIcon(":/go-previous.png"));
mPrevButton->setToolTip ("Switch to previous record");
buttonsLayout->addWidget (mPrevButton, 0);
mNextButton = new QToolButton (this);
mNextButton->setIcon(QIcon(":/go-next.png"));
mNextButton->setToolTip ("Switch to next record");
buttonsLayout->addWidget (mNextButton, 1);
buttonsLayout->addStretch(2);
// optional buttons of the right section
if (mTable.getFeatures() & CSMWorld::IdTable::Feature_Preview)
{
QToolButton* previewButton = new QToolButton (this);
previewButton->setIcon(QIcon(":/edit-preview.png"));
previewButton->setToolTip ("Open a preview of this record");
buttonsLayout->addWidget(previewButton);
connect (previewButton, SIGNAL(clicked()), this, SIGNAL (showPreview()));
}
if (mTable.getFeatures() & CSMWorld::IdTable::Feature_View)
{
QToolButton* viewButton = new QToolButton (this);
viewButton->setIcon(QIcon(":/cell.png"));
viewButton->setToolTip ("Open a scene view of the cell this record is located in");
buttonsLayout->addWidget(viewButton);
connect (viewButton, SIGNAL(clicked()), this, SIGNAL (viewRecord()));
}
// right section
mCloneButton = new QToolButton (this);
mCloneButton->setIcon(QIcon(":/edit-clone.png"));
mCloneButton->setToolTip ("Clone record");
buttonsLayout->addWidget(mCloneButton);
mAddButton = new QToolButton (this);
mAddButton->setIcon(QIcon(":/add.png"));
mAddButton->setToolTip ("Add new record");
buttonsLayout->addWidget(mAddButton);
mDeleteButton = new QToolButton (this);
mDeleteButton->setIcon(QIcon(":/edit-delete.png"));
mDeleteButton->setToolTip ("Delete record");
buttonsLayout->addWidget(mDeleteButton);
mRevertButton = new QToolButton (this);
mRevertButton->setIcon(QIcon(":/edit-undo.png"));
mRevertButton->setToolTip ("Revert record");
buttonsLayout->addWidget(mRevertButton);
setLayout (buttonsLayout);
// connections
if(mBottom && mBottom->canCreateAndDelete())
{
connect (mAddButton, SIGNAL (clicked()), mBottom, SLOT (createRequest()));
connect (mCloneButton, SIGNAL (clicked()), this, SLOT (cloneRequest()));
}
connect (mNextButton, SIGNAL (clicked()), this, SLOT (nextId()));
connect (mPrevButton, SIGNAL (clicked()), this, SLOT (prevId()));
if (mCommandDispatcher)
{
connect (mRevertButton, SIGNAL (clicked()), mCommandDispatcher, SLOT (executeRevert()));
connect (mDeleteButton, SIGNAL (clicked()), mCommandDispatcher, SLOT (executeDelete()));
}
connect (&mTable, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (rowNumberChanged (const QModelIndex&, int, int)));
connect (&mTable, SIGNAL (rowsRemoved (const QModelIndex&, int, int)),
this, SLOT (rowNumberChanged (const QModelIndex&, int, int)));
updateModificationButtons();
updatePrevNextButtons();
}
void CSVWorld::RecordButtonBar::setEditLock (bool locked)
{
mLocked = locked;
updateModificationButtons();
}
void CSVWorld::RecordButtonBar::updateUserSetting (const QString& name, const QStringList& value)
{
if (name=="general-input/cycle")
updatePrevNextButtons();
}
void CSVWorld::RecordButtonBar::universalIdChanged (const CSMWorld::UniversalId& id)
{
mId = id;
updatePrevNextButtons();
}
void CSVWorld::RecordButtonBar::cloneRequest()
{
if (mBottom)
{
int typeColumn = mTable.findColumnIndex (CSMWorld::Columns::ColumnId_RecordType);
QModelIndex typeIndex = mTable.getModelIndex (mId.getId(), typeColumn);
CSMWorld::UniversalId::Type type = static_cast<CSMWorld::UniversalId::Type> (
mTable.data (typeIndex).toInt());
mBottom->cloneRequest (mId.getId(), type);
}
}
void CSVWorld::RecordButtonBar::nextId()
{
int newRow = mTable.getModelIndex (mId.getId(), 0).row() + 1;
if (newRow >= mTable.rowCount())
{
if (CSMSettings::UserSettings::instance().settingValue ("general-input/cycle")
=="true")
newRow = 0;
else
return;
}
emit switchToRow (newRow);
}
void CSVWorld::RecordButtonBar::prevId()
{
int newRow = mTable.getModelIndex (mId.getId(), 0).row() - 1;
if (newRow < 0)
{
if (CSMSettings::UserSettings::instance().settingValue ("general-input/cycle")
=="true")
newRow = mTable.rowCount()-1;
else
return;
}
emit switchToRow (newRow);
}
void CSVWorld::RecordButtonBar::rowNumberChanged (const QModelIndex& parent, int start, int end)
{
updatePrevNextButtons();
}

@ -0,0 +1,87 @@
#ifndef CSV_WORLD_RECORDBUTTONBAR_H
#define CSV_WORLD_RECORDBUTTONBAR_H
#include <QWidget>
#include "../../model/world/universalid.hpp"
class QToolButton;
class QModelIndex;
namespace CSMWorld
{
class IdTable;
class CommandDispatcher;
}
namespace CSVWorld
{
class TableBottomBox;
/// \brief Button bar for use in dialogue-type subviews
///
/// Contains the following buttons:
/// - next/prev
/// - clone
/// - add
/// - delete
/// - revert
/// - preview (optional)
/// - view (optional)
class RecordButtonBar : public QWidget
{
Q_OBJECT
CSMWorld::UniversalId mId;
CSMWorld::IdTable& mTable;
TableBottomBox *mBottom;
CSMWorld::CommandDispatcher *mCommandDispatcher;
QToolButton *mPrevButton;
QToolButton *mNextButton;
QToolButton *mCloneButton;
QToolButton *mAddButton;
QToolButton *mDeleteButton;
QToolButton *mRevertButton;
bool mLocked;
private:
void updateModificationButtons();
void updatePrevNextButtons();
public:
RecordButtonBar (const CSMWorld::UniversalId& id,
CSMWorld::IdTable& table, TableBottomBox *bottomBox = 0,
CSMWorld::CommandDispatcher *commandDispatcher = 0, QWidget *parent = 0);
void setEditLock (bool locked);
void updateUserSetting (const QString& name, const QStringList& value);
public slots:
void universalIdChanged (const CSMWorld::UniversalId& id);
private slots:
void cloneRequest();
void nextId();
void prevId();
void rowNumberChanged (const QModelIndex& parent, int start, int end);
signals:
void showPreview();
void viewRecord();
void switchToRow (int row);
};
}
#endif

@ -170,6 +170,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
manager.add (CSMWorld::UniversalId::Type_Filter,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator, CSMWorld::Scope_Project | CSMWorld::Scope_Session> > (false));
manager.add (CSMWorld::UniversalId::Type_MetaData,
new CSVDoc::SubViewFactory<SimpleDialogueSubView >);
//preview
manager.add (CSMWorld::UniversalId::Type_Preview, new CSVDoc::SubViewFactory<PreviewSubView>);
}

@ -9,6 +9,8 @@
#include <QString>
#include <QtCore/qnamespace.h>
#include <components/misc/stringops.hpp>
#include "../../model/doc/document.hpp"
#include "../../model/world/data.hpp"
@ -128,17 +130,24 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
{
int row = mProxyModel->mapToSource (
mProxyModel->index (selectedRows.begin()->row(), 0)).row();
QString curData = mModel->data(mModel->index(row, column)).toString();
if (row>0 && mModel->data (mModel->index (row, column))==
mModel->data (mModel->index (row-1, column)))
if (row > 0)
{
menu.addAction (mMoveUpAction);
QString prevData = mModel->data(mModel->index(row - 1, column)).toString();
if (Misc::StringUtils::ciEqual(curData.toStdString(), prevData.toStdString()))
{
menu.addAction(mMoveUpAction);
}
}
if (row<mModel->rowCount()-1 && mModel->data (mModel->index (row, column))==
mModel->data (mModel->index (row+1, column)))
if (row < mModel->rowCount() - 1)
{
menu.addAction (mMoveDownAction);
QString nextData = mModel->data(mModel->index(row + 1, column)).toString();
if (Misc::StringUtils::ciEqual(curData.toStdString(), nextData.toStdString()))
{
menu.addAction(mMoveDownAction);
}
}
}
}

@ -232,6 +232,14 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
return edit;
}
case CSMWorld::ColumnBase::Display_LongString256:
{
/// \todo implement size limit. QPlainTextEdit does not support a size limit.
QPlainTextEdit *edit = new QPlainTextEdit(parent);
edit->setUndoRedoEnabled (false);
return edit;
}
case CSMWorld::ColumnBase::Display_Boolean:
return new QCheckBox(parent);
@ -245,6 +253,14 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
return new CSVWidget::DropLineEdit(display, parent);
case CSMWorld::ColumnBase::Display_String32:
{
// For other Display types (that represent record IDs) with drop support IdCompletionDelegate is used
CSVWidget::DropLineEdit *widget = new CSVWidget::DropLineEdit(display, parent);
widget->setMaxLength (32);
return widget;
}
default:
return QStyledItemDelegate::createEditor (parent, option, index);

@ -174,6 +174,15 @@ namespace ESM
endRecord(name);
}
void ESMWriter::writeFixedSizeString(const std::string &data, int size)
{
std::string string;
if (!data.empty())
string = mEncoder ? mEncoder->getLegacyEnc(data) : data;
string.resize(size);
write(string.c_str(), string.size());
}
void ESMWriter::writeHString(const std::string& data)
{
if (data.size() == 0)

@ -120,6 +120,7 @@ public:
void startSubRecord(const std::string& name);
void endRecord(const std::string& name);
void endRecord(uint32_t name);
void writeFixedSizeString(const std::string& data, int size);
void writeHString(const std::string& data);
void writeHCString(const std::string& data);
void writeName(const std::string& data);

@ -71,7 +71,13 @@ void ESM::Header::save (ESMWriter &esm)
if (mFormat>0)
esm.writeHNT ("FORM", mFormat);
esm.writeHNT ("HEDR", mData, 300);
esm.startSubRecord("HEDR");
esm.writeT(mData.version);
esm.writeT(mData.type);
esm.writeFixedSizeString(mData.author.toString(), 32);
esm.writeFixedSizeString(mData.desc.toString(), 256);
esm.writeT(mData.records);
esm.endRecord("HEDR");
for (std::vector<Header::MasterData>::iterator iter = mMaster.begin();
iter != mMaster.end(); ++iter)

Loading…
Cancel
Save