mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-25 06:35:30 +00:00
Added new framework files
This commit is contained in:
parent
d3148555fa
commit
331df17b48
127
apps/opencs/model/settings/connector.cpp
Normal file
127
apps/opencs/model/settings/connector.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
#include "connector.hpp"
|
||||
#include "../../view/settings/view.hpp"
|
||||
#include "../../view/settings/page.hpp"
|
||||
|
||||
CSMSettings::Connector::Connector(CSVSettings::View *master,
|
||||
QObject *parent)
|
||||
: mMasterView (master), QObject(parent)
|
||||
{}
|
||||
|
||||
void CSMSettings::Connector::addSlaveView (CSVSettings::View *view,
|
||||
QList <QStringList> &masterProxyValues)
|
||||
{
|
||||
mSlaveViews.append (view);
|
||||
|
||||
mProxyListMap[view->viewKey()].append (masterProxyValues);
|
||||
}
|
||||
|
||||
QList <QStringList> CSMSettings::Connector::getSlaveViewValues() const
|
||||
{
|
||||
QList <QStringList> list;
|
||||
|
||||
foreach (const CSVSettings::View *view, mSlaveViews)
|
||||
list.append (view->selectedValues());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
bool CSMSettings::Connector::proxyListsMatch (
|
||||
const QList <QStringList> &list1,
|
||||
const QList <QStringList> &list2) const
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
for (int i = 0; i < list1.size(); i++)
|
||||
{
|
||||
success = stringListsMatch (list1.at(i), list2.at(i));
|
||||
|
||||
if (!success)
|
||||
break;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void CSMSettings::Connector::slotUpdateMaster() const
|
||||
{
|
||||
//list of the current values for each slave.
|
||||
QList <QStringList> slaveValueList = getSlaveViewValues();
|
||||
|
||||
int masterColumn = -1;
|
||||
|
||||
/*
|
||||
* A row in the master view is one of the values in the
|
||||
* master view's data model. This corresponds directly to the number of
|
||||
* values in a proxy list contained in the ProxyListMap member.
|
||||
* Thus, we iterate each "column" in the master proxy list
|
||||
* (one for each vlaue in the master. Each column represents
|
||||
* one master value's corresponding list of slave values. We examine
|
||||
* each master value's list, comparing it to the current slave value list,
|
||||
* stopping when we find a match using proxyListsMatch().
|
||||
*
|
||||
* If no match is found, clear the master view's value
|
||||
*/
|
||||
|
||||
for (int i = 0; i < mMasterView->rowCount(); i++)
|
||||
{
|
||||
QList <QStringList> proxyValueList;
|
||||
|
||||
foreach (const QString &settingKey, mProxyListMap.keys())
|
||||
{
|
||||
// append the proxy value list stored in the i'th column
|
||||
// for each setting key. A setting key is the id of the setting
|
||||
// in page.name format.
|
||||
proxyValueList.append (mProxyListMap.value(settingKey).at(i));
|
||||
}
|
||||
|
||||
if (proxyListsMatch (slaveValueList, proxyValueList))
|
||||
{
|
||||
masterColumn = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QString masterValue = mMasterView->value (masterColumn);
|
||||
mMasterView->setSelectedValue (masterValue);
|
||||
}
|
||||
|
||||
void CSMSettings::Connector::slotUpdateSlaves() const
|
||||
{
|
||||
int row = mMasterView->currentIndex();
|
||||
|
||||
if (row == -1)
|
||||
return;
|
||||
|
||||
//iterate the proxy lists for the chosen master index
|
||||
//and pass the list to each slave for updating
|
||||
for (int i = 0; i < mSlaveViews.size(); i++)
|
||||
{
|
||||
QList <QStringList> proxyList =
|
||||
mProxyListMap.value(mSlaveViews.at(i)->viewKey());
|
||||
|
||||
mSlaveViews.at(i)->setSelectedValues (proxyList.at(row));
|
||||
}
|
||||
}
|
||||
|
||||
bool CSMSettings::Connector::stringListsMatch (
|
||||
const QStringList &list1,
|
||||
const QStringList &list2) const
|
||||
{
|
||||
//returns a "sloppy" match, verifying that each list contains all the same
|
||||
//items, though not necessarily in the same order.
|
||||
|
||||
if (list1.size() != list2.size())
|
||||
return false;
|
||||
|
||||
QStringList tempList(list2);
|
||||
|
||||
//iterate each value in the list, removing one occurrence of the value in
|
||||
//the other list. If no corresponding value is found, test fails
|
||||
foreach (const QString &value, list1)
|
||||
{
|
||||
if (!tempList.contains(value))
|
||||
return false;
|
||||
|
||||
tempList.removeOne(value);
|
||||
}
|
||||
return true;
|
||||
}
|
55
apps/opencs/model/settings/connector.hpp
Normal file
55
apps/opencs/model/settings/connector.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef CSMSETTINGS_CONNECTOR_HPP
|
||||
#define CSMSETTINGS_CONNECTOR_HPP
|
||||
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QStringList>
|
||||
|
||||
#include "support.hpp"
|
||||
|
||||
namespace CSVSettings {
|
||||
class View;
|
||||
}
|
||||
|
||||
namespace CSMSettings {
|
||||
|
||||
class Connector : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
CSVSettings::View *mMasterView;
|
||||
|
||||
//map using the view pointer as a key to it's index value
|
||||
QList <CSVSettings::View *> mSlaveViews;
|
||||
|
||||
//list of proxy values for each master value.
|
||||
//value list order is indexed to the master value index.
|
||||
QMap < QString, QList <QStringList> > mProxyListMap;
|
||||
|
||||
public:
|
||||
explicit Connector(CSVSettings::View *master,
|
||||
QObject *parent = 0);
|
||||
|
||||
void setMasterView (CSVSettings::View *view);
|
||||
void addSlaveView (CSVSettings::View *view,
|
||||
QList <QStringList> &masterProxyValues);
|
||||
|
||||
private:
|
||||
|
||||
bool proxyListsMatch (const QList <QStringList> &list1,
|
||||
const QList <QStringList> &list2) const;
|
||||
|
||||
bool stringListsMatch (const QStringList &list1,
|
||||
const QStringList &list2) const;
|
||||
|
||||
QList <QStringList> getSlaveViewValues() const;
|
||||
|
||||
public slots:
|
||||
|
||||
void slotUpdateSlaves() const;
|
||||
void slotUpdateMaster() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CSMSETTINGS_CONNECTOR_HPP
|
281
apps/opencs/model/settings/setting.cpp
Normal file
281
apps/opencs/model/settings/setting.cpp
Normal file
@ -0,0 +1,281 @@
|
||||
#include "setting.hpp"
|
||||
#include "support.hpp"
|
||||
|
||||
CSMSettings::Setting::Setting()
|
||||
{
|
||||
buildDefaultSetting();
|
||||
}
|
||||
|
||||
CSMSettings::Setting::Setting(SettingType typ, const QString &settingName,
|
||||
const QString &pageName, const QStringList &values)
|
||||
: mIsEditorSetting (false)
|
||||
{
|
||||
buildDefaultSetting();
|
||||
|
||||
int vType = static_cast <int> (typ);
|
||||
|
||||
if ((vType % 2) == 0)
|
||||
setProperty (Property_IsMultiValue,
|
||||
QVariant(true).toString());
|
||||
else
|
||||
vType--;
|
||||
|
||||
setProperty (Property_ViewType, QVariant (vType / 2).toString());
|
||||
setProperty (Property_Page, pageName);
|
||||
setProperty (Property_Name, settingName);
|
||||
setProperty (Property_DeclaredValues, values);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::buildDefaultSetting()
|
||||
{
|
||||
int arrLen = sizeof(sPropertyDefaults) / sizeof (*sPropertyDefaults);
|
||||
|
||||
for (int i = 0; i < arrLen; i++)
|
||||
{
|
||||
QStringList propertyList;
|
||||
|
||||
if (i <Property_DefaultValues)
|
||||
propertyList.append (sPropertyDefaults[i]);
|
||||
|
||||
mProperties.append (propertyList);
|
||||
}
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::addProxy (const Setting *setting,
|
||||
const QStringList &vals)
|
||||
{
|
||||
if (serializable())
|
||||
setSerializable (false);
|
||||
|
||||
QList <QStringList> list;
|
||||
|
||||
foreach (const QString &val, vals)
|
||||
list << (QStringList() << val);
|
||||
|
||||
mProxies [setting->page() + '.' + setting->name()] = list;
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::addProxy (const Setting *setting,
|
||||
const QList <QStringList> &list)
|
||||
{
|
||||
if (serializable())
|
||||
setProperty (Property_Serializable, false);
|
||||
|
||||
mProxies [setting->page() + '.' + setting->name()] = list;
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setColumnSpan (int value)
|
||||
{
|
||||
setProperty (Property_ColumnSpan, value);
|
||||
}
|
||||
|
||||
int CSMSettings::Setting::columnSpan() const
|
||||
{
|
||||
return property (Property_ColumnSpan).at(0).toInt();
|
||||
}
|
||||
|
||||
QStringList CSMSettings::Setting::declaredValues() const
|
||||
{
|
||||
return property (Property_DeclaredValues);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setDefinedValues (QStringList list)
|
||||
{
|
||||
setProperty (Property_DefinedValues, list);
|
||||
}
|
||||
|
||||
QStringList CSMSettings::Setting::definedValues() const
|
||||
{
|
||||
return property (Property_DefinedValues);
|
||||
}
|
||||
|
||||
QStringList CSMSettings::Setting::property (SettingProperty prop) const
|
||||
{
|
||||
if (prop >= mProperties.size())
|
||||
return QStringList();
|
||||
|
||||
return mProperties.at(prop);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setDefaultValue (const QString &value)
|
||||
{
|
||||
setDefaultValues (QStringList() << value);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setDefaultValues (const QStringList &values)
|
||||
{
|
||||
setProperty (Property_DefaultValues, values);
|
||||
}
|
||||
|
||||
QStringList CSMSettings::Setting::defaultValues() const
|
||||
{
|
||||
return property (Property_DefaultValues);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setDelimiter (const QString &value)
|
||||
{
|
||||
setProperty (Property_Delimiter, value);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::delimiter() const
|
||||
{
|
||||
return property (Property_Delimiter).at(0);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setEditorSetting(bool state)
|
||||
{
|
||||
mIsEditorSetting = true;
|
||||
}
|
||||
|
||||
bool CSMSettings::Setting::isEditorSetting() const
|
||||
{
|
||||
return mIsEditorSetting;
|
||||
}
|
||||
void CSMSettings::Setting::setIsMultiLine (bool state)
|
||||
{
|
||||
setProperty (Property_IsMultiLine, state);
|
||||
}
|
||||
|
||||
bool CSMSettings::Setting::isMultiLine() const
|
||||
{
|
||||
return (property (Property_IsMultiLine).at(0) == "true");
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setIsMultiValue (bool state)
|
||||
{
|
||||
setProperty (Property_IsMultiValue, state);
|
||||
}
|
||||
|
||||
bool CSMSettings::Setting::isMultiValue() const
|
||||
{
|
||||
return (property (Property_IsMultiValue).at(0) == "true");
|
||||
}
|
||||
|
||||
const CSMSettings::ProxyValueMap &CSMSettings::Setting::proxyLists() const
|
||||
{
|
||||
return mProxies;
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setSerializable (bool state)
|
||||
{
|
||||
setProperty (Property_Serializable, state);
|
||||
}
|
||||
|
||||
bool CSMSettings::Setting::serializable() const
|
||||
{
|
||||
return (property (Property_Serializable).at(0) == "true");
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setName (const QString &value)
|
||||
{
|
||||
setProperty (Property_Name, value);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::name() const
|
||||
{
|
||||
return property (Property_Name).at(0);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setPage (const QString &value)
|
||||
{
|
||||
setProperty (Property_Page, value);
|
||||
}
|
||||
|
||||
QString CSMSettings::Setting::page() const
|
||||
{
|
||||
return property (Property_Page).at(0);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setRowSpan (const int value)
|
||||
{
|
||||
setProperty (Property_RowSpan, value);
|
||||
}
|
||||
|
||||
int CSMSettings::Setting::rowSpan () const
|
||||
{
|
||||
return property (Property_RowSpan).at(0).toInt();
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setViewType (int vType)
|
||||
{
|
||||
setProperty (Property_ViewType, vType);
|
||||
}
|
||||
|
||||
CSVSettings::ViewType CSMSettings::Setting::viewType() const
|
||||
{
|
||||
return static_cast <CSVSettings::ViewType>
|
||||
(property(Property_ViewType).at(0).toInt());
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setViewColumn (int value)
|
||||
{
|
||||
setProperty (Property_ViewColumn, value);
|
||||
}
|
||||
|
||||
int CSMSettings::Setting::viewColumn() const
|
||||
{
|
||||
return property (Property_ViewColumn).at(0).toInt();
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setViewLocation (int row, int column)
|
||||
{
|
||||
setViewRow (row);
|
||||
setViewColumn (column);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setViewRow (int value)
|
||||
{
|
||||
setProperty (Property_ViewRow, value);
|
||||
}
|
||||
|
||||
int CSMSettings::Setting::viewRow() const
|
||||
{
|
||||
return property (Property_ViewRow).at(0).toInt();
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setWidgetWidth (int value)
|
||||
{
|
||||
setProperty (Property_WidgetWidth, value);
|
||||
}
|
||||
|
||||
int CSMSettings::Setting::widgetWidth() const
|
||||
{
|
||||
return property (Property_WidgetWidth).at(0).toInt();
|
||||
}
|
||||
void CSMSettings::Setting::setProperty (SettingProperty prop, bool value)
|
||||
{
|
||||
setProperty (prop, QStringList() << QVariant (value).toString());
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setProperty (SettingProperty prop, int value)
|
||||
{
|
||||
setProperty (prop, QStringList() << QVariant (value).toString());
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setProperty (SettingProperty prop,
|
||||
const QString &value)
|
||||
{
|
||||
setProperty (prop, QStringList() << value);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setProperty (SettingProperty prop,
|
||||
const QStringList &value)
|
||||
{
|
||||
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;
|
||||
}
|
119
apps/opencs/model/settings/setting.hpp
Normal file
119
apps/opencs/model/settings/setting.hpp
Normal file
@ -0,0 +1,119 @@
|
||||
#ifndef CSMSETTINGS_SETTING_HPP
|
||||
#define CSMSETTINGS_SETTING_HPP
|
||||
|
||||
#include <QStringList>
|
||||
#include <QMap>
|
||||
#include "support.hpp"
|
||||
|
||||
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
|
||||
typedef QMap <QString, QList <QStringList> > ProxyValueMap;
|
||||
|
||||
class Setting
|
||||
{
|
||||
QList <QStringList> mProperties;
|
||||
QStringList mDefaults;
|
||||
|
||||
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());
|
||||
|
||||
void addProxy (const Setting *setting, const QStringList &vals);
|
||||
void addProxy (const Setting *setting, const QList <QStringList> &list);
|
||||
|
||||
const QList <QStringList> &properties() const { return mProperties; }
|
||||
const ProxyValueMap &proxies() const { return mProxies; }
|
||||
|
||||
void setColumnSpan (int value);
|
||||
int columnSpan() const;
|
||||
|
||||
void setDeclaredValues (QStringList list);
|
||||
QStringList declaredValues() const;
|
||||
|
||||
void setDefinedValues (QStringList list);
|
||||
QStringList definedValues() const;
|
||||
|
||||
void setDefaultValue (const QString &value);
|
||||
|
||||
void setDefaultValues (const QStringList &values);
|
||||
QStringList defaultValues() const;
|
||||
|
||||
void setDelimiter (const QString &value);
|
||||
QString delimiter() const;
|
||||
|
||||
void setEditorSetting (bool state);
|
||||
bool isEditorSetting() const;
|
||||
|
||||
void setIsMultiLine (bool state);
|
||||
bool isMultiLine() const;
|
||||
|
||||
void setIsMultiValue (bool state);
|
||||
bool isMultiValue() const;
|
||||
|
||||
void setName (const QString &value);
|
||||
QString name() const;
|
||||
|
||||
void setPage (const QString &value);
|
||||
QString page() const;
|
||||
|
||||
void setRowSpan (const int value);
|
||||
int rowSpan() const;
|
||||
|
||||
const ProxyValueMap &proxyLists() const;
|
||||
|
||||
void setSerializable (bool state);
|
||||
bool serializable() const;
|
||||
|
||||
void setViewColumn (int value);
|
||||
int viewColumn() const;
|
||||
|
||||
void setViewLocation (int row = -1, int column = -1);
|
||||
|
||||
void setViewRow (int value);
|
||||
int viewRow() const;
|
||||
|
||||
void setViewType (int vType);
|
||||
CSVSettings::ViewType viewType() const;
|
||||
|
||||
void setWidgetWidth (int value);
|
||||
int widgetWidth() const;
|
||||
|
||||
///returns the specified property value
|
||||
QStringList property (SettingProperty prop) const;
|
||||
|
||||
///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, const QString &value);
|
||||
void setProperty (SettingProperty prop, const QStringList &value);
|
||||
|
||||
void addProxy (Setting* setting,
|
||||
QMap <QString, QStringList> &proxyMap);
|
||||
|
||||
protected:
|
||||
void buildDefaultSetting();
|
||||
};
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(CSMSettings::Setting)
|
||||
|
||||
QDataStream &operator <<(QDataStream &stream, const CSMSettings::Setting& setting);
|
||||
QDataStream &operator >>(QDataStream &stream, CSMSettings::Setting& setting);
|
||||
|
||||
#endif // CSMSETTINGS_SETTING_HPP
|
330
apps/opencs/model/settings/settingmanager.cpp
Normal file
330
apps/opencs/model/settings/settingmanager.cpp
Normal file
@ -0,0 +1,330 @@
|
||||
#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,
|
||||
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 <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 §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::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;
|
||||
}
|
82
apps/opencs/model/settings/settingmanager.hpp
Normal file
82
apps/opencs/model/settings/settingmanager.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
#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,
|
||||
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 <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:
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
}
|
||||
#endif // CSMSETTINGS_SETTINGMANAGER_HPP
|
91
apps/opencs/view/settings/booleanview.cpp
Normal file
91
apps/opencs/view/settings/booleanview.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QRadioButton>
|
||||
#include <QGroupBox>
|
||||
|
||||
#include <QAbstractButton>
|
||||
|
||||
#include "booleanview.hpp"
|
||||
#include "../../model/settings/setting.hpp"
|
||||
|
||||
CSVSettings::BooleanView::BooleanView (CSMSettings::Setting *setting,
|
||||
Page *parent)
|
||||
: View (setting, parent)
|
||||
{
|
||||
foreach (const QString &value, setting->declaredValues())
|
||||
{
|
||||
QAbstractButton *button = 0;
|
||||
|
||||
if (isMultiValue())
|
||||
button = new QCheckBox (value, this);
|
||||
else
|
||||
button = new QRadioButton (value, this);
|
||||
|
||||
connect (button, SIGNAL (clicked (bool)),
|
||||
this, SLOT (slotToggled (bool)));
|
||||
|
||||
button->setObjectName (value);
|
||||
|
||||
addWidget (button);
|
||||
|
||||
mButtons[value] = button;
|
||||
}
|
||||
}
|
||||
|
||||
void CSVSettings::BooleanView::slotToggled (bool state)
|
||||
{
|
||||
//test only for true to avoid multiple selection updates with radiobuttons
|
||||
if (!isMultiValue() && !state)
|
||||
return;
|
||||
|
||||
QStringList values;
|
||||
|
||||
foreach (QString key, mButtons.keys())
|
||||
{
|
||||
if (mButtons.value(key)->isChecked())
|
||||
values.append (key);
|
||||
}
|
||||
setSelectedValues (values, false);
|
||||
|
||||
View::updateView();
|
||||
}
|
||||
|
||||
void CSVSettings::BooleanView::updateView (bool signalUpdate) const
|
||||
{
|
||||
|
||||
QStringList values = selectedValues();
|
||||
|
||||
foreach (const QString &buttonName, mButtons.keys())
|
||||
{
|
||||
QAbstractButton *button = mButtons[buttonName];
|
||||
|
||||
//if the value is not found in the list, the widget is checked false
|
||||
bool buttonValue = values.contains(buttonName);
|
||||
|
||||
//skip if the butotn value will not change
|
||||
if (button->isChecked() == buttonValue)
|
||||
continue;
|
||||
|
||||
//disable autoexclusive if it's enabled and we're setting
|
||||
//the button value to false
|
||||
bool switchExclusive = (!buttonValue && button->autoExclusive());
|
||||
|
||||
if (switchExclusive)
|
||||
button->setAutoExclusive (false);
|
||||
|
||||
button->setChecked (buttonValue);
|
||||
|
||||
if (switchExclusive)
|
||||
button->setAutoExclusive(true);
|
||||
}
|
||||
View::updateView (signalUpdate);
|
||||
}
|
||||
|
||||
CSVSettings::BooleanView *CSVSettings::BooleanViewFactory::createView
|
||||
(CSMSettings::Setting *setting,
|
||||
Page *parent)
|
||||
{
|
||||
return new BooleanView (setting, parent);
|
||||
}
|
44
apps/opencs/view/settings/booleanview.hpp
Normal file
44
apps/opencs/view/settings/booleanview.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef CSVSETTINGS_BOOLEANVIEW_HPP
|
||||
#define CSVSETTINGS_BOOELANVIEW_HPP
|
||||
|
||||
#include <QWidget>
|
||||
#include <QAbstractButton>
|
||||
|
||||
#include "view.hpp"
|
||||
#include "../../model/settings/support.hpp"
|
||||
|
||||
class QStringListModel;
|
||||
|
||||
namespace CSVSettings
|
||||
{
|
||||
class BooleanView : public View
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QMap <QString, QAbstractButton *> mButtons;
|
||||
|
||||
public:
|
||||
explicit BooleanView (CSMSettings::Setting *setting,
|
||||
Page *parent);
|
||||
|
||||
protected:
|
||||
void updateView (bool signalUpdate = true) const;
|
||||
|
||||
private slots:
|
||||
void slotToggled (bool state);
|
||||
};
|
||||
|
||||
class BooleanViewFactory : public QObject, public IViewFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BooleanViewFactory (QWidget *parent = 0)
|
||||
: QObject (parent)
|
||||
{}
|
||||
|
||||
BooleanView *createView (CSMSettings::Setting *setting,
|
||||
Page *parent);
|
||||
};
|
||||
}
|
||||
#endif // CSVSETTINGS_BOOLEANVIEW_HPP
|
132
apps/opencs/view/settings/dialog.cpp
Normal file
132
apps/opencs/view/settings/dialog.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
#include "dialog.hpp"
|
||||
|
||||
#include <QListWidgetItem>
|
||||
#include <QApplication>
|
||||
#include <QWidget>
|
||||
#include <QStackedWidget>
|
||||
#include <QtGui>
|
||||
|
||||
#include "../../model/settings/usersettings.hpp"
|
||||
|
||||
#include "page.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include <QSplitter>
|
||||
|
||||
#include <QTreeView>
|
||||
#include <QListView>
|
||||
#include <QTableView>
|
||||
|
||||
#include <QStandardItemModel>
|
||||
#include <QStandardItem>
|
||||
|
||||
CSVSettings::Dialog::Dialog(QMainWindow *parent)
|
||||
: mStackedWidget (0), mDebugMode (false), SettingWindow (parent)
|
||||
{
|
||||
setWindowTitle(QString::fromUtf8 ("User Settings"));
|
||||
|
||||
setupDialog();
|
||||
|
||||
connect (mPageListWidget,
|
||||
SIGNAL (currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
|
||||
this,
|
||||
SLOT (slotChangePage (QListWidgetItem*, QListWidgetItem*)));
|
||||
}
|
||||
|
||||
void CSVSettings::Dialog::slotChangePage
|
||||
(QListWidgetItem *cur, QListWidgetItem *prev)
|
||||
{
|
||||
mStackedWidget->changePage
|
||||
(mPageListWidget->row (cur), mPageListWidget->row (prev));
|
||||
|
||||
layout()->activate();
|
||||
setFixedSize(minimumSizeHint());
|
||||
}
|
||||
|
||||
void CSVSettings::Dialog::setupDialog()
|
||||
{
|
||||
//create central widget with it's layout and immediate children
|
||||
QWidget *centralWidget = new QGroupBox (this);
|
||||
|
||||
centralWidget->setLayout (new QHBoxLayout());
|
||||
centralWidget->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
setCentralWidget (centralWidget);
|
||||
setDockOptions (QMainWindow::AllowNestedDocks);
|
||||
|
||||
buildPageListWidget (centralWidget);
|
||||
buildStackedWidget (centralWidget);
|
||||
}
|
||||
|
||||
void CSVSettings::Dialog::buildPages()
|
||||
{
|
||||
SettingWindow::createPages ();
|
||||
|
||||
QFontMetrics fm (QApplication::font());
|
||||
|
||||
foreach (Page *page, SettingWindow::pages())
|
||||
{
|
||||
QString pageName = page->objectName();
|
||||
|
||||
int textWidth = fm.width(pageName);
|
||||
|
||||
new QListWidgetItem (pageName, mPageListWidget);
|
||||
mPageListWidget->setFixedWidth (textWidth + 50);
|
||||
|
||||
mStackedWidget->addWidget (&dynamic_cast<QWidget &>(*(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);
|
||||
mPageListWidget->setMinimumWidth(50);
|
||||
mPageListWidget->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||
|
||||
mPageListWidget->setSelectionBehavior (QAbstractItemView::SelectItems);
|
||||
|
||||
centralWidget->layout()->addWidget(mPageListWidget);
|
||||
}
|
||||
|
||||
void CSVSettings::Dialog::buildStackedWidget (QWidget *centralWidget)
|
||||
{
|
||||
mStackedWidget = new ResizeableStackedWidget (centralWidget);
|
||||
|
||||
centralWidget->layout()->addWidget (mStackedWidget);
|
||||
}
|
||||
|
||||
void CSVSettings::Dialog::closeEvent (QCloseEvent *event)
|
||||
{
|
||||
//SettingWindow::closeEvent() must be called first to ensure
|
||||
//model is updated
|
||||
SettingWindow::closeEvent (event);
|
||||
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
void CSVSettings::Dialog::show()
|
||||
{
|
||||
if (pages().isEmpty())
|
||||
buildPages();
|
||||
|
||||
QPoint screenCenter = QApplication::desktop()->screenGeometry().center();
|
||||
|
||||
move (screenCenter - geometry().center());
|
||||
|
||||
QWidget::show();
|
||||
}
|
55
apps/opencs/view/settings/dialog.hpp
Normal file
55
apps/opencs/view/settings/dialog.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef CSVSETTINGS_DIALOG_H
|
||||
#define CSVSETTINGS_DIALOG_H
|
||||
|
||||
#include "settingwindow.hpp"
|
||||
#include "resizeablestackedwidget.hpp"
|
||||
#include <QStandardItem>
|
||||
|
||||
class QStackedWidget;
|
||||
class QListWidget;
|
||||
class QListWidgetItem;
|
||||
|
||||
namespace CSVSettings {
|
||||
|
||||
class Page;
|
||||
|
||||
class Dialog : public SettingWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QListWidget *mPageListWidget;
|
||||
ResizeableStackedWidget *mStackedWidget;
|
||||
bool mDebugMode;
|
||||
|
||||
public:
|
||||
|
||||
explicit Dialog (QMainWindow *parent = 0);
|
||||
|
||||
///Enables setting debug mode. When the dialog opens, a page is created
|
||||
///which displays the SettingModel's contents in a Tree view.
|
||||
void enableDebugMode (bool state, QStandardItemModel *model = 0);
|
||||
|
||||
protected:
|
||||
|
||||
/// Settings are written on close
|
||||
void closeEvent (QCloseEvent *event);
|
||||
|
||||
void setupDialog();
|
||||
|
||||
private:
|
||||
|
||||
void buildPages();
|
||||
void buildPageListWidget (QWidget *centralWidget);
|
||||
void buildStackedWidget (QWidget *centralWidget);
|
||||
void addDebugPage();
|
||||
|
||||
public slots:
|
||||
|
||||
void show();
|
||||
|
||||
private slots:
|
||||
|
||||
void slotChangePage (QListWidgetItem *, QListWidgetItem *);
|
||||
};
|
||||
}
|
||||
#endif // CSVSETTINGS_DIALOG_H
|
103
apps/opencs/view/settings/frame.cpp
Normal file
103
apps/opencs/view/settings/frame.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
#include "frame.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
const QString CSVSettings::Frame::sInvisibleBoxStyle =
|
||||
QString::fromUtf8("Frame { border:2px; padding 2px; margin: 2px;}");
|
||||
|
||||
CSVSettings::Frame::Frame (bool isVisible, const QString &title,
|
||||
QWidget *parent)
|
||||
: mIsHorizontal (true), mLayout (new SettingLayout()),
|
||||
QGroupBox (title, parent)
|
||||
{
|
||||
setFlat (true);
|
||||
mVisibleBoxStyle = styleSheet();
|
||||
|
||||
if (!isVisible)
|
||||
setStyleSheet (sInvisibleBoxStyle);
|
||||
|
||||
setLayout (mLayout);
|
||||
}
|
||||
|
||||
void CSVSettings::Frame::hideWidgets()
|
||||
{
|
||||
for (int i = 0; i < children().size(); i++)
|
||||
{
|
||||
QObject *obj = children().at(i);
|
||||
|
||||
Frame *widgFrame = dynamic_cast <Frame *> (obj);
|
||||
|
||||
if (widgFrame)
|
||||
{
|
||||
widgFrame->hideWidgets();
|
||||
continue;
|
||||
}
|
||||
|
||||
QWidget *widg = static_cast <QWidget *> (obj);
|
||||
if (widg->property("sizePolicy").isValid())
|
||||
widg->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Ignored);
|
||||
}
|
||||
|
||||
layout()->activate();
|
||||
setFixedSize(minimumSizeHint());
|
||||
|
||||
}
|
||||
|
||||
void CSVSettings::Frame::showWidgets()
|
||||
{
|
||||
for (int i = 0; i < children().size(); i++)
|
||||
{
|
||||
QObject *obj = children().at(i);
|
||||
|
||||
Frame *widgFrame = dynamic_cast <Frame *> (obj);
|
||||
|
||||
if (widgFrame)
|
||||
{
|
||||
widgFrame->showWidgets();
|
||||
continue;
|
||||
}
|
||||
|
||||
QWidget *widg = static_cast <QWidget *> (obj);
|
||||
|
||||
if (widg->property("sizePolicy").isValid())
|
||||
widg->setSizePolicy
|
||||
(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
}
|
||||
layout()->activate();
|
||||
setFixedSize(minimumSizeHint());
|
||||
}
|
||||
|
||||
void CSVSettings::Frame::addWidget (QWidget *widget, int row, int column,
|
||||
int rowSpan, int columnSpan)
|
||||
{
|
||||
if (row == -1)
|
||||
row = getNextRow();
|
||||
|
||||
if (column == -1)
|
||||
column = getNextColumn();
|
||||
|
||||
mLayout->addWidget (widget, row, column, rowSpan, columnSpan);
|
||||
//, Qt::AlignLeft | Qt::AlignTop);
|
||||
|
||||
widget->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Ignored);
|
||||
}
|
||||
|
||||
int CSVSettings::Frame::getNextRow () const
|
||||
{
|
||||
int row = mLayout->rowCount();
|
||||
|
||||
if (mIsHorizontal && row > 0)
|
||||
row--;
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
int CSVSettings::Frame::getNextColumn () const
|
||||
{
|
||||
int column = 0;
|
||||
|
||||
if (mIsHorizontal)
|
||||
column = mLayout->columnCount();
|
||||
|
||||
return column;
|
||||
}
|
58
apps/opencs/view/settings/frame.hpp
Normal file
58
apps/opencs/view/settings/frame.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef CSVSETTINGS_FRAME_HPP
|
||||
#define CSVSETTINGS_FRAME_HPP
|
||||
|
||||
#include <QSizePolicy>
|
||||
#include <QGroupBox>
|
||||
#include <QGridLayout>
|
||||
#include "../../model/settings/support.hpp"
|
||||
|
||||
namespace CSVSettings
|
||||
{
|
||||
class SettingLayout : public QGridLayout
|
||||
{
|
||||
public:
|
||||
explicit SettingLayout (QWidget *parent = 0)
|
||||
: QGridLayout (parent)
|
||||
{
|
||||
setContentsMargins(0,0,0,0);
|
||||
setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
}
|
||||
};
|
||||
|
||||
/// Custom implementation of QGroupBox to act as a base for view classes
|
||||
class Frame : public QGroupBox
|
||||
{
|
||||
static const QString sInvisibleBoxStyle;
|
||||
|
||||
QString mVisibleBoxStyle;
|
||||
|
||||
bool mIsHorizontal;
|
||||
|
||||
SettingLayout *mLayout;
|
||||
|
||||
public:
|
||||
explicit Frame (bool isVisible, const QString &title = "",
|
||||
QWidget *parent = 0);
|
||||
|
||||
///Adds a widget to the grid layout, setting the position
|
||||
///relative to the last added widgets, or absolutely for positive
|
||||
///row / column values
|
||||
void addWidget (QWidget *widget, int row = -1, int column = -1,
|
||||
int rowSpan = 1, int columnSpan = 1);
|
||||
|
||||
///Force the grid to lay out in horizontal or vertical alignments
|
||||
void setHLayout() { mIsHorizontal = true; }
|
||||
void setVLayout() { mIsHorizontal = false; }
|
||||
|
||||
void showWidgets();
|
||||
void hideWidgets();
|
||||
|
||||
private:
|
||||
|
||||
int getNextColumn() const;
|
||||
int getNextRow() const;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CSVSETTINGS_FRAME_HPP
|
106
apps/opencs/view/settings/listview.cpp
Normal file
106
apps/opencs/view/settings/listview.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
#include "listview.hpp"
|
||||
#include "../../model/settings/setting.hpp"
|
||||
|
||||
#include <QListView>
|
||||
#include <QComboBox>
|
||||
#include <QStringListModel>
|
||||
|
||||
CSVSettings::ListView::ListView(CSMSettings::Setting *setting,
|
||||
Page *parent)
|
||||
: mComboBox (0), mAbstractItemView (0), View(setting, parent)
|
||||
{
|
||||
QWidget *widget =
|
||||
buildWidget(setting->isMultiLine(), setting->widgetWidth());
|
||||
|
||||
addWidget (widget, setting->viewRow(), setting->viewColumn());
|
||||
|
||||
if (mComboBox)
|
||||
buildComboBoxModel();
|
||||
|
||||
else if (mAbstractItemView)
|
||||
buildAbstractItemViewModel();
|
||||
}
|
||||
|
||||
void CSVSettings::ListView::buildComboBoxModel()
|
||||
{
|
||||
mComboBox->setModel (dataModel());
|
||||
mComboBox->setModelColumn (0);
|
||||
mComboBox->view()->setSelectionModel (selectionModel());
|
||||
|
||||
int curIdx = -1;
|
||||
|
||||
if (!selectionModel()->selection().isEmpty())
|
||||
curIdx = selectionModel()->selectedIndexes().at(0).row();
|
||||
|
||||
mComboBox->setCurrentIndex (curIdx);
|
||||
|
||||
connect (mComboBox, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(emitItemViewUpdate(int)));
|
||||
}
|
||||
|
||||
void CSVSettings::ListView::buildAbstractItemViewModel()
|
||||
{
|
||||
mAbstractItemView->setModel (dataModel());
|
||||
mAbstractItemView->setSelectionModel (selectionModel());
|
||||
|
||||
//connection needs to go here for list view update to signal to
|
||||
//the outside
|
||||
}
|
||||
|
||||
void CSVSettings::ListView::emitItemViewUpdate (int idx)
|
||||
{
|
||||
emit viewUpdated (objectName(), selectedValues());
|
||||
}
|
||||
|
||||
QWidget *CSVSettings::ListView::buildWidget(bool isMultiLine, int width)
|
||||
{
|
||||
QWidget *widget = 0;
|
||||
|
||||
if (isMultiLine)
|
||||
{
|
||||
mAbstractItemView = new QListView (this);
|
||||
widget = mAbstractItemView;
|
||||
|
||||
if (width > 0)
|
||||
widget->setFixedWidth (widgetWidth (width));
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboBox = new QComboBox (this);
|
||||
widget = mComboBox;
|
||||
|
||||
if (width > 0)
|
||||
mComboBox->setMinimumContentsLength (width);
|
||||
}
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
void CSVSettings::ListView::showEvent ( QShowEvent * event )
|
||||
{
|
||||
View::showEvent (event);
|
||||
}
|
||||
|
||||
void CSVSettings::ListView::updateView (bool signalUpdate) const
|
||||
{
|
||||
QStringList values = selectedValues();
|
||||
|
||||
if (mComboBox)
|
||||
{
|
||||
int idx = -1;
|
||||
|
||||
if (values.size() > 0)
|
||||
idx = (mComboBox->findText(values.at(0)));
|
||||
|
||||
mComboBox->setCurrentIndex (idx);
|
||||
}
|
||||
|
||||
View::updateView (signalUpdate);
|
||||
}
|
||||
|
||||
CSVSettings::ListView *CSVSettings::ListViewFactory::createView
|
||||
(CSMSettings::Setting *setting,
|
||||
Page *parent)
|
||||
{
|
||||
return new ListView(setting, parent);
|
||||
}
|
63
apps/opencs/view/settings/listview.hpp
Normal file
63
apps/opencs/view/settings/listview.hpp
Normal file
@ -0,0 +1,63 @@
|
||||
#ifndef CSVSETTINGS_LISTVIEW_HPP
|
||||
#define CSVSETTINGS_LISTVIEW_HPP
|
||||
|
||||
#include "view.hpp"
|
||||
|
||||
|
||||
class QStringListModel;
|
||||
class QComboBox;
|
||||
class QAbstractItemView;
|
||||
|
||||
namespace CSVSettings
|
||||
{
|
||||
class ListView : public View
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QAbstractItemView *mAbstractItemView;
|
||||
QComboBox *mComboBox;
|
||||
|
||||
public:
|
||||
explicit ListView (CSMSettings::Setting *setting,
|
||||
Page *parent);
|
||||
|
||||
protected:
|
||||
|
||||
void updateView (bool signalUpdate = true) const;
|
||||
void showEvent ( QShowEvent * event );
|
||||
|
||||
///Receives signal from widget and signals viwUpdated()
|
||||
void slotTextEdited (QString value);
|
||||
|
||||
private:
|
||||
|
||||
///Helper function to construct a model for an AbstractItemView
|
||||
void buildAbstractItemViewModel();
|
||||
|
||||
///Helper function to construct a model for a combobox
|
||||
void buildComboBoxModel();
|
||||
|
||||
///Helper function to build the view widget
|
||||
QWidget *buildWidget (bool isMultiLine, int width);
|
||||
|
||||
private slots:
|
||||
|
||||
///Receives updates from single-select widgets (like combobox) and
|
||||
///signals viewUpdated with the selected values.
|
||||
void emitItemViewUpdate (int idx);
|
||||
};
|
||||
|
||||
class ListViewFactory : public QObject, public IViewFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ListViewFactory (QWidget *parent = 0)
|
||||
: QObject (parent)
|
||||
{}
|
||||
|
||||
ListView *createView (CSMSettings::Setting *setting,
|
||||
Page *parent);
|
||||
};
|
||||
}
|
||||
#endif // CSVSETTINGS_LISTVIEW_HPP
|
88
apps/opencs/view/settings/page.cpp
Normal file
88
apps/opencs/view/settings/page.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include "page.hpp"
|
||||
#include "view.hpp"
|
||||
#include "booleanview.hpp"
|
||||
#include "textview.hpp"
|
||||
#include "listview.hpp"
|
||||
|
||||
#include "../../model/settings/usersettings.hpp"
|
||||
#include "../../model/settings/connector.hpp"
|
||||
#include "settingwindow.hpp"
|
||||
|
||||
QMap <CSVSettings::ViewType, CSVSettings::IViewFactory *>
|
||||
CSVSettings::Page::mViewFactories;
|
||||
|
||||
CSVSettings::Page::Page(const QString &pageName,
|
||||
QList <CSMSettings::Setting *> settingList,
|
||||
SettingWindow *parent) :
|
||||
mParent(parent), mIsEditorPage (false), Frame(false, "", parent)
|
||||
{
|
||||
setObjectName (pageName);
|
||||
|
||||
if (mViewFactories.size() == 0)
|
||||
buildFactories();
|
||||
|
||||
setVLayout();
|
||||
setupViews (settingList);
|
||||
}
|
||||
|
||||
void CSVSettings::Page::setupViews
|
||||
(QList <CSMSettings::Setting *> &settingList)
|
||||
{
|
||||
foreach (CSMSettings::Setting *setting, settingList)
|
||||
addView (setting);
|
||||
}
|
||||
|
||||
void CSVSettings::Page::addView (CSMSettings::Setting *setting)
|
||||
{
|
||||
if (setting->viewType() == ViewType_Undefined)
|
||||
return;
|
||||
|
||||
View *view = mViewFactories[setting->viewType()]->createView(setting, this);
|
||||
|
||||
if (!view)
|
||||
return;
|
||||
|
||||
mViews.append (view);
|
||||
|
||||
addWidget (view, setting->viewRow(), setting->viewColumn(),
|
||||
setting->rowSpan(), setting->columnSpan() );
|
||||
|
||||
//if this page is an editor page, connect each of it's views up to the
|
||||
//UserSettings singleton for signaling back to OpenCS
|
||||
if (setting->isEditorSetting()) {
|
||||
connect (view, SIGNAL (viewUpdated(const QString&, const QStringList&)),
|
||||
&CSMSettings::UserSettings::instance(),
|
||||
SIGNAL (userSettingUpdated (const QString &, const QStringList &)));
|
||||
}
|
||||
}
|
||||
|
||||
CSVSettings::View *CSVSettings::Page::findView (const QString &page,
|
||||
const QString &setting) const
|
||||
{
|
||||
|
||||
//if this is not the page we're looking for,
|
||||
//appeal to the parent setting window to find the appropriate view
|
||||
if (page != objectName())
|
||||
return mParent->findView (page, setting);
|
||||
|
||||
//otherwise, return the matching view
|
||||
for (int i = 0; i < mViews.size(); i++)
|
||||
{
|
||||
View *view = mViews.at(i);
|
||||
|
||||
if (view->parentPage()->objectName() != page)
|
||||
continue;
|
||||
|
||||
if (view->objectName() == setting)
|
||||
return view;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CSVSettings::Page::buildFactories()
|
||||
{
|
||||
mViewFactories[ViewType_Boolean] = new BooleanViewFactory (this);
|
||||
mViewFactories[ViewType_Text] = new TextViewFactory (this);
|
||||
mViewFactories[ViewType_List] = new ListViewFactory (this);
|
||||
}
|
54
apps/opencs/view/settings/page.hpp
Normal file
54
apps/opencs/view/settings/page.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef CSVSETTINGS_PAGE_HPP
|
||||
#define CSVSETTINGS_PAGE_HPP
|
||||
|
||||
#include <QSizePolicy>
|
||||
#include <QWidget>
|
||||
#include <QMap>
|
||||
#include <QList>
|
||||
|
||||
#include "frame.hpp"
|
||||
|
||||
#include "../../model/settings/support.hpp"
|
||||
|
||||
namespace CSMSettings { class Setting; }
|
||||
|
||||
namespace CSVSettings
|
||||
{
|
||||
class View;
|
||||
class IViewFactory;
|
||||
class SettingWindow;
|
||||
|
||||
class Page : public Frame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QList<View *> mViews;
|
||||
SettingWindow *mParent;
|
||||
static QMap <ViewType, IViewFactory *> mViewFactories;
|
||||
bool mIsEditorPage;
|
||||
|
||||
public:
|
||||
explicit Page(const QString &pageName,
|
||||
QList <CSMSettings::Setting *> settingList,
|
||||
SettingWindow *parent);
|
||||
|
||||
///Creates a new view based on the passed setting and adds it to
|
||||
///the page.
|
||||
void addView (CSMSettings::Setting *setting);
|
||||
|
||||
///Iterates the views created for this page based on the passed setting
|
||||
///and returns it.
|
||||
View *findView (const QString &page, const QString &setting) const;
|
||||
|
||||
const QList <View *> &views () const { return mViews; }
|
||||
|
||||
private:
|
||||
|
||||
///Creates views based on the passed setting list
|
||||
void setupViews (QList <CSMSettings::Setting *> &settingList);
|
||||
|
||||
///Creates factory objects for view construction
|
||||
void buildFactories();
|
||||
};
|
||||
}
|
||||
#endif // CSVSETTINGS_PAGE_HPP
|
40
apps/opencs/view/settings/resizeablestackedwidget.cpp
Normal file
40
apps/opencs/view/settings/resizeablestackedwidget.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include "resizeablestackedwidget.hpp"
|
||||
#include "page.hpp"
|
||||
|
||||
#include <QListWidgetItem>
|
||||
|
||||
CSVSettings::ResizeableStackedWidget::ResizeableStackedWidget(QWidget *parent) :
|
||||
QStackedWidget(parent)
|
||||
{}
|
||||
|
||||
void CSVSettings::ResizeableStackedWidget::addWidget(QWidget* pWidget)
|
||||
{
|
||||
QStackedWidget::addWidget(pWidget);
|
||||
}
|
||||
|
||||
void CSVSettings::ResizeableStackedWidget::changePage
|
||||
(int current, int previous)
|
||||
{
|
||||
if (current == previous)
|
||||
return;
|
||||
|
||||
Page *prevPage = 0;
|
||||
Page *curPage = 0;
|
||||
|
||||
if (previous > -1)
|
||||
prevPage = static_cast <Page *> (widget (previous));
|
||||
|
||||
if (current > -1)
|
||||
curPage = static_cast <Page *> (widget (current));
|
||||
|
||||
if (prevPage)
|
||||
prevPage->hideWidgets();
|
||||
|
||||
if (curPage)
|
||||
curPage->showWidgets();
|
||||
|
||||
layout()->activate();
|
||||
setFixedSize(minimumSizeHint());
|
||||
|
||||
setCurrentIndex (current);
|
||||
}
|
23
apps/opencs/view/settings/resizeablestackedwidget.hpp
Normal file
23
apps/opencs/view/settings/resizeablestackedwidget.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef CSVSETTINGS_RESIZEABLESTACKEDWIDGET_HPP
|
||||
#define CSVSETTINGS_RESIZEABLESTACKEDWIDGET_HPP
|
||||
|
||||
#include <QStackedWidget>
|
||||
|
||||
class QListWidgetItem;
|
||||
|
||||
namespace CSVSettings
|
||||
{
|
||||
class ResizeableStackedWidget : public QStackedWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ResizeableStackedWidget(QWidget *parent = 0);
|
||||
|
||||
void addWidget(QWidget* pWidget);
|
||||
|
||||
void changePage (int, int);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CSVSETTINGS_RESIZEABLESTACKEDWIDGET_HPP
|
114
apps/opencs/view/settings/settingwindow.cpp
Normal file
114
apps/opencs/view/settings/settingwindow.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
|
||||
#include "../../model/settings/setting.hpp"
|
||||
#include "../../model/settings/connector.hpp"
|
||||
#include "../../model/settings/usersettings.hpp"
|
||||
#include "settingwindow.hpp"
|
||||
#include "page.hpp"
|
||||
#include "view.hpp"
|
||||
|
||||
CSVSettings::SettingWindow::SettingWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
{}
|
||||
|
||||
void CSVSettings::SettingWindow::createPages()
|
||||
{
|
||||
CSMSettings::SettingPageMap pageMap = mModel->settingPageMap();
|
||||
|
||||
QList <CSMSettings::Setting *> connectedSettings;
|
||||
|
||||
foreach (const QString &pageName, pageMap.keys())
|
||||
{
|
||||
QList <CSMSettings::Setting *> pageSettings = pageMap.value (pageName);
|
||||
|
||||
mPages.append (new Page (pageName, pageSettings, this));
|
||||
|
||||
for (int i = 0; i < pageSettings.size(); i++)
|
||||
{
|
||||
CSMSettings::Setting *setting = pageSettings.at(i);
|
||||
|
||||
if (!setting->proxyLists().isEmpty())
|
||||
connectedSettings.append (setting);
|
||||
}
|
||||
}
|
||||
|
||||
if (!connectedSettings.isEmpty())
|
||||
createConnections(connectedSettings);
|
||||
}
|
||||
|
||||
void CSVSettings::SettingWindow::createConnections
|
||||
(const QList <CSMSettings::Setting *> &list)
|
||||
{
|
||||
foreach (const CSMSettings::Setting *setting, list)
|
||||
{
|
||||
View *masterView = findView (setting->page(), setting->name());
|
||||
|
||||
CSMSettings::Connector *connector =
|
||||
new CSMSettings::Connector (masterView, this);
|
||||
|
||||
connect (masterView,
|
||||
SIGNAL (viewUpdated(const QString &, const QStringList &)),
|
||||
connector,
|
||||
SLOT (slotUpdateSlaves())
|
||||
);
|
||||
|
||||
const CSMSettings::ProxyValueMap &proxyMap = setting->proxyLists();
|
||||
|
||||
foreach (const QString &key, proxyMap.keys())
|
||||
{
|
||||
QStringList keyPair = key.split('.');
|
||||
|
||||
if (keyPair.size() != 2)
|
||||
continue;
|
||||
|
||||
View *slaveView = findView (keyPair.at(0), keyPair.at(1));
|
||||
|
||||
if (!slaveView)
|
||||
{
|
||||
qWarning () << "Unable to create connection for view "
|
||||
<< key;
|
||||
continue;
|
||||
}
|
||||
|
||||
QList <QStringList> proxyList = proxyMap.value (key);
|
||||
connector->addSlaveView (slaveView, proxyList);
|
||||
|
||||
connect (slaveView,
|
||||
SIGNAL (viewUpdated(const QString &, const QStringList &)),
|
||||
connector,
|
||||
SLOT (slotUpdateMaster()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CSVSettings::View *CSVSettings::SettingWindow::findView
|
||||
(const QString &pageName, const QString &setting)
|
||||
{
|
||||
foreach (const Page *page, mPages)
|
||||
{
|
||||
if (page->objectName() == pageName)
|
||||
return page->findView (pageName, setting);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CSVSettings::SettingWindow::saveSettings()
|
||||
{
|
||||
QMap <QString, QStringList> settingMap;
|
||||
|
||||
foreach (const Page *page, mPages)
|
||||
{
|
||||
foreach (const View *view, page->views())
|
||||
{
|
||||
if (view->serializable())
|
||||
settingMap[view->viewKey()] = view->selectedValues();
|
||||
}
|
||||
}
|
||||
CSMSettings::UserSettings::instance().saveSettings (settingMap);
|
||||
}
|
||||
|
||||
void CSVSettings::SettingWindow::closeEvent (QCloseEvent *event)
|
||||
{
|
||||
QApplication::focusWidget()->clearFocus();
|
||||
}
|
49
apps/opencs/view/settings/settingwindow.hpp
Normal file
49
apps/opencs/view/settings/settingwindow.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef CSVSETTINGS_SETTINGWINDOW_HPP
|
||||
#define CSVSETTINGS_SETTINGWINDOW_HPP
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QList>
|
||||
|
||||
#include "../../model/settings/support.hpp"
|
||||
|
||||
namespace CSMSettings {
|
||||
class Setting;
|
||||
class SettingManager;
|
||||
}
|
||||
|
||||
namespace CSVSettings {
|
||||
|
||||
class Page;
|
||||
class View;
|
||||
|
||||
typedef QList <Page *> PageList;
|
||||
|
||||
class SettingWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
PageList mPages;
|
||||
CSMSettings::SettingManager *mModel;
|
||||
|
||||
public:
|
||||
explicit SettingWindow(QWidget *parent = 0);
|
||||
|
||||
View *findView (const QString &pageName, const QString &setting);
|
||||
void setModel (CSMSettings::SettingManager &model) { mModel = &model; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual void closeEvent (QCloseEvent *event);
|
||||
|
||||
void createPages();
|
||||
|
||||
const PageList &pages() const { return mPages; }
|
||||
|
||||
void saveSettings();
|
||||
|
||||
private:
|
||||
void createConnections (const QList <CSMSettings::Setting *> &list);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CSVSETTINGS_SETTINGWINDOW_HPP
|
73
apps/opencs/view/settings/textview.cpp
Normal file
73
apps/opencs/view/settings/textview.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include <QTextEdit>
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "textview.hpp"
|
||||
#include "../../model/settings/setting.hpp"
|
||||
|
||||
CSVSettings::TextView::TextView(CSMSettings::Setting *setting, Page *parent)
|
||||
: mDelimiter (setting->delimiter()), View (setting, parent)
|
||||
|
||||
{
|
||||
if (setting->isMultiLine())
|
||||
mTextWidget = new QTextEdit ("", this);
|
||||
else
|
||||
mTextWidget = new QLineEdit ("", this);
|
||||
|
||||
if (setting->widgetWidth() > 0)
|
||||
mTextWidget->setFixedWidth (widgetWidth (setting->widgetWidth()));
|
||||
|
||||
connect (mTextWidget, SIGNAL (textEdited (QString)),
|
||||
this, SLOT (slotTextEdited (QString)));
|
||||
|
||||
addWidget (mTextWidget, setting->viewRow(), setting->viewColumn());
|
||||
}
|
||||
|
||||
bool CSVSettings::TextView::isEquivalent
|
||||
(const QString &lhs, const QString &rhs) const
|
||||
{
|
||||
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);
|
||||
|
||||
QStringList returnValues;
|
||||
|
||||
foreach (const QString &splitValue, values)
|
||||
returnValues.append (splitValue.trimmed());
|
||||
|
||||
setSelectedValues (returnValues, false);
|
||||
|
||||
View::updateView();
|
||||
}
|
||||
|
||||
void CSVSettings::TextView::updateView(bool signalUpdate) const
|
||||
{
|
||||
QString values = selectedValues().join (mDelimiter);
|
||||
|
||||
if (isEquivalent (widgetText(), values))
|
||||
return;
|
||||
|
||||
setWidgetText (values);
|
||||
|
||||
View::updateView (signalUpdate);
|
||||
}
|
||||
|
||||
QString CSVSettings::TextView::widgetText() const
|
||||
{
|
||||
return mTextWidget->property("text").toString();
|
||||
}
|
||||
|
||||
CSVSettings::TextView *CSVSettings::TextViewFactory::createView
|
||||
(CSMSettings::Setting *setting,
|
||||
Page *parent)
|
||||
{
|
||||
return new TextView (setting, parent);
|
||||
}
|
||||
|
56
apps/opencs/view/settings/textview.hpp
Normal file
56
apps/opencs/view/settings/textview.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef CSVSETTINGS_TEXTVIEW_HPP
|
||||
#define CSVSETTINGS_TEXTVIEW_HPP
|
||||
|
||||
#include "view.hpp"
|
||||
#include "../../model/settings/setting.hpp"
|
||||
|
||||
namespace CSVSettings
|
||||
{
|
||||
class TextView : public View
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QWidget *mTextWidget;
|
||||
|
||||
QString mDelimiter;
|
||||
|
||||
public:
|
||||
explicit TextView (CSMSettings::Setting *setting,
|
||||
Page *parent = 0);
|
||||
|
||||
protected:
|
||||
|
||||
void updateView (bool signalUpdate = true) const;
|
||||
|
||||
protected slots:
|
||||
|
||||
///Receives updates to the widget for signalling
|
||||
void slotTextEdited (QString value);
|
||||
|
||||
private:
|
||||
|
||||
///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
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TextViewFactory (QWidget *parent = 0)
|
||||
: QObject (parent)
|
||||
{}
|
||||
|
||||
TextView *createView (CSMSettings::Setting *setting,
|
||||
Page *parent);
|
||||
};
|
||||
}
|
||||
#endif // CSVSETTINGS_TEXTVIEW_HPP
|
218
apps/opencs/view/settings/view.cpp
Normal file
218
apps/opencs/view/settings/view.cpp
Normal file
@ -0,0 +1,218 @@
|
||||
#include <QStringListModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStandardItem>
|
||||
#include <QApplication>
|
||||
|
||||
#include "view.hpp"
|
||||
#include "../../model/settings/support.hpp"
|
||||
#include "../../model/settings/setting.hpp"
|
||||
#include "page.hpp"
|
||||
|
||||
CSVSettings::View::View(CSMSettings::Setting *setting,
|
||||
Page *parent)
|
||||
|
||||
: mDataModel(0), mParentPage (parent),
|
||||
mHasFixedValues (!setting->declaredValues().isEmpty()),
|
||||
mIsMultiValue (setting->isMultiValue()),
|
||||
mViewKey (setting->page() + '.' + setting->name()),
|
||||
mSerializable (setting->serializable()),
|
||||
Frame(true, setting->name(), parent)
|
||||
{
|
||||
setObjectName (setting->name());
|
||||
buildView();
|
||||
buildModel (setting);
|
||||
}
|
||||
|
||||
void CSVSettings::View::buildModel (const CSMSettings::Setting *setting)
|
||||
{
|
||||
QStringList values = setting->definedValues();
|
||||
|
||||
if (values.isEmpty())
|
||||
values.append (setting->defaultValues());
|
||||
|
||||
if (mHasFixedValues)
|
||||
buildFixedValueModel (setting->declaredValues());
|
||||
else
|
||||
buildUpdatableValueModel (values);
|
||||
|
||||
mSelectionModel = new QItemSelectionModel (mDataModel, this);
|
||||
|
||||
setSelectedValues (values, false);
|
||||
}
|
||||
|
||||
void CSVSettings::View::buildFixedValueModel (const QStringList &values)
|
||||
{
|
||||
mDataModel = new QStringListModel (values, this);
|
||||
}
|
||||
|
||||
void CSVSettings::View::buildUpdatableValueModel (const QStringList &values)
|
||||
{
|
||||
QList <QStandardItem *> 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;
|
||||
}
|
||||
|
||||
void CSVSettings::View::buildView()
|
||||
{
|
||||
setFlat (true);
|
||||
setHLayout();
|
||||
}
|
||||
|
||||
int CSVSettings::View::currentIndex () const
|
||||
{
|
||||
if (selectedValues().isEmpty())
|
||||
return -1;
|
||||
|
||||
QString currentValue = selectedValues().at(0);
|
||||
|
||||
for (int i = 0; i < mDataModel->rowCount(); i++)
|
||||
if (value(i) == currentValue)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CSVSettings::View::refresh() const
|
||||
{
|
||||
select (mSelectionModel->selection());
|
||||
updateView();
|
||||
}
|
||||
|
||||
int CSVSettings::View::rowCount() const
|
||||
{
|
||||
return mDataModel->rowCount();
|
||||
}
|
||||
|
||||
void CSVSettings::View::select (const QItemSelection &selection) const
|
||||
{
|
||||
mSelectionModel->clear();
|
||||
mSelectionModel->select(selection, QItemSelectionModel::Select);
|
||||
}
|
||||
|
||||
QStringList CSVSettings::View::selectedValues() const
|
||||
{
|
||||
QStringList selValues;
|
||||
|
||||
foreach (const QModelIndex &idx, mSelectionModel->selectedIndexes())
|
||||
selValues.append (value(idx.row()));
|
||||
|
||||
return selValues;
|
||||
}
|
||||
|
||||
void CSVSettings::View::setSelectedValue (const QString &value,
|
||||
bool doViewUpdate, bool signalUpdate)
|
||||
{
|
||||
setSelectedValues (QStringList() << value, doViewUpdate, signalUpdate);
|
||||
}
|
||||
|
||||
void CSVSettings::View::setSelectedValues (const QStringList &list,
|
||||
bool doViewUpdate, bool signalUpdate)
|
||||
{
|
||||
QItemSelection selection;
|
||||
|
||||
if (stringListsMatch (list, selectedValues()))
|
||||
return;
|
||||
|
||||
if (!mHasFixedValues)
|
||||
{
|
||||
QStandardItemModel *model =
|
||||
static_cast <QStandardItemModel *>(mDataModel);
|
||||
|
||||
model->clear();
|
||||
model->appendColumn (toStandardItemList (list));
|
||||
|
||||
for (int i = 0; i < model->rowCount(); i++)
|
||||
{
|
||||
QModelIndex idx = model->index(i, 0);
|
||||
selection.append (QItemSelectionRange (idx, idx));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < mDataModel->rowCount(); i++)
|
||||
{
|
||||
if (list.contains(value(i)))
|
||||
{
|
||||
QModelIndex idx = mDataModel->index(i, 0);
|
||||
selection.append(QItemSelectionRange (idx, idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
select (selection);
|
||||
|
||||
if (doViewUpdate)
|
||||
updateView (signalUpdate);
|
||||
}
|
||||
|
||||
void CSVSettings::View::showEvent ( QShowEvent * event )
|
||||
{
|
||||
refresh();
|
||||
}
|
||||
|
||||
bool CSVSettings::View::stringListsMatch (
|
||||
const QStringList &list1,
|
||||
const QStringList &list2) const
|
||||
{
|
||||
//returns a "sloppy" match, verifying that each list contains all the same
|
||||
//items, though not necessarily in the same order.
|
||||
|
||||
if (list1.size() != list2.size())
|
||||
return false;
|
||||
|
||||
QStringList tempList(list2);
|
||||
|
||||
//iterate each value in the list, removing one occurrence of the value in
|
||||
//the other list. If no corresponding value is found, test fails
|
||||
foreach (const QString &value, list1)
|
||||
{
|
||||
if (!tempList.contains(value))
|
||||
return false;
|
||||
|
||||
tempList.removeOne(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QList <QStandardItem *> CSVSettings::View::toStandardItemList
|
||||
(const QStringList &list) const
|
||||
{
|
||||
QList <QStandardItem *> itemList;
|
||||
|
||||
foreach (const QString &value, list)
|
||||
itemList.append (new QStandardItem (value));
|
||||
|
||||
return itemList;
|
||||
}
|
||||
|
||||
void CSVSettings::View::updateView (bool signalUpdate) const
|
||||
{
|
||||
if (signalUpdate)
|
||||
emit viewUpdated(objectName(), selectedValues());
|
||||
}
|
||||
|
||||
QString CSVSettings::View::value (int row) const
|
||||
{
|
||||
if (row > -1 && row < mDataModel->rowCount())
|
||||
return mDataModel->data (mDataModel->index(row, 0)).toString();
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
int CSVSettings::View::widgetWidth(int characterCount) const
|
||||
{
|
||||
QString widthToken = QString().fill ('P', characterCount);
|
||||
QFontMetrics fm (QApplication::font());
|
||||
|
||||
return (fm.width (widthToken));
|
||||
}
|
163
apps/opencs/view/settings/view.hpp
Normal file
163
apps/opencs/view/settings/view.hpp
Normal file
@ -0,0 +1,163 @@
|
||||
#ifndef CSVSETTINGS_VIEW_HPP
|
||||
#define CSVSETTINGS_VIEW_HPP
|
||||
|
||||
#include <QWidget>
|
||||
#include <QList>
|
||||
|
||||
#include "frame.hpp"
|
||||
#include "../../model/settings/support.hpp"
|
||||
|
||||
class QGroupBox;
|
||||
class QStringList;
|
||||
class QStandardItem;
|
||||
class QItemSelection;
|
||||
class QStringListModel;
|
||||
class QStandardItemModel;
|
||||
class QAbstractItemModel;
|
||||
class QItemSelectionModel;
|
||||
|
||||
namespace CSMSettings { class Setting; }
|
||||
|
||||
namespace CSVSettings
|
||||
{
|
||||
class Page;
|
||||
|
||||
class View : public Frame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
///Pointer to the owning Page instance
|
||||
Page *mParentPage;
|
||||
|
||||
///Pointer to the selection model for the view
|
||||
QItemSelectionModel *mSelectionModel;
|
||||
|
||||
///Pointer to the data model for the view's selection model
|
||||
QAbstractItemModel *mDataModel;
|
||||
|
||||
///State indicating whether or not the setting has a pre-defined list
|
||||
///of values, limiting possible definitions
|
||||
bool mHasFixedValues;
|
||||
|
||||
///State indicating whether the view will allow multiple values
|
||||
bool mIsMultiValue;
|
||||
|
||||
QString mViewKey;
|
||||
|
||||
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;
|
||||
|
||||
///Returns the number of rows in the view's data model
|
||||
int rowCount() const;
|
||||
|
||||
///Returns bool indicating the data in this view should / should not
|
||||
///be serialized to a config file
|
||||
bool serializable() const { return mSerializable; }
|
||||
|
||||
///Returns a pointer to the view's owning parent page
|
||||
const Page *parentPage() const { return mParentPage; }
|
||||
|
||||
///Returns the selected items in the selection model as a QStringList
|
||||
QStringList selectedValues() const;
|
||||
|
||||
///Sets the selected items in the selection model based on passed list.
|
||||
///Bools allow opt-out of updating the view
|
||||
///or signaling the view was updatedto avoid viscious cylcing.
|
||||
void setSelectedValues (const QStringList &values,
|
||||
bool updateView = true,
|
||||
bool signalUpdate = true);
|
||||
|
||||
void setSelectedValue (const QString &value,
|
||||
bool updateView = true,
|
||||
bool signalUpdate = true);
|
||||
|
||||
|
||||
///Returns the value of the data model at the specified row
|
||||
QString value (int row) const;
|
||||
|
||||
QString viewKey() const { return mViewKey; }
|
||||
|
||||
protected:
|
||||
|
||||
/// Returns the model which provides data for the selection model
|
||||
QAbstractItemModel *dataModel() { return mDataModel; }
|
||||
|
||||
///Accessor function for subclasses
|
||||
bool isMultiValue() { return mIsMultiValue; }
|
||||
|
||||
///Returns the view selection model
|
||||
QItemSelectionModel *selectionModel() { return mSelectionModel;}
|
||||
|
||||
///Global callback for basic view initialization
|
||||
void showEvent ( QShowEvent * event );
|
||||
|
||||
///Virtual for updating a specific View subclass
|
||||
///bool indicates whether a signal is emitted that the view was updated
|
||||
virtual void updateView (bool signalUpdate = true) const;
|
||||
|
||||
///Returns the pixel width corresponding to the specified number of
|
||||
///characters.
|
||||
int widgetWidth(int characterCount) const;
|
||||
|
||||
private:
|
||||
|
||||
///Constructs the view layout
|
||||
void buildView();
|
||||
|
||||
///Constructs the data and selection models
|
||||
void buildModel (const CSMSettings::Setting *setting);
|
||||
|
||||
///In cases where the view has a pre-defined list of possible values,
|
||||
///a QStringListModel is created using those values.
|
||||
///View changes operate on the selection model only.
|
||||
void buildFixedValueModel (const QStringList &definitions);
|
||||
|
||||
///In cases where the view does not have a pre-defined list of possible
|
||||
///values, a QStandardItemModel is created, containing the actual
|
||||
///setting definitions. View changes first update the data in the
|
||||
///model to match the data in the view. The selection model always
|
||||
///selects all values.
|
||||
void buildUpdatableValueModel (const QStringList &definitions);
|
||||
|
||||
///Refreshes the view
|
||||
void refresh() const;
|
||||
|
||||
///Convenince function for selection model's select() method. Also
|
||||
///clears out the model beforehand to ensure complete selection.
|
||||
void select (const QItemSelection &selection) const;
|
||||
|
||||
///Compares two string lists "loosely", ensuring that all values in
|
||||
///one list are contained entirely in the other, and that neither list
|
||||
///has more values than the other. List order is not considered.
|
||||
bool stringListsMatch (const QStringList &list1,
|
||||
const QStringList &list2) const;
|
||||
|
||||
///Converts a string list to a list of QStandardItem pointers.
|
||||
QList <QStandardItem *> toStandardItemList(const QStringList &) const;
|
||||
|
||||
signals:
|
||||
|
||||
///Signals that the view has been changed.
|
||||
void viewUpdated(const QString &, const QStringList &) const;
|
||||
|
||||
};
|
||||
|
||||
class IViewFactory
|
||||
{
|
||||
public:
|
||||
|
||||
///Creation interface for view factories
|
||||
virtual View *createView (CSMSettings::Setting *setting,
|
||||
Page *parent) = 0;
|
||||
};
|
||||
}
|
||||
#endif // CSVSETTINGS_VIEW_HPP
|
Loading…
x
Reference in New Issue
Block a user