From d1b6289cad544ddf71b59c22e0edbc92404f81b1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 22 May 2015 19:56:39 +0200 Subject: [PATCH 01/36] Don't teleport followers when using teleportation spells --- apps/openmw/mwclass/door.cpp | 2 +- apps/openmw/mwgui/travelwindow.cpp | 2 +- apps/openmw/mwmechanics/spellcasting.cpp | 2 +- apps/openmw/mwworld/actionteleport.cpp | 25 +++++++++++++----------- apps/openmw/mwworld/actionteleport.hpp | 4 +++- apps/openmw/mwworld/worldimp.cpp | 2 +- 6 files changed, 21 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 2d39881b1f..48fc3b64c1 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -147,7 +147,7 @@ namespace MWClass if (ptr.getCellRef().getTeleport()) { - boost::shared_ptr action(new MWWorld::ActionTeleport (ptr.getCellRef().getDestCell(), ptr.getCellRef().getDoorDest())); + boost::shared_ptr action(new MWWorld::ActionTeleport (ptr.getCellRef().getDestCell(), ptr.getCellRef().getDoorDest(), true)); action->setSound(openSound); diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index 4da1ab33a0..ba6fc2a786 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -183,7 +183,7 @@ namespace MWGui MWBase::Environment::get().getDialogueManager()->goodbyeSelected(); // Teleports any followers, too. - MWWorld::ActionTeleport action(interior ? cellname : "", pos); + MWWorld::ActionTeleport action(interior ? cellname : "", pos, true); action.execute(player); MWBase::Environment::get().getWindowManager()->fadeScreenOut(0); diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 8a43cc9322..1f3a888279 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -679,7 +679,7 @@ namespace MWMechanics if (markedCell) { MWWorld::ActionTeleport action(markedCell->isExterior() ? "" : markedCell->getCell()->mName, - markedPosition); + markedPosition, false); action.execute(target); } } diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 8bbb080086..fccd176a85 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -25,23 +25,26 @@ namespace namespace MWWorld { ActionTeleport::ActionTeleport (const std::string& cellName, - const ESM::Position& position) - : Action (true), mCellName (cellName), mPosition (position) + const ESM::Position& position, bool teleportFollowers) + : Action (true), mCellName (cellName), mPosition (position), mTeleportFollowers(teleportFollowers) { } void ActionTeleport::executeImp (const Ptr& actor) { - //find any NPC that is following the actor and teleport him too - std::set followers; - getFollowers(actor, followers); - for(std::set::iterator it = followers.begin();it != followers.end();++it) + if (mTeleportFollowers) { - MWWorld::Ptr follower = *it; - if (Ogre::Vector3(follower.getRefData().getPosition().pos).squaredDistance( - Ogre::Vector3( actor.getRefData().getPosition().pos)) - <= 800*800) - teleport(*it); + //find any NPC that is following the actor and teleport him too + std::set followers; + getFollowers(actor, followers); + for(std::set::iterator it = followers.begin();it != followers.end();++it) + { + MWWorld::Ptr follower = *it; + if (Ogre::Vector3(follower.getRefData().getPosition().pos).squaredDistance( + Ogre::Vector3( actor.getRefData().getPosition().pos)) + <= 800*800) + teleport(*it); + } } teleport(actor); diff --git a/apps/openmw/mwworld/actionteleport.hpp b/apps/openmw/mwworld/actionteleport.hpp index 9ca664de84..6191ee9f6f 100644 --- a/apps/openmw/mwworld/actionteleport.hpp +++ b/apps/openmw/mwworld/actionteleport.hpp @@ -13,6 +13,7 @@ namespace MWWorld { std::string mCellName; ESM::Position mPosition; + bool mTeleportFollowers; /// Teleports this actor and also teleports anyone following that actor. virtual void executeImp (const Ptr& actor); @@ -22,8 +23,9 @@ namespace MWWorld public: - ActionTeleport (const std::string& cellName, const ESM::Position& position); + ActionTeleport (const std::string& cellName, const ESM::Position& position, bool teleportFollowers); ///< If cellName is empty, an exterior cell is assumed. + /// @param teleportFollowers Whether to teleport any following actors of the target actor as well. }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index bb0402c4e5..96fad106e9 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2921,7 +2921,7 @@ namespace MWWorld if ( !closestMarker.mCell->isExterior() ) cellName = closestMarker.mCell->getCell()->mName; - MWWorld::ActionTeleport action(cellName, closestMarker.getRefData().getPosition()); + MWWorld::ActionTeleport action(cellName, closestMarker.getRefData().getPosition(), false); action.execute(ptr); } From 2f976495403ddc5ed39038632021ef536697df11 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 27 May 2015 00:30:39 +0200 Subject: [PATCH 02/36] Fix for cleanup issue when exiting after a failed savegame load (Fixes #2580) --- apps/openmw/mwrender/npcanimation.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 6a6d52e262..f4943ba554 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -196,7 +196,11 @@ const NpcAnimation::PartBoneMap NpcAnimation::sPartList = createPartListMap(); NpcAnimation::~NpcAnimation() { - if (!mListenerDisabled) + if (!mListenerDisabled + // No need to getInventoryStore() to reset, if none exists + // This is to avoid triggering the listener via ensureCustomData()->autoEquip()->fireEquipmentChanged() + // all from within this destructor. ouch! + && mPtr.getRefData().getCustomData()) mPtr.getClass().getInventoryStore(mPtr).setListener(NULL, mPtr); } From 00c165d3a5e1ef5b79c95d54e6edb8421e1ae7c9 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 28 May 2015 08:44:17 +1000 Subject: [PATCH 03/36] Add user preference option to check unused or redundant pathgrid points. Also resolve namespace clash issue in osx. --- apps/opencs/model/settings/usersettings.cpp | 7 ++++++ apps/opencs/model/tools/pathgridcheck.cpp | 24 ++++++++++++--------- apps/opencs/model/tools/pathgridcheck.hpp | 14 ++++++++++-- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index ea002c5edd..ea75fd6d93 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -264,6 +264,13 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() monoFont->setToolTip ("Whether to use monospaced fonts on script edit subview."); } + declareSection ("verifier", "Verifier"); + { + Setting *extraPathgrid = createSetting (Type_CheckBox, "pathgrid-extra-check", "Pathgrid: Extra Check"); + extraPathgrid->setDefaultValue ("false"); + extraPathgrid->setToolTip ("Additional checks for orphaned or duplicated pathgrid points"); + } + { /****************************************************************** * There are three types of values: diff --git a/apps/opencs/model/tools/pathgridcheck.cpp b/apps/opencs/model/tools/pathgridcheck.cpp index 8f22cc8cd3..c436cfe044 100644 --- a/apps/opencs/model/tools/pathgridcheck.cpp +++ b/apps/opencs/model/tools/pathgridcheck.cpp @@ -8,15 +8,7 @@ #include "../world/subcellcollection.hpp" #include "../world/pathgrid.hpp" -namespace -{ - struct Point - { - unsigned char mConnectionNum; - std::vector mOtherIndex; - Point() : mConnectionNum(0), mOtherIndex(0) {} - }; -} +#include "../settings/usersettings.hpp" CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection& pathgrids) : mPathgrids (pathgrids) @@ -29,6 +21,12 @@ int CSMTools::PathgridCheckStage::setup() void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& messages) { + // NOTE: This is horribly inefficient but in order to use signals the entire Stage class + // hierarchy needs to be braught under Qt which seems like an overkill for a small + // performance gain during verify operations + CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); + bool extraCheck = userSettings.setting ("verifier/pathgrid-extra-check", QString ("false"))=="true"; + const CSMWorld::Record& record = mPathgrids.getRecord (stage); if (record.isDeleted()) @@ -44,7 +42,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message else if (pathgrid.mData.mS2 > static_cast(pathgrid.mPoints.size())) messages.push_back (std::make_pair (id, pathgrid.mId + " has more points than expected")); - std::vector pointList(pathgrid.mPoints.size()); + std::vector pointList(pathgrid.mPoints.size()); std::vector duplList; for (unsigned int i = 0; i < pathgrid.mEdges.size(); ++i) @@ -115,6 +113,9 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message } } + if (!extraCheck) + continue; + // check duplicate points // FIXME: how to do this efficiently? for (unsigned int j = 0; j < pathgrid.mPoints.size(); ++j) @@ -143,6 +144,9 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message } } + if (!extraCheck) + return; + // check pathgrid points that are not connected to anything for (unsigned int i = 0; i < pointList.size(); ++i) { diff --git a/apps/opencs/model/tools/pathgridcheck.hpp b/apps/opencs/model/tools/pathgridcheck.hpp index c90dbc8ed9..603235552e 100644 --- a/apps/opencs/model/tools/pathgridcheck.hpp +++ b/apps/opencs/model/tools/pathgridcheck.hpp @@ -14,13 +14,23 @@ namespace CSMWorld namespace CSMTools { + + struct Point + { + unsigned char mConnectionNum; + std::vector mOtherIndex; + Point() : mConnectionNum(0), mOtherIndex(0) {} + }; + class PathgridCheckStage : public CSMDoc::Stage { - const CSMWorld::SubCellCollection >& mPathgrids; + const CSMWorld::SubCellCollection >& mPathgrids; public: - PathgridCheckStage (const CSMWorld::SubCellCollection >& pathgrids); + PathgridCheckStage (const CSMWorld::SubCellCollection >& pathgrids); virtual int setup(); From 734e52d1c82e2f2a250c3a11fbaecd53592ee27f Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 29 May 2015 06:40:40 +1000 Subject: [PATCH 04/36] Move the user preference check to the preparation step before the running of the operation. --- apps/opencs/model/tools/pathgridcheck.cpp | 13 +++++-------- apps/opencs/model/tools/pathgridcheck.hpp | 15 ++++++++------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/apps/opencs/model/tools/pathgridcheck.cpp b/apps/opencs/model/tools/pathgridcheck.cpp index c436cfe044..58fdbeb2db 100644 --- a/apps/opencs/model/tools/pathgridcheck.cpp +++ b/apps/opencs/model/tools/pathgridcheck.cpp @@ -16,17 +16,14 @@ CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollect int CSMTools::PathgridCheckStage::setup() { + CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); + mExtraCheck = userSettings.setting ("verifier/pathgrid-extra-check", QString ("false"))=="true"; + return mPathgrids.getSize(); } void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& messages) { - // NOTE: This is horribly inefficient but in order to use signals the entire Stage class - // hierarchy needs to be braught under Qt which seems like an overkill for a small - // performance gain during verify operations - CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); - bool extraCheck = userSettings.setting ("verifier/pathgrid-extra-check", QString ("false"))=="true"; - const CSMWorld::Record& record = mPathgrids.getRecord (stage); if (record.isDeleted()) @@ -113,7 +110,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message } } - if (!extraCheck) + if (!mExtraCheck) continue; // check duplicate points @@ -144,7 +141,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message } } - if (!extraCheck) + if (!mExtraCheck) return; // check pathgrid points that are not connected to anything diff --git a/apps/opencs/model/tools/pathgridcheck.hpp b/apps/opencs/model/tools/pathgridcheck.hpp index 603235552e..86ace6af27 100644 --- a/apps/opencs/model/tools/pathgridcheck.hpp +++ b/apps/opencs/model/tools/pathgridcheck.hpp @@ -24,17 +24,18 @@ namespace CSMTools class PathgridCheckStage : public CSMDoc::Stage { - const CSMWorld::SubCellCollection >& mPathgrids; + bool mExtraCheck; + const CSMWorld::SubCellCollection >& mPathgrids; - public: + public: - PathgridCheckStage (const CSMWorld::SubCellCollection >& pathgrids); + PathgridCheckStage (const CSMWorld::SubCellCollection >& pathgrids); - virtual int setup(); + virtual int setup(); - virtual void perform (int stage, CSMDoc::Messages& messages); + virtual void perform (int stage, CSMDoc::Messages& messages); }; } From 393cee406fce7f0781c55451b53efd06427d2ab7 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 29 May 2015 19:28:25 +1000 Subject: [PATCH 05/36] Use signals for user preference setting updates. --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/tools/pathgridcheck.cpp | 15 +++++++++---- apps/opencs/model/tools/pathgridcheck.hpp | 7 +++++- apps/opencs/model/tools/signalhandler.cpp | 23 ++++++++++++++++++++ apps/opencs/model/tools/signalhandler.hpp | 26 +++++++++++++++++++++++ apps/opencs/model/tools/tools.cpp | 9 ++++++-- apps/opencs/model/tools/tools.hpp | 2 +- 7 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 apps/opencs/model/tools/signalhandler.cpp create mode 100644 apps/opencs/model/tools/signalhandler.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 78b2deb7a8..9ed0d6a8b1 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -34,7 +34,7 @@ opencs_hdrs_noqt (model/world opencs_units (model/tools - tools reportmodel + tools reportmodel signalhandler ) opencs_units_noqt (model/tools diff --git a/apps/opencs/model/tools/pathgridcheck.cpp b/apps/opencs/model/tools/pathgridcheck.cpp index 58fdbeb2db..2b11b70661 100644 --- a/apps/opencs/model/tools/pathgridcheck.cpp +++ b/apps/opencs/model/tools/pathgridcheck.cpp @@ -10,14 +10,21 @@ #include "../settings/usersettings.hpp" -CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection& pathgrids) -: mPathgrids (pathgrids) +#include "signalhandler.hpp" + +CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection& pathgrids, + CSMTools::SignalHandler *signalHandler) +: mPathgrids (pathgrids), mSigHandler(signalHandler) {} +CSMTools::PathgridCheckStage::~PathgridCheckStage () +{ + delete mSigHandler; +} + int CSMTools::PathgridCheckStage::setup() { - CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); - mExtraCheck = userSettings.setting ("verifier/pathgrid-extra-check", QString ("false"))=="true"; + mExtraCheck = mSigHandler->extraCheck(); return mPathgrids.getSize(); } diff --git a/apps/opencs/model/tools/pathgridcheck.hpp b/apps/opencs/model/tools/pathgridcheck.hpp index 86ace6af27..8b5dc08a7d 100644 --- a/apps/opencs/model/tools/pathgridcheck.hpp +++ b/apps/opencs/model/tools/pathgridcheck.hpp @@ -14,6 +14,7 @@ namespace CSMWorld namespace CSMTools { + class SignalHandler; struct Point { @@ -25,13 +26,17 @@ namespace CSMTools class PathgridCheckStage : public CSMDoc::Stage { bool mExtraCheck; + CSMTools::SignalHandler *mSigHandler; + const CSMWorld::SubCellCollection >& mPathgrids; public: PathgridCheckStage (const CSMWorld::SubCellCollection >& pathgrids); + CSMWorld::IdAccessor >& pathgrids, CSMTools::SignalHandler *signallHandler); + + ~PathgridCheckStage (); virtual int setup(); diff --git a/apps/opencs/model/tools/signalhandler.cpp b/apps/opencs/model/tools/signalhandler.cpp new file mode 100644 index 0000000000..cfb52ed63c --- /dev/null +++ b/apps/opencs/model/tools/signalhandler.cpp @@ -0,0 +1,23 @@ +#include "signalhandler.hpp" + +#include "../settings/usersettings.hpp" + +CSMTools::SignalHandler::SignalHandler(bool extraCheck) + : mExtraCheck(extraCheck) +{ + connect (&CSMSettings::UserSettings::instance(), + SIGNAL (userSettingUpdated(const QString &, const QStringList &)), + this, + SLOT (updateUserSetting (const QString &, const QStringList &))); +} + +void CSMTools::SignalHandler::updateUserSetting (const QString &name, const QStringList &list) +{ + if (name=="verifier/pathgrid-extra-check") + mExtraCheck = list.at(0) == "true"; +} + +bool CSMTools::SignalHandler::extraCheck () +{ + return mExtraCheck; +} diff --git a/apps/opencs/model/tools/signalhandler.hpp b/apps/opencs/model/tools/signalhandler.hpp new file mode 100644 index 0000000000..c3d075fdfb --- /dev/null +++ b/apps/opencs/model/tools/signalhandler.hpp @@ -0,0 +1,26 @@ +#ifndef CSM_TOOLS_SIGNALHANDLER_H +#define CSM_TOOLS_SIGNALHANDLER_H + +#include + +namespace CSMTools +{ + class SignalHandler : public QObject + { + Q_OBJECT + + bool mExtraCheck; + + public: + + SignalHandler (bool extraCheck); + + bool extraCheck (); + + public slots: + + void updateUserSetting (const QString &name, const QStringList &list); + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 8d93a94332..45c7fbae35 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -10,6 +10,8 @@ #include "../world/data.hpp" #include "../world/universalid.hpp" +#include "../settings/usersettings.hpp" + #include "reportmodel.hpp" #include "mandatoryid.hpp" #include "skillcheck.hpp" @@ -27,6 +29,7 @@ #include "startscriptcheck.hpp" #include "searchoperation.hpp" #include "pathgridcheck.hpp" +#include "signalhandler.hpp" CSMDoc::OperationHolder *CSMTools::Tools::get (int type) { @@ -56,6 +59,8 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() 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))); + CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); + std::vector mandatoryIds; // I want C++11, damn it! mandatoryIds.push_back ("Day"); mandatoryIds.push_back ("DaysPassed"); @@ -97,7 +102,8 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )), mData.getRaces() )); - mVerifierOperation->appendStage (new PathgridCheckStage (mData.getPathgrids())); + mVerifierOperation->appendStage (new PathgridCheckStage (mData.getPathgrids(), + new SignalHandler(userSettings.setting ("verifier/pathgrid-extra-check", QString ("false"))=="true"))); mVerifier.setOperation (mVerifierOperation); } @@ -213,4 +219,3 @@ void CSMTools::Tools::verifierMessage (const CSMWorld::UniversalId& id, const st if (iter!=mActiveReports.end()) mReports[iter->second]->add (id, message, hint); } - diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 0f9e570445..dc19cf456b 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -64,7 +64,7 @@ namespace CSMTools CSMWorld::UniversalId newSearch(); void runSearch (const CSMWorld::UniversalId& searchId, const Search& search); - + void abortOperation (int type); ///< \attention The operation is not aborted immediately. From 76196d815dcd4172b16a751352a52b056b5ab58b Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 30 May 2015 18:58:33 +1000 Subject: [PATCH 06/36] Update user preference setting value via an event message queue. --- apps/opencs/model/tools/signalhandler.cpp | 14 ++++++++++++-- apps/opencs/model/tools/signalhandler.hpp | 4 ++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/tools/signalhandler.cpp b/apps/opencs/model/tools/signalhandler.cpp index cfb52ed63c..64e5ead557 100644 --- a/apps/opencs/model/tools/signalhandler.cpp +++ b/apps/opencs/model/tools/signalhandler.cpp @@ -1,5 +1,7 @@ #include "signalhandler.hpp" +#include + #include "../settings/usersettings.hpp" CSMTools::SignalHandler::SignalHandler(bool extraCheck) @@ -11,12 +13,20 @@ CSMTools::SignalHandler::SignalHandler(bool extraCheck) SLOT (updateUserSetting (const QString &, const QStringList &))); } +// called from the main thread void CSMTools::SignalHandler::updateUserSetting (const QString &name, const QStringList &list) { - if (name=="verifier/pathgrid-extra-check") - mExtraCheck = list.at(0) == "true"; + if (name=="verifier/pathgrid-extra-check" && !list.empty()) + QMetaObject::invokeMethod(this, "updateExtraCheck", Qt::AutoConnection, Q_ARG(bool, list.at(0) == "true")); } +// should be in the operations thread via an event message queue +void CSMTools::SignalHandler::updateExtraCheck (bool extraCheck) +{ + mExtraCheck = extraCheck; +} + +// called from the operations thread bool CSMTools::SignalHandler::extraCheck () { return mExtraCheck; diff --git a/apps/opencs/model/tools/signalhandler.hpp b/apps/opencs/model/tools/signalhandler.hpp index c3d075fdfb..bc063ebd69 100644 --- a/apps/opencs/model/tools/signalhandler.hpp +++ b/apps/opencs/model/tools/signalhandler.hpp @@ -20,6 +20,10 @@ namespace CSMTools public slots: void updateUserSetting (const QString &name, const QStringList &list); + + private slots: + + void updateExtraCheck (bool extraCheck); }; } From 01eba7b721be21a71f54431721b0da039d7c1074 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 30 May 2015 19:17:42 +1000 Subject: [PATCH 07/36] Extra check for thread affinity. --- apps/opencs/model/tools/signalhandler.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/opencs/model/tools/signalhandler.cpp b/apps/opencs/model/tools/signalhandler.cpp index 64e5ead557..2e94e1f872 100644 --- a/apps/opencs/model/tools/signalhandler.cpp +++ b/apps/opencs/model/tools/signalhandler.cpp @@ -1,6 +1,7 @@ #include "signalhandler.hpp" #include +#include #include "../settings/usersettings.hpp" @@ -23,6 +24,13 @@ void CSMTools::SignalHandler::updateUserSetting (const QString &name, const QStr // should be in the operations thread via an event message queue void CSMTools::SignalHandler::updateExtraCheck (bool extraCheck) { + if (thread()!=QThread::currentThread()) + { + QMetaObject::invokeMethod(this,"updateExtraCheck", Qt::QueuedConnection, Q_ARG(bool, extraCheck)); + return; + } + + // extra safety mExtraCheck = extraCheck; } From c4aa3d3ee319a884e77f05313f3a4441cd6f98dc Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 30 May 2015 21:12:47 +1000 Subject: [PATCH 08/36] Revert user preference setting checks until a thread safe method is worked out. The OSX namespace issue is retained. --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/settings/usersettings.cpp | 7 ---- apps/opencs/model/tools/pathgridcheck.cpp | 22 +---------- apps/opencs/model/tools/pathgridcheck.hpp | 9 +---- apps/opencs/model/tools/signalhandler.cpp | 41 --------------------- apps/opencs/model/tools/signalhandler.hpp | 30 --------------- apps/opencs/model/tools/tools.cpp | 9 +---- apps/opencs/model/tools/tools.hpp | 2 +- 8 files changed, 7 insertions(+), 115 deletions(-) delete mode 100644 apps/opencs/model/tools/signalhandler.cpp delete mode 100644 apps/opencs/model/tools/signalhandler.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 9ed0d6a8b1..78b2deb7a8 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -34,7 +34,7 @@ opencs_hdrs_noqt (model/world opencs_units (model/tools - tools reportmodel signalhandler + tools reportmodel ) opencs_units_noqt (model/tools diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index ea75fd6d93..ea002c5edd 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -264,13 +264,6 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() monoFont->setToolTip ("Whether to use monospaced fonts on script edit subview."); } - declareSection ("verifier", "Verifier"); - { - Setting *extraPathgrid = createSetting (Type_CheckBox, "pathgrid-extra-check", "Pathgrid: Extra Check"); - extraPathgrid->setDefaultValue ("false"); - extraPathgrid->setToolTip ("Additional checks for orphaned or duplicated pathgrid points"); - } - { /****************************************************************** * There are three types of values: diff --git a/apps/opencs/model/tools/pathgridcheck.cpp b/apps/opencs/model/tools/pathgridcheck.cpp index 2b11b70661..76edeb573d 100644 --- a/apps/opencs/model/tools/pathgridcheck.cpp +++ b/apps/opencs/model/tools/pathgridcheck.cpp @@ -8,24 +8,12 @@ #include "../world/subcellcollection.hpp" #include "../world/pathgrid.hpp" -#include "../settings/usersettings.hpp" - -#include "signalhandler.hpp" - -CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection& pathgrids, - CSMTools::SignalHandler *signalHandler) -: mPathgrids (pathgrids), mSigHandler(signalHandler) +CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection& pathgrids) +: mPathgrids (pathgrids) {} -CSMTools::PathgridCheckStage::~PathgridCheckStage () -{ - delete mSigHandler; -} - int CSMTools::PathgridCheckStage::setup() { - mExtraCheck = mSigHandler->extraCheck(); - return mPathgrids.getSize(); } @@ -117,9 +105,6 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message } } - if (!mExtraCheck) - continue; - // check duplicate points // FIXME: how to do this efficiently? for (unsigned int j = 0; j < pathgrid.mPoints.size(); ++j) @@ -148,9 +133,6 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message } } - if (!mExtraCheck) - return; - // check pathgrid points that are not connected to anything for (unsigned int i = 0; i < pointList.size(); ++i) { diff --git a/apps/opencs/model/tools/pathgridcheck.hpp b/apps/opencs/model/tools/pathgridcheck.hpp index 8b5dc08a7d..f45b5bc93a 100644 --- a/apps/opencs/model/tools/pathgridcheck.hpp +++ b/apps/opencs/model/tools/pathgridcheck.hpp @@ -14,8 +14,6 @@ namespace CSMWorld namespace CSMTools { - class SignalHandler; - struct Point { unsigned char mConnectionNum; @@ -25,18 +23,13 @@ namespace CSMTools class PathgridCheckStage : public CSMDoc::Stage { - bool mExtraCheck; - CSMTools::SignalHandler *mSigHandler; - const CSMWorld::SubCellCollection >& mPathgrids; public: PathgridCheckStage (const CSMWorld::SubCellCollection >& pathgrids, CSMTools::SignalHandler *signallHandler); - - ~PathgridCheckStage (); + CSMWorld::IdAccessor >& pathgrids); virtual int setup(); diff --git a/apps/opencs/model/tools/signalhandler.cpp b/apps/opencs/model/tools/signalhandler.cpp deleted file mode 100644 index 2e94e1f872..0000000000 --- a/apps/opencs/model/tools/signalhandler.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "signalhandler.hpp" - -#include -#include - -#include "../settings/usersettings.hpp" - -CSMTools::SignalHandler::SignalHandler(bool extraCheck) - : mExtraCheck(extraCheck) -{ - connect (&CSMSettings::UserSettings::instance(), - SIGNAL (userSettingUpdated(const QString &, const QStringList &)), - this, - SLOT (updateUserSetting (const QString &, const QStringList &))); -} - -// called from the main thread -void CSMTools::SignalHandler::updateUserSetting (const QString &name, const QStringList &list) -{ - if (name=="verifier/pathgrid-extra-check" && !list.empty()) - QMetaObject::invokeMethod(this, "updateExtraCheck", Qt::AutoConnection, Q_ARG(bool, list.at(0) == "true")); -} - -// should be in the operations thread via an event message queue -void CSMTools::SignalHandler::updateExtraCheck (bool extraCheck) -{ - if (thread()!=QThread::currentThread()) - { - QMetaObject::invokeMethod(this,"updateExtraCheck", Qt::QueuedConnection, Q_ARG(bool, extraCheck)); - return; - } - - // extra safety - mExtraCheck = extraCheck; -} - -// called from the operations thread -bool CSMTools::SignalHandler::extraCheck () -{ - return mExtraCheck; -} diff --git a/apps/opencs/model/tools/signalhandler.hpp b/apps/opencs/model/tools/signalhandler.hpp deleted file mode 100644 index bc063ebd69..0000000000 --- a/apps/opencs/model/tools/signalhandler.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef CSM_TOOLS_SIGNALHANDLER_H -#define CSM_TOOLS_SIGNALHANDLER_H - -#include - -namespace CSMTools -{ - class SignalHandler : public QObject - { - Q_OBJECT - - bool mExtraCheck; - - public: - - SignalHandler (bool extraCheck); - - bool extraCheck (); - - public slots: - - void updateUserSetting (const QString &name, const QStringList &list); - - private slots: - - void updateExtraCheck (bool extraCheck); - }; -} - -#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 45c7fbae35..8d93a94332 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -10,8 +10,6 @@ #include "../world/data.hpp" #include "../world/universalid.hpp" -#include "../settings/usersettings.hpp" - #include "reportmodel.hpp" #include "mandatoryid.hpp" #include "skillcheck.hpp" @@ -29,7 +27,6 @@ #include "startscriptcheck.hpp" #include "searchoperation.hpp" #include "pathgridcheck.hpp" -#include "signalhandler.hpp" CSMDoc::OperationHolder *CSMTools::Tools::get (int type) { @@ -59,8 +56,6 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() 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))); - CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); - std::vector mandatoryIds; // I want C++11, damn it! mandatoryIds.push_back ("Day"); mandatoryIds.push_back ("DaysPassed"); @@ -102,8 +97,7 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )), mData.getRaces() )); - mVerifierOperation->appendStage (new PathgridCheckStage (mData.getPathgrids(), - new SignalHandler(userSettings.setting ("verifier/pathgrid-extra-check", QString ("false"))=="true"))); + mVerifierOperation->appendStage (new PathgridCheckStage (mData.getPathgrids())); mVerifier.setOperation (mVerifierOperation); } @@ -219,3 +213,4 @@ void CSMTools::Tools::verifierMessage (const CSMWorld::UniversalId& id, const st if (iter!=mActiveReports.end()) mReports[iter->second]->add (id, message, hint); } + diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index dc19cf456b..0f9e570445 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -64,7 +64,7 @@ namespace CSMTools CSMWorld::UniversalId newSearch(); void runSearch (const CSMWorld::UniversalId& searchId, const Search& search); - + void abortOperation (int type); ///< \attention The operation is not aborted immediately. From 87a1f9f9aa2e05db33df52b3a35efe94e9935988 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 30 May 2015 15:31:44 +0300 Subject: [PATCH 09/36] Add ID completion manager --- apps/opencs/CMakeLists.txt | 1 + .../model/world/idcompletionmanager.cpp | 121 ++++++++++++++++++ .../model/world/idcompletionmanager.hpp | 38 ++++++ 3 files changed, 160 insertions(+) create mode 100644 apps/opencs/model/world/idcompletionmanager.cpp create mode 100644 apps/opencs/model/world/idcompletionmanager.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 7723b15f5e..99ba54ac1c 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -26,6 +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 ) opencs_hdrs_noqt (model/world diff --git a/apps/opencs/model/world/idcompletionmanager.cpp b/apps/opencs/model/world/idcompletionmanager.cpp new file mode 100644 index 0000000000..ca614dcd9e --- /dev/null +++ b/apps/opencs/model/world/idcompletionmanager.cpp @@ -0,0 +1,121 @@ +#include "idcompletionmanager.hpp" + +#include + +#include + +#include "data.hpp" +#include "idtablebase.hpp" + +namespace +{ + std::map generateModelTypes() + { + std::map types; + + types[CSMWorld::Columns::ColumnId_Actor] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::Columns::ColumnId_AreaObject] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::Columns::ColumnId_AreaSound] = CSMWorld::UniversalId::Type_Sound; + types[CSMWorld::Columns::ColumnId_BoltObject] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::Columns::ColumnId_BoltSound] = CSMWorld::UniversalId::Type_Sound; + types[CSMWorld::Columns::ColumnId_CastingObject] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::Columns::ColumnId_CastingSound] = CSMWorld::UniversalId::Type_Sound; + types[CSMWorld::Columns::ColumnId_Cell] = CSMWorld::UniversalId::Type_Cell; + types[CSMWorld::Columns::ColumnId_Class] = CSMWorld::UniversalId::Type_Class; + types[CSMWorld::Columns::ColumnId_Creature] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::Columns::ColumnId_DestinationCell] = CSMWorld::UniversalId::Type_Cell; + types[CSMWorld::Columns::ColumnId_Enchantment] = CSMWorld::UniversalId::Type_Enchantment; + types[CSMWorld::Columns::ColumnId_Faction] = CSMWorld::UniversalId::Type_Faction; + types[CSMWorld::Columns::Columnid_Hair] = CSMWorld::UniversalId::Type_Mesh; + types[CSMWorld::Columns::ColumnId_Head] = CSMWorld::UniversalId::Type_Mesh; + types[CSMWorld::Columns::ColumnId_HitObject] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::Columns::ColumnId_HitSound] = CSMWorld::UniversalId::Type_Sound; + types[CSMWorld::Columns::ColumnId_Icon] = CSMWorld::UniversalId::Type_Icon; + types[CSMWorld::Columns::ColumnId_InventoryItemId] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::Columns::ColumnId_MajorSkill1] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_MajorSkill2] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_MajorSkill3] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_MajorSkill4] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_MajorSkill5] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_MinorSkill1] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_MinorSkill2] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_MinorSkill3] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_MinorSkill4] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_MinorSkill5] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_Model] = CSMWorld::UniversalId::Type_Mesh; + types[CSMWorld::Columns::ColumnId_Owner] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::Columns::ColumnId_OwnerGlobal] = CSMWorld::UniversalId::Type_Global; + types[CSMWorld::Columns::ColumnId_Particle] = CSMWorld::UniversalId::Type_Texture; + types[CSMWorld::Columns::ColumnId_PcFaction] = CSMWorld::UniversalId::Type_Faction; + types[CSMWorld::Columns::ColumnId_Race] = CSMWorld::UniversalId::Type_Race; + types[CSMWorld::Columns::ColumnId_ReferenceableId] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::Columns::ColumnId_Region] = CSMWorld::UniversalId::Type_Region; + types[CSMWorld::Columns::ColumnId_Skill1] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_Skill2] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_Skill3] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_Skill4] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_Skill5] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_Skill6] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_Skill7] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::Columns::ColumnId_SleepEncounter] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::Columns::ColumnId_Soul] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::Columns::ColumnId_Sound] = CSMWorld::UniversalId::Type_Sound; + types[CSMWorld::Columns::ColumnId_SoundFile] = CSMWorld::UniversalId::Type_SoundRes; + types[CSMWorld::Columns::ColumnId_SoundName] = CSMWorld::UniversalId::Type_Sound; + types[CSMWorld::Columns::ColumnId_SpellId] = CSMWorld::UniversalId::Type_Spell; + types[CSMWorld::Columns::ColumnId_Script] = CSMWorld::UniversalId::Type_Script; + types[CSMWorld::Columns::ColumnId_TeleportCell] = CSMWorld::UniversalId::Type_Cell; + types[CSMWorld::Columns::ColumnId_Texture] = CSMWorld::UniversalId::Type_Texture; + types[CSMWorld::Columns::ColumnId_Trap] = CSMWorld::UniversalId::Type_Spell; + + return types; + } +} + +const std::map + CSMWorld::IdCompletionManager::sCompleterModelTypes = generateModelTypes(); + +CSMWorld::IdCompletionManager::IdCompletionManager(CSMWorld::Data &data) +{ + generateCompleters(data); +} + +bool CSMWorld::IdCompletionManager::isCompleterExistFor(CSMWorld::Columns::ColumnId id) const +{ + return mCompleters.find(id) != mCompleters.end(); +} + +boost::shared_ptr CSMWorld::IdCompletionManager::getCompleter(CSMWorld::Columns::ColumnId id) +{ + if (!isCompleterExistFor(id)) + { + throw std::logic_error("This column doesn't have an ID completer"); + } + return mCompleters[id]; +} + +void CSMWorld::IdCompletionManager::generateCompleters(CSMWorld::Data &data) +{ + typedef std::map::const_iterator ModelTypeConstIterator; + + ModelTypeConstIterator current = sCompleterModelTypes.begin(); + ModelTypeConstIterator end = sCompleterModelTypes.end(); + for (; current != end; ++current) + { + QAbstractItemModel *model = data.getTableModel(current->second); + CSMWorld::IdTableBase *table = dynamic_cast(model); + if (table != NULL) + { + int idColumn = table->searchColumnIndex(CSMWorld::Columns::ColumnId_Id); + if (idColumn != -1) + { + boost::shared_ptr completer = boost::make_shared(table); + completer->setCompletionColumn(idColumn); + // The completion role must be Qt::DisplayRole to get the ID values from the model + completer->setCompletionRole(Qt::DisplayRole); + completer->setCaseSensitivity(Qt::CaseInsensitive); + mCompleters[current->first] = completer; + } + } + } +} \ No newline at end of file diff --git a/apps/opencs/model/world/idcompletionmanager.hpp b/apps/opencs/model/world/idcompletionmanager.hpp new file mode 100644 index 0000000000..725cfa3312 --- /dev/null +++ b/apps/opencs/model/world/idcompletionmanager.hpp @@ -0,0 +1,38 @@ +#ifndef CSM_WORLD_IDCOMPLETIONMANAGER_HPP +#define CSM_WORLD_IDCOMPLETIONMANAGER_HPP + +#include + +#include + +#include "columns.hpp" +#include "universalid.hpp" + +class QCompleter; + +namespace CSMWorld +{ + class Data; + + /// \brief Creates and stores all ID completers + class IdCompletionManager + { + static const std::map sCompleterModelTypes; + + std::map > mCompleters; + + // Don't allow copying + IdCompletionManager(const IdCompletionManager &); + IdCompletionManager &operator = (const IdCompletionManager &); + + void generateCompleters(CSMWorld::Data &data); + + public: + IdCompletionManager(CSMWorld::Data &data); + + bool isCompleterExistFor(CSMWorld::Columns::ColumnId id) const; + boost::shared_ptr getCompleter(CSMWorld::Columns::ColumnId id); + }; +} + +#endif \ No newline at end of file From 19cc6b83e5c795f8b1a8b8fb9989ab84d262b1ed Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 30 May 2015 15:40:23 +0300 Subject: [PATCH 10/36] Integrate the Id completion manager into the Document class --- apps/opencs/model/doc/document.cpp | 8 +++++++- apps/opencs/model/doc/document.hpp | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index a73201ec0f..1e3d1c59b2 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2257,7 +2257,8 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, mSavingOperation (*this, mProjectPath, encoding), mSaving (&mSavingOperation), mResDir(resDir), - mRunner (mProjectPath), mPhysics(boost::shared_ptr()) + mRunner (mProjectPath), mPhysics(boost::shared_ptr()), + mIdCompletionManager(mData) { if (mContentFiles.empty()) throw std::runtime_error ("Empty content file sequence"); @@ -2488,3 +2489,8 @@ boost::shared_ptr CSMDoc::Document::getPhysics () return mPhysics; } + +CSMWorld::IdCompletionManager &CSMDoc::Document::getIdCompletionManager() +{ + return mIdCompletionManager; +} \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 6b1a1fc1e8..14daeeb758 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -13,6 +13,7 @@ #include #include "../world/data.hpp" +#include "../world/idcompletionmanager.hpp" #include "../tools/tools.hpp" @@ -66,6 +67,7 @@ namespace CSMDoc Blacklist mBlacklist; Runner mRunner; boost::shared_ptr mPhysics; + CSMWorld::IdCompletionManager mIdCompletionManager; // It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is // using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late. @@ -144,6 +146,8 @@ namespace CSMDoc boost::shared_ptr getPhysics(); + CSMWorld::IdCompletionManager &getIdCompletionManager(); + signals: void stateChanged (int state, CSMDoc::Document *document); From 33e36ee9227d88e334c8dbc9f0fd8017216d54ee Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 30 May 2015 15:51:33 +0300 Subject: [PATCH 11/36] Add the ID completion delegate --- apps/opencs/CMakeLists.txt | 2 +- .../view/world/idcompletiondelegate.cpp | 41 +++++++++++++++++++ .../view/world/idcompletiondelegate.hpp | 36 ++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/view/world/idcompletiondelegate.cpp create mode 100644 apps/opencs/view/world/idcompletiondelegate.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 99ba54ac1c..efbe77ccb7 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -69,7 +69,7 @@ opencs_units (view/world opencs_units_noqt (view/world subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate - scripthighlighter idvalidator dialoguecreator physicssystem + scripthighlighter idvalidator dialoguecreator physicssystem idcompletiondelegate ) opencs_units (view/widget diff --git a/apps/opencs/view/world/idcompletiondelegate.cpp b/apps/opencs/view/world/idcompletiondelegate.cpp new file mode 100644 index 0000000000..0f309054b7 --- /dev/null +++ b/apps/opencs/view/world/idcompletiondelegate.cpp @@ -0,0 +1,41 @@ +#include "idcompletiondelegate.hpp" + +#include "../../model/world/idcompletionmanager.hpp" + +CSVWorld::IdCompletionDelegate::IdCompletionDelegate(CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document& document, + QObject *parent) + : CommandDelegate(dispatcher, document, parent) +{} + +QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_None); +} + +QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index, + CSMWorld::ColumnBase::Display display) const +{ + int columnIdData = index.data(CSMWorld::ColumnBase::Role_ColumnId).toInt(); + CSMWorld::Columns::ColumnId columnId = static_cast(columnIdData); + CSMWorld::IdCompletionManager &completionManager = getDocument().getIdCompletionManager(); + + QWidget *editor = CSVWorld::CommandDelegate::createEditor(parent, option, index, display); + QLineEdit *lineEditor = qobject_cast(editor); + if (lineEditor != NULL && completionManager.isCompleterExistFor(columnId)) + { + lineEditor->setCompleter(completionManager.getCompleter(columnId).get()); + } + return editor; +} + +CSVWorld::CommandDelegate *CSVWorld::IdCompletionDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document& document, + QObject *parent) const +{ + return new IdCompletionDelegate(dispatcher, document, parent); +} \ No newline at end of file diff --git a/apps/opencs/view/world/idcompletiondelegate.hpp b/apps/opencs/view/world/idcompletiondelegate.hpp new file mode 100644 index 0000000000..11ecc1cb9b --- /dev/null +++ b/apps/opencs/view/world/idcompletiondelegate.hpp @@ -0,0 +1,36 @@ +#ifndef CSV_WORLD_IDCOMPLETIONMANAGER_HPP +#define CSV_WORLD_IDCOMPLETIONMANAGER_HPP + +#include "util.hpp" + +namespace CSVWorld +{ + /// \brief Enables the Id completion for a column + class IdCompletionDelegate : public CommandDelegate + { + public: + IdCompletionDelegate(CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document& document, + QObject *parent); + + virtual QWidget *createEditor (QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index) const; + + virtual QWidget *createEditor (QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index, + CSMWorld::ColumnBase::Display display) const; + }; + + class IdCompletionDelegateFactory : public CommandDelegateFactory + { + public: + virtual CommandDelegate *makeDelegate(CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document& document, + QObject *parent) const; + ///< The ownership of the returned CommandDelegate is transferred to the caller. + }; +} + +#endif \ No newline at end of file From 7f2dd21c6642147a0cf7f27df29ab6559cab8938 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 30 May 2015 17:20:49 +0200 Subject: [PATCH 12/36] Fix for StartScript regression (Fixes #2590) --- apps/openmw/mwworld/store.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index d6aeeb51ed..ba8be733a0 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -366,6 +366,19 @@ namespace MWWorld inserted.first->second = scpt; } + template <> + inline void Store::load(ESM::ESMReader &esm, const std::string &id) + { + ESM::StartScript s; + s.load(esm); + s.mId = Misc::StringUtils::toLower(s.mId); + std::pair inserted = mStatic.insert(std::make_pair(s.mId, s)); + if (inserted.second) + mShared.push_back(&inserted.first->second); + else + inserted.first->second = s; + } + template <> class Store : public StoreBase { From 5e8718d8b2ba976f7e1c4a339a464f7786b047c1 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 30 May 2015 18:37:13 +0300 Subject: [PATCH 13/36] Add the ID completion delegate factory to the delegate factory collection --- apps/opencs/view/doc/viewmanager.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 97b7aac19a..3e7c2cb972 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -16,6 +16,7 @@ #include "../world/vartypedelegate.hpp" #include "../world/recordstatusdelegate.hpp" #include "../world/idtypedelegate.hpp" +#include "../world/idcompletiondelegate.hpp" #include "../../model/settings/usersettings.hpp" @@ -60,6 +61,33 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType, new CSVWorld::IdTypeDelegateFactory()); + // Columns with QLineEdit editor + static const CSMWorld::ColumnBase::Display sIdCompletionColumns[] = + { + CSMWorld::ColumnBase::Display_Class, + CSMWorld::ColumnBase::Display_Faction, + CSMWorld::ColumnBase::Display_String, + CSMWorld::ColumnBase::Display_GlobalVariable, + CSMWorld::ColumnBase::Display_Icon, + CSMWorld::ColumnBase::Display_Mesh, + CSMWorld::ColumnBase::Display_Miscellaneous, + CSMWorld::ColumnBase::Display_Music, + CSMWorld::ColumnBase::Display_None, + CSMWorld::ColumnBase::Display_Race, + CSMWorld::ColumnBase::Display_Region, + CSMWorld::ColumnBase::Display_Script, + CSMWorld::ColumnBase::Display_Skill, + CSMWorld::ColumnBase::Display_Sound, + CSMWorld::ColumnBase::Display_SoundRes, + CSMWorld::ColumnBase::Display_Texture, + CSMWorld::ColumnBase::Display_Video + }; + + for (std::size_t i = 0; i < sizeof(sIdCompletionColumns) / sizeof(CSMWorld::ColumnBase::Display); ++i) + { + mDelegateFactories->add(sIdCompletionColumns[i], new CSVWorld::IdCompletionDelegateFactory()); + } + struct Mapping { CSMWorld::ColumnBase::Display mDisplay; From 602f33bd91dfcc87da6d8a0cef37d40d2f482594 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 30 May 2015 21:30:25 +0300 Subject: [PATCH 14/36] Add ColumnId role to the IdTree data methods --- apps/opencs/model/world/idtree.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/apps/opencs/model/world/idtree.cpp b/apps/opencs/model/world/idtree.cpp index 7351c03a77..a9ec2c4cd6 100644 --- a/apps/opencs/model/world/idtree.cpp +++ b/apps/opencs/model/world/idtree.cpp @@ -35,28 +35,26 @@ QVariant CSMWorld::IdTree::data (const QModelIndex & index, int role) const if (!index.isValid()) return QVariant(); - if ((role!=Qt::DisplayRole && role!=Qt::EditRole) || index.row() < 0 || index.column() < 0) - return QVariant(); - if (index.internalId() != 0) { std::pair parentAddress(unfoldIndexAddress(index.internalId())); + const NestableColumn *parentColumn = mNestedCollection->getNestableColumn(parentAddress.second); - if (role == Qt::EditRole && - !mNestedCollection->getNestableColumn(parentAddress.second)->nestedColumn(index.column()).isEditable()) - { + if (role == ColumnBase::Role_ColumnId) + return parentColumn->nestedColumn(index.column()).mColumnId; + + if (role == Qt::EditRole && !parentColumn->nestedColumn(index.column()).isEditable()) + return QVariant(); + + if (role != Qt::DisplayRole && role != Qt::EditRole) return QVariant(); - } return mNestedCollection->getNestedData(parentAddress.first, parentAddress.second, index.row(), index.column()); } else { - if (role==Qt::EditRole && !idCollection()->getColumn (index.column()).isEditable()) - return QVariant(); - - return idCollection()->getData (index.row(), index.column()); + return IdTable::data(index, role); } } @@ -79,6 +77,9 @@ QVariant CSMWorld::IdTree::nestedHeaderData(int section, int subSection, Qt::Ori if (role==ColumnBase::Role_Display) return parentColumn->nestedColumn(subSection).mDisplayType; + if (role==ColumnBase::Role_ColumnId) + return parentColumn->nestedColumn(subSection).mColumnId; + return QVariant(); } From e943d17b2905fb3b509662cda4800f6e5129191d Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 30 May 2015 22:01:21 +0300 Subject: [PATCH 15/36] Check for invalid index in IdTable::flags(). This prevents QCompleter from crashes --- apps/opencs/model/world/idtable.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 04aa271ccc..bde6412ece 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -84,6 +84,9 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const { + if (!index.isValid()) + return 0; + Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; if (mIdCollection->getColumn (index.column()).isUserEditable()) From 994c6833bcd91f72d00d1784a227dfcc14f0cfbc Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 30 May 2015 23:54:16 +0300 Subject: [PATCH 16/36] Add missing columns for the ID completion --- apps/opencs/model/world/idcompletionmanager.cpp | 11 +++++++++-- apps/opencs/view/doc/viewmanager.cpp | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/idcompletionmanager.cpp b/apps/opencs/model/world/idcompletionmanager.cpp index ca614dcd9e..c9e135c834 100644 --- a/apps/opencs/model/world/idcompletionmanager.cpp +++ b/apps/opencs/model/world/idcompletionmanager.cpp @@ -22,16 +22,19 @@ namespace types[CSMWorld::Columns::ColumnId_CastingSound] = CSMWorld::UniversalId::Type_Sound; types[CSMWorld::Columns::ColumnId_Cell] = CSMWorld::UniversalId::Type_Cell; types[CSMWorld::Columns::ColumnId_Class] = CSMWorld::UniversalId::Type_Class; + types[CSMWorld::Columns::ColumnId_CloseSound] = CSMWorld::UniversalId::Type_Sound; types[CSMWorld::Columns::ColumnId_Creature] = CSMWorld::UniversalId::Type_Referenceable; types[CSMWorld::Columns::ColumnId_DestinationCell] = CSMWorld::UniversalId::Type_Cell; types[CSMWorld::Columns::ColumnId_Enchantment] = CSMWorld::UniversalId::Type_Enchantment; types[CSMWorld::Columns::ColumnId_Faction] = CSMWorld::UniversalId::Type_Faction; - types[CSMWorld::Columns::Columnid_Hair] = CSMWorld::UniversalId::Type_Mesh; - types[CSMWorld::Columns::ColumnId_Head] = CSMWorld::UniversalId::Type_Mesh; + types[CSMWorld::Columns::Columnid_Hair] = CSMWorld::UniversalId::Type_BodyPart; + types[CSMWorld::Columns::ColumnId_Head] = CSMWorld::UniversalId::Type_BodyPart; types[CSMWorld::Columns::ColumnId_HitObject] = CSMWorld::UniversalId::Type_Referenceable; types[CSMWorld::Columns::ColumnId_HitSound] = CSMWorld::UniversalId::Type_Sound; types[CSMWorld::Columns::ColumnId_Icon] = CSMWorld::UniversalId::Type_Icon; types[CSMWorld::Columns::ColumnId_InventoryItemId] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::Columns::ColumnId_Key] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::Columns::ColumnId_LevelledItemId] = CSMWorld::UniversalId::Type_Referenceable; types[CSMWorld::Columns::ColumnId_MajorSkill1] = CSMWorld::UniversalId::Type_Skill; types[CSMWorld::Columns::ColumnId_MajorSkill2] = CSMWorld::UniversalId::Type_Skill; types[CSMWorld::Columns::ColumnId_MajorSkill3] = CSMWorld::UniversalId::Type_Skill; @@ -43,9 +46,13 @@ namespace types[CSMWorld::Columns::ColumnId_MinorSkill4] = CSMWorld::UniversalId::Type_Skill; types[CSMWorld::Columns::ColumnId_MinorSkill5] = CSMWorld::UniversalId::Type_Skill; types[CSMWorld::Columns::ColumnId_Model] = CSMWorld::UniversalId::Type_Mesh; + types[CSMWorld::Columns::ColumnId_OpenSound] = CSMWorld::UniversalId::Type_Sound; + types[CSMWorld::Columns::ColumnId_OriginalCreature] = CSMWorld::UniversalId::Type_Referenceable; types[CSMWorld::Columns::ColumnId_Owner] = CSMWorld::UniversalId::Type_Referenceable; types[CSMWorld::Columns::ColumnId_OwnerGlobal] = CSMWorld::UniversalId::Type_Global; types[CSMWorld::Columns::ColumnId_Particle] = CSMWorld::UniversalId::Type_Texture; + types[CSMWorld::Columns::ColumnId_PartRefMale] = CSMWorld::UniversalId::Type_BodyPart; + types[CSMWorld::Columns::ColumnId_PartRefFemale] = CSMWorld::UniversalId::Type_BodyPart; types[CSMWorld::Columns::ColumnId_PcFaction] = CSMWorld::UniversalId::Type_Faction; types[CSMWorld::Columns::ColumnId_Race] = CSMWorld::UniversalId::Type_Race; types[CSMWorld::Columns::ColumnId_ReferenceableId] = CSMWorld::UniversalId::Type_Referenceable; diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 3e7c2cb972..f485137032 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -64,7 +64,9 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) // Columns with QLineEdit editor static const CSMWorld::ColumnBase::Display sIdCompletionColumns[] = { + CSMWorld::ColumnBase::Display_Cell, CSMWorld::ColumnBase::Display_Class, + CSMWorld::ColumnBase::Display_Creature, CSMWorld::ColumnBase::Display_Faction, CSMWorld::ColumnBase::Display_String, CSMWorld::ColumnBase::Display_GlobalVariable, @@ -72,15 +74,20 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) CSMWorld::ColumnBase::Display_Mesh, CSMWorld::ColumnBase::Display_Miscellaneous, CSMWorld::ColumnBase::Display_Music, - CSMWorld::ColumnBase::Display_None, + CSMWorld::ColumnBase::Display_None, // Inplace editing (Table SubView) creates QLineEdit using Display_None + CSMWorld::ColumnBase::Display_Npc, CSMWorld::ColumnBase::Display_Race, + CSMWorld::ColumnBase::Display_Referenceable, CSMWorld::ColumnBase::Display_Region, CSMWorld::ColumnBase::Display_Script, CSMWorld::ColumnBase::Display_Skill, CSMWorld::ColumnBase::Display_Sound, CSMWorld::ColumnBase::Display_SoundRes, + CSMWorld::ColumnBase::Display_Static, + CSMWorld::ColumnBase::Display_String, CSMWorld::ColumnBase::Display_Texture, - CSMWorld::ColumnBase::Display_Video + CSMWorld::ColumnBase::Display_Video, + CSMWorld::ColumnBase::Display_Weapon }; for (std::size_t i = 0; i < sizeof(sIdCompletionColumns) / sizeof(CSMWorld::ColumnBase::Display); ++i) From 9e405b69fa74e429c23b4039365957dbdf1bc82d Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sun, 31 May 2015 16:43:28 +0300 Subject: [PATCH 17/36] Create the custom completer popup to avoid the problem with the wrong height of the default popup --- apps/opencs/CMakeLists.txt | 2 +- .../model/world/idcompletionmanager.cpp | 7 +++++ apps/opencs/view/widget/completerpopup.cpp | 28 +++++++++++++++++++ apps/opencs/view/widget/completerpopup.hpp | 17 +++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/view/widget/completerpopup.cpp create mode 100644 apps/opencs/view/widget/completerpopup.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index efbe77ccb7..37d13223a7 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -74,7 +74,7 @@ opencs_units_noqt (view/world opencs_units (view/widget scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton - scenetooltoggle2 + scenetooltoggle2 completerpopup ) opencs_units (view/render diff --git a/apps/opencs/model/world/idcompletionmanager.cpp b/apps/opencs/model/world/idcompletionmanager.cpp index c9e135c834..c483a9fb54 100644 --- a/apps/opencs/model/world/idcompletionmanager.cpp +++ b/apps/opencs/model/world/idcompletionmanager.cpp @@ -4,6 +4,8 @@ #include +#include "../../view/widget/completerpopup.hpp" + #include "data.hpp" #include "idtablebase.hpp" @@ -121,6 +123,11 @@ void CSMWorld::IdCompletionManager::generateCompleters(CSMWorld::Data &data) // The completion role must be Qt::DisplayRole to get the ID values from the model completer->setCompletionRole(Qt::DisplayRole); completer->setCaseSensitivity(Qt::CaseInsensitive); + + QAbstractItemView *popup = new CSVWidget::CompleterPopup(); + completer->setPopup(popup); // The completer takes ownership of the popup + completer->setMaxVisibleItems(10); + mCompleters[current->first] = completer; } } diff --git a/apps/opencs/view/widget/completerpopup.cpp b/apps/opencs/view/widget/completerpopup.cpp new file mode 100644 index 0000000000..ad50b76e6e --- /dev/null +++ b/apps/opencs/view/widget/completerpopup.cpp @@ -0,0 +1,28 @@ +#include "completerpopup.hpp" + +CSVWidget::CompleterPopup::CompleterPopup(QWidget *parent) + : QListView(parent) +{ + setEditTriggers(QAbstractItemView::NoEditTriggers); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setSelectionBehavior(QAbstractItemView::SelectRows); + setSelectionMode(QAbstractItemView::SingleSelection); +} + +int CSVWidget::CompleterPopup::sizeHintForRow(int row) const +{ + if (model() == NULL) + { + return -1; + } + if (row < 0 || row >= model()->rowCount()) + { + return -1; + } + + ensurePolished(); + QModelIndex index = model()->index(row, modelColumn()); + QStyleOptionViewItem option = viewOptions(); + QAbstractItemDelegate *delegate = itemDelegate(index); + return delegate->sizeHint(option, index).height(); +} \ No newline at end of file diff --git a/apps/opencs/view/widget/completerpopup.hpp b/apps/opencs/view/widget/completerpopup.hpp new file mode 100644 index 0000000000..92731ab508 --- /dev/null +++ b/apps/opencs/view/widget/completerpopup.hpp @@ -0,0 +1,17 @@ +#ifndef CSV_WIDGET_COMPLETERPOPUP_HPP +#define CSV_WIDGET_COMPLETERPOPUP_HPP + +#include + +namespace CSVWidget +{ + class CompleterPopup : public QListView + { + public: + CompleterPopup(QWidget *parent = 0); + + virtual int sizeHintForRow(int row) const; + }; +} + +#endif \ No newline at end of file From e636101725c8fe214bf18bfdab455ed81cfd3d67 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sun, 31 May 2015 18:18:49 +0300 Subject: [PATCH 18/36] Add missing new lines at the ends of files --- apps/opencs/model/doc/document.cpp | 2 +- apps/opencs/model/world/idcompletionmanager.cpp | 2 +- apps/opencs/model/world/idcompletionmanager.hpp | 2 +- apps/opencs/view/widget/completerpopup.cpp | 2 +- apps/opencs/view/widget/completerpopup.hpp | 2 +- apps/opencs/view/world/idcompletiondelegate.cpp | 2 +- apps/opencs/view/world/idcompletiondelegate.hpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 1e3d1c59b2..18a4f48787 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2493,4 +2493,4 @@ boost::shared_ptr CSMDoc::Document::getPhysics () CSMWorld::IdCompletionManager &CSMDoc::Document::getIdCompletionManager() { return mIdCompletionManager; -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/idcompletionmanager.cpp b/apps/opencs/model/world/idcompletionmanager.cpp index c483a9fb54..ff5ec6b4bd 100644 --- a/apps/opencs/model/world/idcompletionmanager.cpp +++ b/apps/opencs/model/world/idcompletionmanager.cpp @@ -132,4 +132,4 @@ void CSMWorld::IdCompletionManager::generateCompleters(CSMWorld::Data &data) } } } -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/idcompletionmanager.hpp b/apps/opencs/model/world/idcompletionmanager.hpp index 725cfa3312..fff9868eaf 100644 --- a/apps/opencs/model/world/idcompletionmanager.hpp +++ b/apps/opencs/model/world/idcompletionmanager.hpp @@ -35,4 +35,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/widget/completerpopup.cpp b/apps/opencs/view/widget/completerpopup.cpp index ad50b76e6e..5777325c83 100644 --- a/apps/opencs/view/widget/completerpopup.cpp +++ b/apps/opencs/view/widget/completerpopup.cpp @@ -25,4 +25,4 @@ int CSVWidget::CompleterPopup::sizeHintForRow(int row) const QStyleOptionViewItem option = viewOptions(); QAbstractItemDelegate *delegate = itemDelegate(index); return delegate->sizeHint(option, index).height(); -} \ No newline at end of file +} diff --git a/apps/opencs/view/widget/completerpopup.hpp b/apps/opencs/view/widget/completerpopup.hpp index 92731ab508..6857064b8f 100644 --- a/apps/opencs/view/widget/completerpopup.hpp +++ b/apps/opencs/view/widget/completerpopup.hpp @@ -14,4 +14,4 @@ namespace CSVWidget }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/world/idcompletiondelegate.cpp b/apps/opencs/view/world/idcompletiondelegate.cpp index 0f309054b7..33e1282d4c 100644 --- a/apps/opencs/view/world/idcompletiondelegate.cpp +++ b/apps/opencs/view/world/idcompletiondelegate.cpp @@ -38,4 +38,4 @@ CSVWorld::CommandDelegate *CSVWorld::IdCompletionDelegateFactory::makeDelegate(C QObject *parent) const { return new IdCompletionDelegate(dispatcher, document, parent); -} \ No newline at end of file +} diff --git a/apps/opencs/view/world/idcompletiondelegate.hpp b/apps/opencs/view/world/idcompletiondelegate.hpp index 11ecc1cb9b..979c10c343 100644 --- a/apps/opencs/view/world/idcompletiondelegate.hpp +++ b/apps/opencs/view/world/idcompletiondelegate.hpp @@ -33,4 +33,4 @@ namespace CSVWorld }; } -#endif \ No newline at end of file +#endif From dbe61115b2086fdee2649972d171db5a93c30793 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sun, 31 May 2015 18:22:43 +0300 Subject: [PATCH 19/36] Fix the mistyping header guard in the idcompletiondelegate.hpp --- apps/opencs/view/world/idcompletiondelegate.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/world/idcompletiondelegate.hpp b/apps/opencs/view/world/idcompletiondelegate.hpp index 979c10c343..d2ac6874f6 100644 --- a/apps/opencs/view/world/idcompletiondelegate.hpp +++ b/apps/opencs/view/world/idcompletiondelegate.hpp @@ -1,5 +1,5 @@ -#ifndef CSV_WORLD_IDCOMPLETIONMANAGER_HPP -#define CSV_WORLD_IDCOMPLETIONMANAGER_HPP +#ifndef CSV_WORLD_IDCOMPLETIONDELEGATE_HPP +#define CSV_WORLD_IDCOMPLETIONDELEGATE_HPP #include "util.hpp" From 5dc6cdeb99907385c7ca9cf513aa46f251595e8b Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Mon, 1 Jun 2015 01:14:11 +0300 Subject: [PATCH 20/36] Scroll to the top of the topic list when dialog is started --- apps/openmw/mwgui/dialogue.cpp | 2 ++ components/widgets/list.cpp | 4 ++++ components/widgets/list.hpp | 2 ++ 3 files changed, 8 insertions(+) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 692cea952d..48b9be17db 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -364,6 +364,7 @@ namespace MWGui bool sameActor = (mPtr == actor); mPtr = actor; mTopicsList->setEnabled(true); + mTopicsList->scrollToFirstItem(); setTitle(npcName); clearChoices(); @@ -455,6 +456,7 @@ namespace MWGui mKeywordSearch.seed(Misc::StringUtils::lowerCase(*it), intptr_t(t)); } mTopicsList->adjustSize(); + mTopicsList->scrollToFirstItem(); updateHistory(); } diff --git a/components/widgets/list.cpp b/components/widgets/list.cpp index 5a79de3d1a..e1d80f0226 100644 --- a/components/widgets/list.cpp +++ b/components/widgets/list.cpp @@ -157,4 +157,8 @@ namespace Gui return mScrollView->findWidget (getName() + "_item_" + name)->castType(); } + void MWList::scrollToFirstItem() + { + mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); + } } diff --git a/components/widgets/list.hpp b/components/widgets/list.hpp index 72c8a733c1..1c24af6a4c 100644 --- a/components/widgets/list.hpp +++ b/components/widgets/list.hpp @@ -46,6 +46,8 @@ namespace Gui MyGUI::Button* getItemWidget(const std::string& name); ///< get widget for an item name, useful to set up tooltip + void scrollToFirstItem(); + virtual void setPropertyOverride(const std::string& _key, const std::string& _value); protected: From 5350ce59efec0beee86f0637e5f6412631e31b79 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Mon, 1 Jun 2015 22:42:41 +0300 Subject: [PATCH 21/36] MWList doesn't scroll to the very bottom when it's shown for first time --- components/widgets/list.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/widgets/list.cpp b/components/widgets/list.cpp index e1d80f0226..535a3cad3f 100644 --- a/components/widgets/list.cpp +++ b/components/widgets/list.cpp @@ -48,7 +48,7 @@ namespace Gui const int _scrollBarWidth = 20; // fetch this from skin? const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0; const int spacing = 3; - size_t viewPosition = -mScrollView->getViewOffset().top; + int viewPosition = mScrollView->getViewOffset().top; while (mScrollView->getChildCount()) { @@ -99,10 +99,10 @@ namespace Gui if (!scrollbarShown && mItemHeight > mClient->getSize().height) redraw(true); - size_t viewRange = mScrollView->getCanvasSize().height; + int viewRange = mScrollView->getCanvasSize().height; if(viewPosition > viewRange) viewPosition = viewRange; - mScrollView->setViewOffset(MyGUI::IntPoint(0, viewPosition * -1)); + mScrollView->setViewOffset(MyGUI::IntPoint(0, viewPosition)); } void MWList::setPropertyOverride(const std::string &_key, const std::string &_value) From 959fe3eb8773be66219575ae161e625f03536f69 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Mon, 1 Jun 2015 23:49:40 +0300 Subject: [PATCH 22/36] Reset the scrollbar position in the topic list when DialogueWindow is closed --- apps/openmw/mwgui/dialogue.cpp | 5 +++-- components/widgets/list.cpp | 2 +- components/widgets/list.hpp | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 48b9be17db..0cb0475c91 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -291,7 +291,10 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); } else + { MWBase::Environment::get().getDialogueManager()->goodbyeSelected(); + mTopicsList->scrollToTop(); + } } void DialogueWindow::onWindowResize(MyGUI::Window* _sender) @@ -364,7 +367,6 @@ namespace MWGui bool sameActor = (mPtr == actor); mPtr = actor; mTopicsList->setEnabled(true); - mTopicsList->scrollToFirstItem(); setTitle(npcName); clearChoices(); @@ -456,7 +458,6 @@ namespace MWGui mKeywordSearch.seed(Misc::StringUtils::lowerCase(*it), intptr_t(t)); } mTopicsList->adjustSize(); - mTopicsList->scrollToFirstItem(); updateHistory(); } diff --git a/components/widgets/list.cpp b/components/widgets/list.cpp index 535a3cad3f..db4092b3f8 100644 --- a/components/widgets/list.cpp +++ b/components/widgets/list.cpp @@ -157,7 +157,7 @@ namespace Gui return mScrollView->findWidget (getName() + "_item_" + name)->castType(); } - void MWList::scrollToFirstItem() + void MWList::scrollToTop() { mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); } diff --git a/components/widgets/list.hpp b/components/widgets/list.hpp index 1c24af6a4c..3efe1ff756 100644 --- a/components/widgets/list.hpp +++ b/components/widgets/list.hpp @@ -46,7 +46,7 @@ namespace Gui MyGUI::Button* getItemWidget(const std::string& name); ///< get widget for an item name, useful to set up tooltip - void scrollToFirstItem(); + void scrollToTop(); virtual void setPropertyOverride(const std::string& _key, const std::string& _value); From 2c4025ec72dfd021a9252536c2385672b74e39a5 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 2 Jun 2015 00:26:31 +0300 Subject: [PATCH 23/36] Rename the method isCompleterExistFor() to hasCompleterFor() --- apps/opencs/model/world/idcompletionmanager.cpp | 4 ++-- apps/opencs/model/world/idcompletionmanager.hpp | 2 +- apps/opencs/view/world/idcompletiondelegate.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/idcompletionmanager.cpp b/apps/opencs/model/world/idcompletionmanager.cpp index ff5ec6b4bd..6736e94771 100644 --- a/apps/opencs/model/world/idcompletionmanager.cpp +++ b/apps/opencs/model/world/idcompletionmanager.cpp @@ -89,14 +89,14 @@ CSMWorld::IdCompletionManager::IdCompletionManager(CSMWorld::Data &data) generateCompleters(data); } -bool CSMWorld::IdCompletionManager::isCompleterExistFor(CSMWorld::Columns::ColumnId id) const +bool CSMWorld::IdCompletionManager::hasCompleterFor(CSMWorld::Columns::ColumnId id) const { return mCompleters.find(id) != mCompleters.end(); } boost::shared_ptr CSMWorld::IdCompletionManager::getCompleter(CSMWorld::Columns::ColumnId id) { - if (!isCompleterExistFor(id)) + if (!hasCompleterFor(id)) { throw std::logic_error("This column doesn't have an ID completer"); } diff --git a/apps/opencs/model/world/idcompletionmanager.hpp b/apps/opencs/model/world/idcompletionmanager.hpp index fff9868eaf..ee75ddf248 100644 --- a/apps/opencs/model/world/idcompletionmanager.hpp +++ b/apps/opencs/model/world/idcompletionmanager.hpp @@ -30,7 +30,7 @@ namespace CSMWorld public: IdCompletionManager(CSMWorld::Data &data); - bool isCompleterExistFor(CSMWorld::Columns::ColumnId id) const; + bool hasCompleterFor(CSMWorld::Columns::ColumnId id) const; boost::shared_ptr getCompleter(CSMWorld::Columns::ColumnId id); }; } diff --git a/apps/opencs/view/world/idcompletiondelegate.cpp b/apps/opencs/view/world/idcompletiondelegate.cpp index 33e1282d4c..2a1e97f4bd 100644 --- a/apps/opencs/view/world/idcompletiondelegate.cpp +++ b/apps/opencs/view/world/idcompletiondelegate.cpp @@ -26,7 +26,7 @@ QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent, QWidget *editor = CSVWorld::CommandDelegate::createEditor(parent, option, index, display); QLineEdit *lineEditor = qobject_cast(editor); - if (lineEditor != NULL && completionManager.isCompleterExistFor(columnId)) + if (lineEditor != NULL && completionManager.hasCompleterFor(columnId)) { lineEditor->setCompleter(completionManager.getCompleter(columnId).get()); } From 6cb221f8d09cce21ccdba5cae6e3fac0f0e49b1b Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 2 Jun 2015 11:55:09 +0300 Subject: [PATCH 24/36] Some minor changes to MWList --- components/widgets/list.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/widgets/list.cpp b/components/widgets/list.cpp index db4092b3f8..df7e7d61d2 100644 --- a/components/widgets/list.cpp +++ b/components/widgets/list.cpp @@ -48,7 +48,7 @@ namespace Gui const int _scrollBarWidth = 20; // fetch this from skin? const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0; const int spacing = 3; - int viewPosition = mScrollView->getViewOffset().top; + int viewPosition = -mScrollView->getViewOffset().top; while (mScrollView->getChildCount()) { @@ -102,7 +102,7 @@ namespace Gui int viewRange = mScrollView->getCanvasSize().height; if(viewPosition > viewRange) viewPosition = viewRange; - mScrollView->setViewOffset(MyGUI::IntPoint(0, viewPosition)); + mScrollView->setViewOffset(MyGUI::IntPoint(0, -viewPosition)); } void MWList::setPropertyOverride(const std::string &_key, const std::string &_value) From ee2763f2d4286bd63e15a72aa96424763146a5f4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 2 Jun 2015 14:43:38 +0200 Subject: [PATCH 25/36] Allow 5th parameter for PlaceAtMe (numeric value, ignored) (Fixes #2591) --- components/compiler/extensions0.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index c56ee2ffb5..a16e653c3a 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -531,7 +531,7 @@ namespace Compiler extensions.registerInstruction("placeitemcell","ccffff",opcodePlaceItemCell); extensions.registerInstruction("placeitem","cffff",opcodePlaceItem); extensions.registerInstruction("placeatpc","clfl",opcodePlaceAtPc); - extensions.registerInstruction("placeatme","clfl",opcodePlaceAtMe,opcodePlaceAtMeExplicit); + extensions.registerInstruction("placeatme","clflX",opcodePlaceAtMe,opcodePlaceAtMeExplicit); extensions.registerInstruction("modscale","f",opcodeModScale,opcodeModScaleExplicit); extensions.registerInstruction("rotate","cf",opcodeRotate,opcodeRotateExplicit); extensions.registerInstruction("rotateworld","cf",opcodeRotateWorld,opcodeRotateWorldExplicit); From f84c36b500b09300d49382cdcf4de90449aa32db Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 3 Jun 2015 00:00:39 +0300 Subject: [PATCH 26/36] CommandDelegate: extract a display type from a model if it isn't specified --- apps/opencs/model/world/idtable.cpp | 3 +++ apps/opencs/model/world/idtree.cpp | 3 +++ apps/opencs/view/world/util.cpp | 8 +++++++- apps/opencs/view/world/util.hpp | 2 ++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index bde6412ece..8ca19f7e96 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -33,6 +33,9 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const if (index.row() < 0 || index.column() < 0) return QVariant(); + if (role==ColumnBase::Role_Display) + return QVariant(mIdCollection->getColumn(index.column()).mDisplayType); + if (role==ColumnBase::Role_ColumnId) return QVariant (getColumnId (index.column())); diff --git a/apps/opencs/model/world/idtree.cpp b/apps/opencs/model/world/idtree.cpp index a9ec2c4cd6..a3dbae4655 100644 --- a/apps/opencs/model/world/idtree.cpp +++ b/apps/opencs/model/world/idtree.cpp @@ -40,6 +40,9 @@ QVariant CSMWorld::IdTree::data (const QModelIndex & index, int role) const std::pair parentAddress(unfoldIndexAddress(index.internalId())); const NestableColumn *parentColumn = mNestedCollection->getNestableColumn(parentAddress.second); + if (role == ColumnBase::Role_Display) + return parentColumn->nestedColumn(index.column()).mColumnId; + if (role == ColumnBase::Role_ColumnId) return parentColumn->nestedColumn(index.column()).mColumnId; diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 5452214ef4..3be875ffd7 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -111,6 +111,12 @@ CSMDoc::Document& CSVWorld::CommandDelegate::getDocument() const return mDocument; } +CSMWorld::ColumnBase::Display CSVWorld::CommandDelegate::getDisplayTypeFromIndex(const QModelIndex &index) const +{ + int rawDisplay = index.data(CSMWorld::ColumnBase::Role_Display).toInt(); + return static_cast(rawDisplay); +} + void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const { @@ -146,7 +152,7 @@ void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemMode QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { - return createEditor (parent, option, index, CSMWorld::ColumnBase::Display_None); + return createEditor (parent, option, index, getDisplayTypeFromIndex(index)); } QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option, diff --git a/apps/opencs/view/world/util.hpp b/apps/opencs/view/world/util.hpp index a12e6ae369..8355e971cb 100644 --- a/apps/opencs/view/world/util.hpp +++ b/apps/opencs/view/world/util.hpp @@ -124,6 +124,8 @@ namespace CSVWorld CSMDoc::Document& getDocument() const; + CSMWorld::ColumnBase::Display getDisplayTypeFromIndex(const QModelIndex &index) const; + virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; From 4e759370def736689dfc3acc4f64a4aa5d77ad6b Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 3 Jun 2015 00:02:53 +0300 Subject: [PATCH 27/36] Change Display_String to the proper display type where appropriate --- apps/opencs/model/world/columnbase.cpp | 2 ++ apps/opencs/model/world/columnbase.hpp | 2 ++ apps/opencs/model/world/columnimp.hpp | 21 ++++++++++++-------- apps/opencs/model/world/data.cpp | 8 ++++---- apps/opencs/model/world/refidcollection.cpp | 22 ++++++++++----------- 5 files changed, 32 insertions(+), 23 deletions(-) diff --git a/apps/opencs/model/world/columnbase.cpp b/apps/opencs/model/world/columnbase.cpp index 3d13538c03..9385038757 100644 --- a/apps/opencs/model/world/columnbase.cpp +++ b/apps/opencs/model/world/columnbase.cpp @@ -65,6 +65,8 @@ bool CSMWorld::ColumnBase::isId (Display display) Display_JournalInfo, Display_Scene, Display_GlobalVariable, + Display_BodyPart, + Display_Enchantment, Display_Script, Display_Mesh, diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index bf8378e37b..789823d5cd 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -74,6 +74,8 @@ namespace CSMWorld Display_JournalInfo, Display_Scene, Display_GlobalVariable, + Display_BodyPart, + Display_Enchantment, //CONCRETE TYPES ENDS HERE Display_Integer, diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 6b496e0ca7..8758d924b0 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -709,7 +709,7 @@ namespace CSMWorld struct SleepListColumn : public Column { SleepListColumn() - : Column (Columns::ColumnId_SleepEncounter, ColumnBase::Display_String) + : Column (Columns::ColumnId_SleepEncounter, ColumnBase::Display_CreatureLevelledList) {} virtual QVariant get (const Record& record) const @@ -735,7 +735,7 @@ namespace CSMWorld template struct TextureColumn : public Column { - TextureColumn() : Column (Columns::ColumnId_Texture, ColumnBase::Display_String) {} + TextureColumn() : Column (Columns::ColumnId_Texture, ColumnBase::Display_Texture) {} virtual QVariant get (const Record& record) const { @@ -1269,7 +1269,7 @@ namespace CSMWorld template struct TrapColumn : public Column { - TrapColumn() : Column (Columns::ColumnId_Trap, ColumnBase::Display_String) {} + TrapColumn() : Column (Columns::ColumnId_Trap, ColumnBase::Display_Spell) {} virtual QVariant get (const Record& record) const { @@ -1294,7 +1294,7 @@ namespace CSMWorld template struct FilterColumn : public Column { - FilterColumn() : Column (Columns::ColumnId_Filter, ColumnBase::Display_String) {} + FilterColumn() : Column (Columns::ColumnId_Filter, ColumnBase::Display_Filter) {} virtual QVariant get (const Record& record) const { @@ -1497,7 +1497,10 @@ namespace CSMWorld template struct TopicColumn : public Column { - TopicColumn (bool journal) : Column (journal ? Columns::ColumnId_Journal : Columns::ColumnId_Topic, ColumnBase::Display_String) {} + TopicColumn (bool journal) + : Column (journal ? Columns::ColumnId_Journal : Columns::ColumnId_Topic, + journal ? ColumnBase::Display_Journal : ColumnBase::Display_Topic) + {} virtual QVariant get (const Record& record) const { @@ -1527,7 +1530,7 @@ namespace CSMWorld template struct ActorColumn : public Column { - ActorColumn() : Column (Columns::ColumnId_Actor, ColumnBase::Display_String) {} + ActorColumn() : Column (Columns::ColumnId_Actor, ColumnBase::Display_Npc) {} virtual QVariant get (const Record& record) const { @@ -1830,7 +1833,7 @@ namespace CSMWorld template struct ModelColumn : public Column { - ModelColumn() : Column (Columns::ColumnId_Model, ColumnBase::Display_String) {} + ModelColumn() : Column (Columns::ColumnId_Model, ColumnBase::Display_Mesh) {} virtual QVariant get (const Record& record) const { @@ -2158,7 +2161,9 @@ namespace CSMWorld struct EffectTextureColumn : public Column { EffectTextureColumn (Columns::ColumnId columnId) - : Column (columnId, ColumnBase::Display_Texture) + : Column (columnId, + columnId == Columns::ColumnId_Particle ? ColumnBase::Display_Texture + : ColumnBase::Display_Icon) { assert (this->mColumnId==Columns::ColumnId_Icon || this->mColumnId==Columns::ColumnId_Particle); diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index c27c068f10..529c8f88f9 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -115,7 +115,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc index = mFactions.getColumns()-1; mFactions.addAdapter (std::make_pair(&mFactions.getColumn(index), new FactionReactionsAdapter ())); mFactions.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_Faction, ColumnBase::Display_String)); + new NestedChildColumn (Columns::ColumnId_Faction, ColumnBase::Display_Faction)); mFactions.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_FactionReaction, ColumnBase::Display_Integer)); @@ -135,7 +135,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc index = mRaces.getColumns()-1; mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new SpellListAdapter ())); mRaces.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_String)); + new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_Spell)); // Race attributes mRaces.addColumn (new NestedParentColumn (Columns::ColumnId_RaceAttributes)); index = mRaces.getColumns()-1; @@ -180,7 +180,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc index = mRegions.getColumns()-1; mRegions.addAdapter (std::make_pair(&mRegions.getColumn(index), new RegionSoundListAdapter ())); mRegions.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_SoundName, ColumnBase::Display_String)); + new NestedChildColumn (Columns::ColumnId_SoundName, ColumnBase::Display_Sound)); mRegions.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_SoundChance, ColumnBase::Display_Integer)); @@ -196,7 +196,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mBirthsigns.addAdapter (std::make_pair(&mBirthsigns.getColumn(index), new SpellListAdapter ())); mBirthsigns.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_String)); + new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_Spell)); mSpells.addColumn (new StringIdColumn); mSpells.addColumn (new RecordStateColumn); diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index cda19c87bb..5495926b46 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -99,7 +99,7 @@ CSMWorld::RefIdCollection::RefIdCollection() EnchantableColumns enchantableColumns (inventoryColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Enchantment, ColumnBase::Display_String)); + mColumns.push_back (RefIdColumn (Columns::ColumnId_Enchantment, ColumnBase::Display_Enchantment)); enchantableColumns.mEnchantment = &mColumns.back(); mColumns.push_back (RefIdColumn (Columns::ColumnId_EnchantmentPoints, ColumnBase::Display_Integer)); enchantableColumns.mEnchantmentPoints = &mColumns.back(); @@ -135,7 +135,7 @@ CSMWorld::RefIdCollection::RefIdCollection() new NestedInventoryRefIdAdapter (UniversalId::Type_Creature))); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), inventoryMap)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_String)); + new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_Referenceable)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer)); @@ -150,7 +150,7 @@ CSMWorld::RefIdCollection::RefIdCollection() new NestedSpellRefIdAdapter (UniversalId::Type_Creature))); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), spellsMap)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_SpellId, CSMWorld::ColumnBase::Display_String)); + new RefIdColumn (Columns::ColumnId_SpellId, CSMWorld::ColumnBase::Display_Spell)); // Nested table mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcDestinations, @@ -163,7 +163,7 @@ CSMWorld::RefIdCollection::RefIdCollection() new NestedTravelRefIdAdapter (UniversalId::Type_Creature))); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), destMap)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_DestinationCell, CSMWorld::ColumnBase::Display_String)); + new RefIdColumn (Columns::ColumnId_DestinationCell, CSMWorld::ColumnBase::Display_Cell)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_PosX, CSMWorld::ColumnBase::Display_Float)); mColumns.back().addColumn( @@ -289,7 +289,7 @@ CSMWorld::RefIdCollection::RefIdCollection() new NestedInventoryRefIdAdapter (UniversalId::Type_Container))); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), contMap)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_String)); + new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_Referenceable)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer)); @@ -301,7 +301,7 @@ CSMWorld::RefIdCollection::RefIdCollection() creatureColumns.mSoul = &mColumns.back(); mColumns.push_back (RefIdColumn (Columns::ColumnId_Scale, ColumnBase::Display_Float)); creatureColumns.mScale = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_OriginalCreature, ColumnBase::Display_String)); + mColumns.push_back (RefIdColumn (Columns::ColumnId_OriginalCreature, ColumnBase::Display_Creature)); creatureColumns.mOriginal = &mColumns.back(); mColumns.push_back ( RefIdColumn (Columns::ColumnId_CombatState, ColumnBase::Display_Integer)); @@ -409,10 +409,10 @@ CSMWorld::RefIdCollection::RefIdCollection() mColumns.push_back (RefIdColumn (Columns::ColumnId_Faction, ColumnBase::Display_Faction)); npcColumns.mFaction = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::Columnid_Hair, ColumnBase::Display_String)); + mColumns.push_back (RefIdColumn (Columns::Columnid_Hair, ColumnBase::Display_BodyPart)); npcColumns.mHair = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Head, ColumnBase::Display_String)); + mColumns.push_back (RefIdColumn (Columns::ColumnId_Head, ColumnBase::Display_BodyPart)); npcColumns.mHead = &mColumns.back(); mColumns.push_back (RefIdColumn (Columns::ColumnId_Female, ColumnBase::Display_Boolean)); @@ -539,9 +539,9 @@ CSMWorld::RefIdCollection::RefIdCollection() mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_PartRefType, CSMWorld::ColumnBase::Display_PartRefType)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_PartRefMale, CSMWorld::ColumnBase::Display_String)); + new RefIdColumn (Columns::ColumnId_PartRefMale, CSMWorld::ColumnBase::Display_BodyPart)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_PartRefFemale, CSMWorld::ColumnBase::Display_String)); + new RefIdColumn (Columns::ColumnId_PartRefFemale, CSMWorld::ColumnBase::Display_BodyPart)); LevListColumns levListColumns (baseColumns); @@ -556,7 +556,7 @@ CSMWorld::RefIdCollection::RefIdCollection() new NestedLevListRefIdAdapter (UniversalId::Type_ItemLevelledList))); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), levListMap)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_LevelledItemId, CSMWorld::ColumnBase::Display_String)); + new RefIdColumn (Columns::ColumnId_LevelledItemId, CSMWorld::ColumnBase::Display_Referenceable)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_LevelledItemLevel, CSMWorld::ColumnBase::Display_Integer)); From b25cc6bc556ff688fcf5becd4d71c3551f5681af Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 3 Jun 2015 12:01:13 +0300 Subject: [PATCH 28/36] IdCompletionManager uses Display type instread of ColumnId for creating completers --- .../model/world/idcompletionmanager.cpp | 117 +++++++----------- .../model/world/idcompletionmanager.hpp | 17 +-- apps/opencs/view/doc/viewmanager.cpp | 38 ++---- .../view/world/idcompletiondelegate.cpp | 16 ++- 4 files changed, 70 insertions(+), 118 deletions(-) diff --git a/apps/opencs/model/world/idcompletionmanager.cpp b/apps/opencs/model/world/idcompletionmanager.cpp index 6736e94771..b59987cba2 100644 --- a/apps/opencs/model/world/idcompletionmanager.cpp +++ b/apps/opencs/model/world/idcompletionmanager.cpp @@ -11,102 +11,77 @@ namespace { - std::map generateModelTypes() + std::map generateModelTypes() { - std::map types; + std::map types; - types[CSMWorld::Columns::ColumnId_Actor] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_AreaObject] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_AreaSound] = CSMWorld::UniversalId::Type_Sound; - types[CSMWorld::Columns::ColumnId_BoltObject] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_BoltSound] = CSMWorld::UniversalId::Type_Sound; - types[CSMWorld::Columns::ColumnId_CastingObject] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_CastingSound] = CSMWorld::UniversalId::Type_Sound; - types[CSMWorld::Columns::ColumnId_Cell] = CSMWorld::UniversalId::Type_Cell; - types[CSMWorld::Columns::ColumnId_Class] = CSMWorld::UniversalId::Type_Class; - types[CSMWorld::Columns::ColumnId_CloseSound] = CSMWorld::UniversalId::Type_Sound; - types[CSMWorld::Columns::ColumnId_Creature] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_DestinationCell] = CSMWorld::UniversalId::Type_Cell; - types[CSMWorld::Columns::ColumnId_Enchantment] = CSMWorld::UniversalId::Type_Enchantment; - types[CSMWorld::Columns::ColumnId_Faction] = CSMWorld::UniversalId::Type_Faction; - types[CSMWorld::Columns::Columnid_Hair] = CSMWorld::UniversalId::Type_BodyPart; - types[CSMWorld::Columns::ColumnId_Head] = CSMWorld::UniversalId::Type_BodyPart; - types[CSMWorld::Columns::ColumnId_HitObject] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_HitSound] = CSMWorld::UniversalId::Type_Sound; - types[CSMWorld::Columns::ColumnId_Icon] = CSMWorld::UniversalId::Type_Icon; - types[CSMWorld::Columns::ColumnId_InventoryItemId] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_Key] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_LevelledItemId] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_MajorSkill1] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_MajorSkill2] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_MajorSkill3] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_MajorSkill4] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_MajorSkill5] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_MinorSkill1] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_MinorSkill2] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_MinorSkill3] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_MinorSkill4] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_MinorSkill5] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_Model] = CSMWorld::UniversalId::Type_Mesh; - types[CSMWorld::Columns::ColumnId_OpenSound] = CSMWorld::UniversalId::Type_Sound; - types[CSMWorld::Columns::ColumnId_OriginalCreature] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_Owner] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_OwnerGlobal] = CSMWorld::UniversalId::Type_Global; - types[CSMWorld::Columns::ColumnId_Particle] = CSMWorld::UniversalId::Type_Texture; - types[CSMWorld::Columns::ColumnId_PartRefMale] = CSMWorld::UniversalId::Type_BodyPart; - types[CSMWorld::Columns::ColumnId_PartRefFemale] = CSMWorld::UniversalId::Type_BodyPart; - types[CSMWorld::Columns::ColumnId_PcFaction] = CSMWorld::UniversalId::Type_Faction; - types[CSMWorld::Columns::ColumnId_Race] = CSMWorld::UniversalId::Type_Race; - types[CSMWorld::Columns::ColumnId_ReferenceableId] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_Region] = CSMWorld::UniversalId::Type_Region; - types[CSMWorld::Columns::ColumnId_Skill1] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_Skill2] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_Skill3] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_Skill4] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_Skill5] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_Skill6] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_Skill7] = CSMWorld::UniversalId::Type_Skill; - types[CSMWorld::Columns::ColumnId_SleepEncounter] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_Soul] = CSMWorld::UniversalId::Type_Referenceable; - types[CSMWorld::Columns::ColumnId_Sound] = CSMWorld::UniversalId::Type_Sound; - types[CSMWorld::Columns::ColumnId_SoundFile] = CSMWorld::UniversalId::Type_SoundRes; - types[CSMWorld::Columns::ColumnId_SoundName] = CSMWorld::UniversalId::Type_Sound; - types[CSMWorld::Columns::ColumnId_SpellId] = CSMWorld::UniversalId::Type_Spell; - types[CSMWorld::Columns::ColumnId_Script] = CSMWorld::UniversalId::Type_Script; - types[CSMWorld::Columns::ColumnId_TeleportCell] = CSMWorld::UniversalId::Type_Cell; - types[CSMWorld::Columns::ColumnId_Texture] = CSMWorld::UniversalId::Type_Texture; - types[CSMWorld::Columns::ColumnId_Trap] = CSMWorld::UniversalId::Type_Spell; + types[CSMWorld::ColumnBase::Display_BodyPart ] = CSMWorld::UniversalId::Type_BodyPart; + types[CSMWorld::ColumnBase::Display_Cell ] = CSMWorld::UniversalId::Type_Cell; + types[CSMWorld::ColumnBase::Display_Class ] = CSMWorld::UniversalId::Type_Class; + types[CSMWorld::ColumnBase::Display_CreatureLevelledList] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::ColumnBase::Display_Creature ] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::ColumnBase::Display_Enchantment ] = CSMWorld::UniversalId::Type_Enchantment; + 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_Mesh ] = CSMWorld::UniversalId::Type_Mesh; + types[CSMWorld::ColumnBase::Display_Miscellaneous ] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::ColumnBase::Display_Npc ] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::ColumnBase::Display_Race ] = CSMWorld::UniversalId::Type_Race; + types[CSMWorld::ColumnBase::Display_Region ] = CSMWorld::UniversalId::Type_Region; + types[CSMWorld::ColumnBase::Display_Referenceable ] = CSMWorld::UniversalId::Type_Referenceable; + types[CSMWorld::ColumnBase::Display_Script ] = CSMWorld::UniversalId::Type_Script; + types[CSMWorld::ColumnBase::Display_Skill ] = CSMWorld::UniversalId::Type_Skill; + types[CSMWorld::ColumnBase::Display_Sound ] = CSMWorld::UniversalId::Type_Sound; + types[CSMWorld::ColumnBase::Display_SoundRes ] = CSMWorld::UniversalId::Type_SoundRes; + 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_Weapon ] = CSMWorld::UniversalId::Type_Referenceable; return types; } + + typedef std::map::const_iterator ModelTypeConstIterator; } -const std::map +const std::map CSMWorld::IdCompletionManager::sCompleterModelTypes = generateModelTypes(); +std::vector CSMWorld::IdCompletionManager::getDisplayTypes() +{ + std::vector types; + ModelTypeConstIterator current = sCompleterModelTypes.begin(); + ModelTypeConstIterator end = sCompleterModelTypes.end(); + for (; current != end; ++current) + { + types.push_back(current->first); + } + return types; +} + CSMWorld::IdCompletionManager::IdCompletionManager(CSMWorld::Data &data) { generateCompleters(data); } -bool CSMWorld::IdCompletionManager::hasCompleterFor(CSMWorld::Columns::ColumnId id) const +bool CSMWorld::IdCompletionManager::hasCompleterFor(CSMWorld::ColumnBase::Display display) const { - return mCompleters.find(id) != mCompleters.end(); + return mCompleters.find(display) != mCompleters.end(); } -boost::shared_ptr CSMWorld::IdCompletionManager::getCompleter(CSMWorld::Columns::ColumnId id) +boost::shared_ptr CSMWorld::IdCompletionManager::getCompleter(CSMWorld::ColumnBase::Display display) { - if (!hasCompleterFor(id)) + if (!hasCompleterFor(display)) { throw std::logic_error("This column doesn't have an ID completer"); } - return mCompleters[id]; + return mCompleters[display]; } void CSMWorld::IdCompletionManager::generateCompleters(CSMWorld::Data &data) { - typedef std::map::const_iterator ModelTypeConstIterator; - ModelTypeConstIterator current = sCompleterModelTypes.begin(); ModelTypeConstIterator end = sCompleterModelTypes.end(); for (; current != end; ++current) diff --git a/apps/opencs/model/world/idcompletionmanager.hpp b/apps/opencs/model/world/idcompletionmanager.hpp index ee75ddf248..7944e6777e 100644 --- a/apps/opencs/model/world/idcompletionmanager.hpp +++ b/apps/opencs/model/world/idcompletionmanager.hpp @@ -1,11 +1,12 @@ #ifndef CSM_WORLD_IDCOMPLETIONMANAGER_HPP #define CSM_WORLD_IDCOMPLETIONMANAGER_HPP +#include #include #include -#include "columns.hpp" +#include "columnbase.hpp" #include "universalid.hpp" class QCompleter; @@ -17,21 +18,23 @@ namespace CSMWorld /// \brief Creates and stores all ID completers class IdCompletionManager { - static const std::map sCompleterModelTypes; + static const std::map sCompleterModelTypes; - std::map > mCompleters; + std::map > mCompleters; // Don't allow copying IdCompletionManager(const IdCompletionManager &); IdCompletionManager &operator = (const IdCompletionManager &); - void generateCompleters(CSMWorld::Data &data); + void generateCompleters(Data &data); public: - IdCompletionManager(CSMWorld::Data &data); + static std::vector getDisplayTypes(); - bool hasCompleterFor(CSMWorld::Columns::ColumnId id) const; - boost::shared_ptr getCompleter(CSMWorld::Columns::ColumnId id); + IdCompletionManager(Data &data); + + bool hasCompleterFor(ColumnBase::Display display) const; + boost::shared_ptr getCompleter(ColumnBase::Display display); }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index f485137032..b2f681df17 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -1,6 +1,7 @@ #include "viewmanager.hpp" +#include #include #include @@ -10,6 +11,7 @@ #include "../../model/doc/document.hpp" #include "../../model/world/columns.hpp" #include "../../model/world/universalid.hpp" +#include "../../model/world/idcompletionmanager.hpp" #include "../world/util.hpp" #include "../world/enumdelegate.hpp" @@ -61,38 +63,12 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType, new CSVWorld::IdTypeDelegateFactory()); - // Columns with QLineEdit editor - static const CSMWorld::ColumnBase::Display sIdCompletionColumns[] = + std::vector idCompletionColumns = CSMWorld::IdCompletionManager::getDisplayTypes(); + for (std::vector::const_iterator current = idCompletionColumns.begin(); + current != idCompletionColumns.end(); + ++current) { - CSMWorld::ColumnBase::Display_Cell, - CSMWorld::ColumnBase::Display_Class, - CSMWorld::ColumnBase::Display_Creature, - CSMWorld::ColumnBase::Display_Faction, - CSMWorld::ColumnBase::Display_String, - CSMWorld::ColumnBase::Display_GlobalVariable, - CSMWorld::ColumnBase::Display_Icon, - CSMWorld::ColumnBase::Display_Mesh, - CSMWorld::ColumnBase::Display_Miscellaneous, - CSMWorld::ColumnBase::Display_Music, - CSMWorld::ColumnBase::Display_None, // Inplace editing (Table SubView) creates QLineEdit using Display_None - CSMWorld::ColumnBase::Display_Npc, - CSMWorld::ColumnBase::Display_Race, - CSMWorld::ColumnBase::Display_Referenceable, - CSMWorld::ColumnBase::Display_Region, - CSMWorld::ColumnBase::Display_Script, - CSMWorld::ColumnBase::Display_Skill, - CSMWorld::ColumnBase::Display_Sound, - CSMWorld::ColumnBase::Display_SoundRes, - CSMWorld::ColumnBase::Display_Static, - CSMWorld::ColumnBase::Display_String, - CSMWorld::ColumnBase::Display_Texture, - CSMWorld::ColumnBase::Display_Video, - CSMWorld::ColumnBase::Display_Weapon - }; - - for (std::size_t i = 0; i < sizeof(sIdCompletionColumns) / sizeof(CSMWorld::ColumnBase::Display); ++i) - { - mDelegateFactories->add(sIdCompletionColumns[i], new CSVWorld::IdCompletionDelegateFactory()); + mDelegateFactories->add(*current, new CSVWorld::IdCompletionDelegateFactory()); } struct Mapping diff --git a/apps/opencs/view/world/idcompletiondelegate.cpp b/apps/opencs/view/world/idcompletiondelegate.cpp index 2a1e97f4bd..056026471b 100644 --- a/apps/opencs/view/world/idcompletiondelegate.cpp +++ b/apps/opencs/view/world/idcompletiondelegate.cpp @@ -12,7 +12,7 @@ QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { - return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_None); + return createEditor(parent, option, index, getDisplayTypeFromIndex(index)); } QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent, @@ -20,16 +20,14 @@ QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent, const QModelIndex &index, CSMWorld::ColumnBase::Display display) const { - int columnIdData = index.data(CSMWorld::ColumnBase::Role_ColumnId).toInt(); - CSMWorld::Columns::ColumnId columnId = static_cast(columnIdData); - CSMWorld::IdCompletionManager &completionManager = getDocument().getIdCompletionManager(); - - QWidget *editor = CSVWorld::CommandDelegate::createEditor(parent, option, index, display); - QLineEdit *lineEditor = qobject_cast(editor); - if (lineEditor != NULL && completionManager.hasCompleterFor(columnId)) + if (!index.data(Qt::EditRole).isValid() && !index.data(Qt::DisplayRole).isValid()) { - lineEditor->setCompleter(completionManager.getCompleter(columnId).get()); + return NULL; } + + CSMWorld::IdCompletionManager &completionManager = getDocument().getIdCompletionManager(); + DropLineEdit *editor = new DropLineEdit(parent); + editor->setCompleter(completionManager.getCompleter(display).get()); return editor; } From bd46ddcf47c3a50943a14ea2772dac9e8ef247f8 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 3 Jun 2015 15:51:34 +0300 Subject: [PATCH 29/36] Correct the return type in IdTree::data() for Display_Role --- apps/opencs/model/world/idtree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/idtree.cpp b/apps/opencs/model/world/idtree.cpp index a3dbae4655..1e81d6ac2f 100644 --- a/apps/opencs/model/world/idtree.cpp +++ b/apps/opencs/model/world/idtree.cpp @@ -41,7 +41,7 @@ QVariant CSMWorld::IdTree::data (const QModelIndex & index, int role) const const NestableColumn *parentColumn = mNestedCollection->getNestableColumn(parentAddress.second); if (role == ColumnBase::Role_Display) - return parentColumn->nestedColumn(index.column()).mColumnId; + return parentColumn->nestedColumn(index.column()).mDisplayType; if (role == ColumnBase::Role_ColumnId) return parentColumn->nestedColumn(index.column()).mColumnId; From c40987338d93c6121997630f539ba7e9138540a3 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 4 Jun 2015 23:09:40 +0300 Subject: [PATCH 30/36] Scrollbars don't save their positions between openings --- apps/openmw/mwgui/alchemywindow.cpp | 1 + apps/openmw/mwgui/companionwindow.cpp | 1 + apps/openmw/mwgui/container.cpp | 1 + apps/openmw/mwgui/itemselection.cpp | 1 + apps/openmw/mwgui/itemview.cpp | 5 +++++ apps/openmw/mwgui/itemview.hpp | 2 ++ apps/openmw/mwgui/merchantrepair.cpp | 2 ++ apps/openmw/mwgui/quickkeysmenu.cpp | 1 + apps/openmw/mwgui/recharge.cpp | 2 ++ apps/openmw/mwgui/repair.cpp | 2 ++ apps/openmw/mwgui/settingswindow.cpp | 17 +++++++++++++++++ apps/openmw/mwgui/settingswindow.hpp | 5 +++++ apps/openmw/mwgui/spellcreationdialog.cpp | 1 + apps/openmw/mwgui/spellview.cpp | 4 ++++ apps/openmw/mwgui/spellview.hpp | 2 ++ apps/openmw/mwgui/tradewindow.cpp | 1 + 16 files changed, 48 insertions(+) diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index a54744370c..768ad82e43 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -130,6 +130,7 @@ namespace MWGui mSortModel = new SortFilterItemModel(model); mSortModel->setFilter(SortFilterItemModel::Filter_OnlyIngredients); mItemView->setModel (mSortModel); + mItemView->resetScrollBars(); mNameEdit->setCaption(""); diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp index 4433f9ef8c..69b6aa9f98 100644 --- a/apps/openmw/mwgui/companionwindow.cpp +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -114,6 +114,7 @@ void CompanionWindow::open(const MWWorld::Ptr& npc) mModel = new CompanionItemModel(npc); mSortModel = new SortFilterItemModel(mModel); mItemView->setModel(mSortModel); + mItemView->resetScrollBars(); setTitle(npc.getClass().getName(npc)); } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 1317e1e253..76e9cbb5b6 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -151,6 +151,7 @@ namespace MWGui mSortModel = new SortFilterItemModel(mModel); mItemView->setModel (mSortModel); + mItemView->resetScrollBars(); MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton); diff --git a/apps/openmw/mwgui/itemselection.cpp b/apps/openmw/mwgui/itemselection.cpp index 916f133607..095f392b73 100644 --- a/apps/openmw/mwgui/itemselection.cpp +++ b/apps/openmw/mwgui/itemselection.cpp @@ -39,6 +39,7 @@ namespace MWGui mModel = new InventoryItemModel(container); mSortModel = new SortFilterItemModel(mModel); mItemView->setModel(mSortModel); + mItemView->resetScrollBars(); } void ItemSelectionDialog::setCategory(int category) diff --git a/apps/openmw/mwgui/itemview.cpp b/apps/openmw/mwgui/itemview.cpp index aade232d27..c5320a2be4 100644 --- a/apps/openmw/mwgui/itemview.cpp +++ b/apps/openmw/mwgui/itemview.cpp @@ -128,6 +128,11 @@ void ItemView::update() layoutWidgets(); } +void ItemView::resetScrollBars() +{ + mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); +} + void ItemView::onSelectedItem(MyGUI::Widget *sender) { ItemModel::ModelIndex index = (*sender->getUserData >()).first; diff --git a/apps/openmw/mwgui/itemview.hpp b/apps/openmw/mwgui/itemview.hpp index 9aeba67520..f87a48aa60 100644 --- a/apps/openmw/mwgui/itemview.hpp +++ b/apps/openmw/mwgui/itemview.hpp @@ -30,6 +30,8 @@ namespace MWGui void update(); + void resetScrollBars(); + private: virtual void initialiseOverride(); diff --git a/apps/openmw/mwgui/merchantrepair.cpp b/apps/openmw/mwgui/merchantrepair.cpp index 4407bf9277..862b719d48 100644 --- a/apps/openmw/mwgui/merchantrepair.cpp +++ b/apps/openmw/mwgui/merchantrepair.cpp @@ -114,6 +114,8 @@ void MerchantRepair::onMouseWheel(MyGUI::Widget* _sender, int _rel) void MerchantRepair::open() { center(); + // Reset scrollbars + mList->setViewOffset(MyGUI::IntPoint(0, 0)); } void MerchantRepair::exit() diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 834c156f92..685c7d45c1 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -548,6 +548,7 @@ namespace MWGui WindowModal::open(); mMagicList->setModel(new SpellModel(MWBase::Environment::get().getWorld()->getPlayerPtr())); + mMagicList->resetScrollbars(); } void MagicSelectionDialog::onModelIndexSelected(SpellModel::ModelIndex index) diff --git a/apps/openmw/mwgui/recharge.cpp b/apps/openmw/mwgui/recharge.cpp index a0e5991b46..b7280565b7 100644 --- a/apps/openmw/mwgui/recharge.cpp +++ b/apps/openmw/mwgui/recharge.cpp @@ -44,6 +44,8 @@ Recharge::Recharge() void Recharge::open() { center(); + // Reset scrollbars + mView->setViewOffset(MyGUI::IntPoint(0, 0)); } void Recharge::exit() diff --git a/apps/openmw/mwgui/repair.cpp b/apps/openmw/mwgui/repair.cpp index 9f26923d44..534226aebd 100644 --- a/apps/openmw/mwgui/repair.cpp +++ b/apps/openmw/mwgui/repair.cpp @@ -36,6 +36,8 @@ Repair::Repair() void Repair::open() { center(); + // Reset scrollbars + mRepairView->setViewOffset(MyGUI::IntPoint(0, 0)); } void Repair::exit() diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index d895a28ea7..6991bb2946 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -170,6 +171,7 @@ namespace MWGui setTitle("#{sOptions}"); + getWidget(mSettingsTab, "SettingsTab"); getWidget(mOkButton, "OkButton"); getWidget(mResolutionList, "ResolutionList"); getWidget(mFullscreenButton, "FullscreenButton"); @@ -208,6 +210,7 @@ namespace MWGui mMainWidget->castType()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SettingsWindow::onWindowResize); + mSettingsTab->eventTabChangeSelect += MyGUI::newDelegate(this, &SettingsWindow::onTabChanged); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mShaderModeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShaderModeToggled); mTextureFilteringButton->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringChanged); @@ -275,6 +278,11 @@ namespace MWGui mControllerSwitch->setStateSelected(false); } + void SettingsWindow::onTabChanged(MyGUI::TabControl* /*_sender*/, size_t /*index*/) + { + resetScrollbars(); + } + void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) { exit(); @@ -480,6 +488,7 @@ namespace MWGui mKeyboardSwitch->setStateSelected(true); mControllerSwitch->setStateSelected(false); updateControlsBox(); + resetScrollbars(); } void SettingsWindow::onControllerSwitchClicked(MyGUI::Widget* _sender) @@ -490,6 +499,7 @@ namespace MWGui mKeyboardSwitch->setStateSelected(false); mControllerSwitch->setStateSelected(true); updateControlsBox(); + resetScrollbars(); } void SettingsWindow::updateControlsBox() @@ -584,6 +594,7 @@ namespace MWGui void SettingsWindow::open() { updateControlsBox (); + resetScrollbars(); } void SettingsWindow::exit() @@ -595,4 +606,10 @@ namespace MWGui { updateControlsBox(); } + + void SettingsWindow::resetScrollbars() + { + mResolutionList->setScrollPosition(0); + mControlsBox->setViewOffset(MyGUI::IntPoint(0, 0)); + } } diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 1b970b8de5..8910960b24 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -22,6 +22,7 @@ namespace MWGui void updateControlsBox(); protected: + MyGUI::TabControl* mSettingsTab; MyGUI::Button* mOkButton; // graphics @@ -50,6 +51,7 @@ namespace MWGui MyGUI::Button* mControllerSwitch; bool mKeyboardMode; //if true, setting up the keyboard. Otherwise, it's controller + void onTabChanged(MyGUI::TabControl* _sender, size_t index); void onOkButtonClicked(MyGUI::Widget* _sender); void onFpsToggled(MyGUI::Widget* _sender); void onTextureFilteringChanged(MyGUI::ComboBox* _sender, size_t pos); @@ -74,6 +76,9 @@ namespace MWGui void apply(); void configureWidgets(MyGUI::Widget* widget); + + private: + void resetScrollbars(); }; } diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 1c670838f4..a492ea7aaf 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -551,6 +551,7 @@ namespace MWGui ++i; } mAvailableEffectsList->adjustSize (); + mAvailableEffectsList->scrollToTop(); for (std::vector::const_iterator it = knownEffects.begin(); it != knownEffects.end(); ++it) { diff --git a/apps/openmw/mwgui/spellview.cpp b/apps/openmw/mwgui/spellview.cpp index 6d86b4a23a..af6ff00a53 100644 --- a/apps/openmw/mwgui/spellview.cpp +++ b/apps/openmw/mwgui/spellview.cpp @@ -311,4 +311,8 @@ namespace MWGui mScrollView->setViewOffset(MyGUI::IntPoint(0, static_cast(mScrollView->getViewOffset().top + _rel*0.3f))); } + void SpellView::resetScrollbars() + { + mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); + } } diff --git a/apps/openmw/mwgui/spellview.hpp b/apps/openmw/mwgui/spellview.hpp index 7af1bda7a7..0f0b8a7d25 100644 --- a/apps/openmw/mwgui/spellview.hpp +++ b/apps/openmw/mwgui/spellview.hpp @@ -51,6 +51,8 @@ namespace MWGui virtual void setSize(const MyGUI::IntSize& _value); virtual void setCoord(const MyGUI::IntCoord& _value); + void resetScrollbars(); + private: MyGUI::ScrollView* mScrollView; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index aecfce98d0..bdcf28bf20 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -136,6 +136,7 @@ namespace MWGui mTradeModel = new TradeItemModel(new ContainerItemModel(itemSources, worldItems), mPtr); mSortModel = new SortFilterItemModel(mTradeModel); mItemView->setModel (mSortModel); + mItemView->resetScrollBars(); updateLabels(); From 5c37079f0c06d1837da2b3d6e3f3763d709550dc Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 5 Jun 2015 12:19:21 +1000 Subject: [PATCH 31/36] Include only the columns that are visible for sorting. Should resolve Bug #2611. --- apps/opencs/model/world/idtableproxymodel.cpp | 12 ++++++++++++ apps/opencs/model/world/idtableproxymodel.hpp | 6 ++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/idtableproxymodel.cpp b/apps/opencs/model/world/idtableproxymodel.cpp index 987d274620..3697b055fe 100644 --- a/apps/opencs/model/world/idtableproxymodel.cpp +++ b/apps/opencs/model/world/idtableproxymodel.cpp @@ -21,6 +21,18 @@ void CSMWorld::IdTableProxyModel::updateColumnMap() } } +bool CSMWorld::IdTableProxyModel::filterAcceptsColumn (int sourceColumn, const QModelIndex& sourceParent) + const +{ + int flags = + sourceModel()->headerData (sourceColumn, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); + + if (flags & CSMWorld::ColumnBase::Flag_Table) + return true; + else + return false; +} + bool CSMWorld::IdTableProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const { diff --git a/apps/opencs/model/world/idtableproxymodel.hpp b/apps/opencs/model/world/idtableproxymodel.hpp index 8683c2b9e5..89480f2881 100644 --- a/apps/opencs/model/world/idtableproxymodel.hpp +++ b/apps/opencs/model/world/idtableproxymodel.hpp @@ -24,8 +24,6 @@ namespace CSMWorld void updateColumnMap(); - bool filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const; - public: IdTableProxyModel (QObject *parent = 0); @@ -39,6 +37,10 @@ namespace CSMWorld protected: bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + + virtual bool filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const; + + virtual bool filterAcceptsColumn (int sourceColumn, const QModelIndex& sourceParent) const; }; } From 15fe5d88e2b3c7d172a28bd453b3e0d5f89295aa Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 6 Jun 2015 20:35:55 +1000 Subject: [PATCH 32/36] Allow comments (lines starting with # character) and blank lines in openmw.cfg. Should resolve Feature #2535. - controlled via a checkbox in launcher settings --- apps/launcher/maindialog.cpp | 21 ++++- apps/launcher/settingspage.cpp | 8 ++ components/config/gamesettings.cpp | 128 +++++++++++++++++++++++++++++ components/config/gamesettings.hpp | 2 + files/ui/settingspage.ui | 10 +++ 5 files changed, 166 insertions(+), 3 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index fd36993bfb..27d37dbf03 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -490,7 +490,16 @@ bool Launcher::MainDialog::writeSettings() // Game settings QFile file(userPath + QString("openmw.cfg")); - if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { + QIODevice::OpenMode mode(0); + bool keepComments = mLauncherSettings.value(QString("Settings/keep-comments"), QString("true")) + == QLatin1String("true"); + + if (keepComments) + mode = QIODevice::ReadWrite | QIODevice::Text; + else + mode = QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate; + + if (!file.open(mode)) { // File cannot be opened or created QMessageBox msgBox; msgBox.setWindowTitle(tr("Error writing OpenMW configuration file")); @@ -504,9 +513,15 @@ bool Launcher::MainDialog::writeSettings() } QTextStream stream(&file); - stream.setCodec(QTextCodec::codecForName("UTF-8")); - mGameSettings.writeFile(stream); + if (keepComments) + mGameSettings.writeFileWithComments(file); + else + { + stream.setCodec(QTextCodec::codecForName("UTF-8")); + mGameSettings.writeFile(stream); + } + file.close(); // Graphics settings diff --git a/apps/launcher/settingspage.cpp b/apps/launcher/settingspage.cpp index 843b513914..bc8ffe6180 100644 --- a/apps/launcher/settingspage.cpp +++ b/apps/launcher/settingspage.cpp @@ -260,6 +260,10 @@ void Launcher::SettingsPage::saveSettings() } else { mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1252")); } + + QString keepComments(saveCommentsCheckBox->isChecked() ? "true" : "false"); + + mLauncherSettings.setValue(QLatin1String("Settings/keep-comments"), keepComments); } bool Launcher::SettingsPage::loadSettings() @@ -271,5 +275,9 @@ bool Launcher::SettingsPage::loadSettings() if (index != -1) languageComboBox->setCurrentIndex(index); + QString keepComments(mLauncherSettings.value(QLatin1String("Settings/keep-comments"))); + + saveCommentsCheckBox->setChecked(keepComments == "true"); + return true; } diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index 0481235c78..51c7883ad2 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -1,6 +1,7 @@ #include "gamesettings.hpp" #include "launchersettings.hpp" +#include #include #include #include @@ -173,6 +174,133 @@ bool Config::GameSettings::writeFile(QTextStream &stream) return true; } +// Policy: +// +// - Always ignore a line beginning with '#' or empty lines +// +// - If a line in file exists with matching key and first part of value (before ',', +// '\n', etc) also matches, then replace the line with that of mUserSettings. +// - else remove line (maybe replace the line with '#' in front instead?) +// +// - If there is no corresponding line in file, add at the end +// +bool Config::GameSettings::writeFileWithComments(QFile &file) +{ + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + // slurp + std::vector fileCopy; + QString line = stream.readLine(); + while (!line.isNull()) + { + fileCopy.push_back(line); + line = stream.readLine(); + } + stream.seek(0); + + // empty file, no comments to keep + if (fileCopy.empty()) + return writeFile(stream); + + // Temp copy of settings to save, but with the keys appended with the first part of the value + // + // ATTENTION! + // + // A hack to avoid looping through each line, makes use of the fact that fallbacks values + // are comma separated. + QMap userSettingsCopy; + QRegExp settingRegex("^([^=]+)\\s*=\\s*([^,]+)(.*)$"); + QString settingLine; + QMap::const_iterator settingsIter = mUserSettings.begin(); + for (; settingsIter != mUserSettings.end(); ++settingsIter) + { + settingLine = settingsIter.key()+"="+settingsIter.value(); + if (settingRegex.indexIn(settingLine) != -1) + { + userSettingsCopy[settingRegex.cap(1)+"="+settingRegex.cap(2)] = + (settingRegex.captureCount() < 3) ? "" : settingRegex.cap(3); + } + } + + QString keyVal; + for (std::vector::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) + { + // skip empty or comment lines + if ((*iter).isEmpty() || (*iter).startsWith("#")) + continue; + + // look for a key in the line + if (settingRegex.indexIn(*iter) == -1 || settingRegex.captureCount() < 2) + { + // no key or first part of value found in line, replace with a null string which + // will be remved later + *iter = QString(); + continue; + } + + // look for a matching key in user settings + keyVal = settingRegex.cap(1)+"="+settingRegex.cap(2); + QMap::iterator it = userSettingsCopy.find(keyVal); + if (it == userSettingsCopy.end()) + { + // no such key+valStart, replace with a null string which will be remved later + *iter = QString(); + } + else + { + *iter = QString(it.key()+it.value()); + userSettingsCopy.erase(it); + } + } + + // write the new config file + QString key; + QString value; + for (std::vector::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) + { + if ((*iter).isNull()) + continue; + + if ((*iter).isEmpty() || (*iter).startsWith("#")) + stream << *iter << "\n"; + + if (settingRegex.indexIn(*iter) == -1 || settingRegex.captureCount() < 2) + continue; + + // Quote paths with spaces + key = settingRegex.cap(1); + value = settingRegex.cap(2)+settingRegex.cap(3); + if (key == QLatin1String("data") + || key == QLatin1String("data-local") + || key == QLatin1String("resources")) + { + if (value.contains(QChar(' '))) + { + value.remove(QChar('\"')); // Remove quotes + + stream << key << "=\"" << value << "\"\n"; + continue; + } + } + stream << key << "=" << value << "\n"; + } + + if (!userSettingsCopy.empty()) + { + stream << "# new entries" << "\n"; + QMap::const_iterator it = userSettingsCopy.begin(); + for (; it != userSettingsCopy.end(); ++it) + { + stream << it.key() << it.value() << "\n"; + } + } + + file.resize(file.pos()); + + return true; +} + bool Config::GameSettings::hasMaster() { bool result = false; diff --git a/components/config/gamesettings.hpp b/components/config/gamesettings.hpp index cc5033f351..35614113f4 100644 --- a/components/config/gamesettings.hpp +++ b/components/config/gamesettings.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -66,6 +67,7 @@ namespace Config bool readUserFile(QTextStream &stream); bool writeFile(QTextStream &stream); + bool writeFileWithComments(QFile &file); void setContentList(const QStringList& fileNames); QStringList getContentList() const; diff --git a/files/ui/settingspage.ui b/files/ui/settingspage.ui index 7f5e4a7de8..f38ba764c3 100644 --- a/files/ui/settingspage.ui +++ b/files/ui/settingspage.ui @@ -40,6 +40,16 @@ + + + + Keep comments in openmw.cfg + + + false + + + From d63b01dde3ebe251d9dafd157ca1104bcf413db9 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 6 Jun 2015 15:41:25 +0300 Subject: [PATCH 33/36] Checkboxes in the table view use a combobox editor --- apps/opencs/view/world/util.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 3be875ffd7..e1d165a24f 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -152,7 +152,17 @@ void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemMode QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { - return createEditor (parent, option, index, getDisplayTypeFromIndex(index)); + CSMWorld::ColumnBase::Display display = getDisplayTypeFromIndex(index); + + // This createEditor() method is called implicitly from tables. + // For boolean values in tables use the default editor (combobox). + // Checkboxes is looking ugly in the table view. + // TODO: Find a better solution? + if (display == CSMWorld::ColumnBase::Display_Boolean) + { + return QStyledItemDelegate::createEditor(parent, option, index); + } + return createEditor (parent, option, index, display); } QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option, From 4902c6679210dee8b5158d05d99b072c2f06a494 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 7 Jun 2015 07:21:15 +1000 Subject: [PATCH 34/36] Allow space characters in front of comments. --- components/config/gamesettings.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index 51c7883ad2..1215f08509 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -180,7 +180,7 @@ bool Config::GameSettings::writeFile(QTextStream &stream) // // - If a line in file exists with matching key and first part of value (before ',', // '\n', etc) also matches, then replace the line with that of mUserSettings. -// - else remove line (maybe replace the line with '#' in front instead?) +// - else remove line (TODO: maybe replace the line with '#' in front instead?) // // - If there is no corresponding line in file, add at the end // @@ -224,10 +224,10 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) } QString keyVal; - for (std::vector::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) + for (std::vector::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) { // skip empty or comment lines - if ((*iter).isEmpty() || (*iter).startsWith("#")) + if ((*iter).isEmpty() || (*iter).contains(QRegExp("^\\s*#"))) continue; // look for a key in the line @@ -257,12 +257,14 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) // write the new config file QString key; QString value; - for (std::vector::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) + for (std::vector::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) { if ((*iter).isNull()) continue; - if ((*iter).isEmpty() || (*iter).startsWith("#")) + // Below is based on readFile() code, if that changes corresponding change may be + // required (for example duplicates may be inserted if the rules don't match) + if ((*iter).isEmpty() || (*iter).contains(QRegExp("^\\s*#"))) stream << *iter << "\n"; if (settingRegex.indexIn(*iter) == -1 || settingRegex.captureCount() < 2) From a439f49c4db32a340826ae9b77c940ca59e79e5f Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 7 Jun 2015 07:38:52 +1000 Subject: [PATCH 35/36] Fix loop where there was a potential for double entry. --- components/config/gamesettings.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index 1215f08509..2b3a8ba4bf 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -265,7 +265,10 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) // Below is based on readFile() code, if that changes corresponding change may be // required (for example duplicates may be inserted if the rules don't match) if ((*iter).isEmpty() || (*iter).contains(QRegExp("^\\s*#"))) + { stream << *iter << "\n"; + continue; + } if (settingRegex.indexIn(*iter) == -1 || settingRegex.captureCount() < 2) continue; From d3b7cf44d391ba9624f28070e68784352e6f514d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 7 Jun 2015 13:29:45 +1000 Subject: [PATCH 36/36] Remove user preference setting option. --- apps/launcher/maindialog.cpp | 22 +++------------------- apps/launcher/settingspage.cpp | 8 -------- files/ui/settingspage.ui | 10 ---------- 3 files changed, 3 insertions(+), 37 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 27d37dbf03..2f7a9db332 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -490,16 +490,7 @@ bool Launcher::MainDialog::writeSettings() // Game settings QFile file(userPath + QString("openmw.cfg")); - QIODevice::OpenMode mode(0); - bool keepComments = mLauncherSettings.value(QString("Settings/keep-comments"), QString("true")) - == QLatin1String("true"); - - if (keepComments) - mode = QIODevice::ReadWrite | QIODevice::Text; - else - mode = QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate; - - if (!file.open(mode)) { + if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { // File cannot be opened or created QMessageBox msgBox; msgBox.setWindowTitle(tr("Error writing OpenMW configuration file")); @@ -512,16 +503,8 @@ bool Launcher::MainDialog::writeSettings() return false; } - QTextStream stream(&file); - - if (keepComments) - mGameSettings.writeFileWithComments(file); - else - { - stream.setCodec(QTextCodec::codecForName("UTF-8")); - mGameSettings.writeFile(stream); - } + mGameSettings.writeFileWithComments(file); file.close(); // Graphics settings @@ -540,6 +523,7 @@ bool Launcher::MainDialog::writeSettings() return false; } + QTextStream stream(&file); stream.setDevice(&file); stream.setCodec(QTextCodec::codecForName("UTF-8")); diff --git a/apps/launcher/settingspage.cpp b/apps/launcher/settingspage.cpp index bc8ffe6180..843b513914 100644 --- a/apps/launcher/settingspage.cpp +++ b/apps/launcher/settingspage.cpp @@ -260,10 +260,6 @@ void Launcher::SettingsPage::saveSettings() } else { mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1252")); } - - QString keepComments(saveCommentsCheckBox->isChecked() ? "true" : "false"); - - mLauncherSettings.setValue(QLatin1String("Settings/keep-comments"), keepComments); } bool Launcher::SettingsPage::loadSettings() @@ -275,9 +271,5 @@ bool Launcher::SettingsPage::loadSettings() if (index != -1) languageComboBox->setCurrentIndex(index); - QString keepComments(mLauncherSettings.value(QLatin1String("Settings/keep-comments"))); - - saveCommentsCheckBox->setChecked(keepComments == "true"); - return true; } diff --git a/files/ui/settingspage.ui b/files/ui/settingspage.ui index f38ba764c3..7f5e4a7de8 100644 --- a/files/ui/settingspage.ui +++ b/files/ui/settingspage.ui @@ -40,16 +40,6 @@ - - - - Keep comments in openmw.cfg - - - false - - -