mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-31 06:45:35 +00:00
Merge branch 'master' into cc9cii
This commit is contained in:
commit
2076acec10
94 changed files with 1471 additions and 757 deletions
|
@ -41,9 +41,9 @@ namespace ESSImport
|
|||
{
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
{
|
||||
npcStats.mSkills[i].mRegular.mMod = actorData.mSkills[i][1];
|
||||
npcStats.mSkills[i].mRegular.mCurrent = actorData.mSkills[i][1];
|
||||
npcStats.mSkills[i].mRegular.mBase = actorData.mSkills[i][0];
|
||||
npcStats.mSkills[i].mMod = actorData.mSkills[i][1];
|
||||
npcStats.mSkills[i].mCurrent = actorData.mSkills[i][1];
|
||||
npcStats.mSkills[i].mBase = actorData.mSkills[i][0];
|
||||
}
|
||||
|
||||
npcStats.mTimeToStartDrowning = actorData.mACDT.mBreathMeter;
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace ESSImport
|
|||
for (int i=0; i<8; ++i)
|
||||
out.mObject.mNpcStats.mSkillIncrease[i] = pcdt.mPNAM.mSkillIncreases[i];
|
||||
for (int i=0; i<27; ++i)
|
||||
out.mObject.mNpcStats.mSkills[i].mRegular.mProgress = pcdt.mPNAM.mSkillProgress[i];
|
||||
out.mObject.mNpcStats.mSkills[i].mProgress = pcdt.mPNAM.mSkillProgress[i];
|
||||
out.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress;
|
||||
|
||||
if (pcdt.mPNAM.mDrawState & PCDT::DrawState_Weapon)
|
||||
|
|
|
@ -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
|
||||
|
@ -70,12 +70,12 @@ opencs_units (view/world
|
|||
opencs_units_noqt (view/world
|
||||
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
|
||||
scripthighlighter idvalidator dialoguecreator physicssystem 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
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include <components/ogreinit/ogreinit.hpp>
|
||||
|
||||
#include "model/doc/messages.hpp"
|
||||
|
||||
#include "model/world/universalid.hpp"
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
|
@ -52,6 +54,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
qRegisterMetaType<std::string> ("std::string");
|
||||
qRegisterMetaType<CSMWorld::UniversalId> ("CSMWorld::UniversalId");
|
||||
qRegisterMetaType<CSMDoc::Message> ("CSMDoc::Message");
|
||||
|
||||
OgreInit::OgreInit ogreInit;
|
||||
|
||||
|
|
|
@ -2282,9 +2282,6 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
|||
|
||||
if (mNew)
|
||||
{
|
||||
mData.setDescription ("");
|
||||
mData.setAuthor ("");
|
||||
|
||||
if (mContentFiles.size()==1)
|
||||
createBase();
|
||||
}
|
||||
|
@ -2304,8 +2301,8 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
|||
connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
|
||||
|
||||
connect (
|
||||
&mSaving, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
|
||||
this, SLOT (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
|
||||
&mSaving, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||
this, SLOT (reportMessage (const CSMDoc::Message&, int)));
|
||||
|
||||
connect (&mRunner, SIGNAL (runStateChanged()), this, SLOT (runStateChanged()));
|
||||
}
|
||||
|
@ -2369,9 +2366,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;
|
||||
}
|
||||
|
@ -2401,11 +2398,10 @@ void CSMDoc::Document::modificationStateChanged (bool clean)
|
|||
emit stateChanged (getState(), this);
|
||||
}
|
||||
|
||||
void CSMDoc::Document::reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, int type)
|
||||
void CSMDoc::Document::reportMessage (const CSMDoc::Message& message, int type)
|
||||
{
|
||||
/// \todo find a better way to get these messages to the user.
|
||||
std::cout << message << std::endl;
|
||||
std::cout << message.mMessage << std::endl;
|
||||
}
|
||||
|
||||
void CSMDoc::Document::operationDone (int type, bool failed)
|
||||
|
|
|
@ -120,7 +120,7 @@ namespace CSMDoc
|
|||
|
||||
void save();
|
||||
|
||||
CSMWorld::UniversalId verify();
|
||||
CSMWorld::UniversalId verify (const CSMWorld::UniversalId& reportId = CSMWorld::UniversalId());
|
||||
|
||||
CSMWorld::UniversalId newSearch();
|
||||
|
||||
|
@ -158,8 +158,7 @@ namespace CSMDoc
|
|||
|
||||
void modificationStateChanged (bool clean);
|
||||
|
||||
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, int type);
|
||||
void reportMessage (const CSMDoc::Message& message, int type);
|
||||
|
||||
void operationDone (int type, bool failed);
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ void CSMDoc::Loader::load()
|
|||
{
|
||||
if (iter->second.mRecordsLeft)
|
||||
{
|
||||
CSMDoc::Messages messages;
|
||||
Messages messages (Message::Severity_Error);
|
||||
for (int i=0; i<batchingSize; ++i) // do not flood the system with update signals
|
||||
if (document->getData().continueLoading (messages))
|
||||
{
|
||||
|
@ -68,7 +68,7 @@ void CSMDoc::Loader::load()
|
|||
for (CSMDoc::Messages::Iterator iter (messages.begin());
|
||||
iter!=messages.end(); ++iter)
|
||||
{
|
||||
document->getReport (log)->add (iter->mId, iter->mMessage);
|
||||
document->getReport (log)->add (*iter);
|
||||
emit loadMessage (document, iter->mMessage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,25 @@
|
|||
|
||||
#include "messages.hpp"
|
||||
|
||||
void CSMDoc::Messages::add (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint)
|
||||
{
|
||||
Message data;
|
||||
data.mId = id;
|
||||
data.mMessage = message;
|
||||
data.mHint = hint;
|
||||
CSMDoc::Message::Message() {}
|
||||
|
||||
mMessages.push_back (data);
|
||||
CSMDoc::Message::Message (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, Severity severity)
|
||||
: mId (id), mMessage (message), mHint (hint), mSeverity (severity)
|
||||
{}
|
||||
|
||||
|
||||
CSMDoc::Messages::Messages (Message::Severity default_)
|
||||
: mDefault (default_)
|
||||
{}
|
||||
|
||||
void CSMDoc::Messages::add (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, Message::Severity severity)
|
||||
{
|
||||
if (severity==Message::Severity_Default)
|
||||
severity = mDefault;
|
||||
|
||||
mMessages.push_back (Message (id, message, hint, severity));
|
||||
}
|
||||
|
||||
void CSMDoc::Messages::push_back (const std::pair<CSMWorld::UniversalId, std::string>& data)
|
||||
|
|
|
@ -4,20 +4,41 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
enum Severity
|
||||
{
|
||||
Severity_Info = 0, // no problem
|
||||
Severity_Warning = 1, // a potential problem, but we are probably fine
|
||||
Severity_Error = 2, // an error; we are not fine
|
||||
Severity_SeriousError = 3, // an error so bad we can't even be sure if we are
|
||||
// reporting it correctly
|
||||
Severity_Default = 4
|
||||
};
|
||||
|
||||
CSMWorld::UniversalId mId;
|
||||
std::string mMessage;
|
||||
std::string mHint;
|
||||
Severity mSeverity;
|
||||
|
||||
Message();
|
||||
|
||||
Message (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, Severity severity);
|
||||
};
|
||||
|
||||
class Messages
|
||||
{
|
||||
public:
|
||||
|
||||
struct Message
|
||||
{
|
||||
CSMWorld::UniversalId mId;
|
||||
std::string mMessage;
|
||||
std::string mHint;
|
||||
};
|
||||
// \deprecated Use CSMDoc::Message directly instead.
|
||||
typedef CSMDoc::Message Message;
|
||||
|
||||
typedef std::vector<Message> Collection;
|
||||
|
||||
|
@ -26,11 +47,15 @@ namespace CSMDoc
|
|||
private:
|
||||
|
||||
Collection mMessages;
|
||||
Message::Severity mDefault;
|
||||
|
||||
public:
|
||||
|
||||
Messages (Message::Severity default_);
|
||||
|
||||
void add (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint = "");
|
||||
const std::string& hint = "",
|
||||
Message::Severity severity = Message::Severity_Default);
|
||||
|
||||
/// \deprecated Use add instead.
|
||||
void push_back (const std::pair<CSMWorld::UniversalId, std::string>& data);
|
||||
|
@ -41,4 +66,6 @@ namespace CSMDoc
|
|||
};
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE (CSMDoc::Message)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <QTimer>
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
#include "../settings/usersettings.hpp"
|
||||
|
||||
#include "state.hpp"
|
||||
#include "stage.hpp"
|
||||
|
@ -23,13 +24,17 @@ void CSMDoc::Operation::prepareStages()
|
|||
{
|
||||
iter->second = iter->first->setup();
|
||||
mTotalSteps += iter->second;
|
||||
|
||||
for (std::map<QString, QStringList>::const_iterator iter2 (mSettings.begin()); iter2!=mSettings.end(); ++iter2)
|
||||
iter->first->updateUserSetting (iter2->first, iter2->second);
|
||||
}
|
||||
}
|
||||
|
||||
CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways)
|
||||
: mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()),
|
||||
mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered),
|
||||
mFinalAlways (finalAlways), mError(false), mConnected (false)
|
||||
mFinalAlways (finalAlways), mError(false), mConnected (false), mPrepared (false),
|
||||
mDefaultSeverity (Message::Severity_Error)
|
||||
{
|
||||
mTimer = new QTimer (this);
|
||||
}
|
||||
|
@ -49,8 +54,8 @@ void CSMDoc::Operation::run()
|
|||
connect (mTimer, SIGNAL (timeout()), this, SLOT (executeStage()));
|
||||
mConnected = true;
|
||||
}
|
||||
|
||||
prepareStages();
|
||||
|
||||
mPrepared = false;
|
||||
|
||||
mTimer->start (0);
|
||||
}
|
||||
|
@ -60,6 +65,19 @@ void CSMDoc::Operation::appendStage (Stage *stage)
|
|||
mStages.push_back (std::make_pair (stage, 0));
|
||||
}
|
||||
|
||||
void CSMDoc::Operation::configureSettings (const std::vector<QString>& settings)
|
||||
{
|
||||
for (std::vector<QString>::const_iterator iter (settings.begin()); iter!=settings.end(); ++iter)
|
||||
{
|
||||
mSettings.insert (std::make_pair (*iter, CSMSettings::UserSettings::instance().definitions (*iter)));
|
||||
}
|
||||
}
|
||||
|
||||
void CSMDoc::Operation::setDefaultSeverity (Message::Severity severity)
|
||||
{
|
||||
mDefaultSeverity = severity;
|
||||
}
|
||||
|
||||
bool CSMDoc::Operation::hasError() const
|
||||
{
|
||||
return mError;
|
||||
|
@ -84,9 +102,23 @@ void CSMDoc::Operation::abort()
|
|||
mCurrentStage = mStages.end();
|
||||
}
|
||||
|
||||
void CSMDoc::Operation::updateUserSetting (const QString& name, const QStringList& value)
|
||||
{
|
||||
std::map<QString, QStringList>::iterator iter = mSettings.find (name);
|
||||
|
||||
if (iter!=mSettings.end())
|
||||
iter->second = value;
|
||||
}
|
||||
|
||||
void CSMDoc::Operation::executeStage()
|
||||
{
|
||||
Messages messages;
|
||||
if (!mPrepared)
|
||||
{
|
||||
prepareStages();
|
||||
mPrepared = true;
|
||||
}
|
||||
|
||||
Messages messages (mDefaultSeverity);
|
||||
|
||||
while (mCurrentStage!=mStages.end())
|
||||
{
|
||||
|
@ -103,7 +135,7 @@ void CSMDoc::Operation::executeStage()
|
|||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
emit reportMessage (CSMWorld::UniversalId(), e.what(), "", mType);
|
||||
emit reportMessage (Message (CSMWorld::UniversalId(), e.what(), "", Message::Severity_SeriousError), mType);
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -115,7 +147,7 @@ void CSMDoc::Operation::executeStage()
|
|||
emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType);
|
||||
|
||||
for (Messages::Iterator iter (messages.begin()); iter!=messages.end(); ++iter)
|
||||
emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType);
|
||||
emit reportMessage (*iter, mType);
|
||||
|
||||
if (mCurrentStage==mStages.end())
|
||||
operationDone();
|
||||
|
|
|
@ -2,9 +2,13 @@
|
|||
#define CSM_DOC_OPERATION_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QStringList>
|
||||
|
||||
#include "messages.hpp"
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
|
@ -30,6 +34,9 @@ namespace CSMDoc
|
|||
bool mError;
|
||||
bool mConnected;
|
||||
QTimer *mTimer;
|
||||
std::map<QString, QStringList> mSettings;
|
||||
bool mPrepared;
|
||||
Message::Severity mDefaultSeverity;
|
||||
|
||||
void prepareStages();
|
||||
|
||||
|
@ -46,14 +53,21 @@ namespace CSMDoc
|
|||
///
|
||||
/// \attention Do no call this function while this Operation is running.
|
||||
|
||||
/// Specify settings to be passed on to stages.
|
||||
///
|
||||
/// \attention Do no call this function while this Operation is running.
|
||||
void configureSettings (const std::vector<QString>& settings);
|
||||
|
||||
/// \attention Do no call this function while this Operation is running.
|
||||
void setDefaultSeverity (Message::Severity severity);
|
||||
|
||||
bool hasError() const;
|
||||
|
||||
signals:
|
||||
|
||||
void progress (int current, int max, int type);
|
||||
|
||||
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, int type);
|
||||
void reportMessage (const CSMDoc::Message& message, int type);
|
||||
|
||||
void done (int type, bool failed);
|
||||
|
||||
|
@ -63,6 +77,8 @@ namespace CSMDoc
|
|||
|
||||
void run();
|
||||
|
||||
void updateUserSetting (const QString& name, const QStringList& value);
|
||||
|
||||
private slots:
|
||||
|
||||
void executeStage();
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
|
||||
#include "operationholder.hpp"
|
||||
|
||||
#include "../settings/usersettings.hpp"
|
||||
|
||||
#include "operation.hpp"
|
||||
|
||||
CSMDoc::OperationHolder::OperationHolder (Operation *operation) : mRunning (false)
|
||||
|
@ -19,8 +21,8 @@ void CSMDoc::OperationHolder::setOperation (Operation *operation)
|
|||
this, SIGNAL (progress (int, int, int)));
|
||||
|
||||
connect (
|
||||
mOperation, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
|
||||
this, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
|
||||
mOperation, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||
this, SIGNAL (reportMessage (const CSMDoc::Message&, int)));
|
||||
|
||||
connect (
|
||||
mOperation, SIGNAL (done (int, bool)),
|
||||
|
@ -29,6 +31,9 @@ void CSMDoc::OperationHolder::setOperation (Operation *operation)
|
|||
connect (this, SIGNAL (abortSignal()), mOperation, SLOT (abort()));
|
||||
|
||||
connect (&mThread, SIGNAL (started()), mOperation, SLOT (run()));
|
||||
|
||||
connect (&CSMSettings::UserSettings::instance(), SIGNAL (userSettingUpdated (const QString&, const QStringList&)),
|
||||
mOperation, SLOT (updateUserSetting (const QString&, const QStringList&)));
|
||||
}
|
||||
|
||||
bool CSMDoc::OperationHolder::isRunning() const
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <QObject>
|
||||
#include <QThread>
|
||||
|
||||
#include "messages.hpp"
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class UniversalId;
|
||||
|
@ -44,8 +46,7 @@ namespace CSMDoc
|
|||
|
||||
void progress (int current, int max, int type);
|
||||
|
||||
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, int type);
|
||||
void reportMessage (const CSMDoc::Message& message, int type);
|
||||
|
||||
void done (int type, bool failed);
|
||||
|
||||
|
|
|
@ -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) +
|
||||
|
|
|
@ -2,3 +2,5 @@
|
|||
#include "stage.hpp"
|
||||
|
||||
CSMDoc::Stage::~Stage() {}
|
||||
|
||||
void CSMDoc::Stage::updateUserSetting (const QString& name, const QStringList& value) {}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include "messages.hpp"
|
||||
|
||||
class QString;
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Stage
|
||||
|
@ -21,6 +23,9 @@ namespace CSMDoc
|
|||
|
||||
virtual void perform (int stage, Messages& messages) = 0;
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
|
||||
/// Default-implementation: ignore
|
||||
virtual void updateUserSetting (const QString& name, const QStringList& value);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -303,7 +303,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||
autoDelete->setDefaultValue ("true");
|
||||
}
|
||||
|
||||
declareSection ("script-editor", "Script Editor");
|
||||
declareSection ("script-editor", "Scripts");
|
||||
{
|
||||
Setting *lineNum = createSetting (Type_CheckBox, "show-linenum", "Show Line Numbers");
|
||||
lineNum->setDefaultValue ("true");
|
||||
|
@ -322,6 +322,21 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||
"\nA name from the list of colors defined in the list of SVG color keyword names."
|
||||
"\nX11 color names may also work.";
|
||||
|
||||
QString modeNormal ("Normal");
|
||||
|
||||
QStringList modes;
|
||||
modes << "Ignore" << modeNormal << "Strict";
|
||||
|
||||
Setting *warnings = createSetting (Type_ComboBox, "warnings",
|
||||
"Warning Mode");
|
||||
warnings->setDeclaredValues (modes);
|
||||
warnings->setDefaultValue (modeNormal);
|
||||
warnings->setToolTip ("<ul>How to handle warning messages during compilation:<p>"
|
||||
"<li>Ignore: Do not report warning</li>"
|
||||
"<li>Normal: Report warning as a warning</li>"
|
||||
"<li>Strict: Promote warning to an error</li>"
|
||||
"</ul>");
|
||||
|
||||
Setting *formatInt = createSetting (Type_LineEdit, "colour-int", "Highlight Colour: Int");
|
||||
formatInt->setDefaultValues (QStringList() << "Dark magenta");
|
||||
formatInt->setToolTip ("(Default: Green) Use one of the following formats:" + tooltip);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,24 +6,18 @@
|
|||
|
||||
#include "../world/columns.hpp"
|
||||
|
||||
CSMTools::ReportModel::Line::Line (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint)
|
||||
: mId (id), mMessage (message), mHint (hint)
|
||||
{}
|
||||
|
||||
CSMTools::ReportModel::ReportModel (bool fieldColumn)
|
||||
CSMTools::ReportModel::ReportModel (bool fieldColumn, bool severityColumn)
|
||||
: mColumnField (-1), mColumnSeverity (-1)
|
||||
{
|
||||
if (fieldColumn)
|
||||
{
|
||||
mColumnField = 3;
|
||||
mColumnDescription = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
mColumnDescription = 3;
|
||||
int index = 3;
|
||||
|
||||
mColumnField = -1;
|
||||
}
|
||||
if (severityColumn)
|
||||
mColumnSeverity = index++;
|
||||
|
||||
if (fieldColumn)
|
||||
mColumnField = index++;
|
||||
|
||||
mColumnDescription = index;
|
||||
}
|
||||
|
||||
int CSMTools::ReportModel::rowCount (const QModelIndex & parent) const
|
||||
|
@ -88,6 +82,18 @@ QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const
|
|||
|
||||
return QString::fromUtf8 (field.c_str());
|
||||
}
|
||||
|
||||
if (index.column()==mColumnSeverity)
|
||||
{
|
||||
switch (mRows.at (index.row()).mSeverity)
|
||||
{
|
||||
case CSMDoc::Message::Severity_Info: return "Information";
|
||||
case CSMDoc::Message::Severity_Warning: return "Warning";
|
||||
case CSMDoc::Message::Severity_Error: return "Error";
|
||||
case CSMDoc::Message::Severity_SeriousError: return "Serious Error";
|
||||
case CSMDoc::Message::Severity_Default: break;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
@ -112,6 +118,9 @@ QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orienta
|
|||
if (section==mColumnField)
|
||||
return "Field";
|
||||
|
||||
if (section==mColumnSeverity)
|
||||
return "Severity";
|
||||
|
||||
return "-";
|
||||
}
|
||||
|
||||
|
@ -132,19 +141,18 @@ bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& p
|
|||
return true;
|
||||
}
|
||||
|
||||
void CSMTools::ReportModel::add (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint)
|
||||
void CSMTools::ReportModel::add (const CSMDoc::Message& message)
|
||||
{
|
||||
beginInsertRows (QModelIndex(), mRows.size(), mRows.size());
|
||||
|
||||
mRows.push_back (Line (id, message, hint));
|
||||
mRows.push_back (message);
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void CSMTools::ReportModel::flagAsReplaced (int index)
|
||||
{
|
||||
Line& line = mRows.at (index);
|
||||
CSMDoc::Message& line = mRows.at (index);
|
||||
std::string hint = line.mHint;
|
||||
|
||||
if (hint.empty() || hint[0]!='R')
|
||||
|
@ -176,3 +184,16 @@ void CSMTools::ReportModel::clear()
|
|||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
int CSMTools::ReportModel::countErrors() const
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (std::vector<CSMDoc::Messages::Message>::const_iterator iter (mRows.begin());
|
||||
iter!=mRows.end(); ++iter)
|
||||
if (iter->mSeverity==CSMDoc::Message::Severity_Error ||
|
||||
iter->mSeverity==CSMDoc::Message::Severity_SeriousError)
|
||||
++count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
#include "../doc/messages.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
namespace CSMTools
|
||||
|
@ -14,17 +16,7 @@ namespace CSMTools
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
struct Line
|
||||
{
|
||||
Line (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint);
|
||||
|
||||
CSMWorld::UniversalId mId;
|
||||
std::string mMessage;
|
||||
std::string mHint;
|
||||
};
|
||||
|
||||
std::vector<Line> mRows;
|
||||
std::vector<CSMDoc::Messages::Message> mRows;
|
||||
|
||||
// Fixed columns
|
||||
enum Columns
|
||||
|
@ -35,10 +27,11 @@ namespace CSMTools
|
|||
// Configurable columns
|
||||
int mColumnDescription;
|
||||
int mColumnField;
|
||||
int mColumnSeverity;
|
||||
|
||||
public:
|
||||
|
||||
ReportModel (bool fieldColumn = false);
|
||||
ReportModel (bool fieldColumn = false, bool severityColumn = true);
|
||||
|
||||
virtual int rowCount (const QModelIndex & parent = QModelIndex()) const;
|
||||
|
||||
|
@ -50,8 +43,7 @@ namespace CSMTools
|
|||
|
||||
virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex());
|
||||
|
||||
void add (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint = "");
|
||||
void add (const CSMDoc::Message& message);
|
||||
|
||||
void flagAsReplaced (int index);
|
||||
|
||||
|
@ -60,6 +52,9 @@ namespace CSMTools
|
|||
std::string getHint (int row) const;
|
||||
|
||||
void clear();
|
||||
|
||||
// Return number of messages with Error or SeriousError severity.
|
||||
int countErrors() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,17 @@
|
|||
|
||||
#include "../world/data.hpp"
|
||||
|
||||
CSMDoc::Message::Severity CSMTools::ScriptCheckStage::getSeverity (Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case WarningMessage: return CSMDoc::Message::Severity_Warning;
|
||||
case ErrorMessage: return CSMDoc::Message::Severity_Error;
|
||||
}
|
||||
|
||||
return CSMDoc::Message::Severity_SeriousError;
|
||||
}
|
||||
|
||||
void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc,
|
||||
Type type)
|
||||
{
|
||||
|
@ -18,11 +29,6 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi
|
|||
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||
|
||||
if (type==ErrorMessage)
|
||||
stream << "error ";
|
||||
else
|
||||
stream << "warning ";
|
||||
|
||||
stream
|
||||
<< "script " << mFile
|
||||
<< ", line " << loc.mLine << ", column " << loc.mColumn
|
||||
|
@ -32,19 +38,21 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi
|
|||
|
||||
hintStream << "l:" << loc.mLine << " " << loc.mColumn;
|
||||
|
||||
mMessages->add (id, stream.str(), hintStream.str());
|
||||
mMessages->add (id, stream.str(), hintStream.str(), getSeverity (type));
|
||||
}
|
||||
|
||||
void CSMTools::ScriptCheckStage::report (const std::string& message, Type type)
|
||||
{
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||
|
||||
mMessages->push_back (std::make_pair (id,
|
||||
(type==ErrorMessage ? "error: " : "warning: ") + message));
|
||||
std::ostringstream stream;
|
||||
stream << "script " << mFile << ": " << message;
|
||||
|
||||
mMessages->add (id, stream.str(), "", getSeverity (type));
|
||||
}
|
||||
|
||||
CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document)
|
||||
: mDocument (document), mContext (document.getData()), mMessages (0)
|
||||
: mDocument (document), mContext (document.getData()), mMessages (0), mWarningMode (Mode_Ignore)
|
||||
{
|
||||
/// \todo add an option to configure warning mode
|
||||
setWarningsMode (0);
|
||||
|
@ -58,6 +66,7 @@ int CSMTools::ScriptCheckStage::setup()
|
|||
mContext.clear();
|
||||
mMessages = 0;
|
||||
mId.clear();
|
||||
Compiler::ErrorHandler::reset();
|
||||
|
||||
return mDocument.getData().getScripts().getSize();
|
||||
}
|
||||
|
@ -72,6 +81,13 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
|
||||
mMessages = &messages;
|
||||
|
||||
switch (mWarningMode)
|
||||
{
|
||||
case Mode_Ignore: setWarningsMode (0); break;
|
||||
case Mode_Normal: setWarningsMode (1); break;
|
||||
case Mode_Strict: setWarningsMode (2); break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
const CSMWorld::Data& data = mDocument.getData();
|
||||
|
@ -93,9 +109,24 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
{
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||
|
||||
messages.push_back (std::make_pair (id,
|
||||
std::string ("Critical compile error: ") + error.what()));
|
||||
std::ostringstream stream;
|
||||
stream << "script " << mFile << ": " << error.what();
|
||||
|
||||
messages.add (id, stream.str(), "", CSMDoc::Message::Severity_SeriousError);
|
||||
}
|
||||
|
||||
mMessages = 0;
|
||||
}
|
||||
|
||||
void CSMTools::ScriptCheckStage::updateUserSetting (const QString& name, const QStringList& value)
|
||||
{
|
||||
if (name=="script-editor/warnings" && !value.isEmpty())
|
||||
{
|
||||
if (value.at (0)=="Ignore")
|
||||
mWarningMode = Mode_Ignore;
|
||||
else if (value.at (0)=="Normal")
|
||||
mWarningMode = Mode_Normal;
|
||||
else if (value.at (0)=="Strict")
|
||||
mWarningMode = Mode_Strict;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,13 +18,23 @@ namespace CSMTools
|
|||
/// \brief VerifyStage: make sure that scripts compile
|
||||
class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler
|
||||
{
|
||||
enum WarningMode
|
||||
{
|
||||
Mode_Ignore,
|
||||
Mode_Normal,
|
||||
Mode_Strict
|
||||
};
|
||||
|
||||
const CSMDoc::Document& mDocument;
|
||||
Compiler::Extensions mExtensions;
|
||||
CSMWorld::ScriptContext mContext;
|
||||
std::string mId;
|
||||
std::string mFile;
|
||||
CSMDoc::Messages *mMessages;
|
||||
WarningMode mWarningMode;
|
||||
|
||||
CSMDoc::Message::Severity getSeverity (Type type);
|
||||
|
||||
virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type);
|
||||
///< Report error to the user.
|
||||
|
||||
|
@ -40,6 +50,8 @@ namespace CSMTools
|
|||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this tage will be appended to \a messages.
|
||||
|
||||
virtual void updateUserSetting (const QString& name, const QStringList& value);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -280,7 +280,7 @@ void CSMTools::Search::replace (CSMDoc::Document& document, CSMWorld::IdTableBas
|
|||
bool CSMTools::Search::verify (CSMDoc::Document& document, CSMWorld::IdTableBase *model,
|
||||
const CSMWorld::UniversalId& id, const std::string& messageHint) const
|
||||
{
|
||||
CSMDoc::Messages messages;
|
||||
CSMDoc::Messages messages (CSMDoc::Message::Severity_Info);
|
||||
|
||||
int row = model->getModelIndex (id.getId(),
|
||||
model->findColumnIndex (CSMWorld::Columns::ColumnId_Id)).row();
|
||||
|
|
|
@ -21,6 +21,8 @@ CSMTools::SearchOperation::SearchOperation (CSMDoc::Document& document)
|
|||
iter!=types.end(); ++iter)
|
||||
appendStage (new SearchStage (&dynamic_cast<CSMWorld::IdTableBase&> (
|
||||
*document.getData().getTableModel (*iter))));
|
||||
|
||||
setDefaultSeverity (CSMDoc::Message::Severity_Info);
|
||||
}
|
||||
|
||||
void CSMTools::SearchOperation::configure (const Search& search)
|
||||
|
|
|
@ -51,11 +51,15 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier()
|
|||
{
|
||||
mVerifierOperation = new CSMDoc::Operation (CSMDoc::State_Verifying, false);
|
||||
|
||||
std::vector<QString> settings;
|
||||
settings.push_back ("script-editor/warnings");
|
||||
|
||||
mVerifierOperation->configureSettings (settings);
|
||||
|
||||
connect (&mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
||||
connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
|
||||
connect (&mVerifier,
|
||||
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
|
||||
this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
|
||||
connect (&mVerifier, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||
this, SLOT (verifierMessage (const CSMDoc::Message&, int)));
|
||||
|
||||
std::vector<std::string> mandatoryIds; // I want C++11, damn it!
|
||||
mandatoryIds.push_back ("Day");
|
||||
|
@ -120,9 +124,8 @@ CSMTools::Tools::Tools (CSMDoc::Document& document)
|
|||
|
||||
connect (&mSearch, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
||||
connect (&mSearch, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
|
||||
connect (&mSearch,
|
||||
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
|
||||
this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
|
||||
connect (&mSearch, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||
this, SLOT (verifierMessage (const CSMDoc::Message&, int)));
|
||||
}
|
||||
|
||||
CSMTools::Tools::~Tools()
|
||||
|
@ -143,19 +146,24 @@ 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()
|
||||
{
|
||||
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true)));
|
||||
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true, false)));
|
||||
|
||||
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Search, mNextReportNumber-1);
|
||||
}
|
||||
|
@ -210,12 +218,11 @@ CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId&
|
|||
return mReports.at (id.getIndex());
|
||||
}
|
||||
|
||||
void CSMTools::Tools::verifierMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, int type)
|
||||
void CSMTools::Tools::verifierMessage (const CSMDoc::Message& message, int type)
|
||||
{
|
||||
std::map<int, int>::iterator iter = mActiveReports.find (type);
|
||||
|
||||
if (iter!=mActiveReports.end())
|
||||
mReports[iter->second]->add (id, message, hint);
|
||||
mReports[iter->second]->add (message);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
@ -75,8 +78,7 @@ namespace CSMTools
|
|||
|
||||
private slots:
|
||||
|
||||
void verifierMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, int type);
|
||||
void verifierMessage (const CSMDoc::Message& message, int type);
|
||||
|
||||
signals:
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -923,7 +943,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
|
|||
{
|
||||
// log an error and continue loading the refs to the last loaded cell
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_None);
|
||||
messages.add (id, "Logic error: cell index out of bounds");
|
||||
messages.add (id, "Logic error: cell index out of bounds", "", CSMDoc::Message::Severity_Error);
|
||||
index = mCells.getSize()-1;
|
||||
}
|
||||
std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (index));
|
||||
|
@ -984,7 +1004,8 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
|
|||
else
|
||||
{
|
||||
messages.add (UniversalId::Type_None,
|
||||
"Trying to delete dialogue record " + id + " which does not exist");
|
||||
"Trying to delete dialogue record " + id + " which does not exist",
|
||||
"", CSMDoc::Message::Severity_Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1001,7 +1022,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
|
|||
if (!mDialogue)
|
||||
{
|
||||
messages.add (UniversalId::Type_None,
|
||||
"Found info record not following a dialogue record");
|
||||
"Found info record not following a dialogue record", "", CSMDoc::Message::Severity_Error);
|
||||
|
||||
mReader->skipRecord();
|
||||
break;
|
||||
|
@ -1044,7 +1065,8 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
|
|||
|
||||
if (unhandledRecord)
|
||||
{
|
||||
messages.add (UniversalId::Type_None, "Unsupported record type: " + n.toString());
|
||||
messages.add (UniversalId::Type_None, "Unsupported record type: " + n.toString(), "",
|
||||
CSMDoc::Message::Severity_Error);
|
||||
|
||||
mReader->skipRecord();
|
||||
}
|
||||
|
@ -1101,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();
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace
|
|||
types[CSMWorld::ColumnBase::Display_Faction ] = CSMWorld::UniversalId::Type_Faction;
|
||||
types[CSMWorld::ColumnBase::Display_GlobalVariable ] = CSMWorld::UniversalId::Type_Global;
|
||||
types[CSMWorld::ColumnBase::Display_Icon ] = CSMWorld::UniversalId::Type_Icon;
|
||||
types[CSMWorld::ColumnBase::Display_Journal ] = CSMWorld::UniversalId::Type_Journal;
|
||||
types[CSMWorld::ColumnBase::Display_Mesh ] = CSMWorld::UniversalId::Type_Mesh;
|
||||
types[CSMWorld::ColumnBase::Display_Miscellaneous ] = CSMWorld::UniversalId::Type_Referenceable;
|
||||
types[CSMWorld::ColumnBase::Display_Npc ] = CSMWorld::UniversalId::Type_Referenceable;
|
||||
|
@ -37,6 +38,7 @@ namespace
|
|||
types[CSMWorld::ColumnBase::Display_Spell ] = CSMWorld::UniversalId::Type_Spell;
|
||||
types[CSMWorld::ColumnBase::Display_Static ] = CSMWorld::UniversalId::Type_Referenceable;
|
||||
types[CSMWorld::ColumnBase::Display_Texture ] = CSMWorld::UniversalId::Type_Texture;
|
||||
types[CSMWorld::ColumnBase::Display_Topic ] = CSMWorld::UniversalId::Type_Topic;
|
||||
types[CSMWorld::ColumnBase::Display_Weapon ] = CSMWorld::UniversalId::Type_Referenceable;
|
||||
|
||||
return types;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
27
apps/opencs/model/world/metadata.cpp
Normal file
27
apps/opencs/model/world/metadata.cpp
Normal file
|
@ -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);
|
||||
}
|
29
apps/opencs/model/world/metadata.hpp
Normal file
29
apps/opencs/model/world/metadata.hpp
Normal file
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -87,6 +87,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);
|
||||
|
@ -844,6 +848,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);
|
||||
|
|
|
@ -232,6 +232,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,8 +74,10 @@ 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();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
41
apps/opencs/view/widget/droplineedit.cpp
Normal file
41
apps/opencs/view/widget/droplineedit.cpp
Normal file
|
@ -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());
|
||||
}
|
||||
}
|
41
apps/opencs/view/widget/droplineedit.hpp
Normal file
41
apps/opencs/view/widget/droplineedit.hpp
Normal file
|
@ -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
|
|
@ -15,8 +15,8 @@ void CSVWorld::Creator::setScope (unsigned int scope)
|
|||
CSVWorld::CreatorFactoryBase::~CreatorFactoryBase() {}
|
||||
|
||||
|
||||
CSVWorld::Creator *CSVWorld::NullCreatorFactory::makeCreator (CSMWorld::Data& data,
|
||||
QUndoStack& undoStack, const CSMWorld::UniversalId& id) const
|
||||
CSVWorld::Creator *CSVWorld::NullCreatorFactory::makeCreator (CSMDoc::Document& document,
|
||||
const CSMWorld::UniversalId& id) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -5,16 +5,14 @@
|
|||
|
||||
#include <QWidget>
|
||||
|
||||
#include "../../model/world/universalid.hpp"
|
||||
#include "../../model/doc/document.hpp"
|
||||
|
||||
#include "../../model/world/scope.hpp"
|
||||
#include "../../model/world/universalid.hpp"
|
||||
|
||||
class QUndoStack;
|
||||
|
||||
namespace CSMWorld
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Data;
|
||||
class UniversalId;
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
|
@ -59,8 +57,7 @@ namespace CSVWorld
|
|||
|
||||
virtual ~CreatorFactoryBase();
|
||||
|
||||
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const = 0;
|
||||
virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const = 0;
|
||||
///< The ownership of the returned Creator is transferred to the caller.
|
||||
///
|
||||
/// \note The function can return a 0-pointer, which means no UI for creating/deleting
|
||||
|
@ -72,8 +69,7 @@ namespace CSVWorld
|
|||
{
|
||||
public:
|
||||
|
||||
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const;
|
||||
virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const;
|
||||
///< The ownership of the returned Creator is transferred to the caller.
|
||||
///
|
||||
/// \note The function always returns 0.
|
||||
|
@ -84,8 +80,7 @@ namespace CSVWorld
|
|||
{
|
||||
public:
|
||||
|
||||
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const;
|
||||
virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const;
|
||||
///< The ownership of the returned Creator is transferred to the caller.
|
||||
///
|
||||
/// \note The function can return a 0-pointer, which means no UI for creating/deleting
|
||||
|
@ -93,10 +88,10 @@ namespace CSVWorld
|
|||
};
|
||||
|
||||
template<class CreatorT, unsigned int scope>
|
||||
Creator *CreatorFactory<CreatorT, scope>::makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const
|
||||
Creator *CreatorFactory<CreatorT, scope>::makeCreator (CSMDoc::Document& document,
|
||||
const CSMWorld::UniversalId& id) const
|
||||
{
|
||||
std::auto_ptr<CreatorT> creator (new CreatorT (data, undoStack, id));
|
||||
std::auto_ptr<CreatorT> creator (new CreatorT (document.getData(), document.getUndoStack(), id));
|
||||
|
||||
creator->setScope (scope);
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <components/esm/loaddial.hpp>
|
||||
|
||||
#include "../../model/doc/document.hpp"
|
||||
|
||||
#include "../../model/world/data.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
#include "../../model/world/columns.hpp"
|
||||
|
@ -22,14 +24,14 @@ CSVWorld::DialogueCreator::DialogueCreator (CSMWorld::Data& data, QUndoStack& un
|
|||
: GenericCreator (data, undoStack, id, true), mType (type)
|
||||
{}
|
||||
|
||||
CSVWorld::Creator *CSVWorld::TopicCreatorFactory::makeCreator (CSMWorld::Data& data,
|
||||
QUndoStack& undoStack, const CSMWorld::UniversalId& id) const
|
||||
CSVWorld::Creator *CSVWorld::TopicCreatorFactory::makeCreator (CSMDoc::Document& document,
|
||||
const CSMWorld::UniversalId& id) const
|
||||
{
|
||||
return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Topic);
|
||||
return new DialogueCreator (document.getData(), document.getUndoStack(), id, ESM::Dialogue::Topic);
|
||||
}
|
||||
|
||||
CSVWorld::Creator *CSVWorld::JournalCreatorFactory::makeCreator (CSMWorld::Data& data,
|
||||
QUndoStack& undoStack, const CSMWorld::UniversalId& id) const
|
||||
CSVWorld::Creator *CSVWorld::JournalCreatorFactory::makeCreator (CSMDoc::Document& document,
|
||||
const CSMWorld::UniversalId& id) const
|
||||
{
|
||||
return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Journal);
|
||||
return new DialogueCreator (document.getData(), document.getUndoStack(), id, ESM::Dialogue::Journal);
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@ namespace CSVWorld
|
|||
{
|
||||
public:
|
||||
|
||||
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const;
|
||||
virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const;
|
||||
///< The ownership of the returned Creator is transferred to the caller.
|
||||
};
|
||||
|
||||
|
@ -32,8 +31,7 @@ namespace CSVWorld
|
|||
{
|
||||
public:
|
||||
|
||||
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const;
|
||||
virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const;
|
||||
///< The ownership of the returned Creator is transferred to the caller.
|
||||
};
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "../../model/doc/document.hpp"
|
||||
|
||||
#include "../widget/coloreditor.hpp"
|
||||
#include "../widget/droplineedit.hpp"
|
||||
|
||||
#include "recordstatusdelegate.hpp"
|
||||
#include "util.hpp"
|
||||
|
@ -63,16 +64,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 +138,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 +269,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 +345,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,12 +556,38 @@ 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;
|
||||
}
|
||||
|
||||
std::string CSVWorld::SimpleDialogueSubView::getCurrentId() const
|
||||
{
|
||||
return mCurrentId;
|
||||
}
|
||||
|
||||
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),
|
||||
|
@ -622,162 +604,19 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
|
|||
|
||||
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*)));
|
||||
|
||||
mMainLayout->addWidget(mEditWidget);
|
||||
mEditWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
|
||||
mMainLayout->addWidget (mBottom =
|
||||
new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), 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;
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::setEditLock (bool locked)
|
||||
void CSVWorld::SimpleDialogueSubView::setEditLock (bool locked)
|
||||
{
|
||||
if (!mEditWidget) // hack to indicate that mCurrentId is no longer valid
|
||||
return;
|
||||
|
@ -796,7 +635,7 @@ 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));
|
||||
|
||||
|
@ -829,7 +668,7 @@ 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));
|
||||
|
||||
|
@ -844,56 +683,14 @@ void CSVWorld::DialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent,
|
|||
}
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::tableMimeDataDropped (QWidget* editor,
|
||||
const QModelIndex& index,
|
||||
const CSMWorld::UniversalId& id,
|
||||
const CSMDoc::Document* document)
|
||||
{
|
||||
if (document == &mDocument)
|
||||
{
|
||||
qobject_cast<DropLineEdit*>(editor)->setText(id.getId().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::requestFocus (const std::string& id)
|
||||
void CSVWorld::SimpleDialogueSubView::requestFocus (const std::string& id)
|
||||
{
|
||||
changeCurrentId(id);
|
||||
|
||||
mEditWidget->remake(mTable->getModelIndex (id, 0).row());
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::cloneRequest ()
|
||||
{
|
||||
mBottom->cloneRequest(mCurrentId, static_cast<CSMWorld::UniversalId::Type>(mTable->data(mTable->getModelIndex(mCurrentId, 2)).toInt()));
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::showPreview ()
|
||||
{
|
||||
QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0));
|
||||
|
||||
if (currentIndex.isValid() &&
|
||||
mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview &&
|
||||
currentIndex.row() < mTable->rowCount())
|
||||
{
|
||||
emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, mCurrentId), "");
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::viewRecord ()
|
||||
{
|
||||
QModelIndex currentIndex(mTable->getModelIndex (mCurrentId, 0));
|
||||
|
||||
if (currentIndex.isValid() &&
|
||||
currentIndex.row() < mTable->rowCount())
|
||||
{
|
||||
std::pair<CSMWorld::UniversalId, std::string> params = mTable->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::SimpleDialogueSubView::changeCurrentId (const std::string& newId)
|
||||
{
|
||||
std::vector<std::string> selection;
|
||||
mCurrentId = std::string(newId);
|
||||
|
@ -901,3 +698,186 @@ void CSVWorld::DialogueSubView::changeCurrentId (const std::string& newId)
|
|||
selection.push_back(mCurrentId);
|
||||
mCommandDispatcher.setSelection(selection);
|
||||
}
|
||||
|
||||
|
||||
CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id,
|
||||
CSMDoc::Document& document, const CreatorFactoryBase& creatorFactory, bool sorting)
|
||||
: SimpleDialogueSubView (id, document)
|
||||
{
|
||||
// bottom box
|
||||
getMainLayout().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&)));
|
||||
|
||||
// buttons
|
||||
QHBoxLayout *buttonsLayout = new QHBoxLayout;
|
||||
QToolButton* prevButton = new QToolButton (this);
|
||||
prevButton->setIcon(QIcon(":/go-previous.png"));
|
||||
prevButton->setToolTip ("Switch to previous record");
|
||||
QToolButton* nextButton = new QToolButton (this);
|
||||
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 (this);
|
||||
cloneButton->setIcon(QIcon(":/edit-clone.png"));
|
||||
cloneButton->setToolTip ("Clone record");
|
||||
QToolButton* addButton = new QToolButton (this);
|
||||
addButton->setIcon(QIcon(":/add.png"));
|
||||
addButton->setToolTip ("Add new record");
|
||||
QToolButton* deleteButton = new QToolButton (this);
|
||||
deleteButton->setIcon(QIcon(":/edit-delete.png"));
|
||||
deleteButton->setToolTip ("Delete record");
|
||||
QToolButton* revertButton = new QToolButton (this);
|
||||
revertButton->setIcon(QIcon(":/edit-undo.png"));
|
||||
revertButton->setToolTip ("Revert record");
|
||||
|
||||
if (getTable().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, SLOT(showPreview()));
|
||||
}
|
||||
|
||||
if (getTable().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, 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()), &getCommandDispatcher(), SLOT(executeRevert()));
|
||||
connect(deleteButton, SIGNAL(clicked()), &getCommandDispatcher(), SLOT(executeDelete()));
|
||||
|
||||
connect(addButton, SIGNAL(clicked()), mBottom, SLOT(createRequest()));
|
||||
|
||||
if(!mBottom->canCreateAndDelete())
|
||||
{
|
||||
cloneButton->setDisabled (true);
|
||||
addButton->setDisabled (true);
|
||||
deleteButton->setDisabled (true);
|
||||
}
|
||||
|
||||
getMainLayout().addLayout (buttonsLayout);
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::cloneRequest()
|
||||
{
|
||||
mBottom->cloneRequest (getCurrentId(),
|
||||
static_cast<CSMWorld::UniversalId::Type> (getTable().
|
||||
data (getTable().getModelIndex(getCurrentId(), 2)).toInt()));
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::prevId()
|
||||
{
|
||||
int newRow = getTable().getModelIndex (getCurrentId(), 0).row() - 1;
|
||||
|
||||
if (newRow < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (newRow >= 0)
|
||||
{
|
||||
QModelIndex newIndex (getTable().index(newRow, 0));
|
||||
|
||||
if (!newIndex.isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State> (getTable().data (getTable().index (newRow, 1)).toInt());
|
||||
if (!(state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased))
|
||||
{
|
||||
getEditWidget().remake (newRow);
|
||||
|
||||
setUniversalId(CSMWorld::UniversalId (static_cast<CSMWorld::UniversalId::Type> (getTable().data (getTable().index (newRow, 2)).toInt()),
|
||||
getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData()));
|
||||
|
||||
changeCurrentId(std::string (getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData()));
|
||||
|
||||
getEditWidget().setDisabled (isLocked());
|
||||
|
||||
return;
|
||||
}
|
||||
--newRow;
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::nextId ()
|
||||
{
|
||||
int newRow = getTable().getModelIndex (getCurrentId(), 0).row() + 1;
|
||||
|
||||
if (newRow >= getTable().rowCount())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (newRow < getTable().rowCount())
|
||||
{
|
||||
QModelIndex newIndex (getTable().index(newRow, 0));
|
||||
|
||||
if (!newIndex.isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State> (getTable().data (getTable().index (newRow, 1)).toInt());
|
||||
if (!(state == CSMWorld::RecordBase::State_Deleted))
|
||||
{
|
||||
getEditWidget().remake(newRow);
|
||||
|
||||
setUniversalId(CSMWorld::UniversalId (static_cast<CSMWorld::UniversalId::Type> (getTable().data (getTable().index (newRow, 2)).toInt()),
|
||||
getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData()));
|
||||
|
||||
changeCurrentId(std::string (getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData()));
|
||||
|
||||
getEditWidget().setDisabled (isLocked());
|
||||
|
||||
return;
|
||||
}
|
||||
++newRow;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CSVWorld::DialogueSubView::showPreview ()
|
||||
{
|
||||
QModelIndex currentIndex (getTable().getModelIndex (getCurrentId(), 0));
|
||||
|
||||
if (currentIndex.isValid() &&
|
||||
getTable().getFeatures() & CSMWorld::IdTable::Feature_Preview &&
|
||||
currentIndex.row() < getTable().rowCount())
|
||||
{
|
||||
emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, getCurrentId()), "");
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::viewRecord ()
|
||||
{
|
||||
QModelIndex currentIndex (getTable().getModelIndex (getCurrentId(), 0));
|
||||
|
||||
if (currentIndex.isValid() &&
|
||||
currentIndex.row() < getTable().rowCount())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,14 +171,9 @@ 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
|
||||
|
||||
|
@ -200,23 +184,55 @@ namespace CSVWorld
|
|||
std::string mCurrentId;
|
||||
bool mLocked;
|
||||
const CSMDoc::Document& mDocument;
|
||||
TableBottomBox* mBottom;
|
||||
CSMWorld::CommandDispatcher mCommandDispatcher;
|
||||
|
||||
protected:
|
||||
|
||||
QVBoxLayout& getMainLayout();
|
||||
|
||||
CSMWorld::IdTable& getTable();
|
||||
|
||||
CSMWorld::CommandDispatcher& getCommandDispatcher();
|
||||
|
||||
std::string getCurrentId() const;
|
||||
|
||||
EditWidget& getEditWidget();
|
||||
|
||||
void changeCurrentId(const std::string& newCurrent);
|
||||
|
||||
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 dataChanged(const QModelIndex & index);
|
||||
///\brief we need to care for deleting currently edited record
|
||||
|
||||
void requestFocus (const std::string& id);
|
||||
|
||||
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
|
||||
};
|
||||
|
||||
class DialogueSubView : public SimpleDialogueSubView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
TableBottomBox* mBottom;
|
||||
|
||||
public:
|
||||
|
||||
DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
|
||||
const CreatorFactoryBase& creatorFactory, bool sorting = false);
|
||||
|
||||
private slots:
|
||||
|
||||
void cloneRequest();
|
||||
|
||||
void nextId();
|
||||
|
||||
void prevId();
|
||||
|
@ -224,19 +240,6 @@ namespace CSVWorld
|
|||
void showPreview();
|
||||
|
||||
void viewRecord();
|
||||
|
||||
void cloneRequest();
|
||||
|
||||
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 requestFocus (const std::string& id);
|
||||
|
||||
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
26
apps/opencs/view/world/dragdroputils.cpp
Normal file
26
apps/opencs/view/world/dragdroputils.cpp
Normal file
|
@ -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;
|
||||
}
|
29
apps/opencs/view/world/dragdroputils.hpp
Normal file
29
apps/opencs/view/world/dragdroputils.hpp
Normal file
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -133,6 +133,15 @@ CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undo
|
|||
mClonedType (CSMWorld::UniversalId::Type_None), mScopes (CSMWorld::Scope_Content), mScope (0),
|
||||
mScopeLabel (0), mCloneMode (false)
|
||||
{
|
||||
// If the collection ID has a parent type, use it instead.
|
||||
// It will change IDs with Record/SubRecord class (used for creators in Dialogue subviews)
|
||||
// to IDs with general RecordList class (used for creators in Table subviews).
|
||||
CSMWorld::UniversalId::Type listParentType = CSMWorld::UniversalId::getParentType(mListId.getType());
|
||||
if (listParentType != CSMWorld::UniversalId::Type_None)
|
||||
{
|
||||
mListId = listParentType;
|
||||
}
|
||||
|
||||
mLayout = new QHBoxLayout;
|
||||
mLayout->setContentsMargins (0, 0, 0, 0);
|
||||
|
||||
|
|
|
@ -13,10 +13,12 @@ class QLineEdit;
|
|||
class QHBoxLayout;
|
||||
class QComboBox;
|
||||
class QLabel;
|
||||
class QUndoStack;
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class CreateCommand;
|
||||
class Data;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
|
|
|
@ -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,15 +4,19 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QUuid>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "../../model/doc/document.hpp"
|
||||
|
||||
#include "../../model/world/data.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
#include "../../model/world/columns.hpp"
|
||||
#include "../../model/world/idtable.hpp"
|
||||
#include "../../model/world/idcompletionmanager.hpp"
|
||||
|
||||
#include "../widget/droplineedit.hpp"
|
||||
|
||||
std::string CSVWorld::InfoCreator::getId() const
|
||||
{
|
||||
|
@ -39,13 +43,19 @@ void CSVWorld::InfoCreator::configureCreateCommand (CSMWorld::CreateCommand& com
|
|||
}
|
||||
|
||||
CSVWorld::InfoCreator::InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id)
|
||||
const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager)
|
||||
: GenericCreator (data, undoStack, id)
|
||||
{
|
||||
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);
|
||||
|
||||
setManualEditing (false);
|
||||
|
@ -100,3 +110,12 @@ void CSVWorld::InfoCreator::topicChanged()
|
|||
{
|
||||
update();
|
||||
}
|
||||
|
||||
CSVWorld::Creator *CSVWorld::InfoCreatorFactory::makeCreator(CSMDoc::Document& document,
|
||||
const CSMWorld::UniversalId& id) const
|
||||
{
|
||||
return new InfoCreator(document.getData(),
|
||||
document.getUndoStack(),
|
||||
id,
|
||||
document.getIdCompletionManager());
|
||||
}
|
||||
|
|
|
@ -3,11 +3,15 @@
|
|||
|
||||
#include "genericcreator.hpp"
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class InfoCollection;
|
||||
class IdCompletionManager;
|
||||
}
|
||||
|
||||
namespace CSVWidget
|
||||
{
|
||||
class DropLineEdit;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
|
@ -16,7 +20,7 @@ namespace CSVWorld
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
QLineEdit *mTopic;
|
||||
CSVWidget::DropLineEdit *mTopic;
|
||||
|
||||
virtual std::string getId() const;
|
||||
|
||||
|
@ -25,7 +29,7 @@ namespace CSVWorld
|
|||
public:
|
||||
|
||||
InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id);
|
||||
const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager);
|
||||
|
||||
virtual void cloneMode (const std::string& originId,
|
||||
const CSMWorld::UniversalId::Type type);
|
||||
|
@ -43,6 +47,14 @@ namespace CSVWorld
|
|||
|
||||
void topicChanged();
|
||||
};
|
||||
|
||||
class InfoCreatorFactory : public CreatorFactoryBase
|
||||
{
|
||||
public:
|
||||
|
||||
virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const;
|
||||
///< The ownership of the returned Creator is transferred to the caller.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
#include "referencecreator.hpp"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "../../model/doc/document.hpp"
|
||||
|
||||
#include "../../model/world/data.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
#include "../../model/world/columns.hpp"
|
||||
#include "../../model/world/idtable.hpp"
|
||||
#include "../../model/world/idcompletionmanager.hpp"
|
||||
|
||||
#include "../widget/droplineedit.hpp"
|
||||
|
||||
std::string CSVWorld::ReferenceCreator::getId() const
|
||||
{
|
||||
|
@ -71,13 +75,14 @@ int CSVWorld::ReferenceCreator::getRefNumCount() const
|
|||
}
|
||||
|
||||
CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id)
|
||||
const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager &completionManager)
|
||||
: GenericCreator (data, undoStack, id)
|
||||
{
|
||||
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);
|
||||
|
||||
setManualEditing (false);
|
||||
|
@ -142,3 +147,12 @@ void CSVWorld::ReferenceCreator::cloneMode(const std::string& originId,
|
|||
CSVWorld::GenericCreator::cloneMode(originId, type);
|
||||
cellChanged(); //otherwise ok button will remain disabled
|
||||
}
|
||||
|
||||
CSVWorld::Creator *CSVWorld::ReferenceCreatorFactory::makeCreator (CSMDoc::Document& document,
|
||||
const CSMWorld::UniversalId& id) const
|
||||
{
|
||||
return new ReferenceCreator(document.getData(),
|
||||
document.getUndoStack(),
|
||||
id,
|
||||
document.getIdCompletionManager());
|
||||
}
|
||||
|
|
|
@ -3,15 +3,24 @@
|
|||
|
||||
#include "genericcreator.hpp"
|
||||
|
||||
class QLineEdit;
|
||||
namespace CSMWorld
|
||||
{
|
||||
class IdCompletionManager;
|
||||
}
|
||||
|
||||
namespace CSVWidget
|
||||
{
|
||||
class DropLineEdit;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
|
||||
class ReferenceCreator : public GenericCreator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QLineEdit *mCell;
|
||||
CSVWidget::DropLineEdit *mCell;
|
||||
std::string mId;
|
||||
|
||||
private:
|
||||
|
@ -28,7 +37,7 @@ namespace CSVWorld
|
|||
public:
|
||||
|
||||
ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id);
|
||||
const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager &completionManager);
|
||||
|
||||
virtual void cloneMode(const std::string& originId,
|
||||
const CSMWorld::UniversalId::Type type);
|
||||
|
@ -46,6 +55,14 @@ namespace CSVWorld
|
|||
|
||||
void cellChanged();
|
||||
};
|
||||
|
||||
class ReferenceCreatorFactory : public CreatorFactoryBase
|
||||
{
|
||||
public:
|
||||
|
||||
virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const;
|
||||
///< The ownership of the returned Creator is transferred to the caller.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,9 +33,7 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D
|
|||
|
||||
layout->setContentsMargins (QMargins (0, 0, 0, 0));
|
||||
|
||||
layout->addWidget (mBottom =
|
||||
new TableBottomBox (NullCreatorFactory(), document.getData(), document.getUndoStack(), id,
|
||||
this), 0);
|
||||
layout->addWidget (mBottom = new TableBottomBox (NullCreatorFactory(), document, id, this), 0);
|
||||
|
||||
mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
|||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<ReferenceableCreator> >);
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_References,
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<ReferenceCreator> >);
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, ReferenceCreatorFactory>);
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Topics,
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, TopicCreatorFactory>);
|
||||
|
@ -68,10 +68,10 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
|||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, JournalCreatorFactory>);
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_TopicInfos,
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<InfoCreator> >);
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, InfoCreatorFactory>);
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_JournalInfos,
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<InfoCreator> >);
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, InfoCreatorFactory>);
|
||||
|
||||
// Subviews for resources tables
|
||||
manager.add (CSMWorld::UniversalId::Type_Meshes,
|
||||
|
@ -147,16 +147,16 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
|||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<ReferenceableCreator> > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Reference,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<ReferenceCreator> > (false));
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, ReferenceCreatorFactory> (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Cell,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<CellCreator> > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_JournalInfo,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<InfoCreator> > (false));
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, InfoCreatorFactory> (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_TopicInfo,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<InfoCreator> >(false));
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, InfoCreatorFactory>(false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Topic,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, TopicCreatorFactory> (false));
|
||||
|
@ -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"
|
||||
|
@ -131,17 +133,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -748,36 +757,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();
|
||||
|
|
|
@ -80,8 +80,6 @@ namespace CSVWorld
|
|||
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
|
||||
void dropEvent(QDropEvent *event);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void mouseDoubleClickEvent (QMouseEvent *event);
|
||||
|
|
|
@ -39,8 +39,10 @@ void CSVWorld::TableBottomBox::updateStatus()
|
|||
}
|
||||
}
|
||||
|
||||
CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFactory,
|
||||
CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, QWidget *parent)
|
||||
CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFactory,
|
||||
CSMDoc::Document& document,
|
||||
const CSMWorld::UniversalId& id,
|
||||
QWidget *parent)
|
||||
: QWidget (parent), mShowStatusBar (false), mCreating (false)
|
||||
{
|
||||
for (int i=0; i<4; ++i)
|
||||
|
@ -61,7 +63,7 @@ CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFacto
|
|||
|
||||
setLayout (mLayout);
|
||||
|
||||
mCreator = creatorFactory.makeCreator (data, undoStack, id);
|
||||
mCreator = creatorFactory.makeCreator (document, id);
|
||||
|
||||
if (mCreator)
|
||||
{
|
||||
|
|
|
@ -9,10 +9,9 @@ class QStackedLayout;
|
|||
class QStatusBar;
|
||||
class QUndoStack;
|
||||
|
||||
namespace CSMWorld
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Data;
|
||||
class UniversalId;
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
|
@ -42,8 +41,10 @@ namespace CSVWorld
|
|||
|
||||
public:
|
||||
|
||||
TableBottomBox (const CreatorFactoryBase& creatorFactory, CSMWorld::Data& data,
|
||||
QUndoStack& undoStack, const CSMWorld::UniversalId& id, QWidget *parent = 0);
|
||||
TableBottomBox (const CreatorFactoryBase& creatorFactory,
|
||||
CSMDoc::Document& document,
|
||||
const CSMWorld::UniversalId& id,
|
||||
QWidget *parent = 0);
|
||||
|
||||
virtual ~TableBottomBox();
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
|
|||
layout->setContentsMargins (QMargins (0, 0, 0, 0));
|
||||
|
||||
layout->addWidget (mBottom =
|
||||
new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this), 0);
|
||||
new TableBottomBox (creatorFactory, document, id, this), 0);
|
||||
|
||||
layout->insertWidget (0, mTable =
|
||||
new Table (id, mBottom->canCreateAndDelete(), sorting, document), 2);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -651,9 +651,6 @@ namespace MWMechanics
|
|||
if (mAllowedNodes.empty())
|
||||
return;
|
||||
|
||||
if (actor.getClass().isPureWaterCreature(actor))
|
||||
return;
|
||||
|
||||
state.moveIn(new AiWanderStorage());
|
||||
|
||||
int index = OEngine::Misc::Rng::rollDice(mAllowedNodes.size());
|
||||
|
@ -700,7 +697,8 @@ namespace MWMechanics
|
|||
// actor can wander from the spawn position. AiWander assumes that
|
||||
// pathgrid points are available, and uses them to randomly select wander
|
||||
// destinations within the allowed set of pathgrid points (nodes).
|
||||
if(mDistance)
|
||||
// ... pathgrids don't usually include water, so swimmers ignore them
|
||||
if (mDistance && !actor.getClass().isPureWaterCreature(actor))
|
||||
{
|
||||
float cellXOffset = 0;
|
||||
float cellYOffset = 0;
|
||||
|
|
|
@ -44,6 +44,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)
|
||||
{
|
||||
|
@ -51,7 +53,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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -460,7 +463,10 @@ MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& na
|
|||
return Result_NoName;
|
||||
|
||||
if (listEffects().empty())
|
||||
{
|
||||
removeIngredients();
|
||||
return Result_NoEffects;
|
||||
}
|
||||
|
||||
if (beginEffects() == endEffects())
|
||||
{
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace MWMechanics
|
|||
mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false),
|
||||
mHitRecovery(false), mBlock(false), mMovementFlags(0), mAttackStrength(0.f),
|
||||
mFallHeight(0), mRecalcMagicka(false), mLastRestock(0,0), mGoldPool(0), mActorId(-1),
|
||||
mDeathAnimation(0), mIsWerewolf(false), mLevel (0)
|
||||
mDeathAnimation(0), mLevel (0)
|
||||
{
|
||||
for (int i=0; i<4; ++i)
|
||||
mAiSettings[i] = 0;
|
||||
|
@ -55,7 +55,7 @@ namespace MWMechanics
|
|||
if (index < 0 || index > 7) {
|
||||
throw std::runtime_error("attribute index is out of range");
|
||||
}
|
||||
return (!mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index]);
|
||||
return mAttributes[index];
|
||||
}
|
||||
|
||||
const DynamicStat<float> &CreatureStats::getHealth() const
|
||||
|
@ -139,14 +139,11 @@ namespace MWMechanics
|
|||
throw std::runtime_error("attribute index is out of range");
|
||||
}
|
||||
|
||||
const AttributeValue& currentValue = !mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index];
|
||||
const AttributeValue& currentValue = mAttributes[index];
|
||||
|
||||
if (value != currentValue)
|
||||
{
|
||||
if(!mIsWerewolf)
|
||||
mAttributes[index] = value;
|
||||
else
|
||||
mWerewolfAttributes[index] = value;
|
||||
mAttributes[index] = value;
|
||||
|
||||
if (index == ESM::Attribute::Intelligence)
|
||||
mRecalcMagicka = true;
|
||||
|
|
|
@ -77,10 +77,6 @@ namespace MWMechanics
|
|||
std::vector<int> mSummonGraveyard;
|
||||
|
||||
protected:
|
||||
// These two are only set by NpcStats, but they are declared in CreatureStats to prevent using virtual methods.
|
||||
bool mIsWerewolf;
|
||||
AttributeValue mWerewolfAttributes[8];
|
||||
|
||||
int mLevel;
|
||||
|
||||
public:
|
||||
|
|
|
@ -32,6 +32,7 @@ MWMechanics::NpcStats::NpcStats()
|
|||
, mWerewolfKills (0)
|
||||
, mLevelProgress(0)
|
||||
, mTimeToStartDrowning(20.0)
|
||||
, mIsWerewolf(false)
|
||||
{
|
||||
mSkillIncreases.resize (ESM::Attribute::Length, 0);
|
||||
}
|
||||
|
@ -51,7 +52,7 @@ const MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index) const
|
|||
if (index<0 || index>=ESM::Skill::Length)
|
||||
throw std::runtime_error ("skill index out of range");
|
||||
|
||||
return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]);
|
||||
return mSkill[index];
|
||||
}
|
||||
|
||||
MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index)
|
||||
|
@ -59,7 +60,15 @@ MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index)
|
|||
if (index<0 || index>=ESM::Skill::Length)
|
||||
throw std::runtime_error ("skill index out of range");
|
||||
|
||||
return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]);
|
||||
return mSkill[index];
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::setSkill(int index, const MWMechanics::SkillValue &value)
|
||||
{
|
||||
if (index<0 || index>=ESM::Skill::Length)
|
||||
throw std::runtime_error ("skill index out of range");
|
||||
|
||||
mSkill[index] = value;
|
||||
}
|
||||
|
||||
const std::map<std::string, int>& MWMechanics::NpcStats::getFactionRanks() const
|
||||
|
@ -188,10 +197,6 @@ float MWMechanics::NpcStats::getSkillProgressRequirement (int skillIndex, const
|
|||
|
||||
void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType, float extraFactor)
|
||||
{
|
||||
// Don't increase skills as a werewolf
|
||||
if(mIsWerewolf)
|
||||
return;
|
||||
|
||||
const ESM::Skill *skill =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>().find (skillIndex);
|
||||
float skillGain = 1;
|
||||
|
@ -403,34 +408,12 @@ bool MWMechanics::NpcStats::isWerewolf() const
|
|||
|
||||
void MWMechanics::NpcStats::setWerewolf (bool set)
|
||||
{
|
||||
if (mIsWerewolf == set)
|
||||
return;
|
||||
|
||||
if(set != false)
|
||||
{
|
||||
const MWWorld::Store<ESM::GameSetting> &gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
||||
mWerewolfKills = 0;
|
||||
|
||||
for(size_t i = 0;i < ESM::Attribute::Length;i++)
|
||||
{
|
||||
mWerewolfAttributes[i] = getAttribute(i);
|
||||
// Oh, Bethesda. It's "Intelligence".
|
||||
std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") :
|
||||
ESM::Attribute::sAttributeNames[i]);
|
||||
mWerewolfAttributes[i].setBase(int(gmst.find(name)->getFloat()));
|
||||
}
|
||||
|
||||
for(size_t i = 0;i < ESM::Skill::Length;i++)
|
||||
{
|
||||
mWerewolfSkill[i] = getSkill(i);
|
||||
|
||||
// Acrobatics is set separately for some reason.
|
||||
if(i == ESM::Skill::Acrobatics)
|
||||
continue;
|
||||
|
||||
// "Mercantile"! >_<
|
||||
std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") :
|
||||
ESM::Skill::sSkillNames[i]);
|
||||
mWerewolfSkill[i].setBase(int(gmst.find(name)->getFloat()));
|
||||
}
|
||||
}
|
||||
mIsWerewolf = set;
|
||||
}
|
||||
|
@ -464,14 +447,8 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const
|
|||
state.mDisposition = mDisposition;
|
||||
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
{
|
||||
mSkill[i].writeState (state.mSkills[i].mRegular);
|
||||
mWerewolfSkill[i].writeState (state.mSkills[i].mWerewolf);
|
||||
}
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
{
|
||||
mWerewolfAttributes[i].writeState (state.mWerewolfAttributes[i]);
|
||||
}
|
||||
mSkill[i].writeState (state.mSkills[i]);
|
||||
|
||||
state.mIsWerewolf = mIsWerewolf;
|
||||
|
||||
state.mCrimeId = mCrimeId;
|
||||
|
@ -519,14 +496,7 @@ void MWMechanics::NpcStats::readState (const ESM::NpcStats& state)
|
|||
mDisposition = state.mDisposition;
|
||||
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
{
|
||||
mSkill[i].readState (state.mSkills[i].mRegular);
|
||||
mWerewolfSkill[i].readState (state.mSkills[i].mWerewolf);
|
||||
}
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
{
|
||||
mWerewolfAttributes[i].readState (state.mWerewolfAttributes[i]);
|
||||
}
|
||||
mSkill[i].readState (state.mSkills[i]);
|
||||
|
||||
mIsWerewolf = state.mIsWerewolf;
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace MWMechanics
|
|||
{
|
||||
int mDisposition;
|
||||
SkillValue mSkill[ESM::Skill::Length]; // SkillValue.mProgress used by the player only
|
||||
SkillValue mWerewolfSkill[ESM::Skill::Length];
|
||||
|
||||
int mReputation;
|
||||
int mCrimeId;
|
||||
|
||||
|
@ -41,6 +41,8 @@ namespace MWMechanics
|
|||
/// Countdown to getting damage while underwater
|
||||
float mTimeToStartDrowning;
|
||||
|
||||
bool mIsWerewolf;
|
||||
|
||||
public:
|
||||
|
||||
NpcStats();
|
||||
|
@ -56,6 +58,7 @@ namespace MWMechanics
|
|||
|
||||
const SkillValue& getSkill (int index) const;
|
||||
SkillValue& getSkill (int index);
|
||||
void setSkill(int index, const SkillValue& value);
|
||||
|
||||
const std::map<std::string, int>& getFactionRanks() const;
|
||||
/// Increase the rank in this faction by 1, if such a rank exists.
|
||||
|
|
|
@ -49,6 +49,55 @@ namespace MWWorld
|
|||
mPlayer.mData.setPosition(playerPos);
|
||||
}
|
||||
|
||||
void Player::saveSkillsAttributes()
|
||||
{
|
||||
MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer());
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
mSaveSkills[i] = stats.getSkill(i);
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
mSaveAttributes[i] = stats.getAttribute(i);
|
||||
}
|
||||
|
||||
void Player::restoreSkillsAttributes()
|
||||
{
|
||||
MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer());
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
stats.setSkill(i, mSaveSkills[i]);
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
stats.setAttribute(i, mSaveAttributes[i]);
|
||||
}
|
||||
|
||||
void Player::setWerewolfSkillsAttributes()
|
||||
{
|
||||
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer());
|
||||
for(size_t i = 0;i < ESM::Attribute::Length;++i)
|
||||
{
|
||||
// Oh, Bethesda. It's "Intelligence".
|
||||
std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") :
|
||||
ESM::Attribute::sAttributeNames[i]);
|
||||
|
||||
MWMechanics::AttributeValue value = stats.getAttribute(i);
|
||||
value.setBase(int(gmst.find(name)->getFloat()));
|
||||
stats.setAttribute(i, value);
|
||||
}
|
||||
|
||||
for(size_t i = 0;i < ESM::Skill::Length;i++)
|
||||
{
|
||||
// Acrobatics is set separately for some reason.
|
||||
if(i == ESM::Skill::Acrobatics)
|
||||
continue;
|
||||
|
||||
// "Mercantile"! >_<
|
||||
std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") :
|
||||
ESM::Skill::sSkillNames[i]);
|
||||
|
||||
MWMechanics::SkillValue value = stats.getSkill(i);
|
||||
value.setBase(int(gmst.find(name)->getFloat()));
|
||||
stats.setSkill(i, value);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::set(const ESM::NPC *player)
|
||||
{
|
||||
mPlayer.mBase = player;
|
||||
|
@ -222,6 +271,11 @@ namespace MWWorld
|
|||
|
||||
player.mAutoMove = mAutoMove ? 1 : 0;
|
||||
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
mSaveAttributes[i].writeState(player.mSaveAttributes[i]);
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
mSaveSkills[i].writeState(player.mSaveSkills[i]);
|
||||
|
||||
writer.startRecord (ESM::REC_PLAY);
|
||||
player.save (writer);
|
||||
writer.endRecord (ESM::REC_PLAY);
|
||||
|
@ -242,6 +296,17 @@ namespace MWWorld
|
|||
|
||||
mPlayer.load (player.mObject);
|
||||
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
mSaveAttributes[i].readState(player.mSaveAttributes[i]);
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
mSaveSkills[i].readState(player.mSaveSkills[i]);
|
||||
|
||||
if (player.mObject.mNpcStats.mWerewolfDeprecatedData && player.mObject.mNpcStats.mIsWerewolf)
|
||||
{
|
||||
saveSkillsAttributes();
|
||||
setWerewolfSkillsAttributes();
|
||||
}
|
||||
|
||||
getPlayer().getClass().getCreatureStats(getPlayer()).getAiSequence().clear();
|
||||
|
||||
MWBase::World& world = *MWBase::Environment::get().getWorld();
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
|
||||
#include "../mwmechanics/drawstate.hpp"
|
||||
|
||||
#include "../mwmechanics/stat.hpp"
|
||||
|
||||
#include <components/esm/loadskil.hpp>
|
||||
#include <components/esm/attr.hpp>
|
||||
|
||||
#include <OgreVector3.h>
|
||||
|
||||
namespace ESM
|
||||
|
@ -50,10 +55,18 @@ namespace MWWorld
|
|||
int mCurrentCrimeId; // the id assigned witnesses
|
||||
int mPaidCrimeId; // the last id paid off (0 bounty)
|
||||
|
||||
// Saved skills and attributes prior to becoming a werewolf
|
||||
MWMechanics::SkillValue mSaveSkills[ESM::Skill::Length];
|
||||
MWMechanics::AttributeValue mSaveAttributes[ESM::Attribute::Length];
|
||||
|
||||
public:
|
||||
|
||||
Player(const ESM::NPC *player, const MWBase::World& world);
|
||||
|
||||
void saveSkillsAttributes();
|
||||
void restoreSkillsAttributes();
|
||||
void setWerewolfSkillsAttributes();
|
||||
|
||||
// For mark/recall magic effects
|
||||
void markPosition (CellStore* markedCell, ESM::Position markedPosition);
|
||||
void getMarkedPosition (CellStore*& markedCell, ESM::Position& markedPosition) const;
|
||||
|
|
|
@ -2485,6 +2485,17 @@ namespace MWWorld
|
|||
if (npcStats.isWerewolf() == werewolf)
|
||||
return;
|
||||
|
||||
if (actor == getPlayerPtr())
|
||||
{
|
||||
if (werewolf)
|
||||
{
|
||||
mPlayer->saveSkillsAttributes();
|
||||
mPlayer->setWerewolfSkillsAttributes();
|
||||
}
|
||||
else
|
||||
mPlayer->restoreSkillsAttributes();
|
||||
}
|
||||
|
||||
npcStats.setWerewolf(werewolf);
|
||||
|
||||
// This is a bit dangerous. Equipped items other than WerewolfRobe may reference
|
||||
|
|
|
@ -174,6 +174,17 @@ bool ESMReader::isNextSub(const char* name)
|
|||
return !mCtx.subCached;
|
||||
}
|
||||
|
||||
bool ESMReader::peekNextSub(const char *name)
|
||||
{
|
||||
if (!mCtx.leftRec)
|
||||
return false;
|
||||
|
||||
getSubName();
|
||||
|
||||
mCtx.subCached = true;
|
||||
return mCtx.subName == name;
|
||||
}
|
||||
|
||||
// Read subrecord name. This gets called a LOT, so I've optimized it
|
||||
// slightly.
|
||||
void ESMReader::getSubName()
|
||||
|
|
|
@ -185,6 +185,8 @@ public:
|
|||
*/
|
||||
bool isNextSub(const char* name);
|
||||
|
||||
bool peekNextSub(const char* name);
|
||||
|
||||
// Read subrecord name. This gets called a LOT, so I've optimized it
|
||||
// slightly.
|
||||
void getSubName();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "npcstats.hpp"
|
||||
|
||||
#include "esmreader.hpp"
|
||||
|
@ -31,18 +30,44 @@ void ESM::NpcStats::load (ESMReader &esm)
|
|||
esm.getHNOT (mDisposition, "DISP");
|
||||
|
||||
for (int i=0; i<27; ++i)
|
||||
mSkills[i].load (esm);
|
||||
|
||||
mWerewolfDeprecatedData = false;
|
||||
if (esm.peekNextSub("STBA"))
|
||||
{
|
||||
mSkills[i].mRegular.load (esm);
|
||||
mSkills[i].mWerewolf.load (esm);
|
||||
// we have deprecated werewolf skills, stored interleaved
|
||||
// Load into one big vector, then remove every 2nd value
|
||||
mWerewolfDeprecatedData = true;
|
||||
std::vector<ESM::StatState<int> > skills(mSkills, mSkills + sizeof(mSkills)/sizeof(mSkills[0]));
|
||||
|
||||
for (int i=0; i<27; ++i)
|
||||
{
|
||||
ESM::StatState<int> skill;
|
||||
skill.load(esm);
|
||||
skills.push_back(skill);
|
||||
}
|
||||
|
||||
int i=0;
|
||||
for (std::vector<ESM::StatState<int> >::iterator it = skills.begin(); it != skills.end(); ++i)
|
||||
{
|
||||
if (i%2 == 1)
|
||||
it = skills.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
assert(skills.size() == 27);
|
||||
std::copy(skills.begin(), skills.end(), mSkills);
|
||||
}
|
||||
|
||||
// No longer used
|
||||
bool hasWerewolfAttributes = false;
|
||||
esm.getHNOT (hasWerewolfAttributes, "HWAT");
|
||||
|
||||
if (hasWerewolfAttributes)
|
||||
{
|
||||
ESM::StatState<int> dummy;
|
||||
for (int i=0; i<8; ++i)
|
||||
mWerewolfAttributes[i].load (esm);
|
||||
dummy.load(esm);
|
||||
mWerewolfDeprecatedData = true;
|
||||
}
|
||||
|
||||
mIsWerewolf = false;
|
||||
|
@ -112,14 +137,7 @@ void ESM::NpcStats::save (ESMWriter &esm) const
|
|||
esm.writeHNT ("DISP", mDisposition);
|
||||
|
||||
for (int i=0; i<27; ++i)
|
||||
{
|
||||
mSkills[i].mRegular.save (esm);
|
||||
mSkills[i].mWerewolf.save (esm);
|
||||
}
|
||||
|
||||
esm.writeHNT ("HWAT", true);
|
||||
for (int i=0; i<8; ++i)
|
||||
mWerewolfAttributes[i].save (esm);
|
||||
mSkills[i].save (esm);
|
||||
|
||||
if (mIsWerewolf)
|
||||
esm.writeHNT ("WOLF", mIsWerewolf);
|
||||
|
@ -151,6 +169,7 @@ void ESM::NpcStats::save (ESMWriter &esm) const
|
|||
|
||||
void ESM::NpcStats::blank()
|
||||
{
|
||||
mWerewolfDeprecatedData = false;
|
||||
mIsWerewolf = false;
|
||||
mDisposition = 0;
|
||||
mBounty = 0;
|
||||
|
|
|
@ -16,12 +16,6 @@ namespace ESM
|
|||
|
||||
struct NpcStats
|
||||
{
|
||||
struct Skill
|
||||
{
|
||||
StatState<int> mRegular;
|
||||
StatState<int> mWerewolf;
|
||||
};
|
||||
|
||||
struct Faction
|
||||
{
|
||||
bool mExpelled;
|
||||
|
@ -31,12 +25,13 @@ namespace ESM
|
|||
Faction();
|
||||
};
|
||||
|
||||
StatState<int> mWerewolfAttributes[8];
|
||||
bool mIsWerewolf;
|
||||
|
||||
bool mWerewolfDeprecatedData;
|
||||
|
||||
std::map<std::string, Faction> mFactions; // lower case IDs
|
||||
int mDisposition;
|
||||
Skill mSkills[27];
|
||||
StatState<int> mSkills[27];
|
||||
int mBounty;
|
||||
int mReputation;
|
||||
int mWerewolfKills;
|
||||
|
|
|
@ -31,6 +31,14 @@ void ESM::Player::load (ESMReader &esm)
|
|||
esm.getHNOT (mCurrentCrimeId, "CURD");
|
||||
mPaidCrimeId = -1;
|
||||
esm.getHNOT (mPaidCrimeId, "PAYD");
|
||||
|
||||
if (esm.hasMoreSubs())
|
||||
{
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
mSaveAttributes[i].load(esm);
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
mSaveSkills[i].load(esm);
|
||||
}
|
||||
}
|
||||
|
||||
void ESM::Player::save (ESMWriter &esm) const
|
||||
|
@ -54,4 +62,9 @@ void ESM::Player::save (ESMWriter &esm) const
|
|||
|
||||
esm.writeHNT ("CURD", mCurrentCrimeId);
|
||||
esm.writeHNT ("PAYD", mPaidCrimeId);
|
||||
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
mSaveAttributes[i].save(esm);
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
mSaveSkills[i].save(esm);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include "cellid.hpp"
|
||||
#include "defs.hpp"
|
||||
|
||||
#include "loadskil.hpp"
|
||||
#include "attr.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
|
@ -28,6 +31,9 @@ namespace ESM
|
|||
int mCurrentCrimeId;
|
||||
int mPaidCrimeId;
|
||||
|
||||
StatState<int> mSaveAttributes[ESM::Attribute::Length];
|
||||
StatState<int> mSaveSkills[ESM::Skill::Length];
|
||||
|
||||
void load (ESMReader &esm);
|
||||
void save (ESMWriter &esm) const;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue