From 36271f25ec1d228f7f990c15b509bafbb82df703 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 18 Jun 2015 22:59:40 +0300 Subject: [PATCH 01/53] Rework creator factories to accept Document as a parameter --- apps/opencs/view/world/creator.cpp | 4 ++-- apps/opencs/view/world/creator.hpp | 25 ++++++++-------------- apps/opencs/view/world/dialoguecreator.cpp | 14 ++++++------ apps/opencs/view/world/dialoguecreator.hpp | 6 ++---- apps/opencs/view/world/dialoguesubview.cpp | 3 +-- apps/opencs/view/world/genericcreator.hpp | 2 ++ apps/opencs/view/world/scenesubview.cpp | 4 +--- apps/opencs/view/world/tablebottombox.cpp | 8 ++++--- apps/opencs/view/world/tablebottombox.hpp | 11 +++++----- apps/opencs/view/world/tablesubview.cpp | 2 +- 10 files changed, 37 insertions(+), 42 deletions(-) diff --git a/apps/opencs/view/world/creator.cpp b/apps/opencs/view/world/creator.cpp index 2e7c7fe22a..7a8c8d48f0 100644 --- a/apps/opencs/view/world/creator.cpp +++ b/apps/opencs/view/world/creator.cpp @@ -15,8 +15,8 @@ void CSVWorld::Creator::setScope (unsigned int scope) CSVWorld::CreatorFactoryBase::~CreatorFactoryBase() {} -CSVWorld::Creator *CSVWorld::NullCreatorFactory::makeCreator (CSMWorld::Data& data, - QUndoStack& undoStack, const CSMWorld::UniversalId& id) const +CSVWorld::Creator *CSVWorld::NullCreatorFactory::makeCreator (CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const { return 0; } diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index 506bdab2c9..b2d80cf2f9 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -5,16 +5,12 @@ #include +#include "../../model/world/scope.hpp" #include "../../model/world/universalid.hpp" -#include "../../model/world/scope.hpp" - -class QUndoStack; - -namespace CSMWorld +namespace CSMDoc { - class Data; - class UniversalId; + class Document; } namespace CSVWorld @@ -59,8 +55,7 @@ namespace CSVWorld virtual ~CreatorFactoryBase(); - virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) const = 0; + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const = 0; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function can return a 0-pointer, which means no UI for creating/deleting @@ -72,8 +67,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) const; + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function always returns 0. @@ -84,8 +78,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) const; + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function can return a 0-pointer, which means no UI for creating/deleting @@ -93,10 +86,10 @@ namespace CSVWorld }; template - Creator *CreatorFactory::makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) const + Creator *CreatorFactory::makeCreator (CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const { - std::auto_ptr creator (new CreatorT (data, undoStack, id)); + std::auto_ptr creator (new CreatorT (document.getData(), document.getUndoStack(), id)); creator->setScope (scope); diff --git a/apps/opencs/view/world/dialoguecreator.cpp b/apps/opencs/view/world/dialoguecreator.cpp index 956cd26dfe..3d451ed2dd 100644 --- a/apps/opencs/view/world/dialoguecreator.cpp +++ b/apps/opencs/view/world/dialoguecreator.cpp @@ -3,6 +3,8 @@ #include +#include "../../model/doc/document.hpp" + #include "../../model/world/data.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/columns.hpp" @@ -22,14 +24,14 @@ CSVWorld::DialogueCreator::DialogueCreator (CSMWorld::Data& data, QUndoStack& un : GenericCreator (data, undoStack, id, true), mType (type) {} -CSVWorld::Creator *CSVWorld::TopicCreatorFactory::makeCreator (CSMWorld::Data& data, - QUndoStack& undoStack, const CSMWorld::UniversalId& id) const +CSVWorld::Creator *CSVWorld::TopicCreatorFactory::makeCreator (CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const { - return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Topic); + return new DialogueCreator (document.getData(), document.getUndoStack(), id, ESM::Dialogue::Topic); } -CSVWorld::Creator *CSVWorld::JournalCreatorFactory::makeCreator (CSMWorld::Data& data, - QUndoStack& undoStack, const CSMWorld::UniversalId& id) const +CSVWorld::Creator *CSVWorld::JournalCreatorFactory::makeCreator (CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const { - return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Journal); + return new DialogueCreator (document.getData(), document.getUndoStack(), id, ESM::Dialogue::Journal); } diff --git a/apps/opencs/view/world/dialoguecreator.hpp b/apps/opencs/view/world/dialoguecreator.hpp index 26f866909a..20430fdb6e 100644 --- a/apps/opencs/view/world/dialoguecreator.hpp +++ b/apps/opencs/view/world/dialoguecreator.hpp @@ -23,8 +23,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) const; + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; ///< The ownership of the returned Creator is transferred to the caller. }; @@ -32,8 +31,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) const; + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; ///< The ownership of the returned Creator is transferred to the caller. }; } diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index ab466dfcd8..5d9eda3f24 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -685,8 +685,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM mMainLayout->addWidget(mEditWidget); mEditWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - mMainLayout->addWidget (mBottom = - new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this)); + mMainLayout->addWidget (mBottom = new TableBottomBox (creatorFactory, document, id, this)); mBottom->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index 1f854c69ed..0d2a40486f 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -13,10 +13,12 @@ class QLineEdit; class QHBoxLayout; class QComboBox; class QLabel; +class QUndoStack; namespace CSMWorld { class CreateCommand; + class Data; } namespace CSVWorld diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index aa21612599..397d249296 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -33,9 +33,7 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout->setContentsMargins (QMargins (0, 0, 0, 0)); - layout->addWidget (mBottom = - new TableBottomBox (NullCreatorFactory(), document.getData(), document.getUndoStack(), id, - this), 0); + layout->addWidget (mBottom = new TableBottomBox (NullCreatorFactory(), document, id, this), 0); mLayout->setContentsMargins (QMargins (0, 0, 0, 0)); diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index e9d644f61e..dc3a6cc764 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -39,8 +39,10 @@ void CSVWorld::TableBottomBox::updateStatus() } } -CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFactory, - CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, QWidget *parent) +CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFactory, + CSMDoc::Document& document, + const CSMWorld::UniversalId& id, + QWidget *parent) : QWidget (parent), mShowStatusBar (false), mCreating (false) { for (int i=0; i<4; ++i) @@ -61,7 +63,7 @@ CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFacto setLayout (mLayout); - mCreator = creatorFactory.makeCreator (data, undoStack, id); + mCreator = creatorFactory.makeCreator (document, id); if (mCreator) { diff --git a/apps/opencs/view/world/tablebottombox.hpp b/apps/opencs/view/world/tablebottombox.hpp index 8f0d851632..a7d009c42d 100644 --- a/apps/opencs/view/world/tablebottombox.hpp +++ b/apps/opencs/view/world/tablebottombox.hpp @@ -9,10 +9,9 @@ class QStackedLayout; class QStatusBar; class QUndoStack; -namespace CSMWorld +namespace CSMDoc { - class Data; - class UniversalId; + class Document; } namespace CSVWorld @@ -42,8 +41,10 @@ namespace CSVWorld public: - TableBottomBox (const CreatorFactoryBase& creatorFactory, CSMWorld::Data& data, - QUndoStack& undoStack, const CSMWorld::UniversalId& id, QWidget *parent = 0); + TableBottomBox (const CreatorFactoryBase& creatorFactory, + CSMDoc::Document& document, + const CSMWorld::UniversalId& id, + QWidget *parent = 0); virtual ~TableBottomBox(); diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index faff4c429b..75671a50c4 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -26,7 +26,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout->setContentsMargins (QMargins (0, 0, 0, 0)); layout->addWidget (mBottom = - new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this), 0); + new TableBottomBox (creatorFactory, document, id, this), 0); layout->insertWidget (0, mTable = new Table (id, mBottom->canCreateAndDelete(), sorting, document), 2); From a6734a0ea4857f28c5569e3bc9650b0e8f1e810a Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 19 Jun 2015 11:50:02 +0300 Subject: [PATCH 02/53] Add Cell Id completion to ReferenceCreator --- apps/opencs/view/world/referencecreator.cpp | 15 ++++++++++++++- apps/opencs/view/world/referencecreator.hpp | 16 +++++++++++++++- apps/opencs/view/world/subviews.cpp | 4 ++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/apps/opencs/view/world/referencecreator.cpp b/apps/opencs/view/world/referencecreator.cpp index e9bb04ba7e..81efb17ab6 100644 --- a/apps/opencs/view/world/referencecreator.cpp +++ b/apps/opencs/view/world/referencecreator.cpp @@ -4,10 +4,13 @@ #include #include +#include "../../model/doc/document.hpp" + #include "../../model/world/data.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/columns.hpp" #include "../../model/world/idtable.hpp" +#include "../../model/world/idcompletionmanager.hpp" std::string CSVWorld::ReferenceCreator::getId() const { @@ -71,13 +74,14 @@ int CSVWorld::ReferenceCreator::getRefNumCount() const } CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) + const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager &completionManager) : GenericCreator (data, undoStack, id) { QLabel *label = new QLabel ("Cell", this); insertBeforeButtons (label, false); mCell = new QLineEdit (this); + mCell->setCompleter(completionManager.getCompleter(CSMWorld::ColumnBase::Display_Cell).get()); insertBeforeButtons (mCell, true); setManualEditing (false); @@ -142,3 +146,12 @@ void CSVWorld::ReferenceCreator::cloneMode(const std::string& originId, CSVWorld::GenericCreator::cloneMode(originId, type); cellChanged(); //otherwise ok button will remain disabled } + +CSVWorld::Creator *CSVWorld::ReferenceCreatorFactory::makeCreator (CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const +{ + return new ReferenceCreator(document.getData(), + document.getUndoStack(), + id, + document.getIdCompletionManager()); +} diff --git a/apps/opencs/view/world/referencecreator.hpp b/apps/opencs/view/world/referencecreator.hpp index 877307c29e..7f56143c9f 100644 --- a/apps/opencs/view/world/referencecreator.hpp +++ b/apps/opencs/view/world/referencecreator.hpp @@ -5,8 +5,14 @@ class QLineEdit; +namespace CSMWorld +{ + class IdCompletionManager; +} + namespace CSVWorld { + class ReferenceCreator : public GenericCreator { Q_OBJECT @@ -28,7 +34,7 @@ namespace CSVWorld public: ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id); + const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager &completionManager); virtual void cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type); @@ -46,6 +52,14 @@ namespace CSVWorld void cellChanged(); }; + + class ReferenceCreatorFactory : public CreatorFactoryBase + { + public: + + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; + ///< The ownership of the returned Creator is transferred to the caller. + }; } #endif diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index e81da23e13..fa1b7cdc79 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -59,7 +59,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactoryWithCreator >); manager.add (CSMWorld::UniversalId::Type_References, - new CSVDoc::SubViewFactoryWithCreator >); + new CSVDoc::SubViewFactoryWithCreator); manager.add (CSMWorld::UniversalId::Type_Topics, new CSVDoc::SubViewFactoryWithCreator); @@ -147,7 +147,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactoryWithCreator > (false)); manager.add (CSMWorld::UniversalId::Type_Reference, - new CSVDoc::SubViewFactoryWithCreator > (false)); + new CSVDoc::SubViewFactoryWithCreator (false)); manager.add (CSMWorld::UniversalId::Type_Cell, new CSVDoc::SubViewFactoryWithCreator > (false)); From 581ba55db9f60e3edd027b7d5d18d6825b7ee9b8 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 19 Jun 2015 12:51:50 +0300 Subject: [PATCH 03/53] Add Topic/Journal Id completion to InfoCreator --- .../model/world/idcompletionmanager.cpp | 2 ++ apps/opencs/view/world/infocreator.cpp | 21 ++++++++++++++++++- apps/opencs/view/world/infocreator.hpp | 11 +++++++++- apps/opencs/view/world/subviews.cpp | 8 +++---- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/apps/opencs/model/world/idcompletionmanager.cpp b/apps/opencs/model/world/idcompletionmanager.cpp index b59987cba2..20cd8652c6 100644 --- a/apps/opencs/model/world/idcompletionmanager.cpp +++ b/apps/opencs/model/world/idcompletionmanager.cpp @@ -24,6 +24,7 @@ namespace types[CSMWorld::ColumnBase::Display_Faction ] = CSMWorld::UniversalId::Type_Faction; types[CSMWorld::ColumnBase::Display_GlobalVariable ] = CSMWorld::UniversalId::Type_Global; types[CSMWorld::ColumnBase::Display_Icon ] = CSMWorld::UniversalId::Type_Icon; + types[CSMWorld::ColumnBase::Display_Journal ] = CSMWorld::UniversalId::Type_Journal; types[CSMWorld::ColumnBase::Display_Mesh ] = CSMWorld::UniversalId::Type_Mesh; types[CSMWorld::ColumnBase::Display_Miscellaneous ] = CSMWorld::UniversalId::Type_Referenceable; types[CSMWorld::ColumnBase::Display_Npc ] = CSMWorld::UniversalId::Type_Referenceable; @@ -37,6 +38,7 @@ namespace types[CSMWorld::ColumnBase::Display_Spell ] = CSMWorld::UniversalId::Type_Spell; types[CSMWorld::ColumnBase::Display_Static ] = CSMWorld::UniversalId::Type_Referenceable; types[CSMWorld::ColumnBase::Display_Texture ] = CSMWorld::UniversalId::Type_Texture; + types[CSMWorld::ColumnBase::Display_Topic ] = CSMWorld::UniversalId::Type_Topic; types[CSMWorld::ColumnBase::Display_Weapon ] = CSMWorld::UniversalId::Type_Referenceable; return types; diff --git a/apps/opencs/view/world/infocreator.cpp b/apps/opencs/view/world/infocreator.cpp index f88b9f0b9a..7b8390900c 100644 --- a/apps/opencs/view/world/infocreator.cpp +++ b/apps/opencs/view/world/infocreator.cpp @@ -9,10 +9,13 @@ #include +#include "../../model/doc/document.hpp" + #include "../../model/world/data.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/columns.hpp" #include "../../model/world/idtable.hpp" +#include "../../model/world/idcompletionmanager.hpp" std::string CSVWorld::InfoCreator::getId() const { @@ -39,13 +42,20 @@ void CSVWorld::InfoCreator::configureCreateCommand (CSMWorld::CreateCommand& com } CSVWorld::InfoCreator::InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) + const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager) : GenericCreator (data, undoStack, id) { QLabel *label = new QLabel ("Topic", this); insertBeforeButtons (label, false); mTopic = new QLineEdit (this); + CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Topic; + if (id.getType() == CSMWorld::UniversalId::Type_JournalInfo || // For Dialogue SubView + id.getType() == CSMWorld::UniversalId::Type_JournalInfos) // For Table SubView + { + displayType = CSMWorld::ColumnBase::Display_Journal; + } + mTopic->setCompleter(completionManager.getCompleter(displayType).get()); insertBeforeButtons (mTopic, true); setManualEditing (false); @@ -100,3 +110,12 @@ void CSVWorld::InfoCreator::topicChanged() { update(); } + +CSVWorld::Creator *CSVWorld::InfoCreatorFactory::makeCreator(CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const +{ + return new InfoCreator(document.getData(), + document.getUndoStack(), + id, + document.getIdCompletionManager()); +} diff --git a/apps/opencs/view/world/infocreator.hpp b/apps/opencs/view/world/infocreator.hpp index edc12975cb..1928004bb9 100644 --- a/apps/opencs/view/world/infocreator.hpp +++ b/apps/opencs/view/world/infocreator.hpp @@ -8,6 +8,7 @@ class QLineEdit; namespace CSMWorld { class InfoCollection; + class IdCompletionManager; } namespace CSVWorld @@ -25,7 +26,7 @@ namespace CSVWorld public: InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id); + const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager); virtual void cloneMode (const std::string& originId, const CSMWorld::UniversalId::Type type); @@ -43,6 +44,14 @@ namespace CSVWorld void topicChanged(); }; + + class InfoCreatorFactory : public CreatorFactoryBase + { + public: + + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; + ///< The ownership of the returned Creator is transferred to the caller. + }; } #endif diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index fa1b7cdc79..ba3ab1358c 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -68,10 +68,10 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactoryWithCreator); manager.add (CSMWorld::UniversalId::Type_TopicInfos, - new CSVDoc::SubViewFactoryWithCreator >); + new CSVDoc::SubViewFactoryWithCreator); manager.add (CSMWorld::UniversalId::Type_JournalInfos, - new CSVDoc::SubViewFactoryWithCreator >); + new CSVDoc::SubViewFactoryWithCreator); // Subviews for resources tables manager.add (CSMWorld::UniversalId::Type_Meshes, @@ -153,10 +153,10 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactoryWithCreator > (false)); manager.add (CSMWorld::UniversalId::Type_JournalInfo, - new CSVDoc::SubViewFactoryWithCreator > (false)); + new CSVDoc::SubViewFactoryWithCreator (false)); manager.add (CSMWorld::UniversalId::Type_TopicInfo, - new CSVDoc::SubViewFactoryWithCreator >(false)); + new CSVDoc::SubViewFactoryWithCreator(false)); manager.add (CSMWorld::UniversalId::Type_Topic, new CSVDoc::SubViewFactoryWithCreator (false)); From e212414bc7825febb7f90b9a0aa47bd3d45f10b3 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 19 Jun 2015 13:48:58 +0300 Subject: [PATCH 04/53] Use an ID parent type as the collection ID in GenericCreator. Fix impossibility of creation/cloning records from Dialogue subviews in Info tables --- apps/opencs/view/world/genericcreator.cpp | 9 +++++++++ apps/opencs/view/world/infocreator.cpp | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index a123e127f9..c641096087 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -133,6 +133,15 @@ CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undo mClonedType (CSMWorld::UniversalId::Type_None), mScopes (CSMWorld::Scope_Content), mScope (0), mScopeLabel (0), mCloneMode (false) { + // If the collection ID has a parent type, use it instead. + // It will change IDs with Record/SubRecord class (used for creators in Dialogue subviews) + // to IDs with general RecordList class (used for creators in Table subviews). + CSMWorld::UniversalId::Type listParentType = CSMWorld::UniversalId::getParentType(mListId.getType()); + if (listParentType != CSMWorld::UniversalId::Type_None) + { + mListId = listParentType; + } + mLayout = new QHBoxLayout; mLayout->setContentsMargins (0, 0, 0, 0); diff --git a/apps/opencs/view/world/infocreator.cpp b/apps/opencs/view/world/infocreator.cpp index 7b8390900c..916427fc24 100644 --- a/apps/opencs/view/world/infocreator.cpp +++ b/apps/opencs/view/world/infocreator.cpp @@ -50,8 +50,7 @@ CSVWorld::InfoCreator::InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack, mTopic = new QLineEdit (this); CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Topic; - if (id.getType() == CSMWorld::UniversalId::Type_JournalInfo || // For Dialogue SubView - id.getType() == CSMWorld::UniversalId::Type_JournalInfos) // For Table SubView + if (getCollectionId().getType() == CSMWorld::UniversalId::Type_JournalInfos) { displayType = CSMWorld::ColumnBase::Display_Journal; } From 170692b48004a7ee7ed3a96027d34ef78d110a8f Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 19 Jun 2015 19:24:06 +0300 Subject: [PATCH 05/53] InfoTableProxyModel: invalidate first row cache after row insertion/deletion --- .../model/world/infotableproxymodel.cpp | 19 +++++++++++++------ .../model/world/infotableproxymodel.hpp | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index 7522e492b6..5192dfec05 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -15,11 +15,18 @@ void CSMWorld::InfoTableProxyModel::setSourceModel(QAbstractItemModel *sourceMod { IdTableProxyModel::setSourceModel(sourceModel); mSourceModel = dynamic_cast(sourceModel); - connect(mSourceModel, - SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), - this, - SLOT(modelDataChanged(const QModelIndex &, const QModelIndex &))); - mFirstRowCache.clear(); + if (mSourceModel != NULL) + { + connect(mSourceModel, + SIGNAL(rowsInserted(const QModelIndex &, int, int)), + this, + SLOT(modelRowsChanged(const QModelIndex &, int, int))); + connect(mSourceModel, + SIGNAL(rowsRemoved(const QModelIndex &, int, int)), + this, + SLOT(modelRowsChanged(const QModelIndex &, int, int))); + mFirstRowCache.clear(); + } } bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const @@ -52,7 +59,7 @@ int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const return currentRow + 1; } -void CSMWorld::InfoTableProxyModel::modelDataChanged(const QModelIndex &/*topLeft*/, const QModelIndex &/*bottomRight*/) +void CSMWorld::InfoTableProxyModel::modelRowsChanged(const QModelIndex &/*parent*/, int /*start*/, int /*end*/) { mFirstRowCache.clear(); } diff --git a/apps/opencs/model/world/infotableproxymodel.hpp b/apps/opencs/model/world/infotableproxymodel.hpp index 3228316264..7b0cd8ede4 100644 --- a/apps/opencs/model/world/infotableproxymodel.hpp +++ b/apps/opencs/model/world/infotableproxymodel.hpp @@ -31,7 +31,7 @@ namespace CSMWorld virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; private slots: - void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void modelRowsChanged(const QModelIndex &parent, int start, int end); }; } From f1a38ffe930cb2ae13554543095ab0746edaf637 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 20 Jun 2015 11:29:15 +0300 Subject: [PATCH 06/53] InfoTableProxyModel: ignore the letter case in the search of the first Topic/Journal row --- .../model/world/infotableproxymodel.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index 5192dfec05..2812bae602 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -1,8 +1,18 @@ #include "infotableproxymodel.hpp" +#include + #include "idtablebase.hpp" #include "columns.hpp" +namespace +{ + QString toLower(const QString &str) + { + return Misc::StringUtils::lowerCase(str.toStdString()).c_str(); + } +} + CSMWorld::InfoTableProxyModel::InfoTableProxyModel(CSMWorld::UniversalId::Type type, QObject *parent) : IdTableProxyModel(parent), mType(type), @@ -45,7 +55,7 @@ int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const } int column = mSourceModel->findColumnIndex(columnId); - QString info = mSourceModel->data(mSourceModel->index(currentRow, column)).toString(); + QString info = toLower(mSourceModel->data(mSourceModel->index(currentRow, column)).toString()); if (mFirstRowCache.contains(info)) { @@ -53,10 +63,11 @@ int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const } while (--currentRow >= 0 && - mSourceModel->data(mSourceModel->index(currentRow, column)) == info); + toLower(mSourceModel->data(mSourceModel->index(currentRow, column)).toString()) == info); + ++currentRow; - mFirstRowCache[info] = currentRow + 1; - return currentRow + 1; + mFirstRowCache[info] = currentRow; + return currentRow; } void CSMWorld::InfoTableProxyModel::modelRowsChanged(const QModelIndex &/*parent*/, int /*start*/, int /*end*/) From 8aba52170f000c47960bbe854481c58a1050a6fd Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 11:34:32 +0200 Subject: [PATCH 07/53] fixed a build error --- apps/opencs/view/world/creator.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index b2d80cf2f9..b763481991 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -5,6 +5,8 @@ #include +#include "../../model/doc/document.hpp" + #include "../../model/world/scope.hpp" #include "../../model/world/universalid.hpp" From ced4e237a8e3c7069ebe769c0fea3fe2585d7e30 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 20 Jun 2015 12:43:53 +0300 Subject: [PATCH 08/53] Fix the sorting of Info tables when new row are added --- apps/opencs/model/world/infotableproxymodel.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index 2812bae602..3e564506ce 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -43,6 +43,12 @@ bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QMod { QModelIndex first = mSourceModel->index(getFirstInfoRow(left.row()), left.column()); QModelIndex second = mSourceModel->index(getFirstInfoRow(right.row()), right.column()); + + // If both indexes are belonged to the same Topic/Journal, compare their original rows only + if (first.row() == second.row()) + { + return sortOrder() == Qt::AscendingOrder ? left.row() < right.row() : right.row() < left.row(); + } return IdTableProxyModel::lessThan(first, second); } From 1ee1934053e389f2e18f1c1e7bb67b1d239854c7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 14:21:52 +0200 Subject: [PATCH 09/53] framework for accessing user settings in operation stages --- apps/opencs/model/doc/operation.cpp | 32 ++++++++++++++++++++--- apps/opencs/model/doc/operation.hpp | 11 ++++++++ apps/opencs/model/doc/operationholder.cpp | 5 ++++ apps/opencs/model/doc/stage.cpp | 2 ++ apps/opencs/model/doc/stage.hpp | 5 ++++ 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/doc/operation.cpp b/apps/opencs/model/doc/operation.cpp index 3f1674f509..4a39d29115 100644 --- a/apps/opencs/model/doc/operation.cpp +++ b/apps/opencs/model/doc/operation.cpp @@ -7,6 +7,7 @@ #include #include "../world/universalid.hpp" +#include "../settings/usersettings.hpp" #include "state.hpp" #include "stage.hpp" @@ -23,13 +24,16 @@ void CSMDoc::Operation::prepareStages() { iter->second = iter->first->setup(); mTotalSteps += iter->second; + + for (std::map::const_iterator iter2 (mSettings.begin()); iter2!=mSettings.end(); ++iter2) + iter->first->updateUserSetting (iter2->first, iter2->second); } } CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways) : mType (type), mStages(std::vector >()), mCurrentStage(mStages.begin()), mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered), - mFinalAlways (finalAlways), mError(false), mConnected (false) + mFinalAlways (finalAlways), mError(false), mConnected (false), mPrepared (false) { mTimer = new QTimer (this); } @@ -49,8 +53,8 @@ void CSMDoc::Operation::run() connect (mTimer, SIGNAL (timeout()), this, SLOT (executeStage())); mConnected = true; } - - prepareStages(); + + mPrepared = false; mTimer->start (0); } @@ -60,6 +64,14 @@ void CSMDoc::Operation::appendStage (Stage *stage) mStages.push_back (std::make_pair (stage, 0)); } +void CSMDoc::Operation::configureSettings (const std::vector& settings) +{ + for (std::vector::const_iterator iter (settings.begin()); iter!=settings.end(); ++iter) + { + mSettings.insert (std::make_pair (*iter, CSMSettings::UserSettings::instance().definitions (*iter))); + } +} + bool CSMDoc::Operation::hasError() const { return mError; @@ -84,8 +96,22 @@ void CSMDoc::Operation::abort() mCurrentStage = mStages.end(); } +void CSMDoc::Operation::updateUserSetting (const QString& name, const QStringList& value) +{ + std::map::iterator iter = mSettings.find (name); + + if (iter!=mSettings.end()) + iter->second = value; +} + void CSMDoc::Operation::executeStage() { + if (!mPrepared) + { + prepareStages(); + mPrepared = true; + } + Messages messages; while (mCurrentStage!=mStages.end()) diff --git a/apps/opencs/model/doc/operation.hpp b/apps/opencs/model/doc/operation.hpp index a6217fe2db..6d6ed112b0 100644 --- a/apps/opencs/model/doc/operation.hpp +++ b/apps/opencs/model/doc/operation.hpp @@ -2,9 +2,11 @@ #define CSM_DOC_OPERATION_H #include +#include #include #include +#include namespace CSMWorld { @@ -30,6 +32,8 @@ namespace CSMDoc bool mError; bool mConnected; QTimer *mTimer; + std::map mSettings; + bool mPrepared; void prepareStages(); @@ -46,6 +50,11 @@ namespace CSMDoc /// /// \attention Do no call this function while this Operation is running. + /// Specify settings to be passed on to stages. + /// + /// \attention Do no call this function while this Operation is running. + void configureSettings (const std::vector& settings); + bool hasError() const; signals: @@ -63,6 +72,8 @@ namespace CSMDoc void run(); + void updateUserSetting (const QString& name, const QStringList& value); + private slots: void executeStage(); diff --git a/apps/opencs/model/doc/operationholder.cpp b/apps/opencs/model/doc/operationholder.cpp index d79e140232..5157fd80c9 100644 --- a/apps/opencs/model/doc/operationholder.cpp +++ b/apps/opencs/model/doc/operationholder.cpp @@ -1,6 +1,8 @@ #include "operationholder.hpp" +#include "../settings/usersettings.hpp" + #include "operation.hpp" CSMDoc::OperationHolder::OperationHolder (Operation *operation) : mRunning (false) @@ -29,6 +31,9 @@ void CSMDoc::OperationHolder::setOperation (Operation *operation) connect (this, SIGNAL (abortSignal()), mOperation, SLOT (abort())); connect (&mThread, SIGNAL (started()), mOperation, SLOT (run())); + + connect (&CSMSettings::UserSettings::instance(), SIGNAL (userSettingUpdated (const QString&, const QStringList&)), + mOperation, SLOT (updateUserSetting (const QString&, const QStringList&))); } bool CSMDoc::OperationHolder::isRunning() const diff --git a/apps/opencs/model/doc/stage.cpp b/apps/opencs/model/doc/stage.cpp index 1a2c5c721f..78aa145742 100644 --- a/apps/opencs/model/doc/stage.cpp +++ b/apps/opencs/model/doc/stage.cpp @@ -2,3 +2,5 @@ #include "stage.hpp" CSMDoc::Stage::~Stage() {} + +void CSMDoc::Stage::updateUserSetting (const QString& name, const QStringList& value) {} diff --git a/apps/opencs/model/doc/stage.hpp b/apps/opencs/model/doc/stage.hpp index 126823ae91..e0328a91a1 100644 --- a/apps/opencs/model/doc/stage.hpp +++ b/apps/opencs/model/doc/stage.hpp @@ -8,6 +8,8 @@ #include "messages.hpp" +class QString; + namespace CSMDoc { class Stage @@ -21,6 +23,9 @@ namespace CSMDoc virtual void perform (int stage, Messages& messages) = 0; ///< Messages resulting from this stage will be appended to \a messages. + + /// Default-implementation: ignore + virtual void updateUserSetting (const QString& name, const QStringList& value); }; } From 9a102f81c8e7956e85c8f7599c2293c76f579a32 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 16:21:04 +0200 Subject: [PATCH 10/53] added setting for controlling script compiler warnings --- apps/opencs/model/settings/usersettings.cpp | 16 +++++++++++++++- apps/opencs/model/tools/scriptcheck.cpp | 20 +++++++++++++++++++- apps/opencs/model/tools/scriptcheck.hpp | 10 ++++++++++ apps/opencs/model/tools/tools.cpp | 5 +++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index d1dddf8ba5..78db5313b3 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -293,7 +293,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() autoDelete->setDefaultValue ("true"); } - declareSection ("script-editor", "Script Editor"); + declareSection ("script-editor", "Scripts"); { Setting *lineNum = createSetting (Type_CheckBox, "show-linenum", "Show Line Numbers"); lineNum->setDefaultValue ("true"); @@ -312,6 +312,20 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() "\nA name from the list of colors defined in the list of SVG color keyword names." "\nX11 color names may also work."; + QString modeIgnore ("Ignore"); + + QStringList modes; + modes << modeIgnore << "Strict"; + + Setting *warnings = createSetting (Type_ComboBox, "warnings", + "Warning Mode"); + warnings->setDeclaredValues (modes); + warnings->setDefaultValue (modeIgnore); + warnings->setToolTip ("
    How to handle warning messages during compilation:

    " + "

  • Ignore: Do not report warning
  • " + "
  • Strict: Promote warning to an error
  • " + "
"); + Setting *formatInt = createSetting (Type_LineEdit, "colour-int", "Highlight Colour: Int"); formatInt->setDefaultValues (QStringList() << "Dark magenta"); formatInt->setToolTip ("(Default: Green) Use one of the following formats:" + tooltip); diff --git a/apps/opencs/model/tools/scriptcheck.cpp b/apps/opencs/model/tools/scriptcheck.cpp index a70ee2ae4a..33922e9cf8 100644 --- a/apps/opencs/model/tools/scriptcheck.cpp +++ b/apps/opencs/model/tools/scriptcheck.cpp @@ -44,7 +44,7 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, Type type) } CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document) -: mDocument (document), mContext (document.getData()), mMessages (0) +: mDocument (document), mContext (document.getData()), mMessages (0), mWarningMode (Mode_Ignore) { /// \todo add an option to configure warning mode setWarningsMode (0); @@ -58,6 +58,7 @@ int CSMTools::ScriptCheckStage::setup() mContext.clear(); mMessages = 0; mId.clear(); + Compiler::ErrorHandler::reset(); return mDocument.getData().getScripts().getSize(); } @@ -72,6 +73,12 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages) mMessages = &messages; + switch (mWarningMode) + { + case Mode_Ignore: setWarningsMode (0); break; + case Mode_Strict: setWarningsMode (1); break; + } + try { const CSMWorld::Data& data = mDocument.getData(); @@ -99,3 +106,14 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages) mMessages = 0; } + +void CSMTools::ScriptCheckStage::updateUserSetting (const QString& name, const QStringList& value) +{ + if (name=="script-editor/warnings") + { + if (value.at (0)=="Ignore") + mWarningMode = Mode_Ignore; + else if (value.at (0)=="Strict") + mWarningMode = Mode_Strict; + } +} diff --git a/apps/opencs/model/tools/scriptcheck.hpp b/apps/opencs/model/tools/scriptcheck.hpp index 3fe12fc9a4..0d42b275c3 100644 --- a/apps/opencs/model/tools/scriptcheck.hpp +++ b/apps/opencs/model/tools/scriptcheck.hpp @@ -18,13 +18,21 @@ namespace CSMTools /// \brief VerifyStage: make sure that scripts compile class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler { + enum WarningMode + { + Mode_Ignore, + Mode_Strict + }; + const CSMDoc::Document& mDocument; Compiler::Extensions mExtensions; CSMWorld::ScriptContext mContext; std::string mId; std::string mFile; CSMDoc::Messages *mMessages; + WarningMode mWarningMode; + virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type); ///< Report error to the user. @@ -40,6 +48,8 @@ namespace CSMTools virtual void perform (int stage, CSMDoc::Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. + + virtual void updateUserSetting (const QString& name, const QStringList& value); }; } diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 7d70abae56..fda373bcf1 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -51,6 +51,11 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() { mVerifierOperation = new CSMDoc::Operation (CSMDoc::State_Verifying, false); + std::vector settings; + settings.push_back ("script-editor/warnings"); + + mVerifierOperation->configureSettings (settings); + connect (&mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); connect (&mVerifier, From 27ece7f36aec12f14987227b37a3af45b1f7e81b Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 20 Jun 2015 17:33:36 +0300 Subject: [PATCH 11/53] Rework DropLineEdit. Make it type-sensitive --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/widget/droplineedit.cpp | 82 +++++++++++++++++++ apps/opencs/view/widget/droplineedit.hpp | 50 +++++++++++ apps/opencs/view/world/dialoguesubview.cpp | 5 +- .../view/world/idcompletiondelegate.cpp | 4 +- apps/opencs/view/world/util.cpp | 31 +------ apps/opencs/view/world/util.hpp | 19 ----- 7 files changed, 143 insertions(+), 50 deletions(-) create mode 100644 apps/opencs/view/widget/droplineedit.cpp create mode 100644 apps/opencs/view/widget/droplineedit.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d86798af95..fa703e4972 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -75,7 +75,7 @@ opencs_units_noqt (view/world opencs_units (view/widget scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton - scenetooltoggle2 completerpopup coloreditor colorpickerpopup + scenetooltoggle2 completerpopup coloreditor colorpickerpopup droplineedit ) opencs_units (view/render diff --git a/apps/opencs/view/widget/droplineedit.cpp b/apps/opencs/view/widget/droplineedit.cpp new file mode 100644 index 0000000000..0b2ac63816 --- /dev/null +++ b/apps/opencs/view/widget/droplineedit.cpp @@ -0,0 +1,82 @@ +#include "droplineedit.hpp" + +#include + +#include "../../model/world/tablemimedata.hpp" + +namespace +{ + const CSMWorld::TableMimeData *getEventMimeData(QDropEvent *event) + { + Q_ASSERT(event != NULL); + return dynamic_cast(event->mimeData()); + } +} + +CSVWidget::DropLineEdit::DropLineEdit(QWidget *parent, CSMWorld::UniversalId::Type type) + : QLineEdit(parent), + mDropType(type) +{ + setAcceptDrops(true); +} + +void CSVWidget::DropLineEdit::dragEnterEvent(QDragEnterEvent *event) +{ + if (canAcceptEventData(event)) + { + event->acceptProposedAction(); + } +} + +void CSVWidget::DropLineEdit::dragMoveEvent(QDragMoveEvent *event) +{ + if (canAcceptEventData(event)) + { + event->accept(); + } +} + +void CSVWidget::DropLineEdit::dropEvent(QDropEvent *event) +{ + const CSMWorld::TableMimeData *data = getEventMimeData(event); + if (data == NULL) // May happen when non-records (e.g. plain text) are dragged and dropped + { + return; + } + + int dataIndex = getAcceptedDataIndex(*data); + if (dataIndex != -1) + { + setText(data->getData()[dataIndex].getId().c_str()); + emit tableMimeDataDropped(data->getData(), data->getDocumentPtr()); + } +} + +bool CSVWidget::DropLineEdit::canAcceptEventData(QDropEvent *event) const +{ + const CSMWorld::TableMimeData *data = getEventMimeData(event); + if (data == NULL) // May happen when non-records (e.g. plain text) are dragged and dropped + { + return false; + } + return getAcceptedDataIndex(*data) != -1; +} + +int CSVWidget::DropLineEdit::getAcceptedDataIndex(const CSMWorld::TableMimeData &data) const +{ + if (mDropType == CSMWorld::UniversalId::Type_None) + { + return 0; + } + + std::vector idData = data.getData(); + int size = static_cast(idData.size()); + for (int i = 0; i < size; ++i) + { + if (idData[i].getType() == mDropType) + { + return i; + } + } + return -1; +} diff --git a/apps/opencs/view/widget/droplineedit.hpp b/apps/opencs/view/widget/droplineedit.hpp new file mode 100644 index 0000000000..e49c947b48 --- /dev/null +++ b/apps/opencs/view/widget/droplineedit.hpp @@ -0,0 +1,50 @@ +#ifndef CSV_WIDGET_DROPLINEEDIT_HPP +#define CSV_WIDGET_DROPLINEEDIT_HPP + +#include + +#include "../../model/world/universalid.hpp" + +namespace CSMDoc +{ + class Document; +} + +namespace CSMWorld +{ + class TableMimeData; +} + +namespace CSVWidget +{ + class DropLineEdit : public QLineEdit + { + Q_OBJECT + + CSMWorld::UniversalId::Type mDropType; + ///< The accepted ID type for this LineEdit. + ///< If \a mDropType has Type_None type, this LineEdit accepts all ID types + + bool canAcceptEventData(QDropEvent *event) const; + ///< Checks whether the \a event contains CSMWorld::TableMimeData with a proper ID type + + int getAcceptedDataIndex(const CSMWorld::TableMimeData &data) const; + ///< Checks whether the \a data has a proper type + ///< \return -1 if there is no suitable data (ID type) + + public: + DropLineEdit(QWidget *parent = 0, + CSMWorld::UniversalId::Type type = CSMWorld::UniversalId::Type_None); + + protected: + void dragEnterEvent(QDragEnterEvent *event); + void dragMoveEvent(QDragMoveEvent *event); + void dropEvent(QDropEvent *event); + + signals: + void tableMimeDataDropped(const std::vector &data, + const CSMDoc::Document *document); + }; +} + +#endif diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 5d9eda3f24..a1dbc902ee 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -34,6 +34,7 @@ #include "../../model/doc/document.hpp" #include "../widget/coloreditor.hpp" +#include "../widget/droplineedit.hpp" #include "recordstatusdelegate.hpp" #include "util.hpp" @@ -306,7 +307,7 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase:: // NOTE: For each entry in CSVWorld::CommandDelegate::createEditor() a corresponding entry // is required here - if (qobject_cast(editor)) + if (qobject_cast(editor)) { connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); @@ -850,7 +851,7 @@ void CSVWorld::DialogueSubView::tableMimeDataDropped (QWidget* editor, { if (document == &mDocument) { - qobject_cast(editor)->setText(id.getId().c_str()); + qobject_cast(editor)->setText(id.getId().c_str()); } } diff --git a/apps/opencs/view/world/idcompletiondelegate.cpp b/apps/opencs/view/world/idcompletiondelegate.cpp index 056026471b..5c92e6576d 100644 --- a/apps/opencs/view/world/idcompletiondelegate.cpp +++ b/apps/opencs/view/world/idcompletiondelegate.cpp @@ -2,6 +2,8 @@ #include "../../model/world/idcompletionmanager.hpp" +#include "../widget/droplineedit.hpp" + CSVWorld::IdCompletionDelegate::IdCompletionDelegate(CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) @@ -26,7 +28,7 @@ QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent, } CSMWorld::IdCompletionManager &completionManager = getDocument().getIdCompletionManager(); - DropLineEdit *editor = new DropLineEdit(parent); + CSVWidget::DropLineEdit *editor = new CSVWidget::DropLineEdit(parent); editor->setCompleter(completionManager.getCompleter(display).get()); return editor; } diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 5974987c0c..684327fc2c 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -17,7 +17,10 @@ #include "../../model/world/commands.hpp" #include "../../model/world/tablemimedata.hpp" #include "../../model/world/commanddispatcher.hpp" + #include "../widget/coloreditor.hpp" +#include "../widget/droplineedit.hpp" + #include "dialoguespinbox.hpp" #include "scriptedit.hpp" @@ -250,7 +253,7 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO case CSMWorld::ColumnBase::Display_Video: case CSMWorld::ColumnBase::Display_GlobalVariable: - return new DropLineEdit(parent); + return new CSVWidget::DropLineEdit(parent); case CSMWorld::ColumnBase::Display_ScriptLines: @@ -324,29 +327,3 @@ void CSVWorld::CommandDelegate::setEditorData (QWidget *editor, const QModelInde } } - -CSVWorld::DropLineEdit::DropLineEdit(QWidget* parent) : -QLineEdit(parent) -{ - setAcceptDrops(true); -} - -void CSVWorld::DropLineEdit::dragEnterEvent(QDragEnterEvent *event) -{ - event->acceptProposedAction(); -} - -void CSVWorld::DropLineEdit::dragMoveEvent(QDragMoveEvent *event) -{ - event->accept(); -} - -void CSVWorld::DropLineEdit::dropEvent(QDropEvent *event) -{ - const CSMWorld::TableMimeData* data(dynamic_cast(event->mimeData())); - if (!data) // May happen when non-records (e.g. plain text) are dragged and dropped - return; - - emit tableMimeDataDropped(data->getData(), data->getDocumentPtr()); - //WIP -} diff --git a/apps/opencs/view/world/util.hpp b/apps/opencs/view/world/util.hpp index 8355e971cb..d695be0d7e 100644 --- a/apps/opencs/view/world/util.hpp +++ b/apps/opencs/view/world/util.hpp @@ -5,7 +5,6 @@ #include #include -#include #include "../../model/world/columnbase.hpp" #include "../../model/doc/document.hpp" @@ -91,24 +90,6 @@ namespace CSVWorld }; - class DropLineEdit : public QLineEdit - { - Q_OBJECT - - public: - DropLineEdit(QWidget *parent); - - private: - void dragEnterEvent(QDragEnterEvent *event); - - void dragMoveEvent(QDragMoveEvent *event); - - void dropEvent(QDropEvent *event); - - signals: - void tableMimeDataDropped(const std::vector& data, const CSMDoc::Document* document); - }; - ///< \brief Use commands instead of manipulating the model directly class CommandDelegate : public QStyledItemDelegate { From 0e21c61297d8775740386634e28f60f51ee7dbe2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 16:55:34 +0200 Subject: [PATCH 12/53] replaced redundant CSMTools::ReportModel::Line struct with CSMDoc::Message struct --- apps/opencs/model/doc/messages.cpp | 13 +++++++------ apps/opencs/model/doc/messages.hpp | 18 ++++++++++++------ apps/opencs/model/tools/reportmodel.cpp | 9 ++------- apps/opencs/model/tools/reportmodel.hpp | 14 +++----------- 4 files changed, 24 insertions(+), 30 deletions(-) diff --git a/apps/opencs/model/doc/messages.cpp b/apps/opencs/model/doc/messages.cpp index 9b295fb281..3c709683e1 100644 --- a/apps/opencs/model/doc/messages.cpp +++ b/apps/opencs/model/doc/messages.cpp @@ -1,15 +1,16 @@ #include "messages.hpp" +CSMDoc::Message::Message (const CSMWorld::UniversalId& id, const std::string& message, + const std::string& hint) +: mId (id), mMessage (message), mHint (hint) +{} + + void CSMDoc::Messages::add (const CSMWorld::UniversalId& id, const std::string& message, const std::string& hint) { - Message data; - data.mId = id; - data.mMessage = message; - data.mHint = hint; - - mMessages.push_back (data); + mMessages.push_back (Message (id, message, hint)); } void CSMDoc::Messages::push_back (const std::pair& data) diff --git a/apps/opencs/model/doc/messages.hpp b/apps/opencs/model/doc/messages.hpp index 0f36c73a73..4e143d8698 100644 --- a/apps/opencs/model/doc/messages.hpp +++ b/apps/opencs/model/doc/messages.hpp @@ -8,16 +8,22 @@ namespace CSMDoc { + struct Message + { + CSMWorld::UniversalId mId; + std::string mMessage; + std::string mHint; + + Message (const CSMWorld::UniversalId& id, const std::string& message, + const std::string& hint); + }; + class Messages { public: - struct Message - { - CSMWorld::UniversalId mId; - std::string mMessage; - std::string mHint; - }; + // \deprecated Use CSMDoc::Message directly instead. + typedef CSMDoc::Message Message; typedef std::vector Collection; diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp index 1248e202bf..e661e9eacf 100644 --- a/apps/opencs/model/tools/reportmodel.cpp +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -6,11 +6,6 @@ #include "../world/columns.hpp" -CSMTools::ReportModel::Line::Line (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint) -: mId (id), mMessage (message), mHint (hint) -{} - CSMTools::ReportModel::ReportModel (bool fieldColumn) { if (fieldColumn) @@ -137,14 +132,14 @@ void CSMTools::ReportModel::add (const CSMWorld::UniversalId& id, const std::str { beginInsertRows (QModelIndex(), mRows.size(), mRows.size()); - mRows.push_back (Line (id, message, hint)); + mRows.push_back (CSMDoc::Message (id, message, hint)); endInsertRows(); } void CSMTools::ReportModel::flagAsReplaced (int index) { - Line& line = mRows.at (index); + CSMDoc::Message& line = mRows.at (index); std::string hint = line.mHint; if (hint.empty() || hint[0]!='R') diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp index 4d2d0542f5..ff20f74a51 100644 --- a/apps/opencs/model/tools/reportmodel.hpp +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -6,6 +6,8 @@ #include +#include "../doc/messages.hpp" + #include "../world/universalid.hpp" namespace CSMTools @@ -14,17 +16,7 @@ namespace CSMTools { Q_OBJECT - struct Line - { - Line (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint); - - CSMWorld::UniversalId mId; - std::string mMessage; - std::string mHint; - }; - - std::vector mRows; + std::vector mRows; // Fixed columns enum Columns From 64701b273d041411bc75caaf9527ea2183ee6679 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 20 Jun 2015 18:29:31 +0300 Subject: [PATCH 13/53] LineEdits for ID values accept drops with a proper type --- apps/opencs/view/widget/droplineedit.cpp | 9 ++++++++- apps/opencs/view/widget/droplineedit.hpp | 5 +++-- apps/opencs/view/world/idcompletiondelegate.cpp | 2 +- apps/opencs/view/world/util.cpp | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/apps/opencs/view/widget/droplineedit.cpp b/apps/opencs/view/widget/droplineedit.cpp index 0b2ac63816..f3500dcd25 100644 --- a/apps/opencs/view/widget/droplineedit.cpp +++ b/apps/opencs/view/widget/droplineedit.cpp @@ -13,13 +13,20 @@ namespace } } -CSVWidget::DropLineEdit::DropLineEdit(QWidget *parent, CSMWorld::UniversalId::Type type) +CSVWidget::DropLineEdit::DropLineEdit(CSMWorld::UniversalId::Type type, QWidget *parent) : QLineEdit(parent), mDropType(type) { setAcceptDrops(true); } +CSVWidget::DropLineEdit::DropLineEdit(CSMWorld::ColumnBase::Display display, QWidget *parent) + : QLineEdit(parent), + mDropType(CSMWorld::TableMimeData::convertEnums(display)) +{ + setAcceptDrops(true); +} + void CSVWidget::DropLineEdit::dragEnterEvent(QDragEnterEvent *event) { if (canAcceptEventData(event)) diff --git a/apps/opencs/view/widget/droplineedit.hpp b/apps/opencs/view/widget/droplineedit.hpp index e49c947b48..7ba0513cc7 100644 --- a/apps/opencs/view/widget/droplineedit.hpp +++ b/apps/opencs/view/widget/droplineedit.hpp @@ -3,6 +3,7 @@ #include +#include "../../model/world/columnbase.hpp" #include "../../model/world/universalid.hpp" namespace CSMDoc @@ -33,8 +34,8 @@ namespace CSVWidget ///< \return -1 if there is no suitable data (ID type) public: - DropLineEdit(QWidget *parent = 0, - CSMWorld::UniversalId::Type type = CSMWorld::UniversalId::Type_None); + DropLineEdit(CSMWorld::UniversalId::Type type, QWidget *parent = 0); + DropLineEdit(CSMWorld::ColumnBase::Display display, QWidget *parent = 0); protected: void dragEnterEvent(QDragEnterEvent *event); diff --git a/apps/opencs/view/world/idcompletiondelegate.cpp b/apps/opencs/view/world/idcompletiondelegate.cpp index 5c92e6576d..970490828f 100644 --- a/apps/opencs/view/world/idcompletiondelegate.cpp +++ b/apps/opencs/view/world/idcompletiondelegate.cpp @@ -28,7 +28,7 @@ QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent, } CSMWorld::IdCompletionManager &completionManager = getDocument().getIdCompletionManager(); - CSVWidget::DropLineEdit *editor = new CSVWidget::DropLineEdit(parent); + CSVWidget::DropLineEdit *editor = new CSVWidget::DropLineEdit(display, parent); editor->setCompleter(completionManager.getCompleter(display).get()); return editor; } diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 684327fc2c..d3969dad42 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -253,7 +253,7 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO case CSMWorld::ColumnBase::Display_Video: case CSMWorld::ColumnBase::Display_GlobalVariable: - return new CSVWidget::DropLineEdit(parent); + return new CSVWidget::DropLineEdit(CSMWorld::UniversalId::Type_None, parent); case CSMWorld::ColumnBase::Display_ScriptLines: From 8791832c865b01f1d32f6b49d76febdb99caf8e2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 17:56:42 +0200 Subject: [PATCH 14/53] standarised on the use of the Message struct when passing operations messages around --- apps/opencs/main.cpp | 3 +++ apps/opencs/model/doc/document.cpp | 9 ++++----- apps/opencs/model/doc/document.hpp | 3 +-- apps/opencs/model/doc/loader.cpp | 3 ++- apps/opencs/model/doc/messages.cpp | 2 ++ apps/opencs/model/doc/messages.hpp | 6 ++++++ apps/opencs/model/doc/operation.cpp | 4 ++-- apps/opencs/model/doc/operation.hpp | 5 +++-- apps/opencs/model/doc/operationholder.cpp | 4 ++-- apps/opencs/model/doc/operationholder.hpp | 5 +++-- apps/opencs/model/tools/reportmodel.cpp | 5 ++--- apps/opencs/model/tools/reportmodel.hpp | 3 +-- apps/opencs/model/tools/tools.cpp | 15 ++++++--------- apps/opencs/model/tools/tools.hpp | 3 +-- 14 files changed, 38 insertions(+), 32 deletions(-) diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index b11561c135..ce434fc43b 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -13,6 +13,8 @@ #include +#include "model/doc/messages.hpp" + #include "model/world/universalid.hpp" #ifdef Q_OS_MAC @@ -52,6 +54,7 @@ int main(int argc, char *argv[]) qRegisterMetaType ("std::string"); qRegisterMetaType ("CSMWorld::UniversalId"); + qRegisterMetaType ("CSMDoc::Message"); OgreInit::OgreInit ogreInit; diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index b833b527ff..1e6ae54550 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2304,8 +2304,8 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool))); connect ( - &mSaving, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), - this, SLOT (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); + &mSaving, SIGNAL (reportMessage (const CSMDoc::Message&, int)), + this, SLOT (reportMessage (const CSMDoc::Message&, int))); connect (&mRunner, SIGNAL (runStateChanged()), this, SLOT (runStateChanged())); } @@ -2401,11 +2401,10 @@ void CSMDoc::Document::modificationStateChanged (bool clean) emit stateChanged (getState(), this); } -void CSMDoc::Document::reportMessage (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint, int type) +void CSMDoc::Document::reportMessage (const CSMDoc::Message& message, int type) { /// \todo find a better way to get these messages to the user. - std::cout << message << std::endl; + std::cout << message.mMessage << std::endl; } void CSMDoc::Document::operationDone (int type, bool failed) diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 14daeeb758..4aaaf40b03 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -158,8 +158,7 @@ namespace CSMDoc void modificationStateChanged (bool clean); - void reportMessage (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint, int type); + void reportMessage (const CSMDoc::Message& message, int type); void operationDone (int type, bool failed); diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 43f3b850ea..5cdade37e1 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -68,7 +68,8 @@ void CSMDoc::Loader::load() for (CSMDoc::Messages::Iterator iter (messages.begin()); iter!=messages.end(); ++iter) { - document->getReport (log)->add (iter->mId, iter->mMessage); + document->getReport (log)->add ( + CSMDoc::Message (iter->mId, iter->mMessage, "")); emit loadMessage (document, iter->mMessage); } } diff --git a/apps/opencs/model/doc/messages.cpp b/apps/opencs/model/doc/messages.cpp index 3c709683e1..07604cd857 100644 --- a/apps/opencs/model/doc/messages.cpp +++ b/apps/opencs/model/doc/messages.cpp @@ -1,6 +1,8 @@ #include "messages.hpp" +CSMDoc::Message::Message() {} + CSMDoc::Message::Message (const CSMWorld::UniversalId& id, const std::string& message, const std::string& hint) : mId (id), mMessage (message), mHint (hint) diff --git a/apps/opencs/model/doc/messages.hpp b/apps/opencs/model/doc/messages.hpp index 4e143d8698..ecdb7e2438 100644 --- a/apps/opencs/model/doc/messages.hpp +++ b/apps/opencs/model/doc/messages.hpp @@ -4,6 +4,8 @@ #include #include +#include + #include "../world/universalid.hpp" namespace CSMDoc @@ -14,6 +16,8 @@ namespace CSMDoc std::string mMessage; std::string mHint; + Message(); + Message (const CSMWorld::UniversalId& id, const std::string& message, const std::string& hint); }; @@ -47,4 +51,6 @@ namespace CSMDoc }; } +Q_DECLARE_METATYPE (CSMDoc::Message) + #endif diff --git a/apps/opencs/model/doc/operation.cpp b/apps/opencs/model/doc/operation.cpp index 4a39d29115..99d581a954 100644 --- a/apps/opencs/model/doc/operation.cpp +++ b/apps/opencs/model/doc/operation.cpp @@ -129,7 +129,7 @@ void CSMDoc::Operation::executeStage() } catch (const std::exception& e) { - emit reportMessage (CSMWorld::UniversalId(), e.what(), "", mType); + emit reportMessage (Message (CSMWorld::UniversalId(), e.what(), ""), mType); abort(); } @@ -141,7 +141,7 @@ void CSMDoc::Operation::executeStage() emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType); for (Messages::Iterator iter (messages.begin()); iter!=messages.end(); ++iter) - emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType); + emit reportMessage (*iter, mType); if (mCurrentStage==mStages.end()) operationDone(); diff --git a/apps/opencs/model/doc/operation.hpp b/apps/opencs/model/doc/operation.hpp index 6d6ed112b0..d90a1bf4f3 100644 --- a/apps/opencs/model/doc/operation.hpp +++ b/apps/opencs/model/doc/operation.hpp @@ -8,6 +8,8 @@ #include #include +#include "messages.hpp" + namespace CSMWorld { class UniversalId; @@ -61,8 +63,7 @@ namespace CSMDoc void progress (int current, int max, int type); - void reportMessage (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint, int type); + void reportMessage (const CSMDoc::Message& message, int type); void done (int type, bool failed); diff --git a/apps/opencs/model/doc/operationholder.cpp b/apps/opencs/model/doc/operationholder.cpp index 5157fd80c9..25fc6fc263 100644 --- a/apps/opencs/model/doc/operationholder.cpp +++ b/apps/opencs/model/doc/operationholder.cpp @@ -21,8 +21,8 @@ void CSMDoc::OperationHolder::setOperation (Operation *operation) this, SIGNAL (progress (int, int, int))); connect ( - mOperation, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), - this, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); + mOperation, SIGNAL (reportMessage (const CSMDoc::Message&, int)), + this, SIGNAL (reportMessage (const CSMDoc::Message&, int))); connect ( mOperation, SIGNAL (done (int, bool)), diff --git a/apps/opencs/model/doc/operationholder.hpp b/apps/opencs/model/doc/operationholder.hpp index 6fe6df053c..b73d61dab1 100644 --- a/apps/opencs/model/doc/operationholder.hpp +++ b/apps/opencs/model/doc/operationholder.hpp @@ -4,6 +4,8 @@ #include #include +#include "messages.hpp" + namespace CSMWorld { class UniversalId; @@ -44,8 +46,7 @@ namespace CSMDoc void progress (int current, int max, int type); - void reportMessage (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint, int type); + void reportMessage (const CSMDoc::Message& message, int type); void done (int type, bool failed); diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp index e661e9eacf..b44ad7b605 100644 --- a/apps/opencs/model/tools/reportmodel.cpp +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -127,12 +127,11 @@ bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& p return true; } -void CSMTools::ReportModel::add (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint) +void CSMTools::ReportModel::add (const CSMDoc::Message& message) { beginInsertRows (QModelIndex(), mRows.size(), mRows.size()); - mRows.push_back (CSMDoc::Message (id, message, hint)); + mRows.push_back (message); endInsertRows(); } diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp index ff20f74a51..e9b6124b30 100644 --- a/apps/opencs/model/tools/reportmodel.hpp +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -42,8 +42,7 @@ namespace CSMTools virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); - void add (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint = ""); + void add (const CSMDoc::Message& message); void flagAsReplaced (int index); diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index fda373bcf1..f46dbe6d3d 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -58,9 +58,8 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() connect (&mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); - connect (&mVerifier, - SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), - this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); + connect (&mVerifier, SIGNAL (reportMessage (const CSMDoc::Message&, int)), + this, SLOT (verifierMessage (const CSMDoc::Message&, int))); std::vector mandatoryIds; // I want C++11, damn it! mandatoryIds.push_back ("Day"); @@ -125,9 +124,8 @@ CSMTools::Tools::Tools (CSMDoc::Document& document) connect (&mSearch, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); connect (&mSearch, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); - connect (&mSearch, - SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), - this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); + connect (&mSearch, SIGNAL (reportMessage (const CSMDoc::Message&, int)), + this, SLOT (verifierMessage (const CSMDoc::Message&, int))); } CSMTools::Tools::~Tools() @@ -215,12 +213,11 @@ CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId& return mReports.at (id.getIndex()); } -void CSMTools::Tools::verifierMessage (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint, int type) +void CSMTools::Tools::verifierMessage (const CSMDoc::Message& message, int type) { std::map::iterator iter = mActiveReports.find (type); if (iter!=mActiveReports.end()) - mReports[iter->second]->add (id, message, hint); + mReports[iter->second]->add (message); } diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 0f9e570445..2912fc4717 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -75,8 +75,7 @@ namespace CSMTools private slots: - void verifierMessage (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint, int type); + void verifierMessage (const CSMDoc::Message& message, int type); signals: From 197b8ec731671002b42976d9a2057ffae5c797a7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 19:04:19 +0200 Subject: [PATCH 15/53] added severity attribute for operation messages (Fixes #2717) --- apps/opencs/model/doc/loader.cpp | 5 +-- apps/opencs/model/doc/messages.cpp | 15 +++++-- apps/opencs/model/doc/messages.hpp | 19 +++++++- apps/opencs/model/doc/operation.cpp | 12 +++-- apps/opencs/model/doc/operation.hpp | 4 ++ apps/opencs/model/tools/reportmodel.cpp | 49 ++++++++++++++++----- apps/opencs/model/tools/reportmodel.hpp | 6 ++- apps/opencs/model/tools/scriptcheck.cpp | 30 ++++++++----- apps/opencs/model/tools/scriptcheck.hpp | 1 + apps/opencs/model/tools/search.cpp | 2 +- apps/opencs/model/tools/searchoperation.cpp | 2 + apps/opencs/model/tools/tools.cpp | 2 +- apps/opencs/model/world/data.cpp | 10 +++-- 13 files changed, 117 insertions(+), 40 deletions(-) diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 5cdade37e1..33725a6f94 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -52,7 +52,7 @@ void CSMDoc::Loader::load() { if (iter->second.mRecordsLeft) { - CSMDoc::Messages messages; + Messages messages (Message::Severity_Error); for (int i=0; igetData().continueLoading (messages)) { @@ -68,8 +68,7 @@ void CSMDoc::Loader::load() for (CSMDoc::Messages::Iterator iter (messages.begin()); iter!=messages.end(); ++iter) { - document->getReport (log)->add ( - CSMDoc::Message (iter->mId, iter->mMessage, "")); + document->getReport (log)->add (*iter); emit loadMessage (document, iter->mMessage); } } diff --git a/apps/opencs/model/doc/messages.cpp b/apps/opencs/model/doc/messages.cpp index 07604cd857..34157a05f0 100644 --- a/apps/opencs/model/doc/messages.cpp +++ b/apps/opencs/model/doc/messages.cpp @@ -4,15 +4,22 @@ CSMDoc::Message::Message() {} CSMDoc::Message::Message (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint) -: mId (id), mMessage (message), mHint (hint) + const std::string& hint, Severity severity) +: mId (id), mMessage (message), mHint (hint), mSeverity (severity) {} +CSMDoc::Messages::Messages (Message::Severity default_ = Message::Severity_Error) +: mDefault (default_) +{} + void CSMDoc::Messages::add (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint) + const std::string& hint, Message::Severity severity) { - mMessages.push_back (Message (id, message, hint)); + if (severity==Message::Severity_Default) + severity = mDefault; + + mMessages.push_back (Message (id, message, hint, severity)); } void CSMDoc::Messages::push_back (const std::pair& data) diff --git a/apps/opencs/model/doc/messages.hpp b/apps/opencs/model/doc/messages.hpp index ecdb7e2438..86f5feb152 100644 --- a/apps/opencs/model/doc/messages.hpp +++ b/apps/opencs/model/doc/messages.hpp @@ -12,14 +12,25 @@ namespace CSMDoc { struct Message { + enum Severity + { + Severity_Info = 0, // no problem + Severity_Warning = 1, // a potential problem, but we are probably fine + Severity_Error = 2, // an error; we are not fine + Severity_SeriousError = 3, // an error so bad we can't even be sure if we are + // reporting it correctly + Severity_Default = 4 + }; + CSMWorld::UniversalId mId; std::string mMessage; std::string mHint; + Severity mSeverity; Message(); Message (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint); + const std::string& hint, Severity severity); }; class Messages @@ -36,11 +47,15 @@ namespace CSMDoc private: Collection mMessages; + Message::Severity mDefault; public: + Messages (Message::Severity default_); + void add (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint = ""); + const std::string& hint = "", + Message::Severity severity = Message::Severity_Default); /// \deprecated Use add instead. void push_back (const std::pair& data); diff --git a/apps/opencs/model/doc/operation.cpp b/apps/opencs/model/doc/operation.cpp index 99d581a954..8b27170868 100644 --- a/apps/opencs/model/doc/operation.cpp +++ b/apps/opencs/model/doc/operation.cpp @@ -33,7 +33,8 @@ void CSMDoc::Operation::prepareStages() CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways) : mType (type), mStages(std::vector >()), mCurrentStage(mStages.begin()), mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered), - mFinalAlways (finalAlways), mError(false), mConnected (false), mPrepared (false) + mFinalAlways (finalAlways), mError(false), mConnected (false), mPrepared (false), + mDefaultSeverity (Message::Severity_Error) { mTimer = new QTimer (this); } @@ -72,6 +73,11 @@ void CSMDoc::Operation::configureSettings (const std::vector& settings) } } +void CSMDoc::Operation::setDefaultSeverity (Message::Severity severity) +{ + mDefaultSeverity = severity; +} + bool CSMDoc::Operation::hasError() const { return mError; @@ -112,7 +118,7 @@ void CSMDoc::Operation::executeStage() mPrepared = true; } - Messages messages; + Messages messages (mDefaultSeverity); while (mCurrentStage!=mStages.end()) { @@ -129,7 +135,7 @@ void CSMDoc::Operation::executeStage() } catch (const std::exception& e) { - emit reportMessage (Message (CSMWorld::UniversalId(), e.what(), ""), mType); + emit reportMessage (Message (CSMWorld::UniversalId(), e.what(), "", Message::Severity_SeriousError), mType); abort(); } diff --git a/apps/opencs/model/doc/operation.hpp b/apps/opencs/model/doc/operation.hpp index d90a1bf4f3..703f9d44b7 100644 --- a/apps/opencs/model/doc/operation.hpp +++ b/apps/opencs/model/doc/operation.hpp @@ -36,6 +36,7 @@ namespace CSMDoc QTimer *mTimer; std::map mSettings; bool mPrepared; + Message::Severity mDefaultSeverity; void prepareStages(); @@ -57,6 +58,9 @@ namespace CSMDoc /// \attention Do no call this function while this Operation is running. void configureSettings (const std::vector& settings); + /// \attention Do no call this function while this Operation is running. + void setDefaultSeverity (Message::Severity severity); + bool hasError() const; signals: diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp index b44ad7b605..480691710d 100644 --- a/apps/opencs/model/tools/reportmodel.cpp +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -6,19 +6,18 @@ #include "../world/columns.hpp" -CSMTools::ReportModel::ReportModel (bool fieldColumn) +CSMTools::ReportModel::ReportModel (bool fieldColumn, bool severityColumn) +: mColumnField (-1), mColumnSeverity (-1) { - if (fieldColumn) - { - mColumnField = 3; - mColumnDescription = 4; - } - else - { - mColumnDescription = 3; + int index = 3; - mColumnField = -1; - } + if (severityColumn) + mColumnSeverity = index++; + + if (fieldColumn) + mColumnField = index++; + + mColumnDescription = index; } int CSMTools::ReportModel::rowCount (const QModelIndex & parent) const @@ -83,6 +82,18 @@ QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const return QString::fromUtf8 (field.c_str()); } + + if (index.column()==mColumnSeverity) + { + switch (mRows.at (index.row()).mSeverity) + { + case CSMDoc::Message::Severity_Info: return "Information"; + case CSMDoc::Message::Severity_Warning: return "Warning"; + case CSMDoc::Message::Severity_Error: return "Error"; + case CSMDoc::Message::Severity_SeriousError: return "Serious Error"; + case CSMDoc::Message::Severity_Default: break; + } + } return QVariant(); } @@ -107,6 +118,9 @@ QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orienta if (section==mColumnField) return "Field"; + if (section==mColumnSeverity) + return "Severity"; + return "-"; } @@ -170,3 +184,16 @@ void CSMTools::ReportModel::clear() endRemoveRows(); } } + +int CSMTools::ReportModel::countErrors() const +{ + int count = 0; + + for (std::vector::const_iterator iter (mRows.begin()); + iter!=mRows.end(); ++iter) + if (iter->mSeverity==CSMDoc::Message::Severity_Error || + iter->mSeverity==CSMDoc::Message::Severity_SeriousError) + ++count; + + return count; +} diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp index e9b6124b30..5704970f55 100644 --- a/apps/opencs/model/tools/reportmodel.hpp +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -27,10 +27,11 @@ namespace CSMTools // Configurable columns int mColumnDescription; int mColumnField; + int mColumnSeverity; public: - ReportModel (bool fieldColumn = false); + ReportModel (bool fieldColumn = false, bool severityColumn = true); virtual int rowCount (const QModelIndex & parent = QModelIndex()) const; @@ -51,6 +52,9 @@ namespace CSMTools std::string getHint (int row) const; void clear(); + + // Return number of messages with Error or SeriousError severity. + int countErrors() const; }; } diff --git a/apps/opencs/model/tools/scriptcheck.cpp b/apps/opencs/model/tools/scriptcheck.cpp index 33922e9cf8..190b146c91 100644 --- a/apps/opencs/model/tools/scriptcheck.cpp +++ b/apps/opencs/model/tools/scriptcheck.cpp @@ -11,6 +11,17 @@ #include "../world/data.hpp" +CSMDoc::Message::Severity CSMTools::ScriptCheckStage::getSeverity (Type type) +{ + switch (type) + { + case WarningMessage: return CSMDoc::Message::Severity_Warning; + case ErrorMessage: return CSMDoc::Message::Severity_Error; + } + + return CSMDoc::Message::Severity_SeriousError; +} + void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc, Type type) { @@ -18,11 +29,6 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); - if (type==ErrorMessage) - stream << "error "; - else - stream << "warning "; - stream << "script " << mFile << ", line " << loc.mLine << ", column " << loc.mColumn @@ -32,15 +38,17 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi hintStream << "l:" << loc.mLine << " " << loc.mColumn; - mMessages->add (id, stream.str(), hintStream.str()); + mMessages->add (id, stream.str(), hintStream.str(), getSeverity (type)); } void CSMTools::ScriptCheckStage::report (const std::string& message, Type type) { CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); - mMessages->push_back (std::make_pair (id, - (type==ErrorMessage ? "error: " : "warning: ") + message)); + std::ostringstream stream; + stream << "script " << mFile << ": " << message; + + mMessages->add (id, stream.str(), "", getSeverity (type)); } CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document) @@ -100,8 +108,10 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages) { CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); - messages.push_back (std::make_pair (id, - std::string ("Critical compile error: ") + error.what())); + std::ostringstream stream; + stream << "script " << mFile << ": " << error.what(); + + messages.add (id, stream.str(), "", CSMDoc::Message::Severity_SeriousError); } mMessages = 0; diff --git a/apps/opencs/model/tools/scriptcheck.hpp b/apps/opencs/model/tools/scriptcheck.hpp index 0d42b275c3..97c50a1eb0 100644 --- a/apps/opencs/model/tools/scriptcheck.hpp +++ b/apps/opencs/model/tools/scriptcheck.hpp @@ -32,6 +32,7 @@ namespace CSMTools CSMDoc::Messages *mMessages; WarningMode mWarningMode; + CSMDoc::Message::Severity getSeverity (Type type); virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type); ///< Report error to the user. diff --git a/apps/opencs/model/tools/search.cpp b/apps/opencs/model/tools/search.cpp index 7eb531161e..449df2c638 100644 --- a/apps/opencs/model/tools/search.cpp +++ b/apps/opencs/model/tools/search.cpp @@ -280,7 +280,7 @@ void CSMTools::Search::replace (CSMDoc::Document& document, CSMWorld::IdTableBas bool CSMTools::Search::verify (CSMDoc::Document& document, CSMWorld::IdTableBase *model, const CSMWorld::UniversalId& id, const std::string& messageHint) const { - CSMDoc::Messages messages; + CSMDoc::Messages messages (CSMDoc::Message::Severity_Info); int row = model->getModelIndex (id.getId(), model->findColumnIndex (CSMWorld::Columns::ColumnId_Id)).row(); diff --git a/apps/opencs/model/tools/searchoperation.cpp b/apps/opencs/model/tools/searchoperation.cpp index 4512de5829..8cbc5dc8e6 100644 --- a/apps/opencs/model/tools/searchoperation.cpp +++ b/apps/opencs/model/tools/searchoperation.cpp @@ -21,6 +21,8 @@ CSMTools::SearchOperation::SearchOperation (CSMDoc::Document& document) iter!=types.end(); ++iter) appendStage (new SearchStage (&dynamic_cast ( *document.getData().getTableModel (*iter)))); + + setDefaultSeverity (CSMDoc::Message::Severity_Info); } void CSMTools::SearchOperation::configure (const Search& search) diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index f46dbe6d3d..f0d649f388 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -158,7 +158,7 @@ CSMWorld::UniversalId CSMTools::Tools::runVerifier() CSMWorld::UniversalId CSMTools::Tools::newSearch() { - mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true))); + mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true, false))); return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Search, mNextReportNumber-1); } diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 529c8f88f9..5acd80339e 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -923,7 +923,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) { // log an error and continue loading the refs to the last loaded cell CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_None); - messages.add (id, "Logic error: cell index out of bounds"); + messages.add (id, "Logic error: cell index out of bounds", "", CSMDoc::Message::Severity_Error); index = mCells.getSize()-1; } std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (index)); @@ -984,7 +984,8 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) else { messages.add (UniversalId::Type_None, - "Trying to delete dialogue record " + id + " which does not exist"); + "Trying to delete dialogue record " + id + " which does not exist", + "", CSMDoc::Message::Severity_Warning); } } else @@ -1001,7 +1002,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) if (!mDialogue) { messages.add (UniversalId::Type_None, - "Found info record not following a dialogue record"); + "Found info record not following a dialogue record", "", CSMDoc::Message::Severity_Error); mReader->skipRecord(); break; @@ -1044,7 +1045,8 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) if (unhandledRecord) { - messages.add (UniversalId::Type_None, "Unsupported record type: " + n.toString()); + messages.add (UniversalId::Type_None, "Unsupported record type: " + n.toString(), "", + CSMDoc::Message::Severity_Error); mReader->skipRecord(); } From b9f6baf317bfc3f1cbabafe1d79749a5d83ca523 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 19:16:15 +0200 Subject: [PATCH 16/53] add normal script warnings mode (Fixes #2642) --- apps/opencs/model/settings/usersettings.cpp | 7 ++++--- apps/opencs/model/tools/scriptcheck.cpp | 5 ++++- apps/opencs/model/tools/scriptcheck.hpp | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 78db5313b3..3e59d0582f 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -312,17 +312,18 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() "\nA name from the list of colors defined in the list of SVG color keyword names." "\nX11 color names may also work."; - QString modeIgnore ("Ignore"); + QString modeNormal ("Normal"); QStringList modes; - modes << modeIgnore << "Strict"; + modes << "Ignore" << modeNormal << "Strict"; Setting *warnings = createSetting (Type_ComboBox, "warnings", "Warning Mode"); warnings->setDeclaredValues (modes); - warnings->setDefaultValue (modeIgnore); + warnings->setDefaultValue (modeNormal); warnings->setToolTip ("
    How to handle warning messages during compilation:

    " "

  • Ignore: Do not report warning
  • " + "
  • Normal: Report warning as a warning
  • " "
  • Strict: Promote warning to an error
  • " "
"); diff --git a/apps/opencs/model/tools/scriptcheck.cpp b/apps/opencs/model/tools/scriptcheck.cpp index 190b146c91..928ae156f8 100644 --- a/apps/opencs/model/tools/scriptcheck.cpp +++ b/apps/opencs/model/tools/scriptcheck.cpp @@ -84,7 +84,8 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages) switch (mWarningMode) { case Mode_Ignore: setWarningsMode (0); break; - case Mode_Strict: setWarningsMode (1); break; + case Mode_Normal: setWarningsMode (1); break; + case Mode_Strict: setWarningsMode (2); break; } try @@ -123,6 +124,8 @@ void CSMTools::ScriptCheckStage::updateUserSetting (const QString& name, const Q { if (value.at (0)=="Ignore") mWarningMode = Mode_Ignore; + else if (value.at (0)=="Normal") + mWarningMode = Mode_Normal; else if (value.at (0)=="Strict") mWarningMode = Mode_Strict; } diff --git a/apps/opencs/model/tools/scriptcheck.hpp b/apps/opencs/model/tools/scriptcheck.hpp index 97c50a1eb0..3f02766526 100644 --- a/apps/opencs/model/tools/scriptcheck.hpp +++ b/apps/opencs/model/tools/scriptcheck.hpp @@ -21,6 +21,7 @@ namespace CSMTools enum WarningMode { Mode_Ignore, + Mode_Normal, Mode_Strict }; From c644f15167b777323b165375c4728fcb877ea10a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 19:46:38 +0200 Subject: [PATCH 17/53] calm down travis --- apps/opencs/model/doc/messages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/doc/messages.cpp b/apps/opencs/model/doc/messages.cpp index 34157a05f0..bd6e808c82 100644 --- a/apps/opencs/model/doc/messages.cpp +++ b/apps/opencs/model/doc/messages.cpp @@ -9,7 +9,7 @@ CSMDoc::Message::Message (const CSMWorld::UniversalId& id, const std::string& me {} -CSMDoc::Messages::Messages (Message::Severity default_ = Message::Severity_Error) +CSMDoc::Messages::Messages (Message::Severity default_) : mDefault (default_) {} From 7dcdd130bb65be9fa79d8240946458420c2248d4 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 20 Jun 2015 20:52:47 +0300 Subject: [PATCH 18/53] Rework Dialogue subview code according to DropLineEdit changes --- apps/opencs/view/widget/droplineedit.cpp | 9 ++- apps/opencs/view/widget/droplineedit.hpp | 3 +- apps/opencs/view/world/dialoguesubview.cpp | 70 +--------------------- apps/opencs/view/world/dialoguesubview.hpp | 20 ------- apps/opencs/view/world/util.cpp | 24 ++------ 5 files changed, 14 insertions(+), 112 deletions(-) diff --git a/apps/opencs/view/widget/droplineedit.cpp b/apps/opencs/view/widget/droplineedit.cpp index f3500dcd25..6dae157468 100644 --- a/apps/opencs/view/widget/droplineedit.cpp +++ b/apps/opencs/view/widget/droplineedit.cpp @@ -54,8 +54,9 @@ void CSVWidget::DropLineEdit::dropEvent(QDropEvent *event) int dataIndex = getAcceptedDataIndex(*data); if (dataIndex != -1) { - setText(data->getData()[dataIndex].getId().c_str()); - emit tableMimeDataDropped(data->getData(), data->getDocumentPtr()); + std::vector idData = data->getData(); + setText(idData[dataIndex].getId().c_str()); + emit tableMimeDataDropped(idData[dataIndex], data->getDocumentPtr()); } } @@ -76,11 +77,13 @@ int CSVWidget::DropLineEdit::getAcceptedDataIndex(const CSMWorld::TableMimeData return 0; } + bool isReferenceable = mDropType == CSMWorld::UniversalId::Type_Referenceable; std::vector idData = data.getData(); int size = static_cast(idData.size()); for (int i = 0; i < size; ++i) { - if (idData[i].getType() == mDropType) + CSMWorld::UniversalId::Type type = idData[i].getType(); + if (type == mDropType || isReferenceable && CSMWorld::TableMimeData::isReferencable(type)) { return i; } diff --git a/apps/opencs/view/widget/droplineedit.hpp b/apps/opencs/view/widget/droplineedit.hpp index 7ba0513cc7..ce086b7dc1 100644 --- a/apps/opencs/view/widget/droplineedit.hpp +++ b/apps/opencs/view/widget/droplineedit.hpp @@ -43,8 +43,7 @@ namespace CSVWidget void dropEvent(QDropEvent *event); signals: - void tableMimeDataDropped(const std::vector &data, - const CSMDoc::Document *document); + void tableMimeDataDropped(const CSMWorld::UniversalId &id, const CSMDoc::Document *document); }; } diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index a1dbc902ee..284c5928ba 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -130,52 +130,6 @@ QWidget* CSVWorld::DialogueDelegateDispatcherProxy::getEditor() const return mEditor; } -void CSVWorld::DialogueDelegateDispatcherProxy::tableMimeDataDropped(const std::vector& data, const CSMDoc::Document* document) -{ - QLineEdit* lineEdit = qobject_cast(mEditor); - { - if (!lineEdit || !mIndexWrapper.get()) - { - return; - } - } - for (unsigned i = 0; i < data.size(); ++i) - { - CSMWorld::UniversalId::Type type = data[i].getType(); - if (mDisplay == CSMWorld::ColumnBase::Display_Referenceable) - { - if (type == CSMWorld::UniversalId::Type_Activator - || type == CSMWorld::UniversalId::Type_Potion - || type == CSMWorld::UniversalId::Type_Apparatus - || type == CSMWorld::UniversalId::Type_Armor - || type == CSMWorld::UniversalId::Type_Book - || type == CSMWorld::UniversalId::Type_Clothing - || type == CSMWorld::UniversalId::Type_Container - || type == CSMWorld::UniversalId::Type_Creature - || type == CSMWorld::UniversalId::Type_Door - || type == CSMWorld::UniversalId::Type_Ingredient - || type == CSMWorld::UniversalId::Type_CreatureLevelledList - || type == CSMWorld::UniversalId::Type_ItemLevelledList - || type == CSMWorld::UniversalId::Type_Light - || type == CSMWorld::UniversalId::Type_Lockpick - || type == CSMWorld::UniversalId::Type_Miscellaneous - || type == CSMWorld::UniversalId::Type_Npc - || type == CSMWorld::UniversalId::Type_Probe - || type == CSMWorld::UniversalId::Type_Repair - || type == CSMWorld::UniversalId::Type_Static - || type == CSMWorld::UniversalId::Type_Weapon) - { - type = CSMWorld::UniversalId::Type_Referenceable; - } - } - if (mDisplay == CSMWorld::TableMimeData::convertEnums(type)) - { - emit tableMimeDataDropped(mEditor, mIndexWrapper->mIndex, data[i], document); - emit editorDataCommited(mEditor, mIndexWrapper->mIndex, mDisplay); - break; - } - } -} /* ==============================DialogueDelegateDispatcher========================================== */ @@ -311,12 +265,8 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase:: { connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); - connect(editor, SIGNAL(tableMimeDataDropped(const std::vector&, const CSMDoc::Document*)), - proxy, SLOT(tableMimeDataDropped(const std::vector&, const CSMDoc::Document*))); - - connect(proxy, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), - this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); - + connect(editor, SIGNAL(tableMimeDataDropped(const CSMWorld::UniversalId&, const CSMDoc::Document*)), + proxy, SLOT(editorDataCommited())); } else if (qobject_cast(editor)) { @@ -387,9 +337,6 @@ mCommandDispatcher (commandDispatcher), mDocument (document) { remake (row); - - connect(mDispatcher, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), - this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); } void CSVWorld::EditWidget::remake(int row) @@ -680,8 +627,6 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM mEditWidget = new EditWidget(mainWidget, mTable->getModelIndex(mCurrentId, 0).row(), mTable, mCommandDispatcher, document, false); - connect(mEditWidget, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), - this, SLOT(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); mMainLayout->addWidget(mEditWidget); mEditWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); @@ -844,17 +789,6 @@ void CSVWorld::DialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent, } } -void CSVWorld::DialogueSubView::tableMimeDataDropped (QWidget* editor, - const QModelIndex& index, - const CSMWorld::UniversalId& id, - const CSMDoc::Document* document) -{ - if (document == &mDocument) - { - qobject_cast(editor)->setText(id.getId().c_str()); - } -} - void CSVWorld::DialogueSubView::requestFocus (const std::string& id) { changeCurrentId(id); diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 6cbd8ad778..69e0dc8648 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -86,18 +86,12 @@ namespace CSVWorld public slots: void editorDataCommited(); void setIndex(const QModelIndex& index); - void tableMimeDataDropped(const std::vector& data, - const CSMDoc::Document* document); signals: void editorDataCommited(QWidget* editor, const QModelIndex& index, CSMWorld::ColumnBase::Display display); - void tableMimeDataDropped(QWidget* editor, const QModelIndex& index, - const CSMWorld::UniversalId& id, - const CSMDoc::Document* document); - }; class DialogueDelegateDispatcher : public QAbstractItemDelegate @@ -153,11 +147,6 @@ namespace CSVWorld private slots: void editorDataCommited(QWidget* editor, const QModelIndex& index, CSMWorld::ColumnBase::Display display); - - signals: - void tableMimeDataDropped(QWidget* editor, const QModelIndex& index, - const CSMWorld::UniversalId& id, - const CSMDoc::Document* document); }; class EditWidget : public QScrollArea @@ -182,11 +171,6 @@ namespace CSVWorld virtual ~EditWidget(); void remake(int row); - - signals: - void tableMimeDataDropped(QWidget* editor, const QModelIndex& index, - const CSMWorld::UniversalId& id, - const CSMDoc::Document* document); }; class DialogueSubView : public CSVDoc::SubView @@ -230,10 +214,6 @@ namespace CSVWorld void dataChanged(const QModelIndex & index); ///\brief we need to care for deleting currently edited record - void tableMimeDataDropped(QWidget* editor, const QModelIndex& index, - const CSMWorld::UniversalId& id, - const CSMDoc::Document* document); - void requestFocus (const std::string& id); void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index d3969dad42..8155055897 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -236,29 +236,15 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO return new QCheckBox(parent); - case CSMWorld::ColumnBase::Display_String: - case CSMWorld::ColumnBase::Display_Skill: - case CSMWorld::ColumnBase::Display_Script: - case CSMWorld::ColumnBase::Display_Race: - case CSMWorld::ColumnBase::Display_Region: - case CSMWorld::ColumnBase::Display_Class: - case CSMWorld::ColumnBase::Display_Faction: - case CSMWorld::ColumnBase::Display_Miscellaneous: - case CSMWorld::ColumnBase::Display_Sound: - case CSMWorld::ColumnBase::Display_Mesh: - case CSMWorld::ColumnBase::Display_Icon: - case CSMWorld::ColumnBase::Display_Music: - case CSMWorld::ColumnBase::Display_SoundRes: - case CSMWorld::ColumnBase::Display_Texture: - case CSMWorld::ColumnBase::Display_Video: - case CSMWorld::ColumnBase::Display_GlobalVariable: - - return new CSVWidget::DropLineEdit(CSMWorld::UniversalId::Type_None, parent); - case CSMWorld::ColumnBase::Display_ScriptLines: return new ScriptEdit (mDocument, ScriptHighlighter::Mode_Console, parent); + case CSMWorld::ColumnBase::Display_String: + // For other Display types (that represent record IDs) with drop support IdCompletionDelegate is used + + return new CSVWidget::DropLineEdit(CSMWorld::UniversalId::Type_None, parent); + default: return QStyledItemDelegate::createEditor (parent, option, index); From dc37aea8ebd678b9824f0558b48085b30c61fe0a Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 20 Jun 2015 21:00:15 +0300 Subject: [PATCH 19/53] Add missing mappings to TableMimeData --- apps/opencs/model/world/tablemimedata.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/opencs/model/world/tablemimedata.cpp b/apps/opencs/model/world/tablemimedata.cpp index d40e0c217c..101bbf9ba2 100644 --- a/apps/opencs/model/world/tablemimedata.cpp +++ b/apps/opencs/model/world/tablemimedata.cpp @@ -264,6 +264,8 @@ namespace { CSMWorld::UniversalId::Type_Texture, CSMWorld::ColumnBase::Display_Texture }, { CSMWorld::UniversalId::Type_Video, CSMWorld::ColumnBase::Display_Video }, { CSMWorld::UniversalId::Type_Global, CSMWorld::ColumnBase::Display_GlobalVariable }, + { CSMWorld::UniversalId::Type_BodyPart, CSMWorld::ColumnBase::Display_BodyPart }, + { CSMWorld::UniversalId::Type_Enchantment, CSMWorld::ColumnBase::Display_Enchantment }, { CSMWorld::UniversalId::Type_None, CSMWorld::ColumnBase::Display_None } // end marker }; From c65e7a31e7272ac450fc792ecfe690075e7e643e Mon Sep 17 00:00:00 2001 From: dteviot Date: Sun, 21 Jun 2015 16:23:40 +1200 Subject: [PATCH 20/53] Aquatic creatures no longer try to get onto land. AiWander for aquatic creatures no longer uses path grid points as they're usually on land. --- apps/openmw/mwmechanics/aiwander.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 1f4133c0aa..d89a29e1d0 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -651,9 +651,6 @@ namespace MWMechanics if (mAllowedNodes.empty()) return; - if (actor.getClass().isPureWaterCreature(actor)) - return; - state.moveIn(new AiWanderStorage()); int index = OEngine::Misc::Rng::rollDice(mAllowedNodes.size()); @@ -700,7 +697,8 @@ namespace MWMechanics // actor can wander from the spawn position. AiWander assumes that // pathgrid points are available, and uses them to randomly select wander // destinations within the allowed set of pathgrid points (nodes). - if(mDistance) + // ... pathgrids don't usually include water, so swimmers ignore them + if (mDistance && !actor.getClass().isPureWaterCreature(actor)) { float cellXOffset = 0; float cellYOffset = 0; From 256545205226c44320eb813397bd23021f0e8a31 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sun, 21 Jun 2015 17:08:10 +0300 Subject: [PATCH 21/53] Add some drag'n'drop utils to work with TableMimeData --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/world/dragdroputils.cpp | 26 ++++++++++++++++++++ apps/opencs/view/world/dragdroputils.hpp | 30 ++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/view/world/dragdroputils.cpp create mode 100644 apps/opencs/view/world/dragdroputils.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index fa703e4972..5386da707f 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -70,7 +70,7 @@ opencs_units (view/world opencs_units_noqt (view/world subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate scripthighlighter idvalidator dialoguecreator physicssystem idcompletiondelegate - colordelegate + colordelegate dragdroputils ) opencs_units (view/widget diff --git a/apps/opencs/view/world/dragdroputils.cpp b/apps/opencs/view/world/dragdroputils.cpp new file mode 100644 index 0000000000..7f3974e539 --- /dev/null +++ b/apps/opencs/view/world/dragdroputils.cpp @@ -0,0 +1,26 @@ +#include "dragdroputils.hpp" + +#include + +#include "../../model/world/tablemimedata.hpp" + +const CSMWorld::TableMimeData *CSVWorld::DragDropUtils::getTableMimeData(const QDropEvent &event) +{ + return dynamic_cast(event.mimeData()); +} + +bool CSVWorld::DragDropUtils::canAcceptData(const QDropEvent &event, CSMWorld::ColumnBase::Display type) +{ + const CSMWorld::TableMimeData *data = getTableMimeData(event); + return data != NULL && data->holdsType(type); +} + +CSMWorld::UniversalId CSVWorld::DragDropUtils::getAcceptedData(const QDropEvent &event, + CSMWorld::ColumnBase::Display type) +{ + if (canAcceptData(event, type)) + { + return getTableMimeData(event)->returnMatching(type); + } + return CSMWorld::UniversalId::Type_None; +} diff --git a/apps/opencs/view/world/dragdroputils.hpp b/apps/opencs/view/world/dragdroputils.hpp new file mode 100644 index 0000000000..88e2958a53 --- /dev/null +++ b/apps/opencs/view/world/dragdroputils.hpp @@ -0,0 +1,30 @@ +#ifndef CSV_WORLD_DRAGDROPUTILS_HPP +#define CSV_WORLD_DRAGDROPUTILS_HPP + +#include "../../model/world/columnbase.hpp" + +class QDropEvent; + +namespace CSMWorld +{ + class TableMimeData; + class UniversalId; +} + +namespace CSVWorld +{ + class DragDropUtils + { + public: + static const CSMWorld::TableMimeData *getTableMimeData(const QDropEvent &event); + + static bool canAcceptData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); + ///< Checks whether the \a event contains a valid CSMWorld::TableMimeData that holds the \a type + + static CSMWorld::UniversalId getAcceptedData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); + ///< Gets the accepted data from the \a event using the \a type + ///< \return Type_None if the \a event data doesn't holds the \a type + }; +} + +#endif From a23de394f8ef2dd4c5fdb28b03cf8527cd42e3e0 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sun, 21 Jun 2015 17:16:13 +0300 Subject: [PATCH 22/53] Refine DropLineEdit code --- apps/opencs/view/widget/droplineedit.cpp | 69 ++++-------------------- apps/opencs/view/widget/droplineedit.hpp | 17 ++---- apps/opencs/view/world/util.cpp | 2 +- 3 files changed, 14 insertions(+), 74 deletions(-) diff --git a/apps/opencs/view/widget/droplineedit.cpp b/apps/opencs/view/widget/droplineedit.cpp index 6dae157468..98f1d81c30 100644 --- a/apps/opencs/view/widget/droplineedit.cpp +++ b/apps/opencs/view/widget/droplineedit.cpp @@ -3,33 +3,20 @@ #include #include "../../model/world/tablemimedata.hpp" +#include "../../model/world/universalid.hpp" -namespace -{ - const CSMWorld::TableMimeData *getEventMimeData(QDropEvent *event) - { - Q_ASSERT(event != NULL); - return dynamic_cast(event->mimeData()); - } -} +#include "../world/dragdroputils.hpp" -CSVWidget::DropLineEdit::DropLineEdit(CSMWorld::UniversalId::Type type, QWidget *parent) +CSVWidget::DropLineEdit::DropLineEdit(CSMWorld::ColumnBase::Display type, QWidget *parent) : QLineEdit(parent), mDropType(type) { setAcceptDrops(true); } -CSVWidget::DropLineEdit::DropLineEdit(CSMWorld::ColumnBase::Display display, QWidget *parent) - : QLineEdit(parent), - mDropType(CSMWorld::TableMimeData::convertEnums(display)) -{ - setAcceptDrops(true); -} - void CSVWidget::DropLineEdit::dragEnterEvent(QDragEnterEvent *event) { - if (canAcceptEventData(event)) + if (CSVWorld::DragDropUtils::canAcceptData(*event, mDropType)) { event->acceptProposedAction(); } @@ -37,7 +24,7 @@ void CSVWidget::DropLineEdit::dragEnterEvent(QDragEnterEvent *event) void CSVWidget::DropLineEdit::dragMoveEvent(QDragMoveEvent *event) { - if (canAcceptEventData(event)) + if (CSVWorld::DragDropUtils::canAcceptData(*event, mDropType)) { event->accept(); } @@ -45,48 +32,10 @@ void CSVWidget::DropLineEdit::dragMoveEvent(QDragMoveEvent *event) void CSVWidget::DropLineEdit::dropEvent(QDropEvent *event) { - const CSMWorld::TableMimeData *data = getEventMimeData(event); - if (data == NULL) // May happen when non-records (e.g. plain text) are dragged and dropped + if (CSVWorld::DragDropUtils::canAcceptData(*event, mDropType)) { - return; - } - - int dataIndex = getAcceptedDataIndex(*data); - if (dataIndex != -1) - { - std::vector idData = data->getData(); - setText(idData[dataIndex].getId().c_str()); - emit tableMimeDataDropped(idData[dataIndex], data->getDocumentPtr()); + CSMWorld::UniversalId id = CSVWorld::DragDropUtils::getAcceptedData(*event, mDropType); + setText(id.getId().c_str()); + emit tableMimeDataDropped(id, CSVWorld::DragDropUtils::getTableMimeData(*event)->getDocumentPtr()); } } - -bool CSVWidget::DropLineEdit::canAcceptEventData(QDropEvent *event) const -{ - const CSMWorld::TableMimeData *data = getEventMimeData(event); - if (data == NULL) // May happen when non-records (e.g. plain text) are dragged and dropped - { - return false; - } - return getAcceptedDataIndex(*data) != -1; -} - -int CSVWidget::DropLineEdit::getAcceptedDataIndex(const CSMWorld::TableMimeData &data) const -{ - if (mDropType == CSMWorld::UniversalId::Type_None) - { - return 0; - } - - bool isReferenceable = mDropType == CSMWorld::UniversalId::Type_Referenceable; - std::vector idData = data.getData(); - int size = static_cast(idData.size()); - for (int i = 0; i < size; ++i) - { - CSMWorld::UniversalId::Type type = idData[i].getType(); - if (type == mDropType || isReferenceable && CSMWorld::TableMimeData::isReferencable(type)) - { - return i; - } - } - return -1; -} diff --git a/apps/opencs/view/widget/droplineedit.hpp b/apps/opencs/view/widget/droplineedit.hpp index ce086b7dc1..60832e71bc 100644 --- a/apps/opencs/view/widget/droplineedit.hpp +++ b/apps/opencs/view/widget/droplineedit.hpp @@ -4,7 +4,6 @@ #include #include "../../model/world/columnbase.hpp" -#include "../../model/world/universalid.hpp" namespace CSMDoc { @@ -14,6 +13,7 @@ namespace CSMDoc namespace CSMWorld { class TableMimeData; + class UniversalId; } namespace CSVWidget @@ -22,20 +22,11 @@ namespace CSVWidget { Q_OBJECT - CSMWorld::UniversalId::Type mDropType; - ///< The accepted ID type for this LineEdit. - ///< If \a mDropType has Type_None type, this LineEdit accepts all ID types - - bool canAcceptEventData(QDropEvent *event) const; - ///< Checks whether the \a event contains CSMWorld::TableMimeData with a proper ID type - - int getAcceptedDataIndex(const CSMWorld::TableMimeData &data) const; - ///< Checks whether the \a data has a proper type - ///< \return -1 if there is no suitable data (ID type) + CSMWorld::ColumnBase::Display mDropType; + ///< The accepted Display type for this LineEdit. public: - DropLineEdit(CSMWorld::UniversalId::Type type, QWidget *parent = 0); - DropLineEdit(CSMWorld::ColumnBase::Display display, QWidget *parent = 0); + DropLineEdit(CSMWorld::ColumnBase::Display type, QWidget *parent = 0); protected: void dragEnterEvent(QDragEnterEvent *event); diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 8155055897..62cde4608a 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -243,7 +243,7 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO case CSMWorld::ColumnBase::Display_String: // For other Display types (that represent record IDs) with drop support IdCompletionDelegate is used - return new CSVWidget::DropLineEdit(CSMWorld::UniversalId::Type_None, parent); + return new CSVWidget::DropLineEdit(display, parent); default: From 44582fe3b329d928934015cb2924daf52c964503 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 21 Jun 2015 17:27:52 +0200 Subject: [PATCH 23/53] Don't use separate werewolf skills/attributes for non-player werewolves Still need to deal with save files. --- apps/openmw/mwmechanics/creaturestats.cpp | 11 ++--- apps/openmw/mwmechanics/creaturestats.hpp | 4 -- apps/openmw/mwmechanics/npcstats.cpp | 53 +++++++++-------------- apps/openmw/mwmechanics/npcstats.hpp | 5 ++- apps/openmw/mwworld/player.cpp | 49 +++++++++++++++++++++ apps/openmw/mwworld/player.hpp | 13 ++++++ apps/openmw/mwworld/worldimp.cpp | 11 +++++ components/esm/npcstats.cpp | 4 -- 8 files changed, 101 insertions(+), 49 deletions(-) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 308e720279..e5cb561bf3 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -20,7 +20,7 @@ namespace MWMechanics mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), mMovementFlags(0), mAttackStrength(0.f), mFallHeight(0), mRecalcMagicka(false), mLastRestock(0,0), mGoldPool(0), mActorId(-1), - mDeathAnimation(0), mIsWerewolf(false), mLevel (0) + mDeathAnimation(0), mLevel (0) { for (int i=0; i<4; ++i) mAiSettings[i] = 0; @@ -55,7 +55,7 @@ namespace MWMechanics if (index < 0 || index > 7) { throw std::runtime_error("attribute index is out of range"); } - return (!mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index]); + return mAttributes[index]; } const DynamicStat &CreatureStats::getHealth() const @@ -139,14 +139,11 @@ namespace MWMechanics throw std::runtime_error("attribute index is out of range"); } - const AttributeValue& currentValue = !mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index]; + const AttributeValue& currentValue = mAttributes[index]; if (value != currentValue) { - if(!mIsWerewolf) - mAttributes[index] = value; - else - mWerewolfAttributes[index] = value; + mAttributes[index] = value; if (index == ESM::Attribute::Intelligence) mRecalcMagicka = true; diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 145eb8a5bf..146d9fb1eb 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -77,10 +77,6 @@ namespace MWMechanics std::vector mSummonGraveyard; protected: - // These two are only set by NpcStats, but they are declared in CreatureStats to prevent using virtual methods. - bool mIsWerewolf; - AttributeValue mWerewolfAttributes[8]; - int mLevel; public: diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 94819e6260..577c76c97b 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -32,6 +32,7 @@ MWMechanics::NpcStats::NpcStats() , mWerewolfKills (0) , mLevelProgress(0) , mTimeToStartDrowning(20.0) + , mIsWerewolf(false) { mSkillIncreases.resize (ESM::Attribute::Length, 0); } @@ -51,7 +52,7 @@ const MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index) const if (index<0 || index>=ESM::Skill::Length) throw std::runtime_error ("skill index out of range"); - return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]); + return mSkill[index]; } MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index) @@ -59,7 +60,15 @@ MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index) if (index<0 || index>=ESM::Skill::Length) throw std::runtime_error ("skill index out of range"); - return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]); + return mSkill[index]; +} + +void MWMechanics::NpcStats::setSkill(int index, const MWMechanics::SkillValue &value) +{ + if (index<0 || index>=ESM::Skill::Length) + throw std::runtime_error ("skill index out of range"); + + mSkill[index] = value; } const std::map& MWMechanics::NpcStats::getFactionRanks() const @@ -188,10 +197,6 @@ float MWMechanics::NpcStats::getSkillProgressRequirement (int skillIndex, const void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType, float extraFactor) { - // Don't increase skills as a werewolf - if(mIsWerewolf) - return; - const ESM::Skill *skill = MWBase::Environment::get().getWorld()->getStore().get().find (skillIndex); float skillGain = 1; @@ -403,34 +408,12 @@ bool MWMechanics::NpcStats::isWerewolf() const void MWMechanics::NpcStats::setWerewolf (bool set) { + if (mIsWerewolf == set) + return; + if(set != false) { - const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); - mWerewolfKills = 0; - - for(size_t i = 0;i < ESM::Attribute::Length;i++) - { - mWerewolfAttributes[i] = getAttribute(i); - // Oh, Bethesda. It's "Intelligence". - std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") : - ESM::Attribute::sAttributeNames[i]); - mWerewolfAttributes[i].setBase(int(gmst.find(name)->getFloat())); - } - - for(size_t i = 0;i < ESM::Skill::Length;i++) - { - mWerewolfSkill[i] = getSkill(i); - - // Acrobatics is set separately for some reason. - if(i == ESM::Skill::Acrobatics) - continue; - - // "Mercantile"! >_< - std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") : - ESM::Skill::sSkillNames[i]); - mWerewolfSkill[i].setBase(int(gmst.find(name)->getFloat())); - } } mIsWerewolf = set; } @@ -466,12 +449,14 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const for (int i=0; i& getFactionRanks() const; /// Increase the rank in this faction by 1, if such a rank exists. diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 0b81532e18..d0d99bfcfb 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -49,6 +49,55 @@ namespace MWWorld mPlayer.mData.setPosition(playerPos); } + void Player::saveSkillsAttributes() + { + MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer()); + for (int i=0; i& gmst = MWBase::Environment::get().getWorld()->getStore().get(); + MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer()); + for(size_t i = 0;i < ESM::Attribute::Length;++i) + { + // Oh, Bethesda. It's "Intelligence". + std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") : + ESM::Attribute::sAttributeNames[i]); + + MWMechanics::AttributeValue value = stats.getAttribute(i); + value.setBase(int(gmst.find(name)->getFloat())); + stats.setAttribute(i, value); + } + + for(size_t i = 0;i < ESM::Skill::Length;i++) + { + // Acrobatics is set separately for some reason. + if(i == ESM::Skill::Acrobatics) + continue; + + // "Mercantile"! >_< + std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") : + ESM::Skill::sSkillNames[i]); + + MWMechanics::SkillValue value = stats.getSkill(i); + value.setBase(int(gmst.find(name)->getFloat())); + stats.setSkill(i, value); + } + } + void Player::set(const ESM::NPC *player) { mPlayer.mBase = player; diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index 25d8981cde..2845c58228 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -6,6 +6,11 @@ #include "../mwmechanics/drawstate.hpp" +#include "../mwmechanics/stat.hpp" + +#include +#include + #include namespace ESM @@ -50,10 +55,18 @@ namespace MWWorld int mCurrentCrimeId; // the id assigned witnesses int mPaidCrimeId; // the last id paid off (0 bounty) + // Saved skills and attributes prior to becoming a werewolf + MWMechanics::SkillValue mSaveSkills[ESM::Skill::Length]; + MWMechanics::AttributeValue mSaveAttributes[ESM::Attribute::Length]; + public: Player(const ESM::NPC *player, const MWBase::World& world); + void saveSkillsAttributes(); + void restoreSkillsAttributes(); + void setWerewolfSkillsAttributes(); + // For mark/recall magic effects void markPosition (CellStore* markedCell, ESM::Position markedPosition); void getMarkedPosition (CellStore*& markedCell, ESM::Position& markedPosition) const; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 0f33f3d59b..f8de9f65b9 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2485,6 +2485,17 @@ namespace MWWorld if (npcStats.isWerewolf() == werewolf) return; + if (actor == getPlayerPtr()) + { + if (werewolf) + { + mPlayer->saveSkillsAttributes(); + mPlayer->setWerewolfSkillsAttributes(); + } + else + mPlayer->restoreSkillsAttributes(); + } + npcStats.setWerewolf(werewolf); // This is a bit dangerous. Equipped items other than WerewolfRobe may reference diff --git a/components/esm/npcstats.cpp b/components/esm/npcstats.cpp index cc1d6b3ddc..fa808b72f3 100644 --- a/components/esm/npcstats.cpp +++ b/components/esm/npcstats.cpp @@ -117,10 +117,6 @@ void ESM::NpcStats::save (ESMWriter &esm) const mSkills[i].mWerewolf.save (esm); } - esm.writeHNT ("HWAT", true); - for (int i=0; i<8; ++i) - mWerewolfAttributes[i].save (esm); - if (mIsWerewolf) esm.writeHNT ("WOLF", mIsWerewolf); From d6a7255391425d34512b8b05ac27db1c6fdbf30f Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 21 Jun 2015 17:36:11 +0200 Subject: [PATCH 24/53] Loading/saving for player's original skills/attributes (prior to becoming a werewolf) --- apps/openmw/mwworld/player.cpp | 10 ++++++++++ components/esm/player.cpp | 13 +++++++++++++ components/esm/player.hpp | 6 ++++++ 3 files changed, 29 insertions(+) diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index d0d99bfcfb..e681bd7c5c 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -271,6 +271,11 @@ namespace MWWorld player.mAutoMove = mAutoMove ? 1 : 0; + for (int i=0; i mSaveAttributes[ESM::Attribute::Length]; + StatState mSaveSkills[ESM::Skill::Length]; + void load (ESMReader &esm); void save (ESMWriter &esm) const; }; From b9882eb59ab0c8a13d64b9ed7ffa7b1bdff0f12a Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sun, 21 Jun 2015 18:40:13 +0300 Subject: [PATCH 25/53] DragRecordTable checks drag type before accepting it --- apps/opencs/view/world/dragrecordtable.cpp | 53 +++++++++++++++++++++- apps/opencs/view/world/dragrecordtable.hpp | 7 +++ apps/opencs/view/world/table.cpp | 30 ------------ apps/opencs/view/world/table.hpp | 2 - 4 files changed, 58 insertions(+), 34 deletions(-) diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index 2a1ae1f401..3712348e22 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -1,8 +1,14 @@ +#include "dragrecordtable.hpp" + #include #include +#include "../../model/doc/document.hpp" + #include "../../model/world/tablemimedata.hpp" -#include "dragrecordtable.hpp" +#include "../../model/world/commands.hpp" + +#include "dragdroputils.hpp" void CSVWorld::DragRecordTable::startDragFromTable (const CSVWorld::DragRecordTable& table) { @@ -35,5 +41,48 @@ void CSVWorld::DragRecordTable::dragEnterEvent(QDragEnterEvent *event) void CSVWorld::DragRecordTable::dragMoveEvent(QDragMoveEvent *event) { - event->accept(); + QModelIndex index = indexAt(event->pos()); + if (CSVWorld::DragDropUtils::canAcceptData(*event, getIndexDisplayType(index))) + { + event->accept(); + } + else + { + event->ignore(); + } +} + +void CSVWorld::DragRecordTable::dropEvent(QDropEvent *event) +{ + QModelIndex index = indexAt(event->pos()); + CSMWorld::ColumnBase::Display display = getIndexDisplayType(index); + if (CSVWorld::DragDropUtils::canAcceptData(*event, display)) + { + const CSMWorld::TableMimeData *data = CSVWorld::DragDropUtils::getTableMimeData(*event); + if (data->fromDocument(mDocument)) + { + CSMWorld::UniversalId id = CSVWorld::DragDropUtils::getAcceptedData(*event, display); + QVariant newIndexData = QString::fromUtf8(id.getId().c_str()); + QVariant oldIndexData = index.data(Qt::EditRole); + if (newIndexData != oldIndexData) + { + mDocument.getUndoStack().push(new CSMWorld::ModifyCommand(*model(), index, newIndexData)); + } + } + } +} + +CSMWorld::ColumnBase::Display CSVWorld::DragRecordTable::getIndexDisplayType(const QModelIndex &index) const +{ + Q_ASSERT(model() != NULL); + + if (index.isValid()) + { + QVariant display = model()->headerData(index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display); + if (display.isValid()) + { + return static_cast(display.toInt()); + } + } + return CSMWorld::ColumnBase::Display_None; } diff --git a/apps/opencs/view/world/dragrecordtable.hpp b/apps/opencs/view/world/dragrecordtable.hpp index 48f9e25280..560864ba5a 100644 --- a/apps/opencs/view/world/dragrecordtable.hpp +++ b/apps/opencs/view/world/dragrecordtable.hpp @@ -4,6 +4,8 @@ #include #include +#include "../../model/world/columnbase.hpp" + class QWidget; class QAction; @@ -38,6 +40,11 @@ namespace CSVWorld void dragEnterEvent(QDragEnterEvent *event); void dragMoveEvent(QDragMoveEvent *event); + + void dropEvent(QDropEvent *event); + + private: + CSMWorld::ColumnBase::Display getIndexDisplayType(const QModelIndex &index) const; }; } diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 072b645c42..0ec701a65a 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -697,36 +697,6 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event) } } -void CSVWorld::Table::dropEvent(QDropEvent *event) -{ - QModelIndex index = indexAt (event->pos()); - - if (!index.isValid()) - { - return; - } - - const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); - if (!mime) // May happen when non-records (e.g. plain text) are dragged and dropped - return; - - if (mime->fromDocument (mDocument)) - { - CSMWorld::ColumnBase::Display display = static_cast - (mModel->headerData (index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); - - if (mime->holdsType (display)) - { - CSMWorld::UniversalId record (mime->returnMatching (display)); - - std::auto_ptr command (new CSMWorld::ModifyCommand - (*mProxyModel, index, QVariant (QString::fromUtf8 (record.getId().c_str())))); - - mDocument.getUndoStack().push (command.release()); - } - } //TODO handle drops from different document -} - std::vector CSVWorld::Table::getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const { const int count = mModel->columnCount(); diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 67bf3fe857..38fcd83bd6 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -76,8 +76,6 @@ namespace CSVWorld void mouseMoveEvent(QMouseEvent *event); - void dropEvent(QDropEvent *event); - protected: virtual void mouseDoubleClickEvent (QMouseEvent *event); From 2ce269c0fc2eff88d0dc0e2f7ce971255e842f1e Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 21 Jun 2015 18:18:24 +0200 Subject: [PATCH 26/53] Werewolf stats compatibility with old save files --- apps/openmw/mwmechanics/npcstats.cpp | 23 +++------------- apps/openmw/mwworld/player.cpp | 6 +++++ components/esm/esmreader.cpp | 11 ++++++++ components/esm/esmreader.hpp | 2 ++ components/esm/npcstats.cpp | 40 +++++++++++++++++++++------- components/esm/npcstats.hpp | 11 +++----- 6 files changed, 56 insertions(+), 37 deletions(-) diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 577c76c97b..b9aa8b301c 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -447,16 +447,8 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const state.mDisposition = mDisposition; for (int i=0; i > skills(mSkills, mSkills + sizeof(mSkills)/sizeof(mSkills[0])); + + for (int i=0; i<27; ++i) + { + ESM::StatState skill; + skill.load(esm); + skills.push_back(skill); + } + + int i=0; + for (std::vector >::iterator it = skills.begin(); it != skills.end(); ++i) + { + if (i%2 == 1) + it = skills.erase(it); + else + ++it; + } + assert(skills.size() == 27); + std::copy(skills.begin(), skills.end(), mSkills); } + // No longer used bool hasWerewolfAttributes = false; esm.getHNOT (hasWerewolfAttributes, "HWAT"); - if (hasWerewolfAttributes) { + ESM::StatState dummy; for (int i=0; i<8; ++i) - mWerewolfAttributes[i].load (esm); + dummy.load(esm); + mWerewolfDeprecatedData = true; } mIsWerewolf = false; @@ -112,10 +136,7 @@ void ESM::NpcStats::save (ESMWriter &esm) const esm.writeHNT ("DISP", mDisposition); for (int i=0; i<27; ++i) - { - mSkills[i].mRegular.save (esm); - mSkills[i].mWerewolf.save (esm); - } + mSkills[i].save (esm); if (mIsWerewolf) esm.writeHNT ("WOLF", mIsWerewolf); @@ -147,6 +168,7 @@ void ESM::NpcStats::save (ESMWriter &esm) const void ESM::NpcStats::blank() { + mWerewolfDeprecatedData = false; mIsWerewolf = false; mDisposition = 0; mBounty = 0; diff --git a/components/esm/npcstats.hpp b/components/esm/npcstats.hpp index 0138ab2098..9b27f587c7 100644 --- a/components/esm/npcstats.hpp +++ b/components/esm/npcstats.hpp @@ -16,12 +16,6 @@ namespace ESM struct NpcStats { - struct Skill - { - StatState mRegular; - StatState mWerewolf; - }; - struct Faction { bool mExpelled; @@ -31,12 +25,13 @@ namespace ESM Faction(); }; - StatState mWerewolfAttributes[8]; bool mIsWerewolf; + bool mWerewolfDeprecatedData; + std::map mFactions; // lower case IDs int mDisposition; - Skill mSkills[27]; + StatState mSkills[27]; int mBounty; int mReputation; int mWerewolfKills; From d606b62688e14ea214d0939fec908c6996cf6b82 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sun, 21 Jun 2015 21:35:00 +0300 Subject: [PATCH 27/53] Nested tables accept drops --- apps/opencs/view/world/dragrecordtable.cpp | 12 +++++++-- apps/opencs/view/world/nestedtable.cpp | 29 +++++++++------------- apps/opencs/view/world/nestedtable.hpp | 12 +++------ 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index 3712348e22..8d01cff3ef 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -12,7 +12,13 @@ void CSVWorld::DragRecordTable::startDragFromTable (const CSVWorld::DragRecordTable& table) { - CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (table.getDraggedRecords(), mDocument); + std::vector records = table.getDraggedRecords(); + if (records.empty()) + { + return; + } + + CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (records, mDocument); if (mime) { @@ -27,7 +33,9 @@ CSVWorld::DragRecordTable::DragRecordTable (CSMDoc::Document& document, QWidget* QTableView(parent), mDocument(document), mEditLock(false) -{} +{ + setAcceptDrops(true); +} void CSVWorld::DragRecordTable::setEditLock (bool locked) { diff --git a/apps/opencs/view/world/nestedtable.cpp b/apps/opencs/view/world/nestedtable.cpp index 112873cb9a..92df59a5fc 100644 --- a/apps/opencs/view/world/nestedtable.cpp +++ b/apps/opencs/view/world/nestedtable.cpp @@ -14,8 +14,7 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document, CSMWorld::UniversalId id, CSMWorld::NestedTableProxyModel* model, QWidget* parent) - : QTableView(parent), - mUndoStack(document.getUndoStack()), + : DragRecordTable(document, parent), mModel(model) { mDispatcher = new CSMWorld::CommandDispatcher (document, id, this); @@ -47,8 +46,6 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document, setModel(model); - setAcceptDrops(true); - mAddNewRowAction = new QAction (tr ("Add new row"), this); connect(mAddNewRowAction, SIGNAL(triggered()), @@ -60,12 +57,10 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document, this, SLOT(removeRowActionTriggered())); } -void CSVWorld::NestedTable::dragEnterEvent(QDragEnterEvent *event) -{ -} - -void CSVWorld::NestedTable::dragMoveEvent(QDragMoveEvent *event) +std::vector CSVWorld::NestedTable::getDraggedRecords() const { + // No drag support for nested tables + return std::vector(); } void CSVWorld::NestedTable::contextMenuEvent (QContextMenuEvent *event) @@ -84,16 +79,16 @@ void CSVWorld::NestedTable::contextMenuEvent (QContextMenuEvent *event) void CSVWorld::NestedTable::removeRowActionTriggered() { - mUndoStack.push(new CSMWorld::DeleteNestedCommand(*(mModel->model()), - mModel->getParentId(), - selectionModel()->selectedRows().begin()->row(), - mModel->getParentColumn())); + mDocument.getUndoStack().push(new CSMWorld::DeleteNestedCommand(*(mModel->model()), + mModel->getParentId(), + selectionModel()->selectedRows().begin()->row(), + mModel->getParentColumn())); } void CSVWorld::NestedTable::addNewRowActionTriggered() { - mUndoStack.push(new CSMWorld::AddNestedCommand(*(mModel->model()), - mModel->getParentId(), - selectionModel()->selectedRows().size(), - mModel->getParentColumn())); + mDocument.getUndoStack().push(new CSMWorld::AddNestedCommand(*(mModel->model()), + mModel->getParentId(), + selectionModel()->selectedRows().size(), + mModel->getParentColumn())); } diff --git a/apps/opencs/view/world/nestedtable.hpp b/apps/opencs/view/world/nestedtable.hpp index 5db977942a..1129204011 100644 --- a/apps/opencs/view/world/nestedtable.hpp +++ b/apps/opencs/view/world/nestedtable.hpp @@ -1,10 +1,10 @@ #ifndef CSV_WORLD_NESTEDTABLE_H #define CSV_WORLD_NESTEDTABLE_H -#include #include -class QUndoStack; +#include "dragrecordtable.hpp" + class QAction; class QContextMenuEvent; @@ -22,13 +22,12 @@ namespace CSMDoc namespace CSVWorld { - class NestedTable : public QTableView + class NestedTable : public DragRecordTable { Q_OBJECT QAction *mAddNewRowAction; QAction *mRemoveRowAction; - QUndoStack& mUndoStack; CSMWorld::NestedTableProxyModel* mModel; CSMWorld::CommandDispatcher *mDispatcher; @@ -38,10 +37,7 @@ namespace CSVWorld CSMWorld::NestedTableProxyModel* model, QWidget* parent = NULL); - protected: - void dragEnterEvent(QDragEnterEvent *event); - - void dragMoveEvent(QDragMoveEvent *event); + virtual std::vector getDraggedRecords() const; private: void contextMenuEvent (QContextMenuEvent *event); From 3f54f77647923571a42b4ceb5c18295ce25496c0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 21 Jun 2015 22:15:35 +0200 Subject: [PATCH 28/53] essimporter build fix --- apps/essimporter/convertacdt.cpp | 6 +++--- apps/essimporter/convertplayer.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/essimporter/convertacdt.cpp b/apps/essimporter/convertacdt.cpp index 55a20ec3df..8f090b3fc4 100644 --- a/apps/essimporter/convertacdt.cpp +++ b/apps/essimporter/convertacdt.cpp @@ -41,9 +41,9 @@ namespace ESSImport { for (int i=0; i Date: Tue, 23 Jun 2015 05:06:49 +0200 Subject: [PATCH 29/53] Fix an uninitialized variable --- components/esm/npcstats.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/components/esm/npcstats.cpp b/components/esm/npcstats.cpp index 6394a29da6..e854410b1f 100644 --- a/components/esm/npcstats.cpp +++ b/components/esm/npcstats.cpp @@ -32,6 +32,7 @@ void ESM::NpcStats::load (ESMReader &esm) for (int i=0; i<27; ++i) mSkills[i].load (esm); + mWerewolfDeprecatedData = false; if (esm.peekNextSub("STBA")) { // we have deprecated werewolf skills, stored interleaved From 33a3dabc313665a83384b373a5f5decba8974e54 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 24 Jun 2015 03:50:36 +0200 Subject: [PATCH 30/53] An alchemy effect listed more than once in the same ingredient should not automatically create a potion of that effect (Bug #2722) --- apps/openmw/mwmechanics/alchemy.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index 58c42ddb81..1d43c71ffa 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -44,6 +44,8 @@ std::set MWMechanics::Alchemy::listEffects() const { const MWWorld::LiveCellRef *ingredient = iter->get(); + std::set seenEffects; + for (int i=0; i<4; ++i) if (ingredient->mBase->mData.mEffectID[i]!=-1) { @@ -51,7 +53,8 @@ std::set MWMechanics::Alchemy::listEffects() const ingredient->mBase->mData.mEffectID[i], ingredient->mBase->mData.mSkills[i]!=-1 ? ingredient->mBase->mData.mSkills[i] : ingredient->mBase->mData.mAttributes[i]); - ++effects[key]; + if (seenEffects.insert(key).second) + ++effects[key]; } } } From 6f34a0501a0d8a2562716fd009983644e9d4ca5b Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 24 Jun 2015 03:52:27 +0200 Subject: [PATCH 31/53] Attempting to make a potion with no effects removes the ingredients (Fixes #2722) --- apps/openmw/mwmechanics/alchemy.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index 1d43c71ffa..2fc9fe42f8 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -463,7 +463,10 @@ MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& na return Result_NoName; if (listEffects().empty()) + { + removeIngredients(); return Result_NoEffects; + } if (beginEffects() == endEffects()) { From d1339a643afced0d1e502eebe79c947b2c4ad953 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 24 Jun 2015 15:07:09 +0300 Subject: [PATCH 32/53] Fix for NestedTableProxyModel::forwardDataChanged() --- apps/opencs/model/world/nestedtableproxymodel.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/opencs/model/world/nestedtableproxymodel.cpp b/apps/opencs/model/world/nestedtableproxymodel.cpp index acf1977168..052e629aac 100644 --- a/apps/opencs/model/world/nestedtableproxymodel.cpp +++ b/apps/opencs/model/world/nestedtableproxymodel.cpp @@ -192,4 +192,8 @@ void CSMWorld::NestedTableProxyModel::forwardDataChanged (const QModelIndex& top emit dataChanged(index(0,0), index(mMainModel->rowCount(parent)-1, mMainModel->columnCount(parent)-1)); } + else if (topLeft.parent() == parent && bottomRight.parent() == parent) + { + emit dataChanged(index(topLeft.row(), topLeft.column()), index(bottomRight.row(), bottomRight.column())); + } } From 270c17faa786917ac03f44906c055eec70da577d Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 24 Jun 2015 16:36:09 +0300 Subject: [PATCH 33/53] Prevent drops on non-editable table cells --- apps/opencs/view/world/dragrecordtable.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index 8d01cff3ef..5e8ddae26d 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -52,7 +52,10 @@ void CSVWorld::DragRecordTable::dragMoveEvent(QDragMoveEvent *event) QModelIndex index = indexAt(event->pos()); if (CSVWorld::DragDropUtils::canAcceptData(*event, getIndexDisplayType(index))) { - event->accept(); + if (index.flags() & Qt::ItemIsEditable) + { + event->accept(); + } } else { From e29d9bcc8eac923ecf90c73733302033e01c2700 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 24 Jun 2015 17:29:47 +0200 Subject: [PATCH 34/53] use a namespace instead of a class with only static functions --- apps/opencs/view/world/dragdroputils.hpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/opencs/view/world/dragdroputils.hpp b/apps/opencs/view/world/dragdroputils.hpp index 88e2958a53..d1d780708e 100644 --- a/apps/opencs/view/world/dragdroputils.hpp +++ b/apps/opencs/view/world/dragdroputils.hpp @@ -13,18 +13,17 @@ namespace CSMWorld namespace CSVWorld { - class DragDropUtils + namespace DragDropUtils { - public: - static const CSMWorld::TableMimeData *getTableMimeData(const QDropEvent &event); + const CSMWorld::TableMimeData *getTableMimeData(const QDropEvent &event); - static bool canAcceptData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); - ///< Checks whether the \a event contains a valid CSMWorld::TableMimeData that holds the \a type + bool canAcceptData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); + ///< Checks whether the \a event contains a valid CSMWorld::TableMimeData that holds the \a type - static CSMWorld::UniversalId getAcceptedData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); - ///< Gets the accepted data from the \a event using the \a type - ///< \return Type_None if the \a event data doesn't holds the \a type - }; + CSMWorld::UniversalId getAcceptedData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); + ///< Gets the accepted data from the \a event using the \a type + ///< \return Type_None if the \a event data doesn't holds the \a type + } } #endif From 21f0b586ec1d09828cf75117804b09df3c480f64 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 24 Jun 2015 20:01:29 +0300 Subject: [PATCH 35/53] Rows with the same topic but in different letter case can be reordered --- apps/opencs/model/world/infocollection.cpp | 3 ++- apps/opencs/view/world/table.cpp | 21 +++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/apps/opencs/model/world/infocollection.cpp b/apps/opencs/model/world/infocollection.cpp index a508d28f3d..560be8131e 100644 --- a/apps/opencs/model/world/infocollection.cpp +++ b/apps/opencs/model/world/infocollection.cpp @@ -97,7 +97,8 @@ bool CSMWorld::InfoCollection::reorderRows (int baseIndex, const std::vector #include +#include + #include "../../model/doc/document.hpp" #include "../../model/world/data.hpp" @@ -128,17 +130,24 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) { int row = mProxyModel->mapToSource ( mProxyModel->index (selectedRows.begin()->row(), 0)).row(); + QString curData = mModel->data(mModel->index(row, column)).toString(); - if (row>0 && mModel->data (mModel->index (row, column))== - mModel->data (mModel->index (row-1, column))) + if (row > 0) { - menu.addAction (mMoveUpAction); + QString prevData = mModel->data(mModel->index(row - 1, column)).toString(); + if (Misc::StringUtils::ciEqual(curData.toStdString(), prevData.toStdString())) + { + menu.addAction(mMoveUpAction); + } } - if (rowrowCount()-1 && mModel->data (mModel->index (row, column))== - mModel->data (mModel->index (row+1, column))) + if (row < mModel->rowCount() - 1) { - menu.addAction (mMoveDownAction); + QString nextData = mModel->data(mModel->index(row + 1, column)).toString(); + if (Misc::StringUtils::ciEqual(curData.toStdString(), nextData.toStdString())) + { + menu.addAction(mMoveDownAction); + } } } } From 5b82b9d9d0efc0a395c289e546bd87cae00dcea3 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 25 Jun 2015 11:20:35 +0300 Subject: [PATCH 36/53] ReferenceCreator accepts drops of Cell ID --- apps/opencs/view/world/referencecreator.cpp | 5 +++-- apps/opencs/view/world/referencecreator.hpp | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/opencs/view/world/referencecreator.cpp b/apps/opencs/view/world/referencecreator.cpp index 81efb17ab6..2b0d44df0c 100644 --- a/apps/opencs/view/world/referencecreator.cpp +++ b/apps/opencs/view/world/referencecreator.cpp @@ -2,7 +2,6 @@ #include "referencecreator.hpp" #include -#include #include "../../model/doc/document.hpp" @@ -12,6 +11,8 @@ #include "../../model/world/idtable.hpp" #include "../../model/world/idcompletionmanager.hpp" +#include "../widget/droplineedit.hpp" + std::string CSVWorld::ReferenceCreator::getId() const { return mId; @@ -80,7 +81,7 @@ CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack& QLabel *label = new QLabel ("Cell", this); insertBeforeButtons (label, false); - mCell = new QLineEdit (this); + mCell = new CSVWidget::DropLineEdit(CSMWorld::ColumnBase::Display_Cell, this); mCell->setCompleter(completionManager.getCompleter(CSMWorld::ColumnBase::Display_Cell).get()); insertBeforeButtons (mCell, true); diff --git a/apps/opencs/view/world/referencecreator.hpp b/apps/opencs/view/world/referencecreator.hpp index 7f56143c9f..c230d01268 100644 --- a/apps/opencs/view/world/referencecreator.hpp +++ b/apps/opencs/view/world/referencecreator.hpp @@ -3,13 +3,16 @@ #include "genericcreator.hpp" -class QLineEdit; - namespace CSMWorld { class IdCompletionManager; } +namespace CSVWidget +{ + class DropLineEdit; +} + namespace CSVWorld { @@ -17,7 +20,7 @@ namespace CSVWorld { Q_OBJECT - QLineEdit *mCell; + CSVWidget::DropLineEdit *mCell; std::string mId; private: From d282bead236fe73611dba32f15220e6b73a1ca10 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 25 Jun 2015 11:24:19 +0300 Subject: [PATCH 37/53] InfoCreator accepts drops of Topic/Journal ID --- apps/opencs/view/world/infocreator.cpp | 5 +++-- apps/opencs/view/world/infocreator.hpp | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/opencs/view/world/infocreator.cpp b/apps/opencs/view/world/infocreator.cpp index 916427fc24..268a82a280 100644 --- a/apps/opencs/view/world/infocreator.cpp +++ b/apps/opencs/view/world/infocreator.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -17,6 +16,8 @@ #include "../../model/world/idtable.hpp" #include "../../model/world/idcompletionmanager.hpp" +#include "../widget/droplineedit.hpp" + std::string CSVWorld::InfoCreator::getId() const { std::string id = Misc::StringUtils::lowerCase (mTopic->text().toUtf8().constData()); @@ -48,12 +49,12 @@ CSVWorld::InfoCreator::InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack, QLabel *label = new QLabel ("Topic", this); insertBeforeButtons (label, false); - mTopic = new QLineEdit (this); CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Topic; if (getCollectionId().getType() == CSMWorld::UniversalId::Type_JournalInfos) { displayType = CSMWorld::ColumnBase::Display_Journal; } + mTopic = new CSVWidget::DropLineEdit(displayType, this); mTopic->setCompleter(completionManager.getCompleter(displayType).get()); insertBeforeButtons (mTopic, true); diff --git a/apps/opencs/view/world/infocreator.hpp b/apps/opencs/view/world/infocreator.hpp index 1928004bb9..d131e3fac5 100644 --- a/apps/opencs/view/world/infocreator.hpp +++ b/apps/opencs/view/world/infocreator.hpp @@ -3,21 +3,24 @@ #include "genericcreator.hpp" -class QLineEdit; - namespace CSMWorld { class InfoCollection; class IdCompletionManager; } +namespace CSVWidget +{ + class DropLineEdit; +} + namespace CSVWorld { class InfoCreator : public GenericCreator { Q_OBJECT - QLineEdit *mTopic; + CSVWidget::DropLineEdit *mTopic; virtual std::string getId() const; From 6fbdbb11d5c332913aa20d57707063245fb36d92 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 25 Jun 2015 12:03:40 +0200 Subject: [PATCH 38/53] added refrash menu item to report table (Fixes #2620) --- apps/opencs/model/doc/document.cpp | 4 ++-- apps/opencs/model/doc/document.hpp | 2 +- apps/opencs/model/tools/tools.cpp | 13 +++++++++---- apps/opencs/model/tools/tools.hpp | 7 +++++-- apps/opencs/view/tools/reportsubview.cpp | 22 ++++++++++++++++++++-- apps/opencs/view/tools/reportsubview.hpp | 6 ++++++ apps/opencs/view/tools/reporttable.cpp | 18 ++++++++++++++++-- apps/opencs/view/tools/reporttable.hpp | 9 ++++++++- 8 files changed, 67 insertions(+), 14 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 1e6ae54550..cb349d8be3 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2369,9 +2369,9 @@ void CSMDoc::Document::save() emit stateChanged (getState(), this); } -CSMWorld::UniversalId CSMDoc::Document::verify() +CSMWorld::UniversalId CSMDoc::Document::verify (const CSMWorld::UniversalId& reportId) { - CSMWorld::UniversalId id = mTools.runVerifier(); + CSMWorld::UniversalId id = mTools.runVerifier (reportId); emit stateChanged (getState(), this); return id; } diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 4aaaf40b03..557f3cb23c 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -120,7 +120,7 @@ namespace CSMDoc void save(); - CSMWorld::UniversalId verify(); + CSMWorld::UniversalId verify (const CSMWorld::UniversalId& reportId = CSMWorld::UniversalId()); CSMWorld::UniversalId newSearch(); diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index f0d649f388..c9c1160918 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -146,14 +146,19 @@ CSMTools::Tools::~Tools() delete iter->second; } -CSMWorld::UniversalId CSMTools::Tools::runVerifier() +CSMWorld::UniversalId CSMTools::Tools::runVerifier (const CSMWorld::UniversalId& reportId) { - mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); - mActiveReports[CSMDoc::State_Verifying] = mNextReportNumber-1; + int reportNumber = reportId.getType()==CSMWorld::UniversalId::Type_VerificationResults ? + reportId.getIndex() : mNextReportNumber++; + + if (mReports.find (reportNumber)==mReports.end()) + mReports.insert (std::make_pair (reportNumber, new ReportModel)); + + mActiveReports[CSMDoc::State_Verifying] = reportNumber; getVerifier()->start(); - return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, mNextReportNumber-1); + return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, reportNumber); } CSMWorld::UniversalId CSMTools::Tools::newSearch() diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 2912fc4717..78484d15d9 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -57,8 +57,11 @@ namespace CSMTools virtual ~Tools(); - CSMWorld::UniversalId runVerifier(); - ///< \return ID of the report for this verification run + /// \param reportId If a valid VerificationResults ID, run verifier for the + /// specified report instead of creating a new one. + /// + /// \return ID of the report for this verification run + CSMWorld::UniversalId runVerifier (const CSMWorld::UniversalId& reportId = CSMWorld::UniversalId()); /// Return ID of the report for this search. CSMWorld::UniversalId newSearch(); diff --git a/apps/opencs/view/tools/reportsubview.cpp b/apps/opencs/view/tools/reportsubview.cpp index 492874c01b..42c4d40da0 100644 --- a/apps/opencs/view/tools/reportsubview.cpp +++ b/apps/opencs/view/tools/reportsubview.cpp @@ -4,12 +4,18 @@ #include "reporttable.hpp" CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) -: CSVDoc::SubView (id) +: CSVDoc::SubView (id), mDocument (document), mRefreshState (0) { - setWidget (mTable = new ReportTable (document, id, false, this)); + if (id.getType()==CSMWorld::UniversalId::Type_VerificationResults) + mRefreshState = CSMDoc::State_Verifying; + + setWidget (mTable = new ReportTable (document, id, false, mRefreshState, this)); connect (mTable, SIGNAL (editRequest (const CSMWorld::UniversalId&, const std::string&)), SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&))); + + if (mRefreshState==CSMDoc::State_Verifying) + connect (mTable, SIGNAL (refreshRequest()), this, SLOT (refreshRequest())); } void CSVTools::ReportSubView::setEditLock (bool locked) @@ -21,3 +27,15 @@ void CSVTools::ReportSubView::updateUserSetting (const QString &name, const QStr { mTable->updateUserSetting (name, list); } + +void CSVTools::ReportSubView::refreshRequest() +{ + if (!(mDocument.getState() & mRefreshState)) + { + if (mRefreshState==CSMDoc::State_Verifying) + { + mTable->clear(); + mDocument.verify (getUniversalId()); + } + } +} diff --git a/apps/opencs/view/tools/reportsubview.hpp b/apps/opencs/view/tools/reportsubview.hpp index 7e8a08e3cd..b8eb2690a7 100644 --- a/apps/opencs/view/tools/reportsubview.hpp +++ b/apps/opencs/view/tools/reportsubview.hpp @@ -20,6 +20,8 @@ namespace CSVTools Q_OBJECT ReportTable *mTable; + CSMDoc::Document& mDocument; + int mRefreshState; public: @@ -28,6 +30,10 @@ namespace CSVTools virtual void setEditLock (bool locked); virtual void updateUserSetting (const QString &, const QStringList &); + + private slots: + + void refreshRequest(); }; } diff --git a/apps/opencs/view/tools/reporttable.cpp b/apps/opencs/view/tools/reporttable.cpp index e530e1159e..6ef88bfdd8 100644 --- a/apps/opencs/view/tools/reporttable.cpp +++ b/apps/opencs/view/tools/reporttable.cpp @@ -74,7 +74,12 @@ void CSVTools::ReportTable::contextMenuEvent (QContextMenuEvent *event) if (found) menu.addAction (mReplaceAction); + } + if (mRefreshAction) + { + mRefreshAction->setEnabled ((mDocument.getState() & mRefreshState)==0); + menu.addAction (mRefreshAction); } menu.exec (event->globalPos()); @@ -134,8 +139,10 @@ void CSVTools::ReportTable::mouseDoubleClickEvent (QMouseEvent *event) } CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, - const CSMWorld::UniversalId& id, bool richTextDescription, QWidget *parent) -: CSVWorld::DragRecordTable (document, parent), mModel (document.getReport (id)) + const CSMWorld::UniversalId& id, bool richTextDescription, int refreshState, + QWidget *parent) +: CSVWorld::DragRecordTable (document, parent), mModel (document.getReport (id)), + mRefreshAction (0), mRefreshState (refreshState) { #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) horizontalHeader()->setSectionResizeMode (QHeaderView::Interactive); @@ -171,6 +178,13 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, connect (mReplaceAction, SIGNAL (triggered()), this, SIGNAL (replaceRequest())); addAction (mReplaceAction); + if (mRefreshState) + { + mRefreshAction = new QAction (tr ("Refresh"), this); + connect (mRefreshAction, SIGNAL (triggered()), this, SIGNAL (refreshRequest())); + addAction (mRefreshAction); + } + mDoubleClickActions.insert (std::make_pair (Qt::NoModifier, Action_Edit)); mDoubleClickActions.insert (std::make_pair (Qt::ShiftModifier, Action_Remove)); mDoubleClickActions.insert (std::make_pair (Qt::ControlModifier, Action_EditAndRemove)); diff --git a/apps/opencs/view/tools/reporttable.hpp b/apps/opencs/view/tools/reporttable.hpp index 95ab07cbbf..4f77a57c4e 100644 --- a/apps/opencs/view/tools/reporttable.hpp +++ b/apps/opencs/view/tools/reporttable.hpp @@ -36,7 +36,9 @@ namespace CSVTools QAction *mShowAction; QAction *mRemoveAction; QAction *mReplaceAction; + QAction *mRefreshAction; std::map mDoubleClickActions; + int mRefreshState; private: @@ -49,8 +51,11 @@ namespace CSVTools public: /// \param richTextDescription Use rich text in the description column. + /// \param refreshState Document state to check for refresh function. If value is + /// 0 no refresh function exists. If the document current has the specified state + /// the refresh function is disabled. ReportTable (CSMDoc::Document& document, const CSMWorld::UniversalId& id, - bool richTextDescription, QWidget *parent = 0); + bool richTextDescription, int refreshState = 0, QWidget *parent = 0); virtual std::vector getDraggedRecords() const; @@ -76,6 +81,8 @@ namespace CSVTools void editRequest (const CSMWorld::UniversalId& id, const std::string& hint); void replaceRequest(); + + void refreshRequest(); }; } From 71f3b7ed4f6ab80592dfbf4ef03669e5909535b7 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 25 Jun 2015 20:21:51 +1000 Subject: [PATCH 39/53] Fix crash when user preference is missing. --- apps/opencs/model/tools/scriptcheck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/tools/scriptcheck.cpp b/apps/opencs/model/tools/scriptcheck.cpp index 928ae156f8..665edd7a33 100644 --- a/apps/opencs/model/tools/scriptcheck.cpp +++ b/apps/opencs/model/tools/scriptcheck.cpp @@ -120,7 +120,7 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages) void CSMTools::ScriptCheckStage::updateUserSetting (const QString& name, const QStringList& value) { - if (name=="script-editor/warnings") + if (name=="script-editor/warnings" && !value.isEmpty()) { if (value.at (0)=="Ignore") mWarningMode = Mode_Ignore; From c0f3d70f0662b79c2a8fd66fdef0f8ec61e61f50 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 25 Jun 2015 20:23:43 +1000 Subject: [PATCH 40/53] Use the new severity message attribute. --- apps/opencs/model/tools/pathgridcheck.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/opencs/model/tools/pathgridcheck.cpp b/apps/opencs/model/tools/pathgridcheck.cpp index 76edeb573d..69ee5a8098 100644 --- a/apps/opencs/model/tools/pathgridcheck.cpp +++ b/apps/opencs/model/tools/pathgridcheck.cpp @@ -30,9 +30,9 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message // check the number of pathgrid points if (pathgrid.mData.mS2 > static_cast(pathgrid.mPoints.size())) - messages.push_back (std::make_pair (id, pathgrid.mId + " has less points than expected")); + messages.add (id, pathgrid.mId + " has less points than expected", "", CSMDoc::Message::Severity_Error); else if (pathgrid.mData.mS2 > static_cast(pathgrid.mPoints.size())) - messages.push_back (std::make_pair (id, pathgrid.mId + " has more points than expected")); + messages.add (id, pathgrid.mId + " has more points than expected", "", CSMDoc::Message::Severity_Error); std::vector pointList(pathgrid.mPoints.size()); std::vector duplList; @@ -51,7 +51,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message std::ostringstream ss; ss << "has a duplicate edge between points" << pathgrid.mEdges[i].mV0 << " and " << pathgrid.mEdges[i].mV1; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error); break; } } @@ -64,7 +64,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message { std::ostringstream ss; ss << " has an edge connecting a non-existent point " << pathgrid.mEdges[i].mV0; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error); } } @@ -75,13 +75,13 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message { std::ostringstream ss; ss << " has has less edges than expected for point " << i; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error); } else if (pathgrid.mPoints[i].mConnectionNum < pointList[i].mConnectionNum) { std::ostringstream ss; ss << " has has more edges than expected for point " << i; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error); } // check that edges are bidirectional @@ -101,7 +101,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message { std::ostringstream ss; ss << " has a missing edge between points " << i << " and " << pointList[i].mOtherIndex[j]; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error); } } @@ -124,7 +124,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message << ") x=" << pathgrid.mPoints[i].mX << ", y=" << pathgrid.mPoints[i].mY << ", z=" << pathgrid.mPoints[i].mZ; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Warning); duplList.push_back(i); break; @@ -143,7 +143,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message << ") x=" << pathgrid.mPoints[i].mX << ", y=" << pathgrid.mPoints[i].mY << ", z=" << pathgrid.mPoints[i].mZ; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Warning); } } From 69db0179ca104699d70142286a5a1d226177644f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 25 Jun 2015 13:05:57 +0200 Subject: [PATCH 41/53] update refresh menu item on stateChanged signal instead of when opening the menu --- apps/opencs/view/tools/reportsubview.cpp | 5 +++++ apps/opencs/view/tools/reporttable.cpp | 10 +++++++--- apps/opencs/view/tools/reporttable.hpp | 4 ++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/tools/reportsubview.cpp b/apps/opencs/view/tools/reportsubview.cpp index 42c4d40da0..e29447f250 100644 --- a/apps/opencs/view/tools/reportsubview.cpp +++ b/apps/opencs/view/tools/reportsubview.cpp @@ -15,7 +15,12 @@ CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc: SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&))); if (mRefreshState==CSMDoc::State_Verifying) + { connect (mTable, SIGNAL (refreshRequest()), this, SLOT (refreshRequest())); + + connect (&document, SIGNAL (stateChanged (int, CSMDoc::Document *)), + mTable, SLOT (stateChanged (int, CSMDoc::Document *))); + } } void CSVTools::ReportSubView::setEditLock (bool locked) diff --git a/apps/opencs/view/tools/reporttable.cpp b/apps/opencs/view/tools/reporttable.cpp index 6ef88bfdd8..ca6b0dabfb 100644 --- a/apps/opencs/view/tools/reporttable.cpp +++ b/apps/opencs/view/tools/reporttable.cpp @@ -77,10 +77,7 @@ void CSVTools::ReportTable::contextMenuEvent (QContextMenuEvent *event) } if (mRefreshAction) - { - mRefreshAction->setEnabled ((mDocument.getState() & mRefreshState)==0); menu.addAction (mRefreshAction); - } menu.exec (event->globalPos()); } @@ -181,6 +178,7 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, if (mRefreshState) { mRefreshAction = new QAction (tr ("Refresh"), this); + mRefreshAction->setEnabled (!(mDocument.getState() & mRefreshState)); connect (mRefreshAction, SIGNAL (triggered()), this, SIGNAL (refreshRequest())); addAction (mRefreshAction); } @@ -301,3 +299,9 @@ void CSVTools::ReportTable::clear() { mModel->clear(); } + +void CSVTools::ReportTable::stateChanged (int state, CSMDoc::Document *document) +{ + if (mRefreshAction) + mRefreshAction->setEnabled (!(state & mRefreshState)); +} diff --git a/apps/opencs/view/tools/reporttable.hpp b/apps/opencs/view/tools/reporttable.hpp index 4f77a57c4e..e19b327e45 100644 --- a/apps/opencs/view/tools/reporttable.hpp +++ b/apps/opencs/view/tools/reporttable.hpp @@ -76,6 +76,10 @@ namespace CSVTools void removeSelection(); + public slots: + + void stateChanged (int state, CSMDoc::Document *document); + signals: void editRequest (const CSMWorld::UniversalId& id, const std::string& hint); From 867ce686ae3bbd4b571c467502d035334f63304c Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 25 Jun 2015 19:30:53 +0300 Subject: [PATCH 42/53] Proper conversion to QString for DropLineEdit::dropEvent() --- apps/opencs/view/widget/droplineedit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/view/widget/droplineedit.cpp b/apps/opencs/view/widget/droplineedit.cpp index 98f1d81c30..1df598cb8d 100644 --- a/apps/opencs/view/widget/droplineedit.cpp +++ b/apps/opencs/view/widget/droplineedit.cpp @@ -35,7 +35,7 @@ void CSVWidget::DropLineEdit::dropEvent(QDropEvent *event) if (CSVWorld::DragDropUtils::canAcceptData(*event, mDropType)) { CSMWorld::UniversalId id = CSVWorld::DragDropUtils::getAcceptedData(*event, mDropType); - setText(id.getId().c_str()); + setText(QString::fromUtf8(id.getId().c_str())); emit tableMimeDataDropped(id, CSVWorld::DragDropUtils::getTableMimeData(*event)->getDocumentPtr()); } } From 844e5c504d6d9f00d93e083274243fb1730c5112 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 25 Jun 2015 19:41:26 +0300 Subject: [PATCH 43/53] Fix conversion to QString --- apps/opencs/model/world/infotableproxymodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index 3e564506ce..4ee9fa60ce 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -9,7 +9,7 @@ namespace { QString toLower(const QString &str) { - return Misc::StringUtils::lowerCase(str.toStdString()).c_str(); + return QString::fromUtf8(Misc::StringUtils::lowerCase(str.toStdString()).c_str()); } } From ea97b0a20c3556f5f76d885677df2322ffe8cf04 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 25 Jun 2015 20:08:42 +0300 Subject: [PATCH 44/53] Refine InfoTableProxyModel::getFirstInfoRow() code --- .../model/world/infotableproxymodel.cpp | 25 ++++++++----------- .../model/world/infotableproxymodel.hpp | 3 +++ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index 4ee9fa60ce..e34c505668 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -16,7 +16,9 @@ namespace CSMWorld::InfoTableProxyModel::InfoTableProxyModel(CSMWorld::UniversalId::Type type, QObject *parent) : IdTableProxyModel(parent), mType(type), - mSourceModel(NULL) + mSourceModel(NULL), + mInfoColumnId(type == UniversalId::Type_TopicInfos ? Columns::ColumnId_Topic : + Columns::ColumnId_Journal) { Q_ASSERT(type == UniversalId::Type_TopicInfos || type == UniversalId::Type_JournalInfos); } @@ -54,26 +56,21 @@ bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QMod int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const { - Columns::ColumnId columnId = Columns::ColumnId_Topic; - if (mType == UniversalId::Type_JournalInfos) - { - columnId = Columns::ColumnId_Journal; - } - - int column = mSourceModel->findColumnIndex(columnId); - QString info = toLower(mSourceModel->data(mSourceModel->index(currentRow, column)).toString()); + int row = currentRow; + int column = mSourceModel->findColumnIndex(mInfoColumnId); + QString info = toLower(mSourceModel->data(mSourceModel->index(row, column)).toString()); if (mFirstRowCache.contains(info)) { return mFirstRowCache[info]; } - while (--currentRow >= 0 && - toLower(mSourceModel->data(mSourceModel->index(currentRow, column)).toString()) == info); - ++currentRow; + while (--row >= 0 && + toLower(mSourceModel->data(mSourceModel->index(row, column)).toString()) == info); + ++row; - mFirstRowCache[info] = currentRow; - return currentRow; + mFirstRowCache[info] = row; + return row; } void CSMWorld::InfoTableProxyModel::modelRowsChanged(const QModelIndex &/*parent*/, int /*start*/, int /*end*/) diff --git a/apps/opencs/model/world/infotableproxymodel.hpp b/apps/opencs/model/world/infotableproxymodel.hpp index 7b0cd8ede4..28d6017b31 100644 --- a/apps/opencs/model/world/infotableproxymodel.hpp +++ b/apps/opencs/model/world/infotableproxymodel.hpp @@ -4,6 +4,7 @@ #include #include "idtableproxymodel.hpp" +#include "columns.hpp" #include "universalid.hpp" namespace CSMWorld @@ -16,6 +17,8 @@ namespace CSMWorld UniversalId::Type mType; IdTableBase *mSourceModel; + Columns::ColumnId mInfoColumnId; + ///< Contains ID for Topic or Journal ID mutable QHash mFirstRowCache; From f3ff90e1fde2f46d980a3f2525b79f34edcc151d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 13:01:25 +0200 Subject: [PATCH 45/53] moved meta data into a new single-row table --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/doc/document.cpp | 3 --- apps/opencs/model/world/data.cpp | 29 +++++++++++++------------ apps/opencs/model/world/data.hpp | 10 ++++----- apps/opencs/model/world/metadata.cpp | 27 +++++++++++++++++++++++ apps/opencs/model/world/metadata.hpp | 29 +++++++++++++++++++++++++ apps/opencs/model/world/universalid.cpp | 1 + apps/opencs/model/world/universalid.hpp | 1 + 8 files changed, 78 insertions(+), 24 deletions(-) create mode 100644 apps/opencs/model/world/metadata.cpp create mode 100644 apps/opencs/model/world/metadata.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 5386da707f..3399b9dddb 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -26,7 +26,7 @@ opencs_units_noqt (model/world universalid record commands columnbase scriptcontext cell refidcollection refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection - idcompletionmanager + idcompletionmanager metadata ) opencs_hdrs_noqt (model/world diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 1e6ae54550..34ae3dd8ae 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2282,9 +2282,6 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, if (mNew) { - mData.setDescription (""); - mData.setAuthor (""); - if (mContentFiles.size()==1) createBase(); } diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 5acd80339e..3bd892618a 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -475,6 +475,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mDebugProfiles.addColumn (new ScriptColumn ( ScriptColumn::Type_Lines)); + mMetaData.appendBlankRecord ("sys::meta"); + addModel (new IdTable (&mGlobals), UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst); addModel (new IdTable (&mSkills), UniversalId::Type_Skill); @@ -515,6 +517,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc UniversalId::Type_Texture); addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Videos)), UniversalId::Type_Video); + addModel (new IdTable (&mMetaData), UniversalId::Type_MetaData); mRefLoadCache.clear(); // clear here rather than startLoading() and continueLoading() for multiple content files } @@ -803,6 +806,11 @@ const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) return mResourcesManager.get (id.getType()); } +const CSMWorld::MetaData& CSMWorld::Data::getMetaData() const +{ + return mMetaData.getRecord (0).get(); +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); @@ -847,9 +855,12 @@ int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base mBase = base; mProject = project; - mAuthor = mReader->getAuthor(); - mDescription = mReader->getDesc(); + MetaData metaData; + metaData.mId = "sys::meta"; + metaData.load (*mReader); + mMetaData.setRecord (0, Record (RecordBase::State_ModifiedOnly, 0, &metaData)); + return mReader->getRecordCount(); } @@ -1103,24 +1114,14 @@ int CSMWorld::Data::count (RecordBase::State state) const count (state, mPathgrids); } -void CSMWorld::Data::setDescription (const std::string& description) -{ - mDescription = description; -} - std::string CSMWorld::Data::getDescription() const { - return mDescription; -} - -void CSMWorld::Data::setAuthor (const std::string& author) -{ - mAuthor = author; + return mMetaData.getRecord (0).get().mDescription; } std::string CSMWorld::Data::getAuthor() const { - return mAuthor; + return mMetaData.getRecord (0).get().mAuthor; } std::vector CSMWorld::Data::getIds (bool listDeleted) const diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 060e47bd95..edfd4bc31c 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -44,6 +44,7 @@ #include "infocollection.hpp" #include "nestedinfocollection.hpp" #include "pathgrid.hpp" +#include "metadata.hpp" #ifndef Q_MOC_RUN #include "subcellcollection.hpp" #endif @@ -94,11 +95,10 @@ namespace CSMWorld RefIdCollection mReferenceables; RefCollection mRefs; IdCollection mFilters; + Collection mMetaData; const ResourcesManager& mResourcesManager; std::vector mModels; std::map mModelIndex; - std::string mAuthor; - std::string mDescription; ESM::ESMReader *mReader; const ESM::Dialogue *mDialogue; // last loaded dialogue bool mBase; @@ -238,6 +238,8 @@ namespace CSMWorld /// Throws an exception, if \a id does not match a resources list. const Resources& getResources (const UniversalId& id) const; + const MetaData& getMetaData() const; + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// @@ -267,12 +269,8 @@ namespace CSMWorld int count (RecordBase::State state) const; ///< Return number of top-level records with the given \a state. - void setDescription (const std::string& description); - std::string getDescription() const; - void setAuthor (const std::string& author); - std::string getAuthor() const; signals: diff --git a/apps/opencs/model/world/metadata.cpp b/apps/opencs/model/world/metadata.cpp new file mode 100644 index 0000000000..40b8e95197 --- /dev/null +++ b/apps/opencs/model/world/metadata.cpp @@ -0,0 +1,27 @@ + +#include "metadata.hpp" + +#include +#include +#include + +void CSMWorld::MetaData::blank() +{ + mFormat = ESM::Header::CurrentFormat; + mAuthor.clear(); + mDescription.clear(); +} + +void CSMWorld::MetaData::load (ESM::ESMReader& esm) +{ + mFormat = esm.getHeader().mFormat; + mAuthor = esm.getHeader().mData.author.toString(); + mDescription = esm.getHeader().mData.desc.toString(); +} + +void CSMWorld::MetaData::save (ESM::ESMWriter& esm) const +{ + esm.setFormat (mFormat); + esm.setAuthor (mAuthor); + esm.setDescription (mDescription); +} diff --git a/apps/opencs/model/world/metadata.hpp b/apps/opencs/model/world/metadata.hpp new file mode 100644 index 0000000000..f8df2690ec --- /dev/null +++ b/apps/opencs/model/world/metadata.hpp @@ -0,0 +1,29 @@ +#ifndef CSM_WOLRD_METADATA_H +#define CSM_WOLRD_METADATA_H + +#include + +namespace ESM +{ + class ESMReader; + class ESMWriter; +} + +namespace CSMWorld +{ + struct MetaData + { + std::string mId; + + int mFormat; + std::string mAuthor; + std::string mDescription; + + void blank(); + + void load (ESM::ESMReader& esm); + void save (ESM::ESMWriter& esm) const; + }; +} + +#endif diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index e496fe79bb..584bf5e702 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -120,6 +120,7 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Meta Data", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 0a9fa38473..752504bc45 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -131,6 +131,7 @@ namespace CSMWorld Type_StartScripts, Type_StartScript, Type_Search, + Type_MetaData, Type_RunLog }; From 1870b087e7b3f9454c5450cfdbe30f6b86358054 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 13:13:22 +0200 Subject: [PATCH 46/53] ported setting of meta data for saving to the new mechanism --- apps/opencs/model/doc/savingstages.cpp | 6 ++---- apps/opencs/model/world/data.cpp | 10 ---------- apps/opencs/model/world/data.hpp | 4 ---- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index d6258da6ae..f78c57ecd6 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -53,18 +53,16 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages) mState.getWriter().clearMaster(); - mState.getWriter().setFormat (0); - if (mSimple) { mState.getWriter().setAuthor (""); mState.getWriter().setDescription (""); mState.getWriter().setRecordCount (0); + mState.getWriter().setFormat (ESM::Header::CurrentFormat); } else { - mState.getWriter().setAuthor (mDocument.getData().getAuthor()); - mState.getWriter().setDescription (mDocument.getData().getDescription()); + mDocument.getData().getMetaData().save (mState.getWriter()); mState.getWriter().setRecordCount ( mDocument.getData().count (CSMWorld::RecordBase::State_Modified) + mDocument.getData().count (CSMWorld::RecordBase::State_ModifiedOnly) + diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 3bd892618a..368c7a766f 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -1114,16 +1114,6 @@ int CSMWorld::Data::count (RecordBase::State state) const count (state, mPathgrids); } -std::string CSMWorld::Data::getDescription() const -{ - return mMetaData.getRecord (0).get().mDescription; -} - -std::string CSMWorld::Data::getAuthor() const -{ - return mMetaData.getRecord (0).get().mAuthor; -} - std::vector CSMWorld::Data::getIds (bool listDeleted) const { std::vector ids; diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index edfd4bc31c..15e39b9bab 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -269,10 +269,6 @@ namespace CSMWorld int count (RecordBase::State state) const; ///< Return number of top-level records with the given \a state. - std::string getDescription() const; - - std::string getAuthor() const; - signals: void idListChanged(); From 5a37530c1c296b15b273b5da3cc53e10b6db7a63 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 15:17:18 +0200 Subject: [PATCH 47/53] added missing MetaData table UniversalId type --- apps/opencs/model/world/universalid.cpp | 1 + apps/opencs/model/world/universalid.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 584bf5e702..73d893a260 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -56,6 +56,7 @@ namespace { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Meta Data Table", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 752504bc45..e9104fc226 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -131,6 +131,7 @@ namespace CSMWorld Type_StartScripts, Type_StartScript, Type_Search, + Type_MetaDatas, Type_MetaData, Type_RunLog }; From 10fbe6aada504ebd0e5afebdc5569382f5051806 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 15:17:47 +0200 Subject: [PATCH 48/53] split DialogueSubView in SimpleDialogueSubView and DialogueSubView --- apps/opencs/view/world/dialoguesubview.cpp | 402 +++++++++++---------- apps/opencs/view/world/dialoguesubview.hpp | 61 +++- 2 files changed, 262 insertions(+), 201 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 284c5928ba..d588c2edba 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -548,12 +548,38 @@ void CSVWorld::EditWidget::remake(int row) this->setWidgetResizable(true); } -/* -==============================DialogueSubView========================================== -*/ -CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, - const CreatorFactoryBase& creatorFactory, bool sorting) : +QVBoxLayout& CSVWorld::SimpleDialogueSubView::getMainLayout() +{ + return *mMainLayout; +} + +CSMWorld::IdTable& CSVWorld::SimpleDialogueSubView::getTable() +{ + return *mTable; +} + +CSMWorld::CommandDispatcher& CSVWorld::SimpleDialogueSubView::getCommandDispatcher() +{ + return mCommandDispatcher; +} + +std::string CSVWorld::SimpleDialogueSubView::getCurrentId() const +{ + return mCurrentId; +} + +CSVWorld::EditWidget& CSVWorld::SimpleDialogueSubView::getEditWidget() +{ + return *mEditWidget; +} + +bool CSVWorld::SimpleDialogueSubView::isLocked() const +{ + return mLocked; +} + +CSVWorld::SimpleDialogueSubView::SimpleDialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) : SubView (id), mEditWidget(0), mMainLayout(NULL), @@ -570,60 +596,8 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM QWidget *mainWidget = new QWidget(this); - QHBoxLayout *buttonsLayout = new QHBoxLayout; - QToolButton* prevButton = new QToolButton(mainWidget); - prevButton->setIcon(QIcon(":/go-previous.png")); - prevButton->setToolTip ("Switch to previous record"); - QToolButton* nextButton = new QToolButton(mainWidget); - nextButton->setIcon(QIcon(":/go-next.png")); - nextButton->setToolTip ("Switch to next record"); - buttonsLayout->addWidget(prevButton, 0); - buttonsLayout->addWidget(nextButton, 1); - buttonsLayout->addStretch(2); - - QToolButton* cloneButton = new QToolButton(mainWidget); - cloneButton->setIcon(QIcon(":/edit-clone.png")); - cloneButton->setToolTip ("Clone record"); - QToolButton* addButton = new QToolButton(mainWidget); - addButton->setIcon(QIcon(":/add.png")); - addButton->setToolTip ("Add new record"); - QToolButton* deleteButton = new QToolButton(mainWidget); - deleteButton->setIcon(QIcon(":/edit-delete.png")); - deleteButton->setToolTip ("Delete record"); - QToolButton* revertButton = new QToolButton(mainWidget); - revertButton->setIcon(QIcon(":/edit-undo.png")); - revertButton->setToolTip ("Revert record"); - - if (mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview) - { - QToolButton* previewButton = new QToolButton(mainWidget); - previewButton->setIcon(QIcon(":/edit-preview.png")); - previewButton->setToolTip ("Open a preview of this record"); - buttonsLayout->addWidget(previewButton); - connect(previewButton, SIGNAL(clicked()), this, SLOT(showPreview())); - } - - if (mTable->getFeatures() & CSMWorld::IdTable::Feature_View) - { - QToolButton* viewButton = new QToolButton(mainWidget); - viewButton->setIcon(QIcon(":/cell.png")); - viewButton->setToolTip ("Open a scene view of the cell this record is located in"); - buttonsLayout->addWidget(viewButton); - connect(viewButton, SIGNAL(clicked()), this, SLOT(viewRecord())); - } - - buttonsLayout->addWidget(cloneButton); - buttonsLayout->addWidget(addButton); - buttonsLayout->addWidget(deleteButton); - buttonsLayout->addWidget(revertButton); - - connect(nextButton, SIGNAL(clicked()), this, SLOT(nextId())); - connect(prevButton, SIGNAL(clicked()), this, SLOT(prevId())); - connect(cloneButton, SIGNAL(clicked()), this, SLOT(cloneRequest())); - connect(revertButton, SIGNAL(clicked()), &mCommandDispatcher, SLOT(executeRevert())); - connect(deleteButton, SIGNAL(clicked()), &mCommandDispatcher, SLOT(executeDelete())); - mMainLayout = new QVBoxLayout(mainWidget); + setWidget (mainWidget); mEditWidget = new EditWidget(mainWidget, mTable->getModelIndex(mCurrentId, 0).row(), mTable, mCommandDispatcher, document, false); @@ -631,98 +605,10 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM mMainLayout->addWidget(mEditWidget); mEditWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - mMainLayout->addWidget (mBottom = new TableBottomBox (creatorFactory, document, id, this)); - - mBottom->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); - - connect(mBottom, SIGNAL(requestFocus(const std::string&)), this, SLOT(requestFocus(const std::string&))); - - connect(addButton, SIGNAL(clicked()), mBottom, SLOT(createRequest())); - - if(!mBottom->canCreateAndDelete()) - { - cloneButton->setDisabled (true); - addButton->setDisabled (true); - deleteButton->setDisabled (true); - } - dataChanged(mTable->getModelIndex (mCurrentId, 0)); - mMainLayout->addLayout (buttonsLayout); - setWidget (mainWidget); } -void CSVWorld::DialogueSubView::prevId () -{ - int newRow = mTable->getModelIndex(mCurrentId, 0).row() - 1; - - if (newRow < 0) - { - return; - } - while (newRow >= 0) - { - QModelIndex newIndex(mTable->index(newRow, 0)); - - if (!newIndex.isValid()) - { - return; - } - - CSMWorld::RecordBase::State state = static_cast(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 (mTable->data (mTable->index (newRow, 2)).toInt()), - mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); - - changeCurrentId(std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); - - mEditWidget->setDisabled(mLocked); - - return; - } - --newRow; - } -} - -void CSVWorld::DialogueSubView::nextId () -{ - int newRow = mTable->getModelIndex(mCurrentId, 0).row() + 1; - - if (newRow >= mTable->rowCount()) - { - return; - } - - while (newRow < mTable->rowCount()) - { - QModelIndex newIndex(mTable->index(newRow, 0)); - - if (!newIndex.isValid()) - { - return; - } - - CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (newRow, 1)).toInt()); - if (!(state == CSMWorld::RecordBase::State_Deleted)) - { - mEditWidget->remake(newRow); - - setUniversalId(CSMWorld::UniversalId (static_cast (mTable->data (mTable->index (newRow, 2)).toInt()), - mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); - - changeCurrentId(std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); - - mEditWidget->setDisabled(mLocked); - - return; - } - ++newRow; - } -} - -void CSVWorld::DialogueSubView::setEditLock (bool locked) +void CSVWorld::SimpleDialogueSubView::setEditLock (bool locked) { if (!mEditWidget) // hack to indicate that mCurrentId is no longer valid return; @@ -741,7 +627,7 @@ void CSVWorld::DialogueSubView::setEditLock (bool locked) } -void CSVWorld::DialogueSubView::dataChanged (const QModelIndex & index) +void CSVWorld::SimpleDialogueSubView::dataChanged (const QModelIndex & index) { QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); @@ -774,7 +660,7 @@ void CSVWorld::DialogueSubView::dataChanged (const QModelIndex & index) } } -void CSVWorld::DialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +void CSVWorld::SimpleDialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); @@ -789,45 +675,14 @@ void CSVWorld::DialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent, } } -void CSVWorld::DialogueSubView::requestFocus (const std::string& id) +void CSVWorld::SimpleDialogueSubView::requestFocus (const std::string& id) { changeCurrentId(id); mEditWidget->remake(mTable->getModelIndex (id, 0).row()); } -void CSVWorld::DialogueSubView::cloneRequest () -{ - mBottom->cloneRequest(mCurrentId, static_cast(mTable->data(mTable->getModelIndex(mCurrentId, 2)).toInt())); -} - -void CSVWorld::DialogueSubView::showPreview () -{ - QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); - - if (currentIndex.isValid() && - mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview && - currentIndex.row() < mTable->rowCount()) - { - emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, mCurrentId), ""); - } -} - -void CSVWorld::DialogueSubView::viewRecord () -{ - QModelIndex currentIndex(mTable->getModelIndex (mCurrentId, 0)); - - if (currentIndex.isValid() && - currentIndex.row() < mTable->rowCount()) - { - std::pair params = mTable->view (currentIndex.row()); - - if (params.first.getType()!=CSMWorld::UniversalId::Type_None) - emit focusId (params.first, params.second); - } -} - -void CSVWorld::DialogueSubView::changeCurrentId (const std::string& newId) +void CSVWorld::SimpleDialogueSubView::changeCurrentId (const std::string& newId) { std::vector selection; mCurrentId = std::string(newId); @@ -835,3 +690,186 @@ void CSVWorld::DialogueSubView::changeCurrentId (const std::string& newId) selection.push_back(mCurrentId); mCommandDispatcher.setSelection(selection); } + + +CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, + CSMDoc::Document& document, const CreatorFactoryBase& creatorFactory, bool sorting) +: SimpleDialogueSubView (id, document) +{ + // bottom box + getMainLayout().addWidget (mBottom = new TableBottomBox (creatorFactory, document, id, this)); + + mBottom->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); + + connect(mBottom, SIGNAL(requestFocus(const std::string&)), this, SLOT(requestFocus(const std::string&))); + + // buttons + QHBoxLayout *buttonsLayout = new QHBoxLayout; + QToolButton* prevButton = new QToolButton (this); + prevButton->setIcon(QIcon(":/go-previous.png")); + prevButton->setToolTip ("Switch to previous record"); + QToolButton* nextButton = new QToolButton (this); + nextButton->setIcon(QIcon(":/go-next.png")); + nextButton->setToolTip ("Switch to next record"); + buttonsLayout->addWidget(prevButton, 0); + buttonsLayout->addWidget(nextButton, 1); + buttonsLayout->addStretch(2); + + QToolButton* cloneButton = new QToolButton (this); + cloneButton->setIcon(QIcon(":/edit-clone.png")); + cloneButton->setToolTip ("Clone record"); + QToolButton* addButton = new QToolButton (this); + addButton->setIcon(QIcon(":/add.png")); + addButton->setToolTip ("Add new record"); + QToolButton* deleteButton = new QToolButton (this); + deleteButton->setIcon(QIcon(":/edit-delete.png")); + deleteButton->setToolTip ("Delete record"); + QToolButton* revertButton = new QToolButton (this); + revertButton->setIcon(QIcon(":/edit-undo.png")); + revertButton->setToolTip ("Revert record"); + + if (getTable().getFeatures() & CSMWorld::IdTable::Feature_Preview) + { + QToolButton* previewButton = new QToolButton (this); + previewButton->setIcon(QIcon(":/edit-preview.png")); + previewButton->setToolTip ("Open a preview of this record"); + buttonsLayout->addWidget(previewButton); + connect(previewButton, SIGNAL(clicked()), this, SLOT(showPreview())); + } + + if (getTable().getFeatures() & CSMWorld::IdTable::Feature_View) + { + QToolButton* viewButton = new QToolButton (this); + viewButton->setIcon(QIcon(":/cell.png")); + viewButton->setToolTip ("Open a scene view of the cell this record is located in"); + buttonsLayout->addWidget(viewButton); + connect(viewButton, SIGNAL(clicked()), this, SLOT(viewRecord())); + } + + buttonsLayout->addWidget(cloneButton); + buttonsLayout->addWidget(addButton); + buttonsLayout->addWidget(deleteButton); + buttonsLayout->addWidget(revertButton); + + connect(nextButton, SIGNAL(clicked()), this, SLOT(nextId())); + connect(prevButton, SIGNAL(clicked()), this, SLOT(prevId())); + connect(cloneButton, SIGNAL(clicked()), this, SLOT(cloneRequest())); + connect(revertButton, SIGNAL(clicked()), &getCommandDispatcher(), SLOT(executeRevert())); + connect(deleteButton, SIGNAL(clicked()), &getCommandDispatcher(), SLOT(executeDelete())); + + connect(addButton, SIGNAL(clicked()), mBottom, SLOT(createRequest())); + + if(!mBottom->canCreateAndDelete()) + { + cloneButton->setDisabled (true); + addButton->setDisabled (true); + deleteButton->setDisabled (true); + } + + getMainLayout().addLayout (buttonsLayout); +} + +void CSVWorld::DialogueSubView::cloneRequest() +{ + mBottom->cloneRequest (getCurrentId(), + static_cast (getTable(). + data (getTable().getModelIndex(getCurrentId(), 2)).toInt())); +} + +void CSVWorld::DialogueSubView::prevId() +{ + int newRow = getTable().getModelIndex (getCurrentId(), 0).row() - 1; + + if (newRow < 0) + { + return; + } + while (newRow >= 0) + { + QModelIndex newIndex (getTable().index(newRow, 0)); + + if (!newIndex.isValid()) + { + return; + } + + CSMWorld::RecordBase::State state = static_cast (getTable().data (getTable().index (newRow, 1)).toInt()); + if (!(state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased)) + { + getEditWidget().remake (newRow); + + setUniversalId(CSMWorld::UniversalId (static_cast (getTable().data (getTable().index (newRow, 2)).toInt()), + getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData())); + + changeCurrentId(std::string (getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData())); + + getEditWidget().setDisabled (isLocked()); + + return; + } + --newRow; + } +} + +void CSVWorld::DialogueSubView::nextId () +{ + int newRow = getTable().getModelIndex (getCurrentId(), 0).row() + 1; + + if (newRow >= getTable().rowCount()) + { + return; + } + + while (newRow < getTable().rowCount()) + { + QModelIndex newIndex (getTable().index(newRow, 0)); + + if (!newIndex.isValid()) + { + return; + } + + CSMWorld::RecordBase::State state = static_cast (getTable().data (getTable().index (newRow, 1)).toInt()); + if (!(state == CSMWorld::RecordBase::State_Deleted)) + { + getEditWidget().remake(newRow); + + setUniversalId(CSMWorld::UniversalId (static_cast (getTable().data (getTable().index (newRow, 2)).toInt()), + getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData())); + + changeCurrentId(std::string (getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData())); + + getEditWidget().setDisabled (isLocked()); + + return; + } + ++newRow; + } +} + + +void CSVWorld::DialogueSubView::showPreview () +{ + QModelIndex currentIndex (getTable().getModelIndex (getCurrentId(), 0)); + + if (currentIndex.isValid() && + getTable().getFeatures() & CSMWorld::IdTable::Feature_Preview && + currentIndex.row() < getTable().rowCount()) + { + emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, getCurrentId()), ""); + } +} + +void CSVWorld::DialogueSubView::viewRecord () +{ + QModelIndex currentIndex (getTable().getModelIndex (getCurrentId(), 0)); + + if (currentIndex.isValid() && + currentIndex.row() < getTable().rowCount()) + { + std::pair params = getTable().view (currentIndex.row()); + + if (params.first.getType()!=CSMWorld::UniversalId::Type_None) + emit focusId (params.first, params.second); + } +} diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 69e0dc8648..5d6915d42d 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -173,7 +173,7 @@ namespace CSVWorld void remake(int row); }; - class DialogueSubView : public CSVDoc::SubView + class SimpleDialogueSubView : public CSVDoc::SubView { Q_OBJECT @@ -184,33 +184,32 @@ namespace CSVWorld std::string mCurrentId; bool mLocked; const CSMDoc::Document& mDocument; - TableBottomBox* mBottom; CSMWorld::CommandDispatcher mCommandDispatcher; + protected: + + QVBoxLayout& getMainLayout(); + + CSMWorld::IdTable& getTable(); + + CSMWorld::CommandDispatcher& getCommandDispatcher(); + + std::string getCurrentId() const; + + EditWidget& getEditWidget(); + + void changeCurrentId(const std::string& newCurrent); + + bool isLocked() const; + public: - DialogueSubView (const CSMWorld::UniversalId& id, - CSMDoc::Document& document, - const CreatorFactoryBase& creatorFactory, - bool sorting = false); + SimpleDialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); virtual void setEditLock (bool locked); - private: - void changeCurrentId(const std::string& newCurrent); - private slots: - void nextId(); - - void prevId(); - - void showPreview(); - - void viewRecord(); - - void cloneRequest(); - void dataChanged(const QModelIndex & index); ///\brief we need to care for deleting currently edited record @@ -218,6 +217,30 @@ namespace CSVWorld void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); }; + + class DialogueSubView : public SimpleDialogueSubView + { + Q_OBJECT + + TableBottomBox* mBottom; + + public: + + DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, + const CreatorFactoryBase& creatorFactory, bool sorting = false); + + private slots: + + void cloneRequest(); + + void nextId(); + + void prevId(); + + void showPreview(); + + void viewRecord(); + }; } #endif From 57015f366609f57a0ac727796585a2bace3915aa Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 15:50:36 +0200 Subject: [PATCH 49/53] fixed handling of numeric read-only fields in dialogue sub views --- apps/opencs/view/world/dialoguesubview.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index d588c2edba..99650834ef 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -64,16 +64,24 @@ void CSVWorld::NotEditableSubDelegate::setEditorData (QWidget* editor, const QMo } } + CSMWorld::Columns::ColumnId columnId = static_cast ( + mTable->getColumnId (index.column())); + if (QVariant::String == v.type()) { label->setText(v.toString()); } - else //else we are facing enums + else if (CSMWorld::Columns::hasEnums (columnId)) { int data = v.toInt(); - std::vector enumNames (CSMWorld::Columns::getEnums (static_cast (mTable->getColumnId (index.column())))); + std::vector enumNames (CSMWorld::Columns::getEnums (columnId)); + label->setText(QString::fromUtf8(enumNames.at(data).c_str())); } + else + { + label->setText (v.toString()); + } } void CSVWorld::NotEditableSubDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const From 1e033fa8fe87f8eac5b6414b697d5a55b066bead Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 16:11:00 +0200 Subject: [PATCH 50/53] added meta data dialogue sub view --- apps/opencs/model/world/columnimp.hpp | 72 +++++++++++++++++++++++++++ apps/opencs/model/world/columns.cpp | 4 ++ apps/opencs/model/world/columns.hpp | 4 ++ apps/opencs/model/world/data.cpp | 8 ++- apps/opencs/view/doc/view.cpp | 9 ++++ apps/opencs/view/doc/view.hpp | 2 + apps/opencs/view/world/subviews.cpp | 3 ++ 7 files changed, 101 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index a8ae5dfa12..ba23a3603a 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -2308,6 +2308,78 @@ namespace CSMWorld return true; } }; + + template + struct FormatColumn : public Column + { + FormatColumn() + : Column (Columns::ColumnId_FileFormat, ColumnBase::Display_Integer) + {} + + virtual QVariant get (const Record& record) const + { + return record.get().mFormat; + } + + virtual bool isEditable() const + { + return false; + } + }; + + template + struct AuthorColumn : public Column + { + AuthorColumn() + : Column (Columns::ColumnId_Author, ColumnBase::Display_String) + {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mAuthor.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mAuthor = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; + + template + struct FileDescriptionColumn : public Column + { + FileDescriptionColumn() + : Column (Columns::ColumnId_FileDescription, ColumnBase::Display_LongString) + {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mDescription.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mDescription = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 9491c32469..d6e27caeb1 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -311,6 +311,10 @@ namespace CSMWorld { ColumnId_WaterLevel, "Water Level" }, { ColumnId_MapColor, "Map Color" }, + { ColumnId_FileFormat, "File Format" }, + { ColumnId_FileDescription, "File Description" }, + { ColumnId_Author, "Author" }, + { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, { ColumnId_UseValue3, "Use value 3" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 191bbdea8c..d699c67b7e 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -302,6 +302,10 @@ namespace CSMWorld ColumnId_WaterLevel = 273, ColumnId_MapColor = 274, + ColumnId_FileFormat = 275, + ColumnId_FileDescription = 276, + ColumnId_Author = 277, + // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. ColumnId_UseValue1 = 0x10000, diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 368c7a766f..29f7fa9b84 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -476,7 +476,13 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc ScriptColumn::Type_Lines)); mMetaData.appendBlankRecord ("sys::meta"); - + + mMetaData.addColumn (new StringIdColumn (true)); + mMetaData.addColumn (new RecordStateColumn); + mMetaData.addColumn (new FormatColumn); + mMetaData.addColumn (new AuthorColumn); + mMetaData.addColumn (new FileDescriptionColumn); + addModel (new IdTable (&mGlobals), UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst); addModel (new IdTable (&mSkills), UniversalId::Type_Skill); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 64b066eb1e..c4abb26225 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -70,6 +70,10 @@ void CSVDoc::View::setupFileMenu() connect (loadErrors, SIGNAL (triggered()), this, SLOT (loadErrorLog())); file->addAction (loadErrors); + QAction *meta = new QAction (tr ("Meta Data"), this); + connect (meta, SIGNAL (triggered()), this, SLOT (addMetaDataSubView())); + file->addAction (meta); + QAction *close = new QAction (tr ("&Close"), this); connect (close, SIGNAL (triggered()), this, SLOT (close())); file->addAction(close); @@ -813,6 +817,11 @@ void CSVDoc::View::addSearchSubView() addSubView (mDocument->newSearch()); } +void CSVDoc::View::addMetaDataSubView() +{ + addSubView (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_MetaData, "sys::meta")); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 814dabc6b5..7f4255f8fc 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -224,6 +224,8 @@ namespace CSVDoc void addSearchSubView(); + void addMetaDataSubView(); + void toggleShowStatusBar (bool show); void loadErrorLog(); diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index ba3ab1358c..b8a6ba4298 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -170,6 +170,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (CSMWorld::UniversalId::Type_Filter, new CSVDoc::SubViewFactoryWithCreator > (false)); + manager.add (CSMWorld::UniversalId::Type_MetaData, + new CSVDoc::SubViewFactory); + //preview manager.add (CSMWorld::UniversalId::Type_Preview, new CSVDoc::SubViewFactory); } From a4c2c75d1fafd5458bfae3d555f55b8ab4a00844 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 16:22:06 +0200 Subject: [PATCH 51/53] fixed overwriting of meta data when loading project file --- apps/opencs/model/world/data.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 29f7fa9b84..b38607748f 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -861,11 +861,14 @@ int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base mBase = base; mProject = project; - MetaData metaData; - metaData.mId = "sys::meta"; - metaData.load (*mReader); + if (!mProject && !mBase) + { + MetaData metaData; + metaData.mId = "sys::meta"; + metaData.load (*mReader); - mMetaData.setRecord (0, Record (RecordBase::State_ModifiedOnly, 0, &metaData)); + mMetaData.setRecord (0, Record (RecordBase::State_ModifiedOnly, 0, &metaData)); + } return mReader->getRecordCount(); } From 4487bda702da64a34913219ccf22a318e0545a21 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 18:19:00 +0200 Subject: [PATCH 52/53] size limits for meta data strings --- apps/opencs/model/world/columnbase.cpp | 3 ++- apps/opencs/model/world/columnbase.hpp | 2 ++ apps/opencs/model/world/columnimp.hpp | 4 ++-- apps/opencs/view/world/util.cpp | 16 ++++++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/columnbase.cpp b/apps/opencs/model/world/columnbase.cpp index 9385038757..f209e48c66 100644 --- a/apps/opencs/model/world/columnbase.cpp +++ b/apps/opencs/model/world/columnbase.cpp @@ -100,7 +100,8 @@ bool CSMWorld::ColumnBase::isId (Display display) bool CSMWorld::ColumnBase::isText (Display display) { - return display==Display_String || display==Display_LongString; + return display==Display_String || display==Display_LongString || + display==Display_String32 || display==Display_LongString256; } bool CSMWorld::ColumnBase::isScript (Display display) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 789823d5cd..59f2836c21 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -123,6 +123,8 @@ namespace CSMWorld Display_InfoCondVar, Display_InfoCondComp, Display_RaceSkill, + Display_String32, + Display_LongString256, //top level columns that nest other columns Display_NestedHeader diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index ba23a3603a..15dd2c15b0 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -2331,7 +2331,7 @@ namespace CSMWorld struct AuthorColumn : public Column { AuthorColumn() - : Column (Columns::ColumnId_Author, ColumnBase::Display_String) + : Column (Columns::ColumnId_Author, ColumnBase::Display_String32) {} virtual QVariant get (const Record& record) const @@ -2358,7 +2358,7 @@ namespace CSMWorld struct FileDescriptionColumn : public Column { FileDescriptionColumn() - : Column (Columns::ColumnId_FileDescription, ColumnBase::Display_LongString) + : Column (Columns::ColumnId_FileDescription, ColumnBase::Display_LongString256) {} virtual QVariant get (const Record& record) const diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 62cde4608a..f216585811 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -232,6 +232,14 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO return edit; } + case CSMWorld::ColumnBase::Display_LongString256: + { + /// \todo implement size limit. QPlainTextEdit does not support a size limit. + QPlainTextEdit *edit = new QPlainTextEdit(parent); + edit->setUndoRedoEnabled (false); + return edit; + } + case CSMWorld::ColumnBase::Display_Boolean: return new QCheckBox(parent); @@ -245,6 +253,14 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO return new CSVWidget::DropLineEdit(display, parent); + case CSMWorld::ColumnBase::Display_String32: + { + // For other Display types (that represent record IDs) with drop support IdCompletionDelegate is used + CSVWidget::DropLineEdit *widget = new CSVWidget::DropLineEdit(display, parent); + widget->setMaxLength (32); + return widget; + } + default: return QStyledItemDelegate::createEditor (parent, option, index); From 6d5823e8aabefc0031a65c6157fa66de0afcd03c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 18:54:49 +0200 Subject: [PATCH 53/53] killed some tabs --- apps/opencs/model/world/infotableproxymodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index e34c505668..6216291d07 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -9,7 +9,7 @@ namespace { QString toLower(const QString &str) { - return QString::fromUtf8(Misc::StringUtils::lowerCase(str.toStdString()).c_str()); + return QString::fromUtf8(Misc::StringUtils::lowerCase(str.toStdString()).c_str()); } }