diff --git a/CMakeLists.txt b/CMakeLists.txt index 27007f161..bd437ed61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -345,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 0aa9449f9..3f61a2b8f 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -106,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 f6370ac51..f6a13f4f6 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()); @@ -124,11 +124,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/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 fe15cf7f6..2ef829f86 100644 --- a/apps/opencs/model/settings/setting.cpp +++ b/apps/opencs/model/settings/setting.cpp @@ -45,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, @@ -54,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) diff --git a/apps/opencs/model/settings/setting.hpp b/apps/opencs/model/settings/setting.hpp index cf5dd2a06..89d6cc2c4 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,10 +25,6 @@ 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: diff --git a/apps/opencs/model/settings/settingmanager.cpp b/apps/opencs/model/settings/settingmanager.cpp deleted file mode 100644 index 36ca1ae03..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) -{ - //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); - - - //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 2efc2929f..000000000 --- a/apps/opencs/model/settings/settingmanager.hpp +++ /dev/null @@ -1,84 +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); - - ///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 d65de2b91..229e293b8 100644 --- a/apps/opencs/model/settings/support.hpp +++ b/apps/opencs/model/settings/support.hpp @@ -7,22 +7,10 @@ #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, @@ -55,6 +43,7 @@ namespace CSMSettings Property_Proxies = 25 }; + ///Basic setting widget types. enum SettingType { /* @@ -82,16 +71,11 @@ namespace CSMSettings 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, @@ -100,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; @@ -119,6 +97,9 @@ 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", "setting_type", "is_multi_value", @@ -129,6 +110,7 @@ namespace CSMSettings "defaults", "declarations", "definitions", "proxies" }; + ///Default values for a setting. Used in setting creation. const QString sPropertyDefaults[] = { "", //name diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index a8fd752e3..8d71dbe82 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,9 +33,36 @@ CSMSettings::UserSettings::UserSettings() assert(!mUserSettingsInstance); mUserSettingsInstance = this; + mSettingDefinitions = 0; + buildSettingModelDefaults(); } +void CSMSettings::UserSettings::addDefinitions () +{ + foreach (const QString &key, mSettingDefinitions->allKeys()) + { + QStringList names = key.split('/'); + + Setting *setting = findSetting (names.at(0), names.at(1)); + + if (!setting) + { + qWarning() << "Found definitions for undeclared setting " + << names.at(0) << "/" << names.at(1); + removeSetting (names.at(0), names.at(1)); + continue; + } + + QStringList values = mSettingDefinitions->value (key).toStringList(); + + if (values.isEmpty()) + values.append (setting->defaultValues()); + + setting->setDefinedValues (values); + } +} + void CSMSettings::UserSettings::buildSettingModelDefaults() { QString section = "Window Size"; @@ -127,10 +147,10 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() * 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"); @@ -230,6 +250,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() slaveIntegerSpinbox->setSerializable (false); slaveDoubleSpinbox->setSerializable (false); slaveSlider->setSerializable (false); + slaveDial->setSerializable (false); slaveBoolean->setDefaultValues (QStringList() << "One" << "Three" << "Five"); @@ -283,73 +304,46 @@ CSMSettings::UserSettings::~UserSettings() void CSMSettings::UserSettings::loadSettings (const QString &fileName) { - mUserFilePath = QString::fromUtf8 - (mCfgMgr.getUserConfigPath().string().c_str()) + fileName.toUtf8(); - - QString global = QString::fromUtf8 - (mCfgMgr.getGlobalPath().string().c_str()) + fileName.toUtf8(); + QString userFilePath = QString::fromUtf8 + (mCfgMgr.getUserConfigPath().string().c_str()); - QString local = QString::fromUtf8 - (mCfgMgr.getLocalPath().string().c_str()) + fileName.toUtf8(); + QString globalFilePath = QString::fromUtf8 + (mCfgMgr.getGlobalPath().string().c_str()); - //open user and global streams - QTextStream *userStream = openFilestream (mUserFilePath, true); - QTextStream *otherStream = openFilestream (global, true); + QString otherFilePath = globalFilePath; - //failed stream, try for local - if (!otherStream) - otherStream = openFilestream (local, true); - - //error condition - notify and return - if (!otherStream || !userStream) + //test for local only if global fails (uninstalled copy) + if (!QFile (globalFilePath + fileName).exists()) { - 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.
"); - - message += QObject::tr("
Global filepath: ") + global; - message += QObject::tr("
Local filepath: ") + local; - message += QObject::tr("
User filepath: ") + mUserFilePath; - - displayFileErrorMessage ( message, true); - return; + //if global is invalid, use the local path + otherFilePath = QString::fromUtf8 + (mCfgMgr.getLocalPath().string().c_str()); } - //success condition - merge the two streams into a single map and save - DefinitionPageMap totalMap = readFilestream (userStream); - DefinitionPageMap otherMap = readFilestream(otherStream); + QSettings::setPath + (QSettings::IniFormat, QSettings::UserScope, userFilePath); - //merging other settings file in and ignore duplicate settings to - //avoid overwriting user-level settings - mergeSettings (totalMap, otherMap); + QSettings::setPath + (QSettings::IniFormat, QSettings::SystemScope, otherFilePath); - if (!totalMap.isEmpty()) - addDefinitions (totalMap); + mSettingDefinitions = new QSettings + (QSettings::IniFormat, QSettings::UserScope, "opencs", QString(), this); + + addDefinitions(); } void CSMSettings::UserSettings::saveSettings (const QMap &settingMap) { - for (int i = 0; i < settings().size(); i++) - { - Setting* setting = settings().at(i); + foreach (const QString &key, settingMap.keys()) + mSettingDefinitions->setValue (key, settingMap.value (key)); - QString key = setting->page() + '.' + setting->name(); - - if (!settingMap.keys().contains(key)) - continue; - - setting->setDefinedValues (settingMap.value(key)); - } - - writeFilestream (openFilestream (mUserFilePath, false), settingMap); + mSettingDefinitions->sync(); } QString CSMSettings::UserSettings::settingValue (const QString &settingKey) { - QStringList names = settingKey.split('.'); + QStringList names = settingKey.split('/'); Setting *setting = findSetting(names.at(0), names.at(1)); @@ -366,3 +360,82 @@ CSMSettings::UserSettings& CSMSettings::UserSettings::instance() assert(mUserSettingsInstance); return *mUserSettingsInstance; } + +void CSMSettings::UserSettings::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); +} + +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; + + QList ::iterator removeIterator = mSettings.begin(); + + while (removeIterator != mSettings.end()) + { + if ((*removeIterator)->name() == settingName) + { + if ((*removeIterator)->page() == pageName) + { + mSettings.erase (removeIterator); + break; + } + } + removeIterator++; + } +} + + +CSMSettings::SettingPageMap CSMSettings::UserSettings::settingPageMap() const +{ + SettingPageMap pageMap; + + foreach (Setting *setting, mSettings) + pageMap[setting->page()].append (setting); + + return pageMap; +} + +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)) + { + qWarning() << "Duplicate declaration encountered: " + << (name + '/' + page); + return 0; + } + + Setting *setting = new Setting (typ, name, page); + + + //add declaration to the model + mSettings.append (setting); + + return setting; +} diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index f0ed7af41..3ac348760 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,9 +46,6 @@ 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); @@ -55,9 +54,35 @@ namespace CSMSettings { 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; + private: + ///add definitions to the settings specified in the page map + void addDefinitions(); + 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/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/settings/dialog.cpp b/apps/opencs/view/settings/dialog.cpp index 3ed4d3b09..4e7b08aff 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); @@ -123,6 +110,7 @@ void CSVSettings::Dialog::show() { if (pages().isEmpty()) buildPages(); + QPoint screenCenter = QApplication::desktop()->screenGeometry().center(); move (screenCenter - geometry().center()); 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.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.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 b2701c7bf..8ae6caca0 100644 --- a/apps/opencs/view/settings/rangeview.cpp +++ b/apps/opencs/view/settings/rangeview.cpp @@ -1,6 +1,3 @@ -#include -#include -#include #include #include #include diff --git a/apps/opencs/view/settings/rangeview.hpp b/apps/opencs/view/settings/rangeview.hpp index e8d6df88e..2ab343f1f 100644 --- a/apps/opencs/view/settings/rangeview.hpp +++ b/apps/opencs/view/settings/rangeview.hpp @@ -21,13 +21,19 @@ namespace CSVSettings 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: + ///responds to valueChanged signals void slotUpdateView (int value); void slotUpdateView (double value); 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..aeb652b3b 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; diff --git a/apps/opencs/view/settings/settingwindow.hpp b/apps/opencs/view/settings/settingwindow.hpp index 35ae4c068..071f1b45e 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,33 @@ 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(); 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 index bfb166370..4b1447f8f 100644 --- a/apps/opencs/view/settings/spinbox.cpp +++ b/apps/opencs/view/settings/spinbox.cpp @@ -1,6 +1,5 @@ #include "spinbox.hpp" -#include #include CSVSettings::SpinBox::SpinBox(QWidget *parent) @@ -14,7 +13,7 @@ QString CSVSettings::SpinBox::textFromValue(int val) const if (mValueList.isEmpty()) return QVariant (val).toString(); - QString value = ""; + QString value; if (val < mValueList.size()) value = mValueList.at (val); diff --git a/apps/opencs/view/settings/spinbox.hpp b/apps/opencs/view/settings/spinbox.hpp index f8e59fa05..e887e8c93 100644 --- a/apps/opencs/view/settings/spinbox.hpp +++ b/apps/opencs/view/settings/spinbox.hpp @@ -16,15 +16,22 @@ namespace CSVSettings public: explicit SpinBox(QWidget *parent = 0); - void setObjectName (const QString &name); - + ///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; }; } diff --git a/apps/opencs/view/settings/textview.hpp b/apps/opencs/view/settings/textview.hpp index c485e7fcf..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: diff --git a/apps/opencs/view/settings/view.cpp b/apps/opencs/view/settings/view.cpp index 2a70152c2..c3b33cf84 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) { @@ -42,24 +43,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; } @@ -151,9 +150,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) @@ -192,7 +188,6 @@ bool CSVSettings::View::stringListsMatch ( QList CSVSettings::View::toStandardItemList (const QStringList &list) const { - QList itemList; foreach (const QString &value, list) @@ -212,12 +207,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 23357e45f..5106d8d90 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; 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/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/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