forked from teamnwah/openmw-tes3coop
Merge branch 'master' into QtOGre
Conflicts: apps/opencs/model/doc/document.cpp apps/opencs/view/render/pagedworldspacewidget.cpp apps/opencs/view/render/pagedworldspacewidget.hpp components/nif/niffile.hpp libs/openengine/bullet/physic.hpploadfix
commit
312b7cd571
@ -0,0 +1,139 @@
|
|||||||
|
Adam Hogan <comrade@comrade-desktop.(none)>
|
||||||
|
Aleksandar Jovanov <ajovanov93@yahoo.com>
|
||||||
|
Alexander Olofsson <ace@haxalot.com>
|
||||||
|
Alex McKibben <mckibbenta@gmail.com>
|
||||||
|
Alex "rainChu" Haddad <alx1213@gmail.com>
|
||||||
|
Ardekantur <greystone@ardekantur.com>
|
||||||
|
Armin Preiml <b.nutzer@gmail.com>
|
||||||
|
Artem Kotsynyak <greye@carceri>
|
||||||
|
Arthur Moore <arthur@Behemoth>
|
||||||
|
Arthur Moore <Arthur.Moore.git@cd-net.net>
|
||||||
|
athile <athile@athile.net>
|
||||||
|
athile <athile.g@gmail.com>
|
||||||
|
Stefan Galowicz <bogglez@the.mind>
|
||||||
|
Bret Curtis <psi29a@gmail.com>
|
||||||
|
Britt Mathis <britt.mathis@gmail.com>
|
||||||
|
Sandy Carter <bwrsandman@gmail.com>
|
||||||
|
Sandy Carter <mr.sandy.carter@gmail.com>
|
||||||
|
Carl Maxwell <carl.maxwell@gmail.com>
|
||||||
|
cc9cii <cc9c@iinet.net.au>
|
||||||
|
Cory F. Cohen <cfcohen@verizon.net>
|
||||||
|
Chris Robinson <chris.kcat@gmail.com>
|
||||||
|
Cris Mihalache <mirceam94@hotmail.com>
|
||||||
|
darkf <lw9k123@gmail.com>
|
||||||
|
Diggory Hardy <diggory.hardy@gmail.com>
|
||||||
|
Thomas Luppi <ThomasLuppi@gmail.com>
|
||||||
|
Thomas Luppi <tluppi@thomas-GE60.(none)>
|
||||||
|
Dmitriy 'Endorph' Shkurskiy <end0rph@hotmail.com>
|
||||||
|
Dmitry Marakasov <amdmi3@amdmi3.ru>
|
||||||
|
Douglas Diniz <dgdiniz@gmail.com>
|
||||||
|
Douglas Mencken <dougmencken@gmail.com>
|
||||||
|
Edmondo Tommasina <edmondo.tommasina@gmail.com>
|
||||||
|
Eduard Cot <eduard@eduard-iMac.(none)>
|
||||||
|
Eli2 <fabian@fabian-desktop.(none)>
|
||||||
|
Emanuel Guével <guevel.emanuel@gmail.com>
|
||||||
|
Leon Saunders <LeonDavidSaunders@gmail.com>
|
||||||
|
Fil Krynicki <filipkrynicki@gmail.com>
|
||||||
|
John Blomberg <johnblo@kth.se>
|
||||||
|
Gašper Sedej <gsedej@gmail.com>
|
||||||
|
Michał Bień <michal1.bien@gmail.com>
|
||||||
|
Joel Graff <monograff76@gmail.com>
|
||||||
|
Paul McElroy <pcm1123@gmail.com>
|
||||||
|
Artem Kotsynyak <greye@carceri>
|
||||||
|
Artem Kotsynyak <greye@null.net>
|
||||||
|
gugus <gus_512@hotmail.com>
|
||||||
|
guidoj <guido@thuisbasis.net>
|
||||||
|
gus <gus_512@hotmail.com>
|
||||||
|
Hallfaer Tuilinn <gijsbertth@gmail.com>
|
||||||
|
Julian Ospald <julian.ospald@googlemail.com>
|
||||||
|
Jacob Essex <jacob@jacobessex.com>
|
||||||
|
Jan Borsodi <jborsodi@gmail.com>
|
||||||
|
Jan-Peter Nilsson <peppe@pappkartong.se>
|
||||||
|
Jason Hooks <Hooks@.(none)>
|
||||||
|
Jason Hooks <jason@Jason-ThinkPad-R61.(none)>
|
||||||
|
Jason Hooks <jhooks1@mix.wvu.edu>
|
||||||
|
Jeffrey Haines <jeffhaines@me.com>
|
||||||
|
Jeffrey Haines <jib-y@users.noreply.github.com>
|
||||||
|
Jordan Ayers <jordan.ayers@gmail.com>
|
||||||
|
Jordan Milne <jordan.milne@saynotolinux.com>
|
||||||
|
Josua Grawitter <josh@greyage.org>
|
||||||
|
Julien Voisin <pouicpouicpouic@gmail.com>
|
||||||
|
Karl-Felix Glatzer <karl.glatzer@gmx.de>
|
||||||
|
Chris Robinson <chris.kcat@gmail.com>
|
||||||
|
Kevin Poitra <pupkev@yahoo.com>
|
||||||
|
Roman Proskuryakov <humbug@deeptown.org>
|
||||||
|
Lars Söderberg <lazze_1983@hotmail.com>
|
||||||
|
lazydev <lazydev@homecomp>
|
||||||
|
lazydev <lazydev@nomail>
|
||||||
|
Lukasz Gromanowski <lgromanowski@gmail.com>
|
||||||
|
Marc Bouvier <marcrbouvier@gmail.com>
|
||||||
|
Marcin Hulist <Gohan1989@gmail.com>
|
||||||
|
Marc Zinnschlag <marc@zpages.de>
|
||||||
|
Marek Kochanowicz <herr@mikrus.pl>
|
||||||
|
Marek Kochanowicz <marek@localhost.localdomain>
|
||||||
|
Marek Kochanowicz <sirherrbatka@gmail.com>
|
||||||
|
Mark Siewert <mark.siewert@t-online.de>
|
||||||
|
Mark Siewert <ms@cerebra.localdomain>
|
||||||
|
megaton <9megaton6@gmail.com>
|
||||||
|
Michael Mc Donnell <michael@mcdonnell.dk>
|
||||||
|
Michael Papageorgiou <werdanith@yahoo.gr>
|
||||||
|
Michal Sciubidlo <michal.sciubidlo@gmail.com>
|
||||||
|
Michał Ściubidło <michal.sciubidlo@gmail.com>
|
||||||
|
Nathan Jeffords <blunted2night@gmail.com>
|
||||||
|
Nicolay Korslund <korslund@gmail.com>
|
||||||
|
Nicolay Korslund <nicolayk@met.no>
|
||||||
|
Nikolay Kasyanov <corrmage@gmail.com>
|
||||||
|
pchan3 <chantlerpeter@gmail.com>
|
||||||
|
Pieter van der Kloet <pvdkloet@gmail.com>
|
||||||
|
Mateusz Kołaczek <mateusz.kolaczek@gmail.com>
|
||||||
|
Bret Curtis <psi29a@gmail.com>
|
||||||
|
Pieter van der Kloet <pvdkloet@gmail.com>
|
||||||
|
Rohit Nirmal <rohitnirmal9@gmail.com>
|
||||||
|
Roman Melnik <kromgart@gmail.com>
|
||||||
|
Radu-Marius Popovici <rpopovici@github.com>
|
||||||
|
Sandy Carter <bwrsandman@gmail.com>
|
||||||
|
Scott Howard <showard314@gmail.com>
|
||||||
|
Jannik Heller <scrawl@baseoftrash.de>
|
||||||
|
Jannik Heller <scrawl@scrawl-laptop.(none)>
|
||||||
|
Sebastian Wick <sebastian@sebastianwick.net>
|
||||||
|
Sebastian Wick <wick.sebastian@gmail.com>
|
||||||
|
Sergey Shambir <sergey.shambir.auto@gmail.com>
|
||||||
|
sergoz <parapvr@yandex.ru>
|
||||||
|
Chris Boyce <slothlife@users.noreply.github.com>
|
||||||
|
Star-Demon <starsickle@yahoo.com>
|
||||||
|
Sylvain Thesnieres <garvek@gmail.com>
|
||||||
|
Thomas Luppi <digrules@gmail.com>
|
||||||
|
Thomas Luppi <tluppi@thomas-GE60.(none)>
|
||||||
|
Thoronador <thoronador@users.sourceforge.net>
|
||||||
|
TomKoenderink <tom_koenderink-github@omniadicta.net>
|
||||||
|
Tom Mason <wheybags@wheybags.com>
|
||||||
|
Torben Carrington <torbenlcarrington@Gmail.com>
|
||||||
|
Vincent Heuken <vincent@vincentheuken.com>
|
||||||
|
Manuel Edelmann <edelmann.manuel@gmail.com>
|
||||||
|
Manuel Edelmann <vorenon@hotmail.com>
|
||||||
|
Alexander Nadeau <wareya@gmail.com>
|
||||||
|
Michael Hogan <mr.michaelhogan@gmail.com>
|
||||||
|
Jacob Essex <github@JacobEssex.com>
|
||||||
|
Yuri Krupenin <yuri.krupenin@gmail.com>
|
||||||
|
Bret Curtis <noone@your.box>
|
||||||
|
|
||||||
|
sirherrbatka <herr@localhost.localdomain>
|
||||||
|
sirherrbatka <sirherrbatka@myopera.com>
|
||||||
|
sergei <sergei@ubuntu.(none)>
|
||||||
|
riothamus <digimars@gmail.com>
|
||||||
|
nobrakal <nobrakal@gmail.com>
|
||||||
|
nkorslund <nkorslund@ea6a568a-9f4f-0410-981a-c910a81bb256>
|
||||||
|
mrcheko <cheko@sevas.ua>
|
||||||
|
Miroslav Puda <pakanek@gmail.com>
|
||||||
|
MiroslavR <miroslavr256@gmail.com>
|
||||||
|
mckibbenta <mckibbenta@gmail.com>
|
||||||
|
jeaye <jeaye@arrownext.com>
|
||||||
|
eroen <eroen@falcon.eroen.eu>
|
||||||
|
eroen <eroen@occam.eroen.eu>
|
||||||
|
dreamer-dead <dreamer.dead@gmail.com>
|
||||||
|
crysthala <crystalsoulslayer@gmail.com>
|
||||||
|
Berulacks <beru@eml.cc>
|
||||||
|
Axujen <axujen@gmail.com>
|
||||||
|
root <root@debian>
|
||||||
|
unknown <Hooks@.(none)>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
#include "blacklist.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
bool CSMDoc::Blacklist::isBlacklisted (const CSMWorld::UniversalId& id) const
|
||||||
|
{
|
||||||
|
std::map<CSMWorld::UniversalId::Type, std::vector<std::string> >::const_iterator iter =
|
||||||
|
mIds.find (id.getType());
|
||||||
|
|
||||||
|
if (iter==mIds.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return std::binary_search (iter->second.begin(), iter->second.end(),
|
||||||
|
Misc::StringUtils::lowerCase (id.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Blacklist::add (CSMWorld::UniversalId::Type type,
|
||||||
|
const std::vector<std::string>& ids)
|
||||||
|
{
|
||||||
|
std::vector<std::string>& list = mIds[type];
|
||||||
|
|
||||||
|
int size = list.size();
|
||||||
|
|
||||||
|
list.resize (size+ids.size());
|
||||||
|
|
||||||
|
std::transform (ids.begin(), ids.end(), list.begin()+size, Misc::StringUtils::lowerCase);
|
||||||
|
std::sort (list.begin(), list.end());
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef CSM_DOC_BLACKLIST_H
|
||||||
|
#define CSM_DOC_BLACKLIST_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
/// \brief ID blacklist sorted by UniversalId type
|
||||||
|
class Blacklist
|
||||||
|
{
|
||||||
|
std::map<CSMWorld::UniversalId::Type, std::vector<std::string> > mIds;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool isBlacklisted (const CSMWorld::UniversalId& id) const;
|
||||||
|
|
||||||
|
void add (CSMWorld::UniversalId::Type type, const std::vector<std::string>& ids);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,162 @@
|
|||||||
|
|
||||||
|
#include "runner.hpp"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDir>
|
||||||
|
#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());
|
||||||
|
dir.cdUp();
|
||||||
|
dir.cdUp();
|
||||||
|
dir.cdUp();
|
||||||
|
path = dir.absoluteFilePath(path.prepend("OpenMW.app/Contents/MacOS/"));
|
||||||
|
#else
|
||||||
|
path.prepend(QString("./"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mStartup = new QTemporaryFile (this);
|
||||||
|
mStartup->open();
|
||||||
|
|
||||||
|
{
|
||||||
|
QTextStream stream (mStartup);
|
||||||
|
|
||||||
|
if (!mStartupInstruction.empty())
|
||||||
|
stream << QString::fromUtf8 (mStartupInstruction.c_str()) << '\n';
|
||||||
|
|
||||||
|
stream << QString::fromUtf8 (mProfile.mScriptText.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
mStartup->close();
|
||||||
|
|
||||||
|
QStringList arguments;
|
||||||
|
arguments << "--skip-menu";
|
||||||
|
|
||||||
|
if (mProfile.mFlags & ESM::DebugProfile::Flag_BypassNewGame)
|
||||||
|
arguments << "--new-game=0";
|
||||||
|
else
|
||||||
|
arguments << "--new-game=1";
|
||||||
|
|
||||||
|
arguments << ("--script-run="+mStartup->fileName());;
|
||||||
|
|
||||||
|
arguments <<
|
||||||
|
QString::fromUtf8 (("--data="+mProjectPath.parent_path().string()).c_str());
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator iter (mContentFiles.begin());
|
||||||
|
iter!=mContentFiles.end(); ++iter)
|
||||||
|
{
|
||||||
|
arguments << QString::fromUtf8 (("--content="+*iter).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments
|
||||||
|
<< QString::fromUtf8 (("--content="+mProjectPath.filename().string()).c_str());
|
||||||
|
|
||||||
|
mProcess.start (path, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
mRunning = true;
|
||||||
|
emit runStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Runner::stop()
|
||||||
|
{
|
||||||
|
delete mStartup;
|
||||||
|
mStartup = 0;
|
||||||
|
|
||||||
|
if (mProcess.state()==QProcess::NotRunning)
|
||||||
|
{
|
||||||
|
mRunning = false;
|
||||||
|
emit runStateChanged();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mProcess.kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMDoc::Runner::isRunning() const
|
||||||
|
{
|
||||||
|
return mRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Runner::configure (const ESM::DebugProfile& profile,
|
||||||
|
const std::vector<std::string>& contentFiles, const std::string& startupInstruction)
|
||||||
|
{
|
||||||
|
mProfile = profile;
|
||||||
|
mContentFiles = contentFiles;
|
||||||
|
mStartupInstruction = startupInstruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Runner::finished (int exitCode, QProcess::ExitStatus exitStatus)
|
||||||
|
{
|
||||||
|
mRunning = false;
|
||||||
|
emit runStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextDocument *CSMDoc::Runner::getLog()
|
||||||
|
{
|
||||||
|
return &mLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Runner::readyReadStandardOutput()
|
||||||
|
{
|
||||||
|
mLog.setPlainText (
|
||||||
|
mLog.toPlainText() + QString::fromUtf8 (mProcess.readAllStandardOutput()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::SaveWatcher::SaveWatcher (Runner *runner, Operation *operation)
|
||||||
|
: QObject (runner), mRunner (runner)
|
||||||
|
{
|
||||||
|
connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::SaveWatcher::saveDone (int type, bool failed)
|
||||||
|
{
|
||||||
|
if (failed)
|
||||||
|
mRunner->stop();
|
||||||
|
else
|
||||||
|
mRunner->start();
|
||||||
|
|
||||||
|
deleteLater();
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
#ifndef CSM_DOC_RUNNER_H
|
||||||
|
#define CSM_DOC_RUNNER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QTextDocument>
|
||||||
|
|
||||||
|
#include <components/esm/debugprofile.hpp>
|
||||||
|
|
||||||
|
class QTemporaryFile;
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Runner : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
QProcess mProcess;
|
||||||
|
bool mRunning;
|
||||||
|
ESM::DebugProfile mProfile;
|
||||||
|
std::vector<std::string> mContentFiles;
|
||||||
|
std::string mStartupInstruction;
|
||||||
|
QTemporaryFile *mStartup;
|
||||||
|
QTextDocument mLog;
|
||||||
|
boost::filesystem::path mProjectPath;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Runner (const boost::filesystem::path& projectPath);
|
||||||
|
|
||||||
|
~Runner();
|
||||||
|
|
||||||
|
/// \param delayed Flag as running but do not start the OpenMW process yet (the
|
||||||
|
/// process must be started by another call of start with delayed==false)
|
||||||
|
void start (bool delayed = false);
|
||||||
|
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
/// \note Running state is entered when the start function is called. This
|
||||||
|
/// is not necessarily identical to the moment the child process is started.
|
||||||
|
bool isRunning() const;
|
||||||
|
|
||||||
|
void configure (const ESM::DebugProfile& profile,
|
||||||
|
const std::vector<std::string>& contentFiles,
|
||||||
|
const std::string& startupInstruction);
|
||||||
|
|
||||||
|
QTextDocument *getLog();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void runStateChanged();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void finished (int exitCode, QProcess::ExitStatus exitStatus);
|
||||||
|
|
||||||
|
void readyReadStandardOutput();
|
||||||
|
};
|
||||||
|
|
||||||
|
class Operation;
|
||||||
|
|
||||||
|
/// \brief Watch for end of save operation and restart or stop runner
|
||||||
|
class SaveWatcher : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Runner *mRunner;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// *this attaches itself to runner
|
||||||
|
SaveWatcher (Runner *runner, Operation *operation);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void saveDone (int type, bool failed);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -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
|
|
@ -0,0 +1,51 @@
|
|||||||
|
#include "bodypartcheck.hpp"
|
||||||
|
|
||||||
|
CSMTools::BodyPartCheckStage::BodyPartCheckStage(
|
||||||
|
const CSMWorld::IdCollection<ESM::BodyPart> &bodyParts,
|
||||||
|
const CSMWorld::Resources &meshes,
|
||||||
|
const CSMWorld::IdCollection<ESM::Race> &races ) :
|
||||||
|
mBodyParts(bodyParts),
|
||||||
|
mMeshes(meshes),
|
||||||
|
mRaces(races)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
int CSMTools::BodyPartCheckStage::setup()
|
||||||
|
{
|
||||||
|
return mBodyParts.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMTools::BodyPartCheckStage::perform ( int stage, Messages &messages )
|
||||||
|
{
|
||||||
|
const CSMWorld::Record<ESM::BodyPart> &record = mBodyParts.getRecord(stage);
|
||||||
|
|
||||||
|
if ( record.isDeleted() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
const ESM::BodyPart &bodyPart = record.get();
|
||||||
|
|
||||||
|
CSMWorld::UniversalId id( CSMWorld::UniversalId::Type_BodyPart, bodyPart.mId );
|
||||||
|
|
||||||
|
// Check BYDT
|
||||||
|
if (bodyPart.mData.mPart > 14 )
|
||||||
|
messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range part value." ));
|
||||||
|
|
||||||
|
if (bodyPart.mData.mFlags > 3 )
|
||||||
|
messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range flags value." ));
|
||||||
|
|
||||||
|
if (bodyPart.mData.mType > 2 )
|
||||||
|
messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range type value." ));
|
||||||
|
|
||||||
|
// Check MODL
|
||||||
|
|
||||||
|
if ( bodyPart.mModel.empty() )
|
||||||
|
messages.push_back(std::make_pair( id, bodyPart.mId + " has no model." ));
|
||||||
|
else if ( mMeshes.searchId( bodyPart.mModel ) == -1 )
|
||||||
|
messages.push_back(std::make_pair( id, bodyPart.mId + " has invalid model." ));
|
||||||
|
|
||||||
|
// Check FNAM
|
||||||
|
|
||||||
|
if ( bodyPart.mRace.empty() )
|
||||||
|
messages.push_back(std::make_pair( id, bodyPart.mId + " has no race." ));
|
||||||
|
else if ( mRaces.searchId( bodyPart.mRace ) == -1 )
|
||||||
|
messages.push_back(std::make_pair( id, bodyPart.mId + " has invalid race." ));
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef CSM_TOOLS_BODYPARTCHECK_H
|
||||||
|
#define CSM_TOOLS_BODYPARTCHECK_H
|
||||||
|
|
||||||
|
#include <components/esm/loadbody.hpp>
|
||||||
|
#include <components/esm/loadrace.hpp>
|
||||||
|
|
||||||
|
#include "../world/resources.hpp"
|
||||||
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
|
namespace CSMTools
|
||||||
|
{
|
||||||
|
/// \brief VerifyStage: make sure that body part records are internally consistent
|
||||||
|
class BodyPartCheckStage : public CSMDoc::Stage
|
||||||
|
{
|
||||||
|
const CSMWorld::IdCollection<ESM::BodyPart> &mBodyParts;
|
||||||
|
const CSMWorld::Resources &mMeshes;
|
||||||
|
const CSMWorld::IdCollection<ESM::Race> &mRaces;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BodyPartCheckStage(
|
||||||
|
const CSMWorld::IdCollection<ESM::BodyPart> &bodyParts,
|
||||||
|
const CSMWorld::Resources &meshes,
|
||||||
|
const CSMWorld::IdCollection<ESM::Race> &races );
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
|
||||||
|
virtual void perform( int stage, Messages &messages );
|
||||||
|
///< Messages resulting from this tage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
#include "scope.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
CSMWorld::Scope CSMWorld::getScopeFromId (const std::string& id)
|
||||||
|
{
|
||||||
|
// get root namespace
|
||||||
|
std::string namespace_;
|
||||||
|
|
||||||
|
std::string::size_type i = id.find ("::");
|
||||||
|
|
||||||
|
if (i!=std::string::npos)
|
||||||
|
namespace_ = Misc::StringUtils::lowerCase (id.substr (0, i));
|
||||||
|
|
||||||
|
if (namespace_=="project")
|
||||||
|
return Scope_Project;
|
||||||
|
|
||||||
|
if (namespace_=="session")
|
||||||
|
return Scope_Session;
|
||||||
|
|
||||||
|
return Scope_Content;
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef CSM_WOLRD_SCOPE_H
|
||||||
|
#define CSM_WOLRD_SCOPE_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
enum Scope
|
||||||
|
{
|
||||||
|
// record stored in content file
|
||||||
|
Scope_Content = 1,
|
||||||
|
|
||||||
|
// record stored in project file
|
||||||
|
Scope_Project = 2,
|
||||||
|
|
||||||
|
// record that exists only for the duration of one editing session
|
||||||
|
Scope_Session = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
Scope getScopeFromId (const std::string& id);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,93 @@
|
|||||||
|
|
||||||
|
#include "globaldebugprofilemenu.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <QActionGroup>
|
||||||
|
|
||||||
|
#include "../../model/world/idtable.hpp"
|
||||||
|
#include "../../model/world/record.hpp"
|
||||||
|
|
||||||
|
void CSVDoc::GlobalDebugProfileMenu::rebuild()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
delete mActions;
|
||||||
|
mActions = 0;
|
||||||
|
|
||||||
|
int idColumn = mDebugProfiles->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
|
||||||
|
int stateColumn = mDebugProfiles->findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
|
||||||
|
int globalColumn = mDebugProfiles->findColumnIndex (
|
||||||
|
CSMWorld::Columns::ColumnId_GlobalProfile);
|
||||||
|
|
||||||
|
int size = mDebugProfiles->rowCount();
|
||||||
|
|
||||||
|
std::vector<QString> ids;
|
||||||
|
|
||||||
|
for (int i=0; i<size; ++i)
|
||||||
|
{
|
||||||
|
int state = mDebugProfiles->data (mDebugProfiles->index (i, stateColumn)).toInt();
|
||||||
|
|
||||||
|
bool global = mDebugProfiles->data (mDebugProfiles->index (i, globalColumn)).toInt();
|
||||||
|
|
||||||
|
if (state!=CSMWorld::RecordBase::State_Deleted && global)
|
||||||
|
ids.push_back (
|
||||||
|
mDebugProfiles->data (mDebugProfiles->index (i, idColumn)).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
mActions = new QActionGroup (this);
|
||||||
|
connect (mActions, SIGNAL (triggered (QAction *)), this, SLOT (actionTriggered (QAction *)));
|
||||||
|
|
||||||
|
std::sort (ids.begin(), ids.end());
|
||||||
|
|
||||||
|
for (std::vector<QString>::const_iterator iter (ids.begin()); iter!=ids.end(); ++iter)
|
||||||
|
{
|
||||||
|
mActions->addAction (addAction (*iter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVDoc::GlobalDebugProfileMenu::GlobalDebugProfileMenu (CSMWorld::IdTable *debugProfiles,
|
||||||
|
QWidget *parent)
|
||||||
|
: QMenu (parent), mDebugProfiles (debugProfiles), mActions (0)
|
||||||
|
{
|
||||||
|
rebuild();
|
||||||
|
|
||||||
|
connect (mDebugProfiles, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (profileAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||||
|
|
||||||
|
connect (mDebugProfiles, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (profileInserted (const QModelIndex&, int, int)));
|
||||||
|
|
||||||
|
connect (mDebugProfiles, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
|
this, SLOT (profileChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::GlobalDebugProfileMenu::updateActions (bool running)
|
||||||
|
{
|
||||||
|
if (mActions)
|
||||||
|
mActions->setEnabled (!running);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::GlobalDebugProfileMenu::profileAboutToBeRemoved (const QModelIndex& parent,
|
||||||
|
int start, int end)
|
||||||
|
{
|
||||||
|
rebuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::GlobalDebugProfileMenu::profileInserted (const QModelIndex& parent, int start,
|
||||||
|
int end)
|
||||||
|
{
|
||||||
|
rebuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::GlobalDebugProfileMenu::profileChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
rebuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::GlobalDebugProfileMenu::actionTriggered (QAction *action)
|
||||||
|
{
|
||||||
|
emit triggered (std::string (action->text().toUtf8().constData()));
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
#ifndef CSV_DOC_GLOBALDEBUGPROFILEMENU_H
|
||||||
|
#define CSV_DOC_GLOBALDEBUGPROFILEMENU_H
|
||||||
|
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
|
class QModelIndex;
|
||||||
|
class QActionGroup;
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class IdTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSVDoc
|
||||||
|
{
|
||||||
|
class GlobalDebugProfileMenu : public QMenu
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
CSMWorld::IdTable *mDebugProfiles;
|
||||||
|
QActionGroup *mActions;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void rebuild();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
GlobalDebugProfileMenu (CSMWorld::IdTable *debugProfiles, QWidget *parent = 0);
|
||||||
|
|
||||||
|
void updateActions (bool running);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void profileAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
void profileInserted (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
void profileChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
void actionTriggered (QAction *action);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void triggered (const std::string& profile);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
#include "runlogsubview.hpp"
|
||||||
|
|
||||||
|
#include <QTextEdit>
|
||||||
|
|
||||||
|
CSVDoc::RunLogSubView::RunLogSubView (const CSMWorld::UniversalId& id,
|
||||||
|
CSMDoc::Document& document)
|
||||||
|
: SubView (id)
|
||||||
|
{
|
||||||
|
QTextEdit *edit = new QTextEdit (this);
|
||||||
|
edit->setDocument (document.getRunLog());
|
||||||
|
edit->setReadOnly (true);
|
||||||
|
|
||||||
|
setWidget (edit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::RunLogSubView::setEditLock (bool locked)
|
||||||
|
{
|
||||||
|
// ignored since this SubView does not have editing
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef CSV_DOC_RUNLOGSUBVIEW_H
|
||||||
|
#define CSV_DOC_RUNLOGSUBVIEW_H
|
||||||
|
|
||||||
|
#include "subview.hpp"
|
||||||
|
|
||||||
|
namespace CSVDoc
|
||||||
|
{
|
||||||
|
class RunLogSubView : public SubView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
RunLogSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document);
|
||||||
|
|
||||||
|
virtual void setEditLock (bool locked);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -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
|
|
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef CSV_RENDER_ELEMENTS_H
|
||||||
|
#define CSV_RENDER_ELEMENTS_H
|
||||||
|
|
||||||
|
namespace CSVRender
|
||||||
|
{
|
||||||
|
/// Visual elements in a scene
|
||||||
|
enum Elements
|
||||||
|
{
|
||||||
|
// elements that are part of the actual scene
|
||||||
|
Element_Reference = 0x1,
|
||||||
|
Element_Terrain = 0x2,
|
||||||
|
Element_Water = 0x4,
|
||||||
|
Element_Pathgrid = 0x8,
|
||||||
|
Element_Fog = 0x10,
|
||||||
|
|
||||||
|
// control elements
|
||||||
|
Element_CellMarker = 0x10000,
|
||||||
|
Element_CellArrow = 0x20000,
|
||||||
|
Element_CellBorder = 0x40000
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,151 @@
|
|||||||
|
|
||||||
|
#include "scenetoolrun.hpp"
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QTableWidget>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolRun::adjustToolTips()
|
||||||
|
{
|
||||||
|
QString toolTip = mToolTip;
|
||||||
|
|
||||||
|
if (mSelected==mProfiles.end())
|
||||||
|
toolTip += "<p>No debug profile selected (function disabled)";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toolTip += "<p>Debug profile: " + QString::fromUtf8 (mSelected->c_str());
|
||||||
|
toolTip += "<p>(right click to switch to a different profile)";
|
||||||
|
}
|
||||||
|
|
||||||
|
setToolTip (toolTip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolRun::updateIcon()
|
||||||
|
{
|
||||||
|
setIcon (QIcon (mSelected==mProfiles.end() ? mIconDisabled : mIcon));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolRun::updatePanel()
|
||||||
|
{
|
||||||
|
mTable->setRowCount (mProfiles.size());
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (std::set<std::string>::const_iterator iter (mProfiles.begin()); iter!=mProfiles.end();
|
||||||
|
++iter, ++i)
|
||||||
|
{
|
||||||
|
mTable->setItem (i, 0, new QTableWidgetItem (QString::fromUtf8 (iter->c_str())));
|
||||||
|
|
||||||
|
mTable->setItem (i, 1, new QTableWidgetItem (
|
||||||
|
QApplication::style()->standardIcon (QStyle::SP_TitleBarCloseButton), ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVWidget::SceneToolRun::SceneToolRun (SceneToolbar *parent, const QString& toolTip,
|
||||||
|
const QString& icon, const QString& iconDisabled, const std::vector<std::string>& profiles)
|
||||||
|
: SceneTool (parent, Type_TopAction), mProfiles (profiles.begin(), profiles.end()),
|
||||||
|
mSelected (mProfiles.begin()), mToolTip (toolTip), mIcon (icon),
|
||||||
|
mIconDisabled (iconDisabled)
|
||||||
|
{
|
||||||
|
updateIcon();
|
||||||
|
adjustToolTips();
|
||||||
|
|
||||||
|
mPanel = new QFrame (this, Qt::Popup);
|
||||||
|
|
||||||
|
QHBoxLayout *layout = new QHBoxLayout (mPanel);
|
||||||
|
|
||||||
|
layout->setContentsMargins (QMargins (0, 0, 0, 0));
|
||||||
|
|
||||||
|
mTable = new QTableWidget (0, 2, this);
|
||||||
|
|
||||||
|
mTable->setShowGrid (false);
|
||||||
|
mTable->verticalHeader()->hide();
|
||||||
|
mTable->horizontalHeader()->hide();
|
||||||
|
mTable->horizontalHeader()->setResizeMode (0, QHeaderView::Stretch);
|
||||||
|
mTable->horizontalHeader()->setResizeMode (1, QHeaderView::ResizeToContents);
|
||||||
|
mTable->setSelectionMode (QAbstractItemView::NoSelection);
|
||||||
|
|
||||||
|
layout->addWidget (mTable);
|
||||||
|
|
||||||
|
connect (mTable, SIGNAL (clicked (const QModelIndex&)),
|
||||||
|
this, SLOT (clicked (const QModelIndex&)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolRun::showPanel (const QPoint& position)
|
||||||
|
{
|
||||||
|
updatePanel();
|
||||||
|
|
||||||
|
mPanel->move (position);
|
||||||
|
mPanel->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolRun::activate()
|
||||||
|
{
|
||||||
|
if (mSelected!=mProfiles.end())
|
||||||
|
emit runRequest (*mSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolRun::removeProfile (const std::string& profile)
|
||||||
|
{
|
||||||
|
std::set<std::string>::iterator iter = mProfiles.find (profile);
|
||||||
|
|
||||||
|
if (iter!=mProfiles.end())
|
||||||
|
{
|
||||||
|
if (iter==mSelected)
|
||||||
|
{
|
||||||
|
if (iter!=mProfiles.begin())
|
||||||
|
--mSelected;
|
||||||
|
else
|
||||||
|
++mSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
mProfiles.erase (iter);
|
||||||
|
|
||||||
|
if (mSelected==mProfiles.end())
|
||||||
|
updateIcon();
|
||||||
|
|
||||||
|
adjustToolTips();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolRun::addProfile (const std::string& profile)
|
||||||
|
{
|
||||||
|
std::set<std::string>::iterator iter = mProfiles.find (profile);
|
||||||
|
|
||||||
|
if (iter==mProfiles.end())
|
||||||
|
{
|
||||||
|
mProfiles.insert (profile);
|
||||||
|
|
||||||
|
if (mSelected==mProfiles.end())
|
||||||
|
{
|
||||||
|
mSelected = mProfiles.begin();
|
||||||
|
updateIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
adjustToolTips();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolRun::clicked (const QModelIndex& index)
|
||||||
|
{
|
||||||
|
if (index.column()==0)
|
||||||
|
{
|
||||||
|
// select profile
|
||||||
|
mSelected = mProfiles.begin();
|
||||||
|
std::advance (mSelected, index.row());
|
||||||
|
mPanel->hide();
|
||||||
|
adjustToolTips();
|
||||||
|
}
|
||||||
|
else if (index.column()==1)
|
||||||
|
{
|
||||||
|
// remove profile from list
|
||||||
|
std::set<std::string>::iterator iter = mProfiles.begin();
|
||||||
|
std::advance (iter, index.row());
|
||||||
|
removeProfile (*iter);
|
||||||
|
updatePanel();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
#ifndef CSV_WIDGET_SCENETOOLRUN_H
|
||||||
|
#define CSV_WIDGET_SCENETOOLRUN_H
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "scenetool.hpp"
|
||||||
|
|
||||||
|
class QFrame;
|
||||||
|
class QTableWidget;
|
||||||
|
class QModelIndex;
|
||||||
|
|
||||||
|
namespace CSVWidget
|
||||||
|
{
|
||||||
|
class SceneToolRun : public SceneTool
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
std::set<std::string> mProfiles;
|
||||||
|
std::set<std::string>::iterator mSelected;
|
||||||
|
QString mToolTip;
|
||||||
|
QString mIcon;
|
||||||
|
QString mIconDisabled;
|
||||||
|
QFrame *mPanel;
|
||||||
|
QTableWidget *mTable;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void adjustToolTips();
|
||||||
|
|
||||||
|
void updateIcon();
|
||||||
|
|
||||||
|
void updatePanel();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
SceneToolRun (SceneToolbar *parent, const QString& toolTip, const QString& icon,
|
||||||
|
const QString& iconDisabled, const std::vector<std::string>& profiles);
|
||||||
|
|
||||||
|
virtual void showPanel (const QPoint& position);
|
||||||
|
|
||||||
|
virtual void activate();
|
||||||
|
|
||||||
|
/// \attention This function does not remove the profile from the profile selection
|
||||||
|
/// panel.
|
||||||
|
void removeProfile (const std::string& profile);
|
||||||
|
|
||||||
|
/// \attention This function doe not add the profile to the profile selection
|
||||||
|
/// panel. This only happens when the panel is re-opened.
|
||||||
|
///
|
||||||
|
/// \note Adding profiles that are already listed is a no-op.
|
||||||
|
void addProfile (const std::string& profile);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void clicked (const QModelIndex& index);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void runRequest (const std::string& profile);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,205 @@
|
|||||||
|
|
||||||
|
#include "scenetooltoggle.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
#include "scenetoolbar.hpp"
|
||||||
|
#include "pushbutton.hpp"
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolToggle::adjustToolTip()
|
||||||
|
{
|
||||||
|
QString toolTip = mToolTip;
|
||||||
|
|
||||||
|
toolTip += "<p>Currently enabled: ";
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
for (std::map<PushButton *, ButtonDesc>::const_iterator iter (mButtons.begin());
|
||||||
|
iter!=mButtons.end(); ++iter)
|
||||||
|
if (iter->first->isChecked())
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
toolTip += ", ";
|
||||||
|
else
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
toolTip += iter->second.mName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
toolTip += "none";
|
||||||
|
|
||||||
|
toolTip += "<p>(left click to alter selection)";
|
||||||
|
|
||||||
|
setToolTip (toolTip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolToggle::adjustIcon()
|
||||||
|
{
|
||||||
|
unsigned int selection = getSelection();
|
||||||
|
if (!selection)
|
||||||
|
setIcon (QIcon (QString::fromUtf8 (mEmptyIcon.c_str())));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QPixmap pixmap (48, 48);
|
||||||
|
pixmap.fill (QColor (0, 0, 0, 0));
|
||||||
|
|
||||||
|
{
|
||||||
|
QPainter painter (&pixmap);
|
||||||
|
|
||||||
|
for (std::map<PushButton *, ButtonDesc>::const_iterator iter (mButtons.begin());
|
||||||
|
iter!=mButtons.end(); ++iter)
|
||||||
|
if (iter->first->isChecked())
|
||||||
|
{
|
||||||
|
painter.drawImage (getIconBox (iter->second.mIndex),
|
||||||
|
QImage (QString::fromUtf8 (iter->second.mSmallIcon.c_str())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setIcon (pixmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect CSVWidget::SceneToolToggle::getIconBox (int index) const
|
||||||
|
{
|
||||||
|
// layout for a 3x3 grid
|
||||||
|
int xMax = 3;
|
||||||
|
int yMax = 3;
|
||||||
|
|
||||||
|
// icon size
|
||||||
|
int xBorder = 1;
|
||||||
|
int yBorder = 1;
|
||||||
|
|
||||||
|
int iconXSize = (mIconSize-xBorder*(xMax+1))/xMax;
|
||||||
|
int iconYSize = (mIconSize-yBorder*(yMax+1))/yMax;
|
||||||
|
|
||||||
|
int y = index / xMax;
|
||||||
|
int x = index % xMax;
|
||||||
|
|
||||||
|
int total = mButtons.size();
|
||||||
|
|
||||||
|
int actualYIcons = total/xMax;
|
||||||
|
|
||||||
|
if (total % xMax)
|
||||||
|
++actualYIcons;
|
||||||
|
|
||||||
|
if (actualYIcons!=yMax)
|
||||||
|
{
|
||||||
|
// space out icons vertically, if there aren't enough to populate all rows
|
||||||
|
int diff = yMax - actualYIcons;
|
||||||
|
yBorder += (diff*(yBorder+iconXSize)) / (actualYIcons+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y==actualYIcons-1)
|
||||||
|
{
|
||||||
|
// generating the last row of icons
|
||||||
|
int actualXIcons = total % xMax;
|
||||||
|
|
||||||
|
if (actualXIcons)
|
||||||
|
{
|
||||||
|
// space out icons horizontally, if there aren't enough to fill the last row
|
||||||
|
int diff = xMax - actualXIcons;
|
||||||
|
|
||||||
|
xBorder += (diff*(xBorder+iconXSize)) / (actualXIcons+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QRect ((iconXSize+xBorder)*x+xBorder, (iconYSize+yBorder)*y+yBorder,
|
||||||
|
iconXSize, iconYSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVWidget::SceneToolToggle::SceneToolToggle (SceneToolbar *parent, const QString& toolTip,
|
||||||
|
const std::string& emptyIcon)
|
||||||
|
: SceneTool (parent), mEmptyIcon (emptyIcon), mButtonSize (parent->getButtonSize()),
|
||||||
|
mIconSize (parent->getIconSize()), mToolTip (toolTip), mFirst (0)
|
||||||
|
{
|
||||||
|
mPanel = new QFrame (this, Qt::Popup);
|
||||||
|
|
||||||
|
mLayout = new QHBoxLayout (mPanel);
|
||||||
|
|
||||||
|
mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
|
||||||
|
|
||||||
|
mPanel->setLayout (mLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolToggle::showPanel (const QPoint& position)
|
||||||
|
{
|
||||||
|
mPanel->move (position);
|
||||||
|
mPanel->show();
|
||||||
|
|
||||||
|
if (mFirst)
|
||||||
|
mFirst->setFocus (Qt::OtherFocusReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolToggle::addButton (const std::string& icon, unsigned int id,
|
||||||
|
const std::string& smallIcon, const QString& name, const QString& tooltip)
|
||||||
|
{
|
||||||
|
if (mButtons.size()>=9)
|
||||||
|
throw std::runtime_error ("Exceeded number of buttons in toggle type tool");
|
||||||
|
|
||||||
|
PushButton *button = new PushButton (QIcon (QPixmap (icon.c_str())),
|
||||||
|
PushButton::Type_Toggle, tooltip.isEmpty() ? name: tooltip, mPanel);
|
||||||
|
|
||||||
|
button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||||
|
button->setIconSize (QSize (mIconSize, mIconSize));
|
||||||
|
button->setFixedSize (mButtonSize, mButtonSize);
|
||||||
|
|
||||||
|
mLayout->addWidget (button);
|
||||||
|
|
||||||
|
ButtonDesc desc;
|
||||||
|
desc.mId = id;
|
||||||
|
desc.mSmallIcon = smallIcon;
|
||||||
|
desc.mName = name;
|
||||||
|
desc.mIndex = mButtons.size();
|
||||||
|
|
||||||
|
mButtons.insert (std::make_pair (button, desc));
|
||||||
|
|
||||||
|
connect (button, SIGNAL (clicked()), this, SLOT (selected()));
|
||||||
|
|
||||||
|
if (mButtons.size()==1)
|
||||||
|
mFirst = button;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CSVWidget::SceneToolToggle::getSelection() const
|
||||||
|
{
|
||||||
|
unsigned int selection = 0;
|
||||||
|
|
||||||
|
for (std::map<PushButton *, ButtonDesc>::const_iterator iter (mButtons.begin());
|
||||||
|
iter!=mButtons.end(); ++iter)
|
||||||
|
if (iter->first->isChecked())
|
||||||
|
selection |= iter->second.mId;
|
||||||
|
|
||||||
|
return selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolToggle::setSelection (unsigned int selection)
|
||||||
|
{
|
||||||
|
for (std::map<PushButton *, ButtonDesc>::iterator iter (mButtons.begin());
|
||||||
|
iter!=mButtons.end(); ++iter)
|
||||||
|
iter->first->setChecked (selection & iter->second.mId);
|
||||||
|
|
||||||
|
adjustToolTip();
|
||||||
|
adjustIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolToggle::selected()
|
||||||
|
{
|
||||||
|
std::map<PushButton *, ButtonDesc>::const_iterator iter =
|
||||||
|
mButtons.find (dynamic_cast<PushButton *> (sender()));
|
||||||
|
|
||||||
|
if (iter!=mButtons.end())
|
||||||
|
{
|
||||||
|
if (!iter->first->hasKeepOpen())
|
||||||
|
mPanel->hide();
|
||||||
|
|
||||||
|
adjustToolTip();
|
||||||
|
adjustIcon();
|
||||||
|
|
||||||
|
emit selectionChanged();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
#ifndef CSV_WIDGET_SCENETOOL_TOGGLE_H
|
||||||
|
#define CSV_WIDGET_SCENETOOL_TOGGLE_H
|
||||||
|
|
||||||
|
#include "scenetool.hpp"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
class QHBoxLayout;
|
||||||
|
class QRect;
|
||||||
|
|
||||||
|
namespace CSVWidget
|
||||||
|
{
|
||||||
|
class SceneToolbar;
|
||||||
|
class PushButton;
|
||||||
|
|
||||||
|
///< \brief Multi-Toggle tool
|
||||||
|
class SceneToolToggle : public SceneTool
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
struct ButtonDesc
|
||||||
|
{
|
||||||
|
unsigned int mId;
|
||||||
|
std::string mSmallIcon;
|
||||||
|
QString mName;
|
||||||
|
int mIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string mEmptyIcon;
|
||||||
|
QWidget *mPanel;
|
||||||
|
QHBoxLayout *mLayout;
|
||||||
|
std::map<PushButton *, ButtonDesc> mButtons; // widget, id
|
||||||
|
int mButtonSize;
|
||||||
|
int mIconSize;
|
||||||
|
QString mToolTip;
|
||||||
|
PushButton *mFirst;
|
||||||
|
|
||||||
|
void adjustToolTip();
|
||||||
|
|
||||||
|
void adjustIcon();
|
||||||
|
|
||||||
|
QRect getIconBox (int index) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
SceneToolToggle (SceneToolbar *parent, const QString& toolTip,
|
||||||
|
const std::string& emptyIcon);
|
||||||
|
|
||||||
|
virtual void showPanel (const QPoint& position);
|
||||||
|
|
||||||
|
/// \attention After the last button has been added, setSelection must be called at
|
||||||
|
/// least once to finalise the layout.
|
||||||
|
///
|
||||||
|
/// \note The layout algorithm can not handle more than 9 buttons. To prevent this An
|
||||||
|
/// attempt to add more will result in an exception being thrown.
|
||||||
|
/// The small icons will be sized at (x-4)/3 (where x is the main icon size).
|
||||||
|
void addButton (const std::string& icon, unsigned int id,
|
||||||
|
const std::string& smallIcon, const QString& name, const QString& tooltip = "");
|
||||||
|
|
||||||
|
unsigned int getSelection() const;
|
||||||
|
|
||||||
|
/// \param or'ed button IDs. IDs that do not exist will be ignored.
|
||||||
|
void setSelection (unsigned int selection);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void selectionChanged();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void selected();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue