Merge branch 'master' of https://github.com/OpenMW/openmw into osg

Conflicts:
	apps/opencs/CMakeLists.txt
c++11
scrawl 10 years ago
commit 1956e2c988

@ -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,18 +64,18 @@ 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
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
scripthighlighter idvalidator dialoguecreator idcompletiondelegate
colordelegate
colordelegate dragdroputils
)
opencs_units (view/widget
scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton
scenetooltoggle2 completerpopup coloreditor colorpickerpopup
scenetooltoggle2 completerpopup coloreditor colorpickerpopup droplineedit
)
opencs_units (view/render

@ -2280,9 +2280,6 @@ CSMDoc::Document::Document (const VFS::Manager* vfs, const Files::ConfigurationM
if (mNew)
{
mData.setDescription ("");
mData.setAuthor ("");
if (mContentFiles.size()==1)
createBase();
}
@ -2372,9 +2369,9 @@ void CSMDoc::Document::save()
emit stateChanged (getState(), this);
}
CSMWorld::UniversalId CSMDoc::Document::verify()
CSMWorld::UniversalId CSMDoc::Document::verify (const CSMWorld::UniversalId& reportId)
{
CSMWorld::UniversalId id = mTools.runVerifier();
CSMWorld::UniversalId id = mTools.runVerifier (reportId);
emit stateChanged (getState(), this);
return id;
}

@ -124,7 +124,7 @@ namespace CSMDoc
void save();
CSMWorld::UniversalId verify();
CSMWorld::UniversalId verify (const CSMWorld::UniversalId& reportId = CSMWorld::UniversalId());
CSMWorld::UniversalId newSearch();

@ -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) +

@ -339,6 +339,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:

@ -30,9 +30,9 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
// check the number of pathgrid points
if (pathgrid.mData.mS2 > static_cast<int>(pathgrid.mPoints.size()))
messages.push_back (std::make_pair (id, pathgrid.mId + " has less points than expected"));
messages.add (id, pathgrid.mId + " has less points than expected", "", CSMDoc::Message::Severity_Error);
else if (pathgrid.mData.mS2 > static_cast<int>(pathgrid.mPoints.size()))
messages.push_back (std::make_pair (id, pathgrid.mId + " has more points than expected"));
messages.add (id, pathgrid.mId + " has more points than expected", "", CSMDoc::Message::Severity_Error);
std::vector<CSMTools::Point> pointList(pathgrid.mPoints.size());
std::vector<int> duplList;
@ -51,7 +51,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
std::ostringstream ss;
ss << "has a duplicate edge between points" << pathgrid.mEdges[i].mV0
<< " and " << pathgrid.mEdges[i].mV1;
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
break;
}
}
@ -64,7 +64,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
{
std::ostringstream ss;
ss << " has an edge connecting a non-existent point " << pathgrid.mEdges[i].mV0;
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
}
}
@ -75,13 +75,13 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
{
std::ostringstream ss;
ss << " has has less edges than expected for point " << i;
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
}
else if (pathgrid.mPoints[i].mConnectionNum < pointList[i].mConnectionNum)
{
std::ostringstream ss;
ss << " has has more edges than expected for point " << i;
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
}
// check that edges are bidirectional
@ -101,7 +101,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
{
std::ostringstream ss;
ss << " has a missing edge between points " << i << " and " << pointList[i].mOtherIndex[j];
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
}
}
@ -124,7 +124,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
<< ") x=" << pathgrid.mPoints[i].mX
<< ", y=" << pathgrid.mPoints[i].mY
<< ", z=" << pathgrid.mPoints[i].mZ;
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Warning);
duplList.push_back(i);
break;
@ -143,7 +143,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
<< ") x=" << pathgrid.mPoints[i].mX
<< ", y=" << pathgrid.mPoints[i].mY
<< ", z=" << pathgrid.mPoints[i].mZ;
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Warning);
}
}

@ -120,7 +120,7 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
void CSMTools::ScriptCheckStage::updateUserSetting (const QString& name, const QStringList& value)
{
if (name=="script-editor/warnings")
if (name=="script-editor/warnings" && !value.isEmpty())
{
if (value.at (0)=="Ignore")
mWarningMode = Mode_Ignore;

@ -146,14 +146,19 @@ CSMTools::Tools::~Tools()
delete iter->second;
}
CSMWorld::UniversalId CSMTools::Tools::runVerifier()
CSMWorld::UniversalId CSMTools::Tools::runVerifier (const CSMWorld::UniversalId& reportId)
{
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
mActiveReports[CSMDoc::State_Verifying] = mNextReportNumber-1;
int reportNumber = reportId.getType()==CSMWorld::UniversalId::Type_VerificationResults ?
reportId.getIndex() : mNextReportNumber++;
if (mReports.find (reportNumber)==mReports.end())
mReports.insert (std::make_pair (reportNumber, new ReportModel));
mActiveReports[CSMDoc::State_Verifying] = reportNumber;
getVerifier()->start();
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, mNextReportNumber-1);
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, reportNumber);
}
CSMWorld::UniversalId CSMTools::Tools::newSearch()

@ -57,8 +57,11 @@ namespace CSMTools
virtual ~Tools();
CSMWorld::UniversalId runVerifier();
///< \return ID of the report for this verification run
/// \param reportId If a valid VerificationResults ID, run verifier for the
/// specified report instead of creating a new one.
///
/// \return ID of the report for this verification run
CSMWorld::UniversalId runVerifier (const CSMWorld::UniversalId& reportId = CSMWorld::UniversalId());
/// Return ID of the report for this search.
CSMWorld::UniversalId newSearch();

@ -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
}
@ -813,6 +822,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());
@ -857,8 +871,14 @@ 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();
}
@ -1113,26 +1133,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;

@ -46,6 +46,7 @@
#include "infocollection.hpp"
#include "nestedinfocollection.hpp"
#include "pathgrid.hpp"
#include "metadata.hpp"
#ifndef Q_MOC_RUN
#include "subcellcollection.hpp"
#endif
@ -101,11 +102,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;
@ -253,6 +253,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.
///
@ -282,14 +284,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

@ -192,4 +192,8 @@ void CSMWorld::NestedTableProxyModel::forwardDataChanged (const QModelIndex& top
emit dataChanged(index(0,0),
index(mMainModel->rowCount(parent)-1, mMainModel->columnCount(parent)-1));
}
else if (topLeft.parent() == parent && bottomRight.parent() == parent)
{
emit dataChanged(index(topLeft.row(), topLeft.column()), index(bottomRight.row(), bottomRight.column()));
}
}

@ -264,6 +264,8 @@ namespace
{ CSMWorld::UniversalId::Type_Texture, CSMWorld::ColumnBase::Display_Texture },
{ CSMWorld::UniversalId::Type_Video, CSMWorld::ColumnBase::Display_Video },
{ CSMWorld::UniversalId::Type_Global, CSMWorld::ColumnBase::Display_GlobalVariable },
{ CSMWorld::UniversalId::Type_BodyPart, CSMWorld::ColumnBase::Display_BodyPart },
{ CSMWorld::UniversalId::Type_Enchantment, CSMWorld::ColumnBase::Display_Enchantment },
{ CSMWorld::UniversalId::Type_None, CSMWorld::ColumnBase::Display_None } // end marker
};

@ -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();

@ -4,12 +4,23 @@
#include "reporttable.hpp"
CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
: CSVDoc::SubView (id)
: CSVDoc::SubView (id), mDocument (document), mRefreshState (0)
{
setWidget (mTable = new ReportTable (document, id, false, this));
if (id.getType()==CSMWorld::UniversalId::Type_VerificationResults)
mRefreshState = CSMDoc::State_Verifying;
setWidget (mTable = new ReportTable (document, id, false, mRefreshState, this));
connect (mTable, SIGNAL (editRequest (const CSMWorld::UniversalId&, const std::string&)),
SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&)));
if (mRefreshState==CSMDoc::State_Verifying)
{
connect (mTable, SIGNAL (refreshRequest()), this, SLOT (refreshRequest()));
connect (&document, SIGNAL (stateChanged (int, CSMDoc::Document *)),
mTable, SLOT (stateChanged (int, CSMDoc::Document *)));
}
}
void CSVTools::ReportSubView::setEditLock (bool locked)
@ -21,3 +32,15 @@ void CSVTools::ReportSubView::updateUserSetting (const QString &name, const QStr
{
mTable->updateUserSetting (name, list);
}
void CSVTools::ReportSubView::refreshRequest()
{
if (!(mDocument.getState() & mRefreshState))
{
if (mRefreshState==CSMDoc::State_Verifying)
{
mTable->clear();
mDocument.verify (getUniversalId());
}
}
}

@ -20,6 +20,8 @@ namespace CSVTools
Q_OBJECT
ReportTable *mTable;
CSMDoc::Document& mDocument;
int mRefreshState;
public:
@ -28,6 +30,10 @@ namespace CSVTools
virtual void setEditLock (bool locked);
virtual void updateUserSetting (const QString &, const QStringList &);
private slots:
void refreshRequest();
};
}

@ -74,9 +74,11 @@ void CSVTools::ReportTable::contextMenuEvent (QContextMenuEvent *event)
if (found)
menu.addAction (mReplaceAction);
}
if (mRefreshAction)
menu.addAction (mRefreshAction);
menu.exec (event->globalPos());
}
@ -134,8 +136,10 @@ void CSVTools::ReportTable::mouseDoubleClickEvent (QMouseEvent *event)
}
CSVTools::ReportTable::ReportTable (CSMDoc::Document& document,
const CSMWorld::UniversalId& id, bool richTextDescription, QWidget *parent)
: CSVWorld::DragRecordTable (document, parent), mModel (document.getReport (id))
const CSMWorld::UniversalId& id, bool richTextDescription, int refreshState,
QWidget *parent)
: CSVWorld::DragRecordTable (document, parent), mModel (document.getReport (id)),
mRefreshAction (0), mRefreshState (refreshState)
{
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
horizontalHeader()->setSectionResizeMode (QHeaderView::Interactive);
@ -171,6 +175,14 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document,
connect (mReplaceAction, SIGNAL (triggered()), this, SIGNAL (replaceRequest()));
addAction (mReplaceAction);
if (mRefreshState)
{
mRefreshAction = new QAction (tr ("Refresh"), this);
mRefreshAction->setEnabled (!(mDocument.getState() & mRefreshState));
connect (mRefreshAction, SIGNAL (triggered()), this, SIGNAL (refreshRequest()));
addAction (mRefreshAction);
}
mDoubleClickActions.insert (std::make_pair (Qt::NoModifier, Action_Edit));
mDoubleClickActions.insert (std::make_pair (Qt::ShiftModifier, Action_Remove));
mDoubleClickActions.insert (std::make_pair (Qt::ControlModifier, Action_EditAndRemove));
@ -287,3 +299,9 @@ void CSVTools::ReportTable::clear()
{
mModel->clear();
}
void CSVTools::ReportTable::stateChanged (int state, CSMDoc::Document *document)
{
if (mRefreshAction)
mRefreshAction->setEnabled (!(state & mRefreshState));
}

@ -36,7 +36,9 @@ namespace CSVTools
QAction *mShowAction;
QAction *mRemoveAction;
QAction *mReplaceAction;
QAction *mRefreshAction;
std::map<Qt::KeyboardModifiers, DoubleClickAction> mDoubleClickActions;
int mRefreshState;
private:
@ -49,8 +51,11 @@ namespace CSVTools
public:
/// \param richTextDescription Use rich text in the description column.
/// \param refreshState Document state to check for refresh function. If value is
/// 0 no refresh function exists. If the document current has the specified state
/// the refresh function is disabled.
ReportTable (CSMDoc::Document& document, const CSMWorld::UniversalId& id,
bool richTextDescription, QWidget *parent = 0);
bool richTextDescription, int refreshState = 0, QWidget *parent = 0);
virtual std::vector<CSMWorld::UniversalId> getDraggedRecords() const;
@ -71,11 +76,17 @@ namespace CSVTools
void removeSelection();
public slots:
void stateChanged (int state, CSMDoc::Document *document);
signals:
void editRequest (const CSMWorld::UniversalId& id, const std::string& hint);
void replaceRequest();
void refreshRequest();
};
}

@ -0,0 +1,41 @@
#include "droplineedit.hpp"
#include <QDropEvent>
#include "../../model/world/tablemimedata.hpp"
#include "../../model/world/universalid.hpp"
#include "../world/dragdroputils.hpp"
CSVWidget::DropLineEdit::DropLineEdit(CSMWorld::ColumnBase::Display type, QWidget *parent)
: QLineEdit(parent),
mDropType(type)
{
setAcceptDrops(true);
}
void CSVWidget::DropLineEdit::dragEnterEvent(QDragEnterEvent *event)
{
if (CSVWorld::DragDropUtils::canAcceptData(*event, mDropType))
{
event->acceptProposedAction();
}
}
void CSVWidget::DropLineEdit::dragMoveEvent(QDragMoveEvent *event)
{
if (CSVWorld::DragDropUtils::canAcceptData(*event, mDropType))
{
event->accept();
}
}
void CSVWidget::DropLineEdit::dropEvent(QDropEvent *event)
{
if (CSVWorld::DragDropUtils::canAcceptData(*event, mDropType))
{
CSMWorld::UniversalId id = CSVWorld::DragDropUtils::getAcceptedData(*event, mDropType);
setText(QString::fromUtf8(id.getId().c_str()));
emit tableMimeDataDropped(id, CSVWorld::DragDropUtils::getTableMimeData(*event)->getDocumentPtr());
}
}

@ -0,0 +1,41 @@
#ifndef CSV_WIDGET_DROPLINEEDIT_HPP
#define CSV_WIDGET_DROPLINEEDIT_HPP
#include <QLineEdit>
#include "../../model/world/columnbase.hpp"
namespace CSMDoc
{
class Document;
}
namespace CSMWorld
{
class TableMimeData;
class UniversalId;
}
namespace CSVWidget
{
class DropLineEdit : public QLineEdit
{
Q_OBJECT
CSMWorld::ColumnBase::Display mDropType;
///< The accepted Display type for this LineEdit.
public:
DropLineEdit(CSMWorld::ColumnBase::Display type, QWidget *parent = 0);
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
signals:
void tableMimeDataDropped(const CSMWorld::UniversalId &id, const CSMDoc::Document *document);
};
}
#endif

@ -17,8 +17,6 @@
#include <QLineEdit>
#include <QPlainTextEdit>
#include <QComboBox>
#include <QPushButton>
#include <QToolButton>
#include <QHeaderView>
#include <QScrollBar>
@ -34,11 +32,13 @@
#include "../../model/doc/document.hpp"
#include "../widget/coloreditor.hpp"
#include "../widget/droplineedit.hpp"
#include "recordstatusdelegate.hpp"
#include "util.hpp"
#include "tablebottombox.hpp"
#include "nestedtable.hpp"
#include "recordbuttonbar.hpp"
/*
==============================NotEditableSubDelegate==========================================
*/
@ -63,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
@ -129,52 +137,6 @@ QWidget* CSVWorld::DialogueDelegateDispatcherProxy::getEditor() const
return mEditor;
}
void CSVWorld::DialogueDelegateDispatcherProxy::tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>& data, const CSMDoc::Document* document)
{
QLineEdit* lineEdit = qobject_cast<QLineEdit*>(mEditor);
{
if (!lineEdit || !mIndexWrapper.get())
{
return;
}
}
for (unsigned i = 0; i < data.size(); ++i)
{
CSMWorld::UniversalId::Type type = data[i].getType();
if (mDisplay == CSMWorld::ColumnBase::Display_Referenceable)
{
if (type == CSMWorld::UniversalId::Type_Activator
|| type == CSMWorld::UniversalId::Type_Potion
|| type == CSMWorld::UniversalId::Type_Apparatus
|| type == CSMWorld::UniversalId::Type_Armor
|| type == CSMWorld::UniversalId::Type_Book
|| type == CSMWorld::UniversalId::Type_Clothing
|| type == CSMWorld::UniversalId::Type_Container
|| type == CSMWorld::UniversalId::Type_Creature
|| type == CSMWorld::UniversalId::Type_Door
|| type == CSMWorld::UniversalId::Type_Ingredient
|| type == CSMWorld::UniversalId::Type_CreatureLevelledList
|| type == CSMWorld::UniversalId::Type_ItemLevelledList
|| type == CSMWorld::UniversalId::Type_Light
|| type == CSMWorld::UniversalId::Type_Lockpick
|| type == CSMWorld::UniversalId::Type_Miscellaneous
|| type == CSMWorld::UniversalId::Type_Npc
|| type == CSMWorld::UniversalId::Type_Probe
|| type == CSMWorld::UniversalId::Type_Repair
|| type == CSMWorld::UniversalId::Type_Static
|| type == CSMWorld::UniversalId::Type_Weapon)
{
type = CSMWorld::UniversalId::Type_Referenceable;
}
}
if (mDisplay == CSMWorld::TableMimeData::convertEnums(type))
{
emit tableMimeDataDropped(mEditor, mIndexWrapper->mIndex, data[i], document);
emit editorDataCommited(mEditor, mIndexWrapper->mIndex, mDisplay);
break;
}
}
}
/*
==============================DialogueDelegateDispatcher==========================================
*/
@ -306,16 +268,12 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::
// NOTE: For each entry in CSVWorld::CommandDelegate::createEditor() a corresponding entry
// is required here
if (qobject_cast<DropLineEdit*>(editor))
if (qobject_cast<CSVWidget::DropLineEdit*>(editor))
{
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited()));
connect(editor, SIGNAL(tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>&, const CSMDoc::Document*)),
proxy, SLOT(tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>&, const CSMDoc::Document*)));
connect(proxy, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)),
this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
connect(editor, SIGNAL(tableMimeDataDropped(const CSMWorld::UniversalId&, const CSMDoc::Document*)),
proxy, SLOT(editorDataCommited()));
}
else if (qobject_cast<QCheckBox*>(editor))
{
@ -386,9 +344,6 @@ mCommandDispatcher (commandDispatcher),
mDocument (document)
{
remake (row);
connect(mDispatcher, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)),
this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
}
void CSVWorld::EditWidget::remake(int row)
@ -600,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()))
@ -618,171 +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);
connect(mEditWidget, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)),
this, SLOT(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
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);
dataChanged(mTable->getModelIndex (getUniversalId().getId(), 0));
}
void CSVWorld::DialogueSubView::prevId ()
void CSVWorld::SimpleDialogueSubView::setEditLock (bool locked)
{
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;
}
}
void CSVWorld::DialogueSubView::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())
{
@ -795,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())
@ -828,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)
{
@ -843,60 +676,106 @@ void CSVWorld::DialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent,
}
}
void CSVWorld::DialogueSubView::tableMimeDataDropped (QWidget* editor,
const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document)
void CSVWorld::SimpleDialogueSubView::updateCurrentId()
{
if (document == &mDocument)
{
qobject_cast<DropLineEdit*>(editor)->setText(id.getId().c_str());
}
std::vector<std::string> selection;
selection.push_back (getUniversalId().getId());
mCommandDispatcher.setSelection(selection);
}
void CSVWorld::DialogueSubView::requestFocus (const std::string& id)
CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id,
CSMDoc::Document& document, const CreatorFactoryBase& creatorFactory, bool sorting)
: SimpleDialogueSubView (id, document)
{
changeCurrentId(id);
// 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)));
mEditWidget->remake(mTable->getModelIndex (id, 0).row());
connect (this, SIGNAL (universalIdChanged (const CSMWorld::UniversalId&)),
mButtons, SLOT (universalIdChanged (const CSMWorld::UniversalId&)));
}
void CSVWorld::DialogueSubView::cloneRequest ()
void CSVWorld::DialogueSubView::setEditLock (bool locked)
{
SimpleDialogueSubView::setEditLock (locked);
mButtons->setEditLock (locked);
}
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());
}

@ -86,18 +86,12 @@ namespace CSVWorld
public slots:
void editorDataCommited();
void setIndex(const QModelIndex& index);
void tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>& data,
const CSMDoc::Document* document);
signals:
void editorDataCommited(QWidget* editor,
const QModelIndex& index,
CSMWorld::ColumnBase::Display display);
void tableMimeDataDropped(QWidget* editor, const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document);
};
class DialogueDelegateDispatcher : public QAbstractItemDelegate
@ -153,11 +147,6 @@ namespace CSVWorld
private slots:
void editorDataCommited(QWidget* editor, const QModelIndex& index,
CSMWorld::ColumnBase::Display display);
signals:
void tableMimeDataDropped(QWidget* editor, const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document);
};
class EditWidget : public QScrollArea
@ -182,61 +171,74 @@ namespace CSVWorld
virtual ~EditWidget();
void remake(int row);
signals:
void tableMimeDataDropped(QWidget* editor, const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document);
};
class DialogueSubView : public CSVDoc::SubView
class SimpleDialogueSubView : public CSVDoc::SubView
{
Q_OBJECT
Q_OBJECT
EditWidget* mEditWidget;
QVBoxLayout* mMainLayout;
CSMWorld::IdTable* mTable;
QUndoStack& mUndoStack;
std::string mCurrentId;
bool mLocked;
const CSMDoc::Document& mDocument;
TableBottomBox* mBottom;
CSMWorld::CommandDispatcher mCommandDispatcher;
EditWidget* mEditWidget;
QVBoxLayout* mMainLayout;
CSMWorld::IdTable* mTable;
bool mLocked;
const CSMDoc::Document& mDocument;
CSMWorld::CommandDispatcher mCommandDispatcher;
public:
protected:
DialogueSubView (const CSMWorld::UniversalId& id,
CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory,
bool sorting = false);
QVBoxLayout& getMainLayout();
virtual void setEditLock (bool locked);
CSMWorld::IdTable& getTable();
private:
void changeCurrentId(const std::string& newCurrent);
CSMWorld::CommandDispatcher& getCommandDispatcher();
private slots:
EditWidget& getEditWidget();
void nextId();
void updateCurrentId();
void prevId();
bool isLocked() const;
void showPreview();
public:
void viewRecord();
SimpleDialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document);
void cloneRequest();
virtual void setEditLock (bool locked);
private slots:
void dataChanged(const QModelIndex & index);
///\brief we need to care for deleting currently edited record
void tableMimeDataDropped(QWidget* editor, const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document);
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
};
void requestFocus (const std::string& id);
class RecordButtonBar;
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
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);
virtual void updateUserSetting (const QString& name, const QStringList& value);
private slots:
void showPreview();
void viewRecord();
void switchToRow (int row);
void requestFocus (const std::string& id);
};
}

@ -0,0 +1,26 @@
#include "dragdroputils.hpp"
#include <QDropEvent>
#include "../../model/world/tablemimedata.hpp"
const CSMWorld::TableMimeData *CSVWorld::DragDropUtils::getTableMimeData(const QDropEvent &event)
{
return dynamic_cast<const CSMWorld::TableMimeData *>(event.mimeData());
}
bool CSVWorld::DragDropUtils::canAcceptData(const QDropEvent &event, CSMWorld::ColumnBase::Display type)
{
const CSMWorld::TableMimeData *data = getTableMimeData(event);
return data != NULL && data->holdsType(type);
}
CSMWorld::UniversalId CSVWorld::DragDropUtils::getAcceptedData(const QDropEvent &event,
CSMWorld::ColumnBase::Display type)
{
if (canAcceptData(event, type))
{
return getTableMimeData(event)->returnMatching(type);
}
return CSMWorld::UniversalId::Type_None;
}

@ -0,0 +1,29 @@
#ifndef CSV_WORLD_DRAGDROPUTILS_HPP
#define CSV_WORLD_DRAGDROPUTILS_HPP
#include "../../model/world/columnbase.hpp"
class QDropEvent;
namespace CSMWorld
{
class TableMimeData;
class UniversalId;
}
namespace CSVWorld
{
namespace DragDropUtils
{
const CSMWorld::TableMimeData *getTableMimeData(const QDropEvent &event);
bool canAcceptData(const QDropEvent &event, CSMWorld::ColumnBase::Display type);
///< Checks whether the \a event contains a valid CSMWorld::TableMimeData that holds the \a type
CSMWorld::UniversalId getAcceptedData(const QDropEvent &event, CSMWorld::ColumnBase::Display type);
///< Gets the accepted data from the \a event using the \a type
///< \return Type_None if the \a event data doesn't holds the \a type
}
}
#endif

@ -1,12 +1,24 @@
#include "dragrecordtable.hpp"
#include <QDrag>
#include <QDragEnterEvent>
#include "../../model/doc/document.hpp"
#include "../../model/world/tablemimedata.hpp"
#include "dragrecordtable.hpp"
#include "../../model/world/commands.hpp"
#include "dragdroputils.hpp"
void CSVWorld::DragRecordTable::startDragFromTable (const CSVWorld::DragRecordTable& table)
{
CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (table.getDraggedRecords(), mDocument);
std::vector<CSMWorld::UniversalId> records = table.getDraggedRecords();
if (records.empty())
{
return;
}
CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (records, mDocument);
if (mime)
{
@ -21,7 +33,9 @@ CSVWorld::DragRecordTable::DragRecordTable (CSMDoc::Document& document, QWidget*
QTableView(parent),
mDocument(document),
mEditLock(false)
{}
{
setAcceptDrops(true);
}
void CSVWorld::DragRecordTable::setEditLock (bool locked)
{
@ -35,5 +49,51 @@ void CSVWorld::DragRecordTable::dragEnterEvent(QDragEnterEvent *event)
void CSVWorld::DragRecordTable::dragMoveEvent(QDragMoveEvent *event)
{
event->accept();
QModelIndex index = indexAt(event->pos());
if (CSVWorld::DragDropUtils::canAcceptData(*event, getIndexDisplayType(index)))
{
if (index.flags() & Qt::ItemIsEditable)
{
event->accept();
}
}
else
{
event->ignore();
}
}
void CSVWorld::DragRecordTable::dropEvent(QDropEvent *event)
{
QModelIndex index = indexAt(event->pos());
CSMWorld::ColumnBase::Display display = getIndexDisplayType(index);
if (CSVWorld::DragDropUtils::canAcceptData(*event, display))
{
const CSMWorld::TableMimeData *data = CSVWorld::DragDropUtils::getTableMimeData(*event);
if (data->fromDocument(mDocument))
{
CSMWorld::UniversalId id = CSVWorld::DragDropUtils::getAcceptedData(*event, display);
QVariant newIndexData = QString::fromUtf8(id.getId().c_str());
QVariant oldIndexData = index.data(Qt::EditRole);
if (newIndexData != oldIndexData)
{
mDocument.getUndoStack().push(new CSMWorld::ModifyCommand(*model(), index, newIndexData));
}
}
}
}
CSMWorld::ColumnBase::Display CSVWorld::DragRecordTable::getIndexDisplayType(const QModelIndex &index) const
{
Q_ASSERT(model() != NULL);
if (index.isValid())
{
QVariant display = model()->headerData(index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display);
if (display.isValid())
{
return static_cast<CSMWorld::ColumnBase::Display>(display.toInt());
}
}
return CSMWorld::ColumnBase::Display_None;
}

@ -4,6 +4,8 @@
#include <QTableView>
#include <QEvent>
#include "../../model/world/columnbase.hpp"
class QWidget;
class QAction;
@ -38,6 +40,11 @@ namespace CSVWorld
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
private:
CSMWorld::ColumnBase::Display getIndexDisplayType(const QModelIndex &index) const;
};
}

@ -2,6 +2,8 @@
#include "../../model/world/idcompletionmanager.hpp"
#include "../widget/droplineedit.hpp"
CSVWorld::IdCompletionDelegate::IdCompletionDelegate(CSMWorld::CommandDispatcher *dispatcher,
CSMDoc::Document& document,
QObject *parent)
@ -26,7 +28,7 @@ QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent,
}
CSMWorld::IdCompletionManager &completionManager = getDocument().getIdCompletionManager();
DropLineEdit *editor = new DropLineEdit(parent);
CSVWidget::DropLineEdit *editor = new CSVWidget::DropLineEdit(display, parent);
editor->setCompleter(completionManager.getCompleter(display).get());
return editor;
}

@ -4,7 +4,6 @@
#include <algorithm>
#include <QLabel>
#include <QLineEdit>
#include <QUuid>
#include <components/misc/stringops.hpp>
@ -17,6 +16,8 @@
#include "../../model/world/idtable.hpp"
#include "../../model/world/idcompletionmanager.hpp"
#include "../widget/droplineedit.hpp"
std::string CSVWorld::InfoCreator::getId() const
{
std::string id = Misc::StringUtils::lowerCase (mTopic->text().toUtf8().constData());
@ -48,12 +49,12 @@ CSVWorld::InfoCreator::InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack,
QLabel *label = new QLabel ("Topic", this);
insertBeforeButtons (label, false);
mTopic = new QLineEdit (this);
CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Topic;
if (getCollectionId().getType() == CSMWorld::UniversalId::Type_JournalInfos)
{
displayType = CSMWorld::ColumnBase::Display_Journal;
}
mTopic = new CSVWidget::DropLineEdit(displayType, this);
mTopic->setCompleter(completionManager.getCompleter(displayType).get());
insertBeforeButtons (mTopic, true);

@ -3,21 +3,24 @@
#include "genericcreator.hpp"
class QLineEdit;
namespace CSMWorld
{
class InfoCollection;
class IdCompletionManager;
}
namespace CSVWidget
{
class DropLineEdit;
}
namespace CSVWorld
{
class InfoCreator : public GenericCreator
{
Q_OBJECT
QLineEdit *mTopic;
CSVWidget::DropLineEdit *mTopic;
virtual std::string getId() const;

@ -14,8 +14,7 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document,
CSMWorld::UniversalId id,
CSMWorld::NestedTableProxyModel* model,
QWidget* parent)
: QTableView(parent),
mUndoStack(document.getUndoStack()),
: DragRecordTable(document, parent),
mModel(model)
{
mDispatcher = new CSMWorld::CommandDispatcher (document, id, this);
@ -47,8 +46,6 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document,
setModel(model);
setAcceptDrops(true);
mAddNewRowAction = new QAction (tr ("Add new row"), this);
connect(mAddNewRowAction, SIGNAL(triggered()),
@ -60,12 +57,10 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document,
this, SLOT(removeRowActionTriggered()));
}
void CSVWorld::NestedTable::dragEnterEvent(QDragEnterEvent *event)
{
}
void CSVWorld::NestedTable::dragMoveEvent(QDragMoveEvent *event)
std::vector<CSMWorld::UniversalId> CSVWorld::NestedTable::getDraggedRecords() const
{
// No drag support for nested tables
return std::vector<CSMWorld::UniversalId>();
}
void CSVWorld::NestedTable::contextMenuEvent (QContextMenuEvent *event)
@ -84,16 +79,16 @@ void CSVWorld::NestedTable::contextMenuEvent (QContextMenuEvent *event)
void CSVWorld::NestedTable::removeRowActionTriggered()
{
mUndoStack.push(new CSMWorld::DeleteNestedCommand(*(mModel->model()),
mModel->getParentId(),
selectionModel()->selectedRows().begin()->row(),
mModel->getParentColumn()));
mDocument.getUndoStack().push(new CSMWorld::DeleteNestedCommand(*(mModel->model()),
mModel->getParentId(),
selectionModel()->selectedRows().begin()->row(),
mModel->getParentColumn()));
}
void CSVWorld::NestedTable::addNewRowActionTriggered()
{
mUndoStack.push(new CSMWorld::AddNestedCommand(*(mModel->model()),
mModel->getParentId(),
selectionModel()->selectedRows().size(),
mModel->getParentColumn()));
mDocument.getUndoStack().push(new CSMWorld::AddNestedCommand(*(mModel->model()),
mModel->getParentId(),
selectionModel()->selectedRows().size(),
mModel->getParentColumn()));
}

@ -1,10 +1,10 @@
#ifndef CSV_WORLD_NESTEDTABLE_H
#define CSV_WORLD_NESTEDTABLE_H
#include <QTableView>
#include <QEvent>
class QUndoStack;
#include "dragrecordtable.hpp"
class QAction;
class QContextMenuEvent;
@ -22,13 +22,12 @@ namespace CSMDoc
namespace CSVWorld
{
class NestedTable : public QTableView
class NestedTable : public DragRecordTable
{
Q_OBJECT
QAction *mAddNewRowAction;
QAction *mRemoveRowAction;
QUndoStack& mUndoStack;
CSMWorld::NestedTableProxyModel* mModel;
CSMWorld::CommandDispatcher *mDispatcher;
@ -38,10 +37,7 @@ namespace CSVWorld
CSMWorld::NestedTableProxyModel* model,
QWidget* parent = NULL);
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
virtual std::vector<CSMWorld::UniversalId> getDraggedRecords() const;
private:
void contextMenuEvent (QContextMenuEvent *event);

@ -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

@ -2,7 +2,6 @@
#include "referencecreator.hpp"
#include <QLabel>
#include <QLineEdit>
#include "../../model/doc/document.hpp"
@ -12,6 +11,8 @@
#include "../../model/world/idtable.hpp"
#include "../../model/world/idcompletionmanager.hpp"
#include "../widget/droplineedit.hpp"
std::string CSVWorld::ReferenceCreator::getId() const
{
return mId;
@ -80,7 +81,7 @@ CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack&
QLabel *label = new QLabel ("Cell", this);
insertBeforeButtons (label, false);
mCell = new QLineEdit (this);
mCell = new CSVWidget::DropLineEdit(CSMWorld::ColumnBase::Display_Cell, this);
mCell->setCompleter(completionManager.getCompleter(CSMWorld::ColumnBase::Display_Cell).get());
insertBeforeButtons (mCell, true);

@ -3,13 +3,16 @@
#include "genericcreator.hpp"
class QLineEdit;
namespace CSMWorld
{
class IdCompletionManager;
}
namespace CSVWidget
{
class DropLineEdit;
}
namespace CSVWorld
{
@ -17,7 +20,7 @@ namespace CSVWorld
{
Q_OBJECT
QLineEdit *mCell;
CSVWidget::DropLineEdit *mCell;
std::string mId;
private:

@ -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);
}
}
}
}
@ -697,36 +706,6 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event)
}
}
void CSVWorld::Table::dropEvent(QDropEvent *event)
{
QModelIndex index = indexAt (event->pos());
if (!index.isValid())
{
return;
}
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
if (!mime) // May happen when non-records (e.g. plain text) are dragged and dropped
return;
if (mime->fromDocument (mDocument))
{
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
(mModel->headerData (index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
if (mime->holdsType (display))
{
CSMWorld::UniversalId record (mime->returnMatching (display));
std::auto_ptr<CSMWorld::ModifyCommand> command (new CSMWorld::ModifyCommand
(*mProxyModel, index, QVariant (QString::fromUtf8 (record.getId().c_str()))));
mDocument.getUndoStack().push (command.release());
}
} //TODO handle drops from different document
}
std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const
{
const int count = mModel->columnCount();

@ -76,8 +76,6 @@ namespace CSVWorld
void mouseMoveEvent(QMouseEvent *event);
void dropEvent(QDropEvent *event);
protected:
virtual void mouseDoubleClickEvent (QMouseEvent *event);

@ -17,7 +17,10 @@
#include "../../model/world/commands.hpp"
#include "../../model/world/tablemimedata.hpp"
#include "../../model/world/commanddispatcher.hpp"
#include "../widget/coloreditor.hpp"
#include "../widget/droplineedit.hpp"
#include "dialoguespinbox.hpp"
#include "scriptedit.hpp"
@ -229,33 +232,35 @@ 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);
case CSMWorld::ColumnBase::Display_String:
case CSMWorld::ColumnBase::Display_Skill:
case CSMWorld::ColumnBase::Display_Script:
case CSMWorld::ColumnBase::Display_Race:
case CSMWorld::ColumnBase::Display_Region:
case CSMWorld::ColumnBase::Display_Class:
case CSMWorld::ColumnBase::Display_Faction:
case CSMWorld::ColumnBase::Display_Miscellaneous:
case CSMWorld::ColumnBase::Display_Sound:
case CSMWorld::ColumnBase::Display_Mesh:
case CSMWorld::ColumnBase::Display_Icon:
case CSMWorld::ColumnBase::Display_Music:
case CSMWorld::ColumnBase::Display_SoundRes:
case CSMWorld::ColumnBase::Display_Texture:
case CSMWorld::ColumnBase::Display_Video:
case CSMWorld::ColumnBase::Display_GlobalVariable:
return new DropLineEdit(parent);
case CSMWorld::ColumnBase::Display_ScriptLines:
return new ScriptEdit (mDocument, ScriptHighlighter::Mode_Console, parent);
case CSMWorld::ColumnBase::Display_String:
// For other Display types (that represent record IDs) with drop support IdCompletionDelegate is used
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);
@ -324,29 +329,3 @@ void CSVWorld::CommandDelegate::setEditorData (QWidget *editor, const QModelInde
}
}
CSVWorld::DropLineEdit::DropLineEdit(QWidget* parent) :
QLineEdit(parent)
{
setAcceptDrops(true);
}
void CSVWorld::DropLineEdit::dragEnterEvent(QDragEnterEvent *event)
{
event->acceptProposedAction();
}
void CSVWorld::DropLineEdit::dragMoveEvent(QDragMoveEvent *event)
{
event->accept();
}
void CSVWorld::DropLineEdit::dropEvent(QDropEvent *event)
{
const CSMWorld::TableMimeData* data(dynamic_cast<const CSMWorld::TableMimeData*>(event->mimeData()));
if (!data) // May happen when non-records (e.g. plain text) are dragged and dropped
return;
emit tableMimeDataDropped(data->getData(), data->getDocumentPtr());
//WIP
}

@ -5,7 +5,6 @@
#include <QAbstractTableModel>
#include <QStyledItemDelegate>
#include <QLineEdit>
#include "../../model/world/columnbase.hpp"
#include "../../model/doc/document.hpp"
@ -91,24 +90,6 @@ namespace CSVWorld
};
class DropLineEdit : public QLineEdit
{
Q_OBJECT
public:
DropLineEdit(QWidget *parent);
private:
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
signals:
void tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>& data, const CSMDoc::Document* document);
};
///< \brief Use commands instead of manipulating the model directly
class CommandDelegate : public QStyledItemDelegate
{

@ -45,6 +45,8 @@ std::set<MWMechanics::EffectKey> MWMechanics::Alchemy::listEffects() const
{
const MWWorld::LiveCellRef<ESM::Ingredient> *ingredient = iter->get<ESM::Ingredient>();
std::set<EffectKey> seenEffects;
for (int i=0; i<4; ++i)
if (ingredient->mBase->mData.mEffectID[i]!=-1)
{
@ -52,7 +54,8 @@ std::set<MWMechanics::EffectKey> MWMechanics::Alchemy::listEffects() const
ingredient->mBase->mData.mEffectID[i], ingredient->mBase->mData.mSkills[i]!=-1 ?
ingredient->mBase->mData.mSkills[i] : ingredient->mBase->mData.mAttributes[i]);
++effects[key];
if (seenEffects.insert(key).second)
++effects[key];
}
}
}
@ -461,7 +464,10 @@ MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& na
return Result_NoName;
if (listEffects().empty())
{
removeIngredients();
return Result_NoEffects;
}
if (beginEffects() == endEffects())
{

@ -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