From ce421b230b1938398a9559fdcc89c28c01a4a615 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 29 May 2015 14:07:41 +1000 Subject: [PATCH 01/57] Move scrollbar to newly opened subview. Should resolve Bug #2576. --- apps/opencs/view/doc/view.cpp | 21 +++++++++++++++------ apps/opencs/view/doc/view.hpp | 2 ++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 5e3df27399..c100e84e61 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -519,6 +519,10 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin } } + if (mScroll) + QObject::connect(mScroll->horizontalScrollBar(), + SIGNAL(rangeChanged(int,int)), this, SLOT(moveScrollBarToEnd(int,int))); + // User setting for limiting the number of sub views per top level view. // Automatically open a new top level view if this number is exceeded // @@ -590,12 +594,6 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin mSubViewWindow.setMinimumWidth(mSubViewWindow.width()+minWidth); move(0, y()); } - - // Make the new subview visible, setFocus() or raise() don't seem to work - // On Ubuntu the scrollbar does not go right to the end, even if using - // mScroll->horizontalScrollBar()->setValue(mScroll->horizontalScrollBar()->maximum()); - if (mSubViewWindow.width() > rect.width()) - mScroll->horizontalScrollBar()->setValue(mSubViewWindow.width()); } mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view); @@ -618,6 +616,17 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin view->useHint (hint); } +void CSVDoc::View::moveScrollBarToEnd(int min, int max) +{ + if (mScroll) + { + mScroll->horizontalScrollBar()->setValue(max); + + QObject::disconnect(mScroll->horizontalScrollBar(), + SIGNAL(rangeChanged(int,int)), this, SLOT(moveScrollBarToEnd(int,int))); + } +} + void CSVDoc::View::newView() { mViewManager.addView (mDocument); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 1d44cb7f5a..814dabc6b5 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -233,6 +233,8 @@ namespace CSVDoc void stop(); void closeRequest (SubView *subView); + + void moveScrollBarToEnd(int min, int max); }; } From d7fb49725569e6fed93672f86036e6037cd112b8 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Mon, 8 Jun 2015 21:33:23 +0300 Subject: [PATCH 02/57] Color values are displayed as colored rectangles in tables --- apps/opencs/CMakeLists.txt | 1 + apps/opencs/view/doc/viewmanager.cpp | 4 ++ .../opencs/view/world/colorpickerdelegate.cpp | 50 +++++++++++++++++++ .../opencs/view/world/colorpickerdelegate.hpp | 45 +++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 apps/opencs/view/world/colorpickerdelegate.cpp create mode 100644 apps/opencs/view/world/colorpickerdelegate.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 37d13223a7..4a5a64f604 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -70,6 +70,7 @@ opencs_units (view/world opencs_units_noqt (view/world subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate scripthighlighter idvalidator dialoguecreator physicssystem idcompletiondelegate + colorpickerdelegate ) opencs_units (view/widget diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index b2f681df17..e5bb7fe811 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -19,6 +19,7 @@ #include "../world/recordstatusdelegate.hpp" #include "../world/idtypedelegate.hpp" #include "../world/idcompletiondelegate.hpp" +#include "../world/colorpickerdelegate.hpp" #include "../../model/settings/usersettings.hpp" @@ -63,6 +64,9 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType, new CSVWorld::IdTypeDelegateFactory()); + mDelegateFactories->add (CSMWorld::ColumnBase::Display_Colour, + new CSVWorld::ColorPickerDelegateFactory()); + std::vector idCompletionColumns = CSMWorld::IdCompletionManager::getDisplayTypes(); for (std::vector::const_iterator current = idCompletionColumns.begin(); current != idCompletionColumns.end(); diff --git a/apps/opencs/view/world/colorpickerdelegate.cpp b/apps/opencs/view/world/colorpickerdelegate.cpp new file mode 100644 index 0000000000..aa9f2e9371 --- /dev/null +++ b/apps/opencs/view/world/colorpickerdelegate.cpp @@ -0,0 +1,50 @@ +#include "colorpickerdelegate.hpp" + +#include +#include + +CSVWorld::ColorPickerDelegate::ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document& document, + QObject *parent) + : CommandDelegate(dispatcher, document, parent) +{} + +QWidget *CSVWorld::ColorPickerDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + return createEditor(parent, option, index, getDisplayTypeFromIndex(index)); +} + +QWidget *CSVWorld::ColorPickerDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index, + CSMWorld::ColumnBase::Display display) const +{ + if (display != CSMWorld::ColumnBase::Display_Colour) + { + throw std::logic_error("Wrong column for ColorPickerDelegate"); + } + + return CommandDelegate::createEditor(parent, option, index, display); +} + +void CSVWorld::ColorPickerDelegate::paint(QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + QColor color = index.data().value(); + QRect rect(option.rect.x() + option.rect.width() / 4, + option.rect.y() + option.rect.height() / 4, + option.rect.width() / 2, + option.rect.height() / 2); + + painter->fillRect(rect, color); +} + +CSVWorld::CommandDelegate *CSVWorld::ColorPickerDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document &document, + QObject *parent) const +{ + return new ColorPickerDelegate(dispatcher, document, parent); +} \ No newline at end of file diff --git a/apps/opencs/view/world/colorpickerdelegate.hpp b/apps/opencs/view/world/colorpickerdelegate.hpp new file mode 100644 index 0000000000..e93e0e87de --- /dev/null +++ b/apps/opencs/view/world/colorpickerdelegate.hpp @@ -0,0 +1,45 @@ +#ifndef CSV_WORLD_COLORPICKERDELEGATE_HPP +#define CSV_WORLD_COLORPICKERDELEGATE_HPP + +#include "util.hpp" + +namespace CSVWorld +{ + class ColorPickerDelegate : public CommandDelegate + { + public: + ColorPickerDelegate(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; + + virtual void paint(QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const;/* + + virtual void setEditorData(QWidget *editor, const QModelIndex &index) const; + + virtual void setModelData(QWidget *editor, + QAbstractItemModel &model, + const QModelIndex &index) const;*/ + }; + + class ColorPickerDelegateFactory : 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 From ef88b28c26c8031ba29a4f81a44eb6a4391f362c Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 9 Jun 2015 15:20:50 +0300 Subject: [PATCH 03/57] Create a custom item editor for color columns --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/widget/coloreditbutton.cpp | 42 +++++++++++++++++++ apps/opencs/view/widget/coloreditbutton.hpp | 30 +++++++++++++ .../opencs/view/world/colorpickerdelegate.cpp | 26 ++++++++---- .../opencs/view/world/colorpickerdelegate.hpp | 17 ++++---- 5 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 apps/opencs/view/widget/coloreditbutton.cpp create mode 100644 apps/opencs/view/widget/coloreditbutton.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 4a5a64f604..f8f3ea0360 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -75,7 +75,7 @@ opencs_units_noqt (view/world opencs_units (view/widget scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton - scenetooltoggle2 completerpopup + scenetooltoggle2 completerpopup coloreditbutton ) opencs_units (view/render diff --git a/apps/opencs/view/widget/coloreditbutton.cpp b/apps/opencs/view/widget/coloreditbutton.cpp new file mode 100644 index 0000000000..4960d1ef1b --- /dev/null +++ b/apps/opencs/view/widget/coloreditbutton.cpp @@ -0,0 +1,42 @@ +#include "coloreditbutton.hpp" + +#include +#include +#include + +CSVWidget::ColorEditButton::ColorEditButton(const QColor &color, + const QSize &coloredRectSize, + QWidget *parent) + : QPushButton(parent), + mColor(color), + mColoredRectSize(coloredRectSize) + +{} + +void CSVWidget::ColorEditButton::paintEvent(QPaintEvent *event) +{ + QPushButton::paintEvent(event); + + QRect buttonRect = rect(); + QRect coloredRect(buttonRect.x() + (buttonRect.width() - mColoredRectSize.width()) / 2, + buttonRect.y() + (buttonRect.height() - mColoredRectSize.height()) / 2, + mColoredRectSize.width(), + mColoredRectSize.height()); + QPainter painter(this); + painter.fillRect(coloredRect, mColor); +} + +QColor CSVWidget::ColorEditButton::color() const +{ + return mColor; +} + +void CSVWidget::ColorEditButton::setColor(const QColor &color) +{ + mColor = color; +} + +void CSVWidget::ColorEditButton::setColoredRectSize(const QSize &size) +{ + mColoredRectSize = size; +} \ No newline at end of file diff --git a/apps/opencs/view/widget/coloreditbutton.hpp b/apps/opencs/view/widget/coloreditbutton.hpp new file mode 100644 index 0000000000..e1a8cce9da --- /dev/null +++ b/apps/opencs/view/widget/coloreditbutton.hpp @@ -0,0 +1,30 @@ +#ifndef CSV_WIDGET_COLOREDITBUTTON_HPP +#define CSV_WIDGET_COLOREDITBUTTON_HPP + +#include + +class QColor; +class QSize; + +namespace CSVWidget +{ + class ColorEditButton : public QPushButton + { + QColor mColor; + QSize mColoredRectSize; + + public: + ColorEditButton(const QColor &color, + const QSize &coloredRectSize, + QWidget *parent = 0); + + QColor color() const; + void setColor(const QColor &color); + void setColoredRectSize(const QSize &size); + + protected: + void paintEvent(QPaintEvent *event); + }; +} + +#endif diff --git a/apps/opencs/view/world/colorpickerdelegate.cpp b/apps/opencs/view/world/colorpickerdelegate.cpp index aa9f2e9371..c74a1828f3 100644 --- a/apps/opencs/view/world/colorpickerdelegate.cpp +++ b/apps/opencs/view/world/colorpickerdelegate.cpp @@ -3,6 +3,8 @@ #include #include +#include "../widget/coloreditbutton.hpp" + CSVWorld::ColorPickerDelegate::ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) @@ -26,20 +28,24 @@ QWidget *CSVWorld::ColorPickerDelegate::createEditor(QWidget *parent, throw std::logic_error("Wrong column for ColorPickerDelegate"); } - return CommandDelegate::createEditor(parent, option, index, display); + return new CSVWidget::ColorEditButton(index.data().value(), + getColoredRect(option).size(), + parent); } void CSVWorld::ColorPickerDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - QColor color = index.data().value(); - QRect rect(option.rect.x() + option.rect.width() / 4, - option.rect.y() + option.rect.height() / 4, - option.rect.width() / 2, - option.rect.height() / 2); - - painter->fillRect(rect, color); + painter->fillRect(getColoredRect(option), index.data().value()); +} + +QRect CSVWorld::ColorPickerDelegate::getColoredRect(const QStyleOptionViewItem &option) const +{ + return QRect(option.rect.x() + option.rect.width() / 4, + option.rect.y() + option.rect.height() / 4, + option.rect.width() / 2, + option.rect.height() / 2); } CSVWorld::CommandDelegate *CSVWorld::ColorPickerDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher, @@ -47,4 +53,6 @@ CSVWorld::CommandDelegate *CSVWorld::ColorPickerDelegateFactory::makeDelegate(CS QObject *parent) const { return new ColorPickerDelegate(dispatcher, document, parent); -} \ No newline at end of file +} + + diff --git a/apps/opencs/view/world/colorpickerdelegate.hpp b/apps/opencs/view/world/colorpickerdelegate.hpp index e93e0e87de..147c2f4243 100644 --- a/apps/opencs/view/world/colorpickerdelegate.hpp +++ b/apps/opencs/view/world/colorpickerdelegate.hpp @@ -3,10 +3,19 @@ #include "util.hpp" +class QRect; + +namespace CSVWidget +{ + class ColorEditButton; +} + namespace CSVWorld { class ColorPickerDelegate : public CommandDelegate { + QRect getColoredRect(const QStyleOptionViewItem &option) const; + public: ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, @@ -23,13 +32,7 @@ namespace CSVWorld virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, - const QModelIndex &index) const;/* - - virtual void setEditorData(QWidget *editor, const QModelIndex &index) const; - - virtual void setModelData(QWidget *editor, - QAbstractItemModel &model, - const QModelIndex &index) const;*/ + const QModelIndex &index) const; }; class ColorPickerDelegateFactory : public CommandDelegateFactory From 8e8da724f5dd7bddc5dccee3c081664335cb60c1 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 10 Jun 2015 08:23:38 +1000 Subject: [PATCH 04/57] Remove unnecessary comment entry in the config file. --- components/config/gamesettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index 2b3a8ba4bf..9af6c97143 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -291,9 +291,9 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) stream << key << "=" << value << "\n"; } + // new entries if (!userSettingsCopy.empty()) { - stream << "# new entries" << "\n"; QMap::const_iterator it = userSettingsCopy.begin(); for (; it != userSettingsCopy.end(); ++it) { From 6d7e6cd30c3e6a8b20a59f657e90ac91506eccab Mon Sep 17 00:00:00 2001 From: dteviot Date: Thu, 11 Jun 2015 18:28:31 +1200 Subject: [PATCH 05/57] AiTravel logic merged into AiPackage. --- apps/openmw/mwmechanics/aipackage.cpp | 9 ++++- apps/openmw/mwmechanics/aipackage.hpp | 4 ++ apps/openmw/mwmechanics/aitravel.cpp | 55 ++++++--------------------- apps/openmw/mwmechanics/aitravel.hpp | 3 ++ 4 files changed, 25 insertions(+), 46 deletions(-) diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 52a975320d..802a7723ea 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -30,9 +30,9 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po ESM::Position pos = actor.getRefData().getPosition(); //position of the actor /// Stops the actor when it gets too close to a unloaded cell + const ESM::Cell *cell = actor.getCell()->getCell(); { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - const ESM::Cell *cell = actor.getCell()->getCell(); Movement &movement = actor.getClass().getMovementSettings(actor); //Ensure pursuer doesn't leave loaded cells @@ -67,7 +67,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po //*********************** if(mTimer > 0.25) { - if(distance(mPrevDest, dest) > 10) { //Only rebuild path if it's moved + if (doesPathNeedRecalc(dest, cell)) { //Only rebuild path if it's moved mPathFinder.buildPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved mPrevDest = dest; } @@ -123,3 +123,8 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po return false; } + +bool MWMechanics::AiPackage::doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell) +{ + return distance(mPrevDest, dest) > 10; +} \ No newline at end of file diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 179ae440bb..0370072a41 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -4,6 +4,8 @@ #include "pathfinding.hpp" #include +#include "../mwworld/cellstore.hpp" + #include "obstacle.hpp" #include "aistate.hpp" @@ -71,6 +73,8 @@ namespace MWMechanics /** \return If the actor has arrived at his destination **/ bool pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration); + virtual bool doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell); + // TODO: all this does not belong here, move into temporary storage PathFinder mPathFinder; ObstacleCheck mObstacleCheck; diff --git a/apps/openmw/mwmechanics/aitravel.cpp b/apps/openmw/mwmechanics/aitravel.cpp index 2824e2c6ce..4f4d4c79ff 100644 --- a/apps/openmw/mwmechanics/aitravel.cpp +++ b/apps/openmw/mwmechanics/aitravel.cpp @@ -51,64 +51,31 @@ namespace MWMechanics bool AiTravel::execute (const MWWorld::Ptr& actor, AiState& state, float duration) { - MWBase::World *world = MWBase::Environment::get().getWorld(); ESM::Position pos = actor.getRefData().getPosition(); - Movement &movement = actor.getClass().getMovementSettings(actor); - const ESM::Cell *cell = actor.getCell()->getCell(); actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, false); - actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing); - MWWorld::Ptr player = world->getPlayerPtr(); - if(cell->mData.mX != player.getCell()->getCell()->mData.mX) - { - int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) > - sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } - if(cell->mData.mY != player.getCell()->getCell()->mData.mY) - { - int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) > - sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } - if (!isWithinMaxRange(Ogre::Vector3(mX, mY, mZ), Ogre::Vector3(pos.pos))) return false; + if (pathTo(actor, ESM::Pathgrid::Point(static_cast(mX), static_cast(mY), static_cast(mZ)), duration)) + { + actor.getClass().getMovementSettings(actor).mPosition[1] = 0; + return true; + } + return false; + } + + bool AiTravel::doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell) + { bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; - if(!mPathFinder.isPathConstructed() || cellChange) + if (!mPathFinder.isPathConstructed() || cellChange) { mCellX = cell->mData.mX; mCellY = cell->mData.mY; - - ESM::Pathgrid::Point dest(static_cast(mX), static_cast(mY), static_cast(mZ)); - - ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos)); - - mPathFinder.buildPath(start, dest, actor.getCell(), true); - } - - if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1])) - { - movement.mPosition[1] = 0; return true; } - - zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); - movement.mPosition[1] = 1; - return false; } diff --git a/apps/openmw/mwmechanics/aitravel.hpp b/apps/openmw/mwmechanics/aitravel.hpp index c2732e3aa4..a5a4577e60 100644 --- a/apps/openmw/mwmechanics/aitravel.hpp +++ b/apps/openmw/mwmechanics/aitravel.hpp @@ -34,6 +34,9 @@ namespace MWMechanics virtual int getTypeId() const; + protected: + virtual bool doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell); + private: float mX; float mY; From cb8ca2f03a751373b81e15f75b05b691bb2dee58 Mon Sep 17 00:00:00 2001 From: dteviot Date: Thu, 11 Jun 2015 18:31:35 +1200 Subject: [PATCH 06/57] Moved logic for building a Sync'ed path from AiCombat to PathFinding. Is now used by AiFollow, which should fix "running in circles" bug caused when recalc a path and closest way point is the one NPC has just passed. --- apps/openmw/mwmechanics/aicombat.cpp | 54 ++++++++++--------------- apps/openmw/mwmechanics/aicombat.hpp | 3 ++ apps/openmw/mwmechanics/aipackage.cpp | 2 +- apps/openmw/mwmechanics/pathfinding.cpp | 38 +++++++++++------ apps/openmw/mwmechanics/pathfinding.hpp | 12 +++--- 5 files changed, 56 insertions(+), 53 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 649f259d9a..8f43c6280d 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -677,44 +677,32 @@ namespace MWMechanics return false; } + bool AiCombat::doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell) + { + if (!mPathFinder.getPath().empty()) + { + Ogre::Vector3 currPathTarget(PathFinder::MakeOgreVector3(mPathFinder.getPath().back())); + Ogre::Vector3 newPathTarget = PathFinder::MakeOgreVector3(dest); + float dist = (newPathTarget - currPathTarget).length(); + float targetPosThreshold = (cell->isExterior()) ? 300.0f : 100.0f; + return dist > targetPosThreshold; + } + else + { + // necessarily construct a new path + return true; + } + } + void AiCombat::buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target) { - Ogre::Vector3 newPathTarget = Ogre::Vector3(target.getRefData().getPosition().pos); - - float dist; - - if(!mPathFinder.getPath().empty()) - { - ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); - Ogre::Vector3 currPathTarget(PathFinder::MakeOgreVector3(lastPt)); - dist = (newPathTarget - currPathTarget).length(); - } - else dist = 1e+38F; // necessarily construct a new path - - float targetPosThreshold = (actor.getCell()->getCell()->isExterior())? 300.0f : 100.0f; + ESM::Pathgrid::Point newPathTarget = PathFinder::MakePathgridPoint(target.getRefData().getPosition()); //construct new path only if target has moved away more than on [targetPosThreshold] - if(dist > targetPosThreshold) + if (doesPathNeedRecalc(newPathTarget, actor.getCell()->getCell())) { - ESM::Position pos = actor.getRefData().getPosition(); - - ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos)); - - ESM::Pathgrid::Point dest(PathFinder::MakePathgridPoint(newPathTarget)); - - if(!mPathFinder.isPathConstructed()) - mPathFinder.buildPath(start, dest, actor.getCell(), false); - else - { - PathFinder newPathFinder; - newPathFinder.buildPath(start, dest, actor.getCell(), false); - - if(!mPathFinder.getPath().empty()) - { - newPathFinder.syncStart(mPathFinder.getPath()); - mPathFinder = newPathFinder; - } - } + ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(actor.getRefData().getPosition())); + mPathFinder.buildSyncedPath(start, newPathTarget, actor.getCell(), false); } } diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 307df3872c..8248975b58 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -53,6 +53,9 @@ namespace MWMechanics virtual void writeState(ESM::AiSequence::AiSequence &sequence) const; + protected: + virtual bool doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell); + private: int mTargetActorId; diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 802a7723ea..216bf7b098 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -68,7 +68,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po if(mTimer > 0.25) { if (doesPathNeedRecalc(dest, cell)) { //Only rebuild path if it's moved - mPathFinder.buildPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved + mPathFinder.buildSyncedPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved mPrevDest = dest; } diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 5795f818af..980de1badd 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -301,23 +301,35 @@ namespace MWMechanics return false; } - // used by AiCombat, see header for the rationale - bool PathFinder::syncStart(const std::list &path) + // see header for the rationale + void PathFinder::buildSyncedPath(const ESM::Pathgrid::Point &startPoint, + const ESM::Pathgrid::Point &endPoint, + const MWWorld::CellStore* cell, + bool allowShortcuts) { if (mPath.size() < 2) - return false; //nothing to pop - - std::list::const_iterator oldStart = path.begin(); - std::list::iterator iter = ++mPath.begin(); - - if( (*iter).mX == oldStart->mX - && (*iter).mY == oldStart->mY - && (*iter).mZ == oldStart->mZ) { - mPath.pop_front(); - return true; + // if path has one point, then it's the destination. + // don't need to worry about bad path for this case + buildPath(startPoint, endPoint, cell, allowShortcuts); + } + else + { + const ESM::Pathgrid::Point oldStart(*getPath().begin()); + buildPath(startPoint, endPoint, cell, allowShortcuts); + if (mPath.size() >= 2) + { + // if 2nd waypoint of new path == 1st waypoint of old, + // delete 1st waypoint of new path. + std::list::iterator iter = ++mPath.begin(); + if (iter->mX == oldStart.mX + && iter->mY == oldStart.mY + && iter->mZ == oldStart.mZ) + { + mPath.pop_front(); + } + } } - return false; } } diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index f48de6624c..0f52a6e19d 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -63,13 +63,13 @@ namespace MWMechanics /** Synchronize new path with old one to avoid visiting 1 waypoint 2 times @note - If the first point is chosen as the nearest one - the situation can occur when the 1st point of the new path is undesirable - (i.e. the 2nd point of new path == the 1st point of old path). - @param path - old path - @return true if such point was found and deleted + BuildPath() takes closest PathGrid point to NPC as first point of path. + This is undesireable if NPC has just passed a Pathgrid point, as this + makes the 2nd point of the new path == the 1st point of old path. + Which results in NPC "running in a circle" back to the just passed waypoint. */ - bool syncStart(const std::list &path); + void buildSyncedPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint, + const MWWorld::CellStore* cell, bool allowShortcuts = true); void addPointToPath(ESM::Pathgrid::Point &point) { From 6051c47eef9f88f65412b9f82f3fee7a895866f3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 11 Jun 2015 22:36:19 +0200 Subject: [PATCH 07/57] Fix for incorrect QString -> path conversion --- apps/opencs/editor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 84849cbbba..efd7cf4ec7 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -307,12 +307,12 @@ bool CS::Editor::makeIPCServer() mServer->close(); fullPath.remove(QRegExp("dummy$")); fullPath += mIpcServerName; - if(boost::filesystem::exists(fullPath.toStdString().c_str())) + if(boost::filesystem::exists(fullPath.toUtf8().constData())) { // TODO: compare pid of the current process with that in the file std::cout << "Detected unclean shutdown." << std::endl; // delete the stale file - if(remove(fullPath.toStdString().c_str())) + if(remove(fullPath.toUtf8().constData())) std::cerr << "ERROR removing stale connection file" << std::endl; } } From e257c915bfc75db5474d0e31d307664bbe745e60 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 00:00:23 +0300 Subject: [PATCH 08/57] Add color picker popup to choose color --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/widget/coloreditor.cpp | 111 ++++++++++++++++++ apps/opencs/view/widget/coloreditor.hpp | 43 +++++++ apps/opencs/view/widget/colorpickerpopup.cpp | 63 ++++++++++ apps/opencs/view/widget/colorpickerpopup.hpp | 31 +++++ .../opencs/view/world/colorpickerdelegate.cpp | 8 +- 6 files changed, 253 insertions(+), 5 deletions(-) create mode 100644 apps/opencs/view/widget/coloreditor.cpp create mode 100644 apps/opencs/view/widget/coloreditor.hpp create mode 100644 apps/opencs/view/widget/colorpickerpopup.cpp create mode 100644 apps/opencs/view/widget/colorpickerpopup.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index f8f3ea0360..83a20ecaa1 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -75,7 +75,7 @@ opencs_units_noqt (view/world opencs_units (view/widget scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton - scenetooltoggle2 completerpopup coloreditbutton + scenetooltoggle2 completerpopup coloreditor colorpickerpopup ) opencs_units (view/render diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp new file mode 100644 index 0000000000..bab98fcd51 --- /dev/null +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -0,0 +1,111 @@ +#include "coloreditor.hpp" + +#include +#include +#include +#include +#include +#include + +#include "colorpickerpopup.hpp" + +CSVWidget::ColorEditor::ColorEditor(const QColor &color, + const QSize &coloredRectSize, + QWidget *parent) + : QPushButton(parent), + mColor(color), + mColoredRectSize(coloredRectSize), + mColorPicker(new ColorPickerPopup(this)) +{ + setCheckable(true); + connect(this, SIGNAL(clicked()), this, SLOT(showPicker())); + connect(mColorPicker, SIGNAL(hid()), this, SLOT(pickerHid())); + connect(mColorPicker, SIGNAL(colorChanged(const QColor &)), this, SLOT(pickerColorChanged(const QColor &))); +} + +void CSVWidget::ColorEditor::paintEvent(QPaintEvent *event) +{ + QPushButton::paintEvent(event); + + QRect buttonRect = rect(); + QRect coloredRect(buttonRect.x() + (buttonRect.width() - mColoredRectSize.width()) / 2, + buttonRect.y() + (buttonRect.height() - mColoredRectSize.height()) / 2, + mColoredRectSize.width(), + mColoredRectSize.height()); + QPainter painter(this); + painter.fillRect(coloredRect, mColor); +} + +QColor CSVWidget::ColorEditor::color() const +{ + return mColor; +} + +void CSVWidget::ColorEditor::setColor(const QColor &color) +{ + mColor = color; +} + +void CSVWidget::ColorEditor::setColoredRectSize(const QSize &size) +{ + mColoredRectSize = size; +} + +void CSVWidget::ColorEditor::showPicker() +{ + if (isChecked()) + { + mColorPicker->showPicker(calculatePopupPosition(), mColor); + } + else + { + mColorPicker->hide(); + } +} + +void CSVWidget::ColorEditor::pickerHid() +{ + // If the popup is hidden and mouse isn't above the editor, + // reset the editor checked state manually + QPoint globalEditorPosition = mapToGlobal(QPoint(0, 0)); + QRect globalEditorRect(globalEditorPosition, geometry().size()); + if (!globalEditorRect.contains(QCursor::pos())) + { + setChecked(false); + } +} + +void CSVWidget::ColorEditor::pickerColorChanged(const QColor &color) +{ + mColor = color; + update(); +} + +QPoint CSVWidget::ColorEditor::calculatePopupPosition() +{ + QRect editorGeometry = geometry(); + QRect popupGeometry = mColorPicker->geometry(); + QRect screenGeometry = QApplication::desktop()->screenGeometry(); + + // Center the popup horizontally relative to the editor + int localPopupX = (editorGeometry.width() - popupGeometry.width()) / 2; + // Popup position need to be specified in global coords + QPoint popupPosition = mapToGlobal(QPoint(localPopupX, editorGeometry.height())); + + // Make sure that the popup isn't out of the screen + if (popupPosition.x() < screenGeometry.left()) + { + popupPosition.setX(screenGeometry.left() + 1); + } + else if (popupPosition.x() + popupGeometry.width() > screenGeometry.right()) + { + popupPosition.setX(screenGeometry.right() - popupGeometry.width() - 1); + } + if (popupPosition.y() + popupGeometry.height() > screenGeometry.bottom()) + { + // Place the popup above the editor + popupPosition.setY(popupPosition.y() - popupGeometry.height() - editorGeometry.height() - 1); + } + + return popupPosition; +} diff --git a/apps/opencs/view/widget/coloreditor.hpp b/apps/opencs/view/widget/coloreditor.hpp new file mode 100644 index 0000000000..a0fa497b69 --- /dev/null +++ b/apps/opencs/view/widget/coloreditor.hpp @@ -0,0 +1,43 @@ +#ifndef CSV_WIDGET_COLOREDITOR_HPP +#define CSV_WIDGET_COLOREDITOR_HPP + +#include + +class QColor; +class QPoint; +class QSize; + +namespace CSVWidget +{ + class ColorPickerPopup; + + class ColorEditor : public QPushButton + { + Q_OBJECT + + QColor mColor; + QSize mColoredRectSize; + ColorPickerPopup *mColorPicker; + + QPoint calculatePopupPosition(); + + public: + ColorEditor(const QColor &color, + const QSize &coloredRectSize, + QWidget *parent = 0); + + QColor color() const; + void setColor(const QColor &color); + void setColoredRectSize(const QSize &size); + + protected: + void paintEvent(QPaintEvent *event); + + private slots: + void showPicker(); + void pickerHid(); + void pickerColorChanged(const QColor &color); + }; +} + +#endif diff --git a/apps/opencs/view/widget/colorpickerpopup.cpp b/apps/opencs/view/widget/colorpickerpopup.cpp new file mode 100644 index 0000000000..dd53f1becc --- /dev/null +++ b/apps/opencs/view/widget/colorpickerpopup.cpp @@ -0,0 +1,63 @@ +#include "colorpickerpopup.hpp" + +#include +#include +#include +#include + +CSVWidget::ColorPickerPopup::ColorPickerPopup(QWidget *parent) + : QFrame(parent) +{ + setWindowFlags(Qt::Popup); + setFrameStyle(QFrame::Box | QFrame::Plain); + hide(); + + mColorPicker = new QColorDialog(this); + mColorPicker->setWindowFlags(Qt::Widget); + mColorPicker->setOptions(QColorDialog::NoButtons | QColorDialog::DontUseNativeDialog); + mColorPicker->installEventFilter(this); + mColorPicker->open(); + connect(mColorPicker, + SIGNAL(currentColorChanged(const QColor &)), + this, + SIGNAL(colorChanged(const QColor &))); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(mColorPicker); + layout->setAlignment(Qt::AlignTop | Qt::AlignLeft); + layout->setContentsMargins(0, 0, 0, 0); + setLayout(layout); + setFixedSize(mColorPicker->size()); +} + +void CSVWidget::ColorPickerPopup::showPicker(const QPoint &position, const QColor &initialColor) +{ + QRect geometry = this->geometry(); + geometry.moveTo(position); + setGeometry(geometry); + + mColorPicker->setCurrentColor(initialColor); + show(); +} + +void CSVWidget::ColorPickerPopup::hideEvent(QHideEvent *event) +{ + QFrame::hideEvent(event); + emit hid(); +} + +bool CSVWidget::ColorPickerPopup::eventFilter(QObject *object, QEvent *event) +{ + if (object == mColorPicker && event->type() == QEvent::KeyPress) + { + QKeyEvent *keyEvent = static_cast(event); + // Prevent QColorDialog from closing when Escape is pressed. + // Instead, hide the popup. + if (keyEvent->key() == Qt::Key_Escape) + { + hide(); + return true; + } + } + return QFrame::eventFilter(object, event); +} diff --git a/apps/opencs/view/widget/colorpickerpopup.hpp b/apps/opencs/view/widget/colorpickerpopup.hpp new file mode 100644 index 0000000000..a7aec3bad6 --- /dev/null +++ b/apps/opencs/view/widget/colorpickerpopup.hpp @@ -0,0 +1,31 @@ +#ifndef CSVWIDGET_COLORPICKERPOPUP_HPP +#define CSVWIDGET_COLORPICKERPOPUP_HPP + +#include + +class QColorDialog; + +namespace CSVWidget +{ + class ColorPickerPopup : public QFrame + { + Q_OBJECT + + QColorDialog *mColorPicker; + + public: + explicit ColorPickerPopup(QWidget *parent); + + void showPicker(const QPoint &position, const QColor &initialColor); + + protected: + virtual void hideEvent(QHideEvent *event); + virtual bool eventFilter(QObject *object, QEvent *event); + + signals: + void hid(); + void colorChanged(const QColor &color); + }; +} + +#endif diff --git a/apps/opencs/view/world/colorpickerdelegate.cpp b/apps/opencs/view/world/colorpickerdelegate.cpp index c74a1828f3..4491f392cf 100644 --- a/apps/opencs/view/world/colorpickerdelegate.cpp +++ b/apps/opencs/view/world/colorpickerdelegate.cpp @@ -3,7 +3,7 @@ #include #include -#include "../widget/coloreditbutton.hpp" +#include "../widget/coloreditor.hpp" CSVWorld::ColorPickerDelegate::ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, @@ -28,9 +28,9 @@ QWidget *CSVWorld::ColorPickerDelegate::createEditor(QWidget *parent, throw std::logic_error("Wrong column for ColorPickerDelegate"); } - return new CSVWidget::ColorEditButton(index.data().value(), - getColoredRect(option).size(), - parent); + return new CSVWidget::ColorEditor(index.data().value(), + getColoredRect(option).size(), + parent); } void CSVWorld::ColorPickerDelegate::paint(QPainter *painter, From d03880fbf04a001978c23c7acba0f11156512505 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 11 Jun 2015 23:25:26 +0200 Subject: [PATCH 09/57] Compile fix for old boost versions --- apps/opencs/model/doc/document.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 18a4f48787..b833b527ff 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2272,7 +2272,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, if (boost::filesystem::exists (customFiltersPath)) { - destination << std::ifstream(customFiltersPath.c_str(), std::ios::binary).rdbuf(); + destination << std::ifstream(customFiltersPath.string().c_str(), std::ios::binary).rdbuf(); } else { From fc5176dc3882fe183809bb5060c519641aa2867d Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 11 Jun 2015 23:26:32 +0200 Subject: [PATCH 10/57] Refactor cmake scripts, reducing the amount of find_package(Qt4) --- CMakeLists.txt | 2 ++ apps/launcher/CMakeLists.txt | 4 ++-- apps/opencs/CMakeLists.txt | 5 +++-- apps/wizard/CMakeLists.txt | 4 ++-- components/CMakeLists.txt | 12 +++--------- 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ec69c5560e..0a75976d4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,6 +151,8 @@ endif() # Dependencies +find_package(Qt4 REQUIRED COMPONENTS QtCore QtGui QtNetwork) + # Fix for not visible pthreads functions for linker with glibc 2.15 if (UNIX AND NOT APPLE) find_package (Threads) diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 0de79f8f6b..8be7a20b65 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -57,7 +57,6 @@ set(LAUNCHER_UI source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER}) -find_package(Qt4 REQUIRED) set(QT_USE_QTGUI 1) # Set some platform specific settings @@ -92,7 +91,8 @@ target_link_libraries(openmw-launcher ${OGRE_LIBRARIES} ${OGRE_STATIC_PLUGINS} ${SDL2_LIBRARY_ONLY} - ${QT_LIBRARIES} + ${QT_QTGUI_LIBRARY} + ${QT_QTCORE_LIBRARY} components ) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 37d13223a7..044e8c4eeb 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -160,7 +160,6 @@ endif(WIN32) find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) -find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED) include(${QT_USE_FILE}) qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI}) @@ -208,7 +207,9 @@ target_link_libraries(openmw-cs ${SHINY_LIBRARIES} ${Boost_LIBRARIES} ${BULLET_LIBRARIES} - ${QT_LIBRARIES} + ${QT_QTGUI_LIBRARY} + ${QT_QTCORE_LIBRARY} + ${QT_QTNETWORK_LIBRARY} components ) diff --git a/apps/wizard/CMakeLists.txt b/apps/wizard/CMakeLists.txt index b8cc3fda4d..55f326a0c1 100644 --- a/apps/wizard/CMakeLists.txt +++ b/apps/wizard/CMakeLists.txt @@ -81,7 +81,6 @@ endif (OPENMW_USE_UNSHIELD) source_group(wizard FILES ${WIZARD} ${WIZARD_HEADER}) -find_package(Qt4 REQUIRED) set(QT_USE_QTGUI 1) # Set some platform specific settings @@ -113,7 +112,8 @@ add_executable(openmw-wizard target_link_libraries(openmw-wizard ${Boost_LIBRARIES} - ${QT_LIBRARIES} + ${QT_QTGUI_LIBRARY} + ${QT_QTCORE_LIBRARY} components ) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 01de1c28e1..951a80509d 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -126,11 +126,6 @@ add_component_dir (version set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui ) -find_package(Qt4 COMPONENTS QtCore QtGui) -if(MINGW) -find_package(Bullet REQUIRED COMPONENTS Collision) -endif() - if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) add_component_qt_dir (contentselector model/modelitem model/esmfile @@ -167,16 +162,15 @@ target_link_libraries(components ${Boost_LIBRARIES} ${OGRE_LIBRARIES} ${OENGINE_LIBRARY} + ${QT_QTCORE_LIBRARY} + ${QT_QTGUI_LIBRARY} + ${BULLET_LIBRARIES} ) if (GIT_CHECKOUT) add_dependencies (components git-version) endif (GIT_CHECKOUT) -if(MINGW) -target_link_libraries(components ${QT_LIBRARIES} ${BULLET_LIBRARIES}) -endif() - if (WIN32) target_link_libraries(components shlwapi) endif() From cf95d3fc356597eb5abb38e08bb4ebd091649f2f Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 11 Jun 2015 23:49:27 +0200 Subject: [PATCH 11/57] Refactor cmake scripts, reducing the amount of find_package(Boost) --- CMakeLists.txt | 2 +- apps/bsatool/CMakeLists.txt | 3 ++- apps/esmtool/CMakeLists.txt | 2 +- apps/essimporter/CMakeLists.txt | 3 ++- apps/launcher/CMakeLists.txt | 1 - apps/mwiniimporter/CMakeLists.txt | 3 ++- apps/opencs/CMakeLists.txt | 19 ++++++++++--------- apps/openmw/CMakeLists.txt | 17 +++++------------ apps/wizard/CMakeLists.txt | 1 - components/CMakeLists.txt | 6 +++++- extern/ogre-ffmpeg-videoplayer/CMakeLists.txt | 5 +---- 11 files changed, 29 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a75976d4c..4b447a3e8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -173,7 +173,7 @@ if (HAVE_UNORDERED_MAP) endif () -set(BOOST_COMPONENTS system filesystem program_options) +set(BOOST_COMPONENTS system filesystem program_options thread wave) if(WIN32) set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale) endif(WIN32) diff --git a/apps/bsatool/CMakeLists.txt b/apps/bsatool/CMakeLists.txt index 3f1988a709..27baff8157 100644 --- a/apps/bsatool/CMakeLists.txt +++ b/apps/bsatool/CMakeLists.txt @@ -9,7 +9,8 @@ add_executable(bsatool ) target_link_libraries(bsatool - ${Boost_LIBRARIES} + ${Boost_PROGRAM_OPTIONS_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} components ) diff --git a/apps/esmtool/CMakeLists.txt b/apps/esmtool/CMakeLists.txt index 1d00262151..1d5e662d83 100644 --- a/apps/esmtool/CMakeLists.txt +++ b/apps/esmtool/CMakeLists.txt @@ -13,7 +13,7 @@ add_executable(esmtool ) target_link_libraries(esmtool - ${Boost_LIBRARIES} + ${Boost_PROGRAM_OPTIONS_LIBRARY} components ) diff --git a/apps/essimporter/CMakeLists.txt b/apps/essimporter/CMakeLists.txt index 72ef364ee6..84e31dad9e 100644 --- a/apps/essimporter/CMakeLists.txt +++ b/apps/essimporter/CMakeLists.txt @@ -33,7 +33,8 @@ add_executable(openmw-essimporter ) target_link_libraries(openmw-essimporter - ${Boost_LIBRARIES} + ${Boost_PROGRAM_OPTIONS_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} components ) diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 8be7a20b65..e392b8efc4 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -87,7 +87,6 @@ add_executable(openmw-launcher ) target_link_libraries(openmw-launcher - ${Boost_LIBRARIES} ${OGRE_LIBRARIES} ${OGRE_STATIC_PLUGINS} ${SDL2_LIBRARY_ONLY} diff --git a/apps/mwiniimporter/CMakeLists.txt b/apps/mwiniimporter/CMakeLists.txt index 753c86fef6..e522df6a18 100644 --- a/apps/mwiniimporter/CMakeLists.txt +++ b/apps/mwiniimporter/CMakeLists.txt @@ -14,7 +14,8 @@ add_executable(openmw-iniimporter ) target_link_libraries(openmw-iniimporter - ${Boost_LIBRARIES} + ${Boost_PROGRAM_OPTIONS_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} components ) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 044e8c4eeb..c011f46950 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -153,13 +153,6 @@ if(WIN32) set(QT_USE_QTMAIN TRUE) endif(WIN32) -set(BOOST_COMPONENTS system filesystem program_options thread wave) -if(WIN32) - set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale) -endif(WIN32) - -find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) - include(${QT_USE_FILE}) qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI}) @@ -205,14 +198,22 @@ target_link_libraries(openmw-cs ${OGRE_Overlay_LIBRARIES} ${OGRE_STATIC_PLUGINS} ${SHINY_LIBRARIES} - ${Boost_LIBRARIES} - ${BULLET_LIBRARIES} + ${Boost_SYSTEM_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_PROGRAM_OPTIONS_LIBRARY} + ${Boost_WAVE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTCORE_LIBRARY} ${QT_QTNETWORK_LIBRARY} + ${BULLET_LIBRARIES} components ) +if (WIN32) + target_link_libraries(openmw-cs ${Boost_LOCALE_LIBRARY}) +endif() + + if(APPLE) INSTALL(TARGETS openmw-cs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE) endif() diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index a183d172dc..c7c701d20e 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -91,17 +91,6 @@ add_openmw_dir (mwbase ) # Main executable -if (ANDROID) - set(BOOST_COMPONENTS system filesystem program_options thread wave atomic) -else () - set(BOOST_COMPONENTS system filesystem program_options thread wave) -endif () - -if(WIN32) - set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale) -endif(WIN32) - -find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) if (NOT ANDROID) add_executable(openmw @@ -126,10 +115,14 @@ target_link_libraries(openmw ${OGRE_LIBRARIES} ${OGRE_STATIC_PLUGINS} ${SHINY_LIBRARIES} - ${Boost_LIBRARIES} ${OPENAL_LIBRARY} ${SOUND_INPUT_LIBRARY} ${BULLET_LIBRARIES} + ${Boost_SYSTEM_LIBRARY} + ${Boost_THREAD_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_PROGRAM_OPTIONS_LIBRARY} + ${Boost_WAVE_LIBRARY} ${MYGUI_LIBRARIES} ${SDL2_LIBRARY} ${MYGUI_PLATFORM_LIBRARIES} diff --git a/apps/wizard/CMakeLists.txt b/apps/wizard/CMakeLists.txt index 55f326a0c1..6506541ee9 100644 --- a/apps/wizard/CMakeLists.txt +++ b/apps/wizard/CMakeLists.txt @@ -111,7 +111,6 @@ add_executable(openmw-wizard ) target_link_libraries(openmw-wizard - ${Boost_LIBRARIES} ${QT_QTGUI_LIBRARY} ${QT_QTCORE_LIBRARY} components diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 951a80509d..a6ca2e86d2 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -159,7 +159,11 @@ include_directories(${BULLET_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) add_library(components STATIC ${COMPONENT_FILES} ${MOC_SRCS} ${ESM_UI_HDR}) target_link_libraries(components - ${Boost_LIBRARIES} + ${Boost_SYSTEM_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_THREAD_LIBRARY} + ${Boost_PROGRAM_OPTIONS_LIBRARY} + ${Boost_WAVE_LIBRARY} ${OGRE_LIBRARIES} ${OENGINE_LIBRARY} ${QT_QTCORE_LIBRARY} diff --git a/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt b/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt index 299a57799b..4e8f55eb88 100644 --- a/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt +++ b/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt @@ -32,11 +32,8 @@ endif() include_directories(${FFMPEG_INCLUDE_DIRS}) # Find Boost -set(BOOST_COMPONENTS thread) -find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) -include_directories(${Boost_INCLUDE_DIRS}) add_library(${OGRE_FFMPEG_VIDEOPLAYER_LIBRARY} STATIC ${OGRE_FFMPEG_VIDEOPLAYER_SOURCE_FILES}) -target_link_libraries(${OGRE_FFMPEG_VIDEOPLAYER_LIBRARY} ${VIDEO_FFMPEG_LIBRARIES} ${Boost_LIBRARIES}) +target_link_libraries(${OGRE_FFMPEG_VIDEOPLAYER_LIBRARY} ${VIDEO_FFMPEG_LIBRARIES} ${Boost_THREAD_LIBRARY}) link_directories(${CMAKE_CURRENT_BINARY_DIR}) From 45fcea929ace0facf156cf85457153e5ddfb66a3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 12 Jun 2015 01:45:48 +0200 Subject: [PATCH 12/57] Refactor cmake scripts, reducing the amount of find_package(FFmpeg) --- CMakeLists.txt | 15 ++++++++----- extern/ogre-ffmpeg-videoplayer/CMakeLists.txt | 22 +------------------ 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b447a3e8e..b9282faeec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,25 +98,30 @@ endif() cmake_minimum_required(VERSION 2.6) # Sound setup -set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE) unset(FFMPEG_LIBRARIES CACHE) -find_package(FFmpeg) + +find_package(FFmpeg REQUIRED) + +set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARY}) + +message(STATUS ${FFMPEG_LIBRARIES}) if ( NOT AVCODEC_FOUND OR NOT AVFORMAT_FOUND OR NOT AVUTIL_FOUND OR NOT SWSCALE_FOUND ) message(FATAL_ERROR "FFmpeg component required, but not found!") endif() set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIRS}) -set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES}) if( SWRESAMPLE_FOUND ) add_definitions(-DHAVE_LIBSWRESAMPLE) - set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES}) + set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES}) else() if( AVRESAMPLE_FOUND ) - set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES}) + set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES}) else() message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).") endif() endif() +set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES}) + # TinyXML option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF) if(USE_SYSTEM_TINYXML) diff --git a/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt b/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt index 4e8f55eb88..cda3d39e83 100644 --- a/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt +++ b/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt @@ -11,29 +11,9 @@ set(OGRE_FFMPEG_VIDEOPLAYER_SOURCE_FILES audiofactory.hpp ) -# Find FFMPEG -set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE) -unset(FFMPEG_LIBRARIES CACHE) -find_package(FFmpeg) -if ( NOT AVCODEC_FOUND OR NOT AVFORMAT_FOUND OR NOT AVUTIL_FOUND OR NOT SWSCALE_FOUND ) - message(FATAL_ERROR "FFmpeg component required, but not found!") -endif() -set(VIDEO_FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES}) -if( SWRESAMPLE_FOUND ) - add_definitions(-DHAVE_LIBSWRESAMPLE) - set(VIDEO_FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES}) -else() - if( AVRESAMPLE_FOUND ) - set(VIDEO_FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES}) - else() - message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).") - endif() -endif() -include_directories(${FFMPEG_INCLUDE_DIRS}) - # Find Boost add_library(${OGRE_FFMPEG_VIDEOPLAYER_LIBRARY} STATIC ${OGRE_FFMPEG_VIDEOPLAYER_SOURCE_FILES}) -target_link_libraries(${OGRE_FFMPEG_VIDEOPLAYER_LIBRARY} ${VIDEO_FFMPEG_LIBRARIES} ${Boost_THREAD_LIBRARY}) +target_link_libraries(${OGRE_FFMPEG_VIDEOPLAYER_LIBRARY} ${FFMPEG_LIBRARIES} ${Boost_THREAD_LIBRARY}) link_directories(${CMAKE_CURRENT_BINARY_DIR}) From c04f6cf16766d37fb65d5081290d820e4ddab4d3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 12 Jun 2015 01:58:13 +0200 Subject: [PATCH 13/57] Remove unused code --- components/contentselector/model/contentmodel.cpp | 11 ----------- components/contentselector/model/contentmodel.hpp | 1 - 2 files changed, 12 deletions(-) diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index 62f6d90141..d000290e6f 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -30,17 +30,6 @@ ContentSelectorModel::ContentModel::~ContentModel() void ContentSelectorModel::ContentModel::setEncoding(const QString &encoding) { mEncoding = encoding; - if (encoding == QLatin1String("win1252")) - mCodec = QTextCodec::codecForName("windows-1252"); - - else if (encoding == QLatin1String("win1251")) - mCodec = QTextCodec::codecForName("windows-1251"); - - else if (encoding == QLatin1String("win1250")) - mCodec = QTextCodec::codecForName("windows-1250"); - - else - return; // This should never happen; } int ContentSelectorModel::ContentModel::columnCount(const QModelIndex &parent) const diff --git a/components/contentselector/model/contentmodel.hpp b/components/contentselector/model/contentmodel.hpp index 6585558520..ab965ad69c 100644 --- a/components/contentselector/model/contentmodel.hpp +++ b/components/contentselector/model/contentmodel.hpp @@ -81,7 +81,6 @@ namespace ContentSelectorModel ContentFileList mFiles; QHash mCheckStates; QSet mPluginsWithLoadOrderError; - QTextCodec *mCodec; QString mEncoding; QIcon mWarningIcon; From 4b5c2398a10e57d74c73d888e386118b6227ccdc Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 12 Jun 2015 02:00:06 +0200 Subject: [PATCH 14/57] Remove QTextCodec::setCodecForCStrings Not needed, we're using QString::fromUtf8/toUtf8 to handle encodings correctly. --- apps/launcher/main.cpp | 3 --- apps/wizard/main.cpp | 3 --- 2 files changed, 6 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index ba06861107..32fe8c93a7 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -54,9 +54,6 @@ int main(int argc, char *argv[]) QDir::setCurrent(dir.absolutePath()); - // Support non-latin characters - QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); - Launcher::MainDialog mainWin; Launcher::FirstRunDialogResult result = mainWin.showFirstRunDialog(); diff --git a/apps/wizard/main.cpp b/apps/wizard/main.cpp index e6a94118af..c861a4ac89 100644 --- a/apps/wizard/main.cpp +++ b/apps/wizard/main.cpp @@ -38,9 +38,6 @@ int main(int argc, char *argv[]) QDir::setCurrent(dir.absolutePath()); - // Support non-latin characters - QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); - Wizard::MainWizard wizard; wizard.show(); From 4096d2851c66a574743c4a6d2ca4c61305affdab Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 14:09:25 +0300 Subject: [PATCH 15/57] Remove outdated ColorEditButton files --- apps/opencs/view/widget/coloreditbutton.cpp | 42 --------------------- apps/opencs/view/widget/coloreditbutton.hpp | 30 --------------- 2 files changed, 72 deletions(-) delete mode 100644 apps/opencs/view/widget/coloreditbutton.cpp delete mode 100644 apps/opencs/view/widget/coloreditbutton.hpp diff --git a/apps/opencs/view/widget/coloreditbutton.cpp b/apps/opencs/view/widget/coloreditbutton.cpp deleted file mode 100644 index 4960d1ef1b..0000000000 --- a/apps/opencs/view/widget/coloreditbutton.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "coloreditbutton.hpp" - -#include -#include -#include - -CSVWidget::ColorEditButton::ColorEditButton(const QColor &color, - const QSize &coloredRectSize, - QWidget *parent) - : QPushButton(parent), - mColor(color), - mColoredRectSize(coloredRectSize) - -{} - -void CSVWidget::ColorEditButton::paintEvent(QPaintEvent *event) -{ - QPushButton::paintEvent(event); - - QRect buttonRect = rect(); - QRect coloredRect(buttonRect.x() + (buttonRect.width() - mColoredRectSize.width()) / 2, - buttonRect.y() + (buttonRect.height() - mColoredRectSize.height()) / 2, - mColoredRectSize.width(), - mColoredRectSize.height()); - QPainter painter(this); - painter.fillRect(coloredRect, mColor); -} - -QColor CSVWidget::ColorEditButton::color() const -{ - return mColor; -} - -void CSVWidget::ColorEditButton::setColor(const QColor &color) -{ - mColor = color; -} - -void CSVWidget::ColorEditButton::setColoredRectSize(const QSize &size) -{ - mColoredRectSize = size; -} \ No newline at end of file diff --git a/apps/opencs/view/widget/coloreditbutton.hpp b/apps/opencs/view/widget/coloreditbutton.hpp deleted file mode 100644 index e1a8cce9da..0000000000 --- a/apps/opencs/view/widget/coloreditbutton.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef CSV_WIDGET_COLOREDITBUTTON_HPP -#define CSV_WIDGET_COLOREDITBUTTON_HPP - -#include - -class QColor; -class QSize; - -namespace CSVWidget -{ - class ColorEditButton : public QPushButton - { - QColor mColor; - QSize mColoredRectSize; - - public: - ColorEditButton(const QColor &color, - const QSize &coloredRectSize, - QWidget *parent = 0); - - QColor color() const; - void setColor(const QColor &color); - void setColoredRectSize(const QSize &size); - - protected: - void paintEvent(QPaintEvent *event); - }; -} - -#endif From e13a9388961039b0d8fe3b1e76e295e1c5054041 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 12 Jun 2015 15:10:12 +0200 Subject: [PATCH 16/57] Add support to build with Qt5 (Task #2665) Known issue: the render view doesn't work in Qt5. With the switch to OSG around the corner, this isn't worth fixing. --- CMakeLists.txt | 14 +++++- apps/launcher/CMakeLists.txt | 23 ++++++--- apps/opencs/CMakeLists.txt | 27 +++++++--- apps/opencs/model/world/idtableproxymodel.cpp | 3 +- apps/opencs/view/doc/view.cpp | 2 +- apps/opencs/view/doc/viewmanager.cpp | 6 +-- .../view/render/unpagedworldspacewidget.cpp | 2 +- apps/opencs/view/render/worldspacewidget.cpp | 7 ++- apps/opencs/view/settings/dialog.cpp | 9 +--- apps/opencs/view/settings/dialog.hpp | 5 -- apps/opencs/view/tools/reporttable.cpp | 6 +++ apps/opencs/view/widget/scenetoolrun.cpp | 5 ++ apps/opencs/view/world/dragrecordtable.cpp | 1 + apps/opencs/view/world/dragrecordtable.hpp | 2 +- apps/opencs/view/world/nestedtable.cpp | 4 ++ apps/opencs/view/world/nestedtable.hpp | 2 +- apps/opencs/view/world/table.cpp | 4 ++ apps/opencs/view/world/table.hpp | 2 +- apps/opencs/view/world/tablesubview.cpp | 1 + apps/wizard/CMakeLists.txt | 25 +++++++--- apps/wizard/unshield/unshieldworker.cpp | 1 - apps/wizard/unshield/unshieldworker.hpp | 1 - components/CMakeLists.txt | 49 +++++++++++-------- 23 files changed, 131 insertions(+), 70 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b9282faeec..5f3a0fcc1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,7 +104,6 @@ find_package(FFmpeg REQUIRED) set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARY}) -message(STATUS ${FFMPEG_LIBRARIES}) if ( NOT AVCODEC_FOUND OR NOT AVFORMAT_FOUND OR NOT AVUTIL_FOUND OR NOT SWSCALE_FOUND ) message(FATAL_ERROR "FFmpeg component required, but not found!") endif() @@ -156,7 +155,18 @@ endif() # Dependencies -find_package(Qt4 REQUIRED COMPONENTS QtCore QtGui QtNetwork) +set(DESIRED_QT_VERSION 4 CACHE STRING "The QT version OpenMW should use (4 or 5)") +message(STATUS "Using Qt${DESIRED_QT_VERSION}") + +if (DESIRED_QT_VERSION MATCHES 4) + find_package(Qt4 REQUIRED COMPONENTS QtCore QtGui QtNetwork) +else() + find_package(Qt5Widgets REQUIRED) + find_package(Qt5Core REQUIRED) + find_package(Qt5Network REQUIRED) + # Instruct CMake to run moc automatically when needed. + #set(CMAKE_AUTOMOC ON) +endif() # Fix for not visible pthreads functions for linker with glibc 2.15 if (UNIX AND NOT APPLE) diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index e392b8efc4..66cc157d3b 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -65,12 +65,17 @@ if(WIN32) set(QT_USE_QTMAIN TRUE) endif(WIN32) -QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc) -QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) -QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI}) +if (DESIRED_QT_VERSION MATCHES 4) + include(${QT_USE_FILE}) + QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc) + QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) + QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI}) +else() + QT5_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc) + QT5_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) + QT5_WRAP_UI(UI_HDRS ${LAUNCHER_UI}) +endif() - -include(${QT_USE_FILE}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) if(NOT WIN32) include_directories(${LIBUNSHIELD_INCLUDE_DIR}) @@ -90,14 +95,18 @@ target_link_libraries(openmw-launcher ${OGRE_LIBRARIES} ${OGRE_STATIC_PLUGINS} ${SDL2_LIBRARY_ONLY} - ${QT_QTGUI_LIBRARY} - ${QT_QTCORE_LIBRARY} components ) +if (DESIRED_QT_VERSION MATCHES 4) + target_link_libraries(openmw-launcher ${QT_QTGUI_LIBRARY} ${QT_QTCORE_LIBRARY}) +else() + qt5_use_modules(openmw-launcher Widgets Core) +endif() if (BUILD_WITH_CODE_COVERAGE) add_definitions (--coverage) target_link_libraries(openmw-launcher gcov) endif() + diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index c011f46950..402bd335ab 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -153,11 +153,16 @@ if(WIN32) set(QT_USE_QTMAIN TRUE) endif(WIN32) -include(${QT_USE_FILE}) - -qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI}) -qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT}) -qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES}) +if (DESIRED_QT_VERSION MATCHES 4) + include(${QT_USE_FILE}) + qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI}) + qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT}) + qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES}) +else() + qt5_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI}) + qt5_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT}) + qt5_add_resources(OPENCS_RES_SRC ${OPENCS_RES}) +endif() # for compiled .ui files include_directories(${CMAKE_CURRENT_BINARY_DIR}) @@ -202,13 +207,19 @@ target_link_libraries(openmw-cs ${Boost_FILESYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_WAVE_LIBRARY} - ${QT_QTGUI_LIBRARY} - ${QT_QTCORE_LIBRARY} - ${QT_QTNETWORK_LIBRARY} ${BULLET_LIBRARIES} components ) +if (DESIRED_QT_VERSION MATCHES 4) + target_link_libraries(openmw-cs + ${QT_QTGUI_LIBRARY} + ${QT_QTCORE_LIBRARY} + ${QT_QTNETWORK_LIBRARY}) +else() + qt5_use_modules(openmw-cs Widgets Core Network) +endif() + if (WIN32) target_link_libraries(openmw-cs ${Boost_LOCALE_LIBRARY}) endif() diff --git a/apps/opencs/model/world/idtableproxymodel.cpp b/apps/opencs/model/world/idtableproxymodel.cpp index d8932d2057..5166447138 100644 --- a/apps/opencs/model/world/idtableproxymodel.cpp +++ b/apps/opencs/model/world/idtableproxymodel.cpp @@ -52,9 +52,10 @@ QModelIndex CSMWorld::IdTableProxyModel::getModelIndex (const std::string& id, i void CSMWorld::IdTableProxyModel::setFilter (const boost::shared_ptr& filter) { + beginResetModel(); mFilter = filter; updateColumnMap(); - reset(); + endResetModel(); } bool CSMWorld::IdTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 2485caa883..64b066eb1e 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index b2f681df17..7c79302d74 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -6,6 +6,8 @@ #include #include +#include +#include #include "../../model/doc/documentmanager.hpp" #include "../../model/doc/document.hpp" @@ -24,10 +26,6 @@ #include "view.hpp" -#include -#include -#include - void CSVDoc::ViewManager::updateIndices() { std::map > documents; diff --git a/apps/opencs/view/render/unpagedworldspacewidget.cpp b/apps/opencs/view/render/unpagedworldspacewidget.cpp index 462b62b7a8..383382938d 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.cpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include "../../model/doc/document.hpp" diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index e888148186..ba0ec84460 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -7,7 +7,12 @@ #include #include -#include +#include +#include +#include +#include +#include +#include #include "../../model/world/universalid.hpp" #include "../../model/world/idtable.hpp" diff --git a/apps/opencs/view/settings/dialog.cpp b/apps/opencs/view/settings/dialog.cpp index e8832e2bcc..38eb7bbc7f 100644 --- a/apps/opencs/view/settings/dialog.cpp +++ b/apps/opencs/view/settings/dialog.cpp @@ -8,19 +8,12 @@ #include #include #include +#include #include "../../model/settings/usersettings.hpp" #include "page.hpp" -#include - -#include -#include -#include - -#include -#include CSVSettings::Dialog::Dialog(QMainWindow *parent) : SettingWindow (parent), mStackedWidget (0), mDebugMode (false) diff --git a/apps/opencs/view/settings/dialog.hpp b/apps/opencs/view/settings/dialog.hpp index cb85bddb98..e3a3f575ac 100644 --- a/apps/opencs/view/settings/dialog.hpp +++ b/apps/opencs/view/settings/dialog.hpp @@ -3,7 +3,6 @@ #include "settingwindow.hpp" #include "resizeablestackedwidget.hpp" -#include class QStackedWidget; class QListWidget; @@ -26,10 +25,6 @@ namespace CSVSettings { explicit Dialog (QMainWindow *parent = 0); - ///Enables setting debug mode. When the dialog opens, a page is created - ///which displays the SettingModel's contents in a Tree view. - void enableDebugMode (bool state, QStandardItemModel *model = 0); - protected: /// Settings are written on close diff --git a/apps/opencs/view/tools/reporttable.cpp b/apps/opencs/view/tools/reporttable.cpp index 7cfe8e4f05..c1c8a35dd3 100644 --- a/apps/opencs/view/tools/reporttable.cpp +++ b/apps/opencs/view/tools/reporttable.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include "../../model/tools/reportmodel.hpp" @@ -121,7 +123,11 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, const CSMWorld::UniversalId& id, bool richTextDescription, QWidget *parent) : CSVWorld::DragRecordTable (document, parent), mModel (document.getReport (id)) { +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + horizontalHeader()->setSectionResizeMode (QHeaderView::Interactive); +#else horizontalHeader()->setResizeMode (QHeaderView::Interactive); +#endif horizontalHeader()->setStretchLastSection (true); verticalHeader()->hide(); setSortingEnabled (true); diff --git a/apps/opencs/view/widget/scenetoolrun.cpp b/apps/opencs/view/widget/scenetoolrun.cpp index 8de334efeb..4c9eb676e8 100644 --- a/apps/opencs/view/widget/scenetoolrun.cpp +++ b/apps/opencs/view/widget/scenetoolrun.cpp @@ -65,8 +65,13 @@ CSVWidget::SceneToolRun::SceneToolRun (SceneToolbar *parent, const QString& tool mTable->setShowGrid (false); mTable->verticalHeader()->hide(); mTable->horizontalHeader()->hide(); +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + mTable->horizontalHeader()->setSectionResizeMode (0, QHeaderView::Stretch); + mTable->horizontalHeader()->setSectionResizeMode (1, QHeaderView::ResizeToContents); +#else mTable->horizontalHeader()->setResizeMode (0, QHeaderView::Stretch); mTable->horizontalHeader()->setResizeMode (1, QHeaderView::ResizeToContents); +#endif mTable->setSelectionMode (QAbstractItemView::NoSelection); layout->addWidget (mTable); diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index 7032fee6d2..2a1ae1f401 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -1,4 +1,5 @@ #include +#include #include "../../model/world/tablemimedata.hpp" #include "dragrecordtable.hpp" diff --git a/apps/opencs/view/world/dragrecordtable.hpp b/apps/opencs/view/world/dragrecordtable.hpp index 4996c03acd..48f9e25280 100644 --- a/apps/opencs/view/world/dragrecordtable.hpp +++ b/apps/opencs/view/world/dragrecordtable.hpp @@ -2,7 +2,7 @@ #define CSV_WORLD_DRAGRECORDTABLE_H #include -#include +#include class QWidget; class QAction; diff --git a/apps/opencs/view/world/nestedtable.cpp b/apps/opencs/view/world/nestedtable.cpp index 5c8762020f..112873cb9a 100644 --- a/apps/opencs/view/world/nestedtable.cpp +++ b/apps/opencs/view/world/nestedtable.cpp @@ -23,7 +23,11 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document, setSelectionBehavior (QAbstractItemView::SelectRows); setSelectionMode (QAbstractItemView::ExtendedSelection); +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + horizontalHeader()->setSectionResizeMode (QHeaderView::Interactive); +#else horizontalHeader()->setResizeMode (QHeaderView::Interactive); +#endif verticalHeader()->hide(); int columns = model->columnCount(QModelIndex()); diff --git a/apps/opencs/view/world/nestedtable.hpp b/apps/opencs/view/world/nestedtable.hpp index b8e91844c2..5db977942a 100644 --- a/apps/opencs/view/world/nestedtable.hpp +++ b/apps/opencs/view/world/nestedtable.hpp @@ -2,7 +2,7 @@ #define CSV_WORLD_NESTEDTABLE_H #include -#include +#include class QUndoStack; class QAction; diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index bb3dfa4d32..b4efbd3c8f 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -282,7 +282,11 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, mDispatcher = new CSMWorld::CommandDispatcher (document, id, this); setModel (mProxyModel); +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + horizontalHeader()->setSectionResizeMode (QHeaderView::Interactive); +#else horizontalHeader()->setResizeMode (QHeaderView::Interactive); +#endif verticalHeader()->hide(); setSortingEnabled (sorting); setSelectionBehavior (QAbstractItemView::SelectRows); diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index becb21f65d..67bf3fe857 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include "../../model/filter/node.hpp" #include "../../model/world/columnbase.hpp" diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index af0b644475..faff4c429b 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "../../model/doc/document.hpp" #include "../../model/world/tablemimedata.hpp" diff --git a/apps/wizard/CMakeLists.txt b/apps/wizard/CMakeLists.txt index 6506541ee9..5cd874863b 100644 --- a/apps/wizard/CMakeLists.txt +++ b/apps/wizard/CMakeLists.txt @@ -89,12 +89,17 @@ if(WIN32) set(QT_USE_QTMAIN TRUE) endif(WIN32) -QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/wizard/wizard.qrc) -QT4_WRAP_CPP(MOC_SRCS ${WIZARD_HEADER_MOC}) -QT4_WRAP_UI(UI_HDRS ${WIZARD_UI}) +if (DESIRED_QT_VERSION MATCHES 4) + include(${QT_USE_FILE}) + QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/wizard/wizard.qrc) + QT4_WRAP_CPP(MOC_SRCS ${WIZARD_HEADER_MOC}) + QT4_WRAP_UI(UI_HDRS ${WIZARD_UI}) +else() + QT5_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/wizard/wizard.qrc) + QT5_WRAP_CPP(MOC_SRCS ${WIZARD_HEADER_MOC}) + QT5_WRAP_UI(UI_HDRS ${WIZARD_UI}) +endif() - -include(${QT_USE_FILE}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) if (OPENMW_USE_UNSHIELD) @@ -111,11 +116,17 @@ add_executable(openmw-wizard ) target_link_libraries(openmw-wizard - ${QT_QTGUI_LIBRARY} - ${QT_QTCORE_LIBRARY} components ) +if (DESIRED_QT_VERSION MATCHES 4) + target_link_libraries(openmw-wizard + ${QT_QTGUI_LIBRARY} + ${QT_QTCORE_LIBRARY}) +else() + qt5_use_modules(openmw-wizard Widgets Core) +endif() + if (OPENMW_USE_UNSHIELD) target_link_libraries(openmw-wizard ${LIBUNSHIELD_LIBRARY}) endif() diff --git a/apps/wizard/unshield/unshieldworker.cpp b/apps/wizard/unshield/unshieldworker.cpp index 11e090ed18..9daea2b71a 100644 --- a/apps/wizard/unshield/unshieldworker.cpp +++ b/apps/wizard/unshield/unshieldworker.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include diff --git a/apps/wizard/unshield/unshieldworker.hpp b/apps/wizard/unshield/unshieldworker.hpp index 5ea7b04aee..c1d3cfff1f 100644 --- a/apps/wizard/unshield/unshieldworker.hpp +++ b/apps/wizard/unshield/unshieldworker.hpp @@ -24,7 +24,6 @@ namespace Wizard class UnshieldWorker : public QObject { Q_OBJECT - Q_ENUMS(Wizard::Component) public: UnshieldWorker(QObject *parent = 0); diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index a6ca2e86d2..cbb63bf073 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -126,27 +126,30 @@ add_component_dir (version set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui ) -if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) - add_component_qt_dir (contentselector - model/modelitem model/esmfile - model/naturalsort model/contentmodel - model/loadordererror - view/combobox view/contentselector - ) - add_component_qt_dir (config - gamesettings - launchersettings - settingsbase - ) - - add_component_qt_dir (process - processinvoker +add_component_qt_dir (contentselector + model/modelitem model/esmfile + model/naturalsort model/contentmodel + model/loadordererror + view/combobox view/contentselector + ) +add_component_qt_dir (config + gamesettings + launchersettings + settingsbase ) - include(${QT_USE_FILE}) +add_component_qt_dir (process + processinvoker +) + +if (DESIRED_QT_VERSION MATCHES 4) + include(${QT_USE_FILE}) QT4_WRAP_UI(ESM_UI_HDR ${ESM_UI}) - QT4_WRAP_CPP(MOC_SRCS ${COMPONENT_MOC_FILES}) -endif(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) + QT4_WRAP_CPP(MOC_SRCS ${COMPONENT_MOC_FILES}) +else() + QT5_WRAP_UI(ESM_UI_HDR ${ESM_UI}) + QT5_WRAP_CPP(MOC_SRCS ${COMPONENT_MOC_FILES}) +endif() if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" AND NOT APPLE) @@ -166,11 +169,17 @@ target_link_libraries(components ${Boost_WAVE_LIBRARY} ${OGRE_LIBRARIES} ${OENGINE_LIBRARY} - ${QT_QTCORE_LIBRARY} - ${QT_QTGUI_LIBRARY} ${BULLET_LIBRARIES} ) +if (DESIRED_QT_VERSION MATCHES 4) + target_link_libraries(components + ${QT_QTCORE_LIBRARY} + ${QT_QTGUI_LIBRARY}) +else() + qt5_use_modules(components Widgets Core) +endif() + if (GIT_CHECKOUT) add_dependencies (components git-version) endif (GIT_CHECKOUT) From 89c2a7e26b402e27224d414dc4cf33e2653288a7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 12 Jun 2015 15:22:19 +0200 Subject: [PATCH 17/57] Fix for possibly missing library on windows --- apps/mwiniimporter/CMakeLists.txt | 5 +++++ components/CMakeLists.txt | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/apps/mwiniimporter/CMakeLists.txt b/apps/mwiniimporter/CMakeLists.txt index e522df6a18..4024c0b42a 100644 --- a/apps/mwiniimporter/CMakeLists.txt +++ b/apps/mwiniimporter/CMakeLists.txt @@ -19,6 +19,11 @@ target_link_libraries(openmw-iniimporter components ) +if (WIN32) + target_link_libraries(openmw-iniimporter + ${Boost_LOCALE_LIBRARY}) +endif() + if (MINGW) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -municode") endif() diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index cbb63bf073..1b33b10f6d 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -172,6 +172,11 @@ target_link_libraries(components ${BULLET_LIBRARIES} ) +if (WIN32) + target_link_libraries(components + ${Boost_LOCALE_LIBRARY}) +endif() + if (DESIRED_QT_VERSION MATCHES 4) target_link_libraries(components ${QT_QTCORE_LIBRARY} From eb5180ba8696f043cf91381728a36a86f41f9d44 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 18:33:55 +0300 Subject: [PATCH 18/57] Save selected color in a model when picking is finished --- apps/opencs/view/widget/coloreditor.cpp | 19 ++++------- apps/opencs/view/widget/coloreditor.hpp | 9 +++-- .../opencs/view/world/colorpickerdelegate.cpp | 33 ++++--------------- .../opencs/view/world/colorpickerdelegate.hpp | 9 ----- apps/opencs/view/world/dialoguesubview.cpp | 6 ++++ apps/opencs/view/world/util.cpp | 28 +++++++++++++--- 6 files changed, 45 insertions(+), 59 deletions(-) diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp index bab98fcd51..eaef0f6d34 100644 --- a/apps/opencs/view/widget/coloreditor.cpp +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -9,12 +9,9 @@ #include "colorpickerpopup.hpp" -CSVWidget::ColorEditor::ColorEditor(const QColor &color, - const QSize &coloredRectSize, - QWidget *parent) +CSVWidget::ColorEditor::ColorEditor(const QColor &color, QWidget *parent) : QPushButton(parent), mColor(color), - mColoredRectSize(coloredRectSize), mColorPicker(new ColorPickerPopup(this)) { setCheckable(true); @@ -28,10 +25,10 @@ void CSVWidget::ColorEditor::paintEvent(QPaintEvent *event) QPushButton::paintEvent(event); QRect buttonRect = rect(); - QRect coloredRect(buttonRect.x() + (buttonRect.width() - mColoredRectSize.width()) / 2, - buttonRect.y() + (buttonRect.height() - mColoredRectSize.height()) / 2, - mColoredRectSize.width(), - mColoredRectSize.height()); + QRect coloredRect(qRound(buttonRect.x() + buttonRect.width() / 4.0), + qRound(buttonRect.y() + buttonRect.height() / 4.0), + qRound(buttonRect.width() / 2.0), + qRound(buttonRect.height() / 2.0)); QPainter painter(this); painter.fillRect(coloredRect, mColor); } @@ -46,11 +43,6 @@ void CSVWidget::ColorEditor::setColor(const QColor &color) mColor = color; } -void CSVWidget::ColorEditor::setColoredRectSize(const QSize &size) -{ - mColoredRectSize = size; -} - void CSVWidget::ColorEditor::showPicker() { if (isChecked()) @@ -73,6 +65,7 @@ void CSVWidget::ColorEditor::pickerHid() { setChecked(false); } + emit pickingFinished(); } void CSVWidget::ColorEditor::pickerColorChanged(const QColor &color) diff --git a/apps/opencs/view/widget/coloreditor.hpp b/apps/opencs/view/widget/coloreditor.hpp index a0fa497b69..cca26fade1 100644 --- a/apps/opencs/view/widget/coloreditor.hpp +++ b/apps/opencs/view/widget/coloreditor.hpp @@ -16,19 +16,15 @@ namespace CSVWidget Q_OBJECT QColor mColor; - QSize mColoredRectSize; ColorPickerPopup *mColorPicker; QPoint calculatePopupPosition(); public: - ColorEditor(const QColor &color, - const QSize &coloredRectSize, - QWidget *parent = 0); + ColorEditor(const QColor &color, QWidget *parent = 0); QColor color() const; void setColor(const QColor &color); - void setColoredRectSize(const QSize &size); protected: void paintEvent(QPaintEvent *event); @@ -37,6 +33,9 @@ namespace CSVWidget void showPicker(); void pickerHid(); void pickerColorChanged(const QColor &color); + + signals: + void pickingFinished(); }; } diff --git a/apps/opencs/view/world/colorpickerdelegate.cpp b/apps/opencs/view/world/colorpickerdelegate.cpp index 4491f392cf..7490c07f59 100644 --- a/apps/opencs/view/world/colorpickerdelegate.cpp +++ b/apps/opencs/view/world/colorpickerdelegate.cpp @@ -11,41 +11,20 @@ CSVWorld::ColorPickerDelegate::ColorPickerDelegate(CSMWorld::CommandDispatcher * : CommandDelegate(dispatcher, document, parent) {} -QWidget *CSVWorld::ColorPickerDelegate::createEditor(QWidget *parent, - const QStyleOptionViewItem &option, - const QModelIndex &index) const -{ - return createEditor(parent, option, index, getDisplayTypeFromIndex(index)); -} - -QWidget *CSVWorld::ColorPickerDelegate::createEditor(QWidget *parent, - const QStyleOptionViewItem &option, - const QModelIndex &index, - CSMWorld::ColumnBase::Display display) const -{ - if (display != CSMWorld::ColumnBase::Display_Colour) - { - throw std::logic_error("Wrong column for ColorPickerDelegate"); - } - - return new CSVWidget::ColorEditor(index.data().value(), - getColoredRect(option).size(), - parent); -} - void CSVWorld::ColorPickerDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - painter->fillRect(getColoredRect(option), index.data().value()); + QRect coloredRect = getColoredRect(option); + painter->fillRect(coloredRect, index.data().value()); } QRect CSVWorld::ColorPickerDelegate::getColoredRect(const QStyleOptionViewItem &option) const { - return QRect(option.rect.x() + option.rect.width() / 4, - option.rect.y() + option.rect.height() / 4, - option.rect.width() / 2, - option.rect.height() / 2); + return QRect(qRound(option.rect.x() + option.rect.width() / 4.0), + qRound(option.rect.y() + option.rect.height() / 4.0), + qRound(option.rect.width() / 2.0), + qRound(option.rect.height() / 2.0)); } CSVWorld::CommandDelegate *CSVWorld::ColorPickerDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher, diff --git a/apps/opencs/view/world/colorpickerdelegate.hpp b/apps/opencs/view/world/colorpickerdelegate.hpp index 147c2f4243..f17923648a 100644 --- a/apps/opencs/view/world/colorpickerdelegate.hpp +++ b/apps/opencs/view/world/colorpickerdelegate.hpp @@ -21,15 +21,6 @@ namespace CSVWorld 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; - virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 66e8fcb7a2..541cf050fc 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -33,6 +33,8 @@ #include "../../model/world/commands.hpp" #include "../../model/doc/document.hpp" +#include "../widget/coloreditor.hpp" + #include "recordstatusdelegate.hpp" #include "util.hpp" #include "tablebottombox.hpp" @@ -331,6 +333,10 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase:: { connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); } + else if (qobject_cast(editor)) + { + connect(editor, SIGNAL(pickingFinished()), proxy, SLOT(editorDataCommited())); + } else // throw an exception because this is a coding error throw std::logic_error ("Dialogue editor type missing"); diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index e1d165a24f..de088bffc9 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -17,6 +17,7 @@ #include "../../model/world/commands.hpp" #include "../../model/world/tablemimedata.hpp" #include "../../model/world/commanddispatcher.hpp" +#include "../widget/coloreditor.hpp" #include "dialoguespinbox.hpp" #include "scriptedit.hpp" @@ -123,10 +124,19 @@ void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemM if (!mCommandDispatcher) return; - NastyTableModelHack hack (*model); - QStyledItemDelegate::setModelData (editor, &hack, index); - - QVariant new_ = hack.getData(); + QVariant new_; + // Color columns use a custom editor, so we need explicitly extract a data from it + CSVWidget::ColorEditor *colorEditor = qobject_cast(editor); + if (colorEditor != NULL) + { + new_ = colorEditor->color(); + } + else + { + NastyTableModelHack hack (*model); + QStyledItemDelegate::setModelData (editor, &hack, index); + new_ = hack.getData(); + } if ((model->data (index)!=new_) && (model->flags(index) & Qt::ItemIsEditable)) mCommandDispatcher->executeModify (model, index, new_); @@ -184,7 +194,7 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO { case CSMWorld::ColumnBase::Display_Colour: - return new QLineEdit(parent); + return new CSVWidget::ColorEditor(index.data().value(), parent); case CSMWorld::ColumnBase::Display_Integer: { @@ -284,6 +294,14 @@ void CSVWorld::CommandDelegate::setEditorData (QWidget *editor, const QModelInde } } + // Color columns use a custom editor, so we need explicitly set a data for it + CSVWidget::ColorEditor *colorEditor = qobject_cast(editor); + if (colorEditor != NULL) + { + colorEditor->setColor(index.data().value()); + return; + } + QByteArray n = editor->metaObject()->userProperty().name(); if (n == "dateTime") { From caeba1b8878a91504ac39ceba9eff2d96b6ff1ba Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 20:34:35 +0300 Subject: [PATCH 19/57] Draw the frame around rect in ColorEditor and ColorPickerDelegate --- apps/opencs/view/widget/coloreditor.cpp | 2 ++ apps/opencs/view/world/colorpickerdelegate.cpp | 17 ++++++++--------- apps/opencs/view/world/colorpickerdelegate.hpp | 2 -- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp index eaef0f6d34..e6e3264bee 100644 --- a/apps/opencs/view/widget/coloreditor.cpp +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -31,6 +31,8 @@ void CSVWidget::ColorEditor::paintEvent(QPaintEvent *event) qRound(buttonRect.height() / 2.0)); QPainter painter(this); painter.fillRect(coloredRect, mColor); + painter.setPen(Qt::black); + painter.drawRect(coloredRect); } QColor CSVWidget::ColorEditor::color() const diff --git a/apps/opencs/view/world/colorpickerdelegate.cpp b/apps/opencs/view/world/colorpickerdelegate.cpp index 7490c07f59..4feaa170e3 100644 --- a/apps/opencs/view/world/colorpickerdelegate.cpp +++ b/apps/opencs/view/world/colorpickerdelegate.cpp @@ -15,16 +15,15 @@ void CSVWorld::ColorPickerDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - QRect coloredRect = getColoredRect(option); + QRect coloredRect(qRound(option.rect.x() + option.rect.width() / 4.0), + qRound(option.rect.y() + option.rect.height() / 4.0), + qRound(option.rect.width() / 2.0), + qRound(option.rect.height() / 2.0)); + painter->save(); painter->fillRect(coloredRect, index.data().value()); -} - -QRect CSVWorld::ColorPickerDelegate::getColoredRect(const QStyleOptionViewItem &option) const -{ - return QRect(qRound(option.rect.x() + option.rect.width() / 4.0), - qRound(option.rect.y() + option.rect.height() / 4.0), - qRound(option.rect.width() / 2.0), - qRound(option.rect.height() / 2.0)); + painter->setPen(Qt::black); + painter->drawRect(coloredRect); + painter->restore(); } CSVWorld::CommandDelegate *CSVWorld::ColorPickerDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher, diff --git a/apps/opencs/view/world/colorpickerdelegate.hpp b/apps/opencs/view/world/colorpickerdelegate.hpp index f17923648a..a8e6d87fca 100644 --- a/apps/opencs/view/world/colorpickerdelegate.hpp +++ b/apps/opencs/view/world/colorpickerdelegate.hpp @@ -14,8 +14,6 @@ namespace CSVWorld { class ColorPickerDelegate : public CommandDelegate { - QRect getColoredRect(const QStyleOptionViewItem &option) const; - public: ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, From e516d37cbf22e047cca941c2be7f48deab75dccd Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 22:03:47 +0300 Subject: [PATCH 20/57] MapColourColumn::set() uses the correct color value --- apps/opencs/model/world/columnimp.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 8758d924b0..a8ae5dfa12 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -694,7 +694,7 @@ namespace CSMWorld QColor colour = data.value(); - record2.mMapColor = colour.rgb() & 0xffffff; + record2.mMapColor = (colour.blue() << 16) | (colour.green() << 8) | colour.red(); record.setModified (record2); } From 650e37dba1cf8feb922eda3b16c93048ddc8297b Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 22:31:12 +0300 Subject: [PATCH 21/57] RegionMap uses proper colors --- apps/opencs/model/world/regionmap.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/regionmap.cpp b/apps/opencs/model/world/regionmap.cpp index f63426c04a..42bde9c81a 100644 --- a/apps/opencs/model/world/regionmap.cpp +++ b/apps/opencs/model/world/regionmap.cpp @@ -334,9 +334,9 @@ QVariant CSMWorld::RegionMap::data (const QModelIndex& index, int role) const mColours.find (Misc::StringUtils::lowerCase (cell->second.mRegion)); if (iter!=mColours.end()) - return QBrush ( - QColor (iter->second>>24, (iter->second>>16) & 255, (iter->second>>8) & 255, - iter->second & 255)); + return QBrush (QColor (iter->second & 0xff, + (iter->second >> 8) & 0xff, + (iter->second >> 16) & 0xff)); if (cell->second.mRegion.empty()) return QBrush (Qt::Dense6Pattern); // no region From f19d07b4047daad44c7add15784659c167c1531e Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 23:09:31 +0300 Subject: [PATCH 22/57] Rename ColorPickerDelegate to ColorDelegate --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/doc/viewmanager.cpp | 4 +-- apps/opencs/view/world/colordelegate.cpp | 36 +++++++++++++++++++ ...orpickerdelegate.hpp => colordelegate.hpp} | 14 ++++---- .../opencs/view/world/colorpickerdelegate.cpp | 36 ------------------- 5 files changed, 46 insertions(+), 46 deletions(-) create mode 100644 apps/opencs/view/world/colordelegate.cpp rename apps/opencs/view/world/{colorpickerdelegate.hpp => colordelegate.hpp} (64%) delete mode 100644 apps/opencs/view/world/colorpickerdelegate.cpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 83a20ecaa1..88edf7bb1c 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -70,7 +70,7 @@ opencs_units (view/world opencs_units_noqt (view/world subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate scripthighlighter idvalidator dialoguecreator physicssystem idcompletiondelegate - colorpickerdelegate + colordelegate ) opencs_units (view/widget diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index e5bb7fe811..9699148512 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -19,7 +19,7 @@ #include "../world/recordstatusdelegate.hpp" #include "../world/idtypedelegate.hpp" #include "../world/idcompletiondelegate.hpp" -#include "../world/colorpickerdelegate.hpp" +#include "../world/colordelegate.hpp" #include "../../model/settings/usersettings.hpp" @@ -65,7 +65,7 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) new CSVWorld::IdTypeDelegateFactory()); mDelegateFactories->add (CSMWorld::ColumnBase::Display_Colour, - new CSVWorld::ColorPickerDelegateFactory()); + new CSVWorld::ColorDelegateFactory()); std::vector idCompletionColumns = CSMWorld::IdCompletionManager::getDisplayTypes(); for (std::vector::const_iterator current = idCompletionColumns.begin(); diff --git a/apps/opencs/view/world/colordelegate.cpp b/apps/opencs/view/world/colordelegate.cpp new file mode 100644 index 0000000000..ae71f965a7 --- /dev/null +++ b/apps/opencs/view/world/colordelegate.cpp @@ -0,0 +1,36 @@ +#include "colordelegate.hpp" + +#include +#include + +#include "../widget/coloreditor.hpp" + +CSVWorld::ColorDelegate::ColorDelegate(CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document& document, + QObject *parent) + : CommandDelegate(dispatcher, document, parent) +{} + +void CSVWorld::ColorDelegate::paint(QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + QRect coloredRect(qRound(option.rect.x() + option.rect.width() / 4.0), + qRound(option.rect.y() + option.rect.height() / 4.0), + qRound(option.rect.width() / 2.0), + qRound(option.rect.height() / 2.0)); + painter->save(); + painter->fillRect(coloredRect, index.data().value()); + painter->setPen(Qt::black); + painter->drawRect(coloredRect); + painter->restore(); +} + +CSVWorld::CommandDelegate *CSVWorld::ColorDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document &document, + QObject *parent) const +{ + return new ColorDelegate(dispatcher, document, parent); +} + + diff --git a/apps/opencs/view/world/colorpickerdelegate.hpp b/apps/opencs/view/world/colordelegate.hpp similarity index 64% rename from apps/opencs/view/world/colorpickerdelegate.hpp rename to apps/opencs/view/world/colordelegate.hpp index a8e6d87fca..87051e86d8 100644 --- a/apps/opencs/view/world/colorpickerdelegate.hpp +++ b/apps/opencs/view/world/colordelegate.hpp @@ -1,5 +1,5 @@ -#ifndef CSV_WORLD_COLORPICKERDELEGATE_HPP -#define CSV_WORLD_COLORPICKERDELEGATE_HPP +#ifndef CSV_WORLD_COLORDELEGATE_HPP +#define CSV_WORLD_COLORDELEGATE_HPP #include "util.hpp" @@ -12,19 +12,19 @@ namespace CSVWidget namespace CSVWorld { - class ColorPickerDelegate : public CommandDelegate + class ColorDelegate : public CommandDelegate { public: - ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, - CSMDoc::Document& document, - QObject *parent); + ColorDelegate(CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document& document, + QObject *parent); virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; - class ColorPickerDelegateFactory : public CommandDelegateFactory + class ColorDelegateFactory : public CommandDelegateFactory { public: virtual CommandDelegate *makeDelegate(CSMWorld::CommandDispatcher *dispatcher, diff --git a/apps/opencs/view/world/colorpickerdelegate.cpp b/apps/opencs/view/world/colorpickerdelegate.cpp deleted file mode 100644 index 4feaa170e3..0000000000 --- a/apps/opencs/view/world/colorpickerdelegate.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "colorpickerdelegate.hpp" - -#include -#include - -#include "../widget/coloreditor.hpp" - -CSVWorld::ColorPickerDelegate::ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, - CSMDoc::Document& document, - QObject *parent) - : CommandDelegate(dispatcher, document, parent) -{} - -void CSVWorld::ColorPickerDelegate::paint(QPainter *painter, - const QStyleOptionViewItem &option, - const QModelIndex &index) const -{ - QRect coloredRect(qRound(option.rect.x() + option.rect.width() / 4.0), - qRound(option.rect.y() + option.rect.height() / 4.0), - qRound(option.rect.width() / 2.0), - qRound(option.rect.height() / 2.0)); - painter->save(); - painter->fillRect(coloredRect, index.data().value()); - painter->setPen(Qt::black); - painter->drawRect(coloredRect); - painter->restore(); -} - -CSVWorld::CommandDelegate *CSVWorld::ColorPickerDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher, - CSMDoc::Document &document, - QObject *parent) const -{ - return new ColorPickerDelegate(dispatcher, document, parent); -} - - From b06d1f008f0aed4a6152ef7d0b28a99ad6c5b7eb Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 23:34:08 +0300 Subject: [PATCH 23/57] Redraw the color editor immediately after the color is updated --- apps/opencs/view/widget/coloreditor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp index e6e3264bee..f06187992c 100644 --- a/apps/opencs/view/widget/coloreditor.cpp +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -43,6 +43,7 @@ QColor CSVWidget::ColorEditor::color() const void CSVWidget::ColorEditor::setColor(const QColor &color) { mColor = color; + update(); } void CSVWidget::ColorEditor::showPicker() From a294e24a85672ee7c31c9d08f22d7aab6a4f6902 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 13 Jun 2015 00:37:10 +0300 Subject: [PATCH 24/57] Reset ColorEditor checked state after the popup is hidden --- apps/opencs/view/widget/coloreditor.cpp | 9 +------- apps/opencs/view/widget/colorpickerpopup.cpp | 23 ++++++++++++++++++++ apps/opencs/view/widget/colorpickerpopup.hpp | 1 + 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp index f06187992c..b31225962b 100644 --- a/apps/opencs/view/widget/coloreditor.cpp +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -60,14 +60,7 @@ void CSVWidget::ColorEditor::showPicker() void CSVWidget::ColorEditor::pickerHid() { - // If the popup is hidden and mouse isn't above the editor, - // reset the editor checked state manually - QPoint globalEditorPosition = mapToGlobal(QPoint(0, 0)); - QRect globalEditorRect(globalEditorPosition, geometry().size()); - if (!globalEditorRect.contains(QCursor::pos())) - { - setChecked(false); - } + setChecked(false); emit pickingFinished(); } diff --git a/apps/opencs/view/widget/colorpickerpopup.cpp b/apps/opencs/view/widget/colorpickerpopup.cpp index dd53f1becc..8e71ce39e4 100644 --- a/apps/opencs/view/widget/colorpickerpopup.cpp +++ b/apps/opencs/view/widget/colorpickerpopup.cpp @@ -1,9 +1,12 @@ #include "colorpickerpopup.hpp" #include +#include #include #include +#include #include +#include CSVWidget::ColorPickerPopup::ColorPickerPopup(QWidget *parent) : QFrame(parent) @@ -40,6 +43,26 @@ void CSVWidget::ColorPickerPopup::showPicker(const QPoint &position, const QColo show(); } +void CSVWidget::ColorPickerPopup::mousePressEvent(QMouseEvent *event) +{ + QPushButton *button = qobject_cast(parentWidget()); + if (button != NULL) + { + QStyleOptionButton option; + option.init(button); + QRect buttonRect = option.rect; + buttonRect.moveTo(button->mapToGlobal(buttonRect.topLeft())); + + // If the mouse is pressed above the pop-up parent, + // the pop-up will be hidden and the pressed signal won't be repeated for the parent + if (buttonRect.contains(event->globalPos()) || buttonRect.contains(event->pos())) + { + setAttribute(Qt::WA_NoMouseReplay); + } + } + QFrame::mousePressEvent(event); +} + void CSVWidget::ColorPickerPopup::hideEvent(QHideEvent *event) { QFrame::hideEvent(event); diff --git a/apps/opencs/view/widget/colorpickerpopup.hpp b/apps/opencs/view/widget/colorpickerpopup.hpp index a7aec3bad6..602bbdb6da 100644 --- a/apps/opencs/view/widget/colorpickerpopup.hpp +++ b/apps/opencs/view/widget/colorpickerpopup.hpp @@ -19,6 +19,7 @@ namespace CSVWidget void showPicker(const QPoint &position, const QColor &initialColor); protected: + virtual void mousePressEvent(QMouseEvent *event); virtual void hideEvent(QHideEvent *event); virtual bool eventFilter(QObject *object, QEvent *event); From b81454d226c2ea919b2a48eb6482f7b5553bd5a0 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 13 Jun 2015 14:37:47 +1000 Subject: [PATCH 25/57] Fix using wrong bit flag for NPC stats auto-calculation. Also set the corresponding mNpdtType which is used when determining which data structure to save. Should resolve Bug #2668. --- apps/esmtool/labels.cpp | 24 +++++++++---------- .../opencs/model/tools/referenceablecheck.cpp | 2 +- apps/opencs/model/world/refidadapterimp.cpp | 4 ++++ components/esm/loadnpc.hpp | 12 +++++----- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/apps/esmtool/labels.cpp b/apps/esmtool/labels.cpp index 88e188df01..883a9e7280 100644 --- a/apps/esmtool/labels.cpp +++ b/apps/esmtool/labels.cpp @@ -119,7 +119,7 @@ std::string clothingTypeLabel(int idx) } std::string armorTypeLabel(int idx) -{ +{ if (idx >= 0 && idx <= 10) { static const char *armorTypeLabels[] = { @@ -645,7 +645,7 @@ std::string ruleFunction(int idx) else return "Invalid"; } - + // The "unused flag bits" should probably be defined alongside the // defined bits in the ESM component. The names of the flag bits are // very inconsistent. @@ -653,7 +653,7 @@ std::string ruleFunction(int idx) std::string bodyPartFlags(int flags) { std::string properties = ""; - if (flags == 0) properties += "[None] "; + if (flags == 0) properties += "[None] "; if (flags & ESM::BodyPart::BPF_Female) properties += "Female "; if (flags & ESM::BodyPart::BPF_NotPlayable) properties += "NotPlayable "; int unused = (0xFFFFFFFF ^ @@ -667,7 +667,7 @@ std::string bodyPartFlags(int flags) std::string cellFlags(int flags) { std::string properties = ""; - if (flags == 0) properties += "[None] "; + if (flags == 0) properties += "[None] "; if (flags & ESM::Cell::HasWater) properties += "HasWater "; if (flags & ESM::Cell::Interior) properties += "Interior "; if (flags & ESM::Cell::NoSleep) properties += "NoSleep "; @@ -830,12 +830,12 @@ std::string npcFlags(int flags) std::string properties = ""; if (flags == 0) properties += "[None] "; // Mythicmods and the ESM component differ. Mythicmods says - // 0x8=None and 0x10=AutoCalc, while our code defines 0x8 as - // AutoCalc. The former seems to be correct. All Bethesda - // records have bit 0x8 set. A suspiciously large portion of - // females have autocalc turned off. - if (flags & ESM::NPC::Autocalc) properties += "Unknown "; - if (flags & 0x00000010) properties += "Autocalc "; + // 0x8=None and 0x10=AutoCalc, while our code previously defined + // 0x8 as AutoCalc. The former seems to be correct. All Bethesda + // records have bit 0x8 set. Previously, suspiciously large portion + // of females had autocalc turned off. + if (flags & 0x00000008) properties += "Unknown "; + if (flags & ESM::NPC::Autocalc) properties += "Autocalc "; if (flags & ESM::NPC::Female) properties += "Female "; if (flags & ESM::NPC::Respawn) properties += "Respawn "; if (flags & ESM::NPC::Essential) properties += "Essential "; @@ -847,8 +847,8 @@ std::string npcFlags(int flags) // however the only unknown bit occurs on ALL records, and // relatively few NPCs have this bit set. int unused = (0xFFFFFFFF ^ - (ESM::NPC::Autocalc| - 0x00000010| + (0x00000008| + ESM::NPC::Autocalc| ESM::NPC::Female| ESM::NPC::Respawn| ESM::NPC::Essential| diff --git a/apps/opencs/model/tools/referenceablecheck.cpp b/apps/opencs/model/tools/referenceablecheck.cpp index 548fcd36f6..6b323547f0 100644 --- a/apps/opencs/model/tools/referenceablecheck.cpp +++ b/apps/opencs/model/tools/referenceablecheck.cpp @@ -648,7 +648,7 @@ void CSMTools::ReferenceableCheckStage::npcCheck ( if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated { - if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0008 = autocalculated flag + if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0010 = autocalculated flag { messages.push_back (std::make_pair (id, npc.mId + " mNpdtType or flags mismatch!")); //should not happend? return; diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index d31a9ceaae..cb71319c87 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -546,6 +546,10 @@ void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& d record.get().mFlags |= iter->second; else record.get().mFlags &= ~iter->second; + + if (iter->second == ESM::NPC::Autocalc) + record.get().mNpdtType = (value.toInt() != 0) ? ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS + : ESM::NPC::NPC_DEFAULT; } else ActorRefIdAdapter::setData (column, data, index, value); diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index b535b91b01..281020c981 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -52,12 +52,12 @@ struct NPC enum Flags { - Female = 0x0001, - Essential = 0x0002, - Respawn = 0x0004, - Autocalc = 0x0008, - Skeleton = 0x0400, // Skeleton blood effect (white) - Metal = 0x0800 // Metal blood effect (golden?) + Female = 0x0001, + Essential = 0x0002, + Respawn = 0x0004, + Autocalc = 0x0010, + Skeleton = 0x0400, // Skeleton blood effect (white) + Metal = 0x0800 // Metal blood effect (golden?) }; enum NpcType From 5b6984d8d844c812c16776298be6eab05a2e0615 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 13 Jun 2015 22:24:22 +1000 Subject: [PATCH 26/57] Set modified flag in setData() operations, without which the changes weren't being saved. Should resolve Bug #2656. --- apps/opencs/model/world/refidadapterimp.cpp | 169 +++++++++++++++----- 1 file changed, 128 insertions(+), 41 deletions(-) diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index cb71319c87..4c369ef24f 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -37,10 +37,18 @@ void CSMWorld::PotionRefIdAdapter::setData (const RefIdColumn *column, RefIdData Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Potion))); + ESM::Potion potion = record.get(); + if (column==mAutoCalc) - record.get().mData.mAutoCalc = value.toInt(); + potion.mData.mAutoCalc = value.toInt(); else + { InventoryRefIdAdapter::setData (column, data, index, value); + + return; + } + + record.setModified(potion); } @@ -71,12 +79,19 @@ void CSMWorld::ApparatusRefIdAdapter::setData (const RefIdColumn *column, RefIdD Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Apparatus))); + ESM::Apparatus apparatus = record.get(); + if (column==mType) - record.get().mData.mType = value.toInt(); + apparatus.mData.mType = value.toInt(); else if (column==mQuality) - record.get().mData.mQuality = value.toFloat(); + apparatus.mData.mQuality = value.toFloat(); else + { InventoryRefIdAdapter::setData (column, data, index, value); + + return; + } + record.setModified(apparatus); } @@ -114,14 +129,22 @@ void CSMWorld::ArmorRefIdAdapter::setData (const RefIdColumn *column, RefIdData& Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Armor))); + ESM::Armor armor = record.get(); + if (column==mType) - record.get().mData.mType = value.toInt(); + armor.mData.mType = value.toInt(); else if (column==mHealth) - record.get().mData.mHealth = value.toInt(); + armor.mData.mHealth = value.toInt(); else if (column==mArmor) - record.get().mData.mArmor = value.toInt(); + armor.mData.mArmor = value.toInt(); else + { EnchantableRefIdAdapter::setData (column, data, index, value); + + return; + } + + record.setModified(armor); } CSMWorld::BookRefIdAdapter::BookRefIdAdapter (const EnchantableColumns& columns, @@ -151,12 +174,20 @@ void CSMWorld::BookRefIdAdapter::setData (const RefIdColumn *column, RefIdData& Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Book))); + ESM::Book book = record.get(); + if (column==mScroll) - record.get().mData.mIsScroll = value.toInt(); + book.mData.mIsScroll = value.toInt(); else if (column==mSkill) - record.get().mData.mSkillID = value.toInt(); + book.mData.mSkillID = value.toInt(); else + { EnchantableRefIdAdapter::setData (column, data, index, value); + + return; + } + + record.setModified(book); } CSMWorld::ClothingRefIdAdapter::ClothingRefIdAdapter (const EnchantableColumns& columns, @@ -186,10 +217,18 @@ void CSMWorld::ClothingRefIdAdapter::setData (const RefIdColumn *column, RefIdDa Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Clothing))); + ESM::Clothing clothing = record.get(); + if (column==mType) - record.get().mData.mType = value.toInt(); + clothing.mData.mType = value.toInt(); else + { EnchantableRefIdAdapter::setData (column, data, index, value); + + return; + } + + record.setModified(clothing); } CSMWorld::ContainerRefIdAdapter::ContainerRefIdAdapter (const NameColumns& columns, @@ -226,24 +265,32 @@ void CSMWorld::ContainerRefIdAdapter::setData (const RefIdColumn *column, RefIdD Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container))); + ESM::Container container = record.get(); + if (column==mWeight) - record.get().mWeight = value.toFloat(); + container.mWeight = value.toFloat(); else if (column==mOrganic) { if (value.toInt()) - record.get().mFlags |= ESM::Container::Organic; + container.mFlags |= ESM::Container::Organic; else - record.get().mFlags &= ~ESM::Container::Organic; + container.mFlags &= ~ESM::Container::Organic; } else if (column==mRespawn) { if (value.toInt()) - record.get().mFlags |= ESM::Container::Respawn; + container.mFlags |= ESM::Container::Respawn; else - record.get().mFlags &= ~ESM::Container::Respawn; + container.mFlags &= ~ESM::Container::Respawn; } else + { NameRefIdAdapter::setData (column, data, index, value); + + return; + } + + record.setModified(container); } CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns) @@ -303,20 +350,22 @@ void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdDa Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature))); + ESM::Creature creature = record.get(); + if (column==mColumns.mType) - record.get().mData.mType = value.toInt(); + creature.mData.mType = value.toInt(); else if (column==mColumns.mSoul) - record.get().mData.mSoul = value.toInt(); + creature.mData.mSoul = value.toInt(); else if (column==mColumns.mScale) - record.get().mScale = value.toFloat(); + creature.mScale = value.toFloat(); else if (column==mColumns.mOriginal) - record.get().mOriginal = value.toString().toUtf8().constData(); + creature.mOriginal = value.toString().toUtf8().constData(); else if (column==mColumns.mCombat) - record.get().mData.mCombat = value.toInt(); + creature.mData.mCombat = value.toInt(); else if (column==mColumns.mMagic) - record.get().mData.mMagic = value.toInt(); + creature.mData.mMagic = value.toInt(); else if (column==mColumns.mStealth) - record.get().mData.mStealth = value.toInt(); + creature.mData.mStealth = value.toInt(); else { std::map::const_iterator iter = @@ -325,13 +374,19 @@ void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdDa if (iter!=mColumns.mFlags.end()) { if (value.toInt()!=0) - record.get().mFlags |= iter->second; + creature.mFlags |= iter->second; else - record.get().mFlags &= ~iter->second; + creature.mFlags &= ~iter->second; } else + { ActorRefIdAdapter::setData (column, data, index, value); + + return; + } } + + record.setModified(creature); } CSMWorld::DoorRefIdAdapter::DoorRefIdAdapter (const NameColumns& columns, @@ -361,12 +416,20 @@ void CSMWorld::DoorRefIdAdapter::setData (const RefIdColumn *column, RefIdData& Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Door))); + ESM::Door door = record.get(); + if (column==mOpenSound) - record.get().mOpenSound = value.toString().toUtf8().constData(); + door.mOpenSound = value.toString().toUtf8().constData(); else if (column==mCloseSound) - record.get().mCloseSound = value.toString().toUtf8().constData(); + door.mCloseSound = value.toString().toUtf8().constData(); else + { NameRefIdAdapter::setData (column, data, index, value); + + return; + } + + record.setModified(door); } CSMWorld::LightColumns::LightColumns (const InventoryColumns& columns) @@ -409,14 +472,16 @@ void CSMWorld::LightRefIdAdapter::setData (const RefIdColumn *column, RefIdData& Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Light))); + ESM::Light light = record.get(); + if (column==mColumns.mTime) - record.get().mData.mTime = value.toInt(); + light.mData.mTime = value.toInt(); else if (column==mColumns.mRadius) - record.get().mData.mRadius = value.toInt(); + light.mData.mRadius = value.toInt(); else if (column==mColumns.mColor) - record.get().mData.mColor = value.toInt(); + light.mData.mColor = value.toInt(); else if (column==mColumns.mSound) - record.get().mSound = value.toString().toUtf8().constData(); + light.mSound = value.toString().toUtf8().constData(); else { std::map::const_iterator iter = @@ -425,13 +490,19 @@ void CSMWorld::LightRefIdAdapter::setData (const RefIdColumn *column, RefIdData& if (iter!=mColumns.mFlags.end()) { if (value.toInt()!=0) - record.get().mData.mFlags |= iter->second; + light.mData.mFlags |= iter->second; else - record.get().mData.mFlags &= ~iter->second; + light.mData.mFlags &= ~iter->second; } else + { InventoryRefIdAdapter::setData (column, data, index, value); + + return; + } } + + record.setModified (light); } CSMWorld::MiscRefIdAdapter::MiscRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *key) @@ -456,10 +527,18 @@ void CSMWorld::MiscRefIdAdapter::setData (const RefIdColumn *column, RefIdData& Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Miscellaneous))); + ESM::Miscellaneous misc = record.get(); + if (column==mKey) - record.get().mData.mIsKey = value.toInt(); + misc.mData.mIsKey = value.toInt(); else + { InventoryRefIdAdapter::setData (column, data, index, value); + + return; + } + + record.setModified(misc); } CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns) @@ -525,16 +604,18 @@ void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& d Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); + ESM::NPC npc = record.get(); + if (column==mColumns.mRace) - record.get().mRace = value.toString().toUtf8().constData(); + npc.mRace = value.toString().toUtf8().constData(); else if (column==mColumns.mClass) - record.get().mClass = value.toString().toUtf8().constData(); + npc.mClass = value.toString().toUtf8().constData(); else if (column==mColumns.mFaction) - record.get().mFaction = value.toString().toUtf8().constData(); + npc.mFaction = value.toString().toUtf8().constData(); else if (column==mColumns.mHair) - record.get().mHair = value.toString().toUtf8().constData(); + npc.mHair = value.toString().toUtf8().constData(); else if (column==mColumns.mHead) - record.get().mHead = value.toString().toUtf8().constData(); + npc.mHead = value.toString().toUtf8().constData(); else { std::map::const_iterator iter = @@ -543,17 +624,23 @@ void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& d if (iter!=mColumns.mFlags.end()) { if (value.toInt()!=0) - record.get().mFlags |= iter->second; + npc.mFlags |= iter->second; else - record.get().mFlags &= ~iter->second; + npc.mFlags &= ~iter->second; if (iter->second == ESM::NPC::Autocalc) - record.get().mNpdtType = (value.toInt() != 0) ? ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS - : ESM::NPC::NPC_DEFAULT; + npc.mNpdtType = (value.toInt() != 0) ? ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS + : ESM::NPC::NPC_DEFAULT; } else + { ActorRefIdAdapter::setData (column, data, index, value); + + return; + } } + + record.setModified (npc); } CSMWorld::NpcAttributesRefIdAdapter::NpcAttributesRefIdAdapter () From 2c15ad5e0cae0a5b211ba59aed38a5810cc643e1 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 13 Jun 2015 19:08:31 +0300 Subject: [PATCH 27/57] Add SoundGens verifier --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/tools/soundgencheck.cpp | 49 +++++++++++++++++++++++ apps/opencs/model/tools/soundgencheck.hpp | 30 ++++++++++++++ apps/opencs/model/tools/tools.cpp | 5 +++ 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/model/tools/soundgencheck.cpp create mode 100644 apps/opencs/model/tools/soundgencheck.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 402bd335ab..6a9318319c 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -41,7 +41,7 @@ opencs_units (model/tools opencs_units_noqt (model/tools mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck - startscriptcheck search searchoperation searchstage pathgridcheck + startscriptcheck search searchoperation searchstage pathgridcheck soundgencheck ) diff --git a/apps/opencs/model/tools/soundgencheck.cpp b/apps/opencs/model/tools/soundgencheck.cpp new file mode 100644 index 0000000000..68e5edefd3 --- /dev/null +++ b/apps/opencs/model/tools/soundgencheck.cpp @@ -0,0 +1,49 @@ +#include "soundgencheck.hpp" + +#include + +#include "../world/refiddata.hpp" +#include "../world/universalid.hpp" + +CSMTools::SoundGenCheckStage::SoundGenCheckStage(const CSMWorld::IdCollection &soundGens, + const CSMWorld::IdCollection &sounds, + const CSMWorld::RefIdCollection &referenceables) + : mSoundGens(soundGens), + mSounds(sounds), + mReferenceables(referenceables) +{} + +int CSMTools::SoundGenCheckStage::setup() +{ + return mSoundGens.getSize(); +} + +void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages &messages) +{ + const CSMWorld::Record &record = mSoundGens.getRecord(stage); + if (record.isDeleted()) + { + return; + } + + const ESM::SoundGenerator soundGen = record.get(); + CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_SoundGen, soundGen.mId); + + if (soundGen.mCreature != "") + { + CSMWorld::RefIdData::LocalIndex creatureIndex = mReferenceables.getDataSet().searchId(soundGen.mCreature); + if (creatureIndex.first == -1) + { + messages.push_back(std::make_pair(id, "No such creature '" + soundGen.mCreature + "'")); + } + else if (creatureIndex.second != CSMWorld::UniversalId::Type_Creature) + { + messages.push_back(std::make_pair(id, "'" + soundGen.mCreature + "' is not a creature")); + } + } + + if (mSounds.searchId(soundGen.mSound) == -1) + { + messages.push_back(std::make_pair(id, "No such sound '" + soundGen.mSound + "'")); + } +} diff --git a/apps/opencs/model/tools/soundgencheck.hpp b/apps/opencs/model/tools/soundgencheck.hpp new file mode 100644 index 0000000000..91b08f979e --- /dev/null +++ b/apps/opencs/model/tools/soundgencheck.hpp @@ -0,0 +1,30 @@ +#ifndef CSM_TOOLS_SOUNDGENCHECK_HPP +#define CSM_TOOLS_SOUNDGENCHECK_HPP + +#include "../world/data.hpp" + +#include "../doc/stage.hpp" + +namespace CSMTools +{ + /// \brief VerifyStage: make sure that sound gen records are internally consistent + class SoundGenCheckStage : public CSMDoc::Stage + { + const CSMWorld::IdCollection &mSoundGens; + const CSMWorld::IdCollection &mSounds; + const CSMWorld::RefIdCollection &mReferenceables; + + public: + SoundGenCheckStage(const CSMWorld::IdCollection &soundGens, + const CSMWorld::IdCollection &sounds, + const CSMWorld::RefIdCollection &referenceables); + + virtual int setup(); + ///< \return number of steps + + virtual void perform(int stage, CSMDoc::Messages &messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 8d93a94332..7d70abae56 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -27,6 +27,7 @@ #include "startscriptcheck.hpp" #include "searchoperation.hpp" #include "pathgridcheck.hpp" +#include "soundgencheck.hpp" CSMDoc::OperationHolder *CSMTools::Tools::get (int type) { @@ -99,6 +100,10 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() mVerifierOperation->appendStage (new PathgridCheckStage (mData.getPathgrids())); + mVerifierOperation->appendStage (new SoundGenCheckStage (mData.getSoundGens(), + mData.getSounds(), + mData.getReferenceables())); + mVerifier.setOperation (mVerifierOperation); } From 281088c93b5325b8726c4ca990ffed3d67819e70 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 13 Jun 2015 19:47:39 +0300 Subject: [PATCH 28/57] Add check for an empty sound field to SoundGens verifier --- apps/opencs/model/tools/soundgencheck.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/tools/soundgencheck.cpp b/apps/opencs/model/tools/soundgencheck.cpp index 68e5edefd3..bdf89f19d2 100644 --- a/apps/opencs/model/tools/soundgencheck.cpp +++ b/apps/opencs/model/tools/soundgencheck.cpp @@ -29,7 +29,7 @@ void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages &messages const ESM::SoundGenerator soundGen = record.get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_SoundGen, soundGen.mId); - if (soundGen.mCreature != "") + if (!soundGen.mCreature.empty()) { CSMWorld::RefIdData::LocalIndex creatureIndex = mReferenceables.getDataSet().searchId(soundGen.mCreature); if (creatureIndex.first == -1) @@ -42,7 +42,11 @@ void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages &messages } } - if (mSounds.searchId(soundGen.mSound) == -1) + if (soundGen.mSound.empty()) + { + messages.push_back(std::make_pair(id, "Sound is not specified")); + } + else if (mSounds.searchId(soundGen.mSound) == -1) { messages.push_back(std::make_pair(id, "No such sound '" + soundGen.mSound + "'")); } From b7cd62e4dee69a6496b8b8f609f83d115a46ac62 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 13 Jun 2015 23:49:27 +0200 Subject: [PATCH 29/57] Revert "Remove user preference setting option." This reverts commit d3b7cf44d391ba9624f28070e68784352e6f514d. --- apps/launcher/maindialog.cpp | 22 +++++++++++++++++++--- apps/launcher/settingspage.cpp | 8 ++++++++ files/ui/settingspage.ui | 10 ++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 2f7a9db332..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::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")); @@ -503,8 +512,16 @@ 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 @@ -523,7 +540,6 @@ 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 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/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 3bfe167bc09353fd28c7f729b5d9174819bd4b8a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 13 Jun 2015 23:49:29 +0200 Subject: [PATCH 30/57] Revert "Fix loop where there was a potential for double entry." This reverts commit a439f49c4db32a340826ae9b77c940ca59e79e5f. --- components/config/gamesettings.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index 9af6c97143..c17a5c4f73 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -265,10 +265,7 @@ 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 c54a225467c6e7753dac8bafe6da26b04a8646d5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 13 Jun 2015 23:49:29 +0200 Subject: [PATCH 31/57] Revert "Allow space characters in front of comments." This reverts commit 4902c6679210dee8b5158d05d99b072c2f06a494. --- components/config/gamesettings.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index c17a5c4f73..c0a3b82d1c 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 (TODO: maybe replace the line with '#' in front instead?) +// - else remove line (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).contains(QRegExp("^\\s*#"))) + if ((*iter).isEmpty() || (*iter).startsWith("#")) continue; // look for a key in the line @@ -257,14 +257,12 @@ 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; - // 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*#"))) + if ((*iter).isEmpty() || (*iter).startsWith("#")) stream << *iter << "\n"; if (settingRegex.indexIn(*iter) == -1 || settingRegex.captureCount() < 2) From de98d991b40fdb54d808521a0ba4c39c44491467 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 13 Jun 2015 23:50:04 +0200 Subject: [PATCH 32/57] Revert "Allow comments (lines starting with # character) and blank lines in openmw.cfg. Should resolve Feature #2535." Breaks the saving of content= entry order. This reverts commit 15fe5d88e2b3c7d172a28bd453b3e0d5f89295aa. Conflicts: components/config/gamesettings.cpp --- 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, 3 insertions(+), 166 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 27d37dbf03..fd36993bfb 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 | QIODevice::Truncate)) { // File cannot be opened or created QMessageBox msgBox; msgBox.setWindowTitle(tr("Error writing OpenMW configuration file")); @@ -513,15 +504,9 @@ bool Launcher::MainDialog::writeSettings() } QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); - if (keepComments) - mGameSettings.writeFileWithComments(file); - else - { - stream.setCodec(QTextCodec::codecForName("UTF-8")); - mGameSettings.writeFile(stream); - } - + mGameSettings.writeFile(stream); file.close(); // Graphics settings 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/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index c0a3b82d1c..0481235c78 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -1,7 +1,6 @@ #include "gamesettings.hpp" #include "launchersettings.hpp" -#include #include #include #include @@ -174,133 +173,6 @@ 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"; - } - - // new entries - if (!userSettingsCopy.empty()) - { - 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 35614113f4..cc5033f351 100644 --- a/components/config/gamesettings.hpp +++ b/components/config/gamesettings.hpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include @@ -67,7 +66,6 @@ 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 f38ba764c3..7f5e4a7de8 100644 --- a/files/ui/settingspage.ui +++ b/files/ui/settingspage.ui @@ -40,16 +40,6 @@ - - - - Keep comments in openmw.cfg - - - false - - - From bfff84ba8f76aed1f511870e76a0cc3dda631f46 Mon Sep 17 00:00:00 2001 From: dteviot Date: Sun, 14 Jun 2015 10:30:55 +1200 Subject: [PATCH 33/57] replaced #include with forward class declaration, as suggested by slaugherfish. --- apps/openmw/mwmechanics/aipackage.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 0370072a41..78a2bfd9f7 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -4,8 +4,6 @@ #include "pathfinding.hpp" #include -#include "../mwworld/cellstore.hpp" - #include "obstacle.hpp" #include "aistate.hpp" @@ -16,6 +14,7 @@ namespace MWWorld namespace ESM { + struct Cell; namespace AiSequence { struct AiSequence; From 28caeadef4b61b9fe6fbf2fdd53c69a38a07d282 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 14 Jun 2015 02:31:00 +0200 Subject: [PATCH 34/57] Improve error message for not found records --- apps/openmw/mwworld/store.hpp | 6 +++--- components/esm/loadacti.hpp | 2 ++ components/esm/loadalch.hpp | 3 +++ components/esm/loadappa.hpp | 2 ++ components/esm/loadarmo.hpp | 2 ++ components/esm/loadbody.hpp | 2 ++ components/esm/loadbook.hpp | 2 ++ components/esm/loadbsgn.hpp | 2 ++ components/esm/loadcell.hpp | 2 ++ components/esm/loadclas.hpp | 2 ++ components/esm/loadclot.hpp | 2 ++ components/esm/loadcont.hpp | 2 ++ components/esm/loadcrea.hpp | 2 ++ components/esm/loaddial.hpp | 2 ++ components/esm/loaddoor.hpp | 2 ++ components/esm/loadench.hpp | 2 ++ components/esm/loadfact.hpp | 2 ++ components/esm/loadglob.hpp | 2 ++ components/esm/loadgmst.hpp | 2 ++ components/esm/loadinfo.hpp | 2 ++ components/esm/loadingr.hpp | 2 ++ components/esm/loadland.hpp | 2 ++ components/esm/loadlevlist.hpp | 4 ++++ components/esm/loadligh.hpp | 2 ++ components/esm/loadlock.hpp | 2 ++ components/esm/loadltex.hpp | 2 ++ components/esm/loadmgef.hpp | 2 ++ components/esm/loadmisc.hpp | 2 ++ components/esm/loadnpc.hpp | 2 ++ components/esm/loadpgrd.hpp | 2 ++ components/esm/loadprob.hpp | 2 ++ components/esm/loadrace.hpp | 2 ++ components/esm/loadregn.hpp | 2 ++ components/esm/loadrepa.hpp | 2 ++ components/esm/loadscpt.hpp | 2 ++ components/esm/loadskil.hpp | 2 ++ components/esm/loadsndg.hpp | 2 ++ components/esm/loadsoun.hpp | 2 ++ components/esm/loadspel.hpp | 2 ++ components/esm/loadsscr.hpp | 2 ++ components/esm/loadstat.hpp | 2 ++ components/esm/loadweap.hpp | 2 ++ 42 files changed, 88 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index ba8be733a0..ab09782b14 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -188,7 +188,7 @@ namespace MWWorld const T *ptr = search(id); if (ptr == 0) { std::ostringstream msg; - msg << "Object '" << id << "' not found (const)"; + msg << T::getRecordType() << " '" << id << "' not found"; throw std::runtime_error(msg.str()); } return ptr; @@ -202,7 +202,7 @@ namespace MWWorld if(ptr == 0) { std::ostringstream msg; - msg << "Object starting with '"< CellRefTracker; struct Cell { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Cell"; } enum Flags { diff --git a/components/esm/loadclas.hpp b/components/esm/loadclas.hpp index 3e489bb58a..972b48e889 100644 --- a/components/esm/loadclas.hpp +++ b/components/esm/loadclas.hpp @@ -18,6 +18,8 @@ class ESMWriter; struct Class { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Class"; } enum AutoCalc { diff --git a/components/esm/loadclot.hpp b/components/esm/loadclot.hpp index 50896622aa..6945f224a4 100644 --- a/components/esm/loadclot.hpp +++ b/components/esm/loadclot.hpp @@ -18,6 +18,8 @@ class ESMWriter; struct Clothing { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Clothing"; } enum Type { diff --git a/components/esm/loadcont.hpp b/components/esm/loadcont.hpp index 76c522d748..ab587f9353 100644 --- a/components/esm/loadcont.hpp +++ b/components/esm/loadcont.hpp @@ -36,6 +36,8 @@ struct InventoryList struct Container { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Container"; } enum Flags { diff --git a/components/esm/loadcrea.hpp b/components/esm/loadcrea.hpp index 1b02aa0abc..47e5954a5f 100644 --- a/components/esm/loadcrea.hpp +++ b/components/esm/loadcrea.hpp @@ -22,6 +22,8 @@ class ESMWriter; struct Creature { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Creature"; } // Default is 0x48? enum Flags diff --git a/components/esm/loaddial.hpp b/components/esm/loaddial.hpp index d29948c63b..58598d3536 100644 --- a/components/esm/loaddial.hpp +++ b/components/esm/loaddial.hpp @@ -21,6 +21,8 @@ class ESMWriter; struct Dialogue { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Dialogue"; } enum Type { diff --git a/components/esm/loaddoor.hpp b/components/esm/loaddoor.hpp index ee2b7f7ac5..3073f4e9de 100644 --- a/components/esm/loaddoor.hpp +++ b/components/esm/loaddoor.hpp @@ -12,6 +12,8 @@ class ESMWriter; struct Door { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Door"; } std::string mId, mName, mModel, mScript, mOpenSound, mCloseSound; diff --git a/components/esm/loadench.hpp b/components/esm/loadench.hpp index 3b7746812a..cfcdd4edce 100644 --- a/components/esm/loadench.hpp +++ b/components/esm/loadench.hpp @@ -18,6 +18,8 @@ class ESMWriter; struct Enchantment { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Enchantment"; } enum Type { diff --git a/components/esm/loadfact.hpp b/components/esm/loadfact.hpp index d31670fe28..8645e23fd8 100644 --- a/components/esm/loadfact.hpp +++ b/components/esm/loadfact.hpp @@ -30,6 +30,8 @@ struct RankData struct Faction { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Faction"; } std::string mId, mName; diff --git a/components/esm/loadglob.hpp b/components/esm/loadglob.hpp index 51b2e2dc98..cc5dbbdcfc 100644 --- a/components/esm/loadglob.hpp +++ b/components/esm/loadglob.hpp @@ -18,6 +18,8 @@ class ESMWriter; struct Global { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Global"; } std::string mId; Variant mValue; diff --git a/components/esm/loadgmst.hpp b/components/esm/loadgmst.hpp index 398b8047fd..d9d9048b61 100644 --- a/components/esm/loadgmst.hpp +++ b/components/esm/loadgmst.hpp @@ -19,6 +19,8 @@ class ESMWriter; struct GameSetting { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "GameSetting"; } std::string mId; diff --git a/components/esm/loadinfo.hpp b/components/esm/loadinfo.hpp index 59b1af31a2..54003b0d96 100644 --- a/components/esm/loadinfo.hpp +++ b/components/esm/loadinfo.hpp @@ -21,6 +21,8 @@ class ESMWriter; struct DialInfo { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "DialInfo"; } enum Gender { diff --git a/components/esm/loadingr.hpp b/components/esm/loadingr.hpp index 85f2d5e7d2..5846a97809 100644 --- a/components/esm/loadingr.hpp +++ b/components/esm/loadingr.hpp @@ -16,6 +16,8 @@ class ESMWriter; struct Ingredient { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Ingredient"; } struct IRDTstruct { diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index e510616aff..7dc5e8adb3 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -18,6 +18,8 @@ class ESMWriter; struct Land { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Land"; } Land(); ~Land(); diff --git a/components/esm/loadlevlist.hpp b/components/esm/loadlevlist.hpp index bcea2b234c..dc6fcda5ec 100644 --- a/components/esm/loadlevlist.hpp +++ b/components/esm/loadlevlist.hpp @@ -46,6 +46,8 @@ struct LevelledListBase struct CreatureLevList: LevelledListBase { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "CreatureLevList"; } enum Flags { @@ -64,6 +66,8 @@ struct CreatureLevList: LevelledListBase struct ItemLevList: LevelledListBase { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "ItemLevList"; } enum Flags { diff --git a/components/esm/loadligh.hpp b/components/esm/loadligh.hpp index 2c83248f8a..ed8c36665c 100644 --- a/components/esm/loadligh.hpp +++ b/components/esm/loadligh.hpp @@ -17,6 +17,8 @@ class ESMWriter; struct Light { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Light"; } enum Flags { diff --git a/components/esm/loadlock.hpp b/components/esm/loadlock.hpp index c44e2b0063..0d678cd64c 100644 --- a/components/esm/loadlock.hpp +++ b/components/esm/loadlock.hpp @@ -12,6 +12,8 @@ class ESMWriter; struct Lockpick { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Lockpick"; } struct Data { diff --git a/components/esm/loadltex.hpp b/components/esm/loadltex.hpp index 8b45f82118..50a7881054 100644 --- a/components/esm/loadltex.hpp +++ b/components/esm/loadltex.hpp @@ -28,6 +28,8 @@ class ESMWriter; struct LandTexture { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "LandTexture"; } std::string mId, mTexture; int mIndex; diff --git a/components/esm/loadmgef.hpp b/components/esm/loadmgef.hpp index e66322832f..32b8a85a6d 100644 --- a/components/esm/loadmgef.hpp +++ b/components/esm/loadmgef.hpp @@ -13,6 +13,8 @@ class ESMWriter; struct MagicEffect { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "MagicEffect"; } std::string mId; diff --git a/components/esm/loadmisc.hpp b/components/esm/loadmisc.hpp index 576bd18c0f..6e0b4e01b8 100644 --- a/components/esm/loadmisc.hpp +++ b/components/esm/loadmisc.hpp @@ -17,6 +17,8 @@ class ESMWriter; struct Miscellaneous { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Miscellaneous"; } struct MCDTstruct { diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index b535b91b01..e8867110c4 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -23,6 +23,8 @@ class ESMWriter; struct NPC { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "NPC"; } // Services enum Services diff --git a/components/esm/loadpgrd.hpp b/components/esm/loadpgrd.hpp index 256b86cdad..f33ccbedf9 100644 --- a/components/esm/loadpgrd.hpp +++ b/components/esm/loadpgrd.hpp @@ -16,6 +16,8 @@ class ESMWriter; struct Pathgrid { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Pathgrid"; } struct DATAstruct { diff --git a/components/esm/loadprob.hpp b/components/esm/loadprob.hpp index b89b2ddeb6..c737757aa3 100644 --- a/components/esm/loadprob.hpp +++ b/components/esm/loadprob.hpp @@ -12,6 +12,8 @@ class ESMWriter; struct Probe { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Probe"; } struct Data { diff --git a/components/esm/loadrace.hpp b/components/esm/loadrace.hpp index 7d5736d9b7..553d2e68b1 100644 --- a/components/esm/loadrace.hpp +++ b/components/esm/loadrace.hpp @@ -18,6 +18,8 @@ class ESMWriter; struct Race { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Race"; } struct SkillBonus { diff --git a/components/esm/loadregn.hpp b/components/esm/loadregn.hpp index c231b6aa0d..1e241fffbe 100644 --- a/components/esm/loadregn.hpp +++ b/components/esm/loadregn.hpp @@ -19,6 +19,8 @@ class ESMWriter; struct Region { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Region"; } #pragma pack(push) #pragma pack(1) diff --git a/components/esm/loadrepa.hpp b/components/esm/loadrepa.hpp index 5b404b0e4c..e765bc93a5 100644 --- a/components/esm/loadrepa.hpp +++ b/components/esm/loadrepa.hpp @@ -12,6 +12,8 @@ class ESMWriter; struct Repair { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Repair"; } struct Data { diff --git a/components/esm/loadscpt.hpp b/components/esm/loadscpt.hpp index deb71de6af..56390f3841 100644 --- a/components/esm/loadscpt.hpp +++ b/components/esm/loadscpt.hpp @@ -20,6 +20,8 @@ class Script { public: static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Script"; } struct SCHDstruct { diff --git a/components/esm/loadskil.hpp b/components/esm/loadskil.hpp index 1b9db5bcff..e001842970 100644 --- a/components/esm/loadskil.hpp +++ b/components/esm/loadskil.hpp @@ -20,6 +20,8 @@ class ESMWriter; struct Skill { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Skill"; } std::string mId; diff --git a/components/esm/loadsndg.hpp b/components/esm/loadsndg.hpp index f89a112082..056958f0a8 100644 --- a/components/esm/loadsndg.hpp +++ b/components/esm/loadsndg.hpp @@ -16,6 +16,8 @@ class ESMWriter; struct SoundGenerator { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "SoundGenerator"; } enum Type { diff --git a/components/esm/loadsoun.hpp b/components/esm/loadsoun.hpp index 04a0984fda..ff2202ca7d 100644 --- a/components/esm/loadsoun.hpp +++ b/components/esm/loadsoun.hpp @@ -17,6 +17,8 @@ struct SOUNstruct struct Sound { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Sound"; } SOUNstruct mData; std::string mId, mSound; diff --git a/components/esm/loadspel.hpp b/components/esm/loadspel.hpp index 4bd2210ec0..491da1d179 100644 --- a/components/esm/loadspel.hpp +++ b/components/esm/loadspel.hpp @@ -14,6 +14,8 @@ class ESMWriter; struct Spell { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Spell"; } enum SpellType { diff --git a/components/esm/loadsscr.hpp b/components/esm/loadsscr.hpp index 1420d16c47..dc7ad6a42a 100644 --- a/components/esm/loadsscr.hpp +++ b/components/esm/loadsscr.hpp @@ -20,6 +20,8 @@ class ESMWriter; struct StartScript { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "StartScript"; } std::string mData; std::string mId; diff --git a/components/esm/loadstat.hpp b/components/esm/loadstat.hpp index 45b05136ad..21a9e66e88 100644 --- a/components/esm/loadstat.hpp +++ b/components/esm/loadstat.hpp @@ -23,6 +23,8 @@ class ESMWriter; struct Static { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Static"; } std::string mId, mModel; diff --git a/components/esm/loadweap.hpp b/components/esm/loadweap.hpp index 14ddb47082..f66e9f3a68 100644 --- a/components/esm/loadweap.hpp +++ b/components/esm/loadweap.hpp @@ -16,6 +16,8 @@ class ESMWriter; struct Weapon { static unsigned int sRecordId; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. + static std::string getRecordType() { return "Weapon"; } enum Type { From 520fbd63c4a50a56b79a49bd90b8da6f10c2e26a Mon Sep 17 00:00:00 2001 From: dteviot Date: Sun, 14 Jun 2015 15:14:02 +1200 Subject: [PATCH 35/57] simplified pathfinding code. remove mIsPathConstructed. Instead call !mPath.empty(). --- apps/openmw/mwmechanics/pathfinding.cpp | 17 ++--------------- apps/openmw/mwmechanics/pathfinding.hpp | 4 +--- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 980de1badd..fea993e231 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -114,8 +114,7 @@ namespace MWMechanics } PathFinder::PathFinder() - : mIsPathConstructed(false), - mPathgrid(NULL), + : mPathgrid(NULL), mCell(NULL) { } @@ -124,7 +123,6 @@ namespace MWMechanics { if(!mPath.empty()) mPath.clear(); - mIsPathConstructed = false; } /* @@ -180,7 +178,6 @@ namespace MWMechanics static_cast(endPoint.mX), static_cast(endPoint.mY), static_cast(endPoint.mZ))) { mPath.push_back(endPoint); - mIsPathConstructed = true; return; } } @@ -197,7 +194,6 @@ namespace MWMechanics if(!mPathgrid || mPathgrid->mPoints.empty()) { mPath.push_back(endPoint); - mIsPathConstructed = true; return; } @@ -235,7 +231,6 @@ namespace MWMechanics if(startNode == endNode.first) { mPath.push_back(endPoint); - mIsPathConstructed = true; return; } @@ -243,7 +238,6 @@ namespace MWMechanics if(!mPath.empty()) { - mIsPathConstructed = true; // Add the destination (which may be different to the closest // pathgrid point). However only add if endNode was the closest // point to endPoint. @@ -256,14 +250,8 @@ namespace MWMechanics if(endNode.second) mPath.push_back(endPoint); } - else - mIsPathConstructed = false; } - else - mIsPathConstructed = false; } - else - mIsPathConstructed = false; return; } @@ -271,7 +259,7 @@ namespace MWMechanics float PathFinder::getZAngleToNext(float x, float y) const { // This should never happen (programmers should have an if statement checking - // mIsPathConstructed that prevents this call if otherwise). + // isPathConstructed that prevents this call if otherwise). if(mPath.empty()) return 0.; @@ -293,7 +281,6 @@ namespace MWMechanics mPath.pop_front(); if(mPath.empty()) { - mIsPathConstructed = false; return true; } } diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 0f52a6e19d..644d792368 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -48,7 +48,7 @@ namespace MWMechanics bool isPathConstructed() const { - return mIsPathConstructed; + return !mPath.empty(); } int getPathSize() const @@ -96,8 +96,6 @@ namespace MWMechanics private: - bool mIsPathConstructed; - std::list mPath; const ESM::Pathgrid *mPathgrid; From 0efe8f5465d652d42a7191d8a7c5223dfa711466 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 14 Jun 2015 14:42:08 +1000 Subject: [PATCH 36/57] Fix broken launcher build for windows. --- apps/launcher/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 66cc157d3b..3c7b393149 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -100,6 +100,9 @@ target_link_libraries(openmw-launcher if (DESIRED_QT_VERSION MATCHES 4) target_link_libraries(openmw-launcher ${QT_QTGUI_LIBRARY} ${QT_QTCORE_LIBRARY}) + if(WIN32) + target_link_libraries(openmw-launcher ${QT_QTMAIN_LIBRARY}) + endif(WIN32) else() qt5_use_modules(openmw-launcher Widgets Core) endif() From c22c9c271d6cfab22ac2f6c35714eeb266b2fa0c Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 14 Jun 2015 14:51:01 +1000 Subject: [PATCH 37/57] Allow comments (lines starting with # character) and blank lines in openmw.cfg. Should resolve Feature #2535. - allows moving various config entries up or down - comment lines above config entries stay as a pair --- apps/launcher/maindialog.cpp | 7 +- components/config/gamesettings.cpp | 209 +++++++++++++++++++++++++++++ components/config/gamesettings.hpp | 4 + 3 files changed, 216 insertions(+), 4 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index fd36993bfb..2f7a9db332 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -490,7 +490,7 @@ bool Launcher::MainDialog::writeSettings() // Game settings QFile file(userPath + QString("openmw.cfg")); - if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { + if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { // File cannot be opened or created QMessageBox msgBox; msgBox.setWindowTitle(tr("Error writing OpenMW configuration file")); @@ -503,10 +503,8 @@ bool Launcher::MainDialog::writeSettings() return false; } - QTextStream stream(&file); - stream.setCodec(QTextCodec::codecForName("UTF-8")); - mGameSettings.writeFile(stream); + mGameSettings.writeFileWithComments(file); file.close(); // Graphics settings @@ -525,6 +523,7 @@ bool Launcher::MainDialog::writeSettings() return false; } + QTextStream stream(&file); stream.setDevice(&file); stream.setCodec(QTextCodec::codecForName("UTF-8")); diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index 0481235c78..4339369cf1 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,214 @@ bool Config::GameSettings::writeFile(QTextStream &stream) return true; } +bool Config::GameSettings::isOrderedLine(const QString& line) const +{ + return line.contains(QRegExp("^\\s*fallback-archive\\s*=")) + || line.contains(QRegExp("^\\s*fallback\\s*=")) + || line.contains(QRegExp("^\\s*data\\s*=")) + || line.contains(QRegExp("^\\s*data-local\\s*=")) + || line.contains(QRegExp("^\\s*resources\\s*=")) + || line.contains(QRegExp("^\\s*content\\s*=")); +} + +// Policy: +// +// - Always ignore a line beginning with '#' or empty lines; added above a config +// entry. +// +// - 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 +// +// - 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); + + // start + // | + // | +----------------------------------------------------------+ + // | | | + // v v | + // skip non-"ordered" lines (remove "ordered" lines) | + // | ^ | + // | | | + // | non-"ordered" line, write saved comments | + // | ^ | + // v | | + // blank or comment line, save in temp buffer <--------+ | + // | | | | + // v +------- comment line ------+ | + // "ordered" line | + // | | + // v | + // save in a separate map of comments keyed by "ordered" line | + // | | + // +----------------------------------------------------------+ + // + // + QRegExp settingRegex("^([^=]+)\\s*=\\s*([^,]+)(.*)$"); + std::vector comments; + std::vector::iterator commentStart = fileCopy.end(); + std::map > commentsMap; + for (std::vector::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) + { + if (isOrderedLine(*iter)) + { + // save in a separate map of comments keyed by "ordered" line + if (!comments.empty()) + { + if (settingRegex.indexIn(*iter) != -1) + { + commentsMap[settingRegex.cap(1)+"="+settingRegex.cap(2)] = comments; + comments.clear(); + commentStart = fileCopy.end(); + } + // else do nothing, malformed line + } + + *iter = QString(); // "ordered" lines to be removed later + } + else if ((*iter).isEmpty() || (*iter).contains(QRegExp("^\\s*#"))) + { + // comment line, save in temp buffer + if (comments.empty()) + commentStart = iter; + comments.push_back(*iter); + *iter = QString(); // assume to be deleted later + } + else + { + int index = settingRegex.indexIn(*iter); + + // blank or non-"ordered" line, write saved comments + if (!comments.empty() && index != -1 && settingRegex.captureCount() >= 2 && + mUserSettings.find(settingRegex.cap(1)) != mUserSettings.end()) + { + for (std::vector::const_iterator it = comments.begin(); it != comments.end(); ++it) + { + *commentStart = *it; + ++commentStart; + } + comments.clear(); + commentStart = fileCopy.end(); + } + + // keep blank lines and non-"ordered" lines other than comments + + // look for a key in the line + if (index == -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(); + comments.clear(); + commentStart = fileCopy.end(); + continue; + } + + // look for a matching key in user settings + *iter = QString(); // assume no match + QString key = settingRegex.cap(1); + QString keyVal = settingRegex.cap(1)+"="+settingRegex.cap(2); + QMap::const_iterator i = mUserSettings.find(key); + while (i != mUserSettings.end() && i.key() == key) + { + QString settingLine = i.key() + "=" + i.value(); + if (settingRegex.indexIn(settingLine) != -1) + { + if ((settingRegex.cap(1)+"="+settingRegex.cap(2)) == keyVal) + { + *iter = settingLine; + break; + } + } + ++i; + } + } + } + + // comments at top of file + for (std::vector::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) + { + if ((*iter).isNull()) + continue; + + // 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; + } + } + + // Iterate in reverse order to preserve insertion order + QString settingLine; + QMapIterator it(mUserSettings); + it.toBack(); + + while (it.hasPrevious()) + { + it.previous(); + + // Quote paths with spaces + if ((it.key() == QLatin1String("data") + || it.key() == QLatin1String("data-local") + || it.key() == QLatin1String("resources")) && it.value().contains(QChar(' '))) + { + QString stripped = it.value(); + stripped.remove(QChar('\"')); // Remove quotes + + settingLine = it.key() + "=\"" + stripped + "\""; + } + else + settingLine = it.key() + "=" + it.value(); + + if (settingRegex.indexIn(settingLine) != -1) + { + std::map >::const_iterator i = + commentsMap.find(settingRegex.cap(1)+"="+settingRegex.cap(2)); + + if (i != commentsMap.end()) + { + std::vector cLines = i->second; + for (std::vector::const_iterator ci = cLines.begin(); ci != cLines.end(); ++ci) + stream << *ci << "\n"; + } + } + + stream << settingLine << "\n"; + } + + // flush any end comments + if (!comments.empty()) + { + for (std::vector::const_iterator ci = comments.begin(); ci != comments.end(); ++ci) + stream << *ci << "\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..992a3e5655 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; @@ -81,6 +83,8 @@ namespace Config QString mDataLocal; static const char sContentKey[]; + + bool isOrderedLine(const QString& line) const; }; } #endif // GAMESETTINGS_HPP From 30de47f858dc98ba2ecd8c2657ad33584585e440 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 14 Jun 2015 17:12:14 +0200 Subject: [PATCH 38/57] Reduce the number of jobs in .travis.yml Hopefully this fixes the occasional out-of-memory problems. Note travis-CI virtual machines just have 2 virtual cores according to http://docs.travis-ci.com/user/ci-environment/, so 4 jobs wouldn't improve build times anyway. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1fc85dca38..6b03be1141 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,7 +38,7 @@ before_script: - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi script: - cd ./build - - if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j4; fi + - if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j2; fi - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi after_script: - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi From 36aa4aa9bdeb50a3512d5f2212bb5daaa94477b2 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Mon, 15 Jun 2015 09:53:26 +1000 Subject: [PATCH 39/57] If a removed 'content=' item has comments, keep them in config file for later use. --- components/config/gamesettings.cpp | 47 ++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index 4339369cf1..74d92d55da 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -195,6 +195,9 @@ bool Config::GameSettings::isOrderedLine(const QString& line) const // // - If there is no corresponding line in file, add at the end // +// - Removed content items are saved as comments if the item had any comments. +// Content items prepended with '##' are considered previously removed. +// bool Config::GameSettings::writeFileWithComments(QFile &file) { QTextStream stream(&file); @@ -227,7 +230,8 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) // v | | // blank or comment line, save in temp buffer <--------+ | // | | | | - // v +------- comment line ------+ | + // | +------- comment line ------+ | + // v (special processing '##') | // "ordered" line | // | | // v | @@ -263,7 +267,20 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) // comment line, save in temp buffer if (comments.empty()) commentStart = iter; - comments.push_back(*iter); + + // special removed content processing + if ((*iter).contains(QRegExp("^##content\\s*="))) + { + if (!comments.empty()) + { + commentsMap[*iter] = comments; + comments.clear(); + commentStart = fileCopy.end(); + } + } + else + comments.push_back(*iter); + *iter = QString(); // assume to be deleted later } else @@ -359,17 +376,43 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) std::map >::const_iterator i = commentsMap.find(settingRegex.cap(1)+"="+settingRegex.cap(2)); + // check if previous removed content item with comments + if (i == commentsMap.end()) + i = commentsMap.find("##"+settingRegex.cap(1)+"="+settingRegex.cap(2)); + if (i != commentsMap.end()) { std::vector cLines = i->second; for (std::vector::const_iterator ci = cLines.begin(); ci != cLines.end(); ++ci) stream << *ci << "\n"; + + commentsMap.erase(i); } } stream << settingLine << "\n"; } + // flush any removed settings + if (!commentsMap.empty()) + { + std::map >::const_iterator i = commentsMap.begin(); + for (; i != commentsMap.end(); ++i) + { + if (i->first.contains(QRegExp("^\\s*content\\s*="))) + { + std::vector cLines = i->second; + for (std::vector::const_iterator ci = cLines.begin(); ci != cLines.end(); ++ci) + stream << *ci << "\n"; + + // mark the content line entry for future preocessing + stream << "##" << i->first << "\n"; + + //commentsMap.erase(i); + } + } + } + // flush any end comments if (!comments.empty()) { From 6b28955f316d8e3261d68b99c48bd6ce8a8e3f48 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Mon, 15 Jun 2015 10:26:16 +1000 Subject: [PATCH 40/57] Fix attempt to erase using a const_iterator. --- components/config/gamesettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index 74d92d55da..ca6bfd80da 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -373,7 +373,7 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) if (settingRegex.indexIn(settingLine) != -1) { - std::map >::const_iterator i = + std::map >::iterator i = commentsMap.find(settingRegex.cap(1)+"="+settingRegex.cap(2)); // check if previous removed content item with comments From 609e146a22f2e8b3c70cb15693b4976aba7141d5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 15 Jun 2015 14:16:14 +0200 Subject: [PATCH 41/57] Build fixes for windows --- apps/launcher/CMakeLists.txt | 3 +++ apps/opencs/CMakeLists.txt | 8 ++++++++ apps/wizard/CMakeLists.txt | 7 +++++++ extern/ogre-ffmpeg-videoplayer/CMakeLists.txt | 3 +-- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 3c7b393149..caf96054e7 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -105,6 +105,9 @@ if (DESIRED_QT_VERSION MATCHES 4) endif(WIN32) else() qt5_use_modules(openmw-launcher Widgets Core) + if (WIN32) + target_link_libraries(Qt5::WinMain) + endif() endif() if (BUILD_WITH_CODE_COVERAGE) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 6a9318319c..bf39b36c19 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -216,8 +216,16 @@ if (DESIRED_QT_VERSION MATCHES 4) ${QT_QTGUI_LIBRARY} ${QT_QTCORE_LIBRARY} ${QT_QTNETWORK_LIBRARY}) + + if (WIN32) + target_link_libraries(openmw-cs ${QT_QTMAIN_LIBRARY}) + endif() + else() qt5_use_modules(openmw-cs Widgets Core Network) + if (WIN32) + target_link_libraries(Qt5::WinMain) + endif() endif() if (WIN32) diff --git a/apps/wizard/CMakeLists.txt b/apps/wizard/CMakeLists.txt index 5cd874863b..89438640c1 100644 --- a/apps/wizard/CMakeLists.txt +++ b/apps/wizard/CMakeLists.txt @@ -123,8 +123,15 @@ if (DESIRED_QT_VERSION MATCHES 4) target_link_libraries(openmw-wizard ${QT_QTGUI_LIBRARY} ${QT_QTCORE_LIBRARY}) + + if (WIN32) + target_link_libraries(openmw-wizard ${QT_QTMAIN_LIBRARY}) + endif() else() qt5_use_modules(openmw-wizard Widgets Core) + if (WIN32) + target_link_libraries(Qt5::WinMain) + endif() endif() if (OPENMW_USE_UNSHIELD) diff --git a/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt b/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt index cda3d39e83..edd5575f46 100644 --- a/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt +++ b/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt @@ -11,8 +11,7 @@ set(OGRE_FFMPEG_VIDEOPLAYER_SOURCE_FILES audiofactory.hpp ) -# Find Boost - +include_directories(${FFMPEG_INCLUDE_DIRS}) add_library(${OGRE_FFMPEG_VIDEOPLAYER_LIBRARY} STATIC ${OGRE_FFMPEG_VIDEOPLAYER_SOURCE_FILES}) target_link_libraries(${OGRE_FFMPEG_VIDEOPLAYER_LIBRARY} ${FFMPEG_LIBRARIES} ${Boost_THREAD_LIBRARY}) From 98a77f68a335a7fc878e3c7dba4a509bad8e4e68 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 15 Jun 2015 20:04:36 +0200 Subject: [PATCH 42/57] Fix AiWander::fastForward using incorrect pathgrid coordinates when actor recently moved to a new cell --- apps/openmw/mwmechanics/aiwander.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 0766369747..e6fd684696 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -669,6 +669,9 @@ namespace MWMechanics MWBase::Environment::get().getWorld()->moveObject(actor, static_cast(dest.mX), static_cast(dest.mY), static_cast(dest.mZ)); actor.getClass().adjustPosition(actor, false); + + // may have changed cell + mStoredAvailableNodes = false; } void AiWander::getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell) From 5347d407d805e234a4022896cf4d94e213aa2f8f Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 15 Jun 2015 20:05:12 +0200 Subject: [PATCH 43/57] Disallow AiWander fast-forward for water creatures Pathgrid nodes are usually above the water level, so appearing at a random node would have the creature break out of the water level it's supposed to be constrained to. --- apps/openmw/mwmechanics/aiwander.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index e6fd684696..1f4133c0aa 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -651,6 +651,9 @@ namespace MWMechanics if (mAllowedNodes.empty()) return; + if (actor.getClass().isPureWaterCreature(actor)) + return; + state.moveIn(new AiWanderStorage()); int index = OEngine::Misc::Rng::rollDice(mAllowedNodes.size()); From d906a9d7d10b0b9d7d16d65b7cf3c727ffe32c29 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 16 Jun 2015 00:19:51 +0300 Subject: [PATCH 44/57] DataDisplayDelegate doesn't draw a text outside a table cell --- .../opencs/view/world/datadisplaydelegate.cpp | 32 ++++++++++--------- .../opencs/view/world/datadisplaydelegate.hpp | 1 - 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index b9df52bf7e..71686d77d7 100644 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -15,8 +15,6 @@ CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3), mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName) { - mTextAlignment.setAlignment (Qt::AlignLeft | Qt::AlignVCenter ); - buildPixmaps(); QString value = @@ -81,24 +79,28 @@ void CSVWorld::DataDisplayDelegate::paint (QPainter *painter, const QStyleOption void CSVWorld::DataDisplayDelegate::paintIcon (QPainter *painter, const QStyleOptionViewItem &option, int index) const { - //function-level statics QRect iconRect = option.rect; QRect textRect = iconRect; - const QString &text = mValues.at(index).second; - - iconRect.setSize (mIconSize); - iconRect.translate(mIconLeftOffset, (option.rect.height() - iconRect.height())/2); - - if (mDisplayMode == Mode_IconAndText ) + iconRect.setLeft(iconRect.left() + mIconLeftOffset); + iconRect.setRight(option.rect.right()); + if (mDisplayMode == Mode_IconAndText) { - textRect.translate (iconRect.width() + mTextLeftOffset, 0 ); - painter->drawText (textRect, text, mTextAlignment); - } - else - iconRect.translate( (option.rect.width() - iconRect.width()) / 2, 0); + iconRect.setWidth(mIconSize.width()); + textRect.setLeft(iconRect.right() + mTextLeftOffset); + textRect.setRight(option.rect.right()); - painter->drawPixmap (iconRect, mPixmaps.at(index).second); + QString text = option.fontMetrics.elidedText(mValues.at(index).second, + option.textElideMode, + textRect.width()); + QApplication::style()->drawItemText(painter, + textRect, + Qt::AlignLeft | Qt::AlignVCenter, + option.palette, + true, + text); + } + QApplication::style()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, mPixmaps.at(index).second); } void CSVWorld::DataDisplayDelegate::updateUserSetting (const QString &name, diff --git a/apps/opencs/view/world/datadisplaydelegate.hpp b/apps/opencs/view/world/datadisplaydelegate.hpp index f6e4c26887..07fa1fd8d2 100755 --- a/apps/opencs/view/world/datadisplaydelegate.hpp +++ b/apps/opencs/view/world/datadisplaydelegate.hpp @@ -30,7 +30,6 @@ namespace CSVWorld private: std::vector > mPixmaps; - QTextOption mTextAlignment; QSize mIconSize; int mIconLeftOffset; int mTextLeftOffset; From cccf6c6bdd272c28f848935023b9e9ac60401191 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 16 Jun 2015 12:48:45 +1000 Subject: [PATCH 45/57] Rebuild the list of available content files when opening the open/new dialogues. Should resolve Bug #2644. --- apps/opencs/editor.cpp | 14 ++++++++++++-- apps/opencs/editor.hpp | 2 +- apps/opencs/view/doc/filedialog.cpp | 8 ++++++-- apps/opencs/view/doc/filedialog.hpp | 1 + components/contentselector/model/contentmodel.cpp | 7 +++++++ components/contentselector/model/contentmodel.hpp | 1 + .../contentselector/view/contentselector.cpp | 5 +++++ .../contentselector/view/contentselector.hpp | 1 + components/files/configurationmanager.cpp | 6 +++++- components/files/configurationmanager.hpp | 2 +- 10 files changed, 40 insertions(+), 7 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index efd7cf4ec7..80d8b8a932 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -95,7 +95,7 @@ void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs) } } -std::pair > CS::Editor::readConfig() +std::pair > CS::Editor::readConfig(bool quiet) { boost::program_options::variables_map variables; boost::program_options::options_description desc("Syntax: openmw-cs \nAllowed options"); @@ -115,7 +115,7 @@ std::pair > CS::Editor::readConfi boost::program_options::notify(variables); - mCfgMgr.readConfiguration(variables, desc); + mCfgMgr.readConfiguration(variables, desc, /*quiet*/true); mDocumentManager.setEncoding ( ToUTF8::calculateEncoding (variables["encoding"].as())); @@ -195,6 +195,11 @@ void CS::Editor::cancelCreateGame() void CS::Editor::createAddon() { mStartup.hide(); + + mFileDialog.clearFiles(); + std::pair > config = readConfig(/*quiet*/true); + setupDataFiles (config.first); + mFileDialog.showDialog (CSVDoc::ContentAction_New); } @@ -215,6 +220,11 @@ void CS::Editor::cancelFileDialog() void CS::Editor::loadDocument() { mStartup.hide(); + + mFileDialog.clearFiles(); + std::pair > config = readConfig(/*quiet*/true); + setupDataFiles (config.first); + mFileDialog.showDialog (CSVDoc::ContentAction_Edit); } diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index eb85743a39..cbf306df83 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -62,7 +62,7 @@ namespace CS void setupDataFiles (const Files::PathContainer& dataDirs); - std::pair > readConfig(); + std::pair > readConfig(bool quiet=false); ///< \return data paths // not implemented diff --git a/apps/opencs/view/doc/filedialog.cpp b/apps/opencs/view/doc/filedialog.cpp index eeec81109f..b6f4aaec31 100644 --- a/apps/opencs/view/doc/filedialog.cpp +++ b/apps/opencs/view/doc/filedialog.cpp @@ -33,6 +33,11 @@ void CSVDoc::FileDialog::addFiles(const QString &path) mSelector->addFiles(path); } +void CSVDoc::FileDialog::clearFiles() +{ + mSelector->clearFiles(); +} + QStringList CSVDoc::FileDialog::selectedFilePaths() { QStringList filePaths; @@ -105,7 +110,6 @@ void CSVDoc::FileDialog::buildNewFileView() connect (mFileWidget, SIGNAL (nameChanged(const QString &, bool)), this, SLOT (slotUpdateAcceptButton(const QString &, bool))); - } ui.projectGroupBoxLayout->insertWidget (0, mFileWidget); @@ -139,7 +143,7 @@ void CSVDoc::FileDialog::slotUpdateAcceptButton(int) { QString name = ""; - if (mAction == ContentAction_New) + if (mFileWidget && mAction == ContentAction_New) name = mFileWidget->getName(); slotUpdateAcceptButton (name, true); diff --git a/apps/opencs/view/doc/filedialog.hpp b/apps/opencs/view/doc/filedialog.hpp index 3c23a5cb5a..6488365652 100644 --- a/apps/opencs/view/doc/filedialog.hpp +++ b/apps/opencs/view/doc/filedialog.hpp @@ -45,6 +45,7 @@ namespace CSVDoc void showDialog (ContentAction action); void addFiles (const QString &path); + void clearFiles (); QString filename() const; QStringList selectedFilePaths(); diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index d000290e6f..769afee37b 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -473,6 +473,13 @@ void ContentSelectorModel::ContentModel::addFiles(const QString &path) sortFiles(); } +void ContentSelectorModel::ContentModel::clearFiles() +{ + beginRemoveRows(QModelIndex(), 0, mFiles.count()-1); + mFiles.clear(); + endRemoveRows(); +} + QStringList ContentSelectorModel::ContentModel::gameFiles() const { QStringList gameFiles; diff --git a/components/contentselector/model/contentmodel.hpp b/components/contentselector/model/contentmodel.hpp index ab965ad69c..bc785a2767 100644 --- a/components/contentselector/model/contentmodel.hpp +++ b/components/contentselector/model/contentmodel.hpp @@ -44,6 +44,7 @@ namespace ContentSelectorModel bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); void addFiles(const QString &path); + void clearFiles(); QModelIndex indexFromItem(const EsmFile *item) const; const EsmFile *item(const QString &name) const; diff --git a/components/contentselector/view/contentselector.cpp b/components/contentselector/view/contentselector.cpp index 2fae8e74b9..78aa20cd26 100644 --- a/components/contentselector/view/contentselector.cpp +++ b/components/contentselector/view/contentselector.cpp @@ -150,6 +150,11 @@ void ContentSelectorView::ContentSelector::addFiles(const QString &path) mContentModel->uncheckAll(); } +void ContentSelectorView::ContentSelector::clearFiles() +{ + mContentModel->clearFiles(); +} + QString ContentSelectorView::ContentSelector::currentFile() const { QModelIndex currentIdx = ui.addonView->currentIndex(); diff --git a/components/contentselector/view/contentselector.hpp b/components/contentselector/view/contentselector.hpp index e455807c96..4e9fcfb3c8 100644 --- a/components/contentselector/view/contentselector.hpp +++ b/components/contentselector/view/contentselector.hpp @@ -29,6 +29,7 @@ namespace ContentSelectorView QString currentFile() const; void addFiles(const QString &path); + void clearFiles(); void setProfileContent (const QStringList &fileList); void clearCheckStates(); diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index e321b58143..dc6f02b608 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -52,8 +52,11 @@ void ConfigurationManager::setupTokensMapping() } void ConfigurationManager::readConfiguration(boost::program_options::variables_map& variables, - boost::program_options::options_description& description) + boost::program_options::options_description& description, bool quiet) { + bool silent = mSilent; + mSilent = quiet; + loadConfig(mFixedPath.getUserConfigPath(), variables, description); boost::program_options::notify(variables); @@ -62,6 +65,7 @@ void ConfigurationManager::readConfiguration(boost::program_options::variables_m loadConfig(mFixedPath.getGlobalConfigPath(), variables, description); boost::program_options::notify(variables); + mSilent = silent; } void ConfigurationManager::processPaths(Files::PathContainer& dataDirs, bool create) diff --git a/components/files/configurationmanager.hpp b/components/files/configurationmanager.hpp index 24b08c5236..5f0062c2e9 100644 --- a/components/files/configurationmanager.hpp +++ b/components/files/configurationmanager.hpp @@ -29,7 +29,7 @@ struct ConfigurationManager virtual ~ConfigurationManager(); void readConfiguration(boost::program_options::variables_map& variables, - boost::program_options::options_description& description); + boost::program_options::options_description& description, bool quiet=false); void processPaths(Files::PathContainer& dataDirs, bool create = false); ///< \param create Try creating the directory, if it does not exist. From 6a47ea9a676949c93dd1339f51a7b709b52ce81d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 16 Jun 2015 13:09:44 +1000 Subject: [PATCH 46/57] fix typo --- apps/opencs/editor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 80d8b8a932..bd4f57304f 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -115,7 +115,7 @@ std::pair > CS::Editor::readConfi boost::program_options::notify(variables); - mCfgMgr.readConfiguration(variables, desc, /*quiet*/true); + mCfgMgr.readConfiguration(variables, desc, quiet); mDocumentManager.setEncoding ( ToUTF8::calculateEncoding (variables["encoding"].as())); From 0ffb2bc6bc4527975ccb827a2d953d80761d7566 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 16 Jun 2015 14:18:47 +0300 Subject: [PATCH 47/57] Proper size hint for EnumDelegate --- apps/opencs/view/world/enumdelegate.cpp | 31 +++++++++++++++++++++++++ apps/opencs/view/world/enumdelegate.hpp | 2 ++ 2 files changed, 33 insertions(+) diff --git a/apps/opencs/view/world/enumdelegate.cpp b/apps/opencs/view/world/enumdelegate.cpp index 4b76bf9d65..b9eca670a0 100644 --- a/apps/opencs/view/world/enumdelegate.cpp +++ b/apps/opencs/view/world/enumdelegate.cpp @@ -115,6 +115,37 @@ void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewIte } } +QSize CSVWorld::EnumDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + if (index.data().isValid()) + { + int value = index.data().toInt(); + + // Calculate the size hint as for a combobox. + // So, the whole text is visible (isn't elided) when the editor is created + QStyleOptionComboBox itemOption; + itemOption.fontMetrics = option.fontMetrics; + itemOption.palette = option.palette; + itemOption.rect = option.rect; + itemOption.state = option.state; + + std::vector >::const_iterator current = mValues.begin(); + std::vector >::const_iterator end = mValues.end(); + for (; current != end; ++current) + { + if (current->first == value) + { + QSize valueSize = QSize(itemOption.fontMetrics.width(current->second), + itemOption.fontMetrics.height()); + itemOption.currentText = current->second; + return QApplication::style()->sizeFromContents(QStyle::CT_ComboBox, + &itemOption, + valueSize); + } + } + } + return option.rect.size(); +} CSVWorld::EnumDelegateFactory::EnumDelegateFactory() {} diff --git a/apps/opencs/view/world/enumdelegate.hpp b/apps/opencs/view/world/enumdelegate.hpp index 82890c791c..757dbf0b44 100644 --- a/apps/opencs/view/world/enumdelegate.hpp +++ b/apps/opencs/view/world/enumdelegate.hpp @@ -46,6 +46,8 @@ namespace CSVWorld virtual void paint (QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + }; class EnumDelegateFactory : public CommandDelegateFactory From 2c1ca33a207c50e93c3c1527c2326bfb5090dd33 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 16 Jun 2015 15:39:54 +0300 Subject: [PATCH 48/57] Refactor Enum- and DataDisplayDelegate code --- .../opencs/view/world/datadisplaydelegate.cpp | 11 +-- apps/opencs/view/world/enumdelegate.cpp | 88 +++++++++---------- apps/opencs/view/world/enumdelegate.hpp | 2 + 3 files changed, 45 insertions(+), 56 deletions(-) diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index 71686d77d7..5f23d95d97 100644 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -62,16 +62,11 @@ void CSVWorld::DataDisplayDelegate::paint (QPainter *painter, const QStyleOption EnumDelegate::paint(painter, option, index); else { - unsigned int i = 0; - - for (; i < mValues.size(); ++i) + int valueIndex = getValueIndex(index); + if (valueIndex != -1) { - if (mValues.at(i).first == index.data().toInt()) - break; + paintIcon(painter, option, valueIndex); } - - if (i < mValues.size() ) - paintIcon (painter, option, i); } painter->restore(); diff --git a/apps/opencs/view/world/enumdelegate.cpp b/apps/opencs/view/world/enumdelegate.cpp index b9eca670a0..2190a62c69 100644 --- a/apps/opencs/view/world/enumdelegate.cpp +++ b/apps/opencs/view/world/enumdelegate.cpp @@ -10,6 +10,24 @@ #include "../../model/world/commands.hpp" +int CSVWorld::EnumDelegate::getValueIndex(const QModelIndex &index, int role) const +{ + if (index.isValid() && index.data(role).isValid()) + { + int value = index.data(role).toInt(); + + int size = static_cast(mValues.size()); + for (int i = 0; i < size; ++i) + { + if (value == mValues.at(i).first) + { + return i; + } + } + } + return -1; +} + void CSVWorld::EnumDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const { @@ -67,60 +85,43 @@ QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptio void CSVWorld::EnumDelegate::setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay) const { - if (QComboBox *comboBox = dynamic_cast (editor)) + if (QComboBox *comboBox = dynamic_cast(editor)) { - QVariant data = index.data (Qt::EditRole); - - if (tryDisplay && !data.isValid()) + int role = Qt::EditRole; + if (tryDisplay && !index.data(role).isValid()) { - data = index.data (Qt::DisplayRole); - if (!data.isValid()) + role = Qt::DisplayRole; + if (!index.data(role).isValid()) { return; } } - int value = data.toInt(); - - std::size_t size = mValues.size(); - - for (std::size_t i=0; isetCurrentIndex (i); - break; - } + int valueIndex = getValueIndex(index, role); + if (valueIndex != -1) + { + comboBox->setCurrentIndex(valueIndex); + } } } void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { - if (index.data().isValid()) + int valueIndex = getValueIndex(index); + if (valueIndex != -1) { - QStyleOptionViewItemV4 option2 (option); - - int value = index.data().toInt(); - - for (std::vector >::const_iterator iter (mValues.begin()); - iter!=mValues.end(); ++iter) - if (iter->first==value) - { - option2.text = iter->second; - - QApplication::style()->drawControl (QStyle::CE_ItemViewItem, &option2, painter); - - break; - } + QStyleOptionViewItemV4 itemOption(option); + itemOption.text = mValues.at(valueIndex).second; + QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &itemOption, painter); } } QSize CSVWorld::EnumDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { - if (index.data().isValid()) + int valueIndex = getValueIndex(index); + if (valueIndex != -1) { - int value = index.data().toInt(); - // Calculate the size hint as for a combobox. // So, the whole text is visible (isn't elided) when the editor is created QStyleOptionComboBox itemOption; @@ -129,20 +130,11 @@ QSize CSVWorld::EnumDelegate::sizeHint(const QStyleOptionViewItem &option, const itemOption.rect = option.rect; itemOption.state = option.state; - std::vector >::const_iterator current = mValues.begin(); - std::vector >::const_iterator end = mValues.end(); - for (; current != end; ++current) - { - if (current->first == value) - { - QSize valueSize = QSize(itemOption.fontMetrics.width(current->second), - itemOption.fontMetrics.height()); - itemOption.currentText = current->second; - return QApplication::style()->sizeFromContents(QStyle::CT_ComboBox, - &itemOption, - valueSize); - } - } + const QString &valueText = mValues.at(valueIndex).second; + QSize valueSize = QSize(itemOption.fontMetrics.width(valueText), itemOption.fontMetrics.height()); + + itemOption.currentText = valueText; + return QApplication::style()->sizeFromContents(QStyle::CT_ComboBox, &itemOption, valueSize); } return option.rect.size(); } diff --git a/apps/opencs/view/world/enumdelegate.hpp b/apps/opencs/view/world/enumdelegate.hpp index 757dbf0b44..a31945427e 100644 --- a/apps/opencs/view/world/enumdelegate.hpp +++ b/apps/opencs/view/world/enumdelegate.hpp @@ -19,6 +19,8 @@ namespace CSVWorld std::vector > mValues; + int getValueIndex(const QModelIndex &index, int role = Qt::DisplayRole) const; + private: virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model, From 6cfee630aaa24edff56efa9fc1b124272c2e1f92 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 16 Jun 2015 21:25:06 +0300 Subject: [PATCH 49/57] Proper size hint for DataDisplayDelegate --- .../opencs/view/world/datadisplaydelegate.cpp | 39 ++++++++++++++----- .../opencs/view/world/datadisplaydelegate.hpp | 7 ++-- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index 5f23d95d97..77ed33daa9 100644 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -12,7 +12,8 @@ CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, const QString &settingName, QObject *parent) : EnumDelegate (values, dispatcher, document, parent), mDisplayMode (Mode_TextOnly), - mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3), + mIcons (icons), mIconSize (QSize(16, 16)), + mHorizontalMargin(QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1), mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName) { buildPixmaps(); @@ -43,16 +44,36 @@ void CSVWorld::DataDisplayDelegate::setIconSize(const QSize& size) buildPixmaps(); } -void CSVWorld::DataDisplayDelegate::setIconLeftOffset(int offset) -{ - mIconLeftOffset = offset; -} - void CSVWorld::DataDisplayDelegate::setTextLeftOffset(int offset) { mTextLeftOffset = offset; } +QSize CSVWorld::DataDisplayDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QSize size = EnumDelegate::sizeHint(option, index); + + int valueIndex = getValueIndex(index); + if (valueIndex != -1) + { + if (mDisplayMode == Mode_IconOnly) + { + size.setWidth(mIconSize.width() + 2 * mHorizontalMargin); + } + else if (mDisplayMode == Mode_IconAndText) + { + int valueWidth = option.fontMetrics.width(mValues.at(valueIndex).second); + size.setWidth(size.width() + mIconSize.width() + mTextLeftOffset); + } + + if (mDisplayMode != Mode_TextOnly) + { + size.setHeight(qMax(size.height(), mIconSize.height())); + } + } + return size; +} + void CSVWorld::DataDisplayDelegate::paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { painter->save(); @@ -77,13 +98,13 @@ void CSVWorld::DataDisplayDelegate::paintIcon (QPainter *painter, const QStyleOp QRect iconRect = option.rect; QRect textRect = iconRect; - iconRect.setLeft(iconRect.left() + mIconLeftOffset); - iconRect.setRight(option.rect.right()); + iconRect.setLeft(iconRect.left() + mHorizontalMargin); + iconRect.setRight(option.rect.right() - mHorizontalMargin); if (mDisplayMode == Mode_IconAndText) { iconRect.setWidth(mIconSize.width()); textRect.setLeft(iconRect.right() + mTextLeftOffset); - textRect.setRight(option.rect.right()); + textRect.setRight(option.rect.right() - mHorizontalMargin); QString text = option.fontMetrics.elidedText(mValues.at(index).second, option.textElideMode, diff --git a/apps/opencs/view/world/datadisplaydelegate.hpp b/apps/opencs/view/world/datadisplaydelegate.hpp index 07fa1fd8d2..e565a3469e 100755 --- a/apps/opencs/view/world/datadisplaydelegate.hpp +++ b/apps/opencs/view/world/datadisplaydelegate.hpp @@ -31,7 +31,7 @@ namespace CSVWorld std::vector > mPixmaps; QSize mIconSize; - int mIconLeftOffset; + int mHorizontalMargin; int mTextLeftOffset; QString mSettingKey; @@ -45,12 +45,11 @@ namespace CSVWorld virtual void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + /// pass a QSize defining height / width of icon. Default is QSize (16,16). void setIconSize (const QSize& icon); - /// offset the horizontal position of the icon from the left edge of the cell. Default is 3 pixels. - void setIconLeftOffset (int offset); - /// offset the horizontal position of the text from the right edge of the icon. Default is 8 pixels. void setTextLeftOffset (int offset); From 1e368de28938723a2102b99c8ba7c3e1d81235e1 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 16 Jun 2015 21:47:27 +0300 Subject: [PATCH 50/57] Adjust columns of nested tables when a dialog subview is opened --- apps/opencs/view/world/dialoguesubview.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 66e8fcb7a2..fa3a3e27aa 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -469,8 +469,7 @@ void CSVWorld::EditWidget::remake(int row) mTable->data (mTable->index (row, idColumn)).toString().toUtf8().constData()); NestedTable* table = new NestedTable(mDocument, id, mNestedModels.back(), this); - // FIXME: does not work well when enum delegates are used - //table->resizeColumnsToContents(); + table->resizeColumnsToContents(); if(mTable->index(row, i).data().type() == QVariant::UserType) { From ed0942422370e5e99dc3f4eb6dfd4e74e38c0aff Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 17 Jun 2015 00:45:43 +0300 Subject: [PATCH 51/57] Correct the position of the colored rectangle in ColorEditor and ColorDelegate --- apps/opencs/view/widget/coloreditor.cpp | 8 ++++---- apps/opencs/view/world/colordelegate.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp index b31225962b..798502196e 100644 --- a/apps/opencs/view/widget/coloreditor.cpp +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -25,10 +25,10 @@ void CSVWidget::ColorEditor::paintEvent(QPaintEvent *event) QPushButton::paintEvent(event); QRect buttonRect = rect(); - QRect coloredRect(qRound(buttonRect.x() + buttonRect.width() / 4.0), - qRound(buttonRect.y() + buttonRect.height() / 4.0), - qRound(buttonRect.width() / 2.0), - qRound(buttonRect.height() / 2.0)); + QRect coloredRect(buttonRect.x() + qRound(buttonRect.width() / 4.0), + buttonRect.y() + qRound(buttonRect.height() / 4.0), + buttonRect.width() / 2, + buttonRect.height() / 2); QPainter painter(this); painter.fillRect(coloredRect, mColor); painter.setPen(Qt::black); diff --git a/apps/opencs/view/world/colordelegate.cpp b/apps/opencs/view/world/colordelegate.cpp index ae71f965a7..1a89fc675e 100644 --- a/apps/opencs/view/world/colordelegate.cpp +++ b/apps/opencs/view/world/colordelegate.cpp @@ -15,10 +15,10 @@ void CSVWorld::ColorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - QRect coloredRect(qRound(option.rect.x() + option.rect.width() / 4.0), - qRound(option.rect.y() + option.rect.height() / 4.0), - qRound(option.rect.width() / 2.0), - qRound(option.rect.height() / 2.0)); + QRect coloredRect(option.rect.x() + qRound(option.rect.width() / 4.0), + option.rect.y() + qRound(option.rect.height() / 4.0), + option.rect.width() / 2, + option.rect.height() / 2); painter->save(); painter->fillRect(coloredRect, index.data().value()); painter->setPen(Qt::black); From 2e40b68862256d63803f32eeba579b624adfdaa2 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 17 Jun 2015 22:47:39 +0300 Subject: [PATCH 52/57] Add a custom proxy model for Info tables --- apps/opencs/CMakeLists.txt | 2 +- .../model/world/infotableproxymodel.cpp | 40 +++++++++++++++++++ .../model/world/infotableproxymodel.hpp | 29 ++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/model/world/infotableproxymodel.cpp create mode 100644 apps/opencs/model/world/infotableproxymodel.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index bf39b36c19..d495415907 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -18,7 +18,7 @@ opencs_hdrs_noqt (model/doc opencs_units (model/world - idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable nestedtableproxymodel idtree + idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable nestedtableproxymodel idtree infotableproxymodel ) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp new file mode 100644 index 0000000000..1377ac20ef --- /dev/null +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -0,0 +1,40 @@ +#include "infotableproxymodel.hpp" + +#include "idtablebase.hpp" +#include "columns.hpp" + +CSMWorld::InfoTableProxyModel::InfoTableProxyModel(CSMWorld::UniversalId::Type type, QObject *parent) + : IdTableProxyModel(parent), + mType(type), + mSourceModel(NULL) +{ + Q_ASSERT(type == UniversalId::Type_TopicInfos || type == UniversalId::Type_JournalInfos); +} + +void CSMWorld::InfoTableProxyModel::setSourceModel(QAbstractItemModel *sourceModel) +{ + IdTableProxyModel::setSourceModel(sourceModel); + mSourceModel = dynamic_cast(sourceModel); +} + +bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + QModelIndex first = mSourceModel->index(getFirstInfoRow(left.row()), left.column()); + QModelIndex second = mSourceModel->index(getFirstInfoRow(right.row()), right.column()); + return IdTableProxyModel::lessThan(first, second); +} + +int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const +{ + Columns::ColumnId columnId = Columns::ColumnId_Topic; + if (mType == UniversalId::Type_JournalInfos) + { + columnId = Columns::ColumnId_Journal; + } + + int column = mSourceModel->findColumnIndex(columnId); + QVariant info = mSourceModel->data(mSourceModel->index(currentRow, column)); + while (--currentRow >= 0 && + mSourceModel->data(mSourceModel->index(currentRow, column)) == info); + return currentRow + 1; +} diff --git a/apps/opencs/model/world/infotableproxymodel.hpp b/apps/opencs/model/world/infotableproxymodel.hpp new file mode 100644 index 0000000000..a90607d348 --- /dev/null +++ b/apps/opencs/model/world/infotableproxymodel.hpp @@ -0,0 +1,29 @@ +#ifndef CSM_WORLD_INFOTABLEPROXYMODEL_HPP +#define CSM_WORLD_INFOTABLEPROXYMODEL_HPP + +#include "idtableproxymodel.hpp" +#include "universalid.hpp" + +namespace CSMWorld +{ + class IdTableBase; + + class InfoTableProxyModel : public IdTableProxyModel + { + UniversalId::Type mType; + IdTableBase *mSourceModel; + + int getFirstInfoRow(int currentRow) const; + ///< Finds the first row with the same topic (journal entry) as in \a currentRow + + public: + InfoTableProxyModel(UniversalId::Type type, QObject *parent = 0); + + void setSourceModel(QAbstractItemModel *sourceModel); + + protected: + virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + }; +} + +#endif From a6624ca576f6fd8b63097d0df99bdace6e244a7b Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 17 Jun 2015 23:46:51 +0300 Subject: [PATCH 53/57] Cache topic/journal first rows in InfoTableProxyModel --- .../model/world/infotableproxymodel.cpp | 22 +++++++++++++++++-- .../model/world/infotableproxymodel.hpp | 9 ++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index 1377ac20ef..7522e492b6 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -15,6 +15,11 @@ void CSMWorld::InfoTableProxyModel::setSourceModel(QAbstractItemModel *sourceMod { IdTableProxyModel::setSourceModel(sourceModel); mSourceModel = dynamic_cast(sourceModel); + connect(mSourceModel, + SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), + this, + SLOT(modelDataChanged(const QModelIndex &, const QModelIndex &))); + mFirstRowCache.clear(); } bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const @@ -33,8 +38,21 @@ int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const } int column = mSourceModel->findColumnIndex(columnId); - QVariant info = mSourceModel->data(mSourceModel->index(currentRow, column)); - while (--currentRow >= 0 && + QString info = mSourceModel->data(mSourceModel->index(currentRow, column)).toString(); + + if (mFirstRowCache.contains(info)) + { + return mFirstRowCache[info]; + } + + while (--currentRow >= 0 && mSourceModel->data(mSourceModel->index(currentRow, column)) == info); + + mFirstRowCache[info] = currentRow + 1; return currentRow + 1; } + +void CSMWorld::InfoTableProxyModel::modelDataChanged(const QModelIndex &/*topLeft*/, const QModelIndex &/*bottomRight*/) +{ + mFirstRowCache.clear(); +} diff --git a/apps/opencs/model/world/infotableproxymodel.hpp b/apps/opencs/model/world/infotableproxymodel.hpp index a90607d348..3228316264 100644 --- a/apps/opencs/model/world/infotableproxymodel.hpp +++ b/apps/opencs/model/world/infotableproxymodel.hpp @@ -1,6 +1,8 @@ #ifndef CSM_WORLD_INFOTABLEPROXYMODEL_HPP #define CSM_WORLD_INFOTABLEPROXYMODEL_HPP +#include + #include "idtableproxymodel.hpp" #include "universalid.hpp" @@ -10,9 +12,13 @@ namespace CSMWorld class InfoTableProxyModel : public IdTableProxyModel { + Q_OBJECT + UniversalId::Type mType; IdTableBase *mSourceModel; + mutable QHash mFirstRowCache; + int getFirstInfoRow(int currentRow) const; ///< Finds the first row with the same topic (journal entry) as in \a currentRow @@ -23,6 +29,9 @@ namespace CSMWorld protected: virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + + private slots: + void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); }; } From c60fed89ace024cdfc086fe74a471cab1c436ac3 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 17 Jun 2015 23:50:18 +0300 Subject: [PATCH 54/57] Enable sorting for Info tables --- apps/opencs/view/world/subviews.cpp | 4 ++-- apps/opencs/view/world/table.cpp | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index cd9b37a645..e81da23e13 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -68,10 +68,10 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactoryWithCreator); manager.add (CSMWorld::UniversalId::Type_TopicInfos, - new CSVDoc::SubViewFactoryWithCreator > (false)); + new CSVDoc::SubViewFactoryWithCreator >); manager.add (CSMWorld::UniversalId::Type_JournalInfos, - new CSVDoc::SubViewFactoryWithCreator > (false)); + new CSVDoc::SubViewFactoryWithCreator >); // Subviews for resources tables manager.add (CSMWorld::UniversalId::Type_Meshes, diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index b4efbd3c8f..072b645c42 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -13,6 +13,7 @@ #include "../../model/world/data.hpp" #include "../../model/world/commands.hpp" +#include "../../model/world/infotableproxymodel.hpp" #include "../../model/world/idtableproxymodel.hpp" #include "../../model/world/idtablebase.hpp" #include "../../model/world/idtable.hpp" @@ -276,7 +277,16 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, mModel = &dynamic_cast (*mDocument.getData().getTableModel (id)); - mProxyModel = new CSMWorld::IdTableProxyModel (this); + bool isInfoTable = id.getType() == CSMWorld::UniversalId::Type_TopicInfos || + id.getType() == CSMWorld::UniversalId::Type_JournalInfos; + if (isInfoTable) + { + mProxyModel = new CSMWorld::InfoTableProxyModel(id.getType(), this); + } + else + { + mProxyModel = new CSMWorld::IdTableProxyModel (this); + } mProxyModel->setSourceModel (mModel); mDispatcher = new CSMWorld::CommandDispatcher (document, id, this); From 63d46f7e6627385f1aa18527865e5befd4534622 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 18 Jun 2015 10:26:35 +0200 Subject: [PATCH 55/57] removed an unused variable --- apps/opencs/view/world/datadisplaydelegate.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index 77ed33daa9..72f45a18c1 100644 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -62,7 +62,6 @@ QSize CSVWorld::DataDisplayDelegate::sizeHint(const QStyleOptionViewItem &option } else if (mDisplayMode == Mode_IconAndText) { - int valueWidth = option.fontMetrics.width(mValues.at(valueIndex).second); size.setWidth(size.width() + mIconSize.width() + mTextLeftOffset); } From cf487581f79a917c4c68b1fe3b65d38110a3d520 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 18 Jun 2015 12:50:46 +0300 Subject: [PATCH 56/57] Show the pop-up of ColorEditor immediately after the editor creation in tables --- apps/opencs/view/widget/coloreditor.cpp | 17 +++++++++++++++-- apps/opencs/view/widget/coloreditor.hpp | 6 ++++-- apps/opencs/view/world/util.cpp | 6 ++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp index 798502196e..7ef1ec7b17 100644 --- a/apps/opencs/view/widget/coloreditor.cpp +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -6,13 +6,15 @@ #include #include #include +#include #include "colorpickerpopup.hpp" -CSVWidget::ColorEditor::ColorEditor(const QColor &color, QWidget *parent) +CSVWidget::ColorEditor::ColorEditor(const QColor &color, QWidget *parent, bool popupOnStart) : QPushButton(parent), mColor(color), - mColorPicker(new ColorPickerPopup(this)) + mColorPicker(new ColorPickerPopup(this)), + mPopupOnStart(popupOnStart) { setCheckable(true); connect(this, SIGNAL(clicked()), this, SLOT(showPicker())); @@ -35,6 +37,17 @@ void CSVWidget::ColorEditor::paintEvent(QPaintEvent *event) painter.drawRect(coloredRect); } +void CSVWidget::ColorEditor::showEvent(QShowEvent *event) +{ + QPushButton::showEvent(event); + if (isVisible() && mPopupOnStart) + { + setChecked(true); + showPicker(); + mPopupOnStart = false; + } +} + QColor CSVWidget::ColorEditor::color() const { return mColor; diff --git a/apps/opencs/view/widget/coloreditor.hpp b/apps/opencs/view/widget/coloreditor.hpp index cca26fade1..61232cb13e 100644 --- a/apps/opencs/view/widget/coloreditor.hpp +++ b/apps/opencs/view/widget/coloreditor.hpp @@ -17,17 +17,19 @@ namespace CSVWidget QColor mColor; ColorPickerPopup *mColorPicker; + bool mPopupOnStart; QPoint calculatePopupPosition(); public: - ColorEditor(const QColor &color, QWidget *parent = 0); + ColorEditor(const QColor &color, QWidget *parent = 0, bool popupOnStart = false); QColor color() const; void setColor(const QColor &color); protected: - void paintEvent(QPaintEvent *event); + virtual void paintEvent(QPaintEvent *event); + virtual void showEvent(QShowEvent *event); private slots: void showPicker(); diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index de088bffc9..5974987c0c 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -172,6 +172,12 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO { return QStyledItemDelegate::createEditor(parent, option, index); } + // For tables the pop-up of the color editor should appear immediately after the editor creation + // (the third parameter of ColorEditor's constructor) + else if (display == CSMWorld::ColumnBase::Display_Colour) + { + return new CSVWidget::ColorEditor(index.data().value(), parent, true); + } return createEditor (parent, option, index, display); } From 88d1f158d0978df8793af92069fbd128481451cb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 18 Jun 2015 16:36:27 +0200 Subject: [PATCH 57/57] made double click behaviour in report tables configurable (Fixes #2622) --- apps/opencs/model/settings/usersettings.cpp | 41 +++++++++++++++ apps/opencs/view/tools/reporttable.cpp | 57 +++++++++++++++++++-- apps/opencs/view/tools/reporttable.hpp | 11 ++++ 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 5b6e7ab8b7..d1dddf8ba5 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -234,6 +234,47 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() jumpToAdded->setDeclaredValues (jumpValues); } + declareSection ("report-input", "Report Input"); + { + QString none ("None"); + QString edit ("Edit"); + QString remove ("Remove"); + QString editAndRemove ("Edit And Remove"); + + QStringList values; + values << none << edit << remove << editAndRemove; + + QString toolTip = "
    " + "
  • None
  • " + "
  • Edit: Open a table or dialogue suitable for addressing the listed report
  • " + "
  • Remove: Remove the report from the report table
  • " + "
  • Edit and Remove: Open a table or dialogue suitable for addressing the listed report, then remove the report from the report table
  • " + "
"; + + Setting *doubleClick = createSetting (Type_ComboBox, "double", "Double Click"); + doubleClick->setDeclaredValues (values); + doubleClick->setDefaultValue (edit); + doubleClick->setToolTip ("Action on double click in report table:

" + toolTip); + + Setting *shiftDoubleClick = createSetting (Type_ComboBox, "double-s", + "Shift Double Click"); + shiftDoubleClick->setDeclaredValues (values); + shiftDoubleClick->setDefaultValue (remove); + shiftDoubleClick->setToolTip ("Action on shift double click in report table:

" + toolTip); + + Setting *ctrlDoubleClick = createSetting (Type_ComboBox, "double-c", + "Control Double Click"); + ctrlDoubleClick->setDeclaredValues (values); + ctrlDoubleClick->setDefaultValue (editAndRemove); + ctrlDoubleClick->setToolTip ("Action on control double click in report table:

" + toolTip); + + Setting *shiftCtrlDoubleClick = createSetting (Type_ComboBox, "double-sc", + "Shift Control Double Click"); + shiftCtrlDoubleClick->setDeclaredValues (values); + shiftCtrlDoubleClick->setDefaultValue (none); + shiftCtrlDoubleClick->setToolTip ("Action on shift control double click in report table:

" + toolTip); + } + declareSection ("search", "Search & Replace"); { Setting *before = createSetting (Type_SpinBox, "char-before", diff --git a/apps/opencs/view/tools/reporttable.cpp b/apps/opencs/view/tools/reporttable.cpp index c1c8a35dd3..e530e1159e 100644 --- a/apps/opencs/view/tools/reporttable.cpp +++ b/apps/opencs/view/tools/reporttable.cpp @@ -96,21 +96,35 @@ void CSVTools::ReportTable::mouseDoubleClickEvent (QMouseEvent *event) selectionModel()->select (index, QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Rows); - switch (modifiers) + std::map::iterator iter = + mDoubleClickActions.find (modifiers); + + if (iter==mDoubleClickActions.end()) { - case 0: + event->accept(); + return; + } + + switch (iter->second) + { + case Action_None: + + event->accept(); + break; + + case Action_Edit: event->accept(); showSelection(); break; - case Qt::ShiftModifier: + case Action_Remove: event->accept(); removeSelection(); break; - case Qt::ControlModifier: + case Action_EditAndRemove: event->accept(); showSelection(); @@ -155,7 +169,11 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, mReplaceAction = new QAction (tr ("Replace"), this); connect (mReplaceAction, SIGNAL (triggered()), this, SIGNAL (replaceRequest())); - addAction (mReplaceAction); + addAction (mReplaceAction); + + mDoubleClickActions.insert (std::make_pair (Qt::NoModifier, Action_Edit)); + mDoubleClickActions.insert (std::make_pair (Qt::ShiftModifier, Action_Remove)); + mDoubleClickActions.insert (std::make_pair (Qt::ControlModifier, Action_EditAndRemove)); } std::vector CSVTools::ReportTable::getDraggedRecords() const @@ -176,6 +194,35 @@ std::vector CSVTools::ReportTable::getDraggedRecords() co void CSVTools::ReportTable::updateUserSetting (const QString& name, const QStringList& list) { mIdTypeDelegate->updateUserSetting (name, list); + + QString base ("report-input/double"); + if (name.startsWith (base)) + { + QString modifierString = name.mid (base.size()); + Qt::KeyboardModifiers modifiers = 0; + + if (modifierString=="-s") + modifiers = Qt::ShiftModifier; + else if (modifierString=="-c") + modifiers = Qt::ControlModifier; + else if (modifierString=="-sc") + modifiers = Qt::ShiftModifier | Qt::ControlModifier; + + DoubleClickAction action = Action_None; + + QString value = list.at (0); + + if (value=="Edit") + action = Action_Edit; + else if (value=="Remove") + action = Action_Remove; + else if (value=="Edit And Remove") + action = Action_EditAndRemove; + + mDoubleClickActions[modifiers] = action; + + return; + } } std::vector CSVTools::ReportTable::getReplaceIndices (bool selection) const diff --git a/apps/opencs/view/tools/reporttable.hpp b/apps/opencs/view/tools/reporttable.hpp index c4d5b414ea..95ab07cbbf 100644 --- a/apps/opencs/view/tools/reporttable.hpp +++ b/apps/opencs/view/tools/reporttable.hpp @@ -1,6 +1,8 @@ #ifndef CSV_TOOLS_REPORTTABLE_H #define CSV_TOOLS_REPORTTABLE_H +#include + #include "../world/dragrecordtable.hpp" class QAction; @@ -21,11 +23,20 @@ namespace CSVTools { Q_OBJECT + enum DoubleClickAction + { + Action_None, + Action_Edit, + Action_Remove, + Action_EditAndRemove + }; + CSMTools::ReportModel *mModel; CSVWorld::CommandDelegate *mIdTypeDelegate; QAction *mShowAction; QAction *mRemoveAction; QAction *mReplaceAction; + std::map mDoubleClickActions; private: