forked from mirror/openmw-tes3mp
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
This commit is contained in:
commit
d1d861e1be
90 changed files with 1912 additions and 606 deletions
|
@ -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:
|
||||
|
||||
|
|
157
apps/opencs/model/doc/runner.cpp
Normal file
157
apps/opencs/model/doc/runner.cpp
Normal file
|
@ -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();
|
||||
}
|
85
apps/opencs/model/doc/runner.hpp
Normal file
85
apps/opencs/model/doc/runner.hpp
Normal file
|
@ -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,19 +718,33 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages)
|
|||
|
||||
case ESM::REC_FILT:
|
||||
|
||||
if (mProject)
|
||||
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)
|
||||
mFilters.load (*mReader, mBase);
|
||||
break;
|
||||
|
||||
case ESM::REC_DBGP:
|
||||
|
||||
if (!mProject)
|
||||
{
|
||||
unhandledRecord = true;
|
||||
break;
|
||||
}
|
||||
|
||||
mDebugProfiles.load (*mReader, mBase);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
unhandledRecord = true;
|
||||
}
|
||||
|
||||
if (unhandledRecord)
|
||||
{
|
||||
messages.push_back (std::make_pair (UniversalId::Type_None,
|
||||
"Unsupported record type: " + n.toString()));
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
25
apps/opencs/model/world/scope.cpp
Normal file
25
apps/opencs/model/world/scope.cpp
Normal file
|
@ -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;
|
||||
}
|
23
apps/opencs/model/world/scope.hpp
Normal file
23
apps/opencs/model/world/scope.hpp
Normal file
|
@ -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:
|
||||
|
||||
|
|
93
apps/opencs/view/doc/globaldebugprofilemenu.cpp
Normal file
93
apps/opencs/view/doc/globaldebugprofilemenu.cpp
Normal file
|
@ -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()));
|
||||
}
|
49
apps/opencs/view/doc/globaldebugprofilemenu.hpp
Normal file
49
apps/opencs/view/doc/globaldebugprofilemenu.hpp
Normal file
|
@ -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
|
20
apps/opencs/view/doc/runlogsubview.cpp
Normal file
20
apps/opencs/view/doc/runlogsubview.cpp
Normal file
|
@ -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
|
||||
}
|
20
apps/opencs/view/doc/runlogsubview.hpp
Normal file
20
apps/opencs/view/doc/runlogsubview.hpp
Normal file
|
@ -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)
|
||||
{
|
||||
if (*(data[i].getId().begin()) == '#') //exterior
|
||||
{
|
||||
if (firstIteration)
|
||||
{
|
||||
output = cellsExterior;
|
||||
firstIteration = false;
|
||||
continue;
|
||||
}
|
||||
DropType type = Type_Other;
|
||||
|
||||
if (output == cellsInterior)
|
||||
if (iter->getType()==CSMWorld::UniversalId::Type_Cell ||
|
||||
iter->getType()==CSMWorld::UniversalId::Type_Cell_Missing)
|
||||
{
|
||||
output = cellsMixed;
|
||||
break;
|
||||
} else {
|
||||
output = cellsInterior;
|
||||
}
|
||||
} else //interior
|
||||
{
|
||||
if (firstIteration)
|
||||
{
|
||||
output = cellsInterior;
|
||||
firstIteration = false;
|
||||
continue;
|
||||
type = iter->getId().substr (0, 1)=="#" ? Type_CellsExterior : Type_CellsInterior;
|
||||
}
|
||||
else if (iter->getType()==CSMWorld::UniversalId::Type_DebugProfile)
|
||||
type = Type_DebugProfile;
|
||||
|
||||
if (output == cellsExterior)
|
||||
{
|
||||
output = cellsMixed;
|
||||
break;
|
||||
} else {
|
||||
output = cellsInterior;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
output = notCells;
|
||||
break;
|
||||
}
|
||||
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 +=
|
||||
|
@ -88,3 +92,8 @@ 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()
|
||||
{
|
||||
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();
|
||||
|
|
151
apps/opencs/view/widget/scenetoolrun.cpp
Normal file
151
apps/opencs/view/widget/scenetoolrun.cpp
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
64
apps/opencs/view/widget/scenetoolrun.hpp
Normal file
64
apps/opencs/view/widget/scenetoolrun.hpp
Normal file
|
@ -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,8 +1,17 @@
|
|||
|
||||
#include "creator.hpp"
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
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,31 +171,30 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::cloneMode(const std::string& originId,
|
||||
const CSMWorld::UniversalId::Type type)
|
||||
|
@ -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,
|
||||
|
@ -72,11 +86,15 @@ namespace CSVWorld
|
|||
///< 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
|
||||
{
|
||||
bool first = true;
|
||||
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
|
||||
|
||||
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;
|
||||
|
||||
for (QString::const_iterator iter (input.begin()); iter!=input.end(); ++iter, first = 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),
|
||||
mDocument (document),
|
||||
mWhiteListQoutes("^[a-z|_]{1}[a-z|0-9|_]{0,}$", Qt::CaseInsensitive)
|
||||
|
||||
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),
|
||||
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
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
29
components/esm/debugprofile.cpp
Normal file
29
components/esm/debugprofile.cpp
Normal file
|
@ -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;
|
||||
}
|
38
components/esm/debugprofile.hpp
Normal file
38
components/esm/debugprofile.hpp
Normal file
|
@ -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,6 +124,10 @@ void Script::save(ESMWriter &esm) const
|
|||
|
||||
mVarNames.clear();
|
||||
mScriptData.clear();
|
||||
|
||||
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…
Reference in a new issue