1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-04 03:40:14 +00:00

Merge remote-tracking branch 'sirherrbatka/Editor-Dialog'

This commit is contained in:
Marc Zinnschlag 2014-03-20 22:27:28 +01:00
commit 688e03a9d2
47 changed files with 1564 additions and 205 deletions

View File

@ -60,11 +60,12 @@ opencs_hdrs_noqt (view/doc
opencs_units (view/world opencs_units (view/world
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
scenetoolmode infocreator scriptedit scenetoolmode infocreator scriptedit dialoguesubview previewsubview
) )
opencs_units (view/render opencs_units (view/render
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
previewwidget
) )
opencs_units_noqt (view/render opencs_units_noqt (view/render
@ -72,8 +73,7 @@ opencs_units_noqt (view/render
) )
opencs_units_noqt (view/world opencs_units_noqt (view/world
dialoguesubview subviews subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
scripthighlighter idvalidator dialoguecreator scripthighlighter idvalidator dialoguecreator
) )
@ -147,6 +147,9 @@ if(WIN32)
set(QT_USE_QTMAIN TRUE) set(QT_USE_QTMAIN TRUE)
endif(WIN32) endif(WIN32)
set(BOOST_COMPONENTS system filesystem program_options thread wave)
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED) find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED)
include(${QT_USE_FILE}) include(${QT_USE_FILE})
@ -187,6 +190,8 @@ if(APPLE)
endif(APPLE) endif(APPLE)
target_link_libraries(opencs target_link_libraries(opencs
${OGRE_LIBRARIES}
${SHINY_LIBRARIES}
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${QT_LIBRARIES} ${QT_LIBRARIES}
components components

View File

@ -9,8 +9,13 @@
#include <OgreRoot.h> #include <OgreRoot.h>
#include <OgreRenderWindow.h> #include <OgreRenderWindow.h>
#include <extern/shiny/Main/Factory.hpp>
#include <extern/shiny/Platforms/Ogre/OgrePlatform.hpp>
#include <components/ogreinit/ogreinit.hpp> #include <components/ogreinit/ogreinit.hpp>
#include <components/bsa/resources.hpp>
#include "model/doc/document.hpp" #include "model/doc/document.hpp"
#include "model/world/data.hpp" #include "model/world/data.hpp"
@ -18,14 +23,17 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
: mDocumentManager (mCfgMgr), mViewManager (mDocumentManager), : mDocumentManager (mCfgMgr), mViewManager (mDocumentManager),
mIpcServerName ("org.openmw.OpenCS") mIpcServerName ("org.openmw.OpenCS")
{ {
Files::PathContainer dataDirs = readConfig(); std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
setupDataFiles (dataDirs); setupDataFiles (config.first);
CSMSettings::UserSettings::instance().loadSettings ("opencs.cfg"); CSMSettings::UserSettings::instance().loadSettings ("opencs.cfg");
ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string()); ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string());
Bsa::registerResources (Files::Collections (config.first, !mFsStrict), config.second, true,
mFsStrict);
mNewGame.setLocalData (mLocal); mNewGame.setLocalData (mLocal);
mFileDialog.setLocalData (mLocal); mFileDialog.setLocalData (mLocal);
@ -58,7 +66,7 @@ void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs)
} }
} }
Files::PathContainer CS::Editor::readConfig() std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfig()
{ {
boost::program_options::variables_map variables; boost::program_options::variables_map variables;
boost::program_options::options_description desc("Syntax: opencs <options>\nAllowed options"); boost::program_options::options_description desc("Syntax: opencs <options>\nAllowed options");
@ -68,13 +76,17 @@ Files::PathContainer CS::Editor::readConfig()
("data-local", boost::program_options::value<std::string>()->default_value("")) ("data-local", boost::program_options::value<std::string>()->default_value(""))
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false)) ("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
("encoding", boost::program_options::value<std::string>()->default_value("win1252")) ("encoding", boost::program_options::value<std::string>()->default_value("win1252"))
("resources", boost::program_options::value<std::string>()->default_value("resources")); ("resources", boost::program_options::value<std::string>()->default_value("resources"))
("fallback-archive", boost::program_options::value<std::vector<std::string> >()->
default_value(std::vector<std::string>(), "fallback-archive")->multitoken());
boost::program_options::notify(variables); boost::program_options::notify(variables);
mCfgMgr.readConfiguration(variables, desc); mCfgMgr.readConfiguration(variables, desc);
mDocumentManager.setResourceDir (variables["resources"].as<std::string>()); mDocumentManager.setResourceDir (mResources = variables["resources"].as<std::string>());
mFsStrict = variables["fs-strict"].as<bool>();
Files::PathContainer dataDirs, dataLocal; Files::PathContainer dataDirs, dataLocal;
if (!variables["data"].empty()) { if (!variables["data"].empty()) {
@ -105,7 +117,7 @@ Files::PathContainer CS::Editor::readConfig()
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end()); dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
return dataDirs; return std::make_pair (dataDirs, variables["fallback-archive"].as<std::vector<std::string> >());
} }
void CS::Editor::createGame() void CS::Editor::createGame()
@ -216,6 +228,15 @@ int CS::Editor::run()
if (mLocal.empty()) if (mLocal.empty())
return 1; return 1;
mStartup.show();
QApplication::setQuitOnLastWindowClosed (true);
return QApplication::exec();
}
std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
{
// TODO: setting // TODO: setting
Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName("OpenGL Rendering Subsystem")); Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName("OpenGL Rendering Subsystem"));
@ -233,9 +254,36 @@ int CS::Editor::run()
Ogre::RenderWindow* hiddenWindow = Ogre::Root::getSingleton().createRenderWindow("InactiveHidden", 1, 1, false, &params); Ogre::RenderWindow* hiddenWindow = Ogre::Root::getSingleton().createRenderWindow("InactiveHidden", 1, 1, false, &params);
hiddenWindow->setActive(false); hiddenWindow->setActive(false);
mStartup.show(); sh::OgrePlatform* platform =
new sh::OgrePlatform ("General", (mResources / "materials").string());
QApplication::setQuitOnLastWindowClosed (true); if (!boost::filesystem::exists (mCfgMgr.getCachePath()))
boost::filesystem::create_directories (mCfgMgr.getCachePath());
return QApplication::exec(); platform->setCacheFolder (mCfgMgr.getCachePath().string());
std::auto_ptr<sh::Factory> factory (new sh::Factory (platform));
factory->setCurrentLanguage (sh::Language_GLSL); /// \todo make this configurable
factory->setWriteSourceCache (true);
factory->setReadSourceCache (true);
factory->setReadMicrocodeCache (true);
factory->setWriteMicrocodeCache (true);
factory->loadAllFiles();
sh::Factory::getInstance().setGlobalSetting ("fog", "true");
sh::Factory::getInstance().setGlobalSetting ("shadows", "false");
sh::Factory::getInstance().setGlobalSetting ("shadows_pssm", "false");
sh::Factory::getInstance ().setGlobalSetting ("render_refraction", "false");
sh::Factory::getInstance ().setGlobalSetting ("viewproj_fix", "false");
sh::Factory::getInstance ().setGlobalSetting ("num_lights", "8");
/// \todo add more configurable shiny settings
return factory;
} }

View File

@ -1,11 +1,15 @@
#ifndef CS_EDITOR_H #ifndef CS_EDITOR_H
#define CS_EDITOR_H #define CS_EDITOR_H
#include <memory>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QLocalServer> #include <QLocalServer>
#include <QLocalSocket> #include <QLocalSocket>
#include <extern/shiny/Main/Factory.hpp>
#ifndef Q_MOC_RUN #ifndef Q_MOC_RUN
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#endif #endif
@ -41,12 +45,13 @@ namespace CS
CSVDoc::NewGameDialogue mNewGame; CSVDoc::NewGameDialogue mNewGame;
CSVSettings::UserSettingsDialog mSettings; CSVSettings::UserSettingsDialog mSettings;
CSVDoc::FileDialog mFileDialog; CSVDoc::FileDialog mFileDialog;
boost::filesystem::path mLocal; boost::filesystem::path mLocal;
boost::filesystem::path mResources;
bool mFsStrict;
void setupDataFiles (const Files::PathContainer& dataDirs); void setupDataFiles (const Files::PathContainer& dataDirs);
Files::PathContainer readConfig(); std::pair<Files::PathContainer, std::vector<std::string> > readConfig();
///< \return data paths ///< \return data paths
// not implemented // not implemented
@ -63,6 +68,9 @@ namespace CS
int run(); int run();
///< \return error status ///< \return error status
std::auto_ptr<sh::Factory> setupGraphics();
///< The returned factory must persist at least as long as *this.
private slots: private slots:
void createGame(); void createGame();

View File

@ -7,6 +7,8 @@
#include <QApplication> #include <QApplication>
#include <QIcon> #include <QIcon>
#include <extern/shiny/Main/Factory.hpp>
#include <components/ogreinit/ogreinit.hpp> #include <components/ogreinit/ogreinit.hpp>
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -42,6 +44,8 @@ int main(int argc, char *argv[])
OgreInit::OgreInit ogreInit; OgreInit::OgreInit ogreInit;
std::auto_ptr<sh::Factory> shinyFactory;
Application application (argc, argv); Application application (argc, argv);
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -73,5 +77,7 @@ int main(int argc, char *argv[])
// return 0; // return 0;
} }
shinyFactory = editor.setupGraphics();
return editor.run(); return editor.run();
} }

View File

@ -18,3 +18,8 @@ std::string CSMWorld::ColumnBase::getTitle() const
{ {
return Columns::getName (static_cast<Columns::ColumnId> (mColumnId)); return Columns::getName (static_cast<Columns::ColumnId> (mColumnId));
} }
int CSMWorld::ColumnBase::getId() const
{
return mColumnId;
}

View File

@ -28,6 +28,7 @@ namespace CSMWorld
{ {
Display_None, //Do not use Display_None, //Do not use
Display_String, Display_String,
Display_LongString,
//CONCRETE TYPES STARTS HERE //CONCRETE TYPES STARTS HERE
Display_Skill, Display_Skill,
@ -105,6 +106,8 @@ namespace CSMWorld
///< Can this column be edited directly by the user? ///< Can this column be edited directly by the user?
virtual std::string getTitle() const; virtual std::string getTitle() const;
virtual int getId() const;
}; };
template<typename ESXRecordT> template<typename ESXRecordT>

View File

@ -202,7 +202,7 @@ namespace CSMWorld
struct DescriptionColumn : public Column<ESXRecordT> struct DescriptionColumn : public Column<ESXRecordT>
{ {
DescriptionColumn() DescriptionColumn()
: Column<ESXRecordT> (Columns::ColumnId_Description, ColumnBase::Display_String) : Column<ESXRecordT> (Columns::ColumnId_Description, ColumnBase::Display_LongString)
{} {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
@ -834,7 +834,7 @@ namespace CSMWorld
virtual bool isUserEditable() const virtual bool isUserEditable() const
{ {
return false; return true;
} }
}; };
@ -1114,7 +1114,7 @@ namespace CSMWorld
virtual bool isUserEditable() const virtual bool isUserEditable() const
{ {
return false; return true;
} }
}; };
@ -1380,7 +1380,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct QuestDescriptionColumn : public Column<ESXRecordT> struct QuestDescriptionColumn : public Column<ESXRecordT>
{ {
QuestDescriptionColumn() : Column<ESXRecordT> (Columns::ColumnId_QuestDescription, ColumnBase::Display_String) {} QuestDescriptionColumn() : Column<ESXRecordT> (Columns::ColumnId_QuestDescription, ColumnBase::Display_LongString) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -1560,7 +1560,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct ResponseColumn : public Column<ESXRecordT> struct ResponseColumn : public Column<ESXRecordT>
{ {
ResponseColumn() : Column<ESXRecordT> (Columns::ColumnId_Response, ColumnBase::Display_String) {} ResponseColumn() : Column<ESXRecordT> (Columns::ColumnId_Response, ColumnBase::Display_LongString) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {

View File

@ -250,9 +250,9 @@ CSMWorld::Data::Data() : mRefs (mCells)
addModel (new IdTable (&mTopicInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_TopicInfos, UniversalId::Type_TopicInfo); addModel (new IdTable (&mTopicInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_TopicInfos, UniversalId::Type_TopicInfo);
addModel (new IdTable (&mJournalInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_JournalInfos, UniversalId::Type_JournalInfo); addModel (new IdTable (&mJournalInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_JournalInfos, UniversalId::Type_JournalInfo);
addModel (new IdTable (&mCells, IdTable::Reordering_None, IdTable::Viewing_Id), UniversalId::Type_Cells, UniversalId::Type_Cell); addModel (new IdTable (&mCells, IdTable::Reordering_None, IdTable::Viewing_Id), UniversalId::Type_Cells, UniversalId::Type_Cell);
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables, addModel (new IdTable (&mReferenceables, IdTable::Reordering_None, IdTable::Viewing_None, true),
UniversalId::Type_Referenceable); UniversalId::Type_Referenceables, UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs, IdTable::Reordering_None, IdTable::Viewing_Cell), UniversalId::Type_References, UniversalId::Type_Reference, false); addModel (new IdTable (&mRefs, IdTable::Reordering_None, IdTable::Viewing_Cell, true), UniversalId::Type_References, UniversalId::Type_Reference, false);
addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false); addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false);
} }

View File

@ -5,8 +5,8 @@
#include "columnbase.hpp" #include "columnbase.hpp"
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, Reordering reordering, CSMWorld::IdTable::IdTable (CollectionBase *idCollection, Reordering reordering,
Viewing viewing) Viewing viewing, bool preview)
: mIdCollection (idCollection), mReordering (reordering), mViewing (viewing) : mIdCollection (idCollection), mReordering (reordering), mViewing (viewing), mPreview (preview)
{} {}
CSMWorld::IdTable::~IdTable() CSMWorld::IdTable::~IdTable()
@ -196,6 +196,11 @@ CSMWorld::IdTable::Viewing CSMWorld::IdTable::getViewing() const
return mViewing; return mViewing;
} }
bool CSMWorld::IdTable::hasPreview() const
{
return mPreview;
}
std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row) const std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row) const
{ {
std::string id; std::string id;
@ -231,3 +236,8 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row)
return std::make_pair (UniversalId (UniversalId::Type_Scene, id), hint); return std::make_pair (UniversalId (UniversalId::Type_Scene, id), hint);
} }
int CSMWorld::IdTable::getColumnId(int column) const
{
return mIdCollection->getColumn(column).getId();
}

View File

@ -39,6 +39,7 @@ namespace CSMWorld
CollectionBase *mIdCollection; CollectionBase *mIdCollection;
Reordering mReordering; Reordering mReordering;
Viewing mViewing; Viewing mViewing;
bool mPreview;
// not implemented // not implemented
IdTable (const IdTable&); IdTable (const IdTable&);
@ -47,7 +48,7 @@ namespace CSMWorld
public: public:
IdTable (CollectionBase *idCollection, Reordering reordering = Reordering_None, IdTable (CollectionBase *idCollection, Reordering reordering = Reordering_None,
Viewing viewing = Viewing_None); Viewing viewing = Viewing_None, bool preview = false);
///< The ownership of \a idCollection is not transferred. ///< The ownership of \a idCollection is not transferred.
virtual ~IdTable(); virtual ~IdTable();
@ -100,9 +101,13 @@ namespace CSMWorld
Viewing getViewing() const; Viewing getViewing() const;
bool hasPreview() const;
std::pair<UniversalId, std::string> view (int row) const; std::pair<UniversalId, std::string> view (int row) const;
///< Return the UniversalId and the hint for viewing \a row. If viewing is not ///< Return the UniversalId and the hint for viewing \a row. If viewing is not
/// supported by this table, return (UniversalId::Type_None, ""). /// supported by this table, return (UniversalId::Type_None, "").
int getColumnId(int column) const;
}; };
} }

View File

@ -444,3 +444,8 @@ CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (CSMWorld::U
return CSMWorld::ColumnBase::Display_None; return CSMWorld::ColumnBase::Display_None;
} }
} }
const CSMDoc::Document* CSMWorld::TableMimeData::getDocumentPtr() const
{
return &mDocument;
}

View File

@ -48,6 +48,8 @@ namespace CSMWorld
UniversalId returnMatching(UniversalId::Type type) const; UniversalId returnMatching(UniversalId::Type type) const;
const CSMDoc::Document* getDocumentPtr() const;
UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const; UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const;
static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type); static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type);

View File

@ -92,6 +92,8 @@ namespace
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" }, { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" },
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 }, { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 },
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
}; };

View File

@ -95,7 +95,8 @@ namespace CSMWorld
Type_TopicInfo, Type_TopicInfo,
Type_JournalInfos, Type_JournalInfos,
Type_JournalInfo, Type_JournalInfo,
Type_Scene Type_Scene,
Type_Preview
}; };
enum { NumberOfTypes = Type_Scene+1 }; enum { NumberOfTypes = Type_Scene+1 };

View File

@ -19,3 +19,9 @@ void CSVDoc::SubView::updateEditorSetting (const QString &settingName, const QSt
void CSVDoc::SubView::setStatusBar (bool show) {} void CSVDoc::SubView::setStatusBar (bool show) {}
void CSVDoc::SubView::useHint (const std::string& hint) {} void CSVDoc::SubView::useHint (const std::string& hint) {}
void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id)
{
mUniversalId = id;
setWindowTitle (mUniversalId.toString().c_str());
}

View File

@ -27,6 +27,8 @@ namespace CSVDoc
// not implemented // not implemented
SubView (const SubView&); SubView (const SubView&);
SubView& operator= (SubView&); SubView& operator= (SubView&);
protected:
void setUniversalId(const CSMWorld::UniversalId& id);
public: public:

View File

@ -316,8 +316,16 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
/// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis) /// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis)
SubView *view = mSubViewFactory.makeSubView (id, *mDocument); const std::vector<CSMWorld::UniversalId::Type> referenceables(CSMWorld::UniversalId::listReferenceableTypes());
SubView *view = NULL;
if(std::find(referenceables.begin(), referenceables.end(), id.getType()) != referenceables.end())
{
view = mSubViewFactory.makeSubView (CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Referenceable, id.getId()), *mDocument);
} else
{
view = mSubViewFactory.makeSubView (id, *mDocument);
}
assert(view);
if (!hint.empty()) if (!hint.empty())
view->useHint (hint); view->useHint (hint);

View File

@ -0,0 +1,72 @@
#include "previewwidget.hpp"
#include <OgreSceneManager.h>
#include "../../model/world/data.hpp"
void CSVRender::PreviewWidget::setup (const std::string& id)
{
setNavigation (&mOrbit);
int column = mData.getReferenceables().findColumnIndex (CSMWorld::Columns::ColumnId_Model);
int row = mData.getReferenceables().getIndex (id);
QVariant value = mData.getReferenceables().getData (row, column);
if (!value.isValid())
return;
std::string model = value.toString().toUtf8().constData();
if (model.empty())
return;
mNode = getSceneManager()->getRootSceneNode()->createChildSceneNode();
mNode->setPosition (Ogre::Vector3 (0, 0, 0));
mObject = NifOgre::Loader::createObjects (mNode, "Meshes\\" + model);
}
void CSVRender::PreviewWidget::adjust (const std::string& id)
{
if (mNode)
{
int row = mData.getReferences().getIndex (id);
float scale = mData.getReferences().getData (row, mData.getReferences().
findColumnIndex (CSMWorld::Columns::ColumnId_Scale)).toFloat();
float rotX = mData.getReferences().getData (row, mData.getReferences().
findColumnIndex (CSMWorld::Columns::ColumnId_PositionXRot)).toFloat();
float rotY = mData.getReferences().getData (row, mData.getReferences().
findColumnIndex (CSMWorld::Columns::ColumnId_PositionYRot)).toFloat();
float rotZ = mData.getReferences().getData (row, mData.getReferences().
findColumnIndex (CSMWorld::Columns::ColumnId_PositionZRot)).toFloat();
mNode->setScale (scale, scale, scale);
Ogre::Quaternion xr (Ogre::Radian(-rotX), Ogre::Vector3::UNIT_X);
Ogre::Quaternion yr (Ogre::Radian(-rotY), Ogre::Vector3::UNIT_Y);
Ogre::Quaternion zr (Ogre::Radian(-rotZ), Ogre::Vector3::UNIT_Z);
mNode->setOrientation (xr*yr*zr);
}
}
CSVRender::PreviewWidget::PreviewWidget (const CSMWorld::Data& data,
const std::string& referenceableId, QWidget *parent)
: SceneWidget (parent), mData (data), mNode (0)
{
setup (referenceableId);
}
CSVRender::PreviewWidget::PreviewWidget (const CSMWorld::Data& data,
const std::string& referenceableId, const std::string& referenceId, QWidget *parent)
: SceneWidget (parent), mData (data)
{
setup (referenceableId);
adjust (referenceId);
}

View File

@ -0,0 +1,46 @@
#ifndef OPENCS_VIEW_PREVIEWWIDGET_H
#define OPENCS_VIEW_PREVIEWWIDGET_H
#include <components/nifogre/ogrenifloader.hpp>
#include "scenewidget.hpp"
#include "navigationorbit.hpp"
namespace CSMWorld
{
class Data;
}
namespace CSVRender
{
class PreviewWidget : public SceneWidget
{
Q_OBJECT
const CSMWorld::Data& mData;
CSVRender::NavigationOrbit mOrbit;
NifOgre::ObjectScenePtr mObject;
Ogre::SceneNode *mNode;
void setup (const std::string& id);
///< \param id ID of the referenceable to be viewed
void adjust (const std::string& id);
///< \param id ID of the reference to be viewed
public:
PreviewWidget (const CSMWorld::Data& data, const std::string& referenceableId,
QWidget *parent = 0);
PreviewWidget (const CSMWorld::Data& data, const std::string& referenceableId,
const std::string& referenceId, QWidget *parent = 0);
signals:
void closeRequest();
};
}
#endif

View File

@ -45,15 +45,10 @@ namespace CSVRender
mCamera = mSceneMgr->createCamera("foo"); mCamera = mSceneMgr->createCamera("foo");
Ogre::Entity* ent = mSceneMgr->createEntity("cube", Ogre::SceneManager::PT_CUBE); mCamera->setPosition(300,0,000);
ent->setMaterialName("BaseWhite");
mSceneMgr->getRootSceneNode()->attachObject(ent);
mCamera->setPosition(300,300,300);
mCamera->lookAt(0,0,0); mCamera->lookAt(0,0,0);
mCamera->setNearClipDistance(0.1); mCamera->setNearClipDistance(0.1);
mCamera->setFarClipDistance(3000); mCamera->setFarClipDistance(30000);
QTimer *timer = new QTimer (this); QTimer *timer = new QTimer (this);
@ -118,6 +113,11 @@ namespace CSVRender
} }
} }
Ogre::SceneManager *SceneWidget::getSceneManager()
{
return mSceneMgr;
}
void SceneWidget::paintEvent(QPaintEvent* e) void SceneWidget::paintEvent(QPaintEvent* e)
{ {
if (!mWindow) if (!mWindow)

View File

@ -34,6 +34,8 @@ namespace CSVRender
void setNavigation (Navigation *navigation); void setNavigation (Navigation *navigation);
///< \attention The ownership of \a navigation is not transferred to *this. ///< \attention The ownership of \a navigation is not transferred to *this.
Ogre::SceneManager *getSceneManager();
private: private:
void paintEvent(QPaintEvent* e); void paintEvent(QPaintEvent* e);
void resizeEvent(QResizeEvent* e); void resizeEvent(QResizeEvent* e);

View File

@ -1,11 +1,20 @@
#include "worldspacewidget.hpp" #include "worldspacewidget.hpp"
#include <OgreSceneNode.h>
#include <OgreSceneManager.h>
#include <OgreEntity.h>
#include "../world/scenetoolmode.hpp" #include "../world/scenetoolmode.hpp"
CSVRender::WorldspaceWidget::WorldspaceWidget (QWidget *parent) CSVRender::WorldspaceWidget::WorldspaceWidget (QWidget *parent)
: SceneWidget (parent) : SceneWidget (parent)
{} {
Ogre::Entity* ent = getSceneManager()->createEntity("cube", Ogre::SceneManager::PT_CUBE);
ent->setMaterialName("BaseWhite");
getSceneManager()->getRootSceneNode()->attachObject(ent);
}
void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode) void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
{ {

View File

@ -1,98 +1,663 @@
#include "dialoguesubview.hpp" #include "dialoguesubview.hpp"
#include <utility>
#include <memory>
#include <QGridLayout> #include <QGridLayout>
#include <QLabel> #include <QLabel>
#include <QSize>
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QSpinBox> #include <QSpinBox>
#include <QLineEdit> #include <QLineEdit>
#include <QEvent>
#include <QDataWidgetMapper> #include <QDataWidgetMapper>
#include <QCheckBox>
#include <QLineEdit>
#include <QPlainTextEdit>
#include <QComboBox>
#include <QScrollArea>
#include <QPushButton>
#include <QToolButton>
#include "../../model/world/columnbase.hpp" #include "../../model/world/columnbase.hpp"
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
#include "../../model/world/columns.hpp"
#include "../../model/world/record.hpp"
#include "../../model/world/tablemimedata.hpp"
#include "../../model/doc/document.hpp"
#include "../../model/world/commands.hpp"
CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, #include "recordstatusdelegate.hpp"
bool createAndDelete) #include "util.hpp"
: SubView (id) #include "tablebottombox.hpp"
/*
==============================NotEditableSubDelegate==========================================
*/
CSVWorld::NotEditableSubDelegate::NotEditableSubDelegate(const CSMWorld::IdTable* table, QObject * parent) :
QAbstractItemDelegate(parent),
mTable(table)
{}
void CSVWorld::NotEditableSubDelegate::setEditorData (QLabel* editor, const QModelIndex& index) const
{ {
QWidget *widget = new QWidget (this); QVariant v = index.data(Qt::EditRole);
if (!v.isValid())
{
v = index.data(Qt::DisplayRole);
if (!v.isValid())
{
return;
}
}
setWidget (widget); if (QVariant::String == v.type())
{
editor->setText(v.toString());
} else //else we are facing enums
{
int data = v.toInt();
std::vector<std::string> enumNames (CSMWorld::Columns::getEnums (static_cast<CSMWorld::Columns::ColumnId> (mTable->getColumnId (index.column()))));
editor->setText(QString::fromUtf8(enumNames.at(data).c_str()));
}
}
QGridLayout *layout = new QGridLayout; void CSVWorld::NotEditableSubDelegate::setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const
{
//not editable widgets will not save model data
}
widget->setLayout (layout); void CSVWorld::NotEditableSubDelegate::paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
//does nothing
}
QAbstractItemModel *model = document.getData().getTableModel (id); QSize CSVWorld::NotEditableSubDelegate::sizeHint (const QStyleOptionViewItem& option, const QModelIndex& index) const
{
return QSize();
}
int columns = model->columnCount(); QWidget* CSVWorld::NotEditableSubDelegate::createEditor (QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& index,
CSMWorld::ColumnBase::Display display) const
{
return new QLabel(parent);
}
/*
==============================DialogueDelegateDispatcherProxy==========================================
*/
CSVWorld::DialogueDelegateDispatcherProxy::refWrapper::refWrapper(const QModelIndex& index) :
mIndex(index)
{}
CSVWorld::DialogueDelegateDispatcherProxy::DialogueDelegateDispatcherProxy(QWidget* editor, CSMWorld::ColumnBase::Display display) :
mEditor(editor),
mDisplay(display),
mIndexWrapper(NULL)
{
}
void CSVWorld::DialogueDelegateDispatcherProxy::editorDataCommited()
{
if (mIndexWrapper.get())
{
emit editorDataCommited(mEditor, mIndexWrapper->mIndex, mDisplay);
}
}
void CSVWorld::DialogueDelegateDispatcherProxy::setIndex(const QModelIndex& index)
{
mIndexWrapper.reset(new refWrapper(index));
}
QWidget* CSVWorld::DialogueDelegateDispatcherProxy::getEditor() const
{
return mEditor;
}
void CSVWorld::DialogueDelegateDispatcherProxy::tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>& data, const CSMDoc::Document* document)
{
QLineEdit* lineEdit = qobject_cast<QLineEdit*>(mEditor);
{
if (!lineEdit or !mIndexWrapper.get())
{
return;
}
}
for (unsigned i = 0; i < data.size(); ++i)
{
if (mDisplay == CSMWorld::TableMimeData::convertEnums(data[i].getType()))
{
emit tableMimeDataDropped(mEditor, mIndexWrapper->mIndex, data[i], document);
emit editorDataCommited(mEditor, mIndexWrapper->mIndex, mDisplay);
break;
}
}
}
/*
==============================DialogueDelegateDispatcher==========================================
*/
CSVWorld::DialogueDelegateDispatcher::DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, QUndoStack& undoStack) :
mParent(parent),
mTable(table),
mUndoStack(undoStack),
mNotEditableDelegate(table, parent)
{
}
CSVWorld::CommandDelegate* CSVWorld::DialogueDelegateDispatcher::makeDelegate(CSMWorld::ColumnBase::Display display)
{
CommandDelegate *delegate = NULL;
std::map<int, CommandDelegate*>::const_iterator delegateIt(mDelegates.find(display));
if (delegateIt == mDelegates.end())
{
delegate = CommandDelegateFactoryCollection::get().makeDelegate (
display, mUndoStack, mParent);
mDelegates.insert(std::make_pair<int, CommandDelegate*>(display, delegate));
} else
{
delegate = delegateIt->second;
}
return delegate;
}
void CSVWorld::DialogueDelegateDispatcher::editorDataCommited(QWidget* editor, const QModelIndex& index, CSMWorld::ColumnBase::Display display)
{
setModelData(editor, mTable, index, display);
}
void CSVWorld::DialogueDelegateDispatcher::setEditorData (QWidget* editor, const QModelIndex& index) const
{
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
(mTable->headerData (index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
QLabel* label = qobject_cast<QLabel*>(editor);
if(label)
{
mNotEditableDelegate.setEditorData(label, index);
return;
}
std::map<int, CommandDelegate*>::const_iterator delegateIt(mDelegates.find(display));
if (delegateIt != mDelegates.end())
{
delegateIt->second->setEditorData(editor, index, true);
}
for (unsigned i = 0; i < mProxys.size(); ++i)
{
if (mProxys[i]->getEditor() == editor)
{
mProxys[i]->setIndex(index);
}
}
}
void CSVWorld::DialogueDelegateDispatcher::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const
{
std::map<int, CommandDelegate*>::const_iterator delegateIt(mDelegates.find(display));
if (delegateIt != mDelegates.end())
{
delegateIt->second->setModelData(editor, model, index);
}
}
void CSVWorld::DialogueDelegateDispatcher::paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
//Does nothing
}
QSize CSVWorld::DialogueDelegateDispatcher::sizeHint (const QStyleOptionViewItem& option, const QModelIndex& index) const
{
return QSize(); //silencing warning, otherwise does nothing
}
QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::Display display, const QModelIndex& index)
{
QVariant variant = index.data();
if (!variant.isValid())
{
variant = index.data(Qt::DisplayRole);
if (!variant.isValid())
{
return NULL;
}
}
QWidget* editor = NULL;
if (! (mTable->flags (index) & Qt::ItemIsEditable))
{
return mNotEditableDelegate.createEditor(qobject_cast<QWidget*>(mParent), QStyleOptionViewItem(), index, display);
}
std::map<int, CommandDelegate*>::iterator delegateIt(mDelegates.find(display));
if (delegateIt != mDelegates.end())
{
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()));
connect(editor, SIGNAL(tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>&, const CSMDoc::Document*)),
proxy, SLOT(tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>&, const CSMDoc::Document*)));
connect(proxy, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)),
this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
skip = true;
}
if(!skip && qobject_cast<QCheckBox*>(editor))
{
connect(editor, SIGNAL(stateChanged(int)), proxy, SLOT(editorDataCommited()));
skip = true;
}
if(!skip && qobject_cast<QPlainTextEdit*>(editor))
{
connect(editor, SIGNAL(textChanged()), proxy, SLOT(editorDataCommited()));
skip = true;
}
if(!skip && qobject_cast<QComboBox*>(editor))
{
connect(editor, SIGNAL(currentIndexChanged (int)), proxy, SLOT(editorDataCommited()));
skip = true;
}
if(!skip && 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)));
mProxys.push_back(proxy); //deleted in the destructor
}
return editor;
}
CSVWorld::DialogueDelegateDispatcher::~DialogueDelegateDispatcher()
{
for (unsigned i = 0; i < mProxys.size(); ++i)
{
delete mProxys[i]; //unique_ptr could be handy
}
}
/*
=============================================================EditWidget=====================================================
*/
CSVWorld::EditWidget::EditWidget(QWidget *parent, int row, CSMWorld::IdTable* table, QUndoStack& undoStack, bool createAndDelete) :
mDispatcher(this, table, undoStack),
QScrollArea(parent),
mWidgetMapper(NULL),
mMainWidget(NULL),
mUndoStack(undoStack),
mTable(table)
{
remake (row);
connect(&mDispatcher, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
}
void CSVWorld::EditWidget::remake(int row)
{
if (mMainWidget)
{
delete mMainWidget;
}
mMainWidget = new QWidget (this);
//not sure if widget mapper can handle deleting the widgets that were mapped
if (mWidgetMapper)
{
delete mWidgetMapper;
}
mWidgetMapper = new QDataWidgetMapper (this); mWidgetMapper = new QDataWidgetMapper (this);
mWidgetMapper->setModel (model); mWidgetMapper->setModel(mTable);
mWidgetMapper->setItemDelegate(&mDispatcher);
QFrame* line = new QFrame(mMainWidget);
line->setObjectName(QString::fromUtf8("line"));
line->setGeometry(QRect(320, 150, 118, 3));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
QVBoxLayout *mainLayout = new QVBoxLayout(mMainWidget);
QGridLayout *unlockedLayout = new QGridLayout();
QGridLayout *lockedLayout = new QGridLayout();
mainLayout->addLayout(lockedLayout, 0);
mainLayout->addWidget(line, 1);
mainLayout->addLayout(unlockedLayout, 2);
mainLayout->addStretch(1);
int unlocked = 0;
int locked = 0;
const int columns = mTable->columnCount();
for (int i=0; i<columns; ++i) for (int i=0; i<columns; ++i)
{ {
int flags = model->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); int flags = mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt();
if (flags & CSMWorld::ColumnBase::Flag_Dialogue) if (flags & CSMWorld::ColumnBase::Flag_Dialogue)
{ {
layout->addWidget (new QLabel (model->headerData (i, Qt::Horizontal).toString()), i, 0);
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display> CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
(model->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); (mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
QWidget *widget = 0; mDispatcher.makeDelegate(display);
QWidget *editor = mDispatcher.makeEditor(display, (mTable->index (row, i)));
if (model->flags (model->index (0, i)) & Qt::ItemIsEditable) if (editor)
{ {
switch (display) mWidgetMapper->addMapping (editor, i);
QLabel* label = new QLabel(mTable->headerData (i, Qt::Horizontal).toString(), mMainWidget);
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
editor->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
if (! (mTable->flags (mTable->index (row, i)) & Qt::ItemIsEditable))
{ {
case CSMWorld::ColumnBase::Display_String: lockedLayout->addWidget (label, locked, 0);
lockedLayout->addWidget (editor, locked, 1);
layout->addWidget (widget = new QLineEdit, i, 1); ++locked;
break; } else
case CSMWorld::ColumnBase::Display_Integer:
/// \todo configure widget properly (range)
layout->addWidget (widget = new QSpinBox, i, 1);
break;
case CSMWorld::ColumnBase::Display_Float:
/// \todo configure widget properly (range, format?)
layout->addWidget (widget = new QDoubleSpinBox, i, 1);
break;
default: break; // silence warnings for other times for now
}
}
else
{ {
switch (display) unlockedLayout->addWidget (label, unlocked, 0);
unlockedLayout->addWidget (editor, unlocked, 1);
++unlocked;
}
}
}
}
mWidgetMapper->setCurrentModelIndex(mTable->index(row, 0));
this->setMinimumWidth(325); //TODO find better way to set the width or make it customizable
this->setWidget(mMainWidget);
this->setWidgetResizable(true);
}
/*
==============================DialogueSubView==========================================
*/
CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory, bool sorting) :
SubView (id),
mEditWidget(0),
mMainLayout(NULL),
mUndoStack(document.getUndoStack()),
mTable(dynamic_cast<CSMWorld::IdTable*>(document.getData().getTableModel(id))),
mRow (-1),
mLocked(false),
mDocument(document)
{ {
case CSMWorld::ColumnBase::Display_String: connect(mTable, SIGNAL(dataChanged (const QModelIndex&, const QModelIndex&)), this, SLOT(dataChanged(const QModelIndex&)));
case CSMWorld::ColumnBase::Display_Integer: mRow = mTable->getModelIndex (id.getId(), 0).row();
case CSMWorld::ColumnBase::Display_Float: QWidget *mainWidget = new QWidget(this);
layout->addWidget (widget = new QLabel, i, 1); QHBoxLayout *buttonsLayout = new QHBoxLayout;
break; QToolButton* prevButton = new QToolButton(mainWidget);
prevButton->setIcon(QIcon(":/go-previous.png"));
QToolButton* nextButton = new QToolButton(mainWidget);
nextButton->setIcon(QIcon(":/go-next.png"));
buttonsLayout->addWidget(prevButton, 0);
buttonsLayout->addWidget(nextButton, 1);
buttonsLayout->addStretch(2);
default: break; // silence warnings for other times for now QToolButton* cloneButton = new QToolButton(mainWidget);
cloneButton->setIcon(QIcon(":/edit-clone.png"));
QToolButton* addButton = new QToolButton(mainWidget);
addButton->setIcon(QIcon(":/add.png"));
QToolButton* deleteButton = new QToolButton(mainWidget);
deleteButton->setIcon(QIcon(":/edit-delete.png"));
QToolButton* revertButton = new QToolButton(mainWidget);
revertButton->setIcon(QIcon(":/edit-undo.png"));
if (mTable->hasPreview())
{
QToolButton* previewButton = new QToolButton(mainWidget);
previewButton->setIcon(QIcon(":/edit-preview.png"));
buttonsLayout->addWidget(previewButton);
connect(previewButton, SIGNAL(clicked()), this, SLOT(showPreview()));
}
if (mTable->getViewing()!=CSMWorld::IdTable::Viewing_None)
{
QToolButton* viewButton = new QToolButton(mainWidget);
viewButton->setIcon(QIcon(":/cell.png"));
buttonsLayout->addWidget(viewButton);
connect(viewButton, SIGNAL(clicked()), this, SLOT(viewRecord()));
}
buttonsLayout->addWidget(cloneButton);
buttonsLayout->addWidget(addButton);
buttonsLayout->addWidget(deleteButton);
buttonsLayout->addWidget(revertButton);
connect(nextButton, SIGNAL(clicked()), this, SLOT(nextId()));
connect(prevButton, SIGNAL(clicked()), this, SLOT(prevId()));
connect(cloneButton, SIGNAL(clicked()), this, SLOT(cloneRequest()));
connect(revertButton, SIGNAL(clicked()), this, SLOT(revertRecord()));
connect(deleteButton, SIGNAL(clicked()), this, SLOT(deleteRecord()));
mMainLayout = new QVBoxLayout(mainWidget);
mEditWidget = new EditWidget(mainWidget, mRow, mTable, mUndoStack, false);
connect(mEditWidget, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)),
this, SLOT(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
mMainLayout->addWidget(mEditWidget);
mEditWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
mMainLayout->addWidget (mBottom =
new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this));
mBottom->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
connect(mBottom, SIGNAL(requestFocus(const std::string&)), this, SLOT(requestFocus(const std::string&)));
connect(addButton, SIGNAL(clicked()), mBottom, SLOT(createRequest()));
if(!mBottom->canCreateAndDelete())
{
cloneButton->setDisabled(true);
addButton->setDisabled(true);
deleteButton->setDisabled(true);
}
dataChanged(mTable->index(mRow, 0));
mMainLayout->addLayout(buttonsLayout);
setWidget(mainWidget);
}
void CSVWorld::DialogueSubView::prevId()
{
int newRow = mRow - 1;
if (newRow < 0)
{
return;
}
while (newRow >= 0)
{
QModelIndex newIndex(mTable->index(newRow, 0));
if (!newIndex.isValid())
{
return;
}
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (newRow, 1)).toInt());
if (!(state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased))
{
mEditWidget->remake(newRow);
setUniversalId(CSMWorld::UniversalId (static_cast<CSMWorld::UniversalId::Type> (mTable->data (mTable->index (newRow, 2)).toInt()),
mTable->data (mTable->index (newRow, 0)).toString().toStdString()));
mRow = newRow;
mEditWidget->setDisabled(mLocked);
return;
}
--newRow;
} }
} }
if (widget) void CSVWorld::DialogueSubView::nextId()
mWidgetMapper->addMapping (widget, i); {
} int newRow = mRow + 1;
if (newRow >= mTable->rowCount())
{
return;
} }
mWidgetMapper->setCurrentModelIndex ( while (newRow < mTable->rowCount())
dynamic_cast<CSMWorld::IdTable&> (*model).getModelIndex (id.getId(), 0)); {
QModelIndex newIndex(mTable->index(newRow, 0));
if (!newIndex.isValid())
{
return;
}
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (newRow, 1)).toInt());
if (!(state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased))
{
mEditWidget->remake(newRow);
setUniversalId(CSMWorld::UniversalId (static_cast<CSMWorld::UniversalId::Type> (mTable->data (mTable->index (newRow, 2)).toInt()),
mTable->data (mTable->index (newRow, 0)).toString().toStdString()));
mRow = newRow;
mEditWidget->setDisabled(mLocked);
return;
}
++newRow;
}
} }
void CSVWorld::DialogueSubView::setEditLock (bool locked) void CSVWorld::DialogueSubView::setEditLock (bool locked)
{ {
mLocked = locked;
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (mRow, 1)).toInt());
if (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased)
{
mEditWidget->setDisabled(true);
} else
{
mEditWidget->setDisabled(mLocked);
}
}
void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index)
{
if (index.row() == mRow)
{
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (mRow, 1)).toInt());
if (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased)
{
mEditWidget->setDisabled(true);
} else
{
mEditWidget->setDisabled(mLocked);
}
}
}
void CSVWorld::DialogueSubView::tableMimeDataDropped(QWidget* editor,
const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document)
{
if (document == &mDocument)
{
qobject_cast<DropLineEdit*>(editor)->setText(id.getId().c_str());
}
}
void CSVWorld::DialogueSubView::revertRecord()
{
int rows = mTable->rowCount();
if (!mLocked && mTable->columnCount() > 0 && mRow < mTable->rowCount() )
{
CSMWorld::RecordBase::State state =
static_cast<CSMWorld::RecordBase::State> (mTable->data (mTable->index (mRow, 1)).toInt());
if (state!=CSMWorld::RecordBase::State_BaseOnly)
{
mUndoStack.push(new CSMWorld::RevertCommand(*mTable, mTable->data(mTable->index (mRow, 0)).toString().toStdString()));
}
if (rows != mTable->rowCount())
{
if (mTable->rowCount() == 0)
{
mEditWidget->setDisabled(true); //closing the editor is other option
return;
}
if (mRow >= mTable->rowCount())
{
prevId();
} else {
dataChanged(mTable->index(mRow, 0));
}
}
}
}
void CSVWorld::DialogueSubView::deleteRecord()
{
int rows = mTable->rowCount();
//easier than disabling the button
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (mRow, 1)).toInt());
bool deledetedOrErased = (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased);
if (!mLocked &&
mTable->columnCount() > 0 &&
!deledetedOrErased &&
mRow < rows &&
mBottom->canCreateAndDelete())
{
mUndoStack.push(new CSMWorld::DeleteCommand(*mTable, mTable->data(mTable->index (mRow, 0)).toString().toStdString()));
if (rows != mTable->rowCount())
{
if (mTable->rowCount() == 0)
{
mEditWidget->setDisabled(true); //closing the editor is other option
return;
}
if (mRow >= mTable->rowCount())
{
prevId();
} else {
dataChanged(mTable->index(mRow, 0));
}
}
}
}
void CSVWorld::DialogueSubView::requestFocus (const std::string& id)
{
mRow = mTable->getModelIndex (id, 0).row();
mEditWidget->remake(mRow);
}
void CSVWorld::DialogueSubView::cloneRequest ()
{
mBottom->cloneRequest(mTable->data(mTable->index (mRow, 0)).toString().toStdString(),
static_cast<CSMWorld::UniversalId::Type>(mTable->data(mTable->index(mRow, 2)).toInt()));
}
void CSVWorld::DialogueSubView::showPreview ()
{
if (mTable->hasPreview() && mRow < mTable->rowCount())
{
emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, mTable->data(mTable->index (mRow, 0)).toString().toStdString()), "");
}
}
void CSVWorld::DialogueSubView::viewRecord()
{
if (mRow < mTable->rowCount())
{
std::pair<CSMWorld::UniversalId, std::string> params = mTable->view (mRow);
if (params.first.getType()!=CSMWorld::UniversalId::Type_None)
emit focusId (params.first, params.second);
}
} }

View File

@ -1,9 +1,25 @@
#ifndef CSV_WORLD_DIALOGUESUBVIEW_H #ifndef CSV_WORLD_DIALOGUESUBVIEW_H
#define CSV_WORLD_DIALOGUESUBVIEW_H #define CSV_WORLD_DIALOGUESUBVIEW_H
#include <map>
#include <memory>
#include <QAbstractItemDelegate>
#include <QScrollArea>
#include "../doc/subview.hpp" #include "../doc/subview.hpp"
#include "../../model/world/columnbase.hpp"
class QDataWidgetMapper; class QDataWidgetMapper;
class QSize;
class QEvent;
class QLabel;
class QVBoxLayout;
namespace CSMWorld
{
class IdTable;
}
namespace CSMDoc namespace CSMDoc
{ {
@ -12,15 +28,181 @@ namespace CSMDoc
namespace CSVWorld namespace CSVWorld
{ {
class DialogueSubView : public CSVDoc::SubView class CommandDelegate;
class CreatorFactoryBase;
class TableBottomBox;
class NotEditableSubDelegate : public QAbstractItemDelegate
{ {
const CSMWorld::IdTable* mTable;
public:
NotEditableSubDelegate(const CSMWorld::IdTable* table, QObject * parent = 0);
virtual void setEditorData (QLabel* editor, const QModelIndex& index) const;
virtual void setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const;
virtual void paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
///< does nothing
virtual QSize sizeHint (const QStyleOptionViewItem& option, const QModelIndex& index) const;
///< does nothing
virtual QWidget *createEditor (QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& index,
CSMWorld::ColumnBase::Display display = CSMWorld::ColumnBase::Display_None) const;
};
//this can't be nested into the DialogueDelegateDispatcher, because it needs to emit signals
class DialogueDelegateDispatcherProxy : public QObject
{
Q_OBJECT
class refWrapper
{
public:
refWrapper(const QModelIndex& index);
const QModelIndex& mIndex;
};
QWidget* mEditor;
CSMWorld::ColumnBase::Display mDisplay;
std::auto_ptr<refWrapper> mIndexWrapper;
public:
DialogueDelegateDispatcherProxy(QWidget* editor, CSMWorld::ColumnBase::Display display);
QWidget* getEditor() const;
public slots:
void editorDataCommited();
void setIndex(const QModelIndex& index);
void tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>& data, const CSMDoc::Document* document);
signals:
void editorDataCommited(QWidget* editor, const QModelIndex& index, CSMWorld::ColumnBase::Display display);
void tableMimeDataDropped(QWidget* editor, const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document);
};
class DialogueDelegateDispatcher : public QAbstractItemDelegate
{
Q_OBJECT
std::map<int, CommandDelegate*> mDelegates;
QObject* mParent;
CSMWorld::IdTable* mTable;
QUndoStack& mUndoStack;
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();
CSVWorld::CommandDelegate* makeDelegate(CSMWorld::ColumnBase::Display display);
QWidget* makeEditor(CSMWorld::ColumnBase::Display display, const QModelIndex& index);
///< will return null if delegate is not present, parent of the widget is same as for dispatcher itself
virtual void setEditorData (QWidget* editor, const QModelIndex& index) const;
virtual void setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const;
virtual void paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
///< does nothing
virtual QSize sizeHint (const QStyleOptionViewItem& option, const QModelIndex& index) const;
///< does nothing
private slots:
void editorDataCommited(QWidget* editor, const QModelIndex& index, CSMWorld::ColumnBase::Display display);
signals:
void tableMimeDataDropped(QWidget* editor, const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document);
};
class EditWidget : public QScrollArea
{
Q_OBJECT
QDataWidgetMapper *mWidgetMapper; QDataWidgetMapper *mWidgetMapper;
DialogueDelegateDispatcher mDispatcher;
QWidget* mMainWidget;
CSMWorld::IdTable* mTable;
QUndoStack& mUndoStack;
public: public:
DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete); EditWidget (QWidget *parent, int row, CSMWorld::IdTable* table, QUndoStack& undoStack, bool createAndDelete = false);
void remake(int row);
signals:
void tableMimeDataDropped(QWidget* editor, const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document);
};
class DialogueSubView : public CSVDoc::SubView
{
Q_OBJECT
EditWidget* mEditWidget;
QVBoxLayout* mMainLayout;
CSMWorld::IdTable* mTable;
QUndoStack& mUndoStack;
int mRow;
bool mLocked;
const CSMDoc::Document& mDocument;
TableBottomBox* mBottom;
public:
DialogueSubView (const CSMWorld::UniversalId& id,
CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory,
bool sorting = false);
virtual void setEditLock (bool locked); virtual void setEditLock (bool locked);
private slots:
void nextId();
void prevId();
void showPreview();
void viewRecord();
void revertRecord();
void deleteRecord();
void cloneRequest();
void dataChanged(const QModelIndex & index);
///\brief we need to care for deleting currently edited record
void tableMimeDataDropped(QWidget* editor, const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document);
void requestFocus (const std::string& id);
}; };
} }

View File

@ -41,10 +41,18 @@ CSVWorld::EnumDelegate::EnumDelegate (const std::vector<std::pair<int, QString>
} }
QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option, QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& index) const const QModelIndex& index) const
{ {
if (!index.data().isValid()) return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_None);
//overloading virtual functions is HARD
}
QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index, CSMWorld::ColumnBase::Display display) const
{
if (!index.data(Qt::EditRole).isValid() && !index.data(Qt::DisplayRole).isValid())
return 0; return 0;
QComboBox *comboBox = new QComboBox (parent); QComboBox *comboBox = new QComboBox (parent);
@ -56,11 +64,22 @@ QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptio
return comboBox; return comboBox;
} }
void CSVWorld::EnumDelegate::setEditorData (QWidget *editor, const QModelIndex& index) const void CSVWorld::EnumDelegate::setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay) const
{ {
if (QComboBox *comboBox = dynamic_cast<QComboBox *> (editor)) if (QComboBox *comboBox = dynamic_cast<QComboBox *> (editor))
{ {
int value = index.data (Qt::EditRole).toInt(); QVariant data = index.data (Qt::EditRole);
if (tryDisplay && !data.isValid())
{
data = index.data (Qt::DisplayRole);
if (!data.isValid())
{
return;
}
}
int value = data.toInt();
std::size_t size = mValues.size(); std::size_t size = mValues.size();

View File

@ -4,6 +4,7 @@
#include <vector> #include <vector>
#include <QString> #include <QString>
#include <QStyledItemDelegate>
#include <components/esm/defs.hpp> #include <components/esm/defs.hpp>
@ -31,10 +32,16 @@ namespace CSVWorld
EnumDelegate (const std::vector<std::pair<int, QString> >& values, EnumDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent); QUndoStack& undoStack, QObject *parent);
virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem& option, virtual QWidget *createEditor(QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& index) const; const QModelIndex& index) const;
virtual void setEditorData (QWidget *editor, const QModelIndex& index) const; virtual QWidget *createEditor(QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& index,
CSMWorld::ColumnBase::Display display = CSMWorld::ColumnBase::Display_None) const;
virtual void setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay = false) const;
virtual void paint (QPainter *painter, const QStyleOptionViewItem& option, virtual void paint (QPainter *painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const; const QModelIndex& index) const;

View File

@ -0,0 +1,52 @@
#include "previewsubview.hpp"
#include <QHBoxLayout>
#include "../render/scenewidget.hpp"
#include "scenetoolbar.hpp"
#include "../render/previewwidget.hpp"
CSVWorld::PreviewSubView::PreviewSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
: SubView (id)
{
QHBoxLayout *layout = new QHBoxLayout;
layout->setContentsMargins (QMargins (0, 0, 0, 0));
if (document.getData().getReferenceables().searchId (id.getId())==-1)
{
std::string referenceableId =
document.getData().getReferences().getRecord (id.getId()).get().mRefID;
setWindowTitle (("Preview: Reference to " + referenceableId).c_str());
mScene =
new CSVRender::PreviewWidget (document.getData(), referenceableId, id.getId(), this);
}
else
mScene = new CSVRender::PreviewWidget (document.getData(), id.getId(), this);
SceneToolbar *toolbar = new SceneToolbar (48, this);
layout->addWidget (toolbar, 0);
layout->addWidget (mScene, 1);
QWidget *widget = new QWidget;
widget->setLayout (layout);
setWidget (widget);
connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest()));
}
void CSVWorld::PreviewSubView::setEditLock (bool locked) {}
void CSVWorld::PreviewSubView::closeRequest()
{
deleteLater();
}

View File

@ -0,0 +1,36 @@
#ifndef CSV_WORLD_PREVIEWSUBVIEW_H
#define CSV_WORLD_PREVIEWSUBVIEW_H
#include "../doc/subview.hpp"
namespace CSMDoc
{
class Document;
}
namespace CSVRender
{
class PreviewWidget;
}
namespace CSVWorld
{
class PreviewSubView : public CSVDoc::SubView
{
Q_OBJECT
CSVRender::PreviewWidget *mScene;
public:
PreviewSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document);
virtual void setEditLock (bool locked);
private slots:
void closeRequest();
};
}
#endif

View File

@ -34,7 +34,7 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D
SceneToolbar *toolbar = new SceneToolbar (48, this); SceneToolbar *toolbar = new SceneToolbar (48, this);
if (id.getId()[0]=='#') if (id.getId()=="sys::default")
mScene = new CSVRender::PagedWorldspaceWidget (this); mScene = new CSVRender::PagedWorldspaceWidget (this);
else else
mScene = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this); mScene = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this);

View File

@ -16,6 +16,7 @@
#include "scenesubview.hpp" #include "scenesubview.hpp"
#include "dialoguecreator.hpp" #include "dialoguecreator.hpp"
#include "infocreator.hpp" #include "infocreator.hpp"
#include "previewsubview.hpp"
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
{ {
@ -78,4 +79,62 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
CreatorFactory<CSVFilter::FilterCreator> >); CreatorFactory<CSVFilter::FilterCreator> >);
manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory<SceneSubView>); manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory<SceneSubView>);
//edit subviews
manager.add (CSMWorld::UniversalId::Type_Region,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Spell,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Referenceable,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<ReferenceableCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Birthsign,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Global,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Gmst,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Race,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Class,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Reference,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<ReferenceCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Cell,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<CellCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Filter,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Sound,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Faction,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Skill,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_JournalInfo,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<InfoCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_TopicInfo,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<InfoCreator> >(false));
manager.add (CSMWorld::UniversalId::Type_Topic,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, TopicCreatorFactory> (false));
manager.add (CSMWorld::UniversalId::Type_Journal,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, JournalCreatorFactory> (false));
//preview
manager.add (CSMWorld::UniversalId::Type_Preview, new CSVDoc::SubViewFactory<PreviewSubView>);
} }

View File

@ -39,18 +39,6 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
if (mCreateAction) if (mCreateAction)
menu.addAction(mCloneAction); menu.addAction(mCloneAction);
if (mModel->getViewing()!=CSMWorld::IdTable::Viewing_None)
{
int row = selectedRows.begin()->row();
row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row();
CSMWorld::UniversalId id = mModel->view (row).first;
if (!mDocument.getData().getCells().getRecord (id.getId()).isDeleted())
menu.addAction (mViewAction);
}
} }
if (mCreateAction) if (mCreateAction)
@ -95,6 +83,28 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
} }
} }
if (selectedRows.size()==1)
{
if (mModel->getViewing()!=CSMWorld::IdTable::Viewing_None)
{
int row = selectedRows.begin()->row();
row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row();
CSMWorld::UniversalId id = mModel->view (row).first;
int index = mDocument.getData().getCells().searchId (id.getId());
// index==-1: the ID references a worldspace instead of a cell (ignore for now and go
// ahead)
if (index==-1 || !mDocument.getData().getCells().getRecord (index).isDeleted())
menu.addAction (mViewAction);
}
if (mModel->hasPreview())
menu.addAction (mPreviewAction);
}
menu.exec (event->globalPos()); menu.exec (event->globalPos());
} }
@ -249,6 +259,10 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
connect (mViewAction, SIGNAL (triggered()), this, SLOT (viewRecord())); connect (mViewAction, SIGNAL (triggered()), this, SLOT (viewRecord()));
addAction (mViewAction); addAction (mViewAction);
mPreviewAction = new QAction (tr ("Preview"), this);
connect (mPreviewAction, SIGNAL (triggered()), this, SLOT (previewRecord()));
addAction (mPreviewAction);
connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)), connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (tableSizeUpdate())); this, SLOT (tableSizeUpdate()));
@ -417,6 +431,18 @@ void CSVWorld::Table::viewRecord()
} }
} }
void CSVWorld::Table::previewRecord()
{
QModelIndexList selectedRows = selectionModel()->selectedRows();
if (selectedRows.size()==1)
{
std::string id = getUniversalId (selectedRows.begin()->row()).getId();
emit editRequest (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Preview, id) , "");
}
}
void CSVWorld::Table::updateEditorSetting (const QString &settingName, const QString &settingValue) void CSVWorld::Table::updateEditorSetting (const QString &settingName, const QString &settingValue)
{ {
int columns = mModel->columnCount(); int columns = mModel->columnCount();
@ -508,20 +534,7 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event)
drag->setMimeData (mime); drag->setMimeData (mime);
drag->setPixmap (QString::fromStdString (mime->getIcon())); drag->setPixmap (QString::fromStdString (mime->getIcon()));
drag->exec(Qt::CopyAction);
Qt::DropActions action = Qt::IgnoreAction;
switch (QApplication::keyboardModifiers())
{
case Qt::ControlModifier:
action = Qt::CopyAction;
break;
case Qt::ShiftModifier:
action = Qt::MoveAction;
break;
}
drag->exec(action);
} }
} }

View File

@ -44,6 +44,7 @@ namespace CSVWorld
QAction *mMoveUpAction; QAction *mMoveUpAction;
QAction *mMoveDownAction; QAction *mMoveDownAction;
QAction *mViewAction; QAction *mViewAction;
QAction *mPreviewAction;
CSMWorld::IdTableProxyModel *mProxyModel; CSMWorld::IdTableProxyModel *mProxyModel;
CSMWorld::IdTable *mModel; CSMWorld::IdTable *mModel;
bool mEditLock; bool mEditLock;
@ -111,6 +112,8 @@ namespace CSVWorld
void viewRecord(); void viewRecord();
void previewRecord();
public slots: public slots:
void tableSizeUpdate(); void tableSizeUpdate();

View File

@ -4,8 +4,18 @@
#include <stdexcept> #include <stdexcept>
#include <QUndoStack> #include <QUndoStack>
#include <QMetaProperty>
#include <QStyledItemDelegate>
#include <QLineEdit>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QComboBox>
#include <QCheckBox>
#include <QPlainTextEdit>
#include <QEvent>
#include "../../model/world/commands.hpp" #include "../../model/world/commands.hpp"
#include "../../model/world/tablemimedata.hpp"
CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model) CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model)
: mModel (model) : mModel (model)
@ -117,10 +127,56 @@ void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemMode
} }
QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option, QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const const QModelIndex& index, CSMWorld::ColumnBase::Display display) const
{
QVariant variant = index.data();
if (!variant.isValid())
{
variant = index.data(Qt::DisplayRole);
if (!variant.isValid())
{ {
if (!index.data().isValid())
return 0; return 0;
}
}
if (display != CSMWorld::ColumnBase::Display_None)
{
if (variant.type() == QVariant::Color)
{
return new QLineEdit(parent);
}
if (display == CSMWorld::ColumnBase::Display_Integer)
{
return new QSpinBox(parent);
}
if (display == CSMWorld::ColumnBase::Display_Var)
{
return new QLineEdit(parent);
}
if (display == CSMWorld::ColumnBase::Display_Float)
{
return new QDoubleSpinBox(parent);
}
if (display == CSMWorld::ColumnBase::Display_LongString)
{
return new QTextEdit(parent);
}
if (display == CSMWorld::ColumnBase::Display_String ||
display == CSMWorld::ColumnBase::Display_Skill ||
display == CSMWorld::ColumnBase::Display_Script ||
display == CSMWorld::ColumnBase::Display_Race ||
display == CSMWorld::ColumnBase::Display_Class ||
display == CSMWorld::ColumnBase::Display_Faction ||
display == CSMWorld::ColumnBase::Display_Miscellaneous ||
display == CSMWorld::ColumnBase::Display_Sound)
{
return new DropLineEdit(parent);
}
if (display == CSMWorld::ColumnBase::Display_Boolean)
{
return new QCheckBox(parent);
}
}
return QStyledItemDelegate::createEditor (parent, option, index); return QStyledItemDelegate::createEditor (parent, option, index);
} }
@ -141,3 +197,66 @@ bool CSVWorld::CommandDelegate::updateEditorSetting (const QString &settingName,
{ {
return false; return false;
} }
void CSVWorld::CommandDelegate::setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay) const
{
QVariant v = index.data(Qt::EditRole);
if (tryDisplay)
{
if (!v.isValid())
{
v = index.data(Qt::DisplayRole);
if (!v.isValid())
{
return;
}
}
QPlainTextEdit* plainTextEdit = qobject_cast<QPlainTextEdit*>(editor);
if(plainTextEdit) //for some reason it is easier to brake the loop here
{
if(plainTextEdit->toPlainText() == v.toString())
{
return;
}
}
}
QByteArray n = editor->metaObject()->userProperty().name();
if (n == "dateTime") {
if (editor->inherits("QTimeEdit"))
n = "time";
else if (editor->inherits("QDateEdit"))
n = "date";
}
if (!n.isEmpty()) {
if (!v.isValid())
v = QVariant(editor->property(n).userType(), (const void *)0);
editor->setProperty(n, v);
}
}
CSVWorld::DropLineEdit::DropLineEdit(QWidget* parent) :
QLineEdit(parent)
{
setAcceptDrops(true);
}
void CSVWorld::DropLineEdit::dragEnterEvent(QDragEnterEvent *event)
{
event->acceptProposedAction();
}
void CSVWorld::DropLineEdit::dragMoveEvent(QDragMoveEvent *event)
{
event->accept();
}
void CSVWorld::DropLineEdit::dropEvent(QDropEvent *event)
{
const CSMWorld::TableMimeData* data(dynamic_cast<const CSMWorld::TableMimeData*>(event->mimeData()));
emit tableMimeDataDropped(data->getData(), data->getDocumentPtr());
//WIP
}

View File

@ -5,11 +5,19 @@
#include <QAbstractTableModel> #include <QAbstractTableModel>
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
#include <QLineEdit>
#include "../../model/world/columnbase.hpp" #include "../../model/world/columnbase.hpp"
#include "../../model/doc/document.hpp"
class QUndoStack; class QUndoStack;
namespace CSMWorld
{
class TableMimeData;
class UniversalId;
}
namespace CSVWorld namespace CSVWorld
{ {
///< \brief Getting the data out of an editor widget ///< \brief Getting the data out of an editor widget
@ -79,6 +87,24 @@ namespace CSVWorld
}; };
class DropLineEdit : public QLineEdit
{
Q_OBJECT
public:
DropLineEdit(QWidget *parent);
private:
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
signals:
void tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>& data, const CSMDoc::Document* document);
};
///< \brief Use commands instead of manipulating the model directly ///< \brief Use commands instead of manipulating the model directly
class CommandDelegate : public QStyledItemDelegate class CommandDelegate : public QStyledItemDelegate
{ {
@ -101,8 +127,10 @@ namespace CSVWorld
virtual void setModelData (QWidget *editor, QAbstractItemModel *model, virtual void setModelData (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const; const QModelIndex& index) const;
virtual QWidget *createEditor (QWidget *parent, const QStyleOptionViewItem& option, virtual QWidget *createEditor (QWidget *parent,
const QModelIndex& index) const; const QStyleOptionViewItem& option,
const QModelIndex& index,
CSMWorld::ColumnBase::Display display = CSMWorld::ColumnBase::Display_None) const;
void setEditLock (bool locked); void setEditLock (bool locked);
@ -111,6 +139,9 @@ namespace CSVWorld
virtual bool updateEditorSetting (const QString &settingName, const QString &settingValue); virtual bool updateEditorSetting (const QString &settingName, const QString &settingValue);
///< \return Does column require update? ///< \return Does column require update?
virtual void setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay = false) const;
private slots: private slots:
virtual void slotUpdateEditorSetting (const QString &settingName, const QString &settingValue) {} virtual void slotUpdateEditorSetting (const QString &settingName, const QString &settingValue) {}

View File

@ -12,7 +12,7 @@
#include <components/compiler/extensions0.hpp> #include <components/compiler/extensions0.hpp>
#include <components/bsa/bsa_archive.hpp> #include <components/bsa/resources.hpp>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include <components/translation/translation.hpp> #include <components/translation/translation.hpp>
#include <components/nif/niffile.hpp> #include <components/nif/niffile.hpp>
@ -192,50 +192,6 @@ OMW::Engine::~Engine()
SDL_Quit(); SDL_Quit();
} }
// Load BSA files
void OMW::Engine::loadBSA()
{
// We use separate resource groups to handle location priority.
const Files::PathContainer& dataDirs = mFileCollections.getPaths();
int i=0;
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
{
// Last data dir has the highest priority
std::string groupName = "Data" + Ogre::StringConverter::toString(dataDirs.size()-i, 8, '0');
Ogre::ResourceGroupManager::getSingleton ().createResourceGroup (groupName);
std::string dataDirectory = iter->string();
std::cout << "Data dir " << dataDirectory << std::endl;
Bsa::addDir(dataDirectory, mFSStrict, groupName);
++i;
}
i=0;
for (std::vector<std::string>::const_iterator archive = mArchives.begin(); archive != mArchives.end(); ++archive)
{
if (mFileCollections.doesExist(*archive))
{
// Last BSA has the highest priority
std::string groupName = "DataBSA" + Ogre::StringConverter::toString(mArchives.size()-i, 8, '0');
Ogre::ResourceGroupManager::getSingleton ().createResourceGroup (groupName);
const std::string archivePath = mFileCollections.getPath(*archive).string();
std::cout << "Adding BSA archive " << archivePath << std::endl;
Bsa::addBSA(archivePath, groupName);
++i;
}
else
{
std::stringstream message;
message << "Archive '" << *archive << "' not found";
throw std::runtime_error(message.str());
}
}
}
// add resources directory // add resources directory
// \note This function works recursively. // \note This function works recursively.
@ -385,8 +341,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
mOgre->createWindow("OpenMW", windowSettings); mOgre->createWindow("OpenMW", windowSettings);
loadBSA(); Bsa::registerResources (mFileCollections, mArchives, true, mFSStrict);
// Create input and UI first to set up a bootstrapping environment for // Create input and UI first to set up a bootstrapping environment for
// showing a loading screen and keeping the window responsive while doing so // showing a loading screen and keeping the window responsive while doing so

View File

@ -101,9 +101,6 @@ namespace OMW
/// add a .zip resource /// add a .zip resource
void addZipResource (const boost::filesystem::path& path); void addZipResource (const boost::filesystem::path& path);
/// Load BSA files
void loadBSA();
void executeLocalScripts(); void executeLocalScripts();
virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt); virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt);

View File

@ -15,7 +15,7 @@ add_component_dir (nifoverrides
) )
add_component_dir (bsa add_component_dir (bsa
bsa_archive bsa_file bsa_archive bsa_file resources
) )
add_component_dir (nif add_component_dir (nif

View File

@ -0,0 +1,53 @@
#include "resources.hpp"
#include <iostream>
#include <OgreResourceGroupManager.h>
#include <OgreStringConverter.h>
#include "bsa_archive.hpp"
void Bsa::registerResources (const Files::Collections& collections,
const std::vector<std::string>& archives, bool useLooseFiles, bool fsStrict)
{
const Files::PathContainer& dataDirs = collections.getPaths();
int i=0;
if (useLooseFiles)
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
{
// Last data dir has the highest priority
std::string groupName = "Data" + Ogre::StringConverter::toString(dataDirs.size()-i, 8, '0');
Ogre::ResourceGroupManager::getSingleton ().createResourceGroup (groupName);
std::string dataDirectory = iter->string();
std::cout << "Data dir " << dataDirectory << std::endl;
Bsa::addDir(dataDirectory, fsStrict, groupName);
++i;
}
i=0;
for (std::vector<std::string>::const_iterator archive = archives.begin(); archive != archives.end(); ++archive)
{
if (collections.doesExist(*archive))
{
// Last BSA has the highest priority
std::string groupName = "DataBSA" + Ogre::StringConverter::toString(archives.size()-i, 8, '0');
Ogre::ResourceGroupManager::getSingleton ().createResourceGroup (groupName);
const std::string archivePath = collections.getPath(*archive).string();
std::cout << "Adding BSA archive " << archivePath << std::endl;
Bsa::addBSA(archivePath, groupName);
++i;
}
else
{
std::stringstream message;
message << "Archive '" << *archive << "' not found";
throw std::runtime_error(message.str());
}
}
}

View File

@ -0,0 +1,16 @@
#ifndef BSA_BSA_RESOURCES_H
#define BSA_BSA_RESOURCES_H
#include <vector>
#include <string>
#include "../files/collections.hpp"
namespace Bsa
{
void registerResources (const Files::Collections& collections,
const std::vector<std::string>& archives, bool useLooseFiles, bool fsStrict);
///< Register resources directories and archives as OGRE resources groups
}
#endif

BIN
files/opencs/add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

BIN
files/opencs/edit-clone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

BIN
files/opencs/edit-undo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

BIN
files/opencs/go-next.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

View File

@ -57,6 +57,13 @@
<file>static.png</file> <file>static.png</file>
<file>weapon.png</file> <file>weapon.png</file>
<file>multitype.png</file> <file>multitype.png</file>
<file>go-next.png</file>
<file>go-previous.png</file>
<file>edit-delete.png</file>
<file>edit-undo.png</file>
<file>edit-preview.png</file>
<file>edit-clone.png</file>
<file>add.png</file>
<file alias="startup/create-addon">raster/startup/big/create-addon.png</file> <file alias="startup/create-addon">raster/startup/big/create-addon.png</file>
<file alias="startup/create-game">raster/startup/big/new-game.png</file> <file alias="startup/create-game">raster/startup/big/new-game.png</file>
<file alias="startup/edit-content">raster/startup/big/edit-content.png</file> <file alias="startup/edit-content">raster/startup/big/edit-content.png</file>