1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-19 20:53:50 +00:00

Merge remote-tracking branch 'graffy76/master'

This commit is contained in:
Marc Zinnschlag 2014-05-07 10:35:11 +02:00
commit 21142711f0
32 changed files with 269 additions and 602 deletions

View file

@ -345,8 +345,8 @@ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
"${OpenMW_BINARY_DIR}/openmw.cfg.install") "${OpenMW_BINARY_DIR}/openmw.cfg.install")
configure_file(${OpenMW_SOURCE_DIR}/files/opencs.cfg configure_file(${OpenMW_SOURCE_DIR}/files/opencs.ini
"${OpenMW_BINARY_DIR}/opencs.cfg") "${OpenMW_BINARY_DIR}/opencs.ini")
configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters
"${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY) "${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY)

View file

@ -106,7 +106,6 @@ opencs_units_noqt (view/settings
opencs_units (model/settings opencs_units (model/settings
usersettings usersettings
settingmanager
setting setting
connector connector
) )

View file

@ -27,7 +27,7 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
setupDataFiles (config.first); setupDataFiles (config.first);
CSMSettings::UserSettings::instance().loadSettings ("opencs.cfg"); CSMSettings::UserSettings::instance().loadSettings ("opencs.ini");
mSettings.setModel (CSMSettings::UserSettings::instance()); mSettings.setModel (CSMSettings::UserSettings::instance());
ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string()); ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string());
@ -124,11 +124,6 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
QString path = QString::fromUtf8 (iter->string().c_str()); QString path = QString::fromUtf8 (iter->string().c_str());
mFileDialog.addFiles(path); 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<std::vector<std::string> >()); return std::make_pair (dataDirs, variables["fallback-archive"].as<std::vector<std::string> >());
} }

View file

@ -20,34 +20,46 @@ namespace CSMSettings {
CSVSettings::View *mMasterView; 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 <CSVSettings::View *> mSlaveViews; QList <CSVSettings::View *> mSlaveViews;
//list of proxy values for each master value. ///list of proxy values for each master value.
//value list order is indexed to the master value index. ///value list order is indexed to the master value index.
QMap < QString, QList <QStringList> > mProxyListMap; QMap < QString, QList <QStringList> > mProxyListMap;
public: public:
explicit Connector(CSVSettings::View *master, explicit Connector(CSVSettings::View *master,
QObject *parent = 0); QObject *parent = 0);
///Set the view which acts as a proxy for other setting views
void setMasterView (CSVSettings::View *view); void setMasterView (CSVSettings::View *view);
///Add a view to be updated / update to the master
void addSlaveView (CSVSettings::View *view, void addSlaveView (CSVSettings::View *view,
QList <QStringList> &masterProxyValues); QList <QStringList> &masterProxyValues);
private: private:
///loosely matches lists of proxy values across registered slaves
///against a proxy value list for a given master value
bool proxyListsMatch (const QList <QStringList> &list1, bool proxyListsMatch (const QList <QStringList> &list1,
const QList <QStringList> &list2) const; const QList <QStringList> &list2) const;
///loosely matches two string lists
bool stringListsMatch (const QStringList &list1, bool stringListsMatch (const QStringList &list1,
const QStringList &list2) const; const QStringList &list2) const;
///retrieves current values of registered slave views
QList <QStringList> getSlaveViewValues() const; QList <QStringList> getSlaveViewValues() const;
public slots: public slots:
///updates slave views with proxy values associated with current
///master value
void slotUpdateSlaves() const; void slotUpdateSlaves() const;
///updates master value associated with the currently selected
///slave values, if applicable.
void slotUpdateMaster() const; void slotUpdateMaster() const;
}; };
} }

View file

@ -45,7 +45,7 @@ void CSMSettings::Setting::addProxy (const Setting *setting,
foreach (const QString &val, vals) foreach (const QString &val, vals)
list << (QStringList() << val); list << (QStringList() << val);
mProxies [setting->page() + '.' + setting->name()] = list; mProxies [setting->page() + '/' + setting->name()] = list;
} }
void CSMSettings::Setting::addProxy (const Setting *setting, void CSMSettings::Setting::addProxy (const Setting *setting,
@ -54,7 +54,7 @@ void CSMSettings::Setting::addProxy (const Setting *setting,
if (serializable()) if (serializable())
setProperty (Property_Serializable, false); setProperty (Property_Serializable, false);
mProxies [setting->page() + '.' + setting->name()] = list; mProxies [setting->page() + '/' + setting->name()] = list;
} }
void CSMSettings::Setting::setColumnSpan (int value) void CSMSettings::Setting::setColumnSpan (int value)

View file

@ -7,11 +7,17 @@
namespace CSMSettings namespace CSMSettings
{ {
//Maps setting id ("page.name") to a list of corresponding proxy values. //QString is the setting id in the form of "page/name"
//Order of proxy value stringlists corresponds to order of master proxy's //QList is a list of stringlists of proxy values.
//values in it's declared value list //Order is important! Proxy stringlists are matched against
//master values by their position in the QList.
typedef QMap <QString, QList <QStringList> > ProxyValueMap; typedef QMap <QString, QList <QStringList> > 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 class Setting
{ {
QList <QStringList> mProperties; QList <QStringList> mProperties;
@ -19,10 +25,6 @@ namespace CSMSettings
bool mIsEditorSetting; 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; ProxyValueMap mProxies;
public: public:

View file

@ -1,342 +0,0 @@
#include <QFile>
#include <QTextCodec>
#include <QMessageBox>
#include <QDebug>
#include <QList>
#include "setting.hpp"
#include "settingmanager.hpp"
CSMSettings::SettingManager::SettingManager(QObject *parent) :
QObject(parent)
{
mReadWriteMessage = QObject::tr("<br><b>Could not open or create file for \
writing</b><br><br> Please make sure you have the right\
permissions and try again.<br>");
mReadOnlyMessage = QObject::tr("<br><b>Could not open file for \
reading</b><br><br> Please make sure you have the \
right permissions and try again.<br>");
}
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 <QString, QStringList > &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 &section, 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::Setting *> CSMSettings::SettingManager::findSettings
(const QStringList &list)
{
QList <CSMSettings::Setting *> 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::Setting *> CSMSettings::SettingManager::findSettings
(const QString &pageName)
{
QList <CSMSettings::Setting *> 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);
}

View file

@ -1,84 +0,0 @@
#ifndef CSMSETTINGS_SETTINGMANAGER_HPP
#define CSMSETTINGS_SETTINGMANAGER_HPP
#include <QObject>
#include <QMap>
#include <QStringList>
#include <QTextStream>
#include "support.hpp"
#include "setting.hpp"
namespace CSMSettings
{
typedef QMap <QString, QStringList *> DefinitionMap;
typedef QMap <QString, DefinitionMap *> DefinitionPageMap;
typedef QMap <QString, QList <Setting *> > SettingPageMap;
class SettingManager : public QObject
{
Q_OBJECT
QString mReadOnlyMessage;
QString mReadWriteMessage;
QList <Setting *> 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 <Setting *> findSettings (const QString &pageName);
///retrieve all settings named in the attached list.
///Setting names are specified in "PageName.SettingName" format.
QList <Setting *> 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 <QString, QStringList > &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 <Setting *> 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

View file

@ -7,22 +7,10 @@
#include <QVariant> #include <QVariant>
#include <QStringList> #include <QStringList>
//Typedefs
namespace CSMSettings
{
// Definition / Declaration model typedefs
// "Pair" = Setting name and specific data
// "ListItem" = Page name and associated setting pair
typedef QPair <QString, QString> StringPair;
typedef QPair <QString, QStringList> StringListPair;
typedef QList <StringListPair> StringListPairs;
}
//Enums //Enums
namespace CSMSettings namespace CSMSettings
{ {
///Enumerated properties for scripting
enum SettingProperty enum SettingProperty
{ {
Property_Name = 0, Property_Name = 0,
@ -55,6 +43,7 @@ namespace CSMSettings
Property_Proxies = 25 Property_Proxies = 25
}; };
///Basic setting widget types.
enum SettingType enum SettingType
{ {
/* /*
@ -82,16 +71,11 @@ namespace CSMSettings
Type_Undefined = 40 Type_Undefined = 40
}; };
enum MergeMethod
{
Merge_Accept,
Merge_Ignore,
Merge_Overwrite
};
} }
namespace CSVSettings namespace CSVSettings
{ {
///Categorical view types which encompass the setting widget types
enum ViewType enum ViewType
{ {
ViewType_Boolean = 0, ViewType_Boolean = 0,
@ -100,18 +84,12 @@ namespace CSVSettings
ViewType_Text = 3, ViewType_Text = 3,
ViewType_Undefined = 4 ViewType_Undefined = 4
}; };
enum Alignment
{
Align_Left = Qt::AlignLeft,
Align_Center = Qt::AlignHCenter,
Align_Right = Qt::AlignRight
};
} }
namespace CSMSettings namespace CSMSettings
{ {
///used to construct default settings in the Setting class
struct PropertyDefaultValues struct PropertyDefaultValues
{ {
int id; int id;
@ -119,6 +97,9 @@ namespace CSMSettings
QVariant value; 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[] = const QString sPropertyNames[] =
{ {
"name", "page", "setting_type", "is_multi_value", "name", "page", "setting_type", "is_multi_value",
@ -129,6 +110,7 @@ namespace CSMSettings
"defaults", "declarations", "definitions", "proxies" "defaults", "declarations", "definitions", "proxies"
}; };
///Default values for a setting. Used in setting creation.
const QString sPropertyDefaults[] = const QString sPropertyDefaults[] =
{ {
"", //name "", //name

View file

@ -1,21 +1,14 @@
#include "usersettings.hpp" #include "usersettings.hpp"
#include <QTextStream> #include <QSettings>
#include <QDir>
#include <QString>
#include <QRegExp>
#include <QMap>
#include <QMessageBox>
#include <QTextCodec>
#include <QFile> #include <QFile>
#include <QSortFilterProxyModel>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include <boost/version.hpp> #include <boost/version.hpp>
#include "setting.hpp" #include "setting.hpp"
#include "support.hpp" #include "support.hpp"
#include <QDebug>
/** /**
* Workaround for problems with whitespaces in paths in older versions of Boost library * Workaround for problems with whitespaces in paths in older versions of Boost library
@ -40,9 +33,36 @@ CSMSettings::UserSettings::UserSettings()
assert(!mUserSettingsInstance); assert(!mUserSettingsInstance);
mUserSettingsInstance = this; mUserSettingsInstance = this;
mSettingDefinitions = 0;
buildSettingModelDefaults(); 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() void CSMSettings::UserSettings::buildSettingModelDefaults()
{ {
QString section = "Window Size"; QString section = "Window Size";
@ -127,10 +147,10 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
* proxy slave settings, but must match any declared values the proxy * proxy slave settings, but must match any declared values the proxy
* slave has, if any. * slave has, if any.
*******************************************************************/ *******************************************************************/
/*
//create setting objects, specifying the basic widget type, //create setting objects, specifying the basic widget type,
//the page name, and the view name //the page name, and the view name
/*
Setting *masterBoolean = createSetting (Type_RadioButton, section, Setting *masterBoolean = createSetting (Type_RadioButton, section,
"Master Proxy"); "Master Proxy");
@ -230,6 +250,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
slaveIntegerSpinbox->setSerializable (false); slaveIntegerSpinbox->setSerializable (false);
slaveDoubleSpinbox->setSerializable (false); slaveDoubleSpinbox->setSerializable (false);
slaveSlider->setSerializable (false); slaveSlider->setSerializable (false);
slaveDial->setSerializable (false);
slaveBoolean->setDefaultValues (QStringList() slaveBoolean->setDefaultValues (QStringList()
<< "One" << "Three" << "Five"); << "One" << "Three" << "Five");
@ -283,73 +304,46 @@ CSMSettings::UserSettings::~UserSettings()
void CSMSettings::UserSettings::loadSettings (const QString &fileName) void CSMSettings::UserSettings::loadSettings (const QString &fileName)
{ {
mUserFilePath = QString::fromUtf8 QString userFilePath = QString::fromUtf8
(mCfgMgr.getUserConfigPath().string().c_str()) + fileName.toUtf8(); (mCfgMgr.getUserConfigPath().string().c_str());
QString global = QString::fromUtf8 QString globalFilePath = QString::fromUtf8
(mCfgMgr.getGlobalPath().string().c_str()) + fileName.toUtf8(); (mCfgMgr.getGlobalPath().string().c_str());
QString local = QString::fromUtf8 QString otherFilePath = globalFilePath;
(mCfgMgr.getLocalPath().string().c_str()) + fileName.toUtf8();
//open user and global streams //test for local only if global fails (uninstalled copy)
QTextStream *userStream = openFilestream (mUserFilePath, true); if (!QFile (globalFilePath + fileName).exists())
QTextStream *otherStream = openFilestream (global, true);
//failed stream, try for local
if (!otherStream)
otherStream = openFilestream (local, true);
//error condition - notify and return
if (!otherStream || !userStream)
{ {
QString message = QObject::tr("<br><b>An error was encountered loading \ //if global is invalid, use the local path
user settings files.</b><br><br> One or several files could not \ otherFilePath = QString::fromUtf8
be read. This may be caused by a missing configuration file, \ (mCfgMgr.getLocalPath().string().c_str());
incorrect file permissions or a corrupted installation of \
OpenCS.<br>");
message += QObject::tr("<br>Global filepath: ") + global;
message += QObject::tr("<br>Local filepath: ") + local;
message += QObject::tr("<br>User filepath: ") + mUserFilePath;
displayFileErrorMessage ( message, true);
return;
} }
//success condition - merge the two streams into a single map and save QSettings::setPath
DefinitionPageMap totalMap = readFilestream (userStream); (QSettings::IniFormat, QSettings::UserScope, userFilePath);
DefinitionPageMap otherMap = readFilestream(otherStream);
//merging other settings file in and ignore duplicate settings to QSettings::setPath
//avoid overwriting user-level settings (QSettings::IniFormat, QSettings::SystemScope, otherFilePath);
mergeSettings (totalMap, otherMap);
if (!totalMap.isEmpty()) mSettingDefinitions = new QSettings
addDefinitions (totalMap); (QSettings::IniFormat, QSettings::UserScope, "opencs", QString(), this);
addDefinitions();
} }
void CSMSettings::UserSettings::saveSettings void CSMSettings::UserSettings::saveSettings
(const QMap <QString, QStringList> &settingMap) (const QMap <QString, QStringList> &settingMap)
{ {
for (int i = 0; i < settings().size(); i++) foreach (const QString &key, settingMap.keys())
{ mSettingDefinitions->setValue (key, settingMap.value (key));
Setting* setting = settings().at(i);
QString key = setting->page() + '.' + setting->name(); mSettingDefinitions->sync();
if (!settingMap.keys().contains(key))
continue;
setting->setDefinedValues (settingMap.value(key));
}
writeFilestream (openFilestream (mUserFilePath, false), settingMap);
} }
QString CSMSettings::UserSettings::settingValue (const QString &settingKey) QString CSMSettings::UserSettings::settingValue (const QString &settingKey)
{ {
QStringList names = settingKey.split('.'); QStringList names = settingKey.split('/');
Setting *setting = findSetting(names.at(0), names.at(1)); Setting *setting = findSetting(names.at(0), names.at(1));
@ -366,3 +360,82 @@ CSMSettings::UserSettings& CSMSettings::UserSettings::instance()
assert(mUserSettingsInstance); assert(mUserSettingsInstance);
return *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 <Setting *>::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;
}

View file

@ -1,14 +1,13 @@
#ifndef USERSETTINGS_HPP #ifndef USERSETTINGS_HPP
#define USERSETTINGS_HPP #define USERSETTINGS_HPP
#include <QTextStream> #include <QList>
#include <QStringList> #include <QStringList>
#include <QString> #include <QString>
#include <QMap> #include <QMap>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include "support.hpp"
#include "settingmanager.hpp"
#ifndef Q_MOC_RUN #ifndef Q_MOC_RUN
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
@ -18,20 +17,23 @@ namespace Files { typedef std::vector<boost::filesystem::path> PathContainer;
struct ConfigurationManager;} struct ConfigurationManager;}
class QFile; class QFile;
class QSettings;
namespace CSMSettings { namespace CSMSettings {
class UserSettings: public SettingManager class Setting;
typedef QMap <QString, QList <Setting *> > SettingPageMap;
class UserSettings: public QObject
{ {
Q_OBJECT Q_OBJECT
static UserSettings *mUserSettingsInstance; static UserSettings *mUserSettingsInstance;
QString mUserFilePath;
Files::ConfigurationManager mCfgMgr; Files::ConfigurationManager mCfgMgr;
QString mReadOnlyMessage; QSettings *mSettingDefinitions;
QString mReadWriteMessage; QList <Setting *> mSettings;
public: public:
@ -44,9 +46,6 @@ namespace CSMSettings {
UserSettings (UserSettings const &); //not implemented UserSettings (UserSettings const &); //not implemented
void operator= (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). /// Retrieves the settings file at all three levels (global, local and user).
void loadSettings (const QString &fileName); void loadSettings (const QString &fileName);
@ -55,9 +54,35 @@ namespace CSMSettings {
QString settingValue (const QString &settingKey); 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: private:
///add definitions to the settings specified in the page map
void addDefinitions();
void buildSettingModelDefaults(); 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 #endif // USERSETTINGS_HPP

View file

@ -236,10 +236,10 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to
mViewTotal (totalViews) mViewTotal (totalViews)
{ {
QString width = CSMSettings::UserSettings::instance().settingValue QString width = CSMSettings::UserSettings::instance().settingValue
("Window Size.Width"); ("Window Size/Width");
QString height = CSMSettings::UserSettings::instance().settingValue QString height = CSMSettings::UserSettings::instance().settingValue
("Window Size.Height"); ("Window Size/Height");
resize (width.toInt(), height.toInt()); resize (width.toInt(), height.toInt());

View file

@ -76,22 +76,9 @@ void CSVSettings::Dialog::buildPages()
mStackedWidget->addWidget (&dynamic_cast<QWidget &>(*(page))); mStackedWidget->addWidget (&dynamic_cast<QWidget &>(*(page)));
} }
addDebugPage();
resize (mStackedWidget->sizeHint()); 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) void CSVSettings::Dialog::buildPageListWidget (QWidget *centralWidget)
{ {
mPageListWidget = new QListWidget (centralWidget); mPageListWidget = new QListWidget (centralWidget);
@ -123,6 +110,7 @@ void CSVSettings::Dialog::show()
{ {
if (pages().isEmpty()) if (pages().isEmpty())
buildPages(); buildPages();
QPoint screenCenter = QApplication::desktop()->screenGeometry().center(); QPoint screenCenter = QApplication::desktop()->screenGeometry().center();
move (screenCenter - geometry().center()); move (screenCenter - geometry().center());

View file

@ -41,7 +41,6 @@ namespace CSVSettings {
void buildPages(); void buildPages();
void buildPageListWidget (QWidget *centralWidget); void buildPageListWidget (QWidget *centralWidget);
void buildStackedWidget (QWidget *centralWidget); void buildStackedWidget (QWidget *centralWidget);
void addDebugPage();
public slots: public slots:

View file

@ -44,11 +44,13 @@ namespace CSVSettings
void setHLayout() { mIsHorizontal = true; } void setHLayout() { mIsHorizontal = true; }
void setVLayout() { mIsHorizontal = false; } void setVLayout() { mIsHorizontal = false; }
///show / hide widgets (when stacked widget page changes)
void showWidgets(); void showWidgets();
void hideWidgets(); void hideWidgets();
private: private:
///functions which return the index for the next layout row / column
int getNextColumn() const; int getNextColumn() const;
int getNextRow() const; int getNextRow() const;

View file

@ -1,7 +1,6 @@
#ifndef CSVSETTINGS_PAGE_HPP #ifndef CSVSETTINGS_PAGE_HPP
#define CSVSETTINGS_PAGE_HPP #define CSVSETTINGS_PAGE_HPP
#include <QSizePolicy>
#include <QWidget> #include <QWidget>
#include <QMap> #include <QMap>
#include <QList> #include <QList>
@ -40,6 +39,7 @@ namespace CSVSettings
///and returns it. ///and returns it.
View *findView (const QString &page, const QString &setting) const; View *findView (const QString &page, const QString &setting) const;
///returns the list of views associated with the page
const QList <View *> &views () const { return mViews; } const QList <View *> &views () const { return mViews; }
private: private:

View file

@ -1,6 +1,3 @@
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGroupBox>
#include <QSpinBox> #include <QSpinBox>
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QAbstractSpinBox> #include <QAbstractSpinBox>

View file

@ -21,13 +21,19 @@ namespace CSVSettings
Page *parent); Page *parent);
protected: protected:
///virtual function called through View
void updateView (bool signalUpdate = true) const; void updateView (bool signalUpdate = true) const;
///construct a slider-based view
void buildSlider (CSMSettings::Setting *setting); void buildSlider (CSMSettings::Setting *setting);
///construct a spinbox-based view
void buildSpinBox (CSMSettings::Setting *setting); void buildSpinBox (CSMSettings::Setting *setting);
private slots: private slots:
///responds to valueChanged signals
void slotUpdateView (int value); void slotUpdateView (int value);
void slotUpdateView (double value); void slotUpdateView (double value);

View file

@ -14,8 +14,10 @@ namespace CSVSettings
public: public:
explicit ResizeableStackedWidget(QWidget *parent = 0); explicit ResizeableStackedWidget(QWidget *parent = 0);
///add a widget to the stacked widget
void addWidget(QWidget* pWidget); void addWidget(QWidget* pWidget);
///called whenever the stacked widget page is changed
void changePage (int, int); void changePage (int, int);
}; };
} }

View file

@ -57,7 +57,7 @@ void CSVSettings::SettingWindow::createConnections
foreach (const QString &key, proxyMap.keys()) foreach (const QString &key, proxyMap.keys())
{ {
QStringList keyPair = key.split('.'); QStringList keyPair = key.split('/');
if (keyPair.size() != 2) if (keyPair.size() != 2)
continue; continue;

View file

@ -8,7 +8,7 @@
namespace CSMSettings { namespace CSMSettings {
class Setting; class Setting;
class SettingManager; class UserSettings;
} }
namespace CSVSettings { namespace CSVSettings {
@ -23,25 +23,33 @@ namespace CSVSettings {
Q_OBJECT Q_OBJECT
PageList mPages; PageList mPages;
CSMSettings::SettingManager *mModel; CSMSettings::UserSettings *mModel;
public: public:
explicit SettingWindow(QWidget *parent = 0); 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); 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: protected:
virtual void closeEvent (QCloseEvent *event); virtual void closeEvent (QCloseEvent *event);
///construct the pages to be displayed in the dialog
void createPages(); void createPages();
///return the list of constructed pages
const PageList &pages() const { return mPages; } const PageList &pages() const { return mPages; }
///save settings from the GUI to file
void saveSettings(); void saveSettings();
private: private:
///create connections between settings (used for proxy settings)
void createConnections (const QList <CSMSettings::Setting *> &list); void createConnections (const QList <CSMSettings::Setting *> &list);
}; };
} }

View file

@ -1,6 +1,5 @@
#include "spinbox.hpp" #include "spinbox.hpp"
#include <QSpinBox>
#include <QLineEdit> #include <QLineEdit>
CSVSettings::SpinBox::SpinBox(QWidget *parent) CSVSettings::SpinBox::SpinBox(QWidget *parent)
@ -14,7 +13,7 @@ QString CSVSettings::SpinBox::textFromValue(int val) const
if (mValueList.isEmpty()) if (mValueList.isEmpty())
return QVariant (val).toString(); return QVariant (val).toString();
QString value = ""; QString value;
if (val < mValueList.size()) if (val < mValueList.size())
value = mValueList.at (val); value = mValueList.at (val);

View file

@ -16,15 +16,22 @@ namespace CSVSettings
public: public:
explicit SpinBox(QWidget *parent = 0); explicit SpinBox(QWidget *parent = 0);
void setObjectName (const QString &name); ///set the value displayed in the spin box
void setValue (const QString &value); 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); void setValueList (const QStringList &list);
///returns the pre-defined value list.
const QStringList &valueList() const { return mValueList; } const QStringList &valueList() const { return mValueList; }
protected: protected:
///converts an index value to corresponding text to be displayed
QString textFromValue (int val) const; QString textFromValue (int val) const;
///converts a text value to a corresponding index
int valueFromText (const QString &text) const; int valueFromText (const QString &text) const;
}; };
} }

View file

@ -20,6 +20,7 @@ namespace CSVSettings
protected: protected:
/// virtual function called through View
void updateView (bool signalUpdate = true) const; void updateView (bool signalUpdate = true) const;
protected slots: protected slots:

View file

@ -1,7 +1,8 @@
#include <QStringListModel> #include <QStandardItemModel>
#include <QSortFilterProxyModel>
#include <QStandardItem> #include <QStandardItem>
#include <QApplication> #include <QApplication>
#include <QItemSelectionModel>
#include <QStringListModel>
#include "view.hpp" #include "view.hpp"
#include "../../model/settings/support.hpp" #include "../../model/settings/support.hpp"
@ -14,7 +15,7 @@ CSVSettings::View::View(CSMSettings::Setting *setting,
: mDataModel(0), mParentPage (parent), : mDataModel(0), mParentPage (parent),
mHasFixedValues (!setting->declaredValues().isEmpty()), mHasFixedValues (!setting->declaredValues().isEmpty()),
mIsMultiValue (setting->isMultiValue()), mIsMultiValue (setting->isMultiValue()),
mViewKey (setting->page() + '.' + setting->name()), mViewKey (setting->page() + '/' + setting->name()),
mSerializable (setting->serializable()), mSerializable (setting->serializable()),
Frame(true, setting->name(), parent) Frame(true, setting->name(), parent)
{ {
@ -42,24 +43,22 @@ void CSVSettings::View::buildModel (const CSMSettings::Setting *setting)
void CSVSettings::View::buildFixedValueModel (const QStringList &values) 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); mDataModel = new QStringListModel (values, this);
} }
void CSVSettings::View::buildUpdatableValueModel (const QStringList &values) void CSVSettings::View::buildUpdatableValueModel (const QStringList &values)
{ {
//updateable models are standard item models because they support
//replacing entire columns
QList <QStandardItem *> itemList; QList <QStandardItem *> itemList;
foreach (const QString &value, values) foreach (const QString &value, values)
itemList.append (new QStandardItem(value)); itemList.append (new QStandardItem(value));
// QSortFilterProxyModel *filter = new QSortFilterProxyModel (this);
QStandardItemModel *model = new QStandardItemModel (this); QStandardItemModel *model = new QStandardItemModel (this);
model->appendColumn (itemList); model->appendColumn (itemList);
// filter->setSourceModel (model);
/* filter->setFilterRegExp ("*");
filter->setFilterKeyColumn (0);
filter->setFilterRole (Qt::DisplayRole);*/
mDataModel = model; mDataModel = model;
} }
@ -151,9 +150,6 @@ void CSVSettings::View::setSelectedValues (const QStringList &list,
} }
select (selection); select (selection);
//push changes to model side
//update the view if the selection was set from the model side, not by the //update the view if the selection was set from the model side, not by the
//user //user
if (doViewUpdate) if (doViewUpdate)
@ -192,7 +188,6 @@ bool CSVSettings::View::stringListsMatch (
QList <QStandardItem *> CSVSettings::View::toStandardItemList QList <QStandardItem *> CSVSettings::View::toStandardItemList
(const QStringList &list) const (const QStringList &list) const
{ {
QList <QStandardItem *> itemList; QList <QStandardItem *> itemList;
foreach (const QString &value, list) foreach (const QString &value, list)
@ -212,12 +207,12 @@ QString CSVSettings::View::value (int row) const
if (row > -1 && row < mDataModel->rowCount()) if (row > -1 && row < mDataModel->rowCount())
return mDataModel->data (mDataModel->index(row, 0)).toString(); return mDataModel->data (mDataModel->index(row, 0)).toString();
return ""; return QString();
} }
int CSVSettings::View::widgetWidth(int characterCount) const int CSVSettings::View::widgetWidth(int characterCount) const
{ {
QString widthToken = QString().fill ('P', characterCount); QString widthToken = QString().fill ('m', characterCount);
QFontMetrics fm (QApplication::font()); QFontMetrics fm (QApplication::font());
return (fm.width (widthToken)); return (fm.width (widthToken));

View file

@ -11,8 +11,6 @@ class QGroupBox;
class QStringList; class QStringList;
class QStandardItem; class QStandardItem;
class QItemSelection; class QItemSelection;
class QStringListModel;
class QStandardItemModel;
class QAbstractItemModel; class QAbstractItemModel;
class QItemSelectionModel; class QItemSelectionModel;
@ -42,17 +40,16 @@ namespace CSVSettings
///State indicating whether the view will allow multiple values ///State indicating whether the view will allow multiple values
bool mIsMultiValue; bool mIsMultiValue;
///'pagename.settingname' form of the view's id
QString mViewKey; QString mViewKey;
///indicates whether or not the setting is written to file
bool mSerializable; bool mSerializable;
public: public:
explicit View (CSMSettings::Setting *setting, Page *parent); 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. ///Returns the index / row of the passed value, -1 if not found.
int currentIndex () const; int currentIndex () const;

View file

@ -7,18 +7,19 @@
CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values,
const IconList &icons, const IconList &icons,
QUndoStack &undoStack, QUndoStack &undoStack,
const QString &settingKey, const QString &pageName,
const QString &settingName,
QObject *parent) QObject *parent)
: EnumDelegate (values, undoStack, parent), mDisplayMode (Mode_TextOnly), : EnumDelegate (values, undoStack, parent), mDisplayMode (Mode_TextOnly),
mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3), mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3),
mTextLeftOffset(8), mSettingKey (settingKey) mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName)
{ {
mTextAlignment.setAlignment (Qt::AlignLeft | Qt::AlignVCenter ); mTextAlignment.setAlignment (Qt::AlignLeft | Qt::AlignVCenter );
buildPixmaps(); buildPixmaps();
QString value = QString value =
CSMSettings::UserSettings::instance().settingValue (settingKey); CSMSettings::UserSettings::instance().settingValue (mSettingKey);
updateDisplayMode(value); updateDisplayMode(value);
} }
@ -140,7 +141,7 @@ CSVWorld::CommandDelegate *CSVWorld::DataDisplayDelegateFactory::makeDelegate (Q
QObject *parent) const QObject *parent) const
{ {
return new DataDisplayDelegate (mValues, mIcons, undoStack, "", parent); return new DataDisplayDelegate (mValues, mIcons, undoStack, "", "", parent);
} }

View file

@ -41,7 +41,8 @@ namespace CSVWorld
explicit DataDisplayDelegate (const ValueList & values, explicit DataDisplayDelegate (const ValueList & values,
const IconList & icons, const IconList & icons,
QUndoStack& undoStack, QUndoStack& undoStack,
const QString &settingKey, const QString &pageName,
const QString &settingName,
QObject *parent); QObject *parent);
~DataDisplayDelegate(); ~DataDisplayDelegate();

View file

@ -5,7 +5,7 @@
CSVWorld::IdTypeDelegate::IdTypeDelegate CSVWorld::IdTypeDelegate::IdTypeDelegate
(const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent) (const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent)
: DataDisplayDelegate (values, icons, undoStack, : DataDisplayDelegate (values, icons, undoStack,
"Display Format.Referenceable ID Type Display", "Display Format", "Referenceable ID Type Display",
parent) parent)
{} {}

View file

@ -11,7 +11,7 @@ CSVWorld::RecordStatusDelegate::RecordStatusDelegate(const ValueList& values,
const IconList & icons, const IconList & icons,
QUndoStack &undoStack, QObject *parent) QUndoStack &undoStack, QObject *parent)
: DataDisplayDelegate (values, icons, undoStack, : DataDisplayDelegate (values, icons, undoStack,
"Display Format.Record Status Display", "Display Format", "Record Status Display",
parent) parent)
{} {}

View file

@ -1,5 +0,0 @@
[Editor]
Record Status Display = Icon and Text
[Window Size]
Width = 640
Height = 480

7
files/opencs.ini Normal file
View file

@ -0,0 +1,7 @@
[Display%20Format]
Record%20Status%20Display=Icon Only
Referenceable%20ID%20Type%20Display=Text Only
[Window%20Size]
Height=900
Width=1440