diff --git a/CMakeLists.txt b/CMakeLists.txt index bd45a207c..bd437ed61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,8 +86,6 @@ option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest ang GMock fram # Sound source selection option(USE_FFMPEG "use ffmpeg for sound" ON) -option(USE_AUDIERE "use audiere for sound" ON) -option(USE_MPG123 "use mpg123 + libsndfile for sound" ON) # OS X deployment option(OPENMW_OSX_DEPLOYMENT OFF) @@ -171,27 +169,6 @@ if (USE_FFMPEG) endif (FFMPEG_FOUND) endif (USE_FFMPEG) -if (USE_AUDIERE AND NOT GOT_SOUND_INPUT) - find_package(Audiere) - if (AUDIERE_FOUND) - set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${AUDIERE_INCLUDE_DIR}) - set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${AUDIERE_LIBRARY}) - set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_AUDIERE) - set(GOT_SOUND_INPUT 1) - endif (AUDIERE_FOUND) -endif (USE_AUDIERE AND NOT GOT_SOUND_INPUT) - -if (USE_MPG123 AND NOT GOT_SOUND_INPUT) - find_package(MPG123 REQUIRED) - find_package(SNDFILE REQUIRED) - if (MPG123_FOUND AND SNDFILE_FOUND) - set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${MPG123_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR}) - set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${MPG123_LIBRARY} ${SNDFILE_LIBRARY}) - set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_MPG123) - set(GOT_SOUND_INPUT 1) - endif (MPG123_FOUND AND SNDFILE_FOUND) -endif (USE_MPG123 AND NOT GOT_SOUND_INPUT) - if (NOT GOT_SOUND_INPUT) message(WARNING "--------------------") message(WARNING "Failed to find any sound input packages") @@ -368,8 +345,8 @@ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg "${OpenMW_BINARY_DIR}/openmw.cfg.install") -configure_file(${OpenMW_SOURCE_DIR}/files/opencs.cfg - "${OpenMW_BINARY_DIR}/opencs.cfg") +configure_file(${OpenMW_SOURCE_DIR}/files/opencs.ini + "${OpenMW_BINARY_DIR}/opencs.ini") configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters "${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 3b8e8a4e6..35551f97b 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -60,7 +60,7 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool - scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap + scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable ) opencs_units (view/render @@ -97,6 +97,7 @@ opencs_units (view/settings listview rangeview resizeablestackedwidget + spinbox ) opencs_units_noqt (view/settings @@ -105,7 +106,6 @@ opencs_units_noqt (view/settings opencs_units (model/settings usersettings - settingmanager setting connector ) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index cd871c256..ad6c4be3d 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -27,7 +27,7 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) setupDataFiles (config.first); - CSMSettings::UserSettings::instance().loadSettings ("opencs.cfg"); + CSMSettings::UserSettings::instance().loadSettings ("opencs.ini"); mSettings.setModel (CSMSettings::UserSettings::instance()); ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string()); @@ -129,11 +129,6 @@ std::pair > CS::Editor::readConfi QString path = QString::fromUtf8 (iter->string().c_str()); mFileDialog.addFiles(path); } -/* - //load the settings into the userSettings instance. - const QString settingFileName = "opencs.cfg"; - CSMSettings::UserSettings::instance().loadSettings(settingFileName); -*/ return std::make_pair (dataDirs, variables["fallback-archive"].as >()); } diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index 1febb1678..b184a1ef1 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -13,6 +13,8 @@ #include +#include "model/world/universalid.hpp" + #ifdef Q_OS_MAC #include #endif @@ -47,6 +49,7 @@ int main(int argc, char *argv[]) Q_INIT_RESOURCE (resources); qRegisterMetaType ("std::string"); + qRegisterMetaType ("CSMWorld::UniversalId"); OgreInit::OgreInit ogreInit; diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index a441f4ae2..06c4a0988 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2247,8 +2247,10 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int))); connect (&mSaving, SIGNAL (done (int)), this, SLOT (operationDone (int))); - connect (&mSaving, SIGNAL (reportMessage (const QString&, int)), - this, SLOT (reportMessage (const QString&, int))); + + connect ( + &mSaving, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)), + this, SLOT (reportMessage (const CSMWorld::UniversalId&, const std::string&, int))); } CSMDoc::Document::~Document() @@ -2327,10 +2329,11 @@ void CSMDoc::Document::modificationStateChanged (bool clean) emit stateChanged (getState(), this); } -void CSMDoc::Document::reportMessage (const QString& message, int type) +void CSMDoc::Document::reportMessage (const CSMWorld::UniversalId& id, const std::string& message, + int type) { /// \todo find a better way to get these messages to the user. - std::cout << message.toUtf8().constData() << std::endl; + std::cout << message << std::endl; } void CSMDoc::Document::operationDone (int type) diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 11a4057d1..000f6761a 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -112,7 +112,8 @@ namespace CSMDoc void modificationStateChanged (bool clean); - void reportMessage (const QString& message, int type); + void reportMessage (const CSMWorld::UniversalId& id, const std::string& message, + int type); void operationDone (int type); diff --git a/apps/opencs/model/doc/operation.cpp b/apps/opencs/model/doc/operation.cpp index d29cc2631..42a432043 100644 --- a/apps/opencs/model/doc/operation.cpp +++ b/apps/opencs/model/doc/operation.cpp @@ -6,6 +6,8 @@ #include +#include "../world/universalid.hpp" + #include "state.hpp" #include "stage.hpp" @@ -80,7 +82,7 @@ void CSMDoc::Operation::abort() void CSMDoc::Operation::executeStage() { - std::vector messages; + Stage::Messages messages; while (mCurrentStage!=mStages.end()) { @@ -97,7 +99,7 @@ void CSMDoc::Operation::executeStage() } catch (const std::exception& e) { - emit reportMessage (e.what(), mType); + emit reportMessage (CSMWorld::UniversalId(), e.what(), mType); abort(); } @@ -108,8 +110,8 @@ void CSMDoc::Operation::executeStage() emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType); - for (std::vector::const_iterator iter (messages.begin()); iter!=messages.end(); ++iter) - emit reportMessage (iter->c_str(), mType); + for (Stage::Messages::const_iterator iter (messages.begin()); iter!=messages.end(); ++iter) + emit reportMessage (iter->first, iter->second, mType); if (mCurrentStage==mStages.end()) exit(); diff --git a/apps/opencs/model/doc/operation.hpp b/apps/opencs/model/doc/operation.hpp index 316eda78f..651283880 100644 --- a/apps/opencs/model/doc/operation.hpp +++ b/apps/opencs/model/doc/operation.hpp @@ -5,6 +5,11 @@ #include +namespace CSMWorld +{ + class UniversalId; +} + namespace CSMDoc { class Stage; @@ -46,7 +51,8 @@ namespace CSMDoc void progress (int current, int max, int type); - void reportMessage (const QString& message, int type); + void reportMessage (const CSMWorld::UniversalId& id, const std::string& message, + int type); void done (int type); diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index d7df2117d..eb93d9047 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -23,7 +23,7 @@ int CSMDoc::OpenSaveStage::setup() return 1; } -void CSMDoc::OpenSaveStage::perform (int stage, std::vector& messages) +void CSMDoc::OpenSaveStage::perform (int stage, Messages& messages) { mState.start (mDocument, mProjectFile); @@ -43,7 +43,7 @@ int CSMDoc::WriteHeaderStage::setup() return 1; } -void CSMDoc::WriteHeaderStage::perform (int stage, std::vector& messages) +void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages) { mState.getWriter().setVersion(); @@ -96,7 +96,7 @@ int CSMDoc::WriteDialogueCollectionStage::setup() return mTopics.getSize(); } -void CSMDoc::WriteDialogueCollectionStage::perform (int stage, std::vector& messages) +void CSMDoc::WriteDialogueCollectionStage::perform (int stage, Messages& messages) { const CSMWorld::Record& topic = mTopics.getRecord (stage); @@ -191,7 +191,7 @@ int CSMDoc::WriteRefIdCollectionStage::setup() return mDocument.getData().getReferenceables().getSize(); } -void CSMDoc::WriteRefIdCollectionStage::perform (int stage, std::vector& messages) +void CSMDoc::WriteRefIdCollectionStage::perform (int stage, Messages& messages) { mDocument.getData().getReferenceables().save (stage, mState.getWriter()); } @@ -204,7 +204,7 @@ CSMDoc::WriteFilterStage::WriteFilterStage (Document& document, SavingState& sta mDocument (document), mScope (scope) {} -void CSMDoc::WriteFilterStage::perform (int stage, std::vector& messages) +void CSMDoc::WriteFilterStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mDocument.getData().getFilters().getRecord (stage); @@ -223,7 +223,7 @@ int CSMDoc::CloseSaveStage::setup() return 1; } -void CSMDoc::CloseSaveStage::perform (int stage, std::vector& messages) +void CSMDoc::CloseSaveStage::perform (int stage, Messages& messages) { mState.getStream().close(); @@ -241,7 +241,7 @@ int CSMDoc::FinalSavingStage::setup() return 1; } -void CSMDoc::FinalSavingStage::perform (int stage, std::vector& messages) +void CSMDoc::FinalSavingStage::perform (int stage, Messages& messages) { if (mState.hasError()) { diff --git a/apps/opencs/model/doc/savingstages.hpp b/apps/opencs/model/doc/savingstages.hpp index b8eb0a3b3..c2f0a150a 100644 --- a/apps/opencs/model/doc/savingstages.hpp +++ b/apps/opencs/model/doc/savingstages.hpp @@ -39,7 +39,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -57,7 +57,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -75,7 +75,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -92,7 +92,7 @@ namespace CSMDoc } template - void WriteCollectionStage::perform (int stage, std::vector& messages) + void WriteCollectionStage::perform (int stage, Messages& messages) { CSMWorld::RecordBase::State state = mCollection.getRecord (stage).mState; @@ -130,7 +130,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -147,7 +147,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -161,7 +161,7 @@ namespace CSMDoc WriteFilterStage (Document& document, SavingState& state, CSMFilter::Filter::Scope scope); - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -177,7 +177,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; @@ -193,7 +193,7 @@ namespace CSMDoc virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; } diff --git a/apps/opencs/model/doc/stage.hpp b/apps/opencs/model/doc/stage.hpp index 1f96c60b4..ca34c2229 100644 --- a/apps/opencs/model/doc/stage.hpp +++ b/apps/opencs/model/doc/stage.hpp @@ -4,18 +4,22 @@ #include #include +#include "../world/universalid.hpp" + namespace CSMDoc { class Stage { public: + typedef std::vector > Messages; + virtual ~Stage(); virtual int setup() = 0; ///< \return number of steps - virtual void perform (int stage, std::vector& messages) = 0; + virtual void perform (int stage, Messages& messages) = 0; ///< Messages resulting from this stage will be appended to \a messages. }; } diff --git a/apps/opencs/model/settings/connector.cpp b/apps/opencs/model/settings/connector.cpp index 05a9ba8f9..5e1d64544 100644 --- a/apps/opencs/model/settings/connector.cpp +++ b/apps/opencs/model/settings/connector.cpp @@ -81,6 +81,7 @@ void CSMSettings::Connector::slotUpdateMaster() const } QString masterValue = mMasterView->value (masterColumn); + mMasterView->setSelectedValue (masterValue); } diff --git a/apps/opencs/model/settings/connector.hpp b/apps/opencs/model/settings/connector.hpp index da4c36d44..aaf9936d5 100644 --- a/apps/opencs/model/settings/connector.hpp +++ b/apps/opencs/model/settings/connector.hpp @@ -20,34 +20,46 @@ namespace CSMSettings { CSVSettings::View *mMasterView; - //map using the view pointer as a key to it's index value + ///map using the view pointer as a key to it's index value QList mSlaveViews; - //list of proxy values for each master value. - //value list order is indexed to the master value index. + ///list of proxy values for each master value. + ///value list order is indexed to the master value index. QMap < QString, QList > mProxyListMap; public: explicit Connector(CSVSettings::View *master, QObject *parent = 0); + ///Set the view which acts as a proxy for other setting views void setMasterView (CSVSettings::View *view); + + ///Add a view to be updated / update to the master void addSlaveView (CSVSettings::View *view, QList &masterProxyValues); private: + ///loosely matches lists of proxy values across registered slaves + ///against a proxy value list for a given master value bool proxyListsMatch (const QList &list1, const QList &list2) const; + ///loosely matches two string lists bool stringListsMatch (const QStringList &list1, const QStringList &list2) const; + ///retrieves current values of registered slave views QList getSlaveViewValues() const; public slots: + ///updates slave views with proxy values associated with current + ///master value void slotUpdateSlaves() const; + + ///updates master value associated with the currently selected + ///slave values, if applicable. void slotUpdateMaster() const; }; } diff --git a/apps/opencs/model/settings/setting.cpp b/apps/opencs/model/settings/setting.cpp index ca682b454..2f86d4ff8 100644 --- a/apps/opencs/model/settings/setting.cpp +++ b/apps/opencs/model/settings/setting.cpp @@ -1,13 +1,8 @@ #include "setting.hpp" #include "support.hpp" -CSMSettings::Setting::Setting() -{ - buildDefaultSetting(); -} - CSMSettings::Setting::Setting(SettingType typ, const QString &settingName, - const QString &pageName, const QStringList &values) + const QString &pageName) : mIsEditorSetting (false) { buildDefaultSetting(); @@ -19,10 +14,9 @@ CSMSettings::Setting::Setting(SettingType typ, const QString &settingName, setProperty (Property_IsMultiValue, QVariant(true).toString()); //view type is related to setting type by an order of magnitude - setProperty (Property_ViewType, QVariant (settingType / 10).toString()); + setProperty (Property_SettingType, QVariant (settingType).toString()); setProperty (Property_Page, pageName); setProperty (Property_Name, settingName); - setProperty (Property_DeclaredValues, values); } void CSMSettings::Setting::buildDefaultSetting() @@ -51,7 +45,7 @@ void CSMSettings::Setting::addProxy (const Setting *setting, foreach (const QString &val, vals) list << (QStringList() << val); - mProxies [setting->page() + '.' + setting->name()] = list; + mProxies [setting->page() + '/' + setting->name()] = list; } void CSMSettings::Setting::addProxy (const Setting *setting, @@ -60,7 +54,7 @@ void CSMSettings::Setting::addProxy (const Setting *setting, if (serializable()) setProperty (Property_Serializable, false); - mProxies [setting->page() + '.' + setting->name()] = list; + mProxies [setting->page() + '/' + setting->name()] = list; } void CSMSettings::Setting::setColumnSpan (int value) @@ -73,19 +67,14 @@ int CSMSettings::Setting::columnSpan() const return property (Property_ColumnSpan).at(0).toInt(); } -QStringList CSMSettings::Setting::declaredValues() const +void CSMSettings::Setting::setDeclaredValues (QStringList list) { - return property (Property_DeclaredValues); + setProperty (Property_DeclaredValues, list); } -void CSMSettings::Setting::setDefinedValues (QStringList list) -{ - setProperty (Property_DefinedValues, list); -} - -QStringList CSMSettings::Setting::definedValues() const +QStringList CSMSettings::Setting::declaredValues() const { - return property (Property_DefinedValues); + return property (Property_DeclaredValues); } QStringList CSMSettings::Setting::property (SettingProperty prop) const @@ -96,6 +85,16 @@ QStringList CSMSettings::Setting::property (SettingProperty prop) const return mProperties.at(prop); } +void CSMSettings::Setting::setDefaultValue (int value) +{ + setDefaultValues (QStringList() << QVariant (value).toString()); +} + +void CSMSettings::Setting::setDefaultValue (double value) +{ + setDefaultValues (QStringList() << QVariant (value).toString()); +} + void CSMSettings::Setting::setDefaultValue (const QString &value) { setDefaultValues (QStringList() << value); @@ -165,6 +164,16 @@ bool CSMSettings::Setting::serializable() const return (property (Property_Serializable).at(0) == "true"); } +void CSMSettings::Setting::setSpecialValueText(const QString &text) +{ + setProperty (Property_SpecialValueText, text); +} + +QString CSMSettings::Setting::specialValueText() const +{ + return property (Property_SpecialValueText).at(0); +} + void CSMSettings::Setting::setName (const QString &value) { setProperty (Property_Name, value); @@ -185,6 +194,16 @@ QString CSMSettings::Setting::page() const return property (Property_Page).at(0); } +void CSMSettings::Setting::setPrefix (const QString &value) +{ + setProperty (Property_Prefix, value); +} + +QString CSMSettings::Setting::prefix() const +{ + return property (Property_Prefix).at(0); +} + void CSMSettings::Setting::setRowSpan (const int value) { setProperty (Property_RowSpan, value); @@ -195,15 +214,106 @@ int CSMSettings::Setting::rowSpan () const return property (Property_RowSpan).at(0).toInt(); } -void CSMSettings::Setting::setViewType (int vType) +void CSMSettings::Setting::setSingleStep (int value) { - setProperty (Property_ViewType, vType); + setProperty (Property_SingleStep, value); +} + +void CSMSettings::Setting::setSingleStep (double value) +{ + setProperty (Property_SingleStep, value); +} + +QString CSMSettings::Setting::singleStep() const +{ + return property (Property_SingleStep).at(0); +} + +void CSMSettings::Setting::setSuffix (const QString &value) +{ + setProperty (Property_Suffix, value); +} + +QString CSMSettings::Setting::suffix() const +{ + return property (Property_Suffix).at(0); +} + +void CSMSettings::Setting::setTickInterval (int value) +{ + setProperty (Property_TickInterval, value); +} + +int CSMSettings::Setting::tickInterval () const +{ + return property (Property_TickInterval).at(0).toInt(); +} + +void CSMSettings::Setting::setTicksAbove (bool state) +{ + setProperty (Property_TicksAbove, state); +} + +bool CSMSettings::Setting::ticksAbove() const +{ + return (property (Property_TicksAbove).at(0) == "true"); +} + +void CSMSettings::Setting::setTicksBelow (bool state) +{ + setProperty (Property_TicksBelow, state); +} + +bool CSMSettings::Setting::ticksBelow() const +{ + return (property (Property_TicksBelow).at(0) == "true"); +} + +void CSMSettings::Setting::setType (int settingType) +{ + setProperty (Property_SettingType, settingType); +} + +CSMSettings::SettingType CSMSettings::Setting::type() const +{ + return static_cast ( property ( + Property_SettingType).at(0).toInt()); +} + +void CSMSettings::Setting::setMaximum (int value) +{ + setProperty (Property_Maximum, value); +} + +void CSMSettings::Setting::setMaximum (double value) +{ + setProperty (Property_Maximum, value); +} + +QString CSMSettings::Setting::maximum() const +{ + return property (Property_Maximum).at(0); +} + +void CSMSettings::Setting::setMinimum (int value) +{ + setProperty (Property_Minimum, value); +} + +void CSMSettings::Setting::setMinimum (double value) +{ + setProperty (Property_Minimum, value); +} + +QString CSMSettings::Setting::minimum() const +{ + return property (Property_Minimum).at(0); } CSVSettings::ViewType CSMSettings::Setting::viewType() const { - return static_cast - (property(Property_ViewType).at(0).toInt()); + return static_cast ( property ( + Property_SettingType).at(0).toInt() / 10); } void CSMSettings::Setting::setViewColumn (int value) @@ -241,6 +351,17 @@ int CSMSettings::Setting::widgetWidth() const { return property (Property_WidgetWidth).at(0).toInt(); } + +void CSMSettings::Setting::setWrapping (bool state) +{ + setProperty (Property_Wrapping, state); +} + +bool CSMSettings::Setting::wrapping() const +{ + return (property (Property_Wrapping).at(0) == "true"); +} + void CSMSettings::Setting::setProperty (SettingProperty prop, bool value) { setProperty (prop, QStringList() << QVariant (value).toString()); @@ -251,6 +372,11 @@ void CSMSettings::Setting::setProperty (SettingProperty prop, int value) setProperty (prop, QStringList() << QVariant (value).toString()); } +void CSMSettings::Setting::setProperty (SettingProperty prop, double value) +{ + setProperty (prop, QStringList() << QVariant (value).toString()); +} + void CSMSettings::Setting::setProperty (SettingProperty prop, const QString &value) { @@ -263,18 +389,3 @@ void CSMSettings::Setting::setProperty (SettingProperty prop, if (prop < mProperties.size()) mProperties.replace (prop, value); } - -QDataStream &operator <<(QDataStream &stream, const CSMSettings::Setting& setting) -{ - // stream << setting.properties(); - - // stream << setting.proxies(); - return stream; -} - -QDataStream &operator >>(QDataStream& stream, CSMSettings::Setting& setting) -{ - // stream >> setting.properties(); - // stream >> setting.proxies(); - return stream; -} diff --git a/apps/opencs/model/settings/setting.hpp b/apps/opencs/model/settings/setting.hpp index 1463e4d7d..e40302f00 100644 --- a/apps/opencs/model/settings/setting.hpp +++ b/apps/opencs/model/settings/setting.hpp @@ -7,11 +7,17 @@ namespace CSMSettings { - //Maps setting id ("page.name") to a list of corresponding proxy values. - //Order of proxy value stringlists corresponds to order of master proxy's - //values in it's declared value list + //QString is the setting id in the form of "page/name" + //QList is a list of stringlists of proxy values. + //Order is important! Proxy stringlists are matched against + //master values by their position in the QList. typedef QMap > ProxyValueMap; + ///Setting class is the interface for the User Settings. It contains + ///a great deal of boiler plate to provide the core API functions, as + ///well as the property() functions which use enumeration to be iterable. + ///This makes the Setting class capable of being manipulated by script. + ///See CSMSettings::support.hpp for enumerations / string values. class Setting { QList mProperties; @@ -19,20 +25,12 @@ namespace CSMSettings bool mIsEditorSetting; - //QString is the setting id in the form of "page.name" - //QList is a list of stringlists of proxy values. - //Order is important! Proxy stringlists are matched against - //master values by their position in the QList. ProxyValueMap mProxies; public: - - explicit Setting(); - explicit Setting(SettingType typ, const QString &settingName, - const QString &pageName, - const QStringList &values = QStringList()); + const QString &pageName); void addProxy (const Setting *setting, const QStringList &vals); void addProxy (const Setting *setting, const QList &list); @@ -46,9 +44,8 @@ namespace CSMSettings void setDeclaredValues (QStringList list); QStringList declaredValues() const; - void setDefinedValues (QStringList list); - QStringList definedValues() const; - + void setDefaultValue (int value); + void setDefaultValue (double value); void setDefaultValue (const QString &value); void setDefaultValues (const QStringList &values); @@ -66,12 +63,26 @@ namespace CSMSettings void setIsMultiValue (bool state); bool isMultiValue() const; + void setMask (const QString &value); + QString mask() const; + + void setMaximum (int value); + void setMaximum (double value); + QString maximum() const; + + void setMinimum (int value); + void setMinimum (double value); + QString minimum() const; + void setName (const QString &value); QString name() const; void setPage (const QString &value); QString page() const; + void setPrefix (const QString &value); + QString prefix() const; + void setRowSpan (const int value); int rowSpan() const; @@ -80,6 +91,25 @@ namespace CSMSettings void setSerializable (bool state); bool serializable() const; + void setSpecialValueText (const QString &text); + QString specialValueText() const; + + void setSingleStep (int value); + void setSingleStep (double value); + QString singleStep() const; + + void setSuffix (const QString &value); + QString suffix() const; + + void setTickInterval (int value); + int tickInterval() const; + + void setTicksAbove (bool state); + bool ticksAbove() const; + + void setTicksBelow (bool state); + bool ticksBelow() const; + void setViewColumn (int value); int viewColumn() const; @@ -88,9 +118,14 @@ namespace CSMSettings void setViewRow (int value); int viewRow() const; - void setViewType (int vType); + void setType (int settingType); + CSMSettings::SettingType type() const; + CSVSettings::ViewType viewType() const; + void setWrapping (bool state); + bool wrapping() const; + void setWidgetWidth (int value); int widgetWidth() const; @@ -100,6 +135,7 @@ namespace CSMSettings ///boilerplate code to convert setting values of common types void setProperty (SettingProperty prop, bool value); void setProperty (SettingProperty prop, int value); + void setProperty (SettingProperty prop, double value); void setProperty (SettingProperty prop, const QString &value); void setProperty (SettingProperty prop, const QStringList &value); @@ -111,9 +147,4 @@ namespace CSMSettings }; } -Q_DECLARE_METATYPE(CSMSettings::Setting) - -QDataStream &operator <<(QDataStream &stream, const CSMSettings::Setting& setting); -QDataStream &operator >>(QDataStream &stream, CSMSettings::Setting& setting); - #endif // CSMSETTINGS_SETTING_HPP diff --git a/apps/opencs/model/settings/settingmanager.cpp b/apps/opencs/model/settings/settingmanager.cpp deleted file mode 100644 index eec4c54cf..000000000 --- a/apps/opencs/model/settings/settingmanager.cpp +++ /dev/null @@ -1,342 +0,0 @@ -#include -#include -#include -#include -#include - -#include "setting.hpp" -#include "settingmanager.hpp" - -CSMSettings::SettingManager::SettingManager(QObject *parent) : - QObject(parent) -{ - mReadWriteMessage = QObject::tr("
Could not open or create file for \ - writing

Please make sure you have the right\ - permissions and try again.
"); - - mReadOnlyMessage = QObject::tr("
Could not open file for \ - reading

Please make sure you have the \ - right permissions and try again.
"); - -} - -void CSMSettings::SettingManager::dumpModel() -{ - foreach (Setting *setting, mSettings) - { - if (setting->proxyLists().isEmpty()) - continue; - } -} - -CSMSettings::Setting *CSMSettings::SettingManager::createSetting - (CSMSettings::SettingType typ, const QString &page, const QString &name, - const QStringList &values) -{ - //get list of all settings for the current setting name - if (findSetting (page, name)) - { - qWarning() << "Duplicate declaration encountered: " - << (name + '.' + page); - return 0; - } - - Setting *setting = new Setting (typ, name, page, values); - - //add declaration to the model - mSettings.append (setting); - - return setting; -} - -CSMSettings::DefinitionPageMap - CSMSettings::SettingManager::readFilestream (QTextStream *stream) -{ - //regEx's for page names and keys / values - QRegExp pageRegEx ("^\\[([^]]+)\\]"); - QRegExp keyRegEx ("^([^=]+)\\s*=\\s*(.+)$"); - - QString currPage = "Unassigned"; - - DefinitionPageMap pageMap; - - if (!stream) - { - displayFileErrorMessage(mReadWriteMessage, false); - return pageMap; - } - - if (stream->atEnd()) - return pageMap; - - DefinitionMap *settingMap = new DefinitionMap(); - pageMap[currPage] = settingMap; - - while (!stream->atEnd()) - { - QString line = stream->readLine().simplified(); - - if (line.isEmpty() || line.startsWith("#")) - continue; - - //page name found - if (pageRegEx.exactMatch(line)) - { - currPage = pageRegEx.cap(1).simplified().trimmed(); - settingMap = new DefinitionMap(); - pageMap[currPage] = settingMap; - continue; - } - - //setting definition found - if ( (keyRegEx.indexIn(line) != -1)) - { - QString settingName = keyRegEx.cap(1).simplified(); - QString settingValue = keyRegEx.cap(2).simplified(); - - if (!settingMap->contains (settingName)) - settingMap->insert (settingName, new QStringList()); - - settingMap->value(settingName)->append(settingValue); - } - } - - //return empty map if no settings were ever added to - if (pageMap.size() == 1) - { - QString pageKey = pageMap.keys().at(0); - if (pageMap[pageKey]->size() == 0) - pageMap.clear(); - } - - return pageMap; -} - -bool CSMSettings::SettingManager::writeFilestream(QTextStream *stream, - const QMap &settingListMap) -{ - if (!stream) - { - displayFileErrorMessage(mReadWriteMessage, false); - return false; - } - //disabled after rolling selector class into view. Need to - //iterate views to get setting definitions before writing to file - - QStringList sectionKeys; - - foreach (const QString &key, settingListMap.keys()) - { - QStringList names = key.split('.'); - QString section = names.at(0); - - if (!sectionKeys.contains(section)) - if (!settingListMap.value(key).isEmpty()) - sectionKeys.append (section); - } - - foreach (const QString §ion, sectionKeys) - { - *stream << '[' << section << "]\n"; - foreach (const QString &key, settingListMap.keys()) - { - QStringList names = key.split('.'); - - if (names.at(0) != section) - continue; - - QStringList list = settingListMap.value(key); - - if (list.isEmpty()) - continue; - - QString name = names.at(1); - - foreach (const QString value, list) - { - if (value.isEmpty()) - continue; - - *stream << name << " = " << value << '\n'; - } - } - } - - destroyStream (stream); - return true; -} - -void CSMSettings::SettingManager::mergeSettings(DefinitionPageMap &destMap, DefinitionPageMap &srcMap) -{ - if (srcMap.isEmpty()) - return; - - foreach (const QString &pageKey, srcMap.keys()) - { - DefinitionMap *srcSetting = srcMap.value(pageKey); - //Unique Page: - //insertfrom the source map - if (!destMap.keys().contains (pageKey)) - { - destMap.insert (pageKey, srcSetting); - continue; - } - - DefinitionMap *destSetting = destMap.value(pageKey); - - //Duplicate Page: - //iterate the settings in the source and check for duplicates in the - //destination - foreach (const QString &srcKey, srcSetting->keys()) - { - //insert into destination if unique - if (!destSetting->keys().contains (srcKey)) - destSetting->insert(srcKey, srcSetting->value (srcKey)); - } - } -} - -QTextStream *CSMSettings::SettingManager::openFilestream (const QString &filePath, - bool isReadOnly) const -{ - QIODevice::OpenMode openFlags = QIODevice::Text; - - if (isReadOnly) - openFlags = QIODevice::ReadOnly | openFlags; - else - openFlags = QIODevice::ReadWrite | QIODevice::Truncate | openFlags; - - QFile *file = new QFile(filePath); - QTextStream *stream = 0; - - if (file->open(openFlags)) - stream = new QTextStream(file); - - if (stream) - stream->setCodec(QTextCodec::codecForName("UTF-8")); - - return stream; -} - -void CSMSettings::SettingManager::destroyStream(QTextStream *stream) const -{ - stream->device()->close(); - - delete stream; -} - -void CSMSettings::SettingManager::displayFileErrorMessage(const QString &message, - bool isReadOnly) const -{ - // File cannot be opened or created - QMessageBox msgBox; - msgBox.setWindowTitle(QObject::tr("OpenCS configuration file I/O error")); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - - if (!isReadOnly) - msgBox.setText (mReadWriteMessage + message); - else - msgBox.setText (message); - - msgBox.exec(); -} - -void CSMSettings::SettingManager::addDefinitions (DefinitionPageMap &pageMap) -{ - foreach (QString pageName, pageMap.keys()) - { - DefinitionMap *settingMap = pageMap.value (pageName); - - foreach (QString settingName, (*settingMap).keys()) - { - QStringList *values = settingMap->value (settingName); - Setting *setting = findSetting (pageName, settingName); - - if (!setting) - { - qWarning() << "Found definitions for undeclared setting " - << pageName << "." << settingName; - continue; - } - - if (values->size() == 0) - values->append (setting->defaultValues()); - - setting->setDefinedValues (*values); - } - } -} - -QList CSMSettings::SettingManager::findSettings - (const QStringList &list) -{ - QList settings; - - foreach (const QString &value, list) - { - QStringList names = value.split(".", QString::SkipEmptyParts); - - if (names.size() != 2) - continue; - - Setting *setting = findSetting (names.at(0), names.at(1)); - - if (!setting) - continue; - - settings.append (setting); - } - - return settings; -} - - -CSMSettings::Setting *CSMSettings::SettingManager::findSetting - (const QString &pageName, const QString &settingName) -{ - foreach (Setting *setting, mSettings) - { - if (setting->name() == settingName) - { - if (setting->page() == pageName) - return setting; - } - } - return 0; -} - -QList CSMSettings::SettingManager::findSettings - (const QString &pageName) -{ - QList settings; - - foreach (Setting *setting, mSettings) - { - if (setting->page() == pageName) - settings.append (setting); - } - return settings; -} - -CSMSettings::SettingPageMap CSMSettings::SettingManager::settingPageMap() const -{ - SettingPageMap pageMap; - - foreach (Setting *setting, mSettings) - pageMap[setting->page()].append (setting); - - return pageMap; -} - -void CSMSettings::SettingManager::updateUserSetting(const QString &settingKey, - const QStringList &list) -{ - QStringList names = settingKey.split('.'); - - Setting *setting = findSetting (names.at(0), names.at(1)); - - setting->setDefinedValues (list); - - emit userSettingUpdated (settingKey, list); -} diff --git a/apps/opencs/model/settings/settingmanager.hpp b/apps/opencs/model/settings/settingmanager.hpp deleted file mode 100644 index ca8a2cc7b..000000000 --- a/apps/opencs/model/settings/settingmanager.hpp +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef CSMSETTINGS_SETTINGMANAGER_HPP -#define CSMSETTINGS_SETTINGMANAGER_HPP - -#include -#include -#include -#include - -#include "support.hpp" -#include "setting.hpp" - -namespace CSMSettings -{ - - typedef QMap DefinitionMap; - typedef QMap DefinitionPageMap; - - typedef QMap > SettingPageMap; - - class SettingManager : public QObject - { - Q_OBJECT - - QString mReadOnlyMessage; - QString mReadWriteMessage; - QList mSettings; - - public: - explicit SettingManager(QObject *parent = 0); - - ///retrieve a setting object from a given page and setting name - Setting *findSetting - (const QString &pageName, const QString &settingName); - - ///retrieve all settings for a specified page - QList findSettings (const QString &pageName); - - ///retrieve all settings named in the attached list. - ///Setting names are specified in "PageName.SettingName" format. - QList findSettings (const QStringList &list); - - ///Retreive a map of the settings, keyed by page name - SettingPageMap settingPageMap() const; - - protected: - - ///add a new setting to the model and return it - Setting *createSetting (CSMSettings::SettingType typ, - const QString &page, const QString &name, - const QStringList &values = QStringList()); - - ///add definitions to the settings specified in the page map - void addDefinitions (DefinitionPageMap &pageMap); - - ///read setting definitions from file - DefinitionPageMap readFilestream(QTextStream *stream); - - ///write setting definitions to file - bool writeFilestream (QTextStream *stream, - const QMap &settingMap); - - ///merge PageMaps of settings when loading from multiple files - void mergeSettings (DefinitionPageMap &destMap, DefinitionPageMap &srcMap); - - QTextStream *openFilestream (const QString &filePath, - bool isReadOnly) const; - - void destroyStream(QTextStream *stream) const; - - void displayFileErrorMessage(const QString &message, - bool isReadOnly) const; - - QList settings() const { return mSettings; } - void dumpModel(); - - signals: - - void userSettingUpdated (const QString &, const QStringList &); - - public slots: - - void updateUserSetting (const QString &, const QStringList &); - }; -} -#endif // CSMSETTINGS_SETTINGMANAGER_HPP diff --git a/apps/opencs/model/settings/support.hpp b/apps/opencs/model/settings/support.hpp index ce808587f..229e293b8 100644 --- a/apps/opencs/model/settings/support.hpp +++ b/apps/opencs/model/settings/support.hpp @@ -7,27 +7,15 @@ #include #include -//Typedefs -namespace CSMSettings -{ - // Definition / Declaration model typedefs - // "Pair" = Setting name and specific data - // "ListItem" = Page name and associated setting pair - - typedef QPair StringPair; - typedef QPair StringListPair; - typedef QList StringListPairs; - -} - //Enums namespace CSMSettings { + ///Enumerated properties for scripting enum SettingProperty { Property_Name = 0, Property_Page = 1, - Property_ViewType = 2, + Property_SettingType = 2, Property_IsMultiValue = 3, Property_IsMultiLine = 4, Property_WidgetWidth = 5, @@ -37,14 +25,25 @@ namespace CSMSettings Property_Serializable = 9, Property_ColumnSpan = 10, Property_RowSpan = 11, + Property_Minimum = 12, + Property_Maximum = 13, + Property_SpecialValueText = 14, + Property_Prefix = 15, + Property_Suffix = 16, + Property_SingleStep = 17, + Property_Wrapping = 18, + Property_TickInterval = 19, + Property_TicksAbove = 20, + Property_TicksBelow = 21, //Stringlists should always be the last items - Property_DefaultValues = 12, - Property_DeclaredValues = 13, - Property_DefinedValues = 14, - Property_Proxies = 15 + Property_DefaultValues = 22, + Property_DeclaredValues = 23, + Property_DefinedValues = 24, + Property_Proxies = 25 }; + ///Basic setting widget types. enum SettingType { /* @@ -64,22 +63,19 @@ namespace CSMSettings Type_ListView = 10, Type_ComboBox = 11, Type_SpinBox = 21, - Type_Slider = 23, - Type_Dial = 24, + Type_DoubleSpinBox = 23, + Type_Slider = 25, + Type_Dial = 27, Type_TextArea = 30, - Type_LineEdit = 31 + Type_LineEdit = 31, + Type_Undefined = 40 }; - enum MergeMethod - { - Merge_Accept, - Merge_Ignore, - Merge_Overwrite - }; } namespace CSVSettings { + ///Categorical view types which encompass the setting widget types enum ViewType { ViewType_Boolean = 0, @@ -88,18 +84,12 @@ namespace CSVSettings ViewType_Text = 3, ViewType_Undefined = 4 }; - - enum Alignment - { - Align_Left = Qt::AlignLeft, - Align_Center = Qt::AlignHCenter, - Align_Right = Qt::AlignRight - }; } -// + namespace CSMSettings { + ///used to construct default settings in the Setting class struct PropertyDefaultValues { int id; @@ -107,28 +97,44 @@ namespace CSMSettings QVariant value; }; + ///strings which correspond to setting values. These strings represent + ///the script language keywords which would be used to declare setting + ///views for 3rd party addons const QString sPropertyNames[] = { - "name", "page", "view_type", "is_multi_value", + "name", "page", "setting_type", "is_multi_value", "is_multi_line", "widget_width", "view_row", "view_column", "delimiter", - "is_serializable","column_span", "row_span", + "is_serializable","column_span", "row_span", "minimum", "maximum", + "special_value_text", "prefix", "suffix", "single_step", "wrapping", + "tick_interval", "ticks_above", "ticks_below", "defaults", "declarations", "definitions", "proxies" }; + ///Default values for a setting. Used in setting creation. const QString sPropertyDefaults[] = { "", //name "", //page - "0", //view type + "40", //setting type "false", //multivalue "false", //multiline - "0", //widget width + "7", //widget width "-1", //view row "-1", //view column ",", //delimiter "true", //serialized "1", //column span "1", //row span + "0", //value range + "0", //value minimum + "0", //value maximum + "", //special text + "", //prefix + "", //suffix + "false", //wrapping + "1", //tick interval + "false", //ticks above + "true", //ticks below "", //default values "", //declared values "", //defined values diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index fa89fceee..1a9125439 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -1,21 +1,14 @@ #include "usersettings.hpp" -#include -#include -#include -#include -#include -#include -#include - +#include #include -#include #include #include #include "setting.hpp" #include "support.hpp" +#include /** * Workaround for problems with whitespaces in paths in older versions of Boost library @@ -40,6 +33,8 @@ CSMSettings::UserSettings::UserSettings() assert(!mUserSettingsInstance); mUserSettingsInstance = this; + mSettingDefinitions = 0; + buildSettingModelDefaults(); } @@ -51,7 +46,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() Setting *height = createSetting (Type_LineEdit, section, "Height"); width->setWidgetWidth (5); - height->setWidgetWidth (5); + height->setWidgetWidth (8); width->setDefaultValues (QStringList() << "1024"); height->setDefaultValues (QStringList() << "768"); @@ -66,13 +61,10 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() *Create the proxy setting for predefined values */ Setting *preDefined = createSetting (Type_ComboBox, section, - "Pre-Defined", - QStringList() - << "640 x 480" - << "800 x 600" - << "1024 x 768" - << "1440 x 900" - ); + "Pre-Defined"); + + preDefined->setDeclaredValues (QStringList() << "640 x 480" + << "800 x 600" << "1024 x 768" << "1440 x 900"); preDefined->setViewLocation (1, 1); preDefined->setWidgetWidth (10); @@ -95,12 +87,13 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() << defaultValue << "Icon Only" << "Text Only"; Setting *rsd = createSetting (Type_RadioButton, - section, "Record Status Display", - values); + section, "Record Status Display"); Setting *ritd = createSetting (Type_RadioButton, - section, "Referenceable ID Type Display", - values); + section, "Referenceable ID Type Display"); + + rsd->setDeclaredValues (values); + ritd->setDeclaredValues (values); rsd->setEditorSetting (true); ritd->setEditorSetting (true); @@ -108,44 +101,68 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() section = "Proxy Selection Test"; { - //create three setting objects, specifying the basic widget type, - //the setting view name, the page name, and the default value + /****************************************************************** + * There are three types of values: + * + * Declared values + * + * Pre-determined values, typically for + * combobox drop downs and boolean (radiobutton / checkbox) labels. + * These values represent the total possible list of values that + * may define a setting. No other values are allowed. + * + * Defined values + * + * Values which represent the actual, current value of + * a setting. For settings with declared values, this must be one + * or several declared values, as appropriate. + * + * Proxy values + * Values the proxy master updates the proxy slave when + * it's own definition is set / changed. These are definitions for + * proxy slave settings, but must match any declared values the + * proxy slave has, if any. + *******************************************************************/ +/* + //create setting objects, specifying the basic widget type, + //the page name, and the view name + Setting *masterBoolean = createSetting (Type_RadioButton, section, - "Master Proxy", - QStringList() - << "Profile One" << "Profile Two" - << "Profile Three" << "Profile Four" - ); + "Master Proxy"); Setting *slaveBoolean = createSetting (Type_CheckBox, section, - "Proxy Checkboxes", - QStringList() << "One" << "Two" - << "Three" << "Four" << "Five" - ); + "Proxy Checkboxes"); Setting *slaveSingleText = createSetting (Type_LineEdit, section, - "Proxy TextBox 1" - ); + "Proxy TextBox 1"); Setting *slaveMultiText = createSetting (Type_LineEdit, section, - "ProxyTextBox 2" - ); - - // There are three types of values: - // - // Declared values - Pre-determined values, typically for - // combobox drop downs and boolean (radiobutton / checkbox) labels. - // These values represent the total possible list of values that may - // define a setting. No other values are allowed. - // - // Defined values - Values which represent the atual, current value of - // a setting. For settings with declared values, this must be one or - // several declared values, as appropriate. - // - // Proxy values - values the proxy master updates the proxy slave when - // it's own definition is set / changed. These are definitions for - // proxy slave settings, but must match any declared values the proxy - // slave has, if any. + "ProxyTextBox 2"); + + Setting *slaveAlphaSpinbox = createSetting (Type_SpinBox, section, + "Alpha Spinbox"); + + Setting *slaveIntegerSpinbox = createSetting (Type_SpinBox, section, + "Int Spinbox"); + + Setting *slaveDoubleSpinbox = createSetting (Type_DoubleSpinBox, + section, "Double Spinbox"); + + Setting *slaveSlider = createSetting (Type_Slider, section, "Slider"); + + Setting *slaveDial = createSetting (Type_Dial, section, "Dial"); + + //set declared values for selected views + masterBoolean->setDeclaredValues (QStringList() + << "Profile One" << "Profile Two" + << "Profile Three" << "Profile Four"); + + slaveBoolean->setDeclaredValues (QStringList() + << "One" << "Two" << "Three" << "Four" << "Five"); + + slaveAlphaSpinbox->setDeclaredValues (QStringList() + << "One" << "Two" << "Three" << "Four"); + masterBoolean->addProxy (slaveBoolean, QList () << (QStringList() << "One" << "Three") @@ -168,11 +185,48 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() << (QStringList() << "Two" << "Four") ); + masterBoolean->addProxy (slaveAlphaSpinbox, QList () + << (QStringList() << "Four") + << (QStringList() << "Three") + << (QStringList() << "Two") + << (QStringList() << "One")); + + masterBoolean->addProxy (slaveIntegerSpinbox, QList () + << (QStringList() << "0") + << (QStringList() << "7") + << (QStringList() << "14") + << (QStringList() << "21")); + + masterBoolean->addProxy (slaveDoubleSpinbox, QList () + << (QStringList() << "0.17") + << (QStringList() << "0.34") + << (QStringList() << "0.51") + << (QStringList() << "0.68")); + + masterBoolean->addProxy (slaveSlider, QList () + << (QStringList() << "25") + << (QStringList() << "50") + << (QStringList() << "75") + << (QStringList() << "100") + ); + + masterBoolean->addProxy (slaveDial, QList () + << (QStringList() << "25") + << (QStringList() << "50") + << (QStringList() << "75") + << (QStringList() << "100") + ); + //settings with proxies are not serialized by default //other settings non-serialized for demo purposes slaveBoolean->setSerializable (false); slaveSingleText->setSerializable (false); slaveMultiText->setSerializable (false); + slaveAlphaSpinbox->setSerializable (false); + slaveIntegerSpinbox->setSerializable (false); + slaveDoubleSpinbox->setSerializable (false); + slaveSlider->setSerializable (false); + slaveDial->setSerializable (false); slaveBoolean->setDefaultValues (QStringList() << "One" << "Three" << "Five"); @@ -184,7 +238,39 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() slaveSingleText->setWidgetWidth (24); slaveMultiText->setWidgetWidth (24); - } + + slaveAlphaSpinbox->setDefaultValue ("Two"); + slaveAlphaSpinbox->setWidgetWidth (20); + //slaveAlphaSpinbox->setPrefix ("No. "); + //slaveAlphaSpinbox->setSuffix ("!"); + slaveAlphaSpinbox->setWrapping (true); + + slaveIntegerSpinbox->setDefaultValue (14); + slaveIntegerSpinbox->setMinimum (0); + slaveIntegerSpinbox->setMaximum (58); + slaveIntegerSpinbox->setPrefix ("$"); + slaveIntegerSpinbox->setSuffix (".00"); + slaveIntegerSpinbox->setWidgetWidth (10); + slaveIntegerSpinbox->setSpecialValueText ("Nothing!"); + + slaveDoubleSpinbox->setDefaultValue (0.51); + slaveDoubleSpinbox->setSingleStep(0.17); + slaveDoubleSpinbox->setMaximum(4.0); + + slaveSlider->setMinimum (0); + slaveSlider->setMaximum (100); + slaveSlider->setDefaultValue (75); + slaveSlider->setWidgetWidth (100); + slaveSlider->setTicksAbove (true); + slaveSlider->setTickInterval (25); + + slaveDial->setMinimum (0); + slaveDial->setMaximum (100); + slaveDial->setSingleStep (5); + slaveDial->setDefaultValue (75); + slaveDial->setTickInterval (25); +*/ + } } CSMSettings::UserSettings::~UserSettings() @@ -194,86 +280,147 @@ CSMSettings::UserSettings::~UserSettings() void CSMSettings::UserSettings::loadSettings (const QString &fileName) { - mUserFilePath = QString::fromUtf8 - (mCfgMgr.getUserConfigPath().string().c_str()) + fileName.toUtf8(); + QString userFilePath = QString::fromUtf8 + (mCfgMgr.getUserConfigPath().string().c_str()); - QString global = QString::fromUtf8 - (mCfgMgr.getGlobalPath().string().c_str()) + fileName.toUtf8(); + QString globalFilePath = QString::fromUtf8 + (mCfgMgr.getGlobalPath().string().c_str()); - QString local = QString::fromUtf8 - (mCfgMgr.getLocalPath().string().c_str()) + fileName.toUtf8(); + QString otherFilePath = globalFilePath; - //open user and global streams - QTextStream *userStream = openFilestream (mUserFilePath, true); - QTextStream *otherStream = openFilestream (global, true); + //test for local only if global fails (uninstalled copy) + if (!QFile (globalFilePath + fileName).exists()) + { + //if global is invalid, use the local path + otherFilePath = QString::fromUtf8 + (mCfgMgr.getLocalPath().string().c_str()); + } - //failed stream, try for local - if (!otherStream) - otherStream = openFilestream (local, true); + QSettings::setPath + (QSettings::IniFormat, QSettings::UserScope, userFilePath); - //error condition - notify and return - if (!otherStream || !userStream) - { - QString message = QObject::tr("
An error was encountered loading \ - user settings files.

One or several files could not \ - be read. This may be caused by a missing configuration file, \ - incorrect file permissions or a corrupted installation of \ - OpenCS.
"); + QSettings::setPath + (QSettings::IniFormat, QSettings::SystemScope, otherFilePath); - message += QObject::tr("
Global filepath: ") + global; - message += QObject::tr("
Local filepath: ") + local; - message += QObject::tr("
User filepath: ") + mUserFilePath; + mSettingDefinitions = new QSettings + (QSettings::IniFormat, QSettings::UserScope, "opencs", QString(), this); +} - displayFileErrorMessage ( message, true); - return; - } +bool CSMSettings::UserSettings::hasSettingDefinitions + (const QString &viewKey) const +{ + return (mSettingDefinitions->contains (viewKey)); +} + +void CSMSettings::UserSettings::setDefinitions + (const QString &key, const QStringList &list) +{ + mSettingDefinitions->setValue (key, list); +} + +void CSMSettings::UserSettings::saveDefinitions() const +{ + mSettingDefinitions->sync(); +} - //success condition - merge the two streams into a single map and save - DefinitionPageMap totalMap = readFilestream (userStream); - DefinitionPageMap otherMap = readFilestream(otherStream); +QString CSMSettings::UserSettings::settingValue (const QString &settingKey) +{ + if (!mSettingDefinitions->contains (settingKey)) + return QString(); - //merging other settings file in and ignore duplicate settings to - //avoid overwriting user-level settings - mergeSettings (totalMap, otherMap); + QStringList defs = mSettingDefinitions->value (settingKey).toStringList(); - if (!totalMap.isEmpty()) - addDefinitions (totalMap); + if (defs.isEmpty()) + return QString(); + + return defs.at(0); } -void CSMSettings::UserSettings::saveSettings - (const QMap &settingMap) +CSMSettings::UserSettings& CSMSettings::UserSettings::instance() { - for (int i = 0; i < settings().size(); i++) - { - Setting* setting = settings().at(i); + assert(mUserSettingsInstance); + return *mUserSettingsInstance; +} - QString key = setting->page() + '.' + setting->name(); +void CSMSettings::UserSettings::updateUserSetting(const QString &settingKey, + const QStringList &list) +{ + mSettingDefinitions->setValue (settingKey ,list); - if (!settingMap.keys().contains(key)) - continue; + emit userSettingUpdated (settingKey, list); +} - setting->setDefinedValues (settingMap.value(key)); +CSMSettings::Setting *CSMSettings::UserSettings::findSetting + (const QString &pageName, const QString &settingName) +{ + foreach (Setting *setting, mSettings) + { + if (setting->name() == settingName) + { + if (setting->page() == pageName) + return setting; + } } + return 0; +} + +void CSMSettings::UserSettings::removeSetting + (const QString &pageName, const QString &settingName) +{ + if (mSettings.isEmpty()) + return; - writeFilestream (openFilestream (mUserFilePath, false), settingMap); + QList ::iterator removeIterator = mSettings.begin(); + + while (removeIterator != mSettings.end()) + { + if ((*removeIterator)->name() == settingName) + { + if ((*removeIterator)->page() == pageName) + { + mSettings.erase (removeIterator); + break; + } + } + removeIterator++; + } } -QString CSMSettings::UserSettings::settingValue (const QString &settingKey) + +CSMSettings::SettingPageMap CSMSettings::UserSettings::settingPageMap() const { - QStringList names = settingKey.split('.'); + SettingPageMap pageMap; + + foreach (Setting *setting, mSettings) + pageMap[setting->page()].append (setting); - Setting *setting = findSetting(names.at(0), names.at(1)); + return pageMap; +} - if (setting) +CSMSettings::Setting *CSMSettings::UserSettings::createSetting + (CSMSettings::SettingType typ, const QString &page, const QString &name) +{ + //get list of all settings for the current setting name + if (findSetting (page, name)) { - if (!setting->definedValues().isEmpty()) - return setting->definedValues().at(0); + qWarning() << "Duplicate declaration encountered: " + << (name + '/' + page); + return 0; } - return ""; + + Setting *setting = new Setting (typ, name, page); + + + //add declaration to the model + mSettings.append (setting); + + return setting; } -CSMSettings::UserSettings& CSMSettings::UserSettings::instance() +QStringList CSMSettings::UserSettings::definitions (const QString &viewKey) const { - assert(mUserSettingsInstance); - return *mUserSettingsInstance; + if (mSettingDefinitions->contains (viewKey)) + return mSettingDefinitions->value (viewKey).toStringList(); + + return QStringList(); } diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index f0ed7af41..830cc8c69 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -1,14 +1,13 @@ #ifndef USERSETTINGS_HPP #define USERSETTINGS_HPP -#include +#include #include #include #include #include - -#include "settingmanager.hpp" +#include "support.hpp" #ifndef Q_MOC_RUN #include @@ -18,20 +17,23 @@ namespace Files { typedef std::vector PathContainer; struct ConfigurationManager;} class QFile; +class QSettings; namespace CSMSettings { - class UserSettings: public SettingManager + class Setting; + typedef QMap > SettingPageMap; + + class UserSettings: public QObject { Q_OBJECT static UserSettings *mUserSettingsInstance; - QString mUserFilePath; Files::ConfigurationManager mCfgMgr; - QString mReadOnlyMessage; - QString mReadWriteMessage; + QSettings *mSettingDefinitions; + QList mSettings; public: @@ -44,20 +46,50 @@ namespace CSMSettings { UserSettings (UserSettings const &); //not implemented void operator= (UserSettings const &); //not implemented - /// Writes settings to the last loaded settings file - bool writeSettings(); - /// Retrieves the settings file at all three levels (global, local and user). void loadSettings (const QString &fileName); - /// Writes settings to the user's config file path - void saveSettings (const QMap &settingMap); + /// Updates QSettings and syncs with the ini file + void setDefinitions (const QString &key, const QStringList &defs); QString settingValue (const QString &settingKey); + ///retrieve a setting object from a given page and setting name + Setting *findSetting + (const QString &pageName, const QString &settingName = QString()); + + ///remove a setting from the list + void removeSetting + (const QString &pageName, const QString &settingName); + + ///Retreive a map of the settings, keyed by page name + SettingPageMap settingPageMap() const; + + ///Returns a string list of defined vlaues for the specified setting + ///in "page/name" format. + QStringList definitions (const QString &viewKey) const; + + ///Test to indicate whether or not a setting has any definitions + bool hasSettingDefinitions (const QString &viewKey) const; + + ///Save any unsaved changes in the QSettings object + void saveDefinitions() const; + private: void buildSettingModelDefaults(); + + ///add a new setting to the model and return it + Setting *createSetting (CSMSettings::SettingType typ, + const QString &page, const QString &name); + + signals: + + void userSettingUpdated (const QString &, const QStringList &); + + public slots: + + void updateUserSetting (const QString &, const QStringList &); }; } #endif // USERSETTINGS_HPP diff --git a/apps/opencs/model/tools/birthsigncheck.cpp b/apps/opencs/model/tools/birthsigncheck.cpp index 59c65086e..db20ce4bc 100644 --- a/apps/opencs/model/tools/birthsigncheck.cpp +++ b/apps/opencs/model/tools/birthsigncheck.cpp @@ -17,7 +17,7 @@ int CSMTools::BirthsignCheckStage::setup() return mBirthsigns.getSize(); } -void CSMTools::BirthsignCheckStage::perform (int stage, std::vector& messages) +void CSMTools::BirthsignCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mBirthsigns.getRecord (stage); @@ -30,13 +30,13 @@ void CSMTools::BirthsignCheckStage::perform (int stage, std::vector // test for empty name, description and texture if (birthsign.mName.empty()) - messages.push_back (id.toString() + "|" + birthsign.mId + " has an empty name"); + messages.push_back (std::make_pair (id, birthsign.mId + " has an empty name")); if (birthsign.mDescription.empty()) - messages.push_back (id.toString() + "|" + birthsign.mId + " has an empty description"); + messages.push_back (std::make_pair (id, birthsign.mId + " has an empty description")); if (birthsign.mTexture.empty()) - messages.push_back (id.toString() + "|" + birthsign.mId + " is missing a texture"); + messages.push_back (std::make_pair (id, birthsign.mId + " is missing a texture")); /// \todo test if the texture exists diff --git a/apps/opencs/model/tools/birthsigncheck.hpp b/apps/opencs/model/tools/birthsigncheck.hpp index bdd65b44a..1030e5c02 100644 --- a/apps/opencs/model/tools/birthsigncheck.hpp +++ b/apps/opencs/model/tools/birthsigncheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/classcheck.cpp b/apps/opencs/model/tools/classcheck.cpp index 6923b3153..cea4f3a68 100644 --- a/apps/opencs/model/tools/classcheck.cpp +++ b/apps/opencs/model/tools/classcheck.cpp @@ -18,7 +18,7 @@ int CSMTools::ClassCheckStage::setup() return mClasses.getSize(); } -void CSMTools::ClassCheckStage::perform (int stage, std::vector& messages) +void CSMTools::ClassCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mClasses.getRecord (stage); @@ -31,10 +31,10 @@ void CSMTools::ClassCheckStage::perform (int stage, std::vector& me // test for empty name and description if (class_.mName.empty()) - messages.push_back (id.toString() + "|" + class_.mId + " has an empty name"); + messages.push_back (std::make_pair (id, class_.mId + " has an empty name")); if (class_.mDescription.empty()) - messages.push_back (id.toString() + "|" + class_.mId + " has an empty description"); + messages.push_back (std::make_pair (id, class_.mId + " has an empty description")); // test for invalid attributes for (int i=0; i<2; ++i) @@ -42,18 +42,14 @@ void CSMTools::ClassCheckStage::perform (int stage, std::vector& me { std::ostringstream stream; - stream << id.toString() << "|Attribute #" << i << " of " << class_.mId << " is not set"; + stream << "Attribute #" << i << " of " << class_.mId << " is not set"; - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id, stream.str())); } if (class_.mData.mAttribute[0]==class_.mData.mAttribute[1] && class_.mData.mAttribute[0]!=-1) { - std::ostringstream stream; - - stream << id.toString() << "|Class lists same attribute twice"; - - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id, "Class lists same attribute twice")); } // test for non-unique skill @@ -66,12 +62,7 @@ void CSMTools::ClassCheckStage::perform (int stage, std::vector& me for (std::map::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter) if (iter->second>1) { - std::ostringstream stream; - - stream - << id.toString() << "|" - << ESM::Skill::indexToId (iter->first) << " is listed more than once"; - - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id, + ESM::Skill::indexToId (iter->first) + " is listed more than once")); } } \ No newline at end of file diff --git a/apps/opencs/model/tools/classcheck.hpp b/apps/opencs/model/tools/classcheck.hpp index 3604b451c..ec50ba35d 100644 --- a/apps/opencs/model/tools/classcheck.hpp +++ b/apps/opencs/model/tools/classcheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/factioncheck.cpp b/apps/opencs/model/tools/factioncheck.cpp index c219e5610..42d577163 100644 --- a/apps/opencs/model/tools/factioncheck.cpp +++ b/apps/opencs/model/tools/factioncheck.cpp @@ -18,7 +18,7 @@ int CSMTools::FactionCheckStage::setup() return mFactions.getSize(); } -void CSMTools::FactionCheckStage::perform (int stage, std::vector& messages) +void CSMTools::FactionCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mFactions.getRecord (stage); @@ -31,16 +31,12 @@ void CSMTools::FactionCheckStage::perform (int stage, std::vector& // test for empty name if (faction.mName.empty()) - messages.push_back (id.toString() + "|" + faction.mId + " has an empty name"); + messages.push_back (std::make_pair (id, faction.mId + " has an empty name")); // test for invalid attributes if (faction.mData.mAttribute[0]==faction.mData.mAttribute[1] && faction.mData.mAttribute[0]!=-1) { - std::ostringstream stream; - - stream << id.toString() << "|Faction lists same attribute twice"; - - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id , "Faction lists same attribute twice")); } // test for non-unique skill @@ -53,13 +49,8 @@ void CSMTools::FactionCheckStage::perform (int stage, std::vector& for (std::map::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter) if (iter->second>1) { - std::ostringstream stream; - - stream - << id.toString() << "|" - << ESM::Skill::indexToId (iter->first) << " is listed more than once"; - - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id, + ESM::Skill::indexToId (iter->first) + " is listed more than once")); } /// \todo check data members that can't be edited in the table view diff --git a/apps/opencs/model/tools/factioncheck.hpp b/apps/opencs/model/tools/factioncheck.hpp index 7cd80347d..ccc44e6a9 100644 --- a/apps/opencs/model/tools/factioncheck.hpp +++ b/apps/opencs/model/tools/factioncheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/mandatoryid.cpp b/apps/opencs/model/tools/mandatoryid.cpp index b99abec6d..5f245dd4d 100644 --- a/apps/opencs/model/tools/mandatoryid.cpp +++ b/apps/opencs/model/tools/mandatoryid.cpp @@ -15,9 +15,10 @@ int CSMTools::MandatoryIdStage::setup() return mIds.size(); } -void CSMTools::MandatoryIdStage::perform (int stage, std::vector& messages) +void CSMTools::MandatoryIdStage::perform (int stage, Messages& messages) { if (mIdCollection.searchId (mIds.at (stage))==-1 || mIdCollection.getRecord (mIds.at (stage)).isDeleted()) - messages.push_back (mCollectionId.toString() + "|Missing mandatory record: " + mIds.at (stage)); + messages.push_back (std::make_pair (mCollectionId, + "|Missing mandatory record: " + mIds.at (stage))); } \ No newline at end of file diff --git a/apps/opencs/model/tools/mandatoryid.hpp b/apps/opencs/model/tools/mandatoryid.hpp index 5fddf08d3..a8afea62a 100644 --- a/apps/opencs/model/tools/mandatoryid.hpp +++ b/apps/opencs/model/tools/mandatoryid.hpp @@ -30,7 +30,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/racecheck.cpp b/apps/opencs/model/tools/racecheck.cpp index 413de5ef0..47aeda1e6 100644 --- a/apps/opencs/model/tools/racecheck.cpp +++ b/apps/opencs/model/tools/racecheck.cpp @@ -7,7 +7,7 @@ #include "../world/universalid.hpp" -void CSMTools::RaceCheckStage::performPerRecord (int stage, std::vector& messages) +void CSMTools::RaceCheckStage::performPerRecord (int stage, Messages& messages) { const CSMWorld::Record& record = mRaces.getRecord (stage); @@ -20,24 +20,24 @@ void CSMTools::RaceCheckStage::performPerRecord (int stage, std::vector& messages) +void CSMTools::RaceCheckStage::performFinal (Messages& messages) { CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Races); if (!mPlayable) - messages.push_back (id.toString() + "|No playable race"); + messages.push_back (std::make_pair (id, "No playable race")); } CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection& races) @@ -64,7 +64,7 @@ int CSMTools::RaceCheckStage::setup() return mRaces.getSize()+1; } -void CSMTools::RaceCheckStage::perform (int stage, std::vector& messages) +void CSMTools::RaceCheckStage::perform (int stage, Messages& messages) { if (stage==mRaces.getSize()) performFinal (messages); diff --git a/apps/opencs/model/tools/racecheck.hpp b/apps/opencs/model/tools/racecheck.hpp index ff9948bf6..c68b283be 100644 --- a/apps/opencs/model/tools/racecheck.hpp +++ b/apps/opencs/model/tools/racecheck.hpp @@ -15,9 +15,9 @@ namespace CSMTools const CSMWorld::IdCollection& mRaces; bool mPlayable; - void performPerRecord (int stage, std::vector& messages); + void performPerRecord (int stage, Messages& messages); - void performFinal (std::vector& messages); + void performFinal (Messages& messages); public: @@ -26,7 +26,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/referenceablecheck.cpp b/apps/opencs/model/tools/referenceablecheck.cpp index dab61bfff..488081f46 100644 --- a/apps/opencs/model/tools/referenceablecheck.cpp +++ b/apps/opencs/model/tools/referenceablecheck.cpp @@ -1,7 +1,9 @@ #include "referenceablecheck.hpp" + +#include + #include "../world/record.hpp" #include "../world/universalid.hpp" -#include CSMTools::ReferenceableCheckStage::ReferenceableCheckStage( const CSMWorld::RefIdData& referenceable, const CSMWorld::IdCollection& races, @@ -16,7 +18,7 @@ CSMTools::ReferenceableCheckStage::ReferenceableCheckStage( { } -void CSMTools::ReferenceableCheckStage::perform(int stage, std::vector< std::string >& messages) +void CSMTools::ReferenceableCheckStage::perform (int stage, Messages& messages) { //Checks for books, than, when stage is above mBooksSize goes to other checks, with (stage - PrevSum) as stage. const int bookSize(mReferencables.getBooks().getSize()); @@ -206,11 +208,11 @@ void CSMTools::ReferenceableCheckStage::perform(int stage, std::vector< std::str staticCheck(stage, mReferencables.getStatics(), messages); return; } - + stage -= staticSize; const int creatureSize(mReferencables.getCreatures().getSize()); - + if (stage < creatureSize) { creatureCheck(stage, mReferencables.getCreatures(), messages); @@ -230,7 +232,7 @@ int CSMTools::ReferenceableCheckStage::setup() void CSMTools::ReferenceableCheckStage::bookCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Book >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -248,7 +250,7 @@ void CSMTools::ReferenceableCheckStage::bookCheck( void CSMTools::ReferenceableCheckStage::activatorCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Activator >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -262,15 +264,13 @@ void CSMTools::ReferenceableCheckStage::activatorCheck( //Checking for model, IIRC all activators should have a model if (activator.mModel.empty()) - { - messages.push_back(id.toString() + "|" + activator.mId + " has no model"); - } + messages.push_back (std::make_pair (id, activator.mId + " has no model")); } void CSMTools::ReferenceableCheckStage::potionCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Potion >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -290,7 +290,7 @@ void CSMTools::ReferenceableCheckStage::potionCheck( void CSMTools::ReferenceableCheckStage::apparatusCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Apparatus >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -310,7 +310,7 @@ void CSMTools::ReferenceableCheckStage::apparatusCheck( void CSMTools::ReferenceableCheckStage::armorCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Armor >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -326,21 +326,17 @@ void CSMTools::ReferenceableCheckStage::armorCheck( //checking for armor class, armor should have poistive armor class, but 0 is considered legal if (armor.mData.mArmor < 0) - { - messages.push_back(id.toString() + "|" + armor.mId + " has negative armor class"); - } + messages.push_back (std::make_pair (id, armor.mId + " has negative armor class")); //checking for health. Only positive numbers are allowed, or 0 is illegal if (armor.mData.mHealth <= 0) - { - messages.push_back(id.toString() + "|" + armor.mId + " has non positive health"); - } + messages.push_back (std::make_pair (id, armor.mId + " has non positive health")); } void CSMTools::ReferenceableCheckStage::clothingCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Clothing >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -357,7 +353,7 @@ void CSMTools::ReferenceableCheckStage::clothingCheck( void CSMTools::ReferenceableCheckStage::containerCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Container >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -371,153 +367,109 @@ void CSMTools::ReferenceableCheckStage::containerCheck( //Checking for model, IIRC all containers should have a model if (container.mModel.empty()) - { - messages.push_back(id.toString() + "|" + container.mId + " has no model"); - } + messages.push_back (std::make_pair (id, container.mId + " has no model")); //Checking for capacity (weight) if (container.mWeight < 0) //0 is allowed - { - messages.push_back(id.toString() + "|" + container.mId + " has negative weight (capacity)"); - } + messages.push_back (std::make_pair (id, + container.mId + " has negative weight (capacity)")); //checking for name if (container.mName.empty()) - { - messages.push_back(id.toString() + "|" + container.mId + " has an empty name"); - } + messages.push_back (std::make_pair (id, container.mId + " has an empty name")); } -void CSMTools::ReferenceableCheckStage::creatureCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::Creature >& records, - std::vector< std::string >& messages) +void CSMTools::ReferenceableCheckStage::creatureCheck ( + int stage, const CSMWorld::RefIdDataContainer< ESM::Creature >& records, + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Creature& creature = (dynamic_cast&>(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Creature, creature.mId); if (creature.mModel.empty()) - { - messages.push_back(id.toString() + "|" + creature.mId + " has no model"); - } + messages.push_back (std::make_pair (id, creature.mId + " has no model")); if (creature.mName.empty()) - { - messages.push_back(id.toString() + "|" + creature.mId + " has an empty name"); - } + messages.push_back (std::make_pair (id, creature.mId + " has an empty name")); //stats checks if (creature.mData.mLevel < 1) - { - messages.push_back(id.toString() + "|" + creature.mId + " has non-postive level"); - } + messages.push_back (std::make_pair (id, creature.mId + " has non-postive level")); if (creature.mData.mStrength < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative strength"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative strength")); if (creature.mData.mIntelligence < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative intelligence"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative intelligence")); if (creature.mData.mWillpower < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative willpower"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative willpower")); if (creature.mData.mAgility < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative agility"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative agility")); if (creature.mData.mSpeed < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative speed"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative speed")); if (creature.mData.mEndurance < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative endurance"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative endurance")); if (creature.mData.mPersonality < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative personality"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative personality")); if (creature.mData.mLuck < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative luck"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative luck")); if (creature.mData.mHealth < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative health"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative health")); if (creature.mData.mSoul < 0) - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative soul value"); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative soul value")); for (int i = 0; i < 6; ++i) { if (creature.mData.mAttack[i] < 0) { - messages.push_back(id.toString() + "|" + creature.mId + " has negative attack strength"); + messages.push_back (std::make_pair (id, + creature.mId + " has negative attack strength")); break; } } //TODO, find meaning of other values if (creature.mData.mGold < 0) //It seems that this is for gold in merchant creatures - { - messages.push_back(id.toString() + "|" + creature.mId + " has negative gold "); - } + messages.push_back (std::make_pair (id, creature.mId + " has negative gold ")); } void CSMTools::ReferenceableCheckStage::doorCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::Door >& records, - std::vector< std::string >& messages) + int stage, const CSMWorld::RefIdDataContainer< ESM::Door >& records, + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Door& Door = (dynamic_cast&>(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Door, Door.mId); //usual, name or model if (Door.mName.empty()) - { - messages.push_back(id.toString() + "|" + Door.mId + " has an empty name"); - } + messages.push_back (std::make_pair (id, Door.mId + " has an empty name")); if (Door.mModel.empty()) - { - messages.push_back(id.toString() + "|" + Door.mId + " has no model"); - } - - //TODO, check what static unsigned int sRecordId; is for + messages.push_back (std::make_pair (id, Door.mId + " has no model")); } void CSMTools::ReferenceableCheckStage::ingredientCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Ingredient >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -535,7 +487,7 @@ void CSMTools::ReferenceableCheckStage::ingredientCheck( void CSMTools::ReferenceableCheckStage::creaturesLevListCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::CreatureLevList >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -553,7 +505,7 @@ void CSMTools::ReferenceableCheckStage::creaturesLevListCheck( void CSMTools::ReferenceableCheckStage::itemLevelledListCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::ItemLevList >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -569,40 +521,33 @@ void CSMTools::ReferenceableCheckStage::itemLevelledListCheck( } void CSMTools::ReferenceableCheckStage::lightCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::Light >& records, - std::vector< std::string >& messages) + int stage, const CSMWorld::RefIdDataContainer< ESM::Light >& records, + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Light& light = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Light, light.mId); if (light.mData.mRadius < 0) - { - messages.push_back(id.toString() + "|" + light.mId + " has negative light radius"); - } + messages.push_back (std::make_pair (id, light.mId + " has negative light radius")); if (light.mData.mFlags & ESM::Light::Carry) { inventoryItemCheck(light, messages, id.toString()); if (light.mData.mTime == 0) - { - messages.push_back(id.toString() + "|" + light.mId + " has zero duration"); - } + messages.push_back (std::make_pair (id, light.mId + " has zero duration")); } } void CSMTools::ReferenceableCheckStage::lockpickCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Lockpick >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -622,7 +567,7 @@ void CSMTools::ReferenceableCheckStage::lockpickCheck( void CSMTools::ReferenceableCheckStage::miscCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Miscellaneous >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -637,20 +582,17 @@ void CSMTools::ReferenceableCheckStage::miscCheck( inventoryItemCheck(miscellaneous, messages, id.toString()); } -void CSMTools::ReferenceableCheckStage::npcCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::NPC >& records, - std::vector< std::string >& messages) +void CSMTools::ReferenceableCheckStage::npcCheck ( + int stage, const CSMWorld::RefIdDataContainer< ESM::NPC >& records, + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); if (baseRecord.isDeleted()) - { return; - } const ESM::NPC& npc = (dynamic_cast& >(baseRecord)).get(); - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Npc, npc.mId); + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Npc, npc.mId); short level(npc.mNpdt52.mLevel); char disposition(npc.mNpdt52.mDisposition); @@ -661,15 +603,13 @@ void CSMTools::ReferenceableCheckStage::npcCheck( //Detect if player is present if (Misc::StringUtils::ciEqual(npc.mId, "player")) //Happy now, scrawl? - { mPlayerPresent = true; - } if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated { if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0008 = autocalculated flag { - messages.push_back(id.toString() + "|" + npc.mId + " mNpdtType or flags mismatch!"); //should not happend? + messages.push_back (std::make_pair (id, npc.mId + " mNpdtType or flags mismatch!")); //should not happend? return; } @@ -682,145 +622,100 @@ void CSMTools::ReferenceableCheckStage::npcCheck( else { if (npc.mNpdt52.mMana < 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " mana has negative value"); - } + messages.push_back (std::make_pair (id, npc.mId + " mana has negative value")); if (npc.mNpdt52.mFatigue < 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " fatigue has negative value"); - } + messages.push_back (std::make_pair (id, npc.mId + " fatigue has negative value")); if (npc.mNpdt52.mAgility == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " agility has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " agility has zero value")); if (npc.mNpdt52.mEndurance == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " endurance has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " endurance has zero value")); if (npc.mNpdt52.mIntelligence == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " intelligence has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " intelligence has zero value")); if (npc.mNpdt52.mLuck == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " luck has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " luck has zero value")); if (npc.mNpdt52.mPersonality == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " personality has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " personality has zero value")); if (npc.mNpdt52.mStrength == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " strength has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " strength has zero value")); if (npc.mNpdt52.mSpeed == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " speed has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " speed has zero value")); if (npc.mNpdt52.mWillpower == 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " willpower has zero value"); - } + messages.push_back (std::make_pair (id, npc.mId + " willpower has zero value")); } if (level < 1) - { - messages.push_back(id.toString() + "|" + npc.mId + " level is non positive"); - } + messages.push_back (std::make_pair (id, npc.mId + " level is non positive")); if (gold < 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " gold has negative value"); - } + messages.push_back (std::make_pair (id, npc.mId + " gold has negative value")); if (npc.mName.empty()) - { - messages.push_back(id.toString() + "|" + npc.mId + " has any empty name"); - } + messages.push_back (std::make_pair (id, npc.mId + " has any empty name")); if (npc.mClass.empty()) { - messages.push_back(id.toString() + "|" + npc.mId + " has any empty class"); + messages.push_back (std::make_pair (id, npc.mId + " has any empty class")); } - else //checking if there is such class + else if (mClasses.searchId (npc.mClass) == -1) { - if (mClasses.searchId(npc.mClass) == -1) - { - messages.push_back(id.toString() + "|" + npc.mId + " has invalid class"); - } + messages.push_back (std::make_pair (id, npc.mId + " has invalid class")); } if (npc.mRace.empty()) { - messages.push_back(id.toString() + "|" + npc.mId + " has any empty race"); + messages.push_back (std::make_pair (id, npc.mId + " has any empty race")); } - else //checking if there is a such race + else if (mRaces.searchId (npc.mRace) == -1) { - if (mRaces.searchId(npc.mRace) == -1) - { - messages.push_back(id.toString() + "|" + npc.mId + " has invalid race"); - } + messages.push_back (std::make_pair (id, npc.mId + " has invalid race")); } if (disposition < 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " has negative disposition"); - } + messages.push_back (std::make_pair (id, npc.mId + " has negative disposition")); if (reputation < 0) //It seems that no character in Morrowind.esm have negative reputation. I'm assuming that negative reputation is invalid { - messages.push_back(id.toString() + "|" + npc.mId + " has negative reputation"); + messages.push_back (std::make_pair (id, npc.mId + " has negative reputation")); } - if (npc.mFaction.empty() == false) + if (!npc.mFaction.empty()) { if (rank < 0) - { - messages.push_back(id.toString() + "|" + npc.mId + " has negative rank"); - } + messages.push_back (std::make_pair (id, npc.mId + " has negative rank")); if (mFactions.searchId(npc.mFaction) == -1) - { - messages.push_back(id.toString() + "|" + npc.mId + " has invalid faction"); - } + messages.push_back (std::make_pair (id, npc.mId + " has invalid faction")); } if (npc.mHead.empty()) - { - messages.push_back(id.toString() + "|" + npc.mId + " has no head"); - } + messages.push_back (std::make_pair (id, npc.mId + " has no head")); if (npc.mHair.empty()) - { - messages.push_back(id.toString() + "|" + npc.mId + " has no hair"); - } + messages.push_back (std::make_pair (id, npc.mId + " has no hair")); //TODO: reputation, Disposition, rank, everything else } void CSMTools::ReferenceableCheckStage::weaponCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::Weapon >& records, - std::vector< std::string >& messages) + int stage, const CSMWorld::RefIdDataContainer< ESM::Weapon >& records, + Messages& messages) { - const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); + const CSMWorld::RecordBase& baseRecord = records.getRecord (stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Weapon& weapon = (dynamic_cast& >(baseRecord)).get(); - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Weapon, weapon.mId); + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Weapon, weapon.mId); //TODO, It seems that this stuff for spellcasting is obligatory and In fact We should check if records are present if @@ -860,20 +755,17 @@ void CSMTools::ReferenceableCheckStage::weaponCheck( weapon.mData.mType == ESM::Weapon::Bolt)) { if (weapon.mData.mSlash[0] > weapon.mData.mSlash[1]) - { - messages.push_back(id.toString() + "|" + weapon.mId + " has minimum slash damage higher than maximum"); - } + messages.push_back (std::make_pair (id, + weapon.mId + " has minimum slash damage higher than maximum")); if (weapon.mData.mThrust[0] > weapon.mData.mThrust[1]) - { - messages.push_back(id.toString() + "|" + weapon.mId + " has minimum thrust damage higher than maximum"); - } + messages.push_back (std::make_pair (id, + weapon.mId + " has minimum thrust damage higher than maximum")); } if (weapon.mData.mChop[0] > weapon.mData.mChop[1]) - { - messages.push_back(id.toString() + "|" + weapon.mId + " has minimum chop damage higher than maximum"); - } + messages.push_back (std::make_pair (id, + weapon.mId + " has minimum chop damage higher than maximum")); if (!(weapon.mData.mType == ESM::Weapon::Arrow || weapon.mData.mType == ESM::Weapon::Bolt || @@ -881,14 +773,10 @@ void CSMTools::ReferenceableCheckStage::weaponCheck( { //checking of health if (weapon.mData.mHealth <= 0) - { - messages.push_back(id.toString() + "|" + weapon.mId + " has non-positivie health"); - } + messages.push_back (std::make_pair (id, weapon.mId + " has non-positivie health")); if (weapon.mData.mReach < 0) - { - messages.push_back(id.toString() + "|" + weapon.mId + " has negative reach"); - } + messages.push_back (std::make_pair (id, weapon.mId + " has negative reach")); } } } @@ -896,7 +784,7 @@ void CSMTools::ReferenceableCheckStage::weaponCheck( void CSMTools::ReferenceableCheckStage::probeCheck( int stage, const CSMWorld::RefIdDataContainer< ESM::Probe >& records, - std::vector< std::string >& messages) + Messages& messages) { const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); @@ -912,184 +800,128 @@ void CSMTools::ReferenceableCheckStage::probeCheck( toolCheck(probe, messages, id.toString(), true); } -void CSMTools::ReferenceableCheckStage::repairCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::Repair >& records, - std::vector< std::string >& messages) +void CSMTools::ReferenceableCheckStage::repairCheck ( + int stage, const CSMWorld::RefIdDataContainer< ESM::Repair >& records, + Messages& messages) { - const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); + const CSMWorld::RecordBase& baseRecord = records.getRecord (stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Repair& repair = (dynamic_cast& >(baseRecord)).get(); - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Repair, repair.mId); + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Repair, repair.mId); - inventoryItemCheck(repair, messages, id.toString()); - toolCheck(repair, messages, id.toString(), true); + inventoryItemCheck (repair, messages, id.toString()); + toolCheck (repair, messages, id.toString(), true); } -void CSMTools::ReferenceableCheckStage::staticCheck( - int stage, - const CSMWorld::RefIdDataContainer< ESM::Static >& records, - std::vector< std::string >& messages) +void CSMTools::ReferenceableCheckStage::staticCheck ( + int stage, const CSMWorld::RefIdDataContainer< ESM::Static >& records, + Messages& messages) { - const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); + const CSMWorld::RecordBase& baseRecord = records.getRecord (stage); if (baseRecord.isDeleted()) - { return; - } const ESM::Static& staticElement = (dynamic_cast& >(baseRecord)).get(); - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Static, staticElement.mId); + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Static, staticElement.mId); if (staticElement.mModel.empty()) - { - messages.push_back(id.toString() + "|" + staticElement.mId + " has no model"); - } + messages.push_back (std::make_pair (id, staticElement.mId + " has no model")); } //final check -void CSMTools::ReferenceableCheckStage::finalCheck(std::vector< std::string >& messages) +void CSMTools::ReferenceableCheckStage::finalCheck (Messages& messages) { if (!mPlayerPresent) - { - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Npc); - messages.push_back(id.toString() + "| There is no player record"); - } + messages.push_back (std::make_pair (CSMWorld::UniversalId::Type_Referenceables, + "There is no player record")); } //Templates begins here -template void CSMTools::ReferenceableCheckStage::inventoryItemCheck( - const ITEM& someItem, - std::vector< std::string >& messages, - const std::string& someID, bool enchantable) +template void CSMTools::ReferenceableCheckStage::inventoryItemCheck ( + const Item& someItem, Messages& messages, const std::string& someID, bool enchantable) { if (someItem.mName.empty()) - { - messages.push_back(someID + "|" + someItem.mId + " has an empty name"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has an empty name")); //Checking for weight if (someItem.mData.mWeight < 0) - { - messages.push_back(someID + "|" + someItem.mId + " has negative weight"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has negative weight")); //Checking for value if (someItem.mData.mValue < 0) - { - messages.push_back(someID + "|" + someItem.mId + " has negative value"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has negative value")); -//checking for model + //checking for model if (someItem.mModel.empty()) - { - messages.push_back(someID + "|" + someItem.mId + " has no model"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has no model")); //checking for icon if (someItem.mIcon.empty()) - { - messages.push_back(someID + "|" + someItem.mId + " has no icon"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has no icon")); - if (enchantable) - { - if (someItem.mData.mEnchant < 0) - { - messages.push_back(someID + "|" + someItem.mId + " has negative enchantment"); - } - } + if (enchantable && someItem.mData.mEnchant < 0) + messages.push_back (std::make_pair (someID, someItem.mId + " has negative enchantment")); } -template void CSMTools::ReferenceableCheckStage::inventoryItemCheck( - const ITEM& someItem, - std::vector< std::string >& messages, - const std::string& someID) +template void CSMTools::ReferenceableCheckStage::inventoryItemCheck ( + const Item& someItem, Messages& messages, const std::string& someID) { if (someItem.mName.empty()) - { - messages.push_back(someID + "|" + someItem.mId + " has an empty name"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has an empty name")); //Checking for weight if (someItem.mData.mWeight < 0) - { - messages.push_back(someID + "|" + someItem.mId + " has negative weight"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has negative weight")); //Checking for value if (someItem.mData.mValue < 0) - { - messages.push_back(someID + "|" + someItem.mId + " has negative value"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has negative value")); //checking for model if (someItem.mModel.empty()) - { - messages.push_back(someID + "|" + someItem.mId + " has no model"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has no model")); //checking for icon if (someItem.mIcon.empty()) - { - messages.push_back(someID + "|" + someItem.mId + " has no icon"); - } + messages.push_back (std::make_pair (someID, someItem.mId + " has no icon")); } -template void CSMTools::ReferenceableCheckStage::toolCheck( - const TOOL& someTool, - std::vector< std::string >& messages, - const std::string& someID, bool canBeBroken) +template void CSMTools::ReferenceableCheckStage::toolCheck ( + const Tool& someTool, Messages& messages, const std::string& someID, bool canBeBroken) { if (someTool.mData.mQuality <= 0) - { - messages.push_back(someID + "|" + someTool.mId + " has non-positive quality"); - } + messages.push_back (std::make_pair (someID, someTool.mId + " has non-positive quality")); - if (canBeBroken) - { - if (someTool.mData.mUses <= 0) - { - messages.push_back(someID + "|" + someTool.mId + " has non-positive uses count"); - } - } + if (canBeBroken && someTool.mData.mUses<=0) + messages.push_back (std::make_pair (someID, + someTool.mId + " has non-positive uses count")); } -template void CSMTools::ReferenceableCheckStage::toolCheck( - const TOOL& someTool, - std::vector< std::string >& messages, - const std::string& someID) +template void CSMTools::ReferenceableCheckStage::toolCheck ( + const Tool& someTool, Messages& messages, const std::string& someID) { if (someTool.mData.mQuality <= 0) - { - messages.push_back(someID + "|" + someTool.mId + " has non-positive quality"); - } + messages.push_back (std::make_pair (someID, someTool.mId + " has non-positive quality")); } -template void CSMTools::ReferenceableCheckStage::listCheck( - const LIST& someList, - std::vector< std::string >& messages, - const std::string& someID) +template void CSMTools::ReferenceableCheckStage::listCheck ( + const List& someList, Messages& messages, const std::string& someID) { for (unsigned i = 0; i < someList.mList.size(); ++i) { if (mReferencables.searchId(someList.mList[i].mId).first == -1) - { - messages.push_back(someID + "|" + someList.mId + " contains item without referencable"); - } + messages.push_back (std::make_pair (someID, + someList.mId + " contains item without referencable")); if (someList.mList[i].mLevel < 1) - { - messages.push_back(someID + "|" + someList.mId + " contains item with non-positive level"); - } + messages.push_back (std::make_pair (someID, + someList.mId + " contains item with non-positive level")); } } -// kate: indent-mode cstyle; indent-width 4; replace-tabs on; diff --git a/apps/opencs/model/tools/referenceablecheck.hpp b/apps/opencs/model/tools/referenceablecheck.hpp index 338983cc7..b0129fc2a 100644 --- a/apps/opencs/model/tools/referenceablecheck.hpp +++ b/apps/opencs/model/tools/referenceablecheck.hpp @@ -11,63 +11,64 @@ namespace CSMTools class ReferenceableCheckStage : public CSMDoc::Stage { public: - ReferenceableCheckStage(const CSMWorld::RefIdData& referenceable, - const CSMWorld::IdCollection& races, - const CSMWorld::IdCollection& classes, - const CSMWorld::IdCollection& factions); - virtual void perform(int stage, std::vector< std::string >& messages); + ReferenceableCheckStage (const CSMWorld::RefIdData& referenceable, + const CSMWorld::IdCollection& races, + const CSMWorld::IdCollection& classes, + const CSMWorld::IdCollection& factions); + + virtual void perform(int stage, Messages& messages); virtual int setup(); private: //CONCRETE CHECKS - void bookCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Book >& records, std::vector< std::string >& messages); - void activatorCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Activator >& records, std::vector< std::string >& messages); - void potionCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void apparatusCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void armorCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void clothingCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void containerCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void creatureCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void doorCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void ingredientCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void creaturesLevListCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void itemLevelledListCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void lightCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void lockpickCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void miscCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void npcCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void weaponCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void probeCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void repairCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - void staticCheck(int stage, const CSMWorld::RefIdDataContainer& records, std::vector& messages); - + void bookCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Book >& records, Messages& messages); + void activatorCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Activator >& records, Messages& messages); + void potionCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void apparatusCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void armorCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void clothingCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void containerCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void creatureCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void doorCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void ingredientCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void creaturesLevListCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void itemLevelledListCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void lightCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void lockpickCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void miscCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void npcCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void weaponCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void probeCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void repairCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + void staticCheck(int stage, const CSMWorld::RefIdDataContainer& records, Messages& messages); + //FINAL CHECK - void finalCheck(std::vector& messages); - + void finalCheck (Messages& messages); + //TEMPLATE CHECKS template void inventoryItemCheck(const ITEM& someItem, - std::vector& messages, + Messages& messages, const std::string& someID, bool enchantable); //for all enchantable items. - + template void inventoryItemCheck(const ITEM& someItem, - std::vector& messages, + Messages& messages, const std::string& someID); //for non-enchantable items. - + template void toolCheck(const TOOL& someTool, - std::vector& messages, + Messages& messages, const std::string& someID, bool canbebroken); //for tools with uses. - + template void toolCheck(const TOOL& someTool, - std::vector& messages, + Messages& messages, const std::string& someID); //for tools without uses. template void listCheck(const LIST& someList, - std::vector< std::string >& messages, + Messages& messages, const std::string& someID); - + const CSMWorld::RefIdData& mReferencables; const CSMWorld::IdCollection& mRaces; const CSMWorld::IdCollection& mClasses; diff --git a/apps/opencs/model/tools/regioncheck.cpp b/apps/opencs/model/tools/regioncheck.cpp index 4398e00ef..07df20470 100644 --- a/apps/opencs/model/tools/regioncheck.cpp +++ b/apps/opencs/model/tools/regioncheck.cpp @@ -17,7 +17,7 @@ int CSMTools::RegionCheckStage::setup() return mRegions.getSize(); } -void CSMTools::RegionCheckStage::perform (int stage, std::vector& messages) +void CSMTools::RegionCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mRegions.getRecord (stage); @@ -30,7 +30,7 @@ void CSMTools::RegionCheckStage::perform (int stage, std::vector& m // test for empty name if (region.mName.empty()) - messages.push_back (id.toString() + "|" + region.mId + " has an empty name"); + messages.push_back (std::make_pair (id, region.mId + " has an empty name")); /// \todo test that the ID in mSleeplist exists diff --git a/apps/opencs/model/tools/regioncheck.hpp b/apps/opencs/model/tools/regioncheck.hpp index c8c437cbd..a12903e7d 100644 --- a/apps/opencs/model/tools/regioncheck.hpp +++ b/apps/opencs/model/tools/regioncheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp index d88361746..75545a7c7 100644 --- a/apps/opencs/model/tools/reportmodel.cpp +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -51,16 +51,11 @@ bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& p return true; } -void CSMTools::ReportModel::add (const std::string& row) +void CSMTools::ReportModel::add (const CSMWorld::UniversalId& id, const std::string& message) { - std::string::size_type index = row.find ('|'); - - if (index==std::string::npos) - throw std::logic_error ("invalid report message"); - beginInsertRows (QModelIndex(), mRows.size(), mRows.size()); - mRows.push_back (std::make_pair (row.substr (0, index), row.substr (index+1))); + mRows.push_back (std::make_pair (id, message)); endInsertRows(); } diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp index 55c25d907..0f000245e 100644 --- a/apps/opencs/model/tools/reportmodel.hpp +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -28,7 +28,7 @@ namespace CSMTools virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); - void add (const std::string& row); + void add (const CSMWorld::UniversalId& id, const std::string& message); const CSMWorld::UniversalId& getUniversalId (int row) const; }; diff --git a/apps/opencs/model/tools/scriptcheck.cpp b/apps/opencs/model/tools/scriptcheck.cpp index a5154d292..b989e22a2 100644 --- a/apps/opencs/model/tools/scriptcheck.cpp +++ b/apps/opencs/model/tools/scriptcheck.cpp @@ -16,8 +16,6 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); - stream << id.toString() << "|"; - if (type==ErrorMessage) stream << "error "; else @@ -28,25 +26,15 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi << ", line " << loc.mLine << ", column " << loc.mColumn << " (" << loc.mLiteral << "): " << message; - mMessages->push_back (stream.str()); + mMessages->push_back (std::make_pair (id, stream.str())); } void CSMTools::ScriptCheckStage::report (const std::string& message, Type type) { - std::ostringstream stream; - CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); - stream << id.toString() << "|"; - - if (type==ErrorMessage) - stream << "error: "; - else - stream << "warning: "; - - stream << message; - - mMessages->push_back (stream.str()); + mMessages->push_back (std::make_pair (id, + (type==ErrorMessage ? "error: " : "warning: ") + message)); } CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMWorld::Data& data) @@ -68,7 +56,7 @@ int CSMTools::ScriptCheckStage::setup() return mData.getScripts().getSize(); } -void CSMTools::ScriptCheckStage::perform (int stage, std::vector& messages) +void CSMTools::ScriptCheckStage::perform (int stage, Messages& messages) { mMessages = &messages; mId = mData.getScripts().getId (stage); @@ -90,13 +78,10 @@ void CSMTools::ScriptCheckStage::perform (int stage, std::vector& m } catch (const std::exception& error) { - std::ostringstream stream; - CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); - stream << id.toString() << "|Critical compile error: " << error.what(); - - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id, + std::string ("Critical compile error: ") + error.what())); } mMessages = 0; diff --git a/apps/opencs/model/tools/scriptcheck.hpp b/apps/opencs/model/tools/scriptcheck.hpp index 8de8e1a66..ecf8d61b7 100644 --- a/apps/opencs/model/tools/scriptcheck.hpp +++ b/apps/opencs/model/tools/scriptcheck.hpp @@ -18,7 +18,7 @@ namespace CSMTools CSMWorld::ScriptContext mContext; std::string mId; std::string mFile; - std::vector *mMessages; + Messages *mMessages; virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type); ///< Report error to the user. @@ -33,7 +33,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/skillcheck.cpp b/apps/opencs/model/tools/skillcheck.cpp index 28fc24fd3..630516c72 100644 --- a/apps/opencs/model/tools/skillcheck.cpp +++ b/apps/opencs/model/tools/skillcheck.cpp @@ -16,7 +16,7 @@ int CSMTools::SkillCheckStage::setup() return mSkills.getSize(); } -void CSMTools::SkillCheckStage::perform (int stage, std::vector& messages) +void CSMTools::SkillCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mSkills.getRecord (stage); @@ -32,11 +32,11 @@ void CSMTools::SkillCheckStage::perform (int stage, std::vector& me { std::ostringstream stream; - stream << id.toString() << "|Use value #" << i << " of " << skill.mId << " is negative"; + stream << "Use value #" << i << " of " << skill.mId << " is negative"; - messages.push_back (stream.str()); + messages.push_back (std::make_pair (id, stream.str())); } if (skill.mDescription.empty()) - messages.push_back (id.toString() + "|" + skill.mId + " has an empty description"); + messages.push_back (std::make_pair (id, skill.mId + " has an empty description")); } \ No newline at end of file diff --git a/apps/opencs/model/tools/skillcheck.hpp b/apps/opencs/model/tools/skillcheck.hpp index 662bdadee..cf5d53b5c 100644 --- a/apps/opencs/model/tools/skillcheck.hpp +++ b/apps/opencs/model/tools/skillcheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/soundcheck.cpp b/apps/opencs/model/tools/soundcheck.cpp index dce2d2b6f..3d222e909 100644 --- a/apps/opencs/model/tools/soundcheck.cpp +++ b/apps/opencs/model/tools/soundcheck.cpp @@ -16,7 +16,7 @@ int CSMTools::SoundCheckStage::setup() return mSounds.getSize(); } -void CSMTools::SoundCheckStage::perform (int stage, std::vector& messages) +void CSMTools::SoundCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mSounds.getRecord (stage); @@ -28,7 +28,7 @@ void CSMTools::SoundCheckStage::perform (int stage, std::vector& me CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Sound, sound.mId); if (sound.mData.mMinRange>sound.mData.mMaxRange) - messages.push_back (id.toString() + "|Maximum range larger than minimum range"); + messages.push_back (std::make_pair (id, "Maximum range larger than minimum range")); /// \todo check, if the sound file exists } \ No newline at end of file diff --git a/apps/opencs/model/tools/soundcheck.hpp b/apps/opencs/model/tools/soundcheck.hpp index 00b45cd93..a82a0eb6d 100644 --- a/apps/opencs/model/tools/soundcheck.hpp +++ b/apps/opencs/model/tools/soundcheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/spellcheck.cpp b/apps/opencs/model/tools/spellcheck.cpp index a2cc7c8d2..3d0be46fd 100644 --- a/apps/opencs/model/tools/spellcheck.cpp +++ b/apps/opencs/model/tools/spellcheck.cpp @@ -17,7 +17,7 @@ int CSMTools::SpellCheckStage::setup() return mSpells.getSize(); } -void CSMTools::SpellCheckStage::perform (int stage, std::vector& messages) +void CSMTools::SpellCheckStage::perform (int stage, Messages& messages) { const CSMWorld::Record& record = mSpells.getRecord (stage); @@ -30,11 +30,11 @@ void CSMTools::SpellCheckStage::perform (int stage, std::vector& me // test for empty name and description if (spell.mName.empty()) - messages.push_back (id.toString() + "|" + spell.mId + " has an empty name"); + messages.push_back (std::make_pair (id, spell.mId + " has an empty name")); // test for invalid cost values if (spell.mData.mCost<0) - messages.push_back (id.toString() + "|" + spell.mId + " has a negative spell costs"); + messages.push_back (std::make_pair (id, spell.mId + " has a negative spell costs")); /// \todo check data members that can't be edited in the table view } \ No newline at end of file diff --git a/apps/opencs/model/tools/spellcheck.hpp b/apps/opencs/model/tools/spellcheck.hpp index 880ddafcd..182f1888b 100644 --- a/apps/opencs/model/tools/spellcheck.hpp +++ b/apps/opencs/model/tools/spellcheck.hpp @@ -21,7 +21,7 @@ namespace CSMTools virtual int setup(); ///< \return number of steps - virtual void perform (int stage, std::vector& messages); + virtual void perform (int stage, Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 8104cc3e6..a11297b45 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -45,8 +45,9 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier() connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); connect (mVerifier, SIGNAL (done (int)), this, SIGNAL (done (int))); - connect (mVerifier, SIGNAL (reportMessage (const QString&, int)), - this, SLOT (verifierMessage (const QString&, int))); + connect (mVerifier, + SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)), + this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, int))); std::vector mandatoryIds; // I want C++11, damn it! mandatoryIds.push_back ("Day"); @@ -139,11 +140,12 @@ CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId& return mReports.at (id.getIndex()); } -void CSMTools::Tools::verifierMessage (const QString& message, int type) +void CSMTools::Tools::verifierMessage (const CSMWorld::UniversalId& id, const std::string& message, + int type) { std::map::iterator iter = mActiveReports.find (type); if (iter!=mActiveReports.end()) - mReports[iter->second]->add (message.toUtf8().constData()); + mReports[iter->second]->add (id, message); } diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 0079fab34..3394d3f62 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -61,7 +61,8 @@ namespace CSMTools private slots: - void verifierMessage (const QString& message, int type); + void verifierMessage (const CSMWorld::UniversalId& id, const std::string& message, + int type); signals: diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 93b734e27..885e23033 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -458,7 +458,7 @@ CSMWorld::IdCollection& CSMWorld::Data::getFilters() return mFilters; } -QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) +QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); diff --git a/apps/opencs/model/world/tablemimedata.cpp b/apps/opencs/model/world/tablemimedata.cpp index d7b7728a5..6d65d0ff8 100644 --- a/apps/opencs/model/world/tablemimedata.cpp +++ b/apps/opencs/model/world/tablemimedata.cpp @@ -1,6 +1,9 @@ #include "tablemimedata.hpp" + #include +#include + #include "universalid.hpp" #include "columnbase.hpp" @@ -11,7 +14,7 @@ mDocument(document) mObjectsFormats << QString::fromUtf8 (("tabledata/" + id.getTypeName()).c_str()); } -CSMWorld::TableMimeData::TableMimeData (std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) : +CSMWorld::TableMimeData::TableMimeData (const std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) : mUniversalId (id), mDocument(document) { for (std::vector::iterator it (mUniversalId.begin()); it != mUniversalId.end(); ++it) @@ -33,7 +36,8 @@ std::string CSMWorld::TableMimeData::getIcon() const { if (mUniversalId.empty()) { - throw ("TableMimeData holds no UniversalId"); + qDebug()<<"TableMimeData object does not hold any records!"; //because throwing in the event loop tends to be problematic + throw("TableMimeData object does not hold any records!"); } std::string tmpIcon; @@ -50,7 +54,7 @@ std::string CSMWorld::TableMimeData::getIcon() const if (tmpIcon != mUniversalId[i].getIcon()) { - return ":/multitype.png"; //icon stolen from gnome + return ":/multitype.png"; //icon stolen from gnome TODO: get new icon } tmpIcon = mUniversalId[i].getIcon(); @@ -531,4 +535,4 @@ CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (CSMWorld::U const CSMDoc::Document* CSMWorld::TableMimeData::getDocumentPtr() const { return &mDocument; -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/tablemimedata.hpp b/apps/opencs/model/world/tablemimedata.hpp index adcb147c1..85c243944 100644 --- a/apps/opencs/model/world/tablemimedata.hpp +++ b/apps/opencs/model/world/tablemimedata.hpp @@ -33,7 +33,7 @@ namespace CSMWorld public: TableMimeData(UniversalId id, const CSMDoc::Document& document); - TableMimeData(std::vector& id, const CSMDoc::Document& document); + TableMimeData(const std::vector& id, const CSMDoc::Document& document); ~TableMimeData(); @@ -56,6 +56,7 @@ namespace CSMWorld UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const; static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type); + static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type); private: diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index a62acc02b..94b042ec5 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -64,6 +64,7 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" }, diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 34167cd85..24fb54399 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -60,6 +60,7 @@ namespace CSMWorld Type_Spell, Type_Cells, Type_Cell, + Type_Cell_Missing, //For cells that does not exist yet. Type_Referenceables, Type_Referenceable, Type_Activator, diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index acb272553..95ab6ca27 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -236,10 +236,10 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to mViewTotal (totalViews) { QString width = CSMSettings::UserSettings::instance().settingValue - ("Window Size.Width"); + ("Window Size/Width"); QString height = CSMSettings::UserSettings::instance().settingValue - ("Window Size.Height"); + ("Window Size/Height"); resize (width.toInt(), height.toInt()); diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index 0f23dfe7b..a3f34d218 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -3,8 +3,12 @@ #include -CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent) -: WorldspaceWidget (parent) +#include + +#include + +CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document) +: WorldspaceWidget (document, parent) {} void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint) @@ -44,4 +48,45 @@ void CSVRender::PagedWorldspaceWidget::setCellSelection (const CSMWorld::CellSel { mSelection = selection; emit cellSelectionChanged (mSelection); +} + +std::pair< int, int > CSVRender::PagedWorldspaceWidget::getCoordinatesFromId (const std::string& record) const +{ + std::istringstream stream (record.c_str()); + char ignore; + int x, y; + stream >> ignore >> x >> y; + return std::make_pair(x, y); +} + +void CSVRender::PagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data) +{ + bool selectionChanged = false; + for (unsigned i = 0; i < data.size(); ++i) + { + std::pair coordinates(getCoordinatesFromId(data[i].getId())); + if (mSelection.add(CSMWorld::CellCoordinates(coordinates.first, coordinates.second))) + { + selectionChanged = true; + } + } + if (selectionChanged) + { + emit cellSelectionChanged(mSelection); + } +} + +CSVRender::WorldspaceWidget::dropRequirments CSVRender::PagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const +{ + switch (type) + { + case cellsExterior: + return canHandle; + + case cellsInterior: + return needUnpaged; + + default: + return ignored; + } } \ No newline at end of file diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index f6ff32dc1..0a73c791c 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -13,17 +13,25 @@ namespace CSVRender CSMWorld::CellSelection mSelection; + private: + + std::pair getCoordinatesFromId(const std::string& record) const; + public: - PagedWorldspaceWidget (QWidget *parent); + PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document); ///< \note Sets the cell area selection to an invalid value to indicate that currently /// no cells are displayed. The cells to be displayed will be specified later through /// hint system. - virtual void useViewHint (const std::string& hint); + void useViewHint (const std::string& hint); void setCellSelection (const CSMWorld::CellSelection& selection); + virtual void handleDrop(const std::vector& data); + + virtual dropRequirments getDropRequirements(dropType type) const; + signals: void cellSelectionChanged (const CSMWorld::CellSelection& selection); diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 1aee421ed..8a58b7d32 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -320,7 +320,7 @@ namespace CSVRender } - if (mUpdate) + if (mUpdate && mWindow) { mUpdate = false; mWindow->update(); diff --git a/apps/opencs/view/render/scenewidget.hpp b/apps/opencs/view/render/scenewidget.hpp index 8df9cf347..7f8f104f1 100644 --- a/apps/opencs/view/render/scenewidget.hpp +++ b/apps/opencs/view/render/scenewidget.hpp @@ -36,7 +36,7 @@ namespace CSVRender SceneWidget(QWidget *parent); virtual ~SceneWidget(); - QPaintEngine* paintEngine() const; + QPaintEngine* paintEngine() const; CSVWorld::SceneToolMode *makeLightingSelector (CSVWorld::SceneToolbar *parent); ///< \attention The created tool is not added to the toolbar (via addTool). Doing that diff --git a/apps/opencs/view/render/unpagedworldspacewidget.cpp b/apps/opencs/view/render/unpagedworldspacewidget.cpp index fb74788cc..166c85f44 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.cpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.cpp @@ -3,10 +3,13 @@ #include +#include + #include "../../model/doc/document.hpp" #include "../../model/world/data.hpp" #include "../../model/world/idtable.hpp" +#include "../../model/world/tablemimedata.hpp" void CSVRender::UnpagedWorldspaceWidget::update() { @@ -20,9 +23,8 @@ void CSVRender::UnpagedWorldspaceWidget::update() /// \todo deal with mSunlight and mFog/mForDensity } -CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, - CSMDoc::Document& document, QWidget *parent) -: WorldspaceWidget (parent), mCellId (cellId) +CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget* parent) +: WorldspaceWidget (document, parent), mCellId (cellId) { mCellsModel = &dynamic_cast ( *document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells)); @@ -63,4 +65,26 @@ void CSVRender::UnpagedWorldspaceWidget::cellRowsAboutToBeRemoved (const QModelI if (cellIndex.row()>=start && cellIndex.row()<=end) emit closeRequest(); -} \ No newline at end of file +} + +void CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data) +{ + mCellId = data.begin()->getId(); + update(); + emit cellChanged(*data.begin()); +} + +CSVRender::WorldspaceWidget::dropRequirments CSVRender::UnpagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const +{ + switch(type) + { + case cellsInterior: + return canHandle; + + case cellsExterior: + return needPaged; + + default: + return ignored; + } +} diff --git a/apps/opencs/view/render/unpagedworldspacewidget.hpp b/apps/opencs/view/render/unpagedworldspacewidget.hpp index 17dc46918..bb5340845 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.hpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.hpp @@ -31,13 +31,21 @@ namespace CSVRender public: UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, - QWidget *parent); + QWidget *parent); + + virtual dropRequirments getDropRequirements(dropType type) const; + + virtual void handleDrop(const std::vector& data); private slots: void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); void cellRowsAboutToBeRemoved (const QModelIndex& parent, int start, int end); + + signals: + + void cellChanged(const CSMWorld::UniversalId& id); }; } diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 4d2442c89..59b82bb67 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -5,15 +5,20 @@ #include #include +#include + #include "../world/scenetoolmode.hpp" +#include -CSVRender::WorldspaceWidget::WorldspaceWidget (QWidget *parent) -: SceneWidget (parent) +CSVRender::WorldspaceWidget::WorldspaceWidget (const CSMDoc::Document& document, QWidget* parent) +: SceneWidget (parent), mDocument(document) { Ogre::Entity* ent = getSceneManager()->createEntity("cube", Ogre::SceneManager::PT_CUBE); ent->setMaterialName("BaseWhite"); getSceneManager()->getRootSceneNode()->attachObject(ent); + + setAcceptDrops(true); } void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode) @@ -46,4 +51,78 @@ CSVWorld::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector ( this, SLOT (selectNavigationMode (const std::string&))); return tool; +} + +CSVRender::WorldspaceWidget::dropType CSVRender::WorldspaceWidget::getDropType ( + const std::vector< CSMWorld::UniversalId >& data) +{ + dropType output = notCells; + bool firstIteration = true; + + for (unsigned i = 0; i < data.size(); ++i) + { + if (data[i].getType() == CSMWorld::UniversalId::Type_Cell || + data[i].getType() == CSMWorld::UniversalId::Type_Cell_Missing) + { + if (*(data[i].getId().begin()) == '#') //exterior + { + if (firstIteration) + { + output = cellsExterior; + firstIteration = false; + continue; + } + + if (output == cellsInterior) + { + output = cellsMixed; + break; + } else { + output = cellsInterior; + } + } else //interior + { + if (firstIteration) + { + output = cellsInterior; + firstIteration = false; + continue; + } + + if (output == cellsExterior) + { + output = cellsMixed; + break; + } else { + output = cellsInterior; + } + } + } else { + output = notCells; + break; + } + } + + return output; +} + +void CSVRender::WorldspaceWidget::dragEnterEvent (QDragEnterEvent* event) +{ + event->accept(); +} + +void CSVRender::WorldspaceWidget::dragMoveEvent(QDragMoveEvent *event) +{ + event->accept(); +} + + +void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event) +{ + const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); + + if (mime->fromDocument (mDocument)) + { + emit dataDropped(mime->getData()); + } //not handling drops from different documents at the moment } \ No newline at end of file diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index f7208d7a1..a14e03915 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -6,7 +6,13 @@ #include "navigation1st.hpp" #include "navigationfree.hpp" #include "navigationorbit.hpp" +#include +#include +namespace CSMWorld +{ + class UniversalId; +} namespace CSVWorld { class SceneToolMode; @@ -25,7 +31,23 @@ namespace CSVRender public: - WorldspaceWidget (QWidget *parent = 0); + enum dropType + { + cellsMixed, + cellsInterior, + cellsExterior, + notCells + }; + + enum dropRequirments + { + canHandle, + needPaged, + needUnpaged, + ignored //either mixed cells, or not cells + }; + + WorldspaceWidget (const CSMDoc::Document& document, QWidget *parent = 0); CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent); ///< \attention The created tool is not added to the toolbar (via addTool). Doing that @@ -33,9 +55,26 @@ namespace CSVRender void selectDefaultNavigationMode(); + static dropType getDropType(const std::vector& data); + + virtual dropRequirments getDropRequirements(dropType type) const = 0; + virtual void useViewHint (const std::string& hint); ///< Default-implementation: ignored. + virtual void handleDrop(const std::vector& data) = 0; + + protected: + const CSMDoc::Document& mDocument; //for checking if drop comes from same document + + private: + + void dragEnterEvent(QDragEnterEvent *event); + + void dropEvent(QDropEvent* event); + + void dragMoveEvent(QDragMoveEvent *event); + private slots: void selectNavigationMode (const std::string& mode); @@ -43,6 +82,7 @@ namespace CSVRender signals: void closeRequest(); + void dataDropped(const std::vector& data); }; } diff --git a/apps/opencs/view/settings/booleanview.cpp b/apps/opencs/view/settings/booleanview.cpp index 1c48199d1..2a3f0cba6 100644 --- a/apps/opencs/view/settings/booleanview.cpp +++ b/apps/opencs/view/settings/booleanview.cpp @@ -18,10 +18,19 @@ CSVSettings::BooleanView::BooleanView (CSMSettings::Setting *setting, { QAbstractButton *button = 0; - if (isMultiValue()) + switch (setting->type()) + { + case CSMSettings::Type_CheckBox: button = new QCheckBox (value, this); - else + break; + + case CSMSettings::Type_RadioButton: button = new QRadioButton (value, this); + break; + + default: + break; + } connect (button, SIGNAL (clicked (bool)), this, SLOT (slotToggled (bool))); diff --git a/apps/opencs/view/settings/dialog.cpp b/apps/opencs/view/settings/dialog.cpp index d9d5830d9..56bc1fdfe 100644 --- a/apps/opencs/view/settings/dialog.cpp +++ b/apps/opencs/view/settings/dialog.cpp @@ -76,22 +76,9 @@ void CSVSettings::Dialog::buildPages() mStackedWidget->addWidget (&dynamic_cast(*(page))); } - addDebugPage(); - resize (mStackedWidget->sizeHint()); } -void CSVSettings::Dialog::addDebugPage() -{ - /* - QTreeView *tree = new QTreeView(); - - //tree->setModel( &CSMSettings::UserSettings::instance().model() ); - - mStackedWidget->addWidget(tree); - new QListWidgetItem ("Standard Item Model", mPageListWidget);*/ -} - void CSVSettings::Dialog::buildPageListWidget (QWidget *centralWidget) { mPageListWidget = new QListWidget (centralWidget); @@ -122,11 +109,13 @@ void CSVSettings::Dialog::closeEvent (QCloseEvent *event) void CSVSettings::Dialog::show() { if (pages().isEmpty()) + { buildPages(); + setViewValues(); + } QPoint screenCenter = QApplication::desktop()->screenGeometry().center(); move (screenCenter - geometry().center()); - QWidget::show(); } diff --git a/apps/opencs/view/settings/dialog.hpp b/apps/opencs/view/settings/dialog.hpp index 0cfd415ac..b0e12c461 100644 --- a/apps/opencs/view/settings/dialog.hpp +++ b/apps/opencs/view/settings/dialog.hpp @@ -41,7 +41,6 @@ namespace CSVSettings { void buildPages(); void buildPageListWidget (QWidget *centralWidget); void buildStackedWidget (QWidget *centralWidget); - void addDebugPage(); public slots: diff --git a/apps/opencs/view/settings/frame.cpp b/apps/opencs/view/settings/frame.cpp index db5091999..019024776 100644 --- a/apps/opencs/view/settings/frame.cpp +++ b/apps/opencs/view/settings/frame.cpp @@ -60,8 +60,10 @@ void CSVSettings::Frame::showWidgets() QWidget *widg = static_cast (obj); if (widg->property("sizePolicy").isValid()) + { widg->setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + } } layout()->activate(); setFixedSize(minimumSizeHint()); diff --git a/apps/opencs/view/settings/frame.hpp b/apps/opencs/view/settings/frame.hpp index 2b52dfd1f..bbb92f34f 100644 --- a/apps/opencs/view/settings/frame.hpp +++ b/apps/opencs/view/settings/frame.hpp @@ -44,11 +44,13 @@ namespace CSVSettings void setHLayout() { mIsHorizontal = true; } void setVLayout() { mIsHorizontal = false; } + ///show / hide widgets (when stacked widget page changes) void showWidgets(); void hideWidgets(); private: + ///functions which return the index for the next layout row / column int getNextColumn() const; int getNextRow() const; diff --git a/apps/opencs/view/settings/page.cpp b/apps/opencs/view/settings/page.cpp index e67445873..afd4bff5e 100644 --- a/apps/opencs/view/settings/page.cpp +++ b/apps/opencs/view/settings/page.cpp @@ -7,6 +7,8 @@ #include "../../model/settings/usersettings.hpp" #include "../../model/settings/connector.hpp" +#include "../../model/settings/support.hpp" + #include "settingwindow.hpp" QMap diff --git a/apps/opencs/view/settings/page.hpp b/apps/opencs/view/settings/page.hpp index 7f24f6a62..877d4bef8 100644 --- a/apps/opencs/view/settings/page.hpp +++ b/apps/opencs/view/settings/page.hpp @@ -1,7 +1,6 @@ #ifndef CSVSETTINGS_PAGE_HPP #define CSVSETTINGS_PAGE_HPP -#include #include #include #include @@ -40,6 +39,7 @@ namespace CSVSettings ///and returns it. View *findView (const QString &page, const QString &setting) const; + ///returns the list of views associated with the page const QList &views () const { return mViews; } private: diff --git a/apps/opencs/view/settings/rangeview.cpp b/apps/opencs/view/settings/rangeview.cpp index 2bb5863bc..8ae6caca0 100644 --- a/apps/opencs/view/settings/rangeview.cpp +++ b/apps/opencs/view/settings/rangeview.cpp @@ -1,88 +1,195 @@ -#include -#include - -#include -#include -#include - -#include +#include +#include +#include +#include +#include +#include #include "rangeview.hpp" +#include "spinbox.hpp" #include "../../model/settings/setting.hpp" - - -#include +#include "../../model/settings/support.hpp" CSVSettings::RangeView::RangeView (CSMSettings::Setting *setting, Page *parent) - : View (setting, parent) + : mRangeWidget (0), mRangeType (setting->type()), View (setting, parent) { - foreach (const QString &value, setting->declaredValues()) + + mRangeWidget = 0; + + if (isMultiValue()) + return; + + switch (mRangeType) { - QAbstractButton *button = 0; + case CSMSettings::Type_SpinBox: + case CSMSettings::Type_DoubleSpinBox: + buildSpinBox (setting); + break; + + case CSMSettings::Type_Dial: + case CSMSettings::Type_Slider: + buildSlider (setting); + break; + + default: + break; + } - if (isMultiValue()) - button = new QCheckBox (value, this); - else - button = new QRadioButton (value, this); + mRangeWidget->setFixedWidth (widgetWidth (setting->widgetWidth())); + mRangeWidget->setObjectName (setting->name()); - connect (button, SIGNAL (clicked (bool)), - this, SLOT (slotToggled (bool))); + addWidget (mRangeWidget); +} - button->setObjectName (value); +void CSVSettings::RangeView::buildSlider (CSMSettings::Setting *setting) +{ + switch (setting->type()) + { + case CSMSettings::Type_Slider: + mRangeWidget = new QSlider (Qt::Horizontal, this); + mRangeWidget->setProperty ("tickInterval", setting->tickInterval()); + + if (setting->ticksAbove()) + { + if (setting->ticksBelow()) + mRangeWidget->setProperty ("tickPosition", QSlider::TicksBothSides); + else + mRangeWidget->setProperty ("tickPosition", QSlider::TicksAbove); + } + else if (setting->ticksBelow()) + mRangeWidget->setProperty ("tickPosition", QSlider::TicksBelow); + else + mRangeWidget->setProperty ("tickPosition", QSlider::NoTicks); + + break; - addWidget (button); + case CSMSettings::Type_Dial: + mRangeWidget = new QDial (this); + mRangeWidget->setProperty ("wrapping", setting->wrapping()); + mRangeWidget->setProperty ("notchesVisible", + (setting->ticksAbove() || setting->ticksBelow())); + break; - mButtons[value] = button; + default: + break; } + + mRangeWidget->setProperty ("minimum", setting->minimum()); + mRangeWidget->setProperty ("maximum", setting->maximum()); + mRangeWidget->setProperty ("tracking", false); + mRangeWidget->setProperty ("singleStep", setting->singleStep()); + + connect (mRangeWidget, SIGNAL (valueChanged (int)), + this, SLOT (slotUpdateView (int))); } -void CSVSettings::RangeView::slotToggled (bool state) +void CSVSettings::RangeView::buildSpinBox (CSMSettings::Setting *setting) { - //test only for true to avoid multiple selection updates with radiobuttons - if (!isMultiValue() && !state) - return; + SpinBox *sb = 0; + + switch (setting->type()) + { + case CSMSettings::Type_SpinBox: + + sb = new SpinBox (this); + + if (!setting->declaredValues().isEmpty()) + sb->setValueList (setting->declaredValues()); + + mRangeWidget = sb; - QStringList values; + connect (mRangeWidget, SIGNAL (valueChanged (int)), + this, SLOT (slotUpdateView (int))); + break; - foreach (QString key, mButtons.keys()) + case CSMSettings::Type_DoubleSpinBox: + mRangeWidget = new QDoubleSpinBox (this); + + connect (mRangeWidget, SIGNAL (valueChanged (double)), + this, SLOT (slotUpdateView (double))); + break; + + default: + break; + } + + //min / max values are set automatically in AlphaSpinBox + if (setting->declaredValues().isEmpty()) + { + mRangeWidget->setProperty ("minimum", setting->minimum()); + mRangeWidget->setProperty ("maximum", setting->maximum()); + mRangeWidget->setProperty ("singleStep", setting->singleStep()); + mRangeWidget->setProperty ("specialValueText", + setting->specialValueText()); + } + + mRangeWidget->setProperty ("prefix", setting->prefix()); + mRangeWidget->setProperty ("suffix", setting->suffix()); + mRangeWidget->setProperty ("wrapping", setting->wrapping()); + +} + +void CSVSettings::RangeView::slotUpdateView (int value) +{ + QString textValue = ""; + QStringList list; + + switch (mRangeType) { - if (mButtons.value(key)->isChecked()) - values.append (key); + case CSMSettings::Type_SpinBox: + list = static_cast (mRangeWidget)->valueList(); + if (!list.isEmpty()) + textValue = list.at(value); + break; + + default: + break; } - setSelectedValues (values, false); + + if (textValue.isEmpty()) + textValue = QVariant (value).toString(); + + setSelectedValue (textValue, false); View::updateView(); } -void CSVSettings::RangeView::updateView (bool signalUpdate) const +void CSVSettings::RangeView::slotUpdateView (double value) { + setSelectedValue (QVariant(value).toString(), false); - QStringList values = selectedValues(); + View::updateView(); +} - foreach (const QString &buttonName, mButtons.keys()) - { - QAbstractButton *button = mButtons[buttonName]; +void CSVSettings::RangeView::updateView (bool signalUpdate) const +{ + QString value; - //if the value is not found in the list, the widget is checked false - bool buttonValue = values.contains(buttonName); + if (!selectedValues().isEmpty()) + value = selectedValues().at(0); - //skip if the butotn value will not change - if (button->isChecked() == buttonValue) - continue; + switch (mRangeType) + { + case CSMSettings::Type_SpinBox: + static_cast (mRangeWidget)->setValue (value); + break; - //disable autoexclusive if it's enabled and we're setting - //the button value to false - bool switchExclusive = (!buttonValue && button->autoExclusive()); + case CSMSettings::Type_DoubleSpinBox: + static_cast (mRangeWidget)->setValue (value.toDouble()); + break; - if (switchExclusive) - button->setAutoExclusive (false); + case CSMSettings::Type_Slider: + case CSMSettings::Type_Dial: + mRangeWidget->setProperty ("value", value.toInt()); + mRangeWidget->setProperty ("sliderPosition", value.toInt()); + break; - button->setChecked (buttonValue); + default: + break; - if (switchExclusive) - button->setAutoExclusive(true); } + View::updateView (signalUpdate); } diff --git a/apps/opencs/view/settings/rangeview.hpp b/apps/opencs/view/settings/rangeview.hpp index 1df0c7bd6..2ab343f1f 100644 --- a/apps/opencs/view/settings/rangeview.hpp +++ b/apps/opencs/view/settings/rangeview.hpp @@ -1,13 +1,11 @@ #ifndef CSVSETTINGS_RANGEVIEW_HPP #define CSVSETTINGS_RANGEVIEW_HPP -#include -#include - #include "view.hpp" #include "../../model/settings/support.hpp" class QStringListModel; +class QAbstractSpinBox; namespace CSVSettings { @@ -15,17 +13,30 @@ namespace CSVSettings { Q_OBJECT - QMap mButtons; + QWidget *mRangeWidget; + CSMSettings::SettingType mRangeType; public: explicit RangeView (CSMSettings::Setting *setting, Page *parent); protected: + + ///virtual function called through View void updateView (bool signalUpdate = true) const; + ///construct a slider-based view + void buildSlider (CSMSettings::Setting *setting); + + ///construct a spinbox-based view + void buildSpinBox (CSMSettings::Setting *setting); + private slots: - void slotToggled (bool state); + + ///responds to valueChanged signals + void slotUpdateView (int value); + void slotUpdateView (double value); + }; class RangeViewFactory : public QObject, public IViewFactory diff --git a/apps/opencs/view/settings/resizeablestackedwidget.hpp b/apps/opencs/view/settings/resizeablestackedwidget.hpp index 5e894d8df..2d0c71a23 100644 --- a/apps/opencs/view/settings/resizeablestackedwidget.hpp +++ b/apps/opencs/view/settings/resizeablestackedwidget.hpp @@ -14,8 +14,10 @@ namespace CSVSettings public: explicit ResizeableStackedWidget(QWidget *parent = 0); + ///add a widget to the stacked widget void addWidget(QWidget* pWidget); + ///called whenever the stacked widget page is changed void changePage (int, int); }; } diff --git a/apps/opencs/view/settings/settingwindow.cpp b/apps/opencs/view/settings/settingwindow.cpp index 7bd0b228e..7cdf2bded 100644 --- a/apps/opencs/view/settings/settingwindow.cpp +++ b/apps/opencs/view/settings/settingwindow.cpp @@ -57,7 +57,7 @@ void CSVSettings::SettingWindow::createConnections foreach (const QString &key, proxyMap.keys()) { - QStringList keyPair = key.split('.'); + QStringList keyPair = key.split('/'); if (keyPair.size() != 2) continue; @@ -82,6 +82,25 @@ void CSVSettings::SettingWindow::createConnections } } +void CSVSettings::SettingWindow::setViewValues() +{ + //iterate each page and view, setting their definintions + //if they exist in the model + foreach (const Page *page, mPages) + { + foreach (const View *view, page->views()) + { + //testing beforehand prevents overwriting a proxy setting + if (!mModel->hasSettingDefinitions (view->viewKey())) + continue; + + QStringList defs = mModel->definitions (view->viewKey()); + + view->setSelectedValues(defs); + } + } +} + CSVSettings::View *CSVSettings::SettingWindow::findView (const QString &pageName, const QString &setting) { @@ -95,17 +114,19 @@ CSVSettings::View *CSVSettings::SettingWindow::findView void CSVSettings::SettingWindow::saveSettings() { - QMap settingMap; - + //setting the definition in the model automatically syncs with the file foreach (const Page *page, mPages) { foreach (const View *view, page->views()) { - if (view->serializable()) - settingMap[view->viewKey()] = view->selectedValues(); + if (!view->serializable()) + continue; + + mModel->setDefinitions (view->viewKey(), view->selectedValues()); } } - CSMSettings::UserSettings::instance().saveSettings (settingMap); + + mModel->saveDefinitions(); } void CSVSettings::SettingWindow::closeEvent (QCloseEvent *event) diff --git a/apps/opencs/view/settings/settingwindow.hpp b/apps/opencs/view/settings/settingwindow.hpp index 35ae4c068..2266f130d 100644 --- a/apps/opencs/view/settings/settingwindow.hpp +++ b/apps/opencs/view/settings/settingwindow.hpp @@ -8,7 +8,7 @@ namespace CSMSettings { class Setting; - class SettingManager; + class UserSettings; } namespace CSVSettings { @@ -23,25 +23,36 @@ namespace CSVSettings { Q_OBJECT PageList mPages; - CSMSettings::SettingManager *mModel; + CSMSettings::UserSettings *mModel; public: explicit SettingWindow(QWidget *parent = 0); + ///retrieve a reference to a view based on it's page and setting name View *findView (const QString &pageName, const QString &setting); - void setModel (CSMSettings::SettingManager &model) { mModel = &model; } + + ///set the model the view uses (instance of UserSettings) + void setModel (CSMSettings::UserSettings &model) { mModel = &model; } protected: virtual void closeEvent (QCloseEvent *event); + ///construct the pages to be displayed in the dialog void createPages(); + ///return the list of constructed pages const PageList &pages() const { return mPages; } + ///save settings from the GUI to file void saveSettings(); + ///sets the defined values for the views that have been created + void setViewValues(); + private: + + ///create connections between settings (used for proxy settings) void createConnections (const QList &list); }; } diff --git a/apps/opencs/view/settings/spinbox.cpp b/apps/opencs/view/settings/spinbox.cpp new file mode 100644 index 000000000..4b1447f8f --- /dev/null +++ b/apps/opencs/view/settings/spinbox.cpp @@ -0,0 +1,50 @@ +#include "spinbox.hpp" + +#include + +CSVSettings::SpinBox::SpinBox(QWidget *parent) + : mValueList(QStringList()), QSpinBox(parent) +{ + setRange (0, 0); +} + +QString CSVSettings::SpinBox::textFromValue(int val) const +{ + if (mValueList.isEmpty()) + return QVariant (val).toString(); + + QString value; + + if (val < mValueList.size()) + value = mValueList.at (val); + + return value; +} + +int CSVSettings::SpinBox::valueFromText(const QString &text) const +{ + if (mValueList.isEmpty()) + return -1; + + if (mValueList.contains (text)) + return mValueList.indexOf(text); + + return -1; +} + +void CSVSettings::SpinBox::setValue (const QString &value) +{ + if (!mValueList.isEmpty()) + { + lineEdit()->setText (value); + QSpinBox::setValue(valueFromText(value)); + } + else + QSpinBox::setValue (value.toInt()); +} + +void CSVSettings::SpinBox::setValueList (const QStringList &list) +{ + mValueList = list; + setMaximum (list.size() - 1); +} diff --git a/apps/opencs/view/settings/spinbox.hpp b/apps/opencs/view/settings/spinbox.hpp new file mode 100644 index 000000000..e887e8c93 --- /dev/null +++ b/apps/opencs/view/settings/spinbox.hpp @@ -0,0 +1,38 @@ +#ifndef CSVSETTINGS_SPINBOX_HPP +#define CSVSETTINGS_SPINBOX_HPP + +#include +#include +#include + +namespace CSVSettings +{ + class SpinBox : public QSpinBox + { + Q_OBJECT + + QStringList mValueList; + + public: + explicit SpinBox(QWidget *parent = 0); + + ///set the value displayed in the spin box + void setValue (const QString &value); + + ///set the stringlist that's used as a list of pre-defined values + ///to be displayed as the user scrolls + void setValueList (const QStringList &list); + + ///returns the pre-defined value list. + const QStringList &valueList() const { return mValueList; } + + protected: + + ///converts an index value to corresponding text to be displayed + QString textFromValue (int val) const; + + ///converts a text value to a corresponding index + int valueFromText (const QString &text) const; + }; +} +#endif // CSVSETTINGS_SPINBOX_HPP diff --git a/apps/opencs/view/settings/textview.cpp b/apps/opencs/view/settings/textview.cpp index 5e10c346f..6886732db 100644 --- a/apps/opencs/view/settings/textview.cpp +++ b/apps/opencs/view/settings/textview.cpp @@ -28,11 +28,6 @@ bool CSVSettings::TextView::isEquivalent return (lhs.trimmed() == rhs.trimmed()); } -void CSVSettings::TextView::setWidgetText (const QString &value) const -{ - mTextWidget->setProperty ("text", value); -} - void CSVSettings::TextView::slotTextEdited (QString value) { QStringList values = value.split (mDelimiter, QString::SkipEmptyParts); @@ -51,19 +46,14 @@ void CSVSettings::TextView::updateView(bool signalUpdate) const { QString values = selectedValues().join (mDelimiter); - if (isEquivalent (widgetText(), values)) + if (isEquivalent (mTextWidget->property("text").toString(), values)) return; - setWidgetText (values); + mTextWidget->setProperty("text", values); View::updateView (signalUpdate); } -QString CSVSettings::TextView::widgetText() const -{ - return mTextWidget->property("text").toString(); -} - CSVSettings::TextView *CSVSettings::TextViewFactory::createView (CSMSettings::Setting *setting, Page *parent) diff --git a/apps/opencs/view/settings/textview.hpp b/apps/opencs/view/settings/textview.hpp index 6d718aad8..f4cd03d2f 100644 --- a/apps/opencs/view/settings/textview.hpp +++ b/apps/opencs/view/settings/textview.hpp @@ -20,6 +20,7 @@ namespace CSVSettings protected: + /// virtual function called through View void updateView (bool signalUpdate = true) const; protected slots: @@ -32,12 +33,6 @@ namespace CSVSettings ///Comparison function that returns true if the trimmed() strings ///are equal bool isEquivalent (const QString &lhs, const QString &rhs) const; - - ///Convenience function to return the text of the widget - QString widgetText() const; - - ///Convenience function to set the text of the widget - void setWidgetText (const QString &value) const; }; class TextViewFactory : public QObject, public IViewFactory diff --git a/apps/opencs/view/settings/view.cpp b/apps/opencs/view/settings/view.cpp index 4f93b1c0f..69109e2b3 100644 --- a/apps/opencs/view/settings/view.cpp +++ b/apps/opencs/view/settings/view.cpp @@ -1,7 +1,8 @@ -#include -#include +#include #include #include +#include +#include #include "view.hpp" #include "../../model/settings/support.hpp" @@ -14,7 +15,7 @@ CSVSettings::View::View(CSMSettings::Setting *setting, : mDataModel(0), mParentPage (parent), mHasFixedValues (!setting->declaredValues().isEmpty()), mIsMultiValue (setting->isMultiValue()), - mViewKey (setting->page() + '.' + setting->name()), + mViewKey (setting->page() + '/' + setting->name()), mSerializable (setting->serializable()), Frame(true, setting->name(), parent) { @@ -25,10 +26,7 @@ CSVSettings::View::View(CSMSettings::Setting *setting, void CSVSettings::View::buildModel (const CSMSettings::Setting *setting) { - QStringList values = setting->definedValues(); - - if (values.isEmpty()) - values.append (setting->defaultValues()); + QStringList values = setting->defaultValues(); if (mHasFixedValues) buildFixedValueModel (setting->declaredValues()); @@ -42,24 +40,22 @@ void CSVSettings::View::buildModel (const CSMSettings::Setting *setting) void CSVSettings::View::buildFixedValueModel (const QStringList &values) { + //fixed value models are simple string list models, since they are read-only mDataModel = new QStringListModel (values, this); } void CSVSettings::View::buildUpdatableValueModel (const QStringList &values) { + //updateable models are standard item models because they support + //replacing entire columns QList itemList; foreach (const QString &value, values) itemList.append (new QStandardItem(value)); -// QSortFilterProxyModel *filter = new QSortFilterProxyModel (this); QStandardItemModel *model = new QStandardItemModel (this); model->appendColumn (itemList); -// filter->setSourceModel (model); - /* filter->setFilterRegExp ("*"); - filter->setFilterKeyColumn (0); - filter->setFilterRole (Qt::DisplayRole);*/ mDataModel = model; } @@ -117,7 +113,7 @@ void CSVSettings::View::setSelectedValue (const QString &value, } void CSVSettings::View::setSelectedValues (const QStringList &list, - bool doViewUpdate, bool signalUpdate) + bool doViewUpdate, bool signalUpdate) const { QItemSelection selection; @@ -151,9 +147,6 @@ void CSVSettings::View::setSelectedValues (const QStringList &list, } select (selection); - //push changes to model side - - //update the view if the selection was set from the model side, not by the //user if (doViewUpdate) @@ -211,12 +204,12 @@ QString CSVSettings::View::value (int row) const if (row > -1 && row < mDataModel->rowCount()) return mDataModel->data (mDataModel->index(row, 0)).toString(); - return ""; + return QString(); } int CSVSettings::View::widgetWidth(int characterCount) const { - QString widthToken = QString().fill ('P', characterCount); + QString widthToken = QString().fill ('m', characterCount); QFontMetrics fm (QApplication::font()); return (fm.width (widthToken)); diff --git a/apps/opencs/view/settings/view.hpp b/apps/opencs/view/settings/view.hpp index c99879762..84ad62759 100644 --- a/apps/opencs/view/settings/view.hpp +++ b/apps/opencs/view/settings/view.hpp @@ -11,8 +11,6 @@ class QGroupBox; class QStringList; class QStandardItem; class QItemSelection; -class QStringListModel; -class QStandardItemModel; class QAbstractItemModel; class QItemSelectionModel; @@ -42,17 +40,16 @@ namespace CSVSettings ///State indicating whether the view will allow multiple values bool mIsMultiValue; + ///'pagename.settingname' form of the view's id QString mViewKey; + ///indicates whether or not the setting is written to file bool mSerializable; public: explicit View (CSMSettings::Setting *setting, Page *parent); - ///Physical frame in which the view UI is contained - void addViewWidget (QWidget *widget, int row = -1, int col = -1) const; - ///Returns the index / row of the passed value, -1 if not found. int currentIndex () const; @@ -74,7 +71,7 @@ namespace CSVSettings ///or signaling the view was updatedto avoid viscious cylcing. void setSelectedValues (const QStringList &values, bool updateView = true, - bool signalUpdate = true); + bool signalUpdate = true) const; void setSelectedValue (const QString &value, bool updateView = true, @@ -101,7 +98,7 @@ namespace CSVSettings void showEvent ( QShowEvent * event ); ///Virtual for updating a specific View subclass - ///bool indicates whether a signal is emitted that the view was updated + ///bool indicates whether viewUpdated() signal is emitted virtual void updateView (bool signalUpdate = true) const; ///Returns the pixel width corresponding to the specified number of diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index c3ec68b52..31ec18d52 100644 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -7,18 +7,19 @@ CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, const IconList &icons, QUndoStack &undoStack, - const QString &settingKey, + const QString &pageName, + const QString &settingName, QObject *parent) : EnumDelegate (values, undoStack, parent), mDisplayMode (Mode_TextOnly), mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3), - mTextLeftOffset(8), mSettingKey (settingKey) + mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName) { mTextAlignment.setAlignment (Qt::AlignLeft | Qt::AlignVCenter ); buildPixmaps(); QString value = - CSMSettings::UserSettings::instance().settingValue (settingKey); + CSMSettings::UserSettings::instance().settingValue (mSettingKey); updateDisplayMode(value); } @@ -140,7 +141,7 @@ CSVWorld::CommandDelegate *CSVWorld::DataDisplayDelegateFactory::makeDelegate (Q QObject *parent) const { - return new DataDisplayDelegate (mValues, mIcons, undoStack, "", parent); + return new DataDisplayDelegate (mValues, mIcons, undoStack, "", "", parent); } diff --git a/apps/opencs/view/world/datadisplaydelegate.hpp b/apps/opencs/view/world/datadisplaydelegate.hpp index f11c4a2b9..ef453c58f 100755 --- a/apps/opencs/view/world/datadisplaydelegate.hpp +++ b/apps/opencs/view/world/datadisplaydelegate.hpp @@ -41,7 +41,8 @@ namespace CSVWorld explicit DataDisplayDelegate (const ValueList & values, const IconList & icons, QUndoStack& undoStack, - const QString &settingKey, + const QString &pageName, + const QString &settingName, QObject *parent); ~DataDisplayDelegate(); diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp new file mode 100644 index 000000000..c33fa58ad --- /dev/null +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -0,0 +1,38 @@ +#include + +#include "../../model/world/tablemimedata.hpp" +#include "dragrecordtable.hpp" + +void CSVWorld::DragRecordTable::startDrag (const CSVWorld::DragRecordTable& table) +{ + CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (table.getDraggedRecords(), mDocument); + + if (mime) + { + QDrag* drag = new QDrag (this); + drag->setMimeData (mime); + drag->setPixmap (QString::fromUtf8 (mime->getIcon().c_str())); + drag->exec (Qt::CopyAction); + } +} + +CSVWorld::DragRecordTable::DragRecordTable (CSMDoc::Document& document, QWidget* parent) : +mDocument(document), +QTableView(parent), +mEditLock(false) +{} + +void CSVWorld::DragRecordTable::setEditLock (bool locked) +{ + mEditLock = locked; +} + +void CSVWorld::DragRecordTable::dragEnterEvent(QDragEnterEvent *event) +{ + event->acceptProposedAction(); +} + +void CSVWorld::DragRecordTable::dragMoveEvent(QDragMoveEvent *event) +{ + event->accept(); +} diff --git a/apps/opencs/view/world/dragrecordtable.hpp b/apps/opencs/view/world/dragrecordtable.hpp new file mode 100644 index 000000000..8c5f1b841 --- /dev/null +++ b/apps/opencs/view/world/dragrecordtable.hpp @@ -0,0 +1,45 @@ +#ifndef CSV_WORLD_DRAGRECORDTABLE_H +#define CSV_WORLD_DRAGRECORDTABLE_H + +#include +#include + +class QWidget; +class QAction; + +namespace CSMDoc +{ + class Document; +} + +namespace CSMWorld +{ + class UniversalId; +} + +namespace CSVWorld +{ + class DragRecordTable : public QTableView + { + protected: + CSMDoc::Document& mDocument; + bool mEditLock; + + public: + DragRecordTable(CSMDoc::Document& document, QWidget* parent = NULL); + + virtual std::vector getDraggedRecords() const = 0; + + void setEditLock(bool locked); + + protected: + void startDrag(const DragRecordTable& table); + + void dragEnterEvent(QDragEnterEvent *event); + + void dragMoveEvent(QDragMoveEvent *event); + }; +} + +#endif + diff --git a/apps/opencs/view/world/idtypedelegate.cpp b/apps/opencs/view/world/idtypedelegate.cpp index 485ca57ac..6b4d442f3 100755 --- a/apps/opencs/view/world/idtypedelegate.cpp +++ b/apps/opencs/view/world/idtypedelegate.cpp @@ -5,7 +5,7 @@ CSVWorld::IdTypeDelegate::IdTypeDelegate (const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent) : DataDisplayDelegate (values, icons, undoStack, - "Display Format.Referenceable ID Type Display", + "Display Format", "Referenceable ID Type Display", parent) {} diff --git a/apps/opencs/view/world/recordstatusdelegate.cpp b/apps/opencs/view/world/recordstatusdelegate.cpp index 206adbdd7..4fe7031ce 100644 --- a/apps/opencs/view/world/recordstatusdelegate.cpp +++ b/apps/opencs/view/world/recordstatusdelegate.cpp @@ -11,7 +11,7 @@ CSVWorld::RecordStatusDelegate::RecordStatusDelegate(const ValueList& values, const IconList & icons, QUndoStack &undoStack, QObject *parent) : DataDisplayDelegate (values, icons, undoStack, - "Display Format.Record Status Display", + "Display Format", "Record Status Display", parent) {} diff --git a/apps/opencs/view/world/regionmap.cpp b/apps/opencs/view/world/regionmap.cpp index 738de89ae..849a1988a 100644 --- a/apps/opencs/view/world/regionmap.cpp +++ b/apps/opencs/view/world/regionmap.cpp @@ -17,6 +17,7 @@ #include "../../model/world/idtable.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/columns.hpp" +#include "../../model/world/tablemimedata.hpp" void CSVWorld::RegionMap::contextMenuEvent (QContextMenuEvent *event) { @@ -180,7 +181,7 @@ void CSVWorld::RegionMap::setRegion (const std::string& regionId) CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document, QWidget *parent) -: QTableView (parent), mEditLock (false), mDocument (document) +: DragRecordTable(document, parent) { verticalHeader()->hide(); horizontalHeader()->hide(); @@ -223,11 +224,8 @@ CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId, mViewInTableAction = new QAction (tr ("View Cells in Table"), this); connect (mViewInTableAction, SIGNAL (triggered()), this, SLOT (viewInTable())); addAction (mViewInTableAction); -} -void CSVWorld::RegionMap::setEditLock (bool locked) -{ - mEditLock = locked; + setAcceptDrops(true); } void CSVWorld::RegionMap::selectAll() @@ -343,4 +341,65 @@ void CSVWorld::RegionMap::viewInTable() hint << ")"; emit editRequest (CSMWorld::UniversalId::Type_Cells, hint.str()); +} + +void CSVWorld::RegionMap::mouseMoveEvent (QMouseEvent* event) +{ + startDrag(*this); +} + +std::vector< CSMWorld::UniversalId > CSVWorld::RegionMap::getDraggedRecords() const +{ + QModelIndexList selected(getSelectedCells(true, false)); + std::vector ids; + foreach (QModelIndex it, selected) + { + ids.push_back( + CSMWorld::UniversalId( + CSMWorld::UniversalId::Type_Cell, + model()->data(it, CSMWorld::RegionMap::Role_CellId).toString().toUtf8().constData())); + } + selected = getSelectedCells(false, true); + foreach (QModelIndex it, selected) + { + ids.push_back( + CSMWorld::UniversalId( + CSMWorld::UniversalId::Type_Cell_Missing, + model()->data(it, CSMWorld::RegionMap::Role_CellId).toString().toUtf8().constData())); + } + return ids; +} + +void CSVWorld::RegionMap::dropEvent (QDropEvent* event) +{ + QModelIndex index = indexAt (event->pos()); + + bool exists = QTableView::model()->data(index, Qt::BackgroundRole)!=QBrush (Qt::DiagCrossPattern); + + if (!index.isValid() || !exists) + { + return; + } + + const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); + if (mime->fromDocument(mDocument) && mime->holdsType(CSMWorld::UniversalId::Type_Region)) + { + CSMWorld::UniversalId record (mime->returnMatching (CSMWorld::UniversalId::Type_Region)); + + QAbstractItemModel *regionModel = model(); + + CSMWorld::IdTable *cellsModel = &dynamic_cast (* + mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_Cells)); + + std::string cellId(regionModel->data (index, CSMWorld::RegionMap::Role_CellId). + toString().toUtf8().constData()); + + QModelIndex index2(cellsModel->getModelIndex (cellId, + cellsModel->findColumnIndex (CSMWorld::Columns::ColumnId_Region))); + + mDocument.getUndoStack().push(new CSMWorld::ModifyCommand + (*cellsModel, index2, QString::fromUtf8(record.getId().c_str()))); + + mRegionId = record.getId(); + } } \ No newline at end of file diff --git a/apps/opencs/view/world/regionmap.hpp b/apps/opencs/view/world/regionmap.hpp index c3757fe45..0097a16dc 100644 --- a/apps/opencs/view/world/regionmap.hpp +++ b/apps/opencs/view/world/regionmap.hpp @@ -1,8 +1,14 @@ #ifndef CSV_WORLD_REGIONMAP_H #define CSV_WORLD_REGIONMAP_H +#include +#include + +#include #include +#include "./dragrecordtable.hpp" + class QAction; namespace CSMDoc @@ -17,7 +23,7 @@ namespace CSMWorld namespace CSVWorld { - class RegionMap : public QTableView + class RegionMap : public DragRecordTable { Q_OBJECT @@ -29,8 +35,6 @@ namespace CSVWorld QAction *mUnsetRegionAction; QAction *mViewAction; QAction *mViewInTableAction; - bool mEditLock; - CSMDoc::Document& mDocument; std::string mRegionId; private: @@ -50,12 +54,16 @@ namespace CSVWorld void setRegion (const std::string& regionId); ///< Set region Id of selected cells. + void mouseMoveEvent(QMouseEvent *event); + + void dropEvent(QDropEvent* event); + public: RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document, QWidget *parent = 0); - void setEditLock (bool locked); + virtual std::vector getDraggedRecords() const; signals: diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 0bb11ce8c..36cce9ecd 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "../../model/doc/document.hpp" @@ -18,11 +19,10 @@ #include "tablebottombox.hpp" #include "creator.hpp" -#include "scenetoolbar.hpp" #include "scenetoolmode.hpp" CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) -: SubView (id) +: SubView (id), mLayout(new QHBoxLayout), mDocument(document), mScene(NULL), mToolbar(NULL) { QVBoxLayout *layout = new QVBoxLayout; @@ -32,33 +32,35 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D new TableBottomBox (NullCreatorFactory(), document.getData(), document.getUndoStack(), id, this), 0); - QHBoxLayout *layout2 = new QHBoxLayout; + mLayout->setContentsMargins (QMargins (0, 0, 0, 0)); - layout2->setContentsMargins (QMargins (0, 0, 0, 0)); - - SceneToolbar *toolbar = new SceneToolbar (48+6, this); + CSVRender::WorldspaceWidget* wordspaceWidget = NULL; + widgetType whatWidget; if (id.getId()=="sys::default") { - CSVRender::PagedWorldspaceWidget *widget = new CSVRender::PagedWorldspaceWidget (this); - mScene = widget; - connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)), - this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&))); + whatWidget = widget_Paged; + + CSVRender::PagedWorldspaceWidget *newWidget = new CSVRender::PagedWorldspaceWidget (this, document); + + wordspaceWidget = newWidget; + + makeConnections(newWidget); } else - mScene = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this); + { + whatWidget = widget_Unpaged; - SceneToolMode *navigationTool = mScene->makeNavigationSelector (toolbar); - toolbar->addTool (navigationTool); + CSVRender::UnpagedWorldspaceWidget *newWidget = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this); - SceneToolMode *lightingTool = mScene->makeLightingSelector (toolbar); - toolbar->addTool (lightingTool); + wordspaceWidget = newWidget; - layout2->addWidget (toolbar, 0); + makeConnections(newWidget); + } - layout2->addWidget (mScene, 1); + replaceToolbarAndWorldspace(wordspaceWidget, makeToolbar(wordspaceWidget, whatWidget)); - layout->insertLayout (0, layout2, 1); + layout->insertLayout (0, mLayout, 1); CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this); @@ -69,10 +71,53 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D widget->setLayout (layout); setWidget (widget); +} - mScene->selectDefaultNavigationMode(); +void CSVWorld::SceneSubView::makeConnections (CSVRender::UnpagedWorldspaceWidget* widget) +{ + connect (widget, SIGNAL (closeRequest()), this, SLOT (closeRequest())); + + connect(widget, SIGNAL(dataDropped(const std::vector&)), + this, SLOT(handleDrop(const std::vector&))); + + connect(widget, SIGNAL(cellChanged(const CSMWorld::UniversalId&)), + this, SLOT(cellSelectionChanged(const CSMWorld::UniversalId&))); +} + +void CSVWorld::SceneSubView::makeConnections (CSVRender::PagedWorldspaceWidget* widget) +{ + connect (widget, SIGNAL (closeRequest()), this, SLOT (closeRequest())); + + connect(widget, SIGNAL(dataDropped(const std::vector&)), + this, SLOT(handleDrop(const std::vector&))); + + connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)), + this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&))); +} + +CSVWorld::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::WorldspaceWidget* widget, widgetType type) +{ + CSVWorld::SceneToolbar* toolbar = new SceneToolbar (48+6, this); + + SceneToolMode *navigationTool = widget->makeNavigationSelector (toolbar); + toolbar->addTool (navigationTool); + + SceneToolMode *lightingTool = widget->makeLightingSelector (toolbar); + toolbar->addTool (lightingTool); + +/* Add buttons specific to the type. For now no need for it. + * + switch (type) + { + case widget_Paged: + break; + + case widget_Unpaged: + break; - connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest())); + } +*/ + return toolbar; } void CSVWorld::SceneSubView::setEditLock (bool locked) @@ -102,8 +147,19 @@ void CSVWorld::SceneSubView::closeRequest() deleteLater(); } +void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::UniversalId& id) +{ + setUniversalId(id); + std::ostringstream stream; + stream << "Scene: " << getUniversalId().getId(); + + setWindowTitle (QString::fromUtf8 (stream.str().c_str())); +} + + void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection& selection) { + setUniversalId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Scene, "sys::default")); int size = selection.getSize(); std::ostringstream stream; @@ -126,4 +182,62 @@ void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection } setWindowTitle (QString::fromUtf8 (stream.str().c_str())); +} + +void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalId >& data) +{ + CSVRender::PagedWorldspaceWidget* pagedNewWidget = NULL; + CSVRender::UnpagedWorldspaceWidget* unPagedNewWidget = NULL; + SceneToolbar* toolbar = NULL; + + switch (mScene->getDropRequirements(CSVRender::WorldspaceWidget::getDropType(data))) + { + case CSVRender::WorldspaceWidget::canHandle: + mScene->handleDrop(data); + break; + + case CSVRender::WorldspaceWidget::needPaged: + pagedNewWidget = new CSVRender::PagedWorldspaceWidget(this, mDocument); + toolbar = makeToolbar(pagedNewWidget, widget_Paged); + makeConnections(pagedNewWidget); + replaceToolbarAndWorldspace(pagedNewWidget, toolbar); + mScene->handleDrop(data); + break; + + case CSVRender::WorldspaceWidget::needUnpaged: + unPagedNewWidget = new CSVRender::UnpagedWorldspaceWidget(data.begin()->getId(), mDocument, this); + toolbar = makeToolbar(unPagedNewWidget, widget_Unpaged); + makeConnections(unPagedNewWidget); + replaceToolbarAndWorldspace(unPagedNewWidget, toolbar); + cellSelectionChanged(*(data.begin())); + break; + + case CSVRender::WorldspaceWidget::ignored: + return; + } +} + +void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceWidget* widget, CSVWorld::SceneToolbar* toolbar) +{ + assert(mLayout); + + if (mScene) + { + mLayout->removeWidget(mScene); + mScene->deleteLater(); + } + + if (mToolbar) + { + mLayout->removeWidget(mToolbar); + mToolbar->deleteLater(); + } + + mScene = widget; + mToolbar = toolbar; + + mLayout->addWidget (mToolbar, 0); + mLayout->addWidget (mScene, 1); + + mScene->selectDefaultNavigationMode(); } \ No newline at end of file diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index 0b15ea541..b9ecbe931 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -1,7 +1,10 @@ #ifndef CSV_WORLD_SCENESUBVIEW_H #define CSV_WORLD_SCENESUBVIEW_H +#include + #include "../doc/subview.hpp" +#include "scenetoolbar.hpp" class QModelIndex; @@ -18,6 +21,8 @@ namespace CSMDoc namespace CSVRender { class WorldspaceWidget; + class PagedWorldspaceWidget; + class UnpagedWorldspaceWidget; } namespace CSVWorld @@ -32,6 +37,9 @@ namespace CSVWorld TableBottomBox *mBottom; CSVRender::WorldspaceWidget *mScene; + QHBoxLayout* mLayout; + CSMDoc::Document& mDocument; + SceneToolbar* mToolbar; public: @@ -45,11 +53,30 @@ namespace CSVWorld virtual void useHint (const std::string& hint); + private: + + void makeConnections(CSVRender::PagedWorldspaceWidget* widget); + + void makeConnections(CSVRender::UnpagedWorldspaceWidget* widget); + + void replaceToolbarAndWorldspace(CSVRender::WorldspaceWidget* widget, SceneToolbar* toolbar); + + enum widgetType + { + widget_Paged, + widget_Unpaged + }; + SceneToolbar* makeToolbar(CSVRender::WorldspaceWidget* widget, widgetType type); + private slots: void closeRequest(); void cellSelectionChanged (const CSMWorld::CellSelection& selection); + + void cellSelectionChanged (const CSMWorld::UniversalId& id); + + void handleDrop(const std::vector& data); }; } diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index a5a98aac7..3d4b02c9c 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -188,8 +188,8 @@ std::vector CSVWorld::Table::listDeletableSelectedIds() const CSVWorld::Table::Table (const CSMWorld::UniversalId& id, bool createAndDelete, bool sorting, CSMDoc::Document& document) -: mCreateAction (0), mCloneAction(0), mEditLock (false), mRecordStatusDisplay (0), - mDocument (document) +: mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0), + DragRecordTable(document) { mModel = &dynamic_cast (*mDocument.getData().getTableModel (id)); @@ -282,7 +282,7 @@ void CSVWorld::Table::setEditLock (bool locked) for (std::vector::iterator iter (mDelegates.begin()); iter!=mDelegates.end(); ++iter) (*iter)->setEditLock (locked); - mEditLock = locked; + DragRecordTable::setEditLock(locked); } CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const @@ -518,42 +518,8 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event) { if (event->buttons() & Qt::LeftButton) { - QModelIndexList selectedRows = selectionModel()->selectedRows(); - - if (selectedRows.size() == 0) - { - return; - } - - QDrag* drag = new QDrag (this); - CSMWorld::TableMimeData* mime = NULL; - - if (selectedRows.size() == 1) - { - mime = new CSMWorld::TableMimeData (getUniversalId (selectedRows.begin()->row()), mDocument); - } - else - { - std::vector idToDrag; - - foreach (QModelIndex it, selectedRows) //I had a dream. Dream where you could use C++11 in OpenMW. - { - idToDrag.push_back (getUniversalId (it.row())); - } - - mime = new CSMWorld::TableMimeData (idToDrag, mDocument); - } - - drag->setMimeData (mime); - drag->setPixmap (QString::fromUtf8 (mime->getIcon().c_str())); - drag->exec(Qt::CopyAction); + startDrag(*this); } - -} - -void CSVWorld::Table::dragEnterEvent(QDragEnterEvent *event) -{ - event->acceptProposedAction(); } void CSVWorld::Table::dropEvent(QDropEvent *event) @@ -583,11 +549,6 @@ void CSVWorld::Table::dropEvent(QDropEvent *event) } //TODO handle drops from different document } -void CSVWorld::Table::dragMoveEvent(QDragMoveEvent *event) -{ - event->accept(); -} - std::vector CSVWorld::Table::getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const { const int count = mModel->columnCount(); @@ -605,3 +566,18 @@ std::vector CSVWorld::Table::getColumnsWithDisplay(CSMWorld::Column } return titles; } + +std::vector< CSMWorld::UniversalId > CSVWorld::Table::getDraggedRecords() const +{ + + QModelIndexList selectedRows = selectionModel()->selectedRows(); + std::vector idToDrag; + + foreach (QModelIndex it, selectedRows) //I had a dream. Dream where you could use C++11 in OpenMW. + { + idToDrag.push_back (getUniversalId (it.row())); + } + + return idToDrag; +} + diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index c2811b893..3b1d40e78 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -4,11 +4,11 @@ #include #include -#include #include #include "../../model/filter/node.hpp" #include "../../model/world/columnbase.hpp" +#include "dragrecordtable.hpp" class QUndoStack; class QAction; @@ -31,7 +31,7 @@ namespace CSVWorld class CommandDelegate; ///< Table widget - class Table : public QTableView + class Table : public DragRecordTable { Q_OBJECT @@ -47,9 +47,7 @@ namespace CSVWorld QAction *mPreviewAction; CSMWorld::IdTableProxyModel *mProxyModel; CSMWorld::IdTable *mModel; - bool mEditLock; int mRecordStatusDisplay; - CSMDoc::Document& mDocument; private: @@ -61,10 +59,6 @@ namespace CSVWorld void mouseMoveEvent(QMouseEvent *event); - void dragEnterEvent(QDragEnterEvent *event); - - void dragMoveEvent(QDragMoveEvent *event); - void dropEvent(QDropEvent *event); public: @@ -74,12 +68,14 @@ namespace CSVWorld ///< \param createAndDelete Allow creation and deletion of records. /// \param sorting Allow changing order of rows in the view via column headers. - void setEditLock (bool locked); + virtual void setEditLock (bool locked); CSMWorld::UniversalId getUniversalId (int row) const; std::vector getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const; + virtual std::vector getDraggedRecords() const; + signals: void editRequest (const CSMWorld::UniversalId& id, const std::string& hint); @@ -92,6 +88,7 @@ namespace CSVWorld /// \param modified Number of added and modified records void createRequest(); + void cloneRequest(const CSMWorld::UniversalId&); private slots: diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e83ae2d8d..7a5283125 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -48,7 +48,7 @@ add_openmw_dir (mwscript ) add_openmw_dir (mwsound - soundmanagerimp openal_output audiere_decoder mpgsnd_decoder ffmpeg_decoder + soundmanagerimp openal_output ffmpeg_decoder sound ) add_openmw_dir (mwworld @@ -67,7 +67,7 @@ add_openmw_dir (mwclass add_openmw_dir (mwmechanics mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects - drawstate spells activespells npcstats aipackage aisequence aipersue alchemy aiwander aitravel aifollow + drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting disease pickpocket levelledlist combat steering obstacle ) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index d5f9e30cd..f31241bdb 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -96,6 +96,9 @@ namespace MWBase /// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check! virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) = 0; + /// Makes \a ptr fight \a target. Also shouts a combat taunt. + virtual void startCombat (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target) = 0; + enum OffenseType { OT_Theft, // Taking items owned by an NPC or a faction you are not a member of diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 94238e6d5..4c6ab1c75 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -337,6 +337,12 @@ namespace MWClass { // NOTE: 'object' and/or 'attacker' may be empty. + getCreatureStats(ptr).setAttacked(true); + + // Self defense + if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80) + MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, attacker); + if(!successful) { // TODO: Handle HitAttemptOnMe script function diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index e43bfe40d..6a96c955f 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -621,9 +621,11 @@ namespace MWClass // NOTE: 'object' and/or 'attacker' may be empty. // Attacking peaceful NPCs is a crime - if (!attacker.isEmpty() && ptr.getClass().isNpc() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30) + if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30) MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault); + getCreatureStats(ptr).setAttacked(true); + if(!successful) { // TODO: Handle HitAttemptOnMe script function @@ -659,7 +661,6 @@ namespace MWClass { MWBase::Environment::get().getDialogueManager()->say(ptr, "hit"); } - getCreatureStats(ptr).setAttacked(true); // Check for knockdown float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * fKnockDownMult->getFloat(); diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 01eb770f7..d51d4298f 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -215,16 +215,22 @@ namespace MWGui { std::vector matches; listNames(); - mCommandLine->setCaption(complete( mCommandLine->getOnlyText(), matches )); -#if 0 - int i = 0; - for(std::vector::iterator it=matches.begin(); it < matches.end(); ++it,++i ) + std::string oldCaption = mCommandLine->getCaption(); + std::string newCaption = complete( mCommandLine->getOnlyText(), matches ); + mCommandLine->setCaption(newCaption); + + // List candidates if repeatedly pressing tab + if (oldCaption == newCaption && matches.size()) { - printOK( *it ); - if( i == 50 ) - break; + int i = 0; + printOK(""); + for(std::vector::iterator it=matches.begin(); it < matches.end(); ++it,++i ) + { + printOK( *it ); + if( i == 50 ) + break; + } } -#endif } if(mCommandHistory.empty()) return; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index d2a31e8d1..6a15c8e33 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1447,7 +1447,7 @@ namespace MWGui { return !MyGUI::InputManager::getInstance().isModalAny() // TODO: remove this, once we have properly serialized the state of open windows - && (!isGuiMode() || (mGuiModes.size() == 1 && getMode() == GM_MainMenu)); + && (!isGuiMode() || (mGuiModes.size() == 1 && (getMode() == GM_MainMenu || getMode() == GM_Rest || getMode() == GM_RestBed))); } void WindowManager::playVideo(const std::string &name, bool allowSkipping) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index b0b482cfd..6375bdd1b 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -29,7 +29,7 @@ #include "aicombat.hpp" #include "aifollow.hpp" -#include "aipersue.hpp" +#include "aipursue.hpp" namespace { @@ -206,8 +206,7 @@ namespace MWMechanics if (LOS) { - creatureStats.getAiSequence().stack(AiCombat(MWBase::Environment::get().getWorld()->getPlayerPtr()), ptr); - creatureStats.setHostile(true); + MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player); } } } @@ -719,34 +718,33 @@ namespace MWMechanics CreatureStats& creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr); NpcStats& npcStats = MWWorld::Class::get(ptr).getNpcStats(ptr); - // If I'm a guard and I'm not hostile - if (ptr.getClass().isClass(ptr, "Guard") && !creatureStats.isHostile()) + if (ptr.getClass().isClass(ptr, "Guard") && creatureStats.getAiSequence().getTypeId() != AiPackage::TypeIdPursue && !creatureStats.isHostile()) { /// \todo Move me! I shouldn't be here... const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); - float cutoff = float(esmStore.get().find("iCrimeThreshold")->getInt()) * - float(esmStore.get().find("iCrimeThresholdMultiplier")->getInt()) * - esmStore.get().find("fCrimeGoldDiscountMult")->getFloat(); - // Attack on sight if bounty is greater than the cutoff + float cutoff = float(esmStore.get().find("iCrimeThreshold")->getInt()); + // Force dialogue on sight if bounty is greater than the cutoff + // In vanilla morrowind, the greeting dialogue is scripted to either arrest the player (< 5000 bounty) or attack (>= 5000 bounty) if ( player.getClass().getNpcStats(player).getBounty() >= cutoff + // TODO: do not run these two every frame. keep an Aware state for each actor and update it every 0.2 s or so? && MWBase::Environment::get().getWorld()->getLOS(ptr, player) && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr)) { - creatureStats.getAiSequence().stack(AiCombat(player), ptr); - creatureStats.setHostile(true); - npcStats.setCrimeId( MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() ); + creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); + creatureStats.setAlarmed(true); + npcStats.setCrimeId(MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId()); } } // if I was a witness to a crime if (npcStats.getCrimeId() != -1) { - // if you've payed for your crimes and I havent noticed + // if you've paid for your crimes and I havent noticed if( npcStats.getCrimeId() <= MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() ) { // Calm witness down if (ptr.getClass().isClass(ptr, "Guard")) - creatureStats.getAiSequence().stopPersue(); + creatureStats.getAiSequence().stopPursuit(); creatureStats.getAiSequence().stopCombat(); // Reset factors to attack @@ -761,19 +759,13 @@ namespace MWMechanics else if (!creatureStats.isHostile()) { if (ptr.getClass().isClass(ptr, "Guard")) - creatureStats.getAiSequence().stack(AiPersue(player.getClass().getId(player)), ptr); + creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); else - creatureStats.getAiSequence().stack(AiCombat(player), ptr); - creatureStats.setHostile(true); + { + MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player); + } } } - - // if I didn't report a crime was I attacked? - else if (creatureStats.getAttacked() && !creatureStats.isHostile()) - { - creatureStats.getAiSequence().stack(AiCombat(player), ptr); - creatureStats.setHostile(true); - } } } @@ -852,12 +844,12 @@ namespace MWMechanics } // AI and magic effects update - for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) { if (!iter->first.getClass().getCreatureStats(iter->first).isDead()) { updateActor(iter->first, duration); - if(iter->first.getTypeName() == typeid(ESM::NPC).name()) + if (iter->first.getTypeName() == typeid(ESM::NPC).name()) updateNpc(iter->first, duration, paused); } } @@ -867,11 +859,11 @@ namespace MWMechanics // Reaching the text keys may trigger Hit / Spellcast (and as such, particles), // so updating VFX immediately after that would just remove the particle effects instantly. // There needs to be a magic effect update in between. - for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) iter->second->updateContinuousVfx(); // Animation/movement update - for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) + for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) { if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get( ESM::MagicEffect::Paralyze).mMagnitude > 0) @@ -880,7 +872,7 @@ namespace MWMechanics } // Kill dead actors, update some variables - for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) + for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) { const MWWorld::Class &cls = MWWorld::Class::get(iter->first); CreatureStats &stats = cls.getCreatureStats(iter->first); @@ -888,7 +880,7 @@ namespace MWMechanics //KnockedOutOneFrameLogic //Used for "OnKnockedOut" command //Put here to ensure that it's run for PRECISELY one frame. - if(stats.getKnockedDown() && !stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Start it for one frame if nessesary + if (stats.getKnockedDown() && !stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Start it for one frame if nessesary stats.setKnockedDownOneFrame(true); } else if (stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Turn off KnockedOutOneframe @@ -906,7 +898,7 @@ namespace MWMechanics } // If it's the player and God Mode is turned on, keep it alive - if(iter->first.getRefData().getHandle()=="player" && + if (iter->first.getRefData().getHandle()=="player" && MWBase::Environment::get().getWorld()->getGodModeState()) { MWMechanics::DynamicStat stat (stats.getHealth()); @@ -922,7 +914,7 @@ namespace MWMechanics // Make sure spell effects with CasterLinked flag are removed // TODO: would be nice not to do this all the time... - for(PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2) + for (PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2) { MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells(); spells.purge(iter->first.getRefData().getHandle()); @@ -947,10 +939,40 @@ namespace MWMechanics stats.setMagicEffects(MWMechanics::MagicEffects()); calculateCreatureStatModifiers(iter->first, 0); - if(cls.isEssential(iter->first)) + if (cls.isEssential(iter->first)) MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}"); } } + + // if player is in sneak state see if anyone detects him + const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + if (player.getClass().getCreatureStats(player).getMovementFlag(MWMechanics::CreatureStats::Flag_Sneak)) + { + const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); + const int radius = esmStore.get().find("fSneakUseDist")->getInt(); + bool detected = false; + + for (PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) + { + if (iter->first == player) // not the player + continue; + + // is the player in range and can they be detected + if ( (Ogre::Vector3(iter->first.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(player.getRefData().getPosition().pos)) <= radius*radius) + && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, iter->first) + && MWBase::Environment::get().getWorld()->getLOS(player, iter->first)) + { + detected = true; + MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); + break; + } + } + + if (!detected) + MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); + } + else + MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); } } void Actors::restoreDynamicStats(bool sleep) @@ -1053,6 +1075,8 @@ namespace MWMechanics if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat) { MWMechanics::AiCombat* package = static_cast(stats.getAiSequence().getActivePackage()); + // TODO: This is wrong! It's comparing Ref IDs with Ogre handles. The only case where this (coincidentally) works is the player. + // possibly applies to other code using getTargetId. if(package->getTargetId() == actor.getCellRef().mRefID) list.push_front(*iter); } diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 8e015da15..bd172c373 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -20,7 +20,7 @@ namespace MWMechanics TypeIdFollow = 3, TypeIdActivate = 4, TypeIdCombat = 5, - TypeIdPersue = 6 + TypeIdPursue = 6 }; virtual ~AiPackage(); diff --git a/apps/openmw/mwmechanics/aipersue.cpp b/apps/openmw/mwmechanics/aipursue.cpp similarity index 81% rename from apps/openmw/mwmechanics/aipersue.cpp rename to apps/openmw/mwmechanics/aipursue.cpp index 36e18946c..0c10bd81d 100644 --- a/apps/openmw/mwmechanics/aipersue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -1,4 +1,4 @@ -#include "aipersue.hpp" +#include "aipursue.hpp" #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" @@ -11,15 +11,15 @@ #include "movement.hpp" #include "creaturestats.hpp" -MWMechanics::AiPersue::AiPersue(const std::string &objectId) +MWMechanics::AiPursue::AiPursue(const std::string &objectId) : mObjectId(objectId) { } -MWMechanics::AiPersue *MWMechanics::AiPersue::clone() const +MWMechanics::AiPursue *MWMechanics::AiPursue::clone() const { - return new AiPersue(*this); + return new AiPursue(*this); } -bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor, float duration) +bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) { MWBase::World *world = MWBase::Environment::get().getWorld(); ESM::Position pos = actor.getRefData().getPosition(); @@ -52,11 +52,13 @@ bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor, float duration) } } + // Big TODO: Sync this with current AiFollow. Move common code to a shared base class or helpers (applies to all AI packages, way too much duplicated code) + MWWorld::Ptr target = world->getPtr(mObjectId,false); ESM::Position targetPos = target.getRefData().getPosition(); bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; - if(!mPathFinder.isPathConstructed() || cellChange) + if(!mPathFinder.isPathConstructed() || cellChange || mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) { mCellX = cell->mData.mX; mCellY = cell->mData.mY; @@ -76,15 +78,7 @@ bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor, float duration) if((pos.pos[0]-targetPos.pos[0])*(pos.pos[0]-targetPos.pos[0])+ (pos.pos[1]-targetPos.pos[1])*(pos.pos[1]-targetPos.pos[1])+ - (pos.pos[2]-targetPos.pos[2])*(pos.pos[2]-targetPos.pos[2]) < 200*200) - { - movement.mPosition[1] = 0; - MWWorld::Ptr target = world->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); - return true; - } - - if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) + (pos.pos[2]-targetPos.pos[2])*(pos.pos[2]-targetPos.pos[2]) < 100*100) { movement.mPosition[1] = 0; MWWorld::Ptr target = world->getPtr(mObjectId,false); @@ -100,7 +94,7 @@ bool MWMechanics::AiPersue::execute (const MWWorld::Ptr& actor, float duration) return false; } -int MWMechanics::AiPersue::getTypeId() const +int MWMechanics::AiPursue::getTypeId() const { - return TypeIdPersue; + return TypeIdPursue; } diff --git a/apps/openmw/mwmechanics/aipersue.hpp b/apps/openmw/mwmechanics/aipursue.hpp similarity index 68% rename from apps/openmw/mwmechanics/aipersue.hpp rename to apps/openmw/mwmechanics/aipursue.hpp index 3fd708ab3..86750acca 100644 --- a/apps/openmw/mwmechanics/aipersue.hpp +++ b/apps/openmw/mwmechanics/aipursue.hpp @@ -1,5 +1,5 @@ -#ifndef GAME_MWMECHANICS_AIPERSUE_H -#define GAME_MWMECHANICS_AIPERSUE_H +#ifndef GAME_MWMECHANICS_AIPURSUE_H +#define GAME_MWMECHANICS_AIPURSUE_H #include "aipackage.hpp" #include @@ -9,11 +9,11 @@ namespace MWMechanics { - class AiPersue : public AiPackage + class AiPursue : public AiPackage { public: - AiPersue(const std::string &objectId); - virtual AiPersue *clone() const; + AiPursue(const std::string &objectId); + virtual AiPursue *clone() const; virtual bool execute (const MWWorld::Ptr& actor,float duration); ///< \return Package completed? virtual int getTypeId() const; diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 6460b0305..0b1da180d 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -73,9 +73,9 @@ void MWMechanics::AiSequence::stopCombat() } } -void MWMechanics::AiSequence::stopPersue() +void MWMechanics::AiSequence::stopPursuit() { - while (getTypeId() == AiPackage::TypeIdPersue) + while (getTypeId() == AiPackage::TypeIdPursue) { delete *mPackages.begin(); mPackages.erase (mPackages.begin()); @@ -93,11 +93,16 @@ void MWMechanics::AiSequence::execute (const MWWorld::Ptr& actor,float duration) { if (!mPackages.empty()) { - mLastAiPackage = mPackages.front()->getTypeId(); - if (mPackages.front()->execute (actor,duration)) + MWMechanics::AiPackage* package = mPackages.front(); + mLastAiPackage = package->getTypeId(); + if (package->execute (actor,duration)) { - delete *mPackages.begin(); - mPackages.erase (mPackages.begin()); + // To account for the rare case where AiPackage::execute() queued another AI package + // (e.g. AiPursue executing a dialogue script that uses startCombat) + std::list::iterator toRemove = + std::find(mPackages.begin(), mPackages.end(), package); + mPackages.erase(toRemove); + delete package; mDone = true; } else @@ -118,7 +123,7 @@ void MWMechanics::AiSequence::clear() void MWMechanics::AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor) { - if (package.getTypeId() == AiPackage::TypeIdCombat || package.getTypeId() == AiPackage::TypeIdPersue) + if (package.getTypeId() == AiPackage::TypeIdCombat || package.getTypeId() == AiPackage::TypeIdPursue) { // Notify AiWander of our current position so we can return to it after combat finished for (std::list::const_iterator iter (mPackages.begin()); iter!=mPackages.end(); ++iter) diff --git a/apps/openmw/mwmechanics/aisequence.hpp b/apps/openmw/mwmechanics/aisequence.hpp index cb1b0de02..37e0c7f17 100644 --- a/apps/openmw/mwmechanics/aisequence.hpp +++ b/apps/openmw/mwmechanics/aisequence.hpp @@ -50,8 +50,8 @@ namespace MWMechanics void stopCombat(); ///< Removes all combat packages until first non-combat or stack empty. - void stopPersue(); - ///< Removes all persue packages until first non-persue or stack empty. + void stopPursuit(); + ///< Removes all pursue packages until first non-pursue or stack empty. bool isPackageDone() const; ///< Has a package been completed during the last update? @@ -64,6 +64,7 @@ namespace MWMechanics void stack (const AiPackage& package, const MWWorld::Ptr& actor); ///< Add \a package to the front of the sequence (suspends current package) + /// @param actor The actor that owns this AiSequence void queue (const AiPackage& package); ///< Add \a package to the end of the sequence (executed after all other packages have been diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index fc7f178e4..5381af8da 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -13,6 +13,8 @@ #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" +#include "../mwmechanics/aicombat.hpp" + #include #include "spellcasting.hpp" @@ -852,39 +854,51 @@ namespace MWMechanics // Innocent until proven guilty bool reported = false; - // Find all the NPCs within the alarm radius + // Find all the actors within the alarm radius std::vector neighbors; mActors.getObjectsInRange(Ogre::Vector3(ptr.getRefData().getPosition().pos), esmStore.get().find("fAlarmRadius")->getInt(), neighbors); - // Find an actor who witnessed the crime + int id = MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId(); + + // Find actors who witnessed the crime for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { - if ( *it == ptr - || !it->getClass().isNpc()) continue; // not the player and is an NPC + if (*it == ptr) continue; // not the player // Was the crime seen? - if ( ( MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) || - type == OT_Assault ) + if (MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) { + // TODO: Add more messages + if (type == OT_Theft) + MWBase::Environment::get().getDialogueManager()->say(*it, "thief"); + + if (*it == victim) + { + // Self-defense + // The victim is aware of the criminal/assailant. If being assaulted, fight back now + // (regardless of whether the assault is reported or not) + // This applies to both NPCs and creatures + + // ... except if this is a guard: then the player is given a chance to pay a fine / go to jail instead + if (type == OT_Assault && !ptr.getClass().isClass(ptr, "guard")) + MWBase::Environment::get().getMechanicsManager()->startCombat(victim, ptr); + } + + // Crime reporting only applies to NPCs + if (!it->getClass().isNpc()) + continue; // Will the witness report the crime? if (it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm) { reported = true; - int id = MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId(); // Tell everyone, including yourself for (std::vector::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1) { - if ( *it == ptr - || !it->getClass().isNpc()) continue; // not the player and is an NPC - - // TODO: Add more messages - if (type == OT_Theft) - MWBase::Environment::get().getDialogueManager()->say(*it1, "thief"); - else if (type == OT_Assault) - MWBase::Environment::get().getDialogueManager()->say(*it1, "attack"); + if ( *it1 == ptr + || !it1->getClass().isNpc()) continue; // not the player and is an NPC // Will other witnesses paticipate in crime if ( it1->getClass().getCreatureStats(*it1).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm @@ -896,7 +910,6 @@ namespace MWMechanics // Mark as Alarmed for dialogue it1->getClass().getCreatureStats(*it1).setAlarmed(true); } - break; // Someone saw the crime and everyone has been told } } } @@ -1007,6 +1020,14 @@ namespace MWMechanics return (roll >= target); } + void MechanicsManager::startCombat(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target) + { + MWBase::Environment::get().getDialogueManager()->say(ptr, "attack"); + ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(MWMechanics::AiCombat(target), ptr); + if (target == MWBase::Environment::get().getWorld()->getPlayerPtr()) + ptr.getClass().getCreatureStats(ptr).setHostile(true); + } + void MechanicsManager::getObjectsInRange(const Ogre::Vector3 &position, float radius, std::vector &objects) { mActors.getObjectsInRange(position, radius, objects); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 1c9bab25e..dcd12ee14 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -105,6 +105,9 @@ namespace MWMechanics /// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check! virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer); + /// Makes \a ptr fight \a target. Also shouts a combat taunt. + virtual void startCombat (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target); + /** * @brief Commit a crime. If any actors witness the crime and report it, * reportCrime will be called automatically. diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 97283d065..19d26a176 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -563,7 +563,8 @@ void RenderingManager::configureAmbient(MWWorld::CellStore &mCell) Ogre::ColourValue colour; colour.setAsABGR (mCell.getCell()->mAmbi.mSunlight); mSun->setDiffuseColour (colour); - mSun->setDirection(0,-1,0); + mSun->setDirection(1,-1,-1); + sunEnable(false); } } // Switch through lighting modes. diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 43da111bf..e53b53e58 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -16,7 +16,6 @@ #include "../mwmechanics/aifollow.hpp" #include "../mwmechanics/aitravel.hpp" #include "../mwmechanics/aiwander.hpp" -#include "../mwmechanics/aicombat.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -435,12 +434,8 @@ namespace MWScript std::string targetID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - MWMechanics::CreatureStats& creatureStats = actor.getClass().getCreatureStats(actor); - - - creatureStats.setHostile(true); - creatureStats.getAiSequence().stack( - MWMechanics::AiCombat(MWBase::Environment::get().getWorld()->getPtr(targetID, true) ), actor); + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(targetID, true); + MWBase::Environment::get().getMechanicsManager()->startCombat(actor, target); } }; diff --git a/apps/openmw/mwsound/audiere_decoder.cpp b/apps/openmw/mwsound/audiere_decoder.cpp deleted file mode 100644 index 3f3e3a62d..000000000 --- a/apps/openmw/mwsound/audiere_decoder.cpp +++ /dev/null @@ -1,137 +0,0 @@ -#ifdef OPENMW_USE_AUDIERE - -#include -#include - -#include "audiere_decoder.hpp" - - -static void fail(const std::string &msg) -{ throw std::runtime_error("Audiere exception: "+msg); } - -namespace MWSound -{ - -class OgreFile : public audiere::File -{ - Ogre::DataStreamPtr mStream; - - ADR_METHOD(int) read(void* buffer, int size) - { - return mStream->read(buffer, size); - } - - ADR_METHOD(bool) seek(int position, SeekMode mode) - { - if(mode == CURRENT) - mStream->seek(mStream->tell()+position); - else if(mode == BEGIN) - mStream->seek(position); - else if(mode == END) - mStream->seek(mStream->size()+position); - else - return false; - - return true; - } - - ADR_METHOD(int) tell() - { - return mStream->tell(); - } - - size_t refs; - ADR_METHOD(void) ref() { ++refs; } - ADR_METHOD(void) unref() - { - if(--refs == 0) - delete this; - } - -public: - OgreFile(const Ogre::DataStreamPtr &stream) - : mStream(stream), refs(1) - { } - virtual ~OgreFile() { } - - Ogre::String getName() - { return mStream->getName(); } -}; - - -void Audiere_Decoder::open(const std::string &fname) -{ - close(); - - mSoundFile = audiere::FilePtr(new OgreFile(mResourceMgr.openResource(fname))); - mSoundSource = audiere::OpenSampleSource(mSoundFile); - mSoundFileName = fname; - - int channels, srate; - audiere::SampleFormat format; - - mSoundSource->getFormat(channels, srate, format); - if(format == audiere::SF_S16) - mSampleType = SampleType_Int16; - else if(format == audiere::SF_U8) - mSampleType = SampleType_UInt8; - else - fail("Unsupported sample type"); - - if(channels == 1) - mChannelConfig = ChannelConfig_Mono; - else if(channels == 2) - mChannelConfig = ChannelConfig_Stereo; - else - fail("Unsupported channel count"); - - mSampleRate = srate; -} - -void Audiere_Decoder::close() -{ - mSoundFile = NULL; - mSoundSource = NULL; -} - -std::string Audiere_Decoder::getName() -{ - return mSoundFileName; -} - -void Audiere_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) -{ - *samplerate = mSampleRate; - *chans = mChannelConfig; - *type = mSampleType; -} - -size_t Audiere_Decoder::read(char *buffer, size_t bytes) -{ - int size = bytesToFrames(bytes, mChannelConfig, mSampleType); - size = mSoundSource->read(size, buffer); - return framesToBytes(size, mChannelConfig, mSampleType); -} - -void Audiere_Decoder::rewind() -{ - mSoundSource->reset(); -} - -size_t Audiere_Decoder::getSampleOffset() -{ - return 0; -} - -Audiere_Decoder::Audiere_Decoder() -{ -} - -Audiere_Decoder::~Audiere_Decoder() -{ - close(); -} - -} - -#endif diff --git a/apps/openmw/mwsound/audiere_decoder.hpp b/apps/openmw/mwsound/audiere_decoder.hpp deleted file mode 100644 index f432c32ec..000000000 --- a/apps/openmw/mwsound/audiere_decoder.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef GAME_SOUND_AUDIERE_DECODER_H -#define GAME_SOUND_AUDIERE_DECODER_H - -#include - -#include "audiere.h" - -#include "sound_decoder.hpp" - - -namespace MWSound -{ - class Audiere_Decoder : public Sound_Decoder - { - std::string mSoundFileName; - audiere::FilePtr mSoundFile; - audiere::SampleSourcePtr mSoundSource; - int mSampleRate; - SampleType mSampleType; - ChannelConfig mChannelConfig; - - virtual void open(const std::string &fname); - virtual void close(); - - virtual std::string getName(); - virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type); - - virtual size_t read(char *buffer, size_t bytes); - virtual void rewind(); - virtual size_t getSampleOffset(); - - Audiere_Decoder& operator=(const Audiere_Decoder &rhs); - Audiere_Decoder(const Audiere_Decoder &rhs); - - Audiere_Decoder(); - public: - virtual ~Audiere_Decoder(); - - friend class SoundManager; - }; -#ifndef DEFAULT_DECODER -#define DEFAULT_DECODER (::MWSound::Audiere_Decoder) -#endif -}; - -#endif diff --git a/apps/openmw/mwsound/mpgsnd_decoder.cpp b/apps/openmw/mwsound/mpgsnd_decoder.cpp deleted file mode 100644 index fb187f844..000000000 --- a/apps/openmw/mwsound/mpgsnd_decoder.cpp +++ /dev/null @@ -1,247 +0,0 @@ -#ifdef OPENMW_USE_MPG123 - -#include -#include - -#include "mpgsnd_decoder.hpp" - - -static void fail(const std::string &msg) -{ throw std::runtime_error("MpgSnd exception: "+msg); } - -namespace MWSound -{ - -// -// libSndFile io callbacks -// -sf_count_t MpgSnd_Decoder::ogresf_get_filelen(void *user_data) -{ - Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; - return stream->size(); -} - -sf_count_t MpgSnd_Decoder::ogresf_seek(sf_count_t offset, int whence, void *user_data) -{ - Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; - - if(whence == SEEK_CUR) - stream->seek(stream->tell()+offset); - else if(whence == SEEK_SET) - stream->seek(offset); - else if(whence == SEEK_END) - stream->seek(stream->size()+offset); - else - return -1; - - return stream->tell(); -} - -sf_count_t MpgSnd_Decoder::ogresf_read(void *ptr, sf_count_t count, void *user_data) -{ - Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; - return stream->read(ptr, count); -} - -sf_count_t MpgSnd_Decoder::ogresf_write(const void*, sf_count_t, void*) -{ return -1; } - -sf_count_t MpgSnd_Decoder::ogresf_tell(void *user_data) -{ - Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; - return stream->tell(); -} - -// -// libmpg13 io callbacks -// -ssize_t MpgSnd_Decoder::ogrempg_read(void *user_data, void *ptr, size_t count) -{ - Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; - return stream->read(ptr, count); -} - -off_t MpgSnd_Decoder::ogrempg_lseek(void *user_data, off_t offset, int whence) -{ - Ogre::DataStreamPtr stream = static_cast(user_data)->mDataStream; - - if(whence == SEEK_CUR) - stream->seek(stream->tell()+offset); - else if(whence == SEEK_SET) - stream->seek(offset); - else if(whence == SEEK_END) - stream->seek(stream->size()+offset); - else - return -1; - - return stream->tell(); -} - - -void MpgSnd_Decoder::open(const std::string &fname) -{ - close(); - mDataStream = mResourceMgr.openResource(fname); - - SF_VIRTUAL_IO streamIO = { - ogresf_get_filelen, ogresf_seek, - ogresf_read, ogresf_write, ogresf_tell - }; - mSndFile = sf_open_virtual(&streamIO, SFM_READ, &mSndInfo, this); - if(mSndFile) - { - if(mSndInfo.channels == 1) - mChanConfig = ChannelConfig_Mono; - else if(mSndInfo.channels == 2) - mChanConfig = ChannelConfig_Stereo; - else - { - sf_close(mSndFile); - mSndFile = NULL; - fail("Unsupported channel count in "+fname); - } - mSampleRate = mSndInfo.samplerate; - return; - } - mDataStream->seek(0); - - mMpgFile = mpg123_new(NULL, NULL); - if(mMpgFile && mpg123_replace_reader_handle(mMpgFile, ogrempg_read, ogrempg_lseek, NULL) == MPG123_OK && - mpg123_open_handle(mMpgFile, this) == MPG123_OK) - { - try - { - int encoding, channels; - long rate; - if(mpg123_getformat(mMpgFile, &rate, &channels, &encoding) != MPG123_OK) - fail("Failed to get audio format"); - if(encoding != MPG123_ENC_SIGNED_16) - fail("Unsupported encoding in "+fname); - if(channels != 1 && channels != 2) - fail("Unsupported channel count in "+fname); - mChanConfig = ((channels==2)?ChannelConfig_Stereo:ChannelConfig_Mono); - mSampleRate = rate; - return; - } - catch(std::exception &e) - { - mpg123_close(mMpgFile); - mpg123_delete(mMpgFile); - mMpgFile = NULL; - throw; - } - mpg123_close(mMpgFile); - } - if(mMpgFile) - mpg123_delete(mMpgFile); - mMpgFile = NULL; - - fail("Unsupported file type: "+fname); -} - -void MpgSnd_Decoder::close() -{ - if(mSndFile) - sf_close(mSndFile); - mSndFile = NULL; - - if(mMpgFile) - { - mpg123_close(mMpgFile); - mpg123_delete(mMpgFile); - mMpgFile = NULL; - } - - mDataStream.setNull(); -} - -std::string MpgSnd_Decoder::getName() -{ - return mDataStream->getName(); -} - -void MpgSnd_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) -{ - if(!mSndFile && !mMpgFile) - fail("No open file"); - - *samplerate = mSampleRate; - *chans = mChanConfig; - *type = SampleType_Int16; -} - -size_t MpgSnd_Decoder::read(char *buffer, size_t bytes) -{ - size_t got = 0; - - if(mSndFile) - { - got = sf_read_short(mSndFile, (short*)buffer, bytes/2)*2; - } - else if(mMpgFile) - { - int err; - err = mpg123_read(mMpgFile, (unsigned char*)buffer, bytes, &got); - if(err != MPG123_OK && err != MPG123_DONE) - fail("Failed to read from file"); - } - return got; -} - -void MpgSnd_Decoder::readAll(std::vector &output) -{ - if(mSndFile && mSndInfo.frames > 0) - { - size_t pos = output.size(); - output.resize(pos + mSndInfo.frames*mSndInfo.channels*2); - sf_readf_short(mSndFile, (short*)(&output[0]+pos), mSndInfo.frames); - return; - } - // Fallback in case we don't know the total already - Sound_Decoder::readAll(output); -} - -void MpgSnd_Decoder::rewind() -{ - if(!mSndFile && !mMpgFile) - fail("No open file"); - - if(mSndFile) - { - if(sf_seek(mSndFile, 0, SEEK_SET) == -1) - fail("seek failed"); - } - else if(mMpgFile) - { - if(mpg123_seek(mMpgFile, 0, SEEK_SET) < 0) - fail("seek failed"); - } -} - -size_t MpgSnd_Decoder::getSampleOffset() -{ - return 0; -} - -MpgSnd_Decoder::MpgSnd_Decoder() - : mSndInfo() - , mSndFile(NULL) - , mMpgFile(NULL) - , mDataStream() - , mChanConfig(ChannelConfig_Stereo) - , mSampleRate(0) -{ - static bool initdone = false; - if(!initdone) - mpg123_init(); - initdone = true; -} - -MpgSnd_Decoder::~MpgSnd_Decoder() -{ - close(); -} - -} - -#endif diff --git a/apps/openmw/mwsound/mpgsnd_decoder.hpp b/apps/openmw/mwsound/mpgsnd_decoder.hpp deleted file mode 100644 index be52f6f49..000000000 --- a/apps/openmw/mwsound/mpgsnd_decoder.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef GAME_SOUND_MPGSND_DECODER_H -#define GAME_SOUND_MPGSND_DECODER_H - -#include - -#include - -#include "mpg123.h" -#include "sndfile.h" - -#include "sound_decoder.hpp" - - -namespace MWSound -{ - class MpgSnd_Decoder : public Sound_Decoder - { - SF_INFO mSndInfo; - SNDFILE *mSndFile; - mpg123_handle *mMpgFile; - - Ogre::DataStreamPtr mDataStream; - static sf_count_t ogresf_get_filelen(void *user_data); - static sf_count_t ogresf_seek(sf_count_t offset, int whence, void *user_data); - static sf_count_t ogresf_read(void *ptr, sf_count_t count, void *user_data); - static sf_count_t ogresf_write(const void*, sf_count_t, void*); - static sf_count_t ogresf_tell(void *user_data); - static ssize_t ogrempg_read(void*, void*, size_t); - static off_t ogrempg_lseek(void*, off_t, int); - - ChannelConfig mChanConfig; - int mSampleRate; - - virtual void open(const std::string &fname); - virtual void close(); - - virtual std::string getName(); - virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type); - - virtual size_t read(char *buffer, size_t bytes); - virtual void readAll(std::vector &output); - virtual void rewind(); - virtual size_t getSampleOffset(); - - MpgSnd_Decoder& operator=(const MpgSnd_Decoder &rhs); - MpgSnd_Decoder(const MpgSnd_Decoder &rhs); - - MpgSnd_Decoder(); - public: - virtual ~MpgSnd_Decoder(); - - friend class SoundManager; - }; -#ifndef DEFAULT_DECODER -#define DEFAULT_DECODER (::MWSound::MpgSnd_Decoder) -#endif -} - -#endif diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 33032477f..8ce87a25e 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -17,8 +17,8 @@ #include "openal_output.hpp" #define SOUND_OUT "OpenAL" -/* Set up the sound manager to use FFMPEG, MPG123+libsndfile, or Audiere for - * input. The OPENMW_USE_x macros are set in CMakeLists.txt. +/* Set up the sound manager to use FFMPEG for input. + * The OPENMW_USE_x macros are set in CMakeLists.txt. */ #ifdef OPENMW_USE_FFMPEG #include "ffmpeg_decoder.hpp" @@ -27,20 +27,6 @@ #endif #endif -#ifdef OPENMW_USE_AUDIERE -#include "audiere_decoder.hpp" -#ifndef SOUND_IN -#define SOUND_IN "Audiere" -#endif -#endif - -#ifdef OPENMW_USE_MPG123 -#include "mpgsnd_decoder.hpp" -#ifndef SOUND_IN -#define SOUND_IN "mpg123,sndfile" -#endif -#endif - namespace MWSound { diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 247c0d4bd..e30a2bbc1 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -227,10 +227,6 @@ namespace MWWorld Ogre::Vector3 inertia(0.0f); Ogre::Vector3 velocity; - bool canWalk = ptr.getClass().canWalk(ptr); - bool isBipedal = ptr.getClass().isBipedal(ptr); - bool isNpc = ptr.getClass().isNpc(); - if(position.z < waterlevel || isFlying) // under water by 3/4 or can fly { // TODO: Shouldn't water have higher drag in calculating velocity? @@ -277,14 +273,11 @@ namespace MWWorld // NOTE: velocity is either z axis only or x & z axis Ogre::Vector3 nextpos = newPosition + velocity * remainingTime; - // If not able to fly, walk or bipedal don't allow to move out of water + // If not able to fly, don't allow to swim up into the air // TODO: this if condition may not work for large creatures or situations // where the creature gets above the waterline for some reason if(newPosition.z < waterlevel && // started 3/4 under water !isFlying && // can't fly - !canWalk && // can't walk - !isBipedal && // not bipedal (assume bipedals can walk) - !isNpc && // FIXME: shouldn't really need this nextpos.z > waterlevel && // but about to go above water newPosition.z <= waterlevel) { diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index c40d47d7f..1f994d013 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -37,7 +37,7 @@ namespace MWWorld mTeleported(false), mMarkedCell(NULL), mCurrentCrimeId(-1), - mPayedCrimeId(-1) + mPaidCrimeId(-1) { mPlayer.mBase = player; mPlayer.mRef.mRefID = "player"; @@ -100,7 +100,6 @@ namespace MWWorld void Player::setLeftRight (int value) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[0] = value; } @@ -119,7 +118,6 @@ namespace MWWorld void Player::setUpDown(int value) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[2] = value; } @@ -132,28 +130,7 @@ namespace MWWorld void Player::setSneak(bool sneak) { MWWorld::Ptr ptr = getPlayer(); - ptr.getClass().getCreatureStats(ptr).setMovementFlag(MWMechanics::CreatureStats::Flag_Sneak, sneak); - - if (sneak == true) - { - const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore(); - - // Find all the actors who might be able to see the player - std::vector neighbors; - MWBase::Environment::get().getMechanicsManager()->getActorsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos), - esmStore.get().find("fSneakUseDist")->getInt(), neighbors); - for (std::vector::iterator it = neighbors.begin(); it != neighbors.end(); ++it) - { - if ( MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, *it) ) - { - MWBase::Environment::get().getWindowManager()->setSneakVisibility(false); - break; - } - } - if (neighbors.empty()) - MWBase::Environment::get().getWindowManager()->setSneakVisibility(true); - } } void Player::yaw(float yaw) @@ -223,7 +200,7 @@ namespace MWWorld player.mCellId = mCellStore->getCell()->getCellId(); player.mCurrentCrimeId = mCurrentCrimeId; - player.mPayedCrimeId = mPayedCrimeId; + player.mPaidCrimeId = mPaidCrimeId; player.mBirthsign = mSign; @@ -273,7 +250,7 @@ namespace MWWorld throw std::runtime_error ("invalid player state record (birthsign)"); mCurrentCrimeId = player.mCurrentCrimeId; - mPayedCrimeId = player.mPayedCrimeId; + mPaidCrimeId = player.mPaidCrimeId; mSign = player.mBirthsign; @@ -318,11 +295,11 @@ namespace MWWorld void Player::recordCrimeId() { - mPayedCrimeId = mCurrentCrimeId; + mPaidCrimeId = mCurrentCrimeId; } int Player::getCrimeId() const { - return mPayedCrimeId; + return mPaidCrimeId; } } diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index b1de3e510..d8cde5952 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -48,7 +48,7 @@ namespace MWWorld bool mTeleported; int mCurrentCrimeId; // the id assigned witnesses - int mPayedCrimeId; // the last id payed off (0 bounty) + int mPaidCrimeId; // the last id paid off (0 bounty) public: @@ -105,8 +105,8 @@ namespace MWWorld bool readRecord (ESM::ESMReader& reader, int32_t type); int getNewCrimeId(); // get new id for witnesses - void recordCrimeId(); // record the payed crime id when bounty is 0 - int getCrimeId() const; // get the last payed crime id + void recordCrimeId(); // record the paid crime id when bounty is 0 + int getCrimeId() const; // get the last paid crime id }; } #endif diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 3611114a9..25f523bee 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -329,7 +329,6 @@ void WeatherManager::update(float duration) const bool exterior = (world->isCellExterior() || world->isCellQuasiExterior()); if (!exterior) { - mRendering->sunDisable(false); mRendering->skyDisable(); mRendering->getSkyManager()->setLightningStrength(0.f); stopSounds(true); diff --git a/cmake/FindAudiere.cmake b/cmake/FindAudiere.cmake deleted file mode 100644 index 79427309c..000000000 --- a/cmake/FindAudiere.cmake +++ /dev/null @@ -1,60 +0,0 @@ -# Locate Audiere -# This module defines -# AUDIERE_LIBRARY -# AUDIERE_FOUND, if false, do not try to link to Audiere -# AUDIERE_INCLUDE_DIR, where to find the headers -# -# Created by Nicolay Korslund for OpenMW (http://openmw.com) -# -# More or less a direct ripoff of FindOpenAL.cmake by Eric Wing. - -#============================================================================= -# Copyright 2005-2009 Kitware, Inc. -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distributed this file outside of CMake, substitute the full -# License text for the above reference.) - - -FIND_PATH(AUDIERE_INCLUDE_DIR audiere.h - HINTS - PATH_SUFFIXES include - PATHS - $ENV{AUDIERE_DIR} - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt -) - -FIND_LIBRARY(AUDIERE_LIBRARY - NAMES audiere - HINTS - PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 - PATHS - $ENV{AUDIERE_DIR} - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw - /opt/local - /opt/csw - /opt -) - -SET(AUDIERE_FOUND "NO") -IF(AUDIERE_LIBRARY AND AUDIERE_INCLUDE_DIR) - SET(AUDIERE_FOUND "YES") -ENDIF(AUDIERE_LIBRARY AND AUDIERE_INCLUDE_DIR) - diff --git a/cmake/FindMPG123.cmake b/cmake/FindMPG123.cmake deleted file mode 100644 index 51e562c91..000000000 --- a/cmake/FindMPG123.cmake +++ /dev/null @@ -1,47 +0,0 @@ -# Locate MPG123 -# This module defines -# MPG123_LIBRARY -# MPG123_FOUND, if false, do not try to link to Mpg123 -# MPG123_INCLUDE_DIR, where to find the headers -# -# Created by Nicolay Korslund for OpenMW (http://openmw.com) -# -# Ripped off from other sources. In fact, this file is so generic (I -# just did a search and replace on another file) that I wonder why the -# CMake guys haven't wrapped this entire thing in a single -# function. Do we really need to repeat this stuff for every single -# library when they all work the same? - -FIND_PATH(MPG123_INCLUDE_DIR mpg123.h - HINTS - PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt -) - -FIND_LIBRARY(MPG123_LIBRARY - NAMES mpg123 - HINTS - PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 - PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw - /opt/local - /opt/csw - /opt -) - -SET(MPG123_FOUND "NO") -IF(MPG123_LIBRARY AND MPG123_INCLUDE_DIR) - SET(MPG123_FOUND "YES") -ENDIF(MPG123_LIBRARY AND MPG123_INCLUDE_DIR) - diff --git a/cmake/FindSNDFILE.cmake b/cmake/FindSNDFILE.cmake deleted file mode 100644 index 5c7664b50..000000000 --- a/cmake/FindSNDFILE.cmake +++ /dev/null @@ -1,41 +0,0 @@ -# Locate SNDFILE -# This module defines -# SNDFILE_LIBRARY -# SNDFILE_FOUND, if false, do not try to link to Sndfile -# SNDFILE_INCLUDE_DIR, where to find the headers -# -# Created by Nicolay Korslund for OpenMW (http://openmw.com) - -FIND_PATH(SNDFILE_INCLUDE_DIR sndfile.h - HINTS - PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt -) - -FIND_LIBRARY(SNDFILE_LIBRARY - NAMES sndfile - HINTS - PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 - PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw - /opt/local - /opt/csw - /opt -) - -SET(SNDFILE_FOUND "NO") -IF(SNDFILE_LIBRARY AND SNDFILE_INCLUDE_DIR) - SET(SNDFILE_FOUND "YES") -ENDIF(SNDFILE_LIBRARY AND SNDFILE_INCLUDE_DIR) - diff --git a/components/esm/loadcrea.hpp b/components/esm/loadcrea.hpp index 817c0e43c..e459dded7 100644 --- a/components/esm/loadcrea.hpp +++ b/components/esm/loadcrea.hpp @@ -33,7 +33,7 @@ struct Creature Respawn = 0x002, Weapon = 0x004, // Has weapon and shield - None = 0x008, // ?? + None = 0x008, // ?? This flag appears set for every creature in Morrowind.esm Essential = 0x080, // Blood types diff --git a/components/esm/player.cpp b/components/esm/player.cpp index 70f795afe..52b44c945 100644 --- a/components/esm/player.cpp +++ b/components/esm/player.cpp @@ -28,8 +28,8 @@ void ESM::Player::load (ESMReader &esm) mCurrentCrimeId = -1; esm.getHNOT (mCurrentCrimeId, "CURD"); - mPayedCrimeId = -1; - esm.getHNOT (mPayedCrimeId, "PAYD"); + mPaidCrimeId = -1; + esm.getHNOT (mPaidCrimeId, "PAYD"); } void ESM::Player::save (ESMWriter &esm) const @@ -52,5 +52,5 @@ void ESM::Player::save (ESMWriter &esm) const esm.writeHNString ("SIGN", mBirthsign); esm.writeHNT ("CURD", mCurrentCrimeId); - esm.writeHNT ("PAYD", mPayedCrimeId); + esm.writeHNT ("PAYD", mPaidCrimeId); } diff --git a/components/esm/player.hpp b/components/esm/player.hpp index 377c8547a..440d0a2d9 100644 --- a/components/esm/player.hpp +++ b/components/esm/player.hpp @@ -26,11 +26,11 @@ namespace ESM std::string mBirthsign; int mCurrentCrimeId; - int mPayedCrimeId; + int mPaidCrimeId; void load (ESMReader &esm); void save (ESMWriter &esm) const; }; } -#endif \ No newline at end of file +#endif diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp index c3ea2fd74..82db5ea99 100644 --- a/extern/sdl4ogre/sdlinputwrapper.cpp +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -115,7 +115,7 @@ namespace SFO mWindowListener->windowClosed(); break; default: - std::cerr << "Unhandled SDL event of type " << evt.type << std::endl; + std::cerr << "Unhandled SDL event of type 0x" << std::hex << evt.type << std::endl; break; } } @@ -241,8 +241,8 @@ namespace SFO //eep, wrap the pointer manually if the input driver doesn't support //relative positioning natively - int success = SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE); - if(relative && success != 0) + bool success = SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE) == 0; + if(relative && !success) mWrapPointer = true; //now remove all mouse events using the old setting from the queue diff --git a/files/opencs.cfg b/files/opencs.cfg deleted file mode 100644 index 3faac7c8e..000000000 --- a/files/opencs.cfg +++ /dev/null @@ -1,5 +0,0 @@ -[Editor] -Record Status Display = Icon and Text -[Window Size] -Width = 640 -Height = 480 diff --git a/files/opencs.ini b/files/opencs.ini new file mode 100644 index 000000000..065f11a88 --- /dev/null +++ b/files/opencs.ini @@ -0,0 +1,7 @@ +[Display%20Format] +Record%20Status%20Display=Icon Only +Referenceable%20ID%20Type%20Display=Text Only + +[Window%20Size] +Height=900 +Width=1440 diff --git a/files/settings-default.cfg b/files/settings-default.cfg index f24636d15..2b44d0f4e 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -133,9 +133,9 @@ distant land = false shader = true [Water] -shader = true +shader = false -refraction = true +refraction = false rtt size = 512 reflect terrain = true