Merge branch 'run'

Conflicts:
	apps/opencs/model/world/columns.cpp
	apps/opencs/model/world/columns.hpp
	apps/opencs/model/world/data.cpp
	components/CMakeLists.txt
deque
Marc Zinnschlag 10 years ago
commit d1d861e1be

@ -7,7 +7,7 @@ opencs_units (. editor)
set (CMAKE_BUILD_TYPE DEBUG)
opencs_units (model/doc
document operation saving documentmanager loader
document operation saving documentmanager loader runner
)
opencs_units_noqt (model/doc
@ -26,7 +26,7 @@ opencs_units (model/world
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
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
)
opencs_hdrs_noqt (model/world
@ -46,7 +46,7 @@ opencs_units_noqt (model/tools
opencs_units (view/doc
viewmanager view operations operation subview startup filedialog newgame
filewidget adjusterwidget loader
filewidget adjusterwidget loader globaldebugprofilemenu runlogsubview
)
@ -71,7 +71,7 @@ opencs_units_noqt (view/world
)
opencs_units (view/widget
scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle
scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun
)
opencs_units (view/render
@ -128,12 +128,8 @@ opencs_units_noqt (model/filter
node unarynode narynode leafnode booleannode parser andnode ornode notnode textnode valuenode
)
opencs_hdrs_noqt (model/filter
filter
)
opencs_units (view/filter
filtercreator filterbox recordfilterbox editwidget
filterbox recordfilterbox editwidget
)
set (OPENCS_US

@ -80,7 +80,7 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
boost::program_options::options_description desc("Syntax: opencs <options>\nAllowed options");
desc.add_options()
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken()->composing())
("data-local", boost::program_options::value<std::string>()->default_value(""))
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
("encoding", boost::program_options::value<std::string>()->default_value("win1252"))

@ -2212,7 +2212,8 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
mTools (*this), mResDir(resDir),
mProjectPath ((configuration.getUserDataPath() / "projects") /
(savePath.filename().string() + ".project")),
mSaving (*this, mProjectPath, encoding)
mSaving (*this, mProjectPath, encoding),
mRunner (mProjectPath)
{
if (mContentFiles.empty())
throw std::runtime_error ("Empty content file sequence");
@ -2251,14 +2252,16 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool)));
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
connect (&mTools, SIGNAL (done (int)), this, SLOT (operationDone (int)));
connect (&mTools, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
connect (&mSaving, SIGNAL (done (int)), this, SLOT (operationDone (int)));
connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
connect (
&mSaving, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)),
this, SLOT (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)));
connect (&mRunner, SIGNAL (runStateChanged()), this, SLOT (runStateChanged()));
}
CSMDoc::Document::~Document()
@ -2280,6 +2283,9 @@ int CSMDoc::Document::getState() const
if (mSaving.isRunning())
state |= State_Locked | State_Saving | State_Operation;
if (mRunner.isRunning())
state |= State_Locked | State_Running;
if (int operations = mTools.getRunningOperations())
state |= State_Locked | State_Operation | operations;
@ -2344,7 +2350,7 @@ void CSMDoc::Document::reportMessage (const CSMWorld::UniversalId& id, const std
std::cout << message << std::endl;
}
void CSMDoc::Document::operationDone (int type)
void CSMDoc::Document::operationDone (int type, bool failed)
{
emit stateChanged (getState(), this);
}
@ -2370,6 +2376,48 @@ bool CSMDoc::Document::isBlacklisted (const CSMWorld::UniversalId& id)
return mBlacklist.isBlacklisted (id);
}
void CSMDoc::Document::startRunning (const std::string& profile,
const std::string& startupInstruction)
{
std::vector<std::string> contentFiles;
for (std::vector<boost::filesystem::path>::const_iterator iter (mContentFiles.begin());
iter!=mContentFiles.end(); ++iter)
contentFiles.push_back (iter->filename().string());
mRunner.configure (getData().getDebugProfiles().getRecord (profile).get(), contentFiles,
startupInstruction);
int state = getState();
if (state & State_Modified)
{
// need to save first
mRunner.start (true);
new SaveWatcher (&mRunner, &mSaving); // no, that is not a memory leak. Qt is weird.
if (!(state & State_Saving))
save();
}
else
mRunner.start();
}
void CSMDoc::Document::stopRunning()
{
mRunner.stop();
}
QTextDocument *CSMDoc::Document::getRunLog()
{
return mRunner.getLog();
}
void CSMDoc::Document::runStateChanged()
{
emit stateChanged (getState(), this);
}
void CSMDoc::Document::progress (int current, int max, int type)
{

@ -18,6 +18,7 @@
#include "state.hpp"
#include "saving.hpp"
#include "blacklist.hpp"
#include "runner.hpp"
class QAbstractItemModel;
@ -54,6 +55,7 @@ namespace CSMDoc
Saving mSaving;
boost::filesystem::path mResDir;
Blacklist mBlacklist;
Runner mRunner;
// It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is
// using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late.
@ -115,6 +117,13 @@ namespace CSMDoc
bool isBlacklisted (const CSMWorld::UniversalId& id) const;
void startRunning (const std::string& profile,
const std::string& startupInstruction = "");
void stopRunning();
QTextDocument *getRunLog();
signals:
void stateChanged (int state, CSMDoc::Document *document);
@ -128,7 +137,9 @@ namespace CSMDoc
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
int type);
void operationDone (int type);
void operationDone (int type, bool failed);
void runStateChanged();
public slots:

@ -119,5 +119,5 @@ void CSMDoc::Operation::executeStage()
void CSMDoc::Operation::operationDone()
{
emit done (mType);
emit done (mType, mError);
}

@ -54,7 +54,7 @@ namespace CSMDoc
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
int type);
void done (int type);
void done (int type, bool failed);
public slots:

@ -0,0 +1,157 @@
#include "runner.hpp"
#include <QTemporaryFile>
#include <QTextStream>
#include "operation.hpp"
CSMDoc::Runner::Runner (const boost::filesystem::path& projectPath)
: mRunning (false), mStartup (0), mProjectPath (projectPath)
{
connect (&mProcess, SIGNAL (finished (int, QProcess::ExitStatus)),
this, SLOT (finished (int, QProcess::ExitStatus)));
connect (&mProcess, SIGNAL (readyReadStandardOutput()),
this, SLOT (readyReadStandardOutput()));
mProcess.setProcessChannelMode (QProcess::MergedChannels);
mProfile.blank();
}
CSMDoc::Runner::~Runner()
{
if (mRunning)
{
disconnect (&mProcess, 0, this, 0);
mProcess.kill();
mProcess.waitForFinished();
}
}
void CSMDoc::Runner::start (bool delayed)
{
if (mStartup)
{
delete mStartup;
mStartup = 0;
}
if (!delayed)
{
mLog.clear();
QString path = "openmw";
#ifdef Q_OS_WIN
path.append(QString(".exe"));
#elif defined(Q_OS_MAC)
QDir dir(QCoreApplication::applicationDirPath());
path = dir.absoluteFilePath(name);
#else
path.prepend(QString("./"));
#endif
mStartup = new QTemporaryFile (this);
mStartup->open();
{
QTextStream stream (mStartup);
if (!mStartupInstruction.empty())
stream << QString::fromUtf8 (mStartupInstruction.c_str()) << '\n';
stream << QString::fromUtf8 (mProfile.mScriptText.c_str());
}
mStartup->close();
QStringList arguments;
arguments << "--skip-menu";
if (mProfile.mFlags & ESM::DebugProfile::Flag_BypassNewGame)
arguments << "--new-game=0";
else
arguments << "--new-game=1";
arguments << ("--script-run="+mStartup->fileName());;
arguments <<
QString::fromUtf8 (("--data="+mProjectPath.parent_path().string()).c_str());
for (std::vector<std::string>::const_iterator iter (mContentFiles.begin());
iter!=mContentFiles.end(); ++iter)
{
arguments << QString::fromUtf8 (("--content="+*iter).c_str());
}
arguments
<< QString::fromUtf8 (("--content="+mProjectPath.filename().string()).c_str());
mProcess.start (path, arguments);
}
mRunning = true;
emit runStateChanged();
}
void CSMDoc::Runner::stop()
{
delete mStartup;
mStartup = 0;
if (mProcess.state()==QProcess::NotRunning)
{
mRunning = false;
emit runStateChanged();
}
else
mProcess.kill();
}
bool CSMDoc::Runner::isRunning() const
{
return mRunning;
}
void CSMDoc::Runner::configure (const ESM::DebugProfile& profile,
const std::vector<std::string>& contentFiles, const std::string& startupInstruction)
{
mProfile = profile;
mContentFiles = contentFiles;
mStartupInstruction = startupInstruction;
}
void CSMDoc::Runner::finished (int exitCode, QProcess::ExitStatus exitStatus)
{
mRunning = false;
emit runStateChanged();
}
QTextDocument *CSMDoc::Runner::getLog()
{
return &mLog;
}
void CSMDoc::Runner::readyReadStandardOutput()
{
mLog.setPlainText (
mLog.toPlainText() + QString::fromUtf8 (mProcess.readAllStandardOutput()));
}
CSMDoc::SaveWatcher::SaveWatcher (Runner *runner, Operation *operation)
: QObject (runner), mRunner (runner)
{
connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool)));
}
void CSMDoc::SaveWatcher::saveDone (int type, bool failed)
{
if (failed)
mRunner->stop();
else
mRunner->start();
deleteLater();
}

@ -0,0 +1,85 @@
#ifndef CSM_DOC_RUNNER_H
#define CSM_DOC_RUNNER_H
#include <vector>
#include <string>
#include <boost/filesystem/path.hpp>
#include <QObject>
#include <QProcess>
#include <QTextDocument>
#include <components/esm/debugprofile.hpp>
class QTemporaryFile;
namespace CSMDoc
{
class Runner : public QObject
{
Q_OBJECT
QProcess mProcess;
bool mRunning;
ESM::DebugProfile mProfile;
std::vector<std::string> mContentFiles;
std::string mStartupInstruction;
QTemporaryFile *mStartup;
QTextDocument mLog;
boost::filesystem::path mProjectPath;
public:
Runner (const boost::filesystem::path& projectPath);
~Runner();
/// \param delayed Flag as running but do not start the OpenMW process yet (the
/// process must be started by another call of start with delayed==false)
void start (bool delayed = false);
void stop();
/// \note Running state is entered when the start function is called. This
/// is not necessarily identical to the moment the child process is started.
bool isRunning() const;
void configure (const ESM::DebugProfile& profile,
const std::vector<std::string>& contentFiles,
const std::string& startupInstruction);
QTextDocument *getLog();
signals:
void runStateChanged();
private slots:
void finished (int exitCode, QProcess::ExitStatus exitStatus);
void readyReadStandardOutput();
};
class Operation;
/// \brief Watch for end of save operation and restart or stop runner
class SaveWatcher : public QObject
{
Q_OBJECT
Runner *mRunner;
public:
/// *this attaches itself to runner
SaveWatcher (Runner *runner, Operation *operation);
private slots:
void saveDone (int type, bool failed);
};
}
#endif

@ -17,7 +17,14 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
appendStage (new WriteHeaderStage (mDocument, mState, true));
appendStage (new WriteFilterStage (mDocument, mState, CSMFilter::Filter::Scope_Project));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Filter> > (
mDocument.getData().getFilters(), mState, CSMWorld::Scope_Project));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::DebugProfile> > (
mDocument.getData().getDebugProfiles(), mState, CSMWorld::Scope_Project));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Script> > (
mDocument.getData().getScripts(), mState, CSMWorld::Scope_Project));
appendStage (new CloseSaveStage (mState));

@ -201,23 +201,6 @@ void CSMDoc::WriteRefIdCollectionStage::perform (int stage, Messages& messages)
}
CSMDoc::WriteFilterStage::WriteFilterStage (Document& document, SavingState& state,
CSMFilter::Filter::Scope scope)
: WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> > (document.getData().getFilters(),
state),
mDocument (document), mScope (scope)
{}
void CSMDoc::WriteFilterStage::perform (int stage, Messages& messages)
{
const CSMWorld::Record<CSMFilter::Filter>& record =
mDocument.getData().getFilters().getRecord (stage);
if (record.get().mScope==mScope)
WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> >::perform (stage, messages);
}
CSMDoc::CollectionReferencesStage::CollectionReferencesStage (Document& document,
SavingState& state)
: mDocument (document), mState (state)

@ -5,8 +5,7 @@
#include "../world/record.hpp"
#include "../world/idcollection.hpp"
#include "../filter/filter.hpp"
#include "../world/scope.hpp"
#include "savingstate.hpp"
@ -67,10 +66,12 @@ namespace CSMDoc
{
const CollectionT& mCollection;
SavingState& mState;
CSMWorld::Scope mScope;
public:
WriteCollectionStage (const CollectionT& collection, SavingState& state);
WriteCollectionStage (const CollectionT& collection, SavingState& state,
CSMWorld::Scope scope = CSMWorld::Scope_Content);
virtual int setup();
///< \return number of steps
@ -81,8 +82,8 @@ namespace CSMDoc
template<class CollectionT>
WriteCollectionStage<CollectionT>::WriteCollectionStage (const CollectionT& collection,
SavingState& state)
: mCollection (collection), mState (state)
SavingState& state, CSMWorld::Scope scope)
: mCollection (collection), mState (state), mScope (scope)
{}
template<class CollectionT>
@ -94,6 +95,9 @@ namespace CSMDoc
template<class CollectionT>
void WriteCollectionStage<CollectionT>::perform (int stage, Messages& messages)
{
if (CSMWorld::getScopeFromId (mCollection.getRecord (stage).get().mId)!=mScope)
return;
CSMWorld::RecordBase::State state = mCollection.getRecord (stage).mState;
if (state==CSMWorld::RecordBase::State_Modified ||
@ -152,20 +156,6 @@ namespace CSMDoc
};
class WriteFilterStage : public WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> >
{
Document& mDocument;
CSMFilter::Filter::Scope mScope;
public:
WriteFilterStage (Document& document, SavingState& state, CSMFilter::Filter::Scope scope);
virtual void perform (int stage, Messages& messages);
///< Messages resulting from this stage will be appended to \a messages.
};
class CollectionReferencesStage : public Stage
{
Document& mDocument;

@ -8,12 +8,13 @@ namespace CSMDoc
State_Modified = 1,
State_Locked = 2,
State_Operation = 4,
State_Running = 8,
State_Saving = 8,
State_Verifying = 16,
State_Compiling = 32, // not implemented yet
State_Searching = 64, // not implemented yet
State_Loading = 128 // pseudo-state; can not be encountered in a loaded document
State_Saving = 16,
State_Verifying = 32,
State_Compiling = 64, // not implemented yet
State_Searching = 128, // not implemented yet
State_Loading = 256 // pseudo-state; can not be encountered in a loaded document
};
}

@ -1,25 +0,0 @@
#ifndef CSM_FILTER_FILTER_H
#define CSM_FILTER_FILTER_H
#include <vector>
#include <string>
#include <components/esm/filter.hpp>
namespace CSMFilter
{
/// \brief Wrapper for Filter record
struct Filter : public ESM::Filter
{
enum Scope
{
Scope_Project = 0, // per project
Scope_Session = 1, // exists only for one editing session; not saved
Scope_Content = 2 // embedded in the edited content file
};
Scope mScope;
};
}
#endif

@ -596,7 +596,7 @@ bool CSMFilter::Parser::parse (const std::string& filter, bool allowPredefined)
return false;
}
const CSMWorld::Record<CSMFilter::Filter>& record = mData.getFilters().getRecord (index);
const CSMWorld::Record<ESM::Filter>& record = mData.getFilters().getRecord (index);
if (record.isDeleted())
{

@ -46,7 +46,7 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
mVerifier = new CSMDoc::Operation (CSMDoc::State_Verifying, false);
connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
connect (mVerifier, SIGNAL (done (int)), this, SIGNAL (done (int)));
connect (mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
connect (mVerifier,
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)),
this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, int)));

@ -70,7 +70,7 @@ namespace CSMTools
void progress (int current, int max, int type);
void done (int type);
void done (int type, bool failed);
};
}

@ -100,7 +100,8 @@ namespace CSMWorld
Display_SoundRes,
Display_Texture,
Display_Video,
Display_Colour
Display_Colour,
Display_ScriptLines // console context
};
int mColumnId;

@ -500,6 +500,47 @@ namespace CSMWorld
}
};
template<typename ESXRecordT>
struct FlagColumn2 : public Column<ESXRecordT>
{
int mMask;
bool mInverted;
FlagColumn2 (int columnId, int mask, bool inverted = false)
: Column<ESXRecordT> (columnId, ColumnBase::Display_Boolean), mMask (mask),
mInverted (inverted)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
bool flag = (record.get().mFlags & mMask)!=0;
if (mInverted)
flag = !flag;
return flag;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
int flags = record2.mFlags & ~mMask;
if ((data.toInt()!=0)!=mInverted)
flags |= mMask;
record2.mFlags = flags;
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct WeightHeightColumn : public Column<ESXRecordT>
{
@ -766,8 +807,18 @@ namespace CSMWorld
template<typename ESXRecordT>
struct ScriptColumn : public Column<ESXRecordT>
{
ScriptColumn()
: Column<ESXRecordT> (Columns::ColumnId_ScriptText, ColumnBase::Display_Script, 0) {}
enum Type
{
Type_File, // regular script record
Type_Lines, // console context
Type_Info // dialogue context (not implemented yet)
};
ScriptColumn (Type type)
: Column<ESXRecordT> (Columns::ColumnId_ScriptText,
type==Type_File ? ColumnBase::Display_Script : ColumnBase::Display_ScriptLines,
type==Type_File ? 0 : ColumnBase::Flag_Dialogue)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
@ -1224,36 +1275,6 @@ namespace CSMWorld
}
};
template<typename ESXRecordT>
struct ScopeColumn : public Column<ESXRecordT>
{
ScopeColumn()
: Column<ESXRecordT> (Columns::ColumnId_Scope, ColumnBase::Display_Integer, 0)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mScope);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mScope = static_cast<CSMFilter::Filter::Scope> (data.toInt());
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
virtual bool isUserEditable() const
{
return false;
}
};
template<typename ESXRecordT>
struct PosColumn : public Column<ESXRecordT>

@ -172,7 +172,6 @@ namespace CSMWorld
{ ColumnId_Rank, "Rank" },
{ ColumnId_Gender, "Gender" },
{ ColumnId_PcRank, "PC Rank" },
{ ColumnId_Scope, "Scope" },
{ ColumnId_ReferenceableId, "Referenceable ID" },
{ ColumnId_CombatState, "Combat" },
{ ColumnId_MagicState, "Magic" },
@ -182,6 +181,9 @@ namespace CSMWorld
{ ColumnId_BodyPartType, "Bodypart Type" },
{ ColumnId_MeshType, "Mesh Type" },
{ ColumnId_OwnerGlobal, "Owner Global" },
{ ColumnId_DefaultProfile, "Default Profile" },
{ ColumnId_BypassNewGame, "Bypass New Game" },
{ ColumnId_GlobalProfile, "Global Profile" },
{ ColumnId_UseValue1, "Use value 1" },
{ ColumnId_UseValue2, "Use value 2" },

@ -165,7 +165,6 @@ namespace CSMWorld
ColumnId_Rank = 152,
ColumnId_Gender = 153,
ColumnId_PcRank = 154,
ColumnId_Scope = 155,
ColumnId_ReferenceableId = 156,
ColumnId_CombatState = 157,
ColumnId_MagicState = 158,
@ -175,6 +174,9 @@ namespace CSMWorld
ColumnId_BodyPartType = 162,
ColumnId_MeshType = 163,
ColumnId_OwnerGlobal = 164,
ColumnId_DefaultProfile = 165,
ColumnId_BypassNewGame = 166,
ColumnId_GlobalProfile = 167,
// Allocated to a separate value range, so we don't get a collision should we ever need
// to extend the number of use values.

@ -131,7 +131,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mScripts.addColumn (new StringIdColumn<ESM::Script>);
mScripts.addColumn (new RecordStateColumn<ESM::Script>);
mScripts.addColumn (new FixedRecordTypeColumn<ESM::Script> (UniversalId::Type_Script));
mScripts.addColumn (new ScriptColumn<ESM::Script>);
mScripts.addColumn (new ScriptColumn<ESM::Script> (ScriptColumn<ESM::Script>::Type_File));
mRegions.addColumn (new StringIdColumn<ESM::Region>);
mRegions.addColumn (new RecordStateColumn<ESM::Region>);
@ -252,12 +252,24 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mRefs.addColumn (new TrapColumn<CellRef>);
mRefs.addColumn (new OwnerGlobalColumn<CellRef>);
mFilters.addColumn (new StringIdColumn<CSMFilter::Filter>);
mFilters.addColumn (new RecordStateColumn<CSMFilter::Filter>);
mFilters.addColumn (new FixedRecordTypeColumn<CSMFilter::Filter> (UniversalId::Type_Filter));
mFilters.addColumn (new FilterColumn<CSMFilter::Filter>);
mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>);
mFilters.addColumn (new ScopeColumn<CSMFilter::Filter>);
mFilters.addColumn (new StringIdColumn<ESM::Filter>);
mFilters.addColumn (new RecordStateColumn<ESM::Filter>);
mFilters.addColumn (new FixedRecordTypeColumn<ESM::Filter> (UniversalId::Type_Filter));
mFilters.addColumn (new FilterColumn<ESM::Filter>);
mFilters.addColumn (new DescriptionColumn<ESM::Filter>);
mDebugProfiles.addColumn (new StringIdColumn<ESM::DebugProfile>);
mDebugProfiles.addColumn (new RecordStateColumn<ESM::DebugProfile>);
mDebugProfiles.addColumn (new FixedRecordTypeColumn<ESM::DebugProfile> (UniversalId::Type_DebugProfile));
mDebugProfiles.addColumn (new FlagColumn2<ESM::DebugProfile> (
Columns::ColumnId_DefaultProfile, ESM::DebugProfile::Flag_Default));
mDebugProfiles.addColumn (new FlagColumn2<ESM::DebugProfile> (
Columns::ColumnId_BypassNewGame, ESM::DebugProfile::Flag_BypassNewGame));
mDebugProfiles.addColumn (new FlagColumn2<ESM::DebugProfile> (
Columns::ColumnId_GlobalProfile, ESM::DebugProfile::Flag_Global));
mDebugProfiles.addColumn (new DescriptionColumn<ESM::DebugProfile>);
mDebugProfiles.addColumn (new ScriptColumn<ESM::DebugProfile> (
ScriptColumn<ESM::DebugProfile>::Type_Lines));
addModel (new IdTable (&mGlobals), UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst);
@ -281,6 +293,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference);
addModel (new IdTable (&mFilters), UniversalId::Type_Filter);
addModel (new IdTable (&mDebugProfiles), UniversalId::Type_DebugProfile);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Meshes)),
UniversalId::Type_Mesh);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Icons)),
@ -484,12 +497,12 @@ CSMWorld::RefCollection& CSMWorld::Data::getReferences()
return mRefs;
}
const CSMWorld::IdCollection<CSMFilter::Filter>& CSMWorld::Data::getFilters() const
const CSMWorld::IdCollection<ESM::Filter>& CSMWorld::Data::getFilters() const
{
return mFilters;
}
CSMWorld::IdCollection<CSMFilter::Filter>& CSMWorld::Data::getFilters()
CSMWorld::IdCollection<ESM::Filter>& CSMWorld::Data::getFilters()
{
return mFilters;
}
@ -514,6 +527,16 @@ CSMWorld::IdCollection<ESM::BodyPart>& CSMWorld::Data::getBodyParts()
return mBodyParts;
}
const CSMWorld::IdCollection<ESM::DebugProfile>& CSMWorld::Data::getDebugProfiles() const
{
return mDebugProfiles;
}
CSMWorld::IdCollection<ESM::DebugProfile>& CSMWorld::Data::getDebugProfiles()
{
return mDebugProfiles;
}
const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const
{
return mResourcesManager.get (id.getType());
@ -583,6 +606,8 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages)
ESM::NAME n = mReader->getRecName();
mReader->getRecHeader();
bool unhandledRecord = false;
switch (n.val)
{
case ESM::REC_GLOB: mGlobals.load (*mReader, mBase); break;
@ -693,23 +718,37 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages)
case ESM::REC_FILT:
if (mProject)
if (!mProject)
{
unhandledRecord = true;
break;
}
mFilters.load (*mReader, mBase);
break;
case ESM::REC_DBGP:
if (!mProject)
{
mFilters.load (*mReader, mBase);
mFilters.setData (mFilters.getSize()-1,
mFilters.findColumnIndex (CSMWorld::Columns::ColumnId_Scope),
static_cast<int> (CSMFilter::Filter::Scope_Project));
unhandledRecord = true;
break;
}
// fall through (filter record in a content file is an error with format 0)
mDebugProfiles.load (*mReader, mBase);
break;
default:
messages.push_back (std::make_pair (UniversalId::Type_None,
"Unsupported record type: " + n.toString()));
unhandledRecord = true;
}
if (unhandledRecord)
{
messages.push_back (std::make_pair (UniversalId::Type_None,
"Unsupported record type: " + n.toString()));
mReader->skipRecord();
mReader->skipRecord();
}
return false;

@ -23,11 +23,11 @@
#include <components/esm/loaddial.hpp>
#include <components/esm/loadench.hpp>
#include <components/esm/loadbody.hpp>
#include <components/esm/debugprofile.hpp>
#include <components/esm/filter.hpp>
#include <components/to_utf8/to_utf8.hpp>
#include "../filter/filter.hpp"
#include "../doc/stage.hpp"
#include "idcollection.hpp"
@ -70,12 +70,13 @@ namespace CSMWorld
IdCollection<ESM::Dialogue> mJournals;
IdCollection<ESM::Enchantment> mEnchantments;
IdCollection<ESM::BodyPart> mBodyParts;
IdCollection<ESM::DebugProfile> mDebugProfiles;
InfoCollection mTopicInfos;
InfoCollection mJournalInfos;
IdCollection<Cell> mCells;
RefIdCollection mReferenceables;
RefCollection mRefs;
IdCollection<CSMFilter::Filter> mFilters;
IdCollection<ESM::Filter> mFilters;
const ResourcesManager& mResourcesManager;
std::vector<QAbstractItemModel *> mModels;
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
@ -178,9 +179,9 @@ namespace CSMWorld
RefCollection& getReferences();
const IdCollection<CSMFilter::Filter>& getFilters() const;
const IdCollection<ESM::Filter>& getFilters() const;
IdCollection<CSMFilter::Filter>& getFilters();
IdCollection<ESM::Filter>& getFilters();
const IdCollection<ESM::Enchantment>& getEnchantments() const;
@ -190,6 +191,10 @@ namespace CSMWorld
IdCollection<ESM::BodyPart>& getBodyParts();
const IdCollection<ESM::DebugProfile>& getDebugProfiles() const;
IdCollection<ESM::DebugProfile>& getDebugProfiles();
/// Throws an exception, if \a id does not match a resources list.
const Resources& getResources (const UniversalId& id) const;

@ -0,0 +1,25 @@
#include "scope.hpp"
#include <stdexcept>
#include <components/misc/stringops.hpp>
CSMWorld::Scope CSMWorld::getScopeFromId (const std::string& id)
{
// get root namespace
std::string namespace_;
std::string::size_type i = id.find ("::");
if (i!=std::string::npos)
namespace_ = Misc::StringUtils::lowerCase (id.substr (0, i));
if (namespace_=="project")
return Scope_Project;
if (namespace_=="session")
return Scope_Session;
return Scope_Content;
}

@ -0,0 +1,23 @@
#ifndef CSM_WOLRD_SCOPE_H
#define CSM_WOLRD_SCOPE_H
#include <string>
namespace CSMWorld
{
enum Scope
{
// record stored in content file
Scope_Content = 1,
// record stored in project file
Scope_Project = 2,
// record that exists only for the duration of one editing session
Scope_Session = 4
};
Scope getScopeFromId (const std::string& id);
}
#endif

@ -50,6 +50,8 @@ namespace
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sound Files", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_DebugProfiles, "Debug Profiles", 0 },
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run Log", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};
@ -109,6 +111,7 @@ namespace
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_SoundRes, "Sound File", 0 },
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Texture, "Texture", 0 },
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Video, "Video", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_DebugProfile, "Debug Profile", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};

@ -119,10 +119,13 @@ namespace CSMWorld
Type_Textures,
Type_Texture,
Type_Videos,
Type_Video
Type_Video,
Type_DebugProfiles,
Type_DebugProfile,
Type_RunLog
};
enum { NumberOfTypes = Type_BodyPart+1 };
enum { NumberOfTypes = Type_DebugProfile+1 };
private:

@ -0,0 +1,93 @@
#include "globaldebugprofilemenu.hpp"
#include <vector>
#include <algorithm>
#include <QActionGroup>
#include "../../model/world/idtable.hpp"
#include "../../model/world/record.hpp"
void CSVDoc::GlobalDebugProfileMenu::rebuild()
{
clear();
delete mActions;
mActions = 0;
int idColumn = mDebugProfiles->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
int stateColumn = mDebugProfiles->findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
int globalColumn = mDebugProfiles->findColumnIndex (
CSMWorld::Columns::ColumnId_GlobalProfile);
int size = mDebugProfiles->rowCount();
std::vector<QString> ids;
for (int i=0; i<size; ++i)
{
int state = mDebugProfiles->data (mDebugProfiles->index (i, stateColumn)).toInt();
bool global = mDebugProfiles->data (mDebugProfiles->index (i, globalColumn)).toInt();
if (state!=CSMWorld::RecordBase::State_Deleted && global)
ids.push_back (
mDebugProfiles->data (mDebugProfiles->index (i, idColumn)).toString());
}
mActions = new QActionGroup (this);
connect (mActions, SIGNAL (triggered (QAction *)), this, SLOT (actionTriggered (QAction *)));
std::sort (ids.begin(), ids.end());
for (std::vector<QString>::const_iterator iter (ids.begin()); iter!=ids.end(); ++iter)
{
mActions->addAction (addAction (*iter));
}
}
CSVDoc::GlobalDebugProfileMenu::GlobalDebugProfileMenu (CSMWorld::IdTable *debugProfiles,
QWidget *parent)
: QMenu (parent), mDebugProfiles (debugProfiles), mActions (0)
{
rebuild();
connect (mDebugProfiles, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (profileAboutToBeRemoved (const QModelIndex&, int, int)));
connect (mDebugProfiles, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (profileInserted (const QModelIndex&, int, int)));
connect (mDebugProfiles, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
this, SLOT (profileChanged (const QModelIndex&, const QModelIndex&)));
}
void CSVDoc::GlobalDebugProfileMenu::updateActions (bool running)
{
if (mActions)
mActions->setEnabled (!running);
}
void CSVDoc::GlobalDebugProfileMenu::profileAboutToBeRemoved (const QModelIndex& parent,
int start, int end)
{
rebuild();
}
void CSVDoc::GlobalDebugProfileMenu::profileInserted (const QModelIndex& parent, int start,
int end)
{
rebuild();
}
void CSVDoc::GlobalDebugProfileMenu::profileChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{
rebuild();
}
void CSVDoc::GlobalDebugProfileMenu::actionTriggered (QAction *action)
{
emit triggered (std::string (action->text().toUtf8().constData()));
}

@ -0,0 +1,49 @@
#ifndef CSV_DOC_GLOBALDEBUGPROFILEMENU_H
#define CSV_DOC_GLOBALDEBUGPROFILEMENU_H
#include <QMenu>
class QModelIndex;
class QActionGroup;
namespace CSMWorld
{
class IdTable;
}
namespace CSVDoc
{
class GlobalDebugProfileMenu : public QMenu
{
Q_OBJECT
CSMWorld::IdTable *mDebugProfiles;
QActionGroup *mActions;
private:
void rebuild();
public:
GlobalDebugProfileMenu (CSMWorld::IdTable *debugProfiles, QWidget *parent = 0);
void updateActions (bool running);
private slots:
void profileAboutToBeRemoved (const QModelIndex& parent, int start, int end);
void profileInserted (const QModelIndex& parent, int start, int end);
void profileChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void actionTriggered (QAction *action);
signals:
void triggered (const std::string& profile);
};
}
#endif

@ -0,0 +1,20 @@
#include "runlogsubview.hpp"
#include <QTextEdit>
CSVDoc::RunLogSubView::RunLogSubView (const CSMWorld::UniversalId& id,
CSMDoc::Document& document)
: SubView (id)
{
QTextEdit *edit = new QTextEdit (this);
edit->setDocument (document.getRunLog());
edit->setReadOnly (true);
setWidget (edit);
}
void CSVDoc::RunLogSubView::setEditLock (bool locked)
{
// ignored since this SubView does not have editing
}

@ -0,0 +1,20 @@
#ifndef CSV_DOC_RUNLOGSUBVIEW_H
#define CSV_DOC_RUNLOGSUBVIEW_H
#include "subview.hpp"
namespace CSVDoc
{
class RunLogSubView : public SubView
{
Q_OBJECT
public:
RunLogSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document);
virtual void setEditLock (bool locked);
};
}
#endif

@ -12,6 +12,8 @@
#include "../../model/doc/document.hpp"
#include "../../model/settings/usersettings.hpp"
#include "../../model/world/idtable.hpp"
#include "../world/subviews.hpp"
#include "../tools/subviews.hpp"
@ -19,6 +21,9 @@
#include "viewmanager.hpp"
#include "operations.hpp"
#include "subview.hpp"
#include "globaldebugprofilemenu.hpp"
#include "runlogsubview.hpp"
#include "subviewfactoryimp.hpp"
void CSVDoc::View::closeEvent (QCloseEvent *event)
{
@ -232,6 +237,35 @@ void CSVDoc::View::setupAssetsMenu()
assets->addAction (videos);
}
void CSVDoc::View::setupDebugMenu()
{
QMenu *debug = menuBar()->addMenu (tr ("Debug"));
QAction *profiles = new QAction (tr ("Debug Profiles"), this);
connect (profiles, SIGNAL (triggered()), this, SLOT (addDebugProfilesSubView()));
debug->addAction (profiles);
debug->addSeparator();
mGlobalDebugProfileMenu = new GlobalDebugProfileMenu (
&dynamic_cast<CSMWorld::IdTable&> (*mDocument->getData().getTableModel (
CSMWorld::UniversalId::Type_DebugProfiles)), this);
connect (mGlobalDebugProfileMenu, SIGNAL (triggered (const std::string&)),
this, SLOT (run (const std::string&)));
QAction *runDebug = debug->addMenu (mGlobalDebugProfileMenu);
runDebug->setText (tr ("Run OpenMW"));
mStopDebug = new QAction (tr ("Shutdown OpenMW"), this);
connect (mStopDebug, SIGNAL (triggered()), this, SLOT (stop()));
debug->addAction (mStopDebug);
QAction *runLog = new QAction (tr ("Run Log"), this);
connect (runLog, SIGNAL (triggered()), this, SLOT (addRunLogSubView()));
debug->addAction (runLog);
}
void CSVDoc::View::setupUi()
{
setupFileMenu();
@ -241,6 +275,7 @@ void CSVDoc::View::setupUi()
setupMechanicsMenu();
setupCharacterMenu();
setupAssetsMenu();
setupDebugMenu();
}
void CSVDoc::View::updateTitle()
@ -261,6 +296,7 @@ void CSVDoc::View::updateTitle()
void CSVDoc::View::updateActions()
{
bool editing = !(mDocument->getState() & CSMDoc::State_Locked);
bool running = mDocument->getState() & CSMDoc::State_Running;
for (std::vector<QAction *>::iterator iter (mEditingActions.begin()); iter!=mEditingActions.end(); ++iter)
(*iter)->setEnabled (editing);
@ -268,8 +304,11 @@ void CSVDoc::View::updateActions()
mUndo->setEnabled (editing & mDocument->getUndoStack().canUndo());
mRedo->setEnabled (editing & mDocument->getUndoStack().canRedo());
mSave->setEnabled (!(mDocument->getState() & CSMDoc::State_Saving));
mSave->setEnabled (!(mDocument->getState() & CSMDoc::State_Saving) && !running);
mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying));
mGlobalDebugProfileMenu->updateActions (running);
mStopDebug->setEnabled (running);
}
CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews)
@ -295,9 +334,13 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to
setupUi();
updateActions();
CSVWorld::addSubViewFactories (mSubViewFactory);
CSVTools::addSubViewFactories (mSubViewFactory);
mSubViewFactory.add (CSMWorld::UniversalId::Type_RunLog, new SubViewFactory<RunLogSubView>);
connect (mOperations, SIGNAL (abortOperation (int)), this, SLOT (abortOperation (int)));
}
@ -543,6 +586,16 @@ void CSVDoc::View::addVideosSubView()
addSubView (CSMWorld::UniversalId::Type_Videos);
}
void CSVDoc::View::addDebugProfilesSubView()
{
addSubView (CSMWorld::UniversalId::Type_DebugProfiles);
}
void CSVDoc::View::addRunLogSubView()
{
addSubView (CSMWorld::UniversalId::Type_RunLog);
}
void CSVDoc::View::abortOperation (int type)
{
mDocument->abortOperation (type);
@ -588,3 +641,13 @@ void CSVDoc::View::loadErrorLog()
{
addSubView (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_LoadErrorLog, 0));
}
void CSVDoc::View::run (const std::string& profile, const std::string& startupInstruction)
{
mDocument->startRunning (profile, startupInstruction);
}
void CSVDoc::View::stop()
{
mDocument->stopRunning();
}

@ -25,6 +25,7 @@ namespace CSVDoc
{
class ViewManager;
class Operations;
class GlobalDebugProfileMenu;
class View : public QMainWindow
{
@ -39,10 +40,12 @@ namespace CSVDoc
QAction *mSave;
QAction *mVerify;
QAction *mShowStatusBar;
QAction *mStopDebug;
std::vector<QAction *> mEditingActions;
Operations *mOperations;
SubViewFactoryManager mSubViewFactory;
QMainWindow mSubViewWindow;
GlobalDebugProfileMenu *mGlobalDebugProfileMenu;
// not implemented
@ -67,6 +70,8 @@ namespace CSVDoc
void setupAssetsMenu();
void setupDebugMenu();
void setupUi();
void updateTitle();
@ -194,9 +199,17 @@ namespace CSVDoc
void addVideosSubView();
void addDebugProfilesSubView();
void addRunLogSubView();
void toggleShowStatusBar (bool show);
void loadErrorLog();
void run (const std::string& profile, const std::string& startupInstruction = "");
void stop();
};
}

@ -1,77 +0,0 @@
#include "filtercreator.hpp"
#include <QComboBox>
#include <QLabel>
#include "../../model/filter/filter.hpp"
#include "../../model/world/data.hpp"
#include "../../model/world/commands.hpp"
#include "../../model/world/columns.hpp"
#include "../../model/world/idtable.hpp"
std::string CSVFilter::FilterCreator::getNamespace() const
{
switch (mScope->currentIndex())
{
case CSMFilter::Filter::Scope_Project: return "project::";
case CSMFilter::Filter::Scope_Session: return "session::";
}
return "";
}
void CSVFilter::FilterCreator::update()
{
mNamespace->setText (QString::fromUtf8 (getNamespace().c_str()));
GenericCreator::update();
}
std::string CSVFilter::FilterCreator::getId() const
{
return getNamespace() + GenericCreator::getId();
}
void CSVFilter::FilterCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
{
int index =
dynamic_cast<CSMWorld::IdTable&> (*getData().getTableModel (getCollectionId())).
findColumnIndex (CSMWorld::Columns::ColumnId_Scope);
command.addValue (index, mScope->currentIndex());
}
CSVFilter::FilterCreator::FilterCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id)
: GenericCreator (data, undoStack, id)
{
mNamespace = new QLabel ("::", this);
insertAtBeginning (mNamespace, false);
mScope = new QComboBox (this);
mScope->addItem ("Project");
mScope->addItem ("Session");
/// \todo re-enable for OpenMW 1.1
// mScope->addItem ("Content");
connect (mScope, SIGNAL (currentIndexChanged (int)), this, SLOT (setScope (int)));
insertAtBeginning (mScope, false);
QLabel *label = new QLabel ("Scope", this);
insertAtBeginning (label, false);
mScope->setCurrentIndex (1);
}
void CSVFilter::FilterCreator::reset()
{
GenericCreator::reset();
}
void CSVFilter::FilterCreator::setScope (int index)
{
update();
}

@ -1,43 +0,0 @@
#ifndef CSV_FILTER_FILTERCREATOR_H
#define CSV_FILTER_FILTERCREATOR_H
class QComboBox;
class QLabel;
#include "../world/genericcreator.hpp"
namespace CSVFilter
{
class FilterCreator : public CSVWorld::GenericCreator
{
Q_OBJECT
QComboBox *mScope;
QLabel *mNamespace;
private:
std::string getNamespace() const;
protected:
void update();
virtual std::string getId() const;
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
public:
FilterCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id);
virtual void reset();
private slots:
void setScope (int index);
};
}
#endif

@ -133,6 +133,20 @@ void CSVRender::PagedWorldspaceWidget::referenceAdded (const QModelIndex& parent
flagAsModified();
}
std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction()
{
Ogre::Vector3 position = getCamera()->getPosition();
std::ostringstream stream;
stream
<< "player->position "
<< position.x << ", " << position.y << ", " << position.z
<< ", 0";
return stream.str();
}
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document)
: WorldspaceWidget (document, parent), mDocument (document), mWorldspace ("std::default")
{
@ -206,8 +220,15 @@ std::pair< int, int > CSVRender::PagedWorldspaceWidget::getCoordinatesFromId (co
return std::make_pair(x, y);
}
void CSVRender::PagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data)
bool CSVRender::PagedWorldspaceWidget::handleDrop (
const std::vector< CSMWorld::UniversalId >& data, DropType type)
{
if (WorldspaceWidget::handleDrop (data, type))
return true;
if (type!=Type_CellsExterior)
return false;
bool selectionChanged = false;
for (unsigned i = 0; i < data.size(); ++i)
{
@ -224,16 +245,23 @@ void CSVRender::PagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::
emit cellSelectionChanged(mSelection);
}
return true;
}
CSVRender::WorldspaceWidget::dropRequirments CSVRender::PagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const
CSVRender::WorldspaceWidget::dropRequirments CSVRender::PagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::DropType type) const
{
dropRequirments requirements = WorldspaceWidget::getDropRequirements (type);
if (requirements!=ignored)
return requirements;
switch (type)
{
case cellsExterior:
case Type_CellsExterior:
return canHandle;
case cellsInterior:
case Type_CellsInterior:
return needUnpaged;
default:

@ -42,6 +42,8 @@ namespace CSVRender
virtual void referenceAdded (const QModelIndex& index, int start, int end);
virtual std::string getStartupInstruction();
public:
PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document);
@ -55,9 +57,11 @@ namespace CSVRender
void setCellSelection (const CSMWorld::CellSelection& selection);
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
/// \return Drop handled?
virtual bool handleDrop (const std::vector<CSMWorld::UniversalId>& data,
DropType type);
virtual dropRequirments getDropRequirements(dropType type) const;
virtual dropRequirments getDropRequirements(DropType type) const;
/// \attention The created tool is not added to the toolbar (via addTool). Doing
/// that is the responsibility of the calling function.

@ -1,7 +1,10 @@
#include "unpagedworldspacewidget.hpp"
#include <sstream>
#include <OgreColourValue.h>
#include <OgreCamera.h>
#include <QtGui/qevent.h>
@ -86,13 +89,21 @@ void CSVRender::UnpagedWorldspaceWidget::cellRowsAboutToBeRemoved (const QModelI
emit closeRequest();
}
void CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data)
bool CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector<CSMWorld::UniversalId>& data, DropType type)
{
if (WorldspaceWidget::handleDrop (data, type))
return true;
if (type!=Type_CellsInterior)
return false;
mCellId = data.begin()->getId();
mCell.reset (new Cell (getDocument().getData(), getSceneManager(), mCellId));
update();
emit cellChanged(*data.begin());
/// \todo replace mCell
return true;
}
void CSVRender::UnpagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft,
@ -149,14 +160,33 @@ void CSVRender::UnpagedWorldspaceWidget::referenceAdded (const QModelIndex& pare
flagAsModified();
}
CSVRender::WorldspaceWidget::dropRequirments CSVRender::UnpagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const
std::string CSVRender::UnpagedWorldspaceWidget::getStartupInstruction()
{
Ogre::Vector3 position = getCamera()->getPosition();
std::ostringstream stream;
stream
<< "player->positionCell "
<< position.x << ", " << position.y << ", " << position.z
<< ", 0, \"" << mCellId << "\"";
return stream.str();
}
CSVRender::WorldspaceWidget::dropRequirments CSVRender::UnpagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::DropType type) const
{
dropRequirments requirements = WorldspaceWidget::getDropRequirements (type);
if (requirements!=ignored)
return requirements;
switch(type)
{
case cellsInterior:
case Type_CellsInterior:
return canHandle;
case cellsExterior:
case Type_CellsExterior:
return needPaged;
default:

@ -41,9 +41,11 @@ namespace CSVRender
UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document,
QWidget *parent);
virtual dropRequirments getDropRequirements(dropType type) const;
virtual dropRequirments getDropRequirements(DropType type) const;
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
/// \return Drop handled?
virtual bool handleDrop (const std::vector<CSMWorld::UniversalId>& data,
DropType type);
private:
@ -60,6 +62,8 @@ namespace CSVRender
virtual void referenceAdded (const QModelIndex& index, int start, int end);
virtual std::string getStartupInstruction();
private slots:
void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);

@ -1,6 +1,8 @@
#include "worldspacewidget.hpp"
#include <algorithm>
#include <OgreSceneNode.h>
#include <OgreSceneManager.h>
#include <OgreEntity.h>
@ -8,14 +10,16 @@
#include <QtGui/qevent.h>
#include "../../model/world/universalid.hpp"
#include "../../model/world/idtable.hpp"
#include "../widget/scenetoolmode.hpp"
#include "../widget/scenetooltoggle.hpp"
#include "../widget/scenetoolrun.hpp"
#include "elements.hpp"
CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent)
: SceneWidget (parent), mDocument(document)
: SceneWidget (parent), mDocument(document), mRun (0)
{
setAcceptDrops(true);
@ -38,6 +42,14 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg
this, SLOT (referenceAboutToBeRemoved (const QModelIndex&, int, int)));
connect (references, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (referenceAdded (const QModelIndex&, int, int)));
QAbstractItemModel *debugProfiles =
document.getData().getTableModel (CSMWorld::UniversalId::Type_DebugProfiles);
connect (debugProfiles, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
this, SLOT (debugProfileDataChanged (const QModelIndex&, const QModelIndex&)));
connect (debugProfiles, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (debugProfileAboutToBeRemoved (const QModelIndex&, int, int)));
}
void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
@ -112,59 +124,98 @@ CSVWidget::SceneToolToggle *CSVRender::WorldspaceWidget::makeSceneVisibilitySele
return mSceneElements;
}
CSVRender::WorldspaceWidget::dropType CSVRender::WorldspaceWidget::getDropType (
CSVWidget::SceneToolRun *CSVRender::WorldspaceWidget::makeRunTool (
CSVWidget::SceneToolbar *parent)
{
CSMWorld::IdTable& debugProfiles = dynamic_cast<CSMWorld::IdTable&> (
*mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_DebugProfiles));
std::vector<std::string> profiles;
int idColumn = debugProfiles.findColumnIndex (CSMWorld::Columns::ColumnId_Id);
int stateColumn = debugProfiles.findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
int defaultColumn = debugProfiles.findColumnIndex (
CSMWorld::Columns::ColumnId_DefaultProfile);
int size = debugProfiles.rowCount();
for (int i=0; i<size; ++i)
{
int state = debugProfiles.data (debugProfiles.index (i, stateColumn)).toInt();
bool default_ = debugProfiles.data (debugProfiles.index (i, defaultColumn)).toInt();
if (state!=CSMWorld::RecordBase::State_Deleted && default_)
profiles.push_back (
debugProfiles.data (debugProfiles.index (i, idColumn)).
toString().toUtf8().constData());
}
std::sort (profiles.begin(), profiles.end());
mRun = new CSVWidget::SceneToolRun (parent, "Run OpenMW from the current camera position",
":door.png", ":faction.png", profiles);
connect (mRun, SIGNAL (runRequest (const std::string&)),
this, SLOT (runRequest (const std::string&)));
return mRun;
}
CSVRender::WorldspaceWidget::DropType CSVRender::WorldspaceWidget::getDropType (
const std::vector< CSMWorld::UniversalId >& data)
{
dropType output = notCells;
bool firstIteration = true;
DropType output = Type_Other;
for (unsigned i = 0; i < data.size(); ++i)
for (std::vector<CSMWorld::UniversalId>::const_iterator iter (data.begin());
iter!=data.end(); ++iter)
{
if (data[i].getType() == CSMWorld::UniversalId::Type_Cell ||
data[i].getType() == CSMWorld::UniversalId::Type_Cell_Missing)
DropType type = Type_Other;
if (iter->getType()==CSMWorld::UniversalId::Type_Cell ||
iter->getType()==CSMWorld::UniversalId::Type_Cell_Missing)
{
if (*(data[i].getId().begin()) == '#') //exterior
{
if (firstIteration)
{
output = cellsExterior;
firstIteration = false;
continue;
}
if (output == cellsInterior)
{
output = cellsMixed;
break;
} else {
output = cellsInterior;
}
} else //interior
{
if (firstIteration)
{
output = cellsInterior;
firstIteration = false;
continue;
}
if (output == cellsExterior)
{
output = cellsMixed;
break;
} else {
output = cellsInterior;
}
}
} else {
output = notCells;
break;
type = iter->getId().substr (0, 1)=="#" ? Type_CellsExterior : Type_CellsInterior;
}
else if (iter->getType()==CSMWorld::UniversalId::Type_DebugProfile)
type = Type_DebugProfile;
if (iter==data.begin())
output = type;
else if (output!=type) // mixed types -> ignore
return Type_Other;
}
return output;
}
CSVRender::WorldspaceWidget::dropRequirments
CSVRender::WorldspaceWidget::getDropRequirements (DropType type) const
{
if (type==Type_DebugProfile)
return canHandle;
return ignored;
}
bool CSVRender::WorldspaceWidget::handleDrop (const std::vector<CSMWorld::UniversalId>& data,
DropType type)
{
if (type==Type_DebugProfile)
{
if (mRun)
{
for (std::vector<CSMWorld::UniversalId>::const_iterator iter (data.begin());
iter!=data.end(); ++iter)
mRun->addProfile (iter->getId());
}
return true;
}
return false;
}
unsigned int CSVRender::WorldspaceWidget::getElementMask() const
{
return mSceneElements->getSelection();
@ -179,6 +230,11 @@ void CSVRender::WorldspaceWidget::addVisibilitySelectorButtons (
tool->addButton (":armor.png", Element_Pathgrid, ":armor.png", "Pathgrid");
}
CSMDoc::Document& CSVRender::WorldspaceWidget::getDocument()
{
return mDocument;
}
void CSVRender::WorldspaceWidget::dragEnterEvent (QDragEnterEvent* event)
{
event->accept();
@ -201,6 +257,58 @@ void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event)
} //not handling drops from different documents at the moment
}
void CSVRender::WorldspaceWidget::runRequest (const std::string& profile)
{
mDocument.startRunning (profile, getStartupInstruction());
}
void CSVRender::WorldspaceWidget::debugProfileDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{
if (!mRun)
return;
CSMWorld::IdTable& debugProfiles = dynamic_cast<CSMWorld::IdTable&> (
*mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_DebugProfiles));
int idColumn = debugProfiles.findColumnIndex (CSMWorld::Columns::ColumnId_Id);
int stateColumn = debugProfiles.findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
for (int i=topLeft.row(); i<=bottomRight.row(); ++i)
{
int state = debugProfiles.data (debugProfiles.index (i, stateColumn)).toInt();
// As of version 0.33 this case can not happen because debug profiles exist only in
// project or session scope, which means they will never be in deleted state. But we
// are adding the code for the sake of completeness and to avoid surprises if debug
// profile ever get extended to content scope.
if (state==CSMWorld::RecordBase::State_Deleted)
mRun->removeProfile (debugProfiles.data (
debugProfiles.index (i, idColumn)).toString().toUtf8().constData());
}
}
void CSVRender::WorldspaceWidget::debugProfileAboutToBeRemoved (const QModelIndex& parent,
int start, int end)
{
if (parent.isValid())
return;
if (!mRun)
return;
CSMWorld::IdTable& debugProfiles = dynamic_cast<CSMWorld::IdTable&> (
*mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_DebugProfiles));
int idColumn = debugProfiles.findColumnIndex (CSMWorld::Columns::ColumnId_Id);
for (int i=start; i<=end; ++i)
{
mRun->removeProfile (debugProfiles.data (
debugProfiles.index (i, idColumn)).toString().toUtf8().constData());
}
}
void CSVRender::WorldspaceWidget::elementSelectionChanged()
{
setVisibilityMask (getElementMask());

@ -18,6 +18,7 @@ namespace CSVWidget
class SceneToolMode;
class SceneToolToggle;
class SceneToolbar;
class SceneToolRun;
}
namespace CSVRender
@ -30,15 +31,17 @@ namespace CSVRender
CSVRender::NavigationFree mFree;
CSVRender::NavigationOrbit mOrbit;
CSVWidget::SceneToolToggle *mSceneElements;
CSVWidget::SceneToolRun *mRun;
CSMDoc::Document& mDocument;
public:
enum dropType
enum DropType
{
cellsMixed,
cellsInterior,
cellsExterior,
notCells
Type_CellsInterior,
Type_CellsExterior,
Type_Other,
Type_DebugProfile
};
enum dropRequirments
@ -60,16 +63,22 @@ namespace CSVRender
CSVWidget::SceneToolToggle *makeSceneVisibilitySelector (
CSVWidget::SceneToolbar *parent);
/// \attention The created tool is not added to the toolbar (via addTool). Doing
/// that is the responsibility of the calling function.
CSVWidget::SceneToolRun *makeRunTool (CSVWidget::SceneToolbar *parent);
void selectDefaultNavigationMode();
static dropType getDropType(const std::vector<CSMWorld::UniversalId>& data);
static DropType getDropType(const std::vector<CSMWorld::UniversalId>& data);
virtual dropRequirments getDropRequirements(dropType type) const = 0;
virtual dropRequirments getDropRequirements(DropType type) const;
virtual void useViewHint (const std::string& hint);
///< Default-implementation: ignored.
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data) = 0;
/// \return Drop handled?
virtual bool handleDrop (const std::vector<CSMWorld::UniversalId>& data,
DropType type);
virtual unsigned int getElementMask() const;
@ -77,7 +86,7 @@ namespace CSVRender
virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle *tool);
const CSMDoc::Document& mDocument;
CSMDoc::Document& getDocument();
private:
@ -87,6 +96,8 @@ namespace CSVRender
void dragMoveEvent(QDragMoveEvent *event);
virtual std::string getStartupInstruction() = 0;
private slots:
void selectNavigationMode (const std::string& mode);
@ -104,6 +115,14 @@ namespace CSVRender
virtual void referenceAdded (const QModelIndex& index, int start, int end) = 0;
virtual void runRequest (const std::string& profile);
void debugProfileDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight);
void debugProfileAboutToBeRemoved (const QModelIndex& parent, int start, int end);
protected slots:
void elementSelectionChanged();

@ -21,7 +21,7 @@ CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc:
mTable->setSelectionMode (QAbstractItemView::ExtendedSelection);
mIdTypeDelegate = CSVWorld::IdTypeDelegateFactory().makeDelegate (
document.getUndoStack(), this);
document, this);
mTable->setItemDelegateForColumn (0, mIdTypeDelegate);

@ -20,6 +20,10 @@ void CSVWidget::PushButton::setExtendedToolTip()
break;
case Type_TopAction:
break;
case Type_Mode:
tooltip +=
@ -87,4 +91,9 @@ bool CSVWidget::PushButton::hasKeepOpen() const
QString CSVWidget::PushButton::getBaseToolTip() const
{
return mToolTip;
}
CSVWidget::PushButton::Type CSVWidget::PushButton::getType() const
{
return mType;
}

@ -14,6 +14,7 @@ namespace CSVWidget
enum Type
{
Type_TopMode, // top level button for mode selector panel
Type_TopAction, // top level button that triggers an action
Type_Mode, // mode button
Type_Toggle
};
@ -50,6 +51,8 @@ namespace CSVWidget
/// Return tooltip used at construction (without any button-specific modifications)
QString getBaseToolTip() const;
Type getType() const;
};
}

@ -1,10 +1,12 @@
#include "scenetool.hpp"
#include <QMouseEvent>
#include "scenetoolbar.hpp"
CSVWidget::SceneTool::SceneTool (SceneToolbar *parent)
: PushButton (PushButton::Type_TopMode, "", parent)
CSVWidget::SceneTool::SceneTool (SceneToolbar *parent, Type type)
: PushButton (type, "", parent)
{
setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
setIconSize (QSize (parent->getIconSize(), parent->getIconSize()));
@ -13,7 +15,20 @@ CSVWidget::SceneTool::SceneTool (SceneToolbar *parent)
connect (this, SIGNAL (clicked()), this, SLOT (openRequest()));
}
void CSVWidget::SceneTool::activate() {}
void CSVWidget::SceneTool::mouseReleaseEvent (QMouseEvent *event)
{
if (getType()==Type_TopAction && event->button()==Qt::RightButton)
showPanel (parentWidget()->mapToGlobal (pos()));
else
PushButton::mouseReleaseEvent (event);
}
void CSVWidget::SceneTool::openRequest()
{
showPanel (parentWidget()->mapToGlobal (pos()));
if (getType()==Type_TopAction)
activate();
else
showPanel (parentWidget()->mapToGlobal (pos()));
}

@ -14,10 +14,18 @@ namespace CSVWidget
public:
SceneTool (SceneToolbar *parent);
SceneTool (SceneToolbar *parent, Type type = Type_TopMode);
virtual void showPanel (const QPoint& position) = 0;
/// This function will only called for buttons of type Type_TopAction. The default
/// implementation is empty.
virtual void activate();
protected:
void mouseReleaseEvent (QMouseEvent *event);
private slots:
void openRequest();

@ -0,0 +1,151 @@
#include "scenetoolrun.hpp"
#include <iterator>
#include <QFrame>
#include <QTableWidget>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QApplication>
void CSVWidget::SceneToolRun::adjustToolTips()
{
QString toolTip = mToolTip;
if (mSelected==mProfiles.end())
toolTip += "<p>No debug profile selected (function disabled)";
else
{
toolTip += "<p>Debug profile: " + QString::fromUtf8 (mSelected->c_str());
toolTip += "<p>(right click to switch to a different profile)";
}
setToolTip (toolTip);
}
void CSVWidget::SceneToolRun::updateIcon()
{
setIcon (QIcon (mSelected==mProfiles.end() ? mIconDisabled : mIcon));
}
void CSVWidget::SceneToolRun::updatePanel()
{
mTable->setRowCount (mProfiles.size());
int i = 0;
for (std::set<std::string>::const_iterator iter (mProfiles.begin()); iter!=mProfiles.end();
++iter, ++i)
{
mTable->setItem (i, 0, new QTableWidgetItem (QString::fromUtf8 (iter->c_str())));
mTable->setItem (i, 1, new QTableWidgetItem (
QApplication::style()->standardIcon (QStyle::SP_TitleBarCloseButton), ""));
}
}
CSVWidget::SceneToolRun::SceneToolRun (SceneToolbar *parent, const QString& toolTip,
const QString& icon, const QString& iconDisabled, const std::vector<std::string>& profiles)
: SceneTool (parent, Type_TopAction), mProfiles (profiles.begin(), profiles.end()),
mSelected (mProfiles.begin()), mToolTip (toolTip), mIcon (icon),
mIconDisabled (iconDisabled)
{
updateIcon();
adjustToolTips();
mPanel = new QFrame (this, Qt::Popup);
QHBoxLayout *layout = new QHBoxLayout (mPanel);
layout->setContentsMargins (QMargins (0, 0, 0, 0));
mTable = new QTableWidget (0, 2, this);
mTable->setShowGrid (false);
mTable->verticalHeader()->hide();
mTable->horizontalHeader()->hide();
mTable->horizontalHeader()->setResizeMode (0, QHeaderView::Stretch);
mTable->horizontalHeader()->setResizeMode (1, QHeaderView::ResizeToContents);
mTable->setSelectionMode (QAbstractItemView::NoSelection);
layout->addWidget (mTable);
connect (mTable, SIGNAL (clicked (const QModelIndex&)),
this, SLOT (clicked (const QModelIndex&)));
}
void CSVWidget::SceneToolRun::showPanel (const QPoint& position)
{
updatePanel();
mPanel->move (position);
mPanel->show();
}
void CSVWidget::SceneToolRun::activate()
{
if (mSelected!=mProfiles.end())
emit runRequest (*mSelected);
}
void CSVWidget::SceneToolRun::removeProfile (const std::string& profile)
{
std::set<std::string>::iterator iter = mProfiles.find (profile);
if (iter!=mProfiles.end())
{
if (iter==mSelected)
{
if (iter!=mProfiles.begin())
--mSelected;
else
++mSelected;
}
mProfiles.erase (iter);
if (mSelected==mProfiles.end())
updateIcon();
adjustToolTips();
}
}
void CSVWidget::SceneToolRun::addProfile (const std::string& profile)
{
std::set<std::string>::iterator iter = mProfiles.find (profile);
if (iter==mProfiles.end())
{
mProfiles.insert (profile);
if (mSelected==mProfiles.end())
{
mSelected = mProfiles.begin();
updateIcon();
}
adjustToolTips();
}
}
void CSVWidget::SceneToolRun::clicked (const QModelIndex& index)
{
if (index.column()==0)
{
// select profile
mSelected = mProfiles.begin();
std::advance (mSelected, index.row());
mPanel->hide();
adjustToolTips();
}
else if (index.column()==1)
{
// remove profile from list
std::set<std::string>::iterator iter = mProfiles.begin();
std::advance (iter, index.row());
removeProfile (*iter);
updatePanel();
}
}

@ -0,0 +1,64 @@
#ifndef CSV_WIDGET_SCENETOOLRUN_H
#define CSV_WIDGET_SCENETOOLRUN_H
#include <set>
#include <string>
#include "scenetool.hpp"
class QFrame;
class QTableWidget;
class QModelIndex;
namespace CSVWidget
{
class SceneToolRun : public SceneTool
{
Q_OBJECT
std::set<std::string> mProfiles;
std::set<std::string>::iterator mSelected;
QString mToolTip;
QString mIcon;
QString mIconDisabled;
QFrame *mPanel;
QTableWidget *mTable;
private:
void adjustToolTips();
void updateIcon();
void updatePanel();
public:
SceneToolRun (SceneToolbar *parent, const QString& toolTip, const QString& icon,
const QString& iconDisabled, const std::vector<std::string>& profiles);
virtual void showPanel (const QPoint& position);
virtual void activate();
/// \attention This function does not remove the profile from the profile selection
/// panel.
void removeProfile (const std::string& profile);
/// \attention This function doe not add the profile to the profile selection
/// panel. This only happens when the panel is re-opened.
///
/// \note Adding profiles that are already listed is a no-op.
void addProfile (const std::string& profile);
private slots:
void clicked (const QModelIndex& index);
signals:
void runRequest (const std::string& profile);
};
}
#endif

@ -1,7 +1,16 @@
#include "creator.hpp"
CSVWorld::Creator:: ~Creator() {}
#include <stdexcept>
CSVWorld::Creator::~Creator() {}
void CSVWorld::Creator::setScope (unsigned int scope)
{
if (scope!=CSMWorld::Scope_Content)
throw std::logic_error ("Invalid scope in creator");
}
CSVWorld::CreatorFactoryBase::~CreatorFactoryBase() {}

@ -1,9 +1,14 @@
#ifndef CSV_WORLD_CREATOR_H
#define CSV_WORLD_CREATOR_H
#include <memory>
#include <QWidget>
#include "../../model/world/universalid.hpp"
#include "../../model/world/scope.hpp"
class QUndoStack;
namespace CSMWorld
@ -32,6 +37,9 @@ namespace CSVWorld
virtual void toggleWidgets(bool active = true) = 0;
/// Default implementation: Throw an exception if scope!=Scope_Content.
virtual void setScope (unsigned int scope);
signals:
void done();
@ -68,7 +76,7 @@ namespace CSVWorld
/// \note The function always returns 0.
};
template<class CreatorT>
template<class CreatorT, unsigned int scope = CSMWorld::Scope_Content>
class CreatorFactory : public CreatorFactoryBase
{
public:
@ -81,11 +89,15 @@ namespace CSVWorld
/// records should be provided.
};
template<class CreatorT>
Creator *CreatorFactory<CreatorT>::makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
template<class CreatorT, unsigned int scope>
Creator *CreatorFactory<CreatorT, scope>::makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id) const
{
return new CreatorT (data, undoStack, id);
std::auto_ptr<CreatorT> creator (new CreatorT (data, undoStack, id));
creator->setScope (scope);
return creator.release();
}
}

@ -6,11 +6,11 @@
CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values,
const IconList &icons,
QUndoStack &undoStack,
CSMDoc::Document& document,
const QString &pageName,
const QString &settingName,
QObject *parent)
: EnumDelegate (values, undoStack, parent), mDisplayMode (Mode_TextOnly),
: EnumDelegate (values, document, parent), mDisplayMode (Mode_TextOnly),
mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3),
mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName)
{
@ -126,8 +126,6 @@ void CSVWorld::DataDisplayDelegate::updateDisplayMode (const QString &mode)
CSVWorld::DataDisplayDelegate::~DataDisplayDelegate()
{
mIcons.clear();
mPixmaps.clear();
}
void CSVWorld::DataDisplayDelegateFactory::add (int enumValue, QString enumName, QString iconFilename)
@ -137,11 +135,10 @@ void CSVWorld::DataDisplayDelegateFactory::add (int enumValue, QString enumName,
}
CSVWorld::CommandDelegate *CSVWorld::DataDisplayDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
CSVWorld::CommandDelegate *CSVWorld::DataDisplayDelegateFactory::makeDelegate (
CSMDoc::Document& document, QObject *parent) const
{
return new DataDisplayDelegate (mValues, mIcons, undoStack, "", "", parent);
return new DataDisplayDelegate (mValues, mIcons, document, "", "", parent);
}

@ -40,7 +40,7 @@ namespace CSVWorld
public:
explicit DataDisplayDelegate (const ValueList & values,
const IconList & icons,
QUndoStack& undoStack,
CSMDoc::Document& document,
const QString &pageName,
const QString &settingName,
QObject *parent);
@ -82,7 +82,7 @@ namespace CSVWorld
public:
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
protected:

@ -167,10 +167,10 @@ void CSVWorld::DialogueDelegateDispatcherProxy::tableMimeDataDropped(const std::
==============================DialogueDelegateDispatcher==========================================
*/
CSVWorld::DialogueDelegateDispatcher::DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, QUndoStack& undoStack) :
CSVWorld::DialogueDelegateDispatcher::DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, CSMDoc::Document& document) :
mParent(parent),
mTable(table),
mUndoStack(undoStack),
mDocument (document),
mNotEditableDelegate(table, parent)
{
}
@ -182,7 +182,7 @@ CSVWorld::CommandDelegate* CSVWorld::DialogueDelegateDispatcher::makeDelegate(CS
if (delegateIt == mDelegates.end())
{
delegate = CommandDelegateFactoryCollection::get().makeDelegate (
display, mUndoStack, mParent);
display, mDocument, mParent);
mDelegates.insert(std::make_pair(display, delegate));
} else
{
@ -266,7 +266,6 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::
editor = delegateIt->second->createEditor(qobject_cast<QWidget*>(mParent), QStyleOptionViewItem(), index, display);
DialogueDelegateDispatcherProxy* proxy = new DialogueDelegateDispatcherProxy(editor, display);
bool skip = false;
if (qobject_cast<DropLineEdit*>(editor))
{
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited()));
@ -274,27 +273,22 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::
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*)));
skip = true;
}
if(!skip && qobject_cast<QCheckBox*>(editor))
else if (qobject_cast<QCheckBox*>(editor))
{
connect(editor, SIGNAL(stateChanged(int)), proxy, SLOT(editorDataCommited()));
skip = true;
}
if(!skip && qobject_cast<QPlainTextEdit*>(editor))
else if (qobject_cast<QPlainTextEdit*>(editor))
{
connect(editor, SIGNAL(textChanged()), proxy, SLOT(editorDataCommited()));
skip = true;
}
if(!skip && qobject_cast<QComboBox*>(editor))
else if (qobject_cast<QComboBox*>(editor))
{
connect(editor, SIGNAL(currentIndexChanged (int)), proxy, SLOT(editorDataCommited()));
skip = true;
}
if(!skip && qobject_cast<QAbstractSpinBox*>(editor))
else if (qobject_cast<QAbstractSpinBox*>(editor))
{
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited()));
skip = true;
}
connect(proxy, SIGNAL(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)), this, SLOT(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)));
@ -315,12 +309,12 @@ CSVWorld::DialogueDelegateDispatcher::~DialogueDelegateDispatcher()
=============================================================EditWidget=====================================================
*/
CSVWorld::EditWidget::EditWidget(QWidget *parent, int row, CSMWorld::IdTable* table, QUndoStack& undoStack, bool createAndDelete) :
mDispatcher(this, table, undoStack),
CSVWorld::EditWidget::EditWidget(QWidget *parent, int row, CSMWorld::IdTable* table, CSMDoc::Document& document, bool createAndDelete) :
mDispatcher(this, table, document),
QScrollArea(parent),
mWidgetMapper(NULL),
mMainWidget(NULL),
mUndoStack(undoStack),
mDocument (document),
mTable(table)
{
remake (row);
@ -478,7 +472,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
mMainLayout = new QVBoxLayout(mainWidget);
mEditWidget = new EditWidget(mainWidget, mRow, mTable, mUndoStack, false);
mEditWidget = new EditWidget(mainWidget, mRow, mTable, 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*)));

@ -101,14 +101,14 @@ namespace CSVWorld
CSMWorld::IdTable* mTable;
QUndoStack& mUndoStack;
CSMDoc::Document& mDocument;
NotEditableSubDelegate mNotEditableDelegate;
std::vector<DialogueDelegateDispatcherProxy*> mProxys; //once we move to the C++11 we should use unique_ptr
public:
DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, QUndoStack& undoStack);
DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, CSMDoc::Document& document);
~DialogueDelegateDispatcher();
@ -145,11 +145,11 @@ namespace CSVWorld
DialogueDelegateDispatcher mDispatcher;
QWidget* mMainWidget;
CSMWorld::IdTable* mTable;
QUndoStack& mUndoStack;
CSMDoc::Document& mDocument;
public:
EditWidget (QWidget *parent, int row, CSMWorld::IdTable* table, QUndoStack& undoStack, bool createAndDelete = false);
EditWidget (QWidget *parent, int row, CSMWorld::IdTable* table, CSMDoc::Document& document, bool createAndDelete = false);
void remake(int row);

@ -35,8 +35,8 @@ void CSVWorld::EnumDelegate::addCommands (QAbstractItemModel *model,
CSVWorld::EnumDelegate::EnumDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent)
: CommandDelegate (undoStack, parent), mValues (values)
CSMDoc::Document& document, QObject *parent)
: CommandDelegate (document, parent), mValues (values)
{
}
@ -140,10 +140,10 @@ CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const std::vector<std::strin
add (i, names[i].c_str());
}
CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (
CSMDoc::Document& document, QObject *parent) const
{
return new EnumDelegate (mValues, undoStack, parent);
return new EnumDelegate (mValues, document, parent);
}
void CSVWorld::EnumDelegateFactory::add (int value, const QString& name)

@ -30,7 +30,7 @@ namespace CSVWorld
public:
EnumDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent);
CSMDoc::Document& document, QObject *parent);
virtual QWidget *createEditor(QWidget *parent,
const QStyleOptionViewItem& option,
@ -64,7 +64,7 @@ namespace CSVWorld
EnumDelegateFactory (const std::vector<std::string>& names, bool allowNone = false);
/// \param allowNone Use value of -1 for "none selected" (empty string)
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
void add (int value, const QString& name);

@ -7,6 +7,10 @@
#include <QPushButton>
#include <QLineEdit>
#include <QUndoStack>
#include <QLabel>
#include <QComboBox>
#include <components/misc/stringops.hpp>
#include "../../model/world/commands.hpp"
#include "../../model/world/data.hpp"
@ -56,22 +60,66 @@ const CSMWorld::UniversalId& CSVWorld::GenericCreator::getCollectionId() const
return mListId;
}
CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id, bool relaxedIdRules):
std::string CSVWorld::GenericCreator::getNamespace() const
{
CSMWorld::Scope scope = CSMWorld::Scope_Content;
if (mScope)
{
scope = static_cast<CSMWorld::Scope> (mScope->itemData (mScope->currentIndex()).toInt());
}
else
{
if (mScopes & CSMWorld::Scope_Project)
scope = CSMWorld::Scope_Project;
else if (mScopes & CSMWorld::Scope_Session)
scope = CSMWorld::Scope_Session;
}
mData (data),
mUndoStack (undoStack),
mListId (id),
mLocked (false),
mCloneMode(false),
mClonedType(CSMWorld::UniversalId::Type_None)
switch (scope)
{
case CSMWorld::Scope_Content: return "";
case CSMWorld::Scope_Project: return "project::";
case CSMWorld::Scope_Session: return "session::";
}
return "";
}
void CSVWorld::GenericCreator::updateNamespace()
{
std::string namespace_ = getNamespace();
mValidator->setNamespace (namespace_);
int index = mId->text().indexOf ("::");
if (index==-1)
{
// no namespace in old text
mId->setText (QString::fromUtf8 (namespace_.c_str()) + mId->text());
}
else
{
std::string oldNamespace =
Misc::StringUtils::lowerCase (mId->text().left (index).toUtf8().constData());
if (oldNamespace=="project" || oldNamespace=="session")
mId->setText (QString::fromUtf8 (namespace_.c_str()) + mId->text().mid (index+2));
}
}
CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id, bool relaxedIdRules)
: mData (data), mUndoStack (undoStack), mListId (id), mLocked (false), mCloneMode (false),
mClonedType (CSMWorld::UniversalId::Type_None), mScopes (CSMWorld::Scope_Content), mScope (0),
mScopeLabel (0)
{
mLayout = new QHBoxLayout;
mLayout->setContentsMargins (0, 0, 0, 0);
mId = new QLineEdit;
mId->setValidator (new IdValidator (relaxedIdRules, this));
mId->setValidator (mValidator = new IdValidator (relaxedIdRules, this));
mLayout->addWidget (mId, 1);
mCreate = new QPushButton ("Create");
@ -99,22 +147,17 @@ void CSVWorld::GenericCreator::reset()
mCloneMode = false;
mId->setText ("");
update();
updateNamespace();
}
std::string CSVWorld::GenericCreator::getErrors() const
{
std::string errors;
std::string id = getId();
if (id.empty())
{
errors = "Missing ID";
}
else if (mData.hasId (id))
{
if (!mId->hasAcceptableInput())
errors = mValidator->getError();
else if (mData.hasId (getId()))
errors = "ID is already in use";
}
return errors;
}
@ -128,29 +171,28 @@ void CSVWorld::GenericCreator::create()
{
if (!mLocked)
{
std::string id = getId();
if (mCloneMode)
{
std::string id = getId();
std::auto_ptr<CSMWorld::CloneCommand> command (new CSMWorld::CloneCommand (
dynamic_cast<CSMWorld::IdTable&> (*mData.getTableModel(mListId)), mClonedId, id, mClonedType));
mUndoStack.push(command.release());
emit done();
emit requestFocus(id);
} else {
std::string id = getId();
}
else
{
std::auto_ptr<CSMWorld::CreateCommand> command (new CSMWorld::CreateCommand (
dynamic_cast<CSMWorld::IdTable&> (*mData.getTableModel (mListId)), id));
configureCreateCommand (*command);
mUndoStack.push (command.release());
emit done();
emit requestFocus (id);
}
emit done();
emit requestFocus(id);
}
}
@ -165,3 +207,49 @@ void CSVWorld::GenericCreator::cloneMode(const std::string& originId,
void CSVWorld::GenericCreator::toggleWidgets(bool active)
{
}
void CSVWorld::GenericCreator::setScope (unsigned int scope)
{
mScopes = scope;
int count = (mScopes & CSMWorld::Scope_Content) + (mScopes & CSMWorld::Scope_Project) +
(mScopes & CSMWorld::Scope_Session);
// scope selector widget
if (count>1)
{
mScope = new QComboBox (this);
insertAtBeginning (mScope, false);
if (mScopes & CSMWorld::Scope_Content)
mScope->addItem ("Content", static_cast<int> (CSMWorld::Scope_Content));
if (mScopes & CSMWorld::Scope_Project)
mScope->addItem ("Project", static_cast<int> (CSMWorld::Scope_Project));
if (mScopes & CSMWorld::Scope_Session)
mScope->addItem ("Session", static_cast<int> (CSMWorld::Scope_Session));
connect (mScope, SIGNAL (currentIndexChanged (int)), this, SLOT (scopeChanged (int)));
mScopeLabel = new QLabel ("Scope", this);
insertAtBeginning (mScopeLabel, false);
mScope->setCurrentIndex (0);
}
else
{
delete mScope;
mScope = 0;
delete mScopeLabel;
mScopeLabel = 0;
}
updateNamespace();
}
void CSVWorld::GenericCreator::scopeChanged (int index)
{
update();
updateNamespace();
}

@ -5,6 +5,8 @@ class QString;
class QPushButton;
class QLineEdit;
class QHBoxLayout;
class QComboBox;
class QLabel;
#include "creator.hpp"
@ -17,6 +19,8 @@ namespace CSMWorld
namespace CSVWorld
{
class IdValidator;
class GenericCreator : public Creator
{
Q_OBJECT
@ -31,6 +35,10 @@ namespace CSVWorld
bool mLocked;
std::string mClonedId;
CSMWorld::UniversalId::Type mClonedType;
unsigned int mScopes;
QComboBox *mScope;
QLabel *mScopeLabel;
IdValidator *mValidator;
protected:
bool mCloneMode;
@ -54,6 +62,12 @@ namespace CSVWorld
const CSMWorld::UniversalId& getCollectionId() const;
std::string getNamespace() const;
private:
void updateNamespace();
public:
GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack,
@ -65,18 +79,22 @@ namespace CSVWorld
virtual void toggleWidgets (bool active = true);
virtual void cloneMode(const std::string& originId,
virtual void cloneMode(const std::string& originId,
const CSMWorld::UniversalId::Type type);
virtual std::string getErrors() const;
///< Return formatted error descriptions for the current state of the creator. if an empty
/// string is returned, there is no error.
virtual void setScope (unsigned int scope);
private slots:
void textChanged (const QString& text);
void create();
void scopeChanged (int index);
};
}

@ -3,8 +3,8 @@
#include "../../model/world/universalid.hpp"
CSVWorld::IdTypeDelegate::IdTypeDelegate
(const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent)
: DataDisplayDelegate (values, icons, undoStack,
(const ValueList &values, const IconList &icons, CSMDoc::Document& document, QObject *parent)
: DataDisplayDelegate (values, icons, document,
"Display Format", "Referenceable ID Type Display",
parent)
{}
@ -20,8 +20,8 @@ CSVWorld::IdTypeDelegateFactory::IdTypeDelegateFactory()
}
}
CSVWorld::CommandDelegate *CSVWorld::IdTypeDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
CSVWorld::CommandDelegate *CSVWorld::IdTypeDelegateFactory::makeDelegate (
CSMDoc::Document& document, QObject *parent) const
{
return new IdTypeDelegate (mValues, mIcons, undoStack, parent);
return new IdTypeDelegate (mValues, mIcons, document, parent);
}

@ -11,7 +11,7 @@ namespace CSVWorld
class IdTypeDelegate : public DataDisplayDelegate
{
public:
IdTypeDelegate (const ValueList &mValues, const IconList &icons, QUndoStack& undoStack, QObject *parent);
IdTypeDelegate (const ValueList &mValues, const IconList &icons, CSMDoc::Document& document, QObject *parent);
};
class IdTypeDelegateFactory : public DataDisplayDelegateFactory
@ -20,7 +20,7 @@ namespace CSVWorld
IdTypeDelegateFactory();
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
};
}

@ -1,6 +1,8 @@
#include "idvalidator.hpp"
#include <components/misc/stringops.hpp>
bool CSVWorld::IdValidator::isValid (const QChar& c, bool first) const
{
if (c.isLetter() || c=='_')
@ -18,6 +20,8 @@ CSVWorld::IdValidator::IdValidator (bool relaxed, QObject *parent)
QValidator::State CSVWorld::IdValidator::validate (QString& input, int& pos) const
{
mError.clear();
if (mRelaxed)
{
if (input.indexOf ('"')!=-1 || input.indexOf ("::")!=-1 || input.indexOf ("#")!=-1)
@ -25,12 +29,95 @@ QValidator::State CSVWorld::IdValidator::validate (QString& input, int& pos) con
}
else
{
if (input.isEmpty())
{
mError = "Missing ID";
return QValidator::Intermediate;
}
bool first = true;
bool scope = false;
bool prevScope = false;
QString::const_iterator iter = input.begin();
if (!mNamespace.empty())
{
std::string namespace_ = input.left (mNamespace.size()).toUtf8().constData();
if (Misc::StringUtils::lowerCase (namespace_)!=mNamespace)
return QValidator::Invalid; // incorrect namespace
iter += namespace_.size();
first = false;
prevScope = true;
}
else
{
int index = input.indexOf (":");
if (index!=-1)
{
QString namespace_ = input.left (index);
if (namespace_=="project" || namespace_=="session")
return QValidator::Invalid; // reserved namespace
}
}
for (; iter!=input.end(); ++iter, first = false)
{
if (*iter==':')
{
if (first)
return QValidator::Invalid; // scope operator at the beginning
for (QString::const_iterator iter (input.begin()); iter!=input.end(); ++iter, first = false)
if (!isValid (*iter, first))
return QValidator::Invalid;
if (scope)
{
scope = false;
prevScope = true;
}
else
{
if (prevScope)
return QValidator::Invalid; // sequence of two scope operators
scope = true;
}
}
else if (scope)
return QValidator::Invalid; // incomplete scope operator
else
{
prevScope = false;
if (!isValid (*iter, first))
return QValidator::Invalid;
}
}
if (scope)
{
mError = "ID ending with incomplete scope operator";
return QValidator::Intermediate;
}
if (prevScope)
{
mError = "ID ending with scope operator";
return QValidator::Intermediate;
}
}
return QValidator::Acceptable;
}
void CSVWorld::IdValidator::setNamespace (const std::string& namespace_)
{
mNamespace = Misc::StringUtils::lowerCase (namespace_);
}
std::string CSVWorld::IdValidator::getError() const
{
return mError;
}

@ -1,6 +1,8 @@
#ifndef CSV_WORLD_IDVALIDATOR_H
#define CSV_WORLD_IDVALIDATOR_H
#include <string>
#include <QValidator>
namespace CSVWorld
@ -8,6 +10,8 @@ namespace CSVWorld
class IdValidator : public QValidator
{
bool mRelaxed;
std::string mNamespace;
mutable std::string mError;
private:
@ -20,6 +24,14 @@ namespace CSVWorld
virtual State validate (QString& input, int& pos) const;
void setNamespace (const std::string& namespace_);
/// Return a description of the error that resulted in the last call of validate
/// returning QValidator::Intermediate. If the last call to validate returned
/// a different value (or if there was no such call yet), an empty string is
/// returned.
std::string getError() const;
};
}

@ -9,16 +9,16 @@
CSVWorld::RecordStatusDelegate::RecordStatusDelegate(const ValueList& values,
const IconList & icons,
QUndoStack &undoStack, QObject *parent)
: DataDisplayDelegate (values, icons, undoStack,
CSMDoc::Document& document, QObject *parent)
: DataDisplayDelegate (values, icons, document,
"Display Format", "Record Status Display",
parent)
{}
CSVWorld::CommandDelegate *CSVWorld::RecordStatusDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
CSVWorld::CommandDelegate *CSVWorld::RecordStatusDelegateFactory::makeDelegate (
CSMDoc::Document& document, QObject *parent) const
{
return new RecordStatusDelegate (mValues, mIcons, undoStack, parent);
return new RecordStatusDelegate (mValues, mIcons, document, parent);
}
CSVWorld::RecordStatusDelegateFactory::RecordStatusDelegateFactory()

@ -19,7 +19,7 @@ namespace CSVWorld
explicit RecordStatusDelegate(const ValueList& values,
const IconList& icons,
QUndoStack& undoStack, QObject *parent = 0);
CSMDoc::Document& document, QObject *parent = 0);
};
class RecordStatusDelegateFactory : public DataDisplayDelegateFactory
@ -28,7 +28,7 @@ namespace CSVWorld
RecordStatusDelegateFactory();
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
};

@ -20,6 +20,7 @@
#include "../widget/scenetoolbar.hpp"
#include "../widget/scenetoolmode.hpp"
#include "../widget/scenetooltoggle.hpp"
#include "../widget/scenetoolrun.hpp"
#include "tablebottombox.hpp"
#include "creator.hpp"
@ -121,6 +122,9 @@ CSVWidget::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::Worldsp
toolbar->addTool (controlVisibilityTool);
}
CSVWidget::SceneToolRun *runTool = widget->makeRunTool (toolbar);
toolbar->addTool (runTool);
return toolbar;
}
@ -194,10 +198,12 @@ void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalI
CSVRender::UnpagedWorldspaceWidget* unPagedNewWidget = NULL;
CSVWidget::SceneToolbar* toolbar = NULL;
switch (mScene->getDropRequirements(CSVRender::WorldspaceWidget::getDropType(data)))
CSVRender::WorldspaceWidget::DropType type = CSVRender::WorldspaceWidget::getDropType (data);
switch (mScene->getDropRequirements (type))
{
case CSVRender::WorldspaceWidget::canHandle:
mScene->handleDrop(data);
mScene->handleDrop (data, type);
break;
case CSVRender::WorldspaceWidget::needPaged:
@ -205,7 +211,7 @@ void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalI
toolbar = makeToolbar(pagedNewWidget, widget_Paged);
makeConnections(pagedNewWidget);
replaceToolbarAndWorldspace(pagedNewWidget, toolbar);
mScene->handleDrop(data);
mScene->handleDrop (data, type);
break;
case CSVRender::WorldspaceWidget::needUnpaged:

@ -6,14 +6,35 @@
#include <QRegExp>
#include <QString>
#include "../../model/doc/document.hpp"
#include "../../model/world/universalid.hpp"
#include "../../model/world/tablemimedata.hpp"
CSVWorld::ScriptEdit::ScriptEdit (QWidget* parent, const CSMDoc::Document& document) :
QTextEdit (parent),
CSVWorld::ScriptEdit::ChangeLock::ChangeLock (ScriptEdit& edit) : mEdit (edit)
{
++mEdit.mChangeLocked;
}
CSVWorld::ScriptEdit::ChangeLock::~ChangeLock()
{
--mEdit.mChangeLocked;
}
CSVWorld::ScriptEdit::ScriptEdit (const CSMDoc::Document& document, ScriptHighlighter::Mode mode,
QWidget* parent)
: QPlainTextEdit (parent),
mDocument (document),
mWhiteListQoutes("^[a-z|_]{1}[a-z|0-9|_]{0,}$", Qt::CaseInsensitive)
mWhiteListQoutes("^[a-z|_]{1}[a-z|0-9|_]{0,}$", Qt::CaseInsensitive),
mChangeLocked (0)
{
// setAcceptRichText (false);
setLineWrapMode (QPlainTextEdit::NoWrap);
setTabStopWidth (4);
setUndoRedoEnabled (false); // we use OpenCS-wide undo/redo instead
mAllowedTypes <<CSMWorld::UniversalId::Type_Journal
<<CSMWorld::UniversalId::Type_Global
<<CSMWorld::UniversalId::Type_Topic
@ -40,14 +61,29 @@ CSVWorld::ScriptEdit::ScriptEdit (QWidget* parent, const CSMDoc::Document& docum
<<CSMWorld::UniversalId::Type_Probe
<<CSMWorld::UniversalId::Type_Repair
<<CSMWorld::UniversalId::Type_Static
<<CSMWorld::UniversalId::Type_Weapon;
<<CSMWorld::UniversalId::Type_Weapon
<<CSMWorld::UniversalId::Type_Script
<<CSMWorld::UniversalId::Type_Region;
mHighlighter = new ScriptHighlighter (document.getData(), mode, ScriptEdit::document());
connect (&document.getData(), SIGNAL (idListChanged()), this, SLOT (idListChanged()));
connect (&mUpdateTimer, SIGNAL (timeout()), this, SLOT (updateHighlighting()));
mUpdateTimer.setSingleShot (true);
}
bool CSVWorld::ScriptEdit::isChangeLocked() const
{
return mChangeLocked!=0;
}
void CSVWorld::ScriptEdit::dragEnterEvent (QDragEnterEvent* event)
{
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
if (!mime)
QTextEdit::dragEnterEvent(event);
QPlainTextEdit::dragEnterEvent(event);
else
{
setTextCursor (cursorForPosition (event->pos()));
@ -59,7 +95,7 @@ void CSVWorld::ScriptEdit::dragMoveEvent (QDragMoveEvent* event)
{
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
if (!mime)
QTextEdit::dragMoveEvent(event);
QPlainTextEdit::dragMoveEvent(event);
else
{
setTextCursor (cursorForPosition (event->pos()));
@ -72,7 +108,7 @@ void CSVWorld::ScriptEdit::dropEvent (QDropEvent* event)
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
{
QTextEdit::dropEvent(event);
QPlainTextEdit::dropEvent(event);
return;
}
@ -103,3 +139,21 @@ bool CSVWorld::ScriptEdit::stringNeedsQuote (const std::string& id) const
//I'm not quite sure when do we need to put quotes. To be safe we will use quotes for anything other than…
return !(string.contains(mWhiteListQoutes));
}
void CSVWorld::ScriptEdit::idListChanged()
{
mHighlighter->invalidateIds();
if (!mUpdateTimer.isActive())
mUpdateTimer.start (0);
}
void CSVWorld::ScriptEdit::updateHighlighting()
{
if (isChangeLocked())
return;
ChangeLock lock (*this);
mHighlighter->rehighlight();
}

@ -1,11 +1,14 @@
#ifndef SCRIPTEDIT_H
#define SCRIPTEDIT_H
#include <qtextedit.h>
#include <QPlainTextEdit>
#include <QVector>
#include <QTimer>
#include "../../model/world/universalid.hpp"
#include "scripthighlighter.hpp"
class QWidget;
class QRegExp;
@ -16,11 +19,42 @@ namespace CSMDoc
namespace CSVWorld
{
class ScriptEdit : public QTextEdit
class ScriptEdit : public QPlainTextEdit
{
Q_OBJECT
public:
ScriptEdit (QWidget* parent, const CSMDoc::Document& document);
class ChangeLock
{
ScriptEdit& mEdit;
ChangeLock (const ChangeLock&);
ChangeLock& operator= (const ChangeLock&);
public:
ChangeLock (ScriptEdit& edit);
~ChangeLock();
};
friend class ChangeLock;
private:
int mChangeLocked;
ScriptHighlighter *mHighlighter;
QTimer mUpdateTimer;
public:
ScriptEdit (const CSMDoc::Document& document, ScriptHighlighter::Mode mode,
QWidget* parent);
/// Should changes to the data be ignored (i.e. not cause updated)?
///
/// \note This mechanism is used to avoid infinite update recursions
bool isChangeLocked() const;
private:
QVector<CSMWorld::UniversalId::Type> mAllowedTypes;
@ -34,6 +68,12 @@ namespace CSVWorld
void dragMoveEvent (QDragMoveEvent* event);
bool stringNeedsQuote(const std::string& id) const;
private slots:
void idListChanged();
void updateHighlighting();
};
}
#endif // SCRIPTEDIT_H

@ -30,6 +30,16 @@ bool CSVWorld::ScriptHighlighter::parseName (const std::string& name, const Comp
bool CSVWorld::ScriptHighlighter::parseKeyword (int keyword, const Compiler::TokenLoc& loc,
Compiler::Scanner& scanner)
{
if (((mMode==Mode_Console || mMode==Mode_Dialogue) &&
(keyword==Compiler::Scanner::K_begin || keyword==Compiler::Scanner::K_end ||
keyword==Compiler::Scanner::K_short || keyword==Compiler::Scanner::K_long ||
keyword==Compiler::Scanner::K_float))
|| (mMode==Mode_Console && (keyword==Compiler::Scanner::K_if ||
keyword==Compiler::Scanner::K_endif || keyword==Compiler::Scanner::K_else ||
keyword==Compiler::Scanner::K_elseif || keyword==Compiler::Scanner::K_while ||
keyword==Compiler::Scanner::K_endwhile)))
return parseName (loc.mLiteral, loc, scanner);
highlight (loc, Type_Keyword);
return true;
}
@ -63,8 +73,10 @@ void CSVWorld::ScriptHighlighter::highlight (const Compiler::TokenLoc& loc, Type
setFormat (index, length, mScheme[type]);
}
CSVWorld::ScriptHighlighter::ScriptHighlighter (const CSMWorld::Data& data, QTextDocument *parent)
: QSyntaxHighlighter (parent), Compiler::Parser (mErrorHandler, mContext), mContext (data)
CSVWorld::ScriptHighlighter::ScriptHighlighter (const CSMWorld::Data& data, Mode mode,
QTextDocument *parent)
: QSyntaxHighlighter (parent), Compiler::Parser (mErrorHandler, mContext), mContext (data),
mMode (mode)
{
/// \todo replace this with user settings
{

@ -28,12 +28,20 @@ namespace CSVWorld
Type_Id
};
enum Mode
{
Mode_General,
Mode_Console,
Mode_Dialogue
};
private:
Compiler::NullErrorHandler mErrorHandler;
Compiler::Extensions mExtensions;
CSMWorld::ScriptContext mContext;
std::map<Type, QTextCharFormat> mScheme;
Mode mMode;
private:
@ -74,7 +82,7 @@ namespace CSVWorld
public:
ScriptHighlighter (const CSMWorld::Data& data, QTextDocument *parent);
ScriptHighlighter (const CSMWorld::Data& data, Mode mode, QTextDocument *parent);
virtual void highlightBlock (const QString& text);

@ -3,8 +3,6 @@
#include <stdexcept>
#include <QTextEdit>
#include "../../model/doc/document.hpp"
#include "../../model/world/universalid.hpp"
#include "../../model/world/data.hpp"
@ -12,28 +10,12 @@
#include "../../model/world/commands.hpp"
#include "../../model/world/idtable.hpp"
#include "scripthighlighter.hpp"
#include "scriptedit.hpp"
CSVWorld::ScriptSubView::ChangeLock::ChangeLock (ScriptSubView& view) : mView (view)
{
++mView.mChangeLocked;
}
CSVWorld::ScriptSubView::ChangeLock::~ChangeLock()
{
--mView.mChangeLocked;
}
CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
: SubView (id), mDocument (document), mColumn (-1), mChangeLocked (0)
: SubView (id), mDocument (document), mColumn (-1)
{
setWidget (mEditor = new ScriptEdit (this, mDocument));
mEditor->setAcceptRichText (false);
mEditor->setLineWrapMode (QTextEdit::NoWrap);
mEditor->setTabStopWidth (4);
mEditor->setUndoRedoEnabled (false); // we use OpenCS-wide undo/redo instead
setWidget (mEditor = new ScriptEdit (mDocument, ScriptHighlighter::Mode_General, this));
mModel = &dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Scripts));
@ -58,14 +40,6 @@ CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc:
connect (mModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (rowsAboutToBeRemoved (const QModelIndex&, int, int)));
connect (&document.getData(), SIGNAL (idListChanged()), this, SLOT (idListChanged()));
mHighlighter = new ScriptHighlighter (document.getData(), mEditor->document());
connect (&mUpdateTimer, SIGNAL (timeout()), this, SLOT (updateHighlighting()));
mUpdateTimer.setSingleShot (true);
}
void CSVWorld::ScriptSubView::setEditLock (bool locked)
@ -73,20 +47,12 @@ void CSVWorld::ScriptSubView::setEditLock (bool locked)
mEditor->setReadOnly (locked);
}
void CSVWorld::ScriptSubView::idListChanged()
{
mHighlighter->invalidateIds();
if (!mUpdateTimer.isActive())
mUpdateTimer.start (0);
}
void CSVWorld::ScriptSubView::textChanged()
{
if (mChangeLocked)
if (mEditor->isChangeLocked())
return;
ChangeLock lock (*this);
ScriptEdit::ChangeLock lock (*mEditor);
mDocument.getUndoStack().push (new CSMWorld::ModifyCommand (*mModel,
mModel->getModelIndex (getUniversalId().getId(), mColumn), mEditor->toPlainText()));
@ -94,10 +60,10 @@ void CSVWorld::ScriptSubView::textChanged()
void CSVWorld::ScriptSubView::dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
{
if (mChangeLocked)
if (mEditor->isChangeLocked())
return;
ChangeLock lock (*this);
ScriptEdit::ChangeLock lock (*mEditor);
QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn);
@ -118,12 +84,3 @@ void CSVWorld::ScriptSubView::rowsAboutToBeRemoved (const QModelIndex& parent, i
deleteLater();
}
void CSVWorld::ScriptSubView::updateHighlighting()
{
if (mChangeLocked)
return;
ChangeLock lock (*this);
mHighlighter->rehighlight();
}

@ -3,9 +3,6 @@
#include "../doc/subview.hpp"
#include <QTimer>
class QTextEdit;
class QModelIndex;
namespace CSMDoc
@ -20,34 +17,16 @@ namespace CSMWorld
namespace CSVWorld
{
class ScriptHighlighter;
class ScriptEdit;
class ScriptSubView : public CSVDoc::SubView
{
Q_OBJECT
QTextEdit *mEditor;
ScriptEdit *mEditor;
CSMDoc::Document& mDocument;
CSMWorld::IdTable *mModel;
int mColumn;
int mChangeLocked;
ScriptHighlighter *mHighlighter;
QTimer mUpdateTimer;
class ChangeLock
{
ScriptSubView& mView;
ChangeLock (const ChangeLock&);
ChangeLock& operator= (const ChangeLock&);
public:
ChangeLock (ScriptSubView& view);
~ChangeLock();
};
friend class ChangeLock;
public:
@ -57,17 +36,11 @@ namespace CSVWorld
public slots:
void idListChanged();
void textChanged();
void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end);
private slots:
void updateHighlighting();
};
}

@ -3,8 +3,6 @@
#include "../doc/subviewfactoryimp.hpp"
#include "../filter/filtercreator.hpp"
#include "tablesubview.hpp"
#include "dialoguesubview.hpp"
#include "scriptsubview.hpp"
@ -35,7 +33,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
CSMWorld::UniversalId::Type_Factions,
CSMWorld::UniversalId::Type_Races,
CSMWorld::UniversalId::Type_Sounds,
CSMWorld::UniversalId::Type_Scripts,
CSMWorld::UniversalId::Type_Regions,
CSMWorld::UniversalId::Type_Birthsigns,
CSMWorld::UniversalId::Type_Spells,
@ -91,11 +88,20 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
// Other stuff (combined record tables)
manager.add (CSMWorld::UniversalId::Type_RegionMap, new CSVDoc::SubViewFactory<RegionMapSubView>);
manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory<SceneSubView>);
// More other stuff
manager.add (CSMWorld::UniversalId::Type_Filters,
new CSVDoc::SubViewFactoryWithCreator<TableSubView,
CreatorFactory<CSVFilter::FilterCreator> >);
CreatorFactory<GenericCreator, CSMWorld::Scope_Project | CSMWorld::Scope_Session> >);
manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory<SceneSubView>);
manager.add (CSMWorld::UniversalId::Type_DebugProfiles,
new CSVDoc::SubViewFactoryWithCreator<TableSubView,
CreatorFactory<GenericCreator, CSMWorld::Scope_Project | CSMWorld::Scope_Session> >);
manager.add (CSMWorld::UniversalId::Type_Scripts,
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<GenericCreator,
CSMWorld::Scope_Project | CSMWorld::Scope_Content> >);
// Dialogue subviews
static const CSMWorld::UniversalId::Type sTableTypes2[] =
@ -106,7 +112,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
CSMWorld::UniversalId::Type_Global,
CSMWorld::UniversalId::Type_Race,
CSMWorld::UniversalId::Type_Class,
CSMWorld::UniversalId::Type_Filter,
CSMWorld::UniversalId::Type_Sound,
CSMWorld::UniversalId::Type_Faction,
CSMWorld::UniversalId::Type_Enchantment,
@ -147,6 +152,12 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
manager.add (CSMWorld::UniversalId::Type_Journal,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, JournalCreatorFactory> (false));
manager.add (CSMWorld::UniversalId::Type_DebugProfile,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator, CSMWorld::Scope_Project | CSMWorld::Scope_Session> > (false));
manager.add (CSMWorld::UniversalId::Type_Filter,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator, CSMWorld::Scope_Project | CSMWorld::Scope_Session> > (false));
//preview
manager.add (CSMWorld::UniversalId::Type_Preview, new CSVDoc::SubViewFactory<PreviewSubView>);
}

@ -179,7 +179,7 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
mModel->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
CommandDelegate *delegate = CommandDelegateFactoryCollection::get().makeDelegate (display,
mDocument.getUndoStack(), this);
mDocument, this);
mDelegates.push_back (delegate);
setItemDelegateForColumn (i, delegate);

@ -17,6 +17,8 @@
#include "../../model/world/commands.hpp"
#include "../../model/world/tablemimedata.hpp"
#include "scriptedit.hpp"
CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model)
: mModel (model)
{}
@ -78,15 +80,15 @@ void CSVWorld::CommandDelegateFactoryCollection::add (CSMWorld::ColumnBase::Disp
}
CSVWorld::CommandDelegate *CSVWorld::CommandDelegateFactoryCollection::makeDelegate (
CSMWorld::ColumnBase::Display display, QUndoStack& undoStack, QObject *parent) const
CSMWorld::ColumnBase::Display display, CSMDoc::Document& document, QObject *parent) const
{
std::map<CSMWorld::ColumnBase::Display, CommandDelegateFactory *>::const_iterator iter =
mFactories.find (display);
if (iter!=mFactories.end())
return iter->second->makeDelegate (undoStack, parent);
return iter->second->makeDelegate (document, parent);
return new CommandDelegate (undoStack, parent);
return new CommandDelegate (document, parent);
}
const CSVWorld::CommandDelegateFactoryCollection& CSVWorld::CommandDelegateFactoryCollection::get()
@ -100,7 +102,12 @@ const CSVWorld::CommandDelegateFactoryCollection& CSVWorld::CommandDelegateFacto
QUndoStack& CSVWorld::CommandDelegate::getUndoStack() const
{
return mUndoStack;
return mDocument.getUndoStack();
}
CSMDoc::Document& CSVWorld::CommandDelegate::getDocument() const
{
return mDocument;
}
void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model,
@ -112,11 +119,11 @@ void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemM
QVariant new_ = hack.getData();
if (model->data (index)!=new_)
mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, new_));
getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, new_));
}
CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent)
: QStyledItemDelegate (parent), mUndoStack (undoStack), mEditLock (false)
CSVWorld::CommandDelegate::CommandDelegate (CSMDoc::Document& document, QObject *parent)
: QStyledItemDelegate (parent), mDocument (document), mEditLock (false)
{}
void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemModel *model,
@ -162,8 +169,11 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
return new QDoubleSpinBox(parent);
case CSMWorld::ColumnBase::Display_LongString:
return new QTextEdit(parent);
{
QPlainTextEdit *edit = new QPlainTextEdit(parent);
edit->setUndoRedoEnabled (false);
return edit;
}
case CSMWorld::ColumnBase::Display_Boolean:
@ -188,6 +198,10 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
return new DropLineEdit(parent);
case CSMWorld::ColumnBase::Display_ScriptLines:
return new ScriptEdit (mDocument, ScriptHighlighter::Mode_Console, parent);
default:
return QStyledItemDelegate::createEditor (parent, option, index);

@ -51,7 +51,8 @@ namespace CSVWorld
virtual ~CommandDelegateFactory();
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const = 0;
virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent)
const = 0;
///< The ownership of the returned CommandDelegate is transferred to the caller.
};
@ -77,7 +78,7 @@ namespace CSVWorld
///
/// This function must not be called more than once per value of \a display.
CommandDelegate *makeDelegate (CSMWorld::ColumnBase::Display display, QUndoStack& undoStack,
CommandDelegate *makeDelegate (CSMWorld::ColumnBase::Display display, CSMDoc::Document& document,
QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
///
@ -110,19 +111,21 @@ namespace CSVWorld
{
Q_OBJECT
QUndoStack& mUndoStack;
CSMDoc::Document& mDocument;
bool mEditLock;
protected:
QUndoStack& getUndoStack() const;
CSMDoc::Document& getDocument() const;
virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const;
public:
CommandDelegate (QUndoStack& undoStack, QObject *parent);
CommandDelegate (CSMDoc::Document& document, QObject *parent);
virtual void setModelData (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const;

@ -47,8 +47,8 @@ void CSVWorld::VarTypeDelegate::addCommands (QAbstractItemModel *model, const QM
}
CSVWorld::VarTypeDelegate::VarTypeDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent)
: EnumDelegate (values, undoStack, parent)
CSMDoc::Document& document, QObject *parent)
: EnumDelegate (values, document, parent)
{}
@ -68,10 +68,10 @@ CSVWorld::VarTypeDelegateFactory::VarTypeDelegateFactory (ESM::VarType type0,
add (type3);
}
CSVWorld::CommandDelegate *CSVWorld::VarTypeDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
CSVWorld::CommandDelegate *CSVWorld::VarTypeDelegateFactory::makeDelegate (
CSMDoc::Document& document, QObject *parent) const
{
return new VarTypeDelegate (mValues, undoStack, parent);
return new VarTypeDelegate (mValues, document, parent);
}
void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type)

@ -17,7 +17,7 @@ namespace CSVWorld
public:
VarTypeDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent);
CSMDoc::Document& document, QObject *parent);
};
class VarTypeDelegateFactory : public CommandDelegateFactory
@ -30,7 +30,7 @@ namespace CSVWorld
ESM::VarType type1 = ESM::VT_Unknown, ESM::VarType type2 = ESM::VT_Unknown,
ESM::VarType type3 = ESM::VT_Unknown);
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
void add (ESM::VarType type);

@ -64,7 +64,7 @@ add_openmw_dir (mwworld
cells localscripts customdata weather inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy cellstore actionapply actioneat
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
contentloader esmloader omwloader actiontrap cellreflist projectilemanager cellref
contentloader esmloader actiontrap cellreflist projectilemanager cellref
)
add_openmw_dir (mwclass
@ -109,7 +109,7 @@ if (NOT ANDROID)
${APPLE_BUNDLE_RESOURCES}
)
else ()
add_library(openmw
add_library(openmw
SHARED
${OPENMW_LIBS} ${OPENMW_LIBS_HEADER}
${OPENMW_FILES}
@ -139,18 +139,18 @@ target_link_libraries(openmw
if (ANDROID)
target_link_libraries(openmw
${OGRE_STATIC_PLUGINS}
${OGRE_STATIC_PLUGINS}
EGL
android
log
dl
dl
MyGUI.OgrePlatform
MyGUIEngineStatic
Plugin_StrangeButtonStatic
cpufeatures
BulletCollision
BulletDynamics
LinearMath
LinearMath
)
endif (ANDROID)

@ -186,6 +186,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
, mGrab(true)
, mScriptBlacklistUse (true)
, mExportFonts(false)
, mNewGame (false)
{
std::srand ( std::time(NULL) );
MWClass::registerClasses();
@ -268,9 +269,10 @@ void OMW::Engine::setScriptsVerbosity(bool scriptsVerbosity)
mVerboseScripts = scriptsVerbosity;
}
void OMW::Engine::setSkipMenu (bool skipMenu)
void OMW::Engine::setSkipMenu (bool skipMenu, bool newGame)
{
mSkipMenu = skipMenu;
mNewGame = newGame;
}
std::string OMW::Engine::loadSettings (Settings::Manager & settings)
@ -474,7 +476,7 @@ void OMW::Engine::go()
}
else
{
MWBase::Environment::get().getStateManager()->newGame (true);
MWBase::Environment::get().getStateManager()->newGame (!mNewGame);
}
// Start the main rendering loop

@ -95,6 +95,7 @@ namespace OMW
Translation::Storage mTranslationDataStorage;
std::vector<std::string> mScriptBlacklist;
bool mScriptBlacklistUse;
bool mNewGame;
Nif::Cache mNifCache;
@ -157,7 +158,11 @@ namespace OMW
/// Disable or enable all sounds
void setSoundUsage(bool soundUsage);
void setSkipMenu (bool skipMenu);
/// Skip main menu and go directly into the game
///
/// \param newGame Start a new game instead off dumping the player into the game
/// (ignored if !skipMenu).
void setSkipMenu (bool skipMenu, bool newGame);
void setGrabMouse(bool grab) { mGrab = grab; }

@ -105,7 +105,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
("help", "print help message")
("version", "print version information and quit")
("data", bpo::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")
->multitoken(), "set data directories (later directories have higher priority)")
->multitoken()->composing(), "set data directories (later directories have higher priority)")
("data-local", bpo::value<std::string>()->default_value(""),
"set local data directory (highest priority)")
@ -153,6 +153,9 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
("skip-menu", bpo::value<bool>()->implicit_value(true)
->default_value(false), "skip main menu on game startup")
("new-game", bpo::value<bool>()->implicit_value(true)
->default_value(false), "run new game sequence (ignored if skip-menu=0)")
("fs-strict", bpo::value<bool>()->implicit_value(true)
->default_value(false), "strict file system handling (no case folding)")
@ -256,7 +259,9 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
// startup-settings
engine.setCell(variables["start"].as<std::string>());
engine.setSkipMenu (variables["skip-menu"].as<bool>());
engine.setSkipMenu (variables["skip-menu"].as<bool>(), variables["new-game"].as<bool>());
if (!variables["skip-menu"].as<bool>() && variables["new-game"].as<bool>())
std::cerr << "new-game used without skip-menu -> ignoring it" << std::endl;
// scripts
engine.setCompileAll(variables["script-all"].as<bool>());

@ -81,7 +81,13 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener)
mMagicEffects.load (esm);
} else if (n.val == ESM::REC_SKIL) {
mSkills.load (esm);
} else {
}
else if (n.val==ESM::REC_FILT || ESM::REC_DBGP)
{
// ignore project file only records
esm.skipRecord();
}
else {
std::stringstream error;
error << "Unknown record: " << n.toString();
throw std::runtime_error(error.str());

@ -1,17 +0,0 @@
#include "omwloader.hpp"
namespace MWWorld
{
OmwLoader::OmwLoader(Loading::Listener& listener)
: ContentLoader(listener)
{
}
void OmwLoader::load(const boost::filesystem::path& filepath, int& index)
{
ContentLoader::load(filepath.filename(), index);
}
} /* namespace MWWorld */

@ -1,21 +0,0 @@
#ifndef OMWLOADER_HPP
#define OMWLOADER_HPP
#include "contentloader.hpp"
namespace MWWorld
{
/**
* @brief Placeholder for real OpenMW content loader
*/
struct OmwLoader : public ContentLoader
{
OmwLoader(Loading::Listener& listener);
void load(const boost::filesystem::path& filepath, int& index);
};
} /* namespace MWWorld */
#endif /* OMWLOADER_HPP */

@ -51,7 +51,6 @@
#include "contentloader.hpp"
#include "esmloader.hpp"
#include "omwloader.hpp"
using namespace Ogre;
@ -170,12 +169,12 @@ namespace MWWorld
GameContentLoader gameContentLoader(*listener);
EsmLoader esmLoader(mStore, mEsm, encoder, *listener);
OmwLoader omwLoader(*listener);
gameContentLoader.addLoader(".esm", &esmLoader);
gameContentLoader.addLoader(".esp", &esmLoader);
gameContentLoader.addLoader(".omwgame", &omwLoader);
gameContentLoader.addLoader(".omwaddon", &omwLoader);
gameContentLoader.addLoader(".omwgame", &esmLoader);
gameContentLoader.addLoader(".omwaddon", &esmLoader);
gameContentLoader.addLoader(".project", &esmLoader);
loadContentFiles(fileCollections, contentFiles, gameContentLoader);

@ -45,7 +45,7 @@ add_component_dir (esm
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate
npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate
npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
aisequence magiceffects
)

@ -0,0 +1,29 @@
#include "debugprofile.hpp"
#include "esmreader.hpp"
#include "esmwriter.hpp"
#include "defs.hpp"
unsigned int ESM::DebugProfile::sRecordId = REC_DBGP;
void ESM::DebugProfile::load (ESMReader& esm)
{
mDescription = esm.getHNString ("DESC");
mScriptText = esm.getHNString ("SCRP");
esm.getHNT (mFlags, "FLAG");
}
void ESM::DebugProfile::save (ESMWriter& esm) const
{
esm.writeHNCString ("DESC", mDescription);
esm.writeHNCString ("SCRP", mScriptText);
esm.writeHNT ("FLAG", mFlags);
}
void ESM::DebugProfile::blank()
{
mDescription.clear();
mScriptText.clear();
mFlags = 0;
}

@ -0,0 +1,38 @@
#ifndef COMPONENTS_ESM_DEBUGPROFILE_H
#define COMPONENTS_ESM_DEBUGPROFILE_H
#include <string>
namespace ESM
{
class ESMReader;
class ESMWriter;
struct DebugProfile
{
static unsigned int sRecordId;
enum Flags
{
Flag_Default = 1, // add to newly opened scene subviews
Flag_BypassNewGame = 2, // bypass regular game startup
Flag_Global = 4 // make available from main menu (i.e. not location specific)
};
std::string mId;
std::string mDescription;
std::string mScriptText;
unsigned int mFlags;
void load (ESMReader& esm);
void save (ESMWriter& esm) const;
/// Set record to default state (does not touch the ID).
void blank();
};
}
#endif

@ -115,7 +115,8 @@ enum RecNameInts
REC_MARK = FourCC<'M','A','R','K'>::value,
// format 1
REC_FILT = 0x544C4946
REC_FILT = 0x544C4946,
REC_DBGP = FourCC<'D','B','G','P'>::value ///< only used in project files
};
}

@ -124,7 +124,11 @@ void Script::save(ESMWriter &esm) const
mVarNames.clear();
mScriptData.clear();
mScriptText = "Begin " + mId + "\n\nEnd " + mId + "\n";
if (mId.find ("::")!=std::string::npos)
mScriptText = "Begin \"" + mId + "\"\n\nEnd " + mId + "\n";
else
mScriptText = "Begin " + mId + "\n\nEnd " + mId + "\n";
}
}

@ -73,6 +73,8 @@ Allowed options:
correctly compiled anyway
2 - treat warnings as errors
--skip-menu [=arg(=1)] (=0) skip main menu on game startup
--new-game [=arg(=1)] (=0) run new game sequence (ignored if
skip-menu=0)
--fs-strict [=arg(=1)] (=0) strict file system handling (no case
folding)
--encoding arg (=win1252) Character encoding used in OpenMW game

Loading…
Cancel
Save