merge master

actorid
mrcheko 11 years ago
commit 6a3dddfb9a

@ -41,4 +41,4 @@ notifications:
- "chat.freenode.net#openmw" - "chat.freenode.net#openmw"
on_success: change on_success: change
on_failure: always on_failure: always
use_notice: true

@ -24,7 +24,7 @@ opencs_units (model/world
opencs_units_noqt (model/world opencs_units_noqt (model/world
universalid record commands columnbase scriptcontext cell refidcollection universalid record commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection
) )
opencs_hdrs_noqt (model/world opencs_hdrs_noqt (model/world
@ -60,7 +60,7 @@ opencs_hdrs_noqt (view/doc
opencs_units (view/world opencs_units (view/world
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
scenetoolmode infocreator scriptedit dialoguesubview previewsubview scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap
) )
opencs_units (view/render opencs_units (view/render
@ -88,34 +88,29 @@ opencs_units_noqt (view/tools
) )
opencs_units (view/settings opencs_units (view/settings
abstractblock settingwindow
proxyblock dialog
abstractwidget page
usersettingsdialog view
datadisplayformatpage booleanview
windowpage textview
listview
resizeablestackedwidget
) )
opencs_units_noqt (view/settings opencs_units_noqt (view/settings
abstractpage frame
blankpage
groupblock
customblock
groupbox
itemblock
settingwidget
toggleblock
support
) )
opencs_units (model/settings opencs_units (model/settings
usersettings usersettings
settingcontainer settingmanager
setting
connector
) )
opencs_units_noqt (model/settings opencs_hdrs_noqt (model/settings
support support
settingsitem
) )
opencs_units_noqt (model/filter opencs_units_noqt (model/filter

@ -28,6 +28,7 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
setupDataFiles (config.first); setupDataFiles (config.first);
CSMSettings::UserSettings::instance().loadSettings ("opencs.cfg"); CSMSettings::UserSettings::instance().loadSettings ("opencs.cfg");
mSettings.setModel (CSMSettings::UserSettings::instance());
ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string()); ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string());
@ -117,6 +118,18 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end()); dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
//iterate the data directories and add them to the file dialog for loading
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
{
QString path = QString::fromStdString(iter->string());
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> >());
} }

@ -24,7 +24,7 @@
#include "view/doc/filedialog.hpp" #include "view/doc/filedialog.hpp"
#include "view/doc/newgame.hpp" #include "view/doc/newgame.hpp"
#include "view/settings/usersettingsdialog.hpp" #include "view/settings/dialog.hpp"
namespace OgreInit namespace OgreInit
{ {
@ -43,7 +43,7 @@ namespace CS
CSVDoc::ViewManager mViewManager; CSVDoc::ViewManager mViewManager;
CSVDoc::StartupDialogue mStartup; CSVDoc::StartupDialogue mStartup;
CSVDoc::NewGameDialogue mNewGame; CSVDoc::NewGameDialogue mNewGame;
CSVSettings::UserSettingsDialog mSettings; CSVSettings::Dialog mSettings;
CSVDoc::FileDialog mFileDialog; CSVDoc::FileDialog mFileDialog;
boost::filesystem::path mLocal; boost::filesystem::path mLocal;
boost::filesystem::path mResources; boost::filesystem::path mResources;

@ -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;
}

@ -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

@ -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;
}

@ -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

@ -1,82 +0,0 @@
#include "settingcontainer.hpp"
#include <QStringList>
CSMSettings::SettingContainer::SettingContainer(QObject *parent) :
QObject(parent), mValue (0), mValues (0)
{
}
CSMSettings::SettingContainer::SettingContainer(const QString &value, QObject *parent) :
QObject(parent), mValue (new QString (value)), mValues (0)
{
}
void CSMSettings::SettingContainer::insert (const QString &value)
{
if (mValue)
{
mValues = new QStringList;
mValues->push_back (*mValue);
mValues->push_back (value);
delete mValue;
mValue = 0;
}
else
{
delete mValue;
mValue = new QString (value);
}
}
void CSMSettings::SettingContainer::update (const QString &value, int index)
{
if (isEmpty())
mValue = new QString(value);
else if (mValue)
*mValue = value;
else if (mValues)
mValues->replace(index, value);
}
QString CSMSettings::SettingContainer::getValue (int index) const
{
QString retVal("");
//if mValue is valid, it's a single-value property.
//ignore the index and return the value
if (mValue)
retVal = *mValue;
//otherwise, if it's a multivalued property
//return the appropriate value at the index
else if (mValues)
{
if (index == -1)
retVal = mValues->at(0);
else if (index < mValues->size())
retVal = mValues->at(index);
}
return retVal;
}
int CSMSettings::SettingContainer::count () const
{
int retVal = 0;
if (!isEmpty())
{
if (mValues)
retVal = mValues->size();
else
retVal = 1;
}
return retVal;
}

@ -1,47 +0,0 @@
#ifndef SETTINGCONTAINER_HPP
#define SETTINGCONTAINER_HPP
#include <QObject>
class QStringList;
namespace CSMSettings
{
class SettingContainer : public QObject
{
Q_OBJECT
QString *mValue;
QStringList *mValues;
public:
explicit SettingContainer (QObject *parent = 0);
explicit SettingContainer (const QString &value, QObject *parent = 0);
/// add a value to the container
/// multiple values supported
void insert (const QString &value);
/// update an existing value
/// index specifies multiple values
void update (const QString &value, int index = 0);
/// return value at specified index
QString getValue (int index = -1) const;
/// retrieve list of all values
inline QStringList *getValues() const { return mValues; }
/// return size of list
int count() const;
/// test for empty container
/// useful for default-constructed containers returned by QMap when invalid key is passed
inline bool isEmpty() const { return (!mValue && !mValues); }
inline bool isMultiValue() const { return (mValues); }
};
}
#endif // SETTINGCONTAINER_HPP

@ -0,0 +1,342 @@
#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 &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);
}

@ -0,0 +1,85 @@
#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:
void userSettingUpdated (const QString &, const QStringList &);
public slots:
void updateUserSetting (const QString &, const QStringList &);
};
}
#endif // CSMSETTINGS_SETTINGMANAGER_HPP

@ -1,104 +0,0 @@
#include "settingsitem.hpp"
#include <QStringList>
bool CSMSettings::SettingsItem::updateItem (const QStringList *values)
{
QStringList::ConstIterator it = values->begin();
//if the item is not multivalued,
//save the last value passed in the container
if (!mIsMultiValue)
{
it = values->end();
it--;
}
bool isValid = true;
QString value ("");
for (; it != values->end(); ++it)
{
value = *it;
isValid = validate(value);
//skip only the invalid values
if (!isValid)
continue;
insert(value);
}
return isValid;
}
bool CSMSettings::SettingsItem::updateItem (const QString &value)
{
//takes a value or a SettingsContainer and updates itself accordingly
//after validating the data against it's own definition
QString newValue = value;
if (!validate (newValue))
newValue = mDefaultValue;
bool success = (getValue() != newValue);
if (success)
{
if (mIsMultiValue)
insert (newValue);
else
update (newValue);
}
return success;
}
bool CSMSettings::SettingsItem::updateItem(int valueListIndex)
{
bool success = false;
if (mValueList)
{
if (mValueList->size() > valueListIndex)
success = updateItem (mValueList->at(valueListIndex));
}
return success;
}
bool CSMSettings::SettingsItem::validate (const QString &value)
{
//if there is no value list or value pair, there is no validation to do
bool isValid = !(!mValueList->isEmpty() || mValuePair);
if (!isValid && !mValueList->isEmpty())
{
for (QStringList::Iterator it = mValueList->begin(); it != mValueList->end(); ++it)
// foreach (QString listItem, *mValueList)
{
isValid = (value == *it);
if (isValid)
break;
}
}
else if (!isValid && mValuePair)
{
int numVal = value.toInt();
isValid = (numVal > mValuePair->left.toInt() && numVal < mValuePair->right.toInt());
}
return isValid;
}
void CSMSettings::SettingsItem::setDefaultValue (const QString &value)
{
mDefaultValue = value;
update (value);
}
QString CSMSettings::SettingsItem::getDefaultValue() const
{
return mDefaultValue;
}

@ -1,67 +0,0 @@
#ifndef SETTINGSITEM_HPP
#define SETTINGSITEM_HPP
#include <QObject>
#include "support.hpp"
#include "settingcontainer.hpp"
namespace CSMSettings
{
/// Represents a setting including metadata
/// (valid values, ranges, defaults, and multivalue status
class SettingsItem : public SettingContainer
{
QStringPair *mValuePair;
QStringList *mValueList;
bool mIsMultiValue;
QString mDefaultValue;
public:
explicit SettingsItem(QString name, bool isMultiValue,
const QString& defaultValue, QObject *parent = 0)
: SettingContainer(defaultValue, parent),
mIsMultiValue (isMultiValue), mValueList (0),
mValuePair (0), mDefaultValue (defaultValue)
{
QObject::setObjectName(name);
}
/// updateItem overloads for updating setting value
/// provided a list of values (multi-valued),
/// a specific value
/// or an index value corresponding to the mValueList
bool updateItem (const QStringList *values);
bool updateItem (const QString &value);
bool updateItem (int valueListIndex);
/// retrieve list of valid values for setting
inline QStringList *getValueList() { return mValueList; }
/// write list of valid values for setting
inline void setValueList (QStringList *valueList) { mValueList = valueList; }
/// valuePair used for spin boxes (max / min)
inline QStringPair *getValuePair() { return mValuePair; }
/// set value range (spinbox / integer use)
inline void setValuePair (QStringPair valuePair)
{
delete mValuePair;
mValuePair = new QStringPair(valuePair);
}
inline bool isMultivalue () { return mIsMultiValue; }
void setDefaultValue (const QString &value);
QString getDefaultValue () const;
private:
/// Verifies that the supplied value is one of the following:
/// 1. Within the limits of the value pair (min / max)
/// 2. One of the values indicated in the value list
bool validate (const QString &value);
};
}
#endif // SETTINGSITEM_HPP

@ -1 +0,0 @@
#include "support.hpp"

@ -1,39 +1,126 @@
#ifndef MODEL_SUPPORT_HPP #ifndef SETTING_SUPPORT_HPP
#define MODEL_SUPPORT_HPP #define SETTING_SUPPORT_HPP
#include <QObject> #include <Qt>
#include <QPair>
#include <QList>
#include <QVariant>
#include <QStringList> #include <QStringList>
class QLayout; //Typedefs
class QWidget; namespace CSMSettings
class QListWidgetItem; {
// 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
namespace CSMSettings namespace CSMSettings
{ {
class SettingContainer; enum SettingProperty
{
Property_Name = 0,
Property_Page = 1,
Property_ViewType = 2,
Property_IsMultiValue = 3,
Property_IsMultiLine = 4,
Property_WidgetWidth = 5,
Property_ViewRow = 6,
Property_ViewColumn = 7,
Property_Delimiter = 8,
Property_Serializable = 9,
Property_ColumnSpan = 10,
Property_RowSpan = 11,
typedef QList<SettingContainer *> SettingList; //Stringlists should always be the last items
typedef QMap<QString, SettingContainer *> SettingMap; Property_DefaultValues = 12,
typedef QMap<QString, SettingMap *> SectionMap; Property_DeclaredValues = 13,
Property_DefinedValues = 14,
Property_Proxies = 15
};
struct QStringPair enum SettingType
{ {
QStringPair(): left (""), right ("") Type_MultiBool = 0,
{} Type_SingleBool = 1,
Type_MultiList = 2,
Type_SingleList = 3,
Type_MultiRange = 4,
Type_SingleRange = 5,
Type_MultiText = 6,
Type_SingleText = 7
};
QStringPair (const QString &leftValue, const QString &rightValue) enum MergeMethod
: left (leftValue), right(rightValue) {
{} Merge_Accept,
Merge_Ignore,
Merge_Overwrite
};
}
QStringPair (const QStringPair &pair) namespace CSVSettings
: left (pair.left), right (pair.right) {
{} enum ViewType
{
ViewType_Boolean = 0,
ViewType_List = 1,
ViewType_Range = 2,
ViewType_Text = 3,
ViewType_Undefined = 4
};
QString left; enum Alignment
QString right; {
Align_Left = Qt::AlignLeft,
Align_Center = Qt::AlignHCenter,
Align_Right = Qt::AlignRight
};
}
bool isEmpty() const //
{ return (left.isEmpty() && right.isEmpty()); } namespace CSMSettings
{
struct PropertyDefaultValues
{
int id;
QString name;
QVariant value;
};
const QString sPropertyNames[] =
{
"name", "page", "view_type", "is_multi_value",
"is_multi_line", "widget_width", "view_row", "view_column", "delimiter",
"is_serializable","column_span", "row_span",
"defaults", "declarations", "definitions", "proxies"
};
const QString sPropertyDefaults[] =
{
"", //name
"", //page
"0", //view type
"false", //multivalue
"false", //multiline
"0", //widget width
"-1", //view row
"-1", //view column
",", //delimiter
"true", //serialized
"1", //column span
"1", //row span
"", //default values
"", //declared values
"", //defined values
"" //proxy values
}; };
} }
#endif // MODEL_SUPPORT_HPP
#endif // VIEW_SUPPORT_HPP

@ -9,11 +9,14 @@
#include <QTextCodec> #include <QTextCodec>
#include <QFile> #include <QFile>
#include <QSortFilterProxyModel>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include "settingcontainer.hpp"
#include <boost/version.hpp> #include <boost/version.hpp>
#include "setting.hpp"
#include "support.hpp"
/** /**
* 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
*/ */
@ -37,269 +40,236 @@ CSMSettings::UserSettings::UserSettings()
assert(!mUserSettingsInstance); assert(!mUserSettingsInstance);
mUserSettingsInstance = this; mUserSettingsInstance = this;
mReadWriteMessage = QObject::tr("<br><b>Could not open or create file for writing</b><br><br> \ buildSettingModelDefaults();
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>");
buildEditorSettingDefaults();
} }
void CSMSettings::UserSettings::buildEditorSettingDefaults() void CSMSettings::UserSettings::buildSettingModelDefaults()
{ {
SettingContainer *windowHeight = new SettingContainer("768", this); QString section = "Window Size";
SettingContainer *windowWidth = new SettingContainer("1024", this);
SettingContainer *rsDelegate = new SettingContainer("Icon and Text", this);
SettingContainer *refIdTypeDelegate = new SettingContainer("Icon and Text", this);
windowHeight->setObjectName ("Height");
windowWidth->setObjectName ("Width");
rsDelegate->setObjectName ("Record Status Display");
refIdTypeDelegate->setObjectName ("Referenceable ID Type Display");
SettingMap *displayFormatMap = new SettingMap;
SettingMap *windowSizeMap = new SettingMap;
displayFormatMap->insert (rsDelegate->objectName(), rsDelegate );
displayFormatMap->insert (refIdTypeDelegate->objectName(), refIdTypeDelegate);
windowSizeMap->insert (windowWidth->objectName(), windowWidth );
windowSizeMap->insert (windowHeight->objectName(), windowHeight );
mEditorSettingDefaults.insert ("Display Format", displayFormatMap);
mEditorSettingDefaults.insert ("Window Size", windowSizeMap);
}
CSMSettings::UserSettings::~UserSettings()
{
mUserSettingsInstance = 0;
}
QTextStream *CSMSettings::UserSettings::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); Setting *width = createSetting (Type_SingleText, section, "Width");
stream->setCodec(QTextCodec::codecForName("UTF-8")); Setting *height = createSetting (Type_SingleText, section, "Height");
width->setWidgetWidth (5);
height->setWidgetWidth (5);
width->setDefaultValues (QStringList() << "1024");
height->setDefaultValues (QStringList() << "768");
width->setEditorSetting (true);
height->setEditorSetting (true);
height->setViewLocation (2,2);
width->setViewLocation (2,1);
/*
*Create the proxy setting for predefined values
*/
Setting *preDefined = createSetting (Type_SingleList, section,
"Pre-Defined",
QStringList()
<< "640 x 480"
<< "800 x 600"
<< "1024 x 768"
<< "1440 x 900"
);
preDefined->setViewLocation (1, 1);
preDefined->setWidgetWidth (10);
preDefined->setColumnSpan (2);
preDefined->addProxy (width,
QStringList() << "640" << "800" << "1024" << "1440"
);
preDefined->addProxy (height,
QStringList() << "480" << "600" << "768" << "900"
);
} }
return stream; section = "Display Format";
}
bool CSMSettings::UserSettings::writeSettings(QMap<QString, CSMSettings::SettingList *> &settings)
{
QTextStream *stream = openFileStream(mUserFilePath);
bool success = (stream);
if (success)
{ {
QList<QString> keyList = settings.keys(); QString defaultValue = "Icon and Text";
foreach (QString key, keyList) QStringList values = QStringList()
{ << defaultValue << "Icon Only" << "Text Only";
SettingList *sectionSettings = settings[key];
*stream << "[" << key << "]" << '\n'; Setting *rsd = createSetting (Type_SingleBool,
section, "Record Status Display",
values);
foreach (SettingContainer *item, *sectionSettings) Setting *ritd = createSetting (Type_SingleBool,
*stream << item->objectName() << " = " << item->getValue() << '\n'; section, "Referenceable ID Type Display",
} values);
stream->device()->close(); rsd->setEditorSetting (true);
delete stream; ritd->setEditorSetting (true);
stream = 0;
} }
else
section = "Proxy Selection Test";
{ {
displayFileErrorMessage(mReadWriteMessage, false); //create three setting objects, specifying the basic widget type,
//the setting view name, the page name, and the default value
Setting *masterBoolean = createSetting (Type_SingleBool, section,
"Master Proxy",
QStringList()
<< "Profile One" << "Profile Two"
<< "Profile Three" << "Profile Four"
);
Setting *slaveBoolean = createSetting (Type_MultiBool, section,
"Proxy Checkboxes",
QStringList() << "One" << "Two"
<< "Three" << "Four" << "Five"
);
Setting *slaveSingleText = createSetting (Type_SingleText, section,
"Proxy TextBox 1"
);
Setting *slaveMultiText = createSetting (Type_SingleText, section,
"ProxyTextBox 2"
);
// There are three types of values:
//
// Declared values - Pre-determined values, typically for
// combobox drop downs and boolean (radiobutton / checkbox) labels.
// These values represent the total possible list of values that may
// define a setting. No other values are allowed.
//
// Defined values - Values which represent the atual, current value of
// a setting. For settings with declared values, this must be one or
// several declared values, as appropriate.
//
// Proxy values - values the proxy master updates the proxy slave when
// it's own definition is set / changed. These are definitions for
// proxy slave settings, but must match any declared values the proxy
// slave has, if any.
masterBoolean->addProxy (slaveBoolean, QList <QStringList>()
<< (QStringList() << "One" << "Three")
<< (QStringList() << "One" << "Three")
<< (QStringList() << "One" << "Three" << "Five")
<< (QStringList() << "Two" << "Four")
);
masterBoolean->addProxy (slaveSingleText, QList <QStringList>()
<< (QStringList() << "Text A")
<< (QStringList() << "Text B")
<< (QStringList() << "Text A")
<< (QStringList() << "Text C")
);
masterBoolean->addProxy (slaveMultiText, QList <QStringList>()
<< (QStringList() << "One" << "Three")
<< (QStringList() << "One" << "Three")
<< (QStringList() << "One" << "Three" << "Five")
<< (QStringList() << "Two" << "Four")
);
//settings with proxies are not serialized by default
//other settings non-serialized for demo purposes
slaveBoolean->setSerializable (false);
slaveSingleText->setSerializable (false);
slaveMultiText->setSerializable (false);
slaveBoolean->setDefaultValues (QStringList()
<< "One" << "Three" << "Five");
slaveSingleText->setDefaultValue ("Text A");
slaveMultiText->setDefaultValues (QStringList()
<< "One" << "Three" << "Five");
slaveSingleText->setWidgetWidth (24);
slaveMultiText->setWidgetWidth (24);
} }
return (success);
} }
CSMSettings::UserSettings::~UserSettings()
const CSMSettings::SectionMap &CSMSettings::UserSettings::getSectionMap() const
{ {
return mSectionSettings; mUserSettingsInstance = 0;
} }
const CSMSettings::SettingMap *CSMSettings::UserSettings::getSettings(const QString &sectionName) const void CSMSettings::UserSettings::loadSettings (const QString &fileName)
{ {
return getValidSettings(sectionName); mUserFilePath = QString::fromUtf8
} (mCfgMgr.getUserConfigPath().c_str()) + fileName.toUtf8();
bool CSMSettings::UserSettings::loadFromFile(const QString &filePath) QString global = QString::fromUtf8
{ (mCfgMgr.getGlobalPath().c_str()) + fileName.toUtf8();
if (filePath.isEmpty())
return false;
SectionMap loadedSettings; QString local = QString::fromUtf8
(mCfgMgr.getLocalPath().c_str()) + fileName.toUtf8();
QTextStream *stream = openFileStream (filePath, true); //open user and global streams
QTextStream *userStream = openFilestream (mUserFilePath, true);
QTextStream *otherStream = openFilestream (global, true);
bool success = (stream); //failed stream, try for local
if (!otherStream)
otherStream = openFilestream (local, true);
if (success) //error condition - notify and return
if (!otherStream || !userStream)
{ {
//looks for a square bracket, "'\\[" QString message = QObject::tr("<br><b>An error was encountered loading \
//that has one or more "not nothing" in it, "([^]]+)" user settings files.</b><br><br> One or several files could not \
//and is closed with a square bracket, "\\]" be read. This may be caused by a missing configuration file, \
incorrect file permissions or a corrupted installation of \
QRegExp sectionRe("^\\[([^]]+)\\]"); OpenCS.<br>");
//Find any character(s) that is/are not equal sign(s), "[^=]+"
//followed by an optional whitespace, an equal sign, and another optional whitespace, "\\s*=\\s*"
//and one or more periods, "(.+)"
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
CSMSettings::SettingMap *settings = 0;
QString section = "none";
while (!stream->atEnd())
{
QString line = stream->readLine().simplified();
if (line.isEmpty() || line.startsWith("#"))
continue;
//if a section is found, push it onto a new QStringList
//and push the QStringList onto
if (sectionRe.exactMatch(line))
{
//add the previous section's settings to the member map
if (settings)
loadedSettings.insert(section, settings);
//save new section and create a new list
section = sectionRe.cap(1);
settings = new SettingMap;
continue;
}
if (keyRe.indexIn(line) != -1) message += QObject::tr("<br>Global filepath: ") + global;
{ message += QObject::tr("<br>Local filepath: ") + local;
SettingContainer *sc = new SettingContainer (keyRe.cap(2).simplified()); message += QObject::tr("<br>User filepath: ") + mUserFilePath;
sc->setObjectName(keyRe.cap(1).simplified());
(*settings)[keyRe.cap(1).simplified()] = sc;
}
} displayFileErrorMessage ( message, true);
return;
loadedSettings.insert(section, settings);
stream->device()->close();
delete stream;
stream = 0;
} }
mergeMap (loadedSettings); //success condition - merge the two streams into a single map and save
DefinitionPageMap totalMap = readFilestream (userStream);
DefinitionPageMap otherMap = readFilestream(otherStream);
return success; //merging other settings file in and ignore duplicate settings to
} //avoid overwriting user-level settings
mergeSettings (totalMap, otherMap);
void CSMSettings::UserSettings::mergeMap (const CSMSettings::SectionMap &sectionSettings) if (!totalMap.isEmpty())
{ addDefinitions (totalMap);
foreach (QString key, sectionSettings.uniqueKeys())
{
// insert entire section if it does not already exist in the loaded files
if (mSectionSettings.find(key) == mSectionSettings.end())
mSectionSettings.insert(key, sectionSettings.value(key));
else
{
SettingMap *passedSettings = sectionSettings.value(key);
SettingMap *settings = mSectionSettings.value(key);
foreach (QString key2, passedSettings->uniqueKeys())
{
//insert section settings individially if they do not already exist
if (settings->find(key2) == settings->end())
settings->insert(key2, passedSettings->value(key2));
else
{
settings->value(key2)->update(passedSettings->value(key2)->getValue());
}
}
}
}
} }
void CSMSettings::UserSettings::loadSettings (const QString &fileName) void CSMSettings::UserSettings::saveSettings
(const QMap <QString, QStringList> &settingMap)
{ {
mSectionSettings.clear(); for (int i = 0; i < settings().size(); i++)
//global
QString globalFilePath = QString::fromStdString(mCfgMgr.getGlobalPath().string()) + fileName;
bool globalOk = loadFromFile(globalFilePath);
//local
QString localFilePath = QString::fromStdString(mCfgMgr.getLocalPath().string()) + fileName;
bool localOk = loadFromFile(localFilePath);
//user
mUserFilePath = QString::fromStdString(mCfgMgr.getUserConfigPath().string()) + fileName;
loadFromFile(mUserFilePath);
if (!(localOk || globalOk))
{ {
QString message = QObject::tr("<br><b>Could not open user settings files for reading</b><br><br> \ Setting* setting = settings().at(i);
Global and local settings files could not be read.\
You may have incorrect file permissions or the OpenCS installation may be corrupted.<br>");
message += QObject::tr("<br>Global filepath: ") + globalFilePath; QString key = setting->page() + '.' + setting->name();
message += QObject::tr("<br>Local filepath: ") + localFilePath;
displayFileErrorMessage ( message, true); if (!settingMap.keys().contains(key))
continue;
setting->setDefinedValues (settingMap.value(key));
} }
writeFilestream (openFilestream (mUserFilePath, false), settingMap);
} }
void CSMSettings::UserSettings::updateSettings (const QString &sectionName, const QString &settingName) QString CSMSettings::UserSettings::settingValue (const QString &settingKey)
{ {
QStringList names = settingKey.split('.');
SettingMap *settings = getValidSettings(sectionName); Setting *setting = findSetting(names.at(0), names.at(1));
if (!settings)
return;
if (settingName.isEmpty()) if (setting)
{
foreach (const SettingContainer *setting, *settings)
emit signalUpdateEditorSetting (setting->objectName(), setting->getValue());
}
else
{ {
if (settings->find(settingName) != settings->end()) if (!setting->definedValues().isEmpty())
{ return setting->definedValues().at(0);
const SettingContainer *setting = settings->value(settingName);
emit signalUpdateEditorSetting (setting->objectName(), setting->getValue());
}
} }
} return "";
QString CSMSettings::UserSettings::getSetting (const QString &section, const QString &setting) const
{
SettingMap *settings = getValidSettings(section);
QString retVal = "";
if (settings->find(setting) != settings->end())
retVal = settings->value(setting)->getValue();
return retVal;
} }
CSMSettings::UserSettings& CSMSettings::UserSettings::instance() CSMSettings::UserSettings& CSMSettings::UserSettings::instance()
@ -307,49 +277,3 @@ CSMSettings::UserSettings& CSMSettings::UserSettings::instance()
assert(mUserSettingsInstance); assert(mUserSettingsInstance);
return *mUserSettingsInstance; return *mUserSettingsInstance;
} }
void CSMSettings::UserSettings::displayFileErrorMessage(const QString &message, bool isReadOnly)
{
// 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();
}
CSMSettings::SettingMap *
CSMSettings::UserSettings::getValidSettings (const QString &sectionName) const
{
SettingMap *settings = 0;
//copy the default values for the entire section if it's not found
if (mSectionSettings.find(sectionName) == mSectionSettings.end())
{
if (mEditorSettingDefaults.find(sectionName) != mEditorSettingDefaults.end())
settings = mEditorSettingDefaults.value (sectionName);
}
//otherwise, iterate the section's settings, looking for missing values and replacing them with defaults.
else
{
SettingMap *loadedSettings = mSectionSettings[sectionName];
SettingMap *defaultSettings = mEditorSettingDefaults[sectionName];
foreach (QString key, defaultSettings->uniqueKeys())
{
//write the default value to the loaded settings
if (loadedSettings->find((key))==loadedSettings->end())
loadedSettings->insert(key, defaultSettings->value(key));
}
settings = mSectionSettings.value (sectionName);
}
return settings;
}

@ -8,7 +8,7 @@
#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>
@ -21,17 +21,15 @@ class QFile;
namespace CSMSettings { namespace CSMSettings {
struct UserSettings: public QObject class UserSettings: public SettingManager
{ {
Q_OBJECT Q_OBJECT
SectionMap mSectionSettings;
SectionMap mEditorSettingDefaults;
static UserSettings *mUserSettingsInstance; static UserSettings *mUserSettingsInstance;
QString mUserFilePath; QString mUserFilePath;
Files::ConfigurationManager mCfgMgr; Files::ConfigurationManager mCfgMgr;
QString mReadOnlyMessage; QString mReadOnlyMessage;
QString mReadWriteMessage; QString mReadWriteMessage;
@ -47,48 +45,19 @@ namespace CSMSettings {
void operator= (UserSettings const &); //not implemented void operator= (UserSettings const &); //not implemented
/// Writes settings to the last loaded settings file /// Writes settings to the last loaded settings file
bool writeSettings(QMap<QString, SettingList *> &sections); bool writeSettings();
/// Called from editor to trigger signal to update the specified setting.
/// If no setting name is specified, all settings found in the specified section are updated.
void updateSettings (const QString &sectionName, const QString &settingName = "");
/// Retrieves the settings file at all three levels (global, local and user). /// Retrieves the settings file at all three levels (global, local and user).
/// \todo Multi-valued settings are not fully implemented. Setting values
/// \todo loaded in later files will always overwrite previously loaded values.
void loadSettings (const QString &fileName); void loadSettings (const QString &fileName);
/// Returns the entire map of settings across all sections /// Writes settings to the user's config file path
const SectionMap &getSectionMap () const; void saveSettings (const QMap <QString, QStringList > &settingMap);
const SettingMap *getSettings (const QString &sectionName) const; QString settingValue (const QString &settingKey);
/// Retrieves the value as a QString of the specified setting in the specified section
QString getSetting(const QString &section, const QString &setting) const;
private: private:
void buildSettingModelDefaults();
/// Opens a QTextStream from the provided path as read-only or read-write.
QTextStream *openFileStream (const QString &filePath, bool isReadOnly = false) const;
/// Parses a setting file specified in filePath from the provided text stream.
bool loadFromFile (const QString &filePath = "");
/// merge the passed map into mSectionSettings
void mergeMap (const SectionMap &);
void displayFileErrorMessage(const QString &message, bool isReadOnly);
void buildEditorSettingDefaults();
SettingMap *getValidSettings (const QString &sectionName) const;
signals:
void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue);
}; };
} }
#endif // USERSETTINGS_HPP #endif // USERSETTINGS_HPP

@ -9,6 +9,9 @@
namespace CSMWorld namespace CSMWorld
{ {
/// \brief Wrapper for Cell record /// \brief Wrapper for Cell record
///
/// \attention The mData.mX and mData.mY fields of the ESM::Cell struct are not used.
/// Exterior cell coordinates are encoded in the cell ID.
struct Cell : public ESM::Cell struct Cell : public ESM::Cell
{ {
std::string mId; std::string mId;

@ -0,0 +1,60 @@
#include "cellcoordinates.hpp"
#include <ostream>
#include <sstream>
CSMWorld::CellCoordinates::CellCoordinates() : mX (0), mY (0) {}
CSMWorld::CellCoordinates::CellCoordinates (int x, int y) : mX (x), mY (y) {}
int CSMWorld::CellCoordinates::getX() const
{
return mX;
}
int CSMWorld::CellCoordinates::getY() const
{
return mY;
}
CSMWorld::CellCoordinates CSMWorld::CellCoordinates::move (int x, int y) const
{
return CellCoordinates (mX + x, mY + y);
}
std::string CSMWorld::CellCoordinates::getId (const std::string& worldspace) const
{
// we ignore the worldspace for now, since there is only one (will change in 1.1)
std::ostringstream stream;
stream << "#" << mX << " " << mY;
return stream.str();
}
bool CSMWorld::operator== (const CellCoordinates& left, const CellCoordinates& right)
{
return left.getX()==right.getX() && left.getY()==right.getY();
}
bool CSMWorld::operator!= (const CellCoordinates& left, const CellCoordinates& right)
{
return !(left==right);
}
bool CSMWorld::operator< (const CellCoordinates& left, const CellCoordinates& right)
{
if (left.getX()<right.getX())
return true;
if (left.getX()>right.getX())
return false;
return left.getY()<right.getY();
}
std::ostream& CSMWorld::operator<< (std::ostream& stream, const CellCoordinates& coordiantes)
{
return stream << coordiantes.getX() << ", " << coordiantes.getY();
}

@ -0,0 +1,42 @@
#ifndef CSM_WOLRD_CELLCOORDINATES_H
#define CSM_WOLRD_CELLCOORDINATES_H
#include <iosfwd>
#include <string>
#include <QMetaType>
namespace CSMWorld
{
class CellCoordinates
{
int mX;
int mY;
public:
CellCoordinates();
CellCoordinates (int x, int y);
int getX() const;
int getY() const;
CellCoordinates move (int x, int y) const;
///< Return a copy of *this, moved by the given offset.
std::string getId (const std::string& worldspace) const;
///< Return the ID for the cell at these coordinates.
};
bool operator== (const CellCoordinates& left, const CellCoordinates& right);
bool operator!= (const CellCoordinates& left, const CellCoordinates& right);
bool operator< (const CellCoordinates& left, const CellCoordinates& right);
std::ostream& operator<< (std::ostream& stream, const CellCoordinates& coordiantes);
}
Q_DECLARE_METATYPE (CSMWorld::CellCoordinates)
#endif

@ -0,0 +1,83 @@
#include "cellselection.hpp"
#include <cmath>
#include <stdexcept>
#include <limits>
CSMWorld::CellSelection::Iterator CSMWorld::CellSelection::begin() const
{
return mCells.begin();
}
CSMWorld::CellSelection::Iterator CSMWorld::CellSelection::end() const
{
return mCells.end();
}
bool CSMWorld::CellSelection::add (const CellCoordinates& coordinates)
{
return mCells.insert (coordinates).second;
}
void CSMWorld::CellSelection::remove (const CellCoordinates& coordinates)
{
mCells.erase (coordinates);
}
bool CSMWorld::CellSelection::has (const CellCoordinates& coordinates) const
{
return mCells.find (coordinates)!=end();
}
int CSMWorld::CellSelection::getSize() const
{
return mCells.size();
}
CSMWorld::CellCoordinates CSMWorld::CellSelection::getCentre() const
{
if (mCells.empty())
throw std::logic_error ("call of getCentre on empty cell selection");
double x = 0;
double y = 0;
for (Iterator iter = begin(); iter!=end(); ++iter)
{
x += iter->getX();
y += iter->getY();
}
x /= mCells.size();
y /= mCells.size();
Iterator closest = begin();
double distance = std::numeric_limits<double>::max();
for (Iterator iter (begin()); iter!=end(); ++iter)
{
double deltaX = x - iter->getX();
double deltaY = y - iter->getY();
double delta = std::sqrt (deltaX * deltaX + deltaY * deltaY);
if (delta<distance)
{
distance = delta;
closest = iter;
}
}
return *closest;
}
void CSMWorld::CellSelection::move (int x, int y)
{
Container moved;
for (Iterator iter = begin(); iter!=end(); ++iter)
moved.insert (iter->move (x, y));
mCells.swap (moved);
}

@ -0,0 +1,57 @@
#ifndef CSM_WOLRD_CELLSELECTION_H
#define CSM_WOLRD_CELLSELECTION_H
#include <set>
#include <QMetaType>
#include "cellcoordinates.hpp"
namespace CSMWorld
{
/// \brief Selection of cells in a paged worldspace
///
/// \note The CellSelection does not specify the worldspace it applies to.
class CellSelection
{
public:
typedef std::set<CellCoordinates> Container;
typedef Container::const_iterator Iterator;
private:
Container mCells;
public:
Iterator begin() const;
Iterator end() const;
bool add (const CellCoordinates& coordinates);
///< Ignored if the cell specified by \a coordinates is already part of the selection.
///
/// \return Was a cell added to the collection?
void remove (const CellCoordinates& coordinates);
///< ignored if the cell specified by \a coordinates is not part of the selection.
bool has (const CellCoordinates& coordinates) const;
///< \return Is the cell specified by \a coordinates part of the selection?
int getSize() const;
///< Return number of cells.
CellCoordinates getCentre() const;
///< Return the selected cell that is closest to the geometric centre of the selection.
///
/// \attention This function must not be called on selections that are empty.
void move (int x, int y);
};
}
Q_DECLARE_METATYPE (CSMWorld::CellSelection)
#endif

@ -785,7 +785,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct RegionColumn : public Column<ESXRecordT> struct RegionColumn : public Column<ESXRecordT>
{ {
RegionColumn() : Column<ESXRecordT> (Columns::ColumnId_Region, ColumnBase::Display_String) {} RegionColumn() : Column<ESXRecordT> (Columns::ColumnId_Region, ColumnBase::Display_Region) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {

@ -38,14 +38,3 @@ std::string CSMWorld::RefCollection::getNewId()
stream << "ref#" << mNextId++; stream << "ref#" << mNextId++;
return stream.str(); return stream.str();
} }
void CSMWorld::RefCollection::cloneRecord(const std::string& origin,
const std::string& destination,
const CSMWorld::UniversalId::Type type,
const CSMWorld::UniversalId::ArgumentType argumentType)
{
Record<CSMWorld::CellRef> clone(getRecord(origin));
clone.mState = CSMWorld::RecordBase::State_ModifiedOnly;
clone.get().mId = destination;
insertRecord(clone, getAppendIndex(destination, type), type);
}

@ -26,11 +26,6 @@ namespace CSMWorld
///< Load a sequence of references. ///< Load a sequence of references.
std::string getNewId(); std::string getNewId();
void cloneRecord(const std::string& origin,
const std::string& destination,
const CSMWorld::UniversalId::Type type,
const CSMWorld::UniversalId::ArgumentType argumentType);
}; };
} }

@ -1,6 +1,7 @@
#include "regionmap.hpp" #include "regionmap.hpp"
#include <cmath>
#include <algorithm> #include <algorithm>
#include <QBrush> #include <QBrush>
@ -25,17 +26,28 @@ CSMWorld::RegionMap::CellDescription::CellDescription (const Record<Cell>& cell)
mName = cell2.mName; mName = cell2.mName;
} }
CSMWorld::RegionMap::CellIndex CSMWorld::RegionMap::getIndex (const QModelIndex& index) const CSMWorld::CellCoordinates CSMWorld::RegionMap::getIndex (const QModelIndex& index) const
{ {
return CellIndex (index.column()+mMin.first, return mMin.move (index.column(), mMax.getY()-mMin.getY() - index.row()-1);
(mMax.second-mMin.second - index.row()-1)+mMin.second);
} }
QModelIndex CSMWorld::RegionMap::getIndex (const CellIndex& index) const QModelIndex CSMWorld::RegionMap::getIndex (const CellCoordinates& index) const
{ {
// I hate you, Qt API naming scheme! // I hate you, Qt API naming scheme!
return QAbstractTableModel::index (mMax.second-mMin.second - (index.second-mMin.second)-1, return QAbstractTableModel::index (mMax.getY()-mMin.getY() - (index.getY()-mMin.getY())-1,
index.first-mMin.first); index.getX()-mMin.getX());
}
CSMWorld::CellCoordinates CSMWorld::RegionMap::getIndex (const Cell& cell) const
{
std::istringstream stream (cell.mId);
char ignore;
int x = 0;
int y = 0;
stream >> ignore >> x >> y;
return CellCoordinates (x, y);
} }
void CSMWorld::RegionMap::buildRegions() void CSMWorld::RegionMap::buildRegions()
@ -70,21 +82,21 @@ void CSMWorld::RegionMap::buildMap()
{ {
CellDescription description (cell); CellDescription description (cell);
CellIndex index (cell2.mData.mX, cell2.mData.mY); CellCoordinates index = getIndex (cell2);
mMap.insert (std::make_pair (index, description)); mMap.insert (std::make_pair (index, description));
} }
} }
std::pair<CellIndex, CellIndex> mapSize = getSize(); std::pair<CellCoordinates, CellCoordinates> mapSize = getSize();
mMin = mapSize.first; mMin = mapSize.first;
mMax = mapSize.second; mMax = mapSize.second;
} }
void CSMWorld::RegionMap::addCell (const CellIndex& index, const CellDescription& description) void CSMWorld::RegionMap::addCell (const CellCoordinates& index, const CellDescription& description)
{ {
std::map<CellIndex, CellDescription>::iterator cell = mMap.find (index); std::map<CellCoordinates, CellDescription>::iterator cell = mMap.find (index);
if (cell!=mMap.end()) if (cell!=mMap.end())
{ {
@ -114,7 +126,7 @@ void CSMWorld::RegionMap::addCells (int start, int end)
if (cell2.isExterior()) if (cell2.isExterior())
{ {
CellIndex index (cell2.mData.mX, cell2.mData.mY); CellCoordinates index = getIndex (cell2);
CellDescription description (cell); CellDescription description (cell);
@ -123,9 +135,9 @@ void CSMWorld::RegionMap::addCells (int start, int end)
} }
} }
void CSMWorld::RegionMap::removeCell (const CellIndex& index) void CSMWorld::RegionMap::removeCell (const CellCoordinates& index)
{ {
std::map<CellIndex, CellDescription>::iterator cell = mMap.find (index); std::map<CellCoordinates, CellDescription>::iterator cell = mMap.find (index);
if (cell!=mMap.end()) if (cell!=mMap.end())
{ {
@ -160,7 +172,7 @@ void CSMWorld::RegionMap::updateRegions (const std::vector<std::string>& regions
std::for_each (regions2.begin(), regions2.end(), &Misc::StringUtils::lowerCase); std::for_each (regions2.begin(), regions2.end(), &Misc::StringUtils::lowerCase);
std::sort (regions2.begin(), regions2.end()); std::sort (regions2.begin(), regions2.end());
for (std::map<CellIndex, CellDescription>::const_iterator iter (mMap.begin()); for (std::map<CellCoordinates, CellDescription>::const_iterator iter (mMap.begin());
iter!=mMap.end(); ++iter) iter!=mMap.end(); ++iter)
{ {
if (!iter->second.mRegion.empty() && if (!iter->second.mRegion.empty() &&
@ -176,90 +188,57 @@ void CSMWorld::RegionMap::updateRegions (const std::vector<std::string>& regions
void CSMWorld::RegionMap::updateSize() void CSMWorld::RegionMap::updateSize()
{ {
std::pair<CellIndex, CellIndex> size = getSize(); std::pair<CellCoordinates, CellCoordinates> size = getSize();
if (int diff = size.first.getX() - mMin.getX())
{ {
int diff = size.first.first - mMin.first; beginInsertColumns (QModelIndex(), 0, std::abs (diff)-1);
mMin = CellCoordinates (size.first.getX(), mMin.getY());
if (diff<0) endInsertColumns();
{
beginInsertColumns (QModelIndex(), 0, -diff-1);
mMin.first = size.first.first;
endInsertColumns();
}
else if (diff>0)
{
beginRemoveColumns (QModelIndex(), 0, diff-1);
mMin.first = size.first.first;
endRemoveColumns();
}
} }
if (int diff = size.first.getY() - mMin.getY())
{ {
int diff = size.first.second - mMin.second; beginInsertRows (QModelIndex(), 0, std::abs (diff)-1);
mMin = CellCoordinates (mMin.getX(), size.first.getY());
if (diff<0) endInsertRows();
{
beginInsertRows (QModelIndex(), 0, -diff-1);
mMin.second = size.first.second;
endInsertRows();
}
else if (diff>0)
{
beginRemoveRows (QModelIndex(), 0, diff-1);
mMin.second = size.first.second;
endRemoveRows();
}
} }
if (int diff = size.second.getX() - mMax.getX())
{ {
int diff = size.second.first - mMax.first; int columns = columnCount();
if (diff>0) if (diff>0)
{
int columns = columnCount();
beginInsertColumns (QModelIndex(), columns, columns+diff-1); beginInsertColumns (QModelIndex(), columns, columns+diff-1);
mMax.first = size.second.first; else
endInsertColumns();
}
else if (diff<0)
{
int columns = columnCount();
beginRemoveColumns (QModelIndex(), columns+diff, columns-1); beginRemoveColumns (QModelIndex(), columns+diff, columns-1);
mMax.first = size.second.first;
endRemoveColumns(); mMax = CellCoordinates (size.second.getX(), mMax.getY());
} endInsertColumns();
} }
if (int diff = size.second.getY() - mMax.getY())
{ {
int diff = size.second.second - mMax.second; int rows = rowCount();
if (diff>0) if (diff>0)
{
int rows = rowCount();
beginInsertRows (QModelIndex(), rows, rows+diff-1); beginInsertRows (QModelIndex(), rows, rows+diff-1);
mMax.second = size.second.second; else
endInsertRows();
}
else if (diff<0)
{
int rows = rowCount();
beginRemoveRows (QModelIndex(), rows+diff, rows-1); beginRemoveRows (QModelIndex(), rows+diff, rows-1);
mMax.second = size.second.second;
endRemoveRows(); mMax = CellCoordinates (mMax.getX(), size.second.getY());
} endInsertRows();
} }
} }
std::pair<CSMWorld::RegionMap::CellIndex, CSMWorld::RegionMap::CellIndex> CSMWorld::RegionMap::getSize() std::pair<CSMWorld::CellCoordinates, CSMWorld::CellCoordinates> CSMWorld::RegionMap::getSize() const
const
{ {
const IdCollection<Cell>& cells = mData.getCells(); const IdCollection<Cell>& cells = mData.getCells();
int size = cells.getSize(); int size = cells.getSize();
CellIndex min (0, 0); CellCoordinates min (0, 0);
CellIndex max (0, 0); CellCoordinates max (0, 0);
for (int i=0; i<size; ++i) for (int i=0; i<size; ++i)
{ {
@ -269,24 +248,24 @@ std::pair<CSMWorld::RegionMap::CellIndex, CSMWorld::RegionMap::CellIndex> CSMWor
if (cell2.isExterior()) if (cell2.isExterior())
{ {
CellIndex index (cell2.mData.mX, cell2.mData.mY); CellCoordinates index = getIndex (cell2);
if (min==max) if (min==max)
{ {
min = index; min = index;
max = std::make_pair (min.first+1, min.second+1); max = min.move (1, 1);
} }
else else
{ {
if (index.first<min.first) if (index.getX()<min.getX())
min.first = index.first; min = CellCoordinates (index.getX(), min.getY());
else if (index.first>=max.first) else if (index.getX()>=max.getX())
max.first = index.first + 1; max = CellCoordinates (index.getX()+1, max.getY());
if (index.second<min.second) if (index.getY()<min.getY())
min.second = index.second; min = CellCoordinates (min.getX(), index.getY());
else if (index.second>=max.second) else if (index.getY()>=max.getY())
max.second = index.second + 1; max = CellCoordinates (max.getX(), index.getY() + 1);
} }
} }
} }
@ -323,7 +302,7 @@ int CSMWorld::RegionMap::rowCount (const QModelIndex& parent) const
if (parent.isValid()) if (parent.isValid())
return 0; return 0;
return mMax.second-mMin.second; return mMax.getY()-mMin.getY();
} }
int CSMWorld::RegionMap::columnCount (const QModelIndex& parent) const int CSMWorld::RegionMap::columnCount (const QModelIndex& parent) const
@ -331,7 +310,7 @@ int CSMWorld::RegionMap::columnCount (const QModelIndex& parent) const
if (parent.isValid()) if (parent.isValid())
return 0; return 0;
return mMax.first-mMin.first; return mMax.getX()-mMin.getX();
} }
QVariant CSMWorld::RegionMap::data (const QModelIndex& index, int role) const QVariant CSMWorld::RegionMap::data (const QModelIndex& index, int role) const
@ -343,7 +322,7 @@ QVariant CSMWorld::RegionMap::data (const QModelIndex& index, int role) const
{ {
/// \todo GUI class in non-GUI code. Needs to be addressed eventually. /// \todo GUI class in non-GUI code. Needs to be addressed eventually.
std::map<CellIndex, CellDescription>::const_iterator cell = std::map<CellCoordinates, CellDescription>::const_iterator cell =
mMap.find (getIndex (index)); mMap.find (getIndex (index));
if (cell!=mMap.end()) if (cell!=mMap.end())
@ -370,13 +349,13 @@ QVariant CSMWorld::RegionMap::data (const QModelIndex& index, int role) const
if (role==Qt::ToolTipRole) if (role==Qt::ToolTipRole)
{ {
CellIndex cellIndex = getIndex (index); CellCoordinates cellIndex = getIndex (index);
std::ostringstream stream; std::ostringstream stream;
stream << cellIndex.first << ", " << cellIndex.second; stream << cellIndex;
std::map<CellIndex, CellDescription>::const_iterator cell = std::map<CellCoordinates, CellDescription>::const_iterator cell =
mMap.find (cellIndex); mMap.find (cellIndex);
if (cell!=mMap.end()) if (cell!=mMap.end())
@ -406,15 +385,33 @@ QVariant CSMWorld::RegionMap::data (const QModelIndex& index, int role) const
return QString::fromUtf8 (stream.str().c_str()); return QString::fromUtf8 (stream.str().c_str());
} }
if (role==Role_Region)
{
CellCoordinates cellIndex = getIndex (index);
std::map<CellCoordinates, CellDescription>::const_iterator cell =
mMap.find (cellIndex);
if (cell!=mMap.end() && !cell->second.mRegion.empty())
return QString::fromUtf8 (Misc::StringUtils::lowerCase (cell->second.mRegion).c_str());
}
if (role==Role_CellId)
{
CellCoordinates cellIndex = getIndex (index);
std::ostringstream stream;
stream << "#" << cellIndex.getX() << " " << cellIndex.getY();
return QString::fromUtf8 (stream.str().c_str());
}
return QVariant(); return QVariant();
} }
Qt::ItemFlags CSMWorld::RegionMap::flags (const QModelIndex& index) const Qt::ItemFlags CSMWorld::RegionMap::flags (const QModelIndex& index) const
{ {
if (mMap.find (getIndex (index))!=mMap.end()) return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
return 0;
} }
void CSMWorld::RegionMap::regionsAboutToBeRemoved (const QModelIndex& parent, int start, int end) void CSMWorld::RegionMap::regionsAboutToBeRemoved (const QModelIndex& parent, int start, int end)
@ -491,11 +488,7 @@ void CSMWorld::RegionMap::cellsAboutToBeRemoved (const QModelIndex& parent, int
const Cell& cell2 = cell.get(); const Cell& cell2 = cell.get();
if (cell2.isExterior()) if (cell2.isExterior())
{ removeCell (getIndex (cell2));
CellIndex index (cell2.mData.mX, cell2.mData.mY);
removeCell (index);
}
} }
} }

@ -9,6 +9,7 @@
#include "record.hpp" #include "record.hpp"
#include "cell.hpp" #include "cell.hpp"
#include "cellcoordinates.hpp"
namespace CSMWorld namespace CSMWorld
{ {
@ -23,7 +24,11 @@ namespace CSMWorld
public: public:
typedef std::pair<int, int> CellIndex; enum Role
{
Role_Region = Qt::UserRole,
Role_CellId = Qt::UserRole+1
};
private: private:
@ -39,27 +44,29 @@ namespace CSMWorld
}; };
Data& mData; Data& mData;
std::map<CellIndex, CellDescription> mMap; std::map<CellCoordinates, CellDescription> mMap;
CellIndex mMin; ///< inclusive CellCoordinates mMin; ///< inclusive
CellIndex mMax; ///< exclusive CellCoordinates mMax; ///< exclusive
std::map<std::string, unsigned int> mColours; ///< region ID, colour (RGBA) std::map<std::string, unsigned int> mColours; ///< region ID, colour (RGBA)
CellIndex getIndex (const QModelIndex& index) const; CellCoordinates getIndex (const QModelIndex& index) const;
///< Translates a Qt model index into a cell index (which can contain negative components) ///< Translates a Qt model index into a cell index (which can contain negative components)
QModelIndex getIndex (const CellIndex& index) const; QModelIndex getIndex (const CellCoordinates& index) const;
CellCoordinates getIndex (const Cell& cell) const;
void buildRegions(); void buildRegions();
void buildMap(); void buildMap();
void addCell (const CellIndex& index, const CellDescription& description); void addCell (const CellCoordinates& index, const CellDescription& description);
///< May be called on a cell that is already in the map (in which case an update is ///< May be called on a cell that is already in the map (in which case an update is
// performed) // performed)
void addCells (int start, int end); void addCells (int start, int end);
void removeCell (const CellIndex& index); void removeCell (const CellCoordinates& index);
///< May be called on a cell that is not in the map (in which case the call is ignored) ///< May be called on a cell that is not in the map (in which case the call is ignored)
void addRegion (const std::string& region, unsigned int colour); void addRegion (const std::string& region, unsigned int colour);
@ -78,7 +85,7 @@ namespace CSMWorld
void updateSize(); void updateSize();
std::pair<CellIndex, CellIndex> getSize() const; std::pair<CellCoordinates, CellCoordinates> getSize() const;
public: public:
@ -89,6 +96,8 @@ namespace CSMWorld
virtual int columnCount (const QModelIndex& parent = QModelIndex()) const; virtual int columnCount (const QModelIndex& parent = QModelIndex()) const;
virtual QVariant data (const QModelIndex& index, int role = Qt::DisplayRole) const; virtual QVariant data (const QModelIndex& index, int role = Qt::DisplayRole) const;
///< \note Calling this function with role==Role_CellId may return the ID of a cell
/// that does not exist.
virtual Qt::ItemFlags flags (const QModelIndex& index) const; virtual Qt::ItemFlags flags (const QModelIndex& index) const;

@ -12,16 +12,15 @@ CSMWorld::UniversalId CSVDoc::SubView::getUniversalId() const
return mUniversalId; return mUniversalId;
} }
void CSVDoc::SubView::updateEditorSetting (const QString &settingName, const QString &settingValue)
{
}
void CSVDoc::SubView::setStatusBar (bool show) {} void CSVDoc::SubView::setStatusBar (bool show) {}
void CSVDoc::SubView::useHint (const std::string& hint) {} void CSVDoc::SubView::useHint (const std::string& hint) {}
void CSVDoc::SubView::updateUserSetting (const QString &, const QStringList &)
{}
void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id) void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id)
{ {
mUniversalId = id; mUniversalId = id;
setWindowTitle (mUniversalId.toString().c_str()); setWindowTitle (mUniversalId.toString().c_str());
} }

@ -37,7 +37,6 @@ namespace CSVDoc
CSMWorld::UniversalId getUniversalId() const; CSMWorld::UniversalId getUniversalId() const;
virtual void setEditLock (bool locked) = 0; virtual void setEditLock (bool locked) = 0;
virtual void updateEditorSetting (const QString &, const QString &);
virtual void setStatusBar (bool show); virtual void setStatusBar (bool show);
///< Default implementation: ignored ///< Default implementation: ignored
@ -48,6 +47,10 @@ namespace CSVDoc
signals: signals:
void focusId (const CSMWorld::UniversalId& universalId, const std::string& hint); void focusId (const CSMWorld::UniversalId& universalId, const std::string& hint);
public slots:
virtual void updateUserSetting
(const QString &, const QStringList &);
}; };
} }

@ -12,7 +12,7 @@
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
#include "../world/subviews.hpp" #include "../world/subviews.hpp"
#include "../tools/subviews.hpp" #include "../tools/subviews.hpp"
#include "../settings/usersettingsdialog.hpp" #include "../../model/settings/usersettings.hpp"
#include "viewmanager.hpp" #include "viewmanager.hpp"
#include "operations.hpp" #include "operations.hpp"
#include "subview.hpp" #include "subview.hpp"
@ -235,8 +235,11 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to
: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1),
mViewTotal (totalViews) mViewTotal (totalViews)
{ {
QString width = CSMSettings::UserSettings::instance().getSetting(QString("Window Size"), QString("Width")); QString width = CSMSettings::UserSettings::instance().settingValue
QString height = CSMSettings::UserSettings::instance().getSetting(QString("Window Size"), QString("Height")); ("Window Size.Width");
QString height = CSMSettings::UserSettings::instance().settingValue
("Window Size.Height");
resize (width.toInt(), height.toInt()); resize (width.toInt(), height.toInt());
@ -336,7 +339,10 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&)), this, connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&)), this,
SLOT (addSubView (const CSMWorld::UniversalId&, const std::string&))); SLOT (addSubView (const CSMWorld::UniversalId&, const std::string&)));
CSMSettings::UserSettings::instance().updateSettings("Display Format"); connect (&CSMSettings::UserSettings::instance(),
SIGNAL (userSettingUpdated (const QString &, const QStringList &)),
view,
SLOT (updateUserSetting (const QString &, const QStringList &)));
view->show(); view->show();
} }
@ -484,25 +490,9 @@ void CSVDoc::View::resizeViewHeight (int height)
resize (geometry().width(), height); resize (geometry().width(), height);
} }
void CSVDoc::View::updateEditorSetting (const QString &settingName, const QString &settingValue) void CSVDoc::View::updateUserSetting
{ (const QString &name, const QStringList &list)
if ( (settingName == "Record Status Display") || (settingName == "Referenceable ID Type Display") ) {}
{
foreach (QObject *view, mSubViewWindow.children())
{
// not all mSubviewWindow children are CSVDoc::Subview objects
CSVDoc::SubView *subview = dynamic_cast<CSVDoc::SubView *>(view);
if (subview)
subview->updateEditorSetting (settingName, settingValue);
}
}
else if (settingName == "Width")
resizeViewWidth (settingValue.toInt());
else if (settingName == "Height")
resizeViewHeight (settingValue.toInt());
}
void CSVDoc::View::toggleShowStatusBar (bool show) void CSVDoc::View::toggleShowStatusBar (bool show)
{ {

@ -126,6 +126,8 @@ namespace CSVDoc
void abortOperation (int type); void abortOperation (int type);
void updateUserSetting (const QString &, const QStringList &);
private slots: private slots:
void newView(); void newView();

@ -15,7 +15,8 @@
#include "../world/vartypedelegate.hpp" #include "../world/vartypedelegate.hpp"
#include "../world/recordstatusdelegate.hpp" #include "../world/recordstatusdelegate.hpp"
#include "../world/idtypedelegate.hpp" #include "../world/idtypedelegate.hpp"
#include "../settings/usersettingsdialog.hpp"
#include "../../model/settings/usersettings.hpp"
#include "view.hpp" #include "view.hpp"
@ -83,9 +84,6 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
for (std::size_t i=0; i<sizeof (sMapping)/sizeof (Mapping); ++i) for (std::size_t i=0; i<sizeof (sMapping)/sizeof (Mapping); ++i)
mDelegateFactories->add (sMapping[i].mDisplay, new CSVWorld::EnumDelegateFactory ( mDelegateFactories->add (sMapping[i].mDisplay, new CSVWorld::EnumDelegateFactory (
CSMWorld::Columns::getEnums (sMapping[i].mColumnId), sMapping[i].mAllowNone)); CSMWorld::Columns::getEnums (sMapping[i].mColumnId), sMapping[i].mAllowNone));
connect (&CSMSettings::UserSettings::instance(), SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)),
this, SLOT (slotUpdateEditorSetting (const QString &, const QString &)));
} }
CSVDoc::ViewManager::~ViewManager() CSVDoc::ViewManager::~ViewManager()
@ -119,6 +117,11 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
connect (view, SIGNAL (loadDocumentRequest ()), this, SIGNAL (loadDocumentRequest())); connect (view, SIGNAL (loadDocumentRequest ()), this, SIGNAL (loadDocumentRequest()));
connect (view, SIGNAL (editSettingsRequest()), this, SIGNAL (editSettingsRequest())); connect (view, SIGNAL (editSettingsRequest()), this, SIGNAL (editSettingsRequest()));
connect (&CSMSettings::UserSettings::instance(),
SIGNAL (userSettingUpdated(const QString &, const QStringList &)),
view,
SLOT (updateUserSetting (const QString &, const QStringList &)));
updateIndices(); updateIndices();
return view; return view;
@ -313,9 +316,3 @@ void CSVDoc::ViewManager::exitApplication (CSVDoc::View *view)
if (notifySaveOnClose (view)) if (notifySaveOnClose (view))
QApplication::instance()->exit(); QApplication::instance()->exit();
} }
void CSVDoc::ViewManager::slotUpdateEditorSetting (const QString &settingName, const QString &settingValue)
{
foreach (CSVDoc::View *view, mViews)
view->updateEditorSetting (settingName, settingValue);
}

@ -76,9 +76,6 @@ namespace CSVDoc
void progress (int current, int max, int type, int threads, CSMDoc::Document *document); void progress (int current, int max, int type, int threads, CSMDoc::Document *document);
void onExitWarningHandler(int state, CSMDoc::Document* document); void onExitWarningHandler(int state, CSMDoc::Document* document);
/// connected to update signal in UserSettings
void slotUpdateEditorSetting (const QString &, const QString &);
}; };
} }

@ -193,11 +193,4 @@ std::string CSVFilter::EditWidget::generateFilter (std::pair< std::string, std::
} }
return ss.str(); return ss.str();
} }
void CSVFilter::EditWidget::useFilterRequest (const std::string& idOfFilter)
{
clear();
insert(QString::fromUtf8(idOfFilter.c_str()));
}

@ -30,6 +30,9 @@ namespace CSVFilter
EditWidget (CSMWorld::Data& data, QWidget *parent = 0); EditWidget (CSMWorld::Data& data, QWidget *parent = 0);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action);
signals: signals:
void filterChanged (boost::shared_ptr<CSMFilter::Node> filter); void filterChanged (boost::shared_ptr<CSMFilter::Node> filter);
@ -47,10 +50,7 @@ namespace CSVFilter
void filterRowsInserted (const QModelIndex& parent, int start, int end); void filterRowsInserted (const QModelIndex& parent, int start, int end);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action);
void useFilterRequest(const std::string& idOfFilter);
}; };
} }

@ -15,23 +15,24 @@ CSVFilter::FilterBox::FilterBox (CSMWorld::Data& data, QWidget *parent)
layout->setContentsMargins (0, 0, 0, 0); layout->setContentsMargins (0, 0, 0, 0);
RecordFilterBox *recordFilterBox = new RecordFilterBox (data, this); mRecordFilterBox = new RecordFilterBox (data, this);
layout->addWidget (recordFilterBox); layout->addWidget (mRecordFilterBox);
setLayout (layout); setLayout (layout);
connect (recordFilterBox, connect (mRecordFilterBox,
SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)), SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)),
this, SIGNAL (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>))); this, SIGNAL (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)));
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)),
recordFilterBox, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
connect(this, SIGNAL(useFilterRequest(const std::string&)), recordFilterBox, SIGNAL(useFilterRequest(const std::string&)));
setAcceptDrops(true); setAcceptDrops(true);
} }
void CSVFilter::FilterBox::setRecordFilter (const std::string& filter)
{
mRecordFilterBox->setFilter (filter);
}
void CSVFilter::FilterBox::dropEvent (QDropEvent* event) void CSVFilter::FilterBox::dropEvent (QDropEvent* event)
{ {
std::vector<CSMWorld::UniversalId> data = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData())->getData(); std::vector<CSMWorld::UniversalId> data = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData())->getData();
@ -48,3 +49,9 @@ void CSVFilter::FilterBox::dragMoveEvent (QDragMoveEvent* event)
{ {
event->accept(); event->accept();
} }
void CSVFilter::FilterBox::createFilterRequest (std::vector< std::pair< std::string, std::vector< std::string > > >& filterSource,
Qt::DropAction action)
{
mRecordFilterBox->createFilterRequest(filterSource, action);
}

@ -16,27 +16,33 @@ namespace CSMWorld
namespace CSVFilter namespace CSVFilter
{ {
class RecordFilterBox;
class FilterBox : public QWidget class FilterBox : public QWidget
{ {
Q_OBJECT Q_OBJECT
RecordFilterBox *mRecordFilterBox;
public:
FilterBox (CSMWorld::Data& data, QWidget *parent = 0);
void setRecordFilter (const std::string& filter);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action);
private:
void dragEnterEvent (QDragEnterEvent* event); void dragEnterEvent (QDragEnterEvent* event);
void dropEvent (QDropEvent* event); void dropEvent (QDropEvent* event);
void dragMoveEvent(QDragMoveEvent *event); void dragMoveEvent(QDragMoveEvent *event);
public:
FilterBox (CSMWorld::Data& data, QWidget *parent = 0);
signals: signals:
void recordFilterChanged (boost::shared_ptr<CSMFilter::Node> filter); void recordFilterChanged (boost::shared_ptr<CSMFilter::Node> filter);
void recordDropped (std::vector<CSMWorld::UniversalId>& types, Qt::DropAction action); void recordDropped (std::vector<CSMWorld::UniversalId>& types, Qt::DropAction action);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action);
void useFilterRequest(const std::string& idOfFilter);
}; };
} }

@ -15,18 +15,25 @@ CSVFilter::RecordFilterBox::RecordFilterBox (CSMWorld::Data& data, QWidget *pare
layout->addWidget (new QLabel ("Record Filter", this)); layout->addWidget (new QLabel ("Record Filter", this));
EditWidget *editWidget = new EditWidget (data, this); mEdit = new EditWidget (data, this);
layout->addWidget (editWidget); layout->addWidget (mEdit);
setLayout (layout); setLayout (layout);
connect ( connect (
editWidget, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)), mEdit, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)),
this, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>))); this, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)));
}
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)), void CSVFilter::RecordFilterBox::setFilter (const std::string& filter)
editWidget, SLOT(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction))); {
mEdit->clear();
mEdit->setText (QString::fromUtf8 (filter.c_str()));
}
connect(this, SIGNAL(useFilterRequest(const std::string&)), editWidget, SLOT(useFilterRequest(const std::string&))); void CSVFilter::RecordFilterBox::createFilterRequest (std::vector< std::pair< std::string, std::vector< std::string > > >& filterSource,
Qt::DropAction action)
{
mEdit->createFilterRequest(filterSource, action);
} }

@ -17,20 +17,28 @@ namespace CSMWorld
namespace CSVFilter namespace CSVFilter
{ {
class EditWidget;
class RecordFilterBox : public QWidget class RecordFilterBox : public QWidget
{ {
Q_OBJECT Q_OBJECT
EditWidget *mEdit;
public: public:
RecordFilterBox (CSMWorld::Data& data, QWidget *parent = 0); RecordFilterBox (CSMWorld::Data& data, QWidget *parent = 0);
signals: void setFilter (const std::string& filter);
void useFilterRequest(const std::string& idOfFilter);
void filterChanged (boost::shared_ptr<CSMFilter::Node> filter);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource, void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action); Qt::DropAction action);
void useFilterRequest(const std::string& idOfFilter);
signals:
void filterChanged (boost::shared_ptr<CSMFilter::Node> filter);
}; };
} }

@ -1,6 +1,47 @@
#include "pagedworldspacewidget.hpp" #include "pagedworldspacewidget.hpp"
#include <sstream>
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent) CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent)
: WorldspaceWidget (parent) : WorldspaceWidget (parent)
{} {}
void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint)
{
if (!hint.empty())
{
CSMWorld::CellSelection selection;
if (hint[0]=='c')
{
// syntax: c:#x1 y1; #x2 y2 (number of coordinate pairs can be 0 or larger)
char ignore;
std::istringstream stream (hint.c_str());
if (stream >> ignore)
{
char ignore1; // : or ;
char ignore2; // #
int x, y;
while (stream >> ignore1 >> ignore2 >> x >> y)
selection.add (CSMWorld::CellCoordinates (x, y));
/// \todo adjust camera position
}
}
else if (hint[0]=='r')
{
/// \todo implement 'r' type hints
}
setCellSelection (selection);
}
}
void CSVRender::PagedWorldspaceWidget::setCellSelection (const CSMWorld::CellSelection& selection)
{
mSelection = selection;
emit cellSelectionChanged (mSelection);
}

@ -1,6 +1,8 @@
#ifndef OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H #ifndef OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H
#define OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H #define OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H
#include "../../model/world/cellselection.hpp"
#include "worldspacewidget.hpp" #include "worldspacewidget.hpp"
namespace CSVRender namespace CSVRender
@ -9,9 +11,22 @@ namespace CSVRender
{ {
Q_OBJECT Q_OBJECT
CSMWorld::CellSelection mSelection;
public: public:
PagedWorldspaceWidget (QWidget *parent); PagedWorldspaceWidget (QWidget *parent);
///< \note Sets the cell area selection to an invalid value to indicate that currently
/// no cells are displayed. The cells to be displayed will be specified later through
/// hint system.
virtual void useViewHint (const std::string& hint);
void setCellSelection (const CSMWorld::CellSelection& selection);
signals:
void cellSelectionChanged (const CSMWorld::CellSelection& selection);
}; };
} }

@ -26,6 +26,8 @@ void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
setNavigation (&mOrbit); setNavigation (&mOrbit);
} }
void CSVRender::WorldspaceWidget::useViewHint (const std::string& hint) {}
void CSVRender::WorldspaceWidget::selectDefaultNavigationMode() void CSVRender::WorldspaceWidget::selectDefaultNavigationMode()
{ {
setNavigation (&m1st); setNavigation (&m1st);

@ -33,6 +33,9 @@ namespace CSVRender
void selectDefaultNavigationMode(); void selectDefaultNavigationMode();
virtual void useViewHint (const std::string& hint);
///< Default-implementation: ignored.
private slots: private slots:
void selectNavigationMode (const std::string& mode); void selectNavigationMode (const std::string& mode);

@ -1,112 +0,0 @@
#include "abstractblock.hpp"
CSVSettings::AbstractBlock::AbstractBlock(QWidget* parent)
: QObject (parent), mBox ( new GroupBox (parent) ), mWidgetParent (parent)
{}
CSVSettings::AbstractBlock::AbstractBlock(bool isVisible, QWidget* parent)
: QObject (parent), mBox ( new GroupBox (isVisible, parent)), mWidgetParent (parent)
{}
QLayout *CSVSettings::AbstractBlock::createLayout (Orientation direction,
bool isZeroMargin, QWidget* parent)
{
QLayout *layout = 0;
if (direction == Orient_Vertical)
layout = new QVBoxLayout (parent);
else
layout = new QHBoxLayout (parent);
if (isZeroMargin)
layout->setContentsMargins(0, 0, 0, 0);
return layout;
}
QGroupBox *CSVSettings::AbstractBlock::getGroupBox()
{
return mBox;
}
CSVSettings::AbstractWidget *CSVSettings::AbstractBlock::buildWidget (const QString& widgetName, WidgetDef &def,
QLayout *layout, bool isConnected) const
{
AbstractWidget *widg = 0;
switch (def.type)
{
case Widget_RadioButton:
widg = new SettingWidget<QRadioButton> (def, layout, mBox);
break;
case Widget_SpinBox:
widg = new SettingWidget<QSpinBox> (def, layout, mBox);
break;
case Widget_CheckBox:
widg = new SettingWidget<QCheckBox> (def, layout, mBox);
break;
case Widget_LineEdit:
widg = new SettingWidget<QLineEdit> (def, layout, mBox);
break;
case Widget_ListBox:
widg = new SettingWidget<QListWidget> (def, layout, mBox);
break;
case Widget_ComboBox:
widg = new SettingWidget<QComboBox> (def, layout, mBox);
break;
default:
break;
};
if (!mBox->layout())
mBox->setLayout(widg->getLayout());
widg->widget()->setObjectName(widgetName);
if (isConnected)
connect (widg, SIGNAL (signalUpdateItem (const QString &)), this, SLOT (slotUpdate (const QString &)));
connect (this, SIGNAL (signalUpdateWidget (const QString &)), widg, SLOT (slotUpdateWidget (const QString &) ));
return widg;
}
void CSVSettings::AbstractBlock::setVisible (bool isVisible)
{
mBox->setBorderVisibility (isVisible);
}
bool CSVSettings::AbstractBlock::isVisible () const
{
return mBox->borderVisibile();
}
QWidget *CSVSettings::AbstractBlock::getParent() const
{
return mWidgetParent;
}
void CSVSettings::AbstractBlock::slotUpdate (const QString &value)
{
slotUpdateSetting (objectName(), value);
}
void CSVSettings::AbstractBlock::slotSetEnabled(bool value)
{
mBox->setEnabled(value);
}
void CSVSettings::AbstractBlock::slotUpdateSetting (const QString &settingName, const QString &settingValue)
{
bool doEmit = true;
updateBySignal (settingName, settingValue, doEmit);
if (doEmit)
emit signalUpdateSetting (settingName, settingValue);
}

@ -1,82 +0,0 @@
#ifndef ABSTRACTBLOCK_HPP
#define ABSTRACTBLOCK_HPP
#include <QObject>
#include <QList>
#include "settingwidget.hpp"
#include "../../model/settings/settingsitem.hpp"
#include "groupbox.hpp"
namespace CSVSettings
{
/// Abstract base class for all blocks
class AbstractBlock : public QObject
{
Q_OBJECT
protected:
typedef QMap<QString, CSMSettings::SettingsItem*> SettingsItemMap;
GroupBox *mBox;
QWidget *mWidgetParent;
public:
explicit AbstractBlock (QWidget *parent = 0);
explicit AbstractBlock (bool isVisible, QWidget *parent = 0);
QGroupBox *getGroupBox();
void setVisible (bool isVisible);
bool isVisible() const;
virtual CSMSettings::SettingList *getSettings() = 0;
/// update settings found in the passed map and are encapsulated by the block
virtual bool updateSettings (const CSMSettings::SettingMap &settings) = 0;
/// update callback function called from update slot
/// used for updating application-level settings in the editor
virtual bool updateBySignal (const QString &name, const QString &value, bool &doEmit)
{ return false; }
protected:
/// Creates the layout for the block's QGroupBox
QLayout *createLayout (Orientation direction, bool isZeroMargin, QWidget* parent = 0);
/// Creates widgets that exist as direct children of the block
AbstractWidget *buildWidget (const QString &widgetName, WidgetDef &wDef,
QLayout *layout = 0, bool isConnected = true) const;
QWidget *getParent() const;
public slots:
/// enables / disables block-level widgets based on signals from other widgets
/// used in ToggleBlock
void slotSetEnabled (bool value);
/// receives updates to applicaion-level settings in the Editor
void slotUpdateSetting (const QString &settingName, const QString &settingValue);
private slots:
/// receives updates to a setting in the block pushed from the application level
void slotUpdate (const QString &value);
signals:
/// signal to UserSettings instance
void signalUpdateSetting (const QString &propertyName, const QString &propertyValue);
/// signal to widget for updating widget value
void signalUpdateWidget (const QString & value);
/// ProxyBlock use only.
/// Name and value correspond to settings for which the block is a proxy.
void signalUpdateProxySetting (const QString &propertyName, const QString &propertyValue);
};
}
#endif // ABSTRACTBLOCK_HPP

@ -1,44 +0,0 @@
#include "abstractpage.hpp"
#include <QGroupBox>
#include <QLabel>
#include <QVBoxLayout>
#include <QRadioButton>
#include <QCheckBox>
#include <QSpinBox>
#include <QComboBox>
#include <QLineEdit>
#include <QMargins>
CSVSettings::AbstractPage::AbstractPage(QWidget *parent):
QWidget(parent)
{
QGridLayout *pageLayout = new QGridLayout(this);
setLayout (pageLayout);
}
CSVSettings::AbstractPage::AbstractPage(const QString &pageName, QWidget *parent):
QWidget(parent)
{
QWidget::setObjectName (pageName);
QGridLayout *pageLayout = new QGridLayout(this);
setLayout (pageLayout);
}
CSVSettings::AbstractPage::~AbstractPage()
{
}
CSMSettings::SettingList *CSVSettings::AbstractPage::getSettings()
{
CSMSettings::SettingList *settings = new CSMSettings::SettingList();
foreach (AbstractBlock *block, mAbstractBlocks)
{
CSMSettings::SettingList *groupSettings = block->getSettings();
settings->append (*groupSettings);
}
return settings;
}

@ -1,70 +0,0 @@
#ifndef ABSTRACTPAGE_HPP
#define ABSTRACTPAGE_HPP
#include <QWidget>
#include <QList>
#include <QLayout>
#include "abstractblock.hpp"
class SettingMap;
class SettingList;
namespace CSVSettings {
typedef QList<AbstractBlock *> AbstractBlockList;
/// Abstract base class for all setting pages in the dialog
/// \todo Scripted implementation of settings should eliminate the need
/// \todo derive page classes.
/// \todo AbstractPage should be replaced with a general page construction class.
class AbstractPage: public QWidget
{
protected:
AbstractBlockList mAbstractBlocks;
public:
AbstractPage(QWidget *parent = 0);
AbstractPage (const QString &pageName, QWidget* parent = 0);
~AbstractPage();
virtual void setupUi() = 0;
/// triggers widgiet initialization at the page level. All widgets updated to
/// current setting values
virtual void initializeWidgets (const CSMSettings::SettingMap &settings) = 0;
/// retrieve the list of settings local to the page.
CSMSettings::SettingList *getSettings();
void setObjectName();
protected:
/// Create a block for the page.
/// Block is constructed using passed definition struct
/// Page level-layout is created and assigned
template <typename S, typename T>
AbstractBlock *buildBlock (T *def)
{
S *block = new S (this);
int ret = block->build (def);
if (ret < 0)
return 0;
QGroupBox *box = block->getGroupBox();
QWidget::layout()->addWidget (box);
return block;
}
};
}
#endif // ABSTRACTPAGE_HPP

@ -1,78 +0,0 @@
#include "abstractwidget.hpp"
#include <QLayout>
#include <QLabel>
void CSVSettings::AbstractWidget::build(QWidget *widget, WidgetDef &def, bool noLabel)
{
if (!mLayout)
createLayout(def.orientation, true);
buildLabelAndWidget (widget, def, noLabel);
}
void CSVSettings::AbstractWidget::buildLabelAndWidget (QWidget *widget, WidgetDef &def, bool noLabel)
{
if (def.widgetWidth > -1)
widget->setFixedWidth (def.widgetWidth);
if (!(def.caption.isEmpty() || noLabel) )
{
QLabel *label = new QLabel (def.caption, &dynamic_cast<QWidget &>( *parent()));
label->setBuddy (widget);
mLayout->addWidget (label);
if (def.labelWidth > -1)
label->setFixedWidth(def.labelWidth);
}
mLayout->addWidget (widget);
mLayout->setAlignment (widget, getAlignment (def.widgetAlignment));
}
void CSVSettings::AbstractWidget::createLayout
(Orientation direction, bool isZeroMargin)
{
if (direction == Orient_Vertical)
mLayout = new QVBoxLayout ();
else
mLayout = new QHBoxLayout ();
if (isZeroMargin)
mLayout->setContentsMargins(0, 0, 0, 0);
}
QFlags<Qt::AlignmentFlag> CSVSettings::AbstractWidget::getAlignment (CSVSettings::Alignment flag)
{
return QFlags<Qt::AlignmentFlag>(static_cast<int>(flag));
}
QLayout *CSVSettings::AbstractWidget::getLayout()
{
return mLayout;
}
void CSVSettings::AbstractWidget::slotUpdateWidget (const QString &value)
{
updateWidget (value);
}
void CSVSettings::AbstractWidget::slotUpdateItem(const QString &value)
{
emit signalUpdateItem (value);
}
void CSVSettings::AbstractWidget::slotUpdateItem(bool value)
{
if (value)
emit signalUpdateItem (widget()->objectName());
}
void CSVSettings::AbstractWidget::slotUpdateItem(int value)
{
emit signalUpdateItem (QString::number(value));
}
void CSVSettings::AbstractWidget::slotUpdateItem (QListWidgetItem* current, QListWidgetItem* previous)
{}

@ -1,69 +0,0 @@
#ifndef ABSTRACTWIDGET_HPP
#define ABSTRACTWIDGET_HPP
#include <QWidget>
#include "support.hpp"
class QLayout;
namespace CSVSettings
{
/// Abstract base class for widgets which are used in user preferences dialog
class AbstractWidget : public QObject
{
Q_OBJECT
QLayout *mLayout;
public:
/// Passed layout is assigned the constructed widget.
/// if no layout is passed, one is created.
explicit AbstractWidget (QLayout *layout = 0, QWidget* parent = 0)
: QObject (parent), mLayout (layout)
{}
/// retrieve layout for insertion into itemblock
QLayout *getLayout();
/// create the derived widget instance
void build (QWidget* widget, WidgetDef &def, bool noLabel = false);
/// reference to the derived widget instance
virtual QWidget *widget() = 0;
protected:
/// Callback called by receiving slot for widget udpates
virtual void updateWidget (const QString &value) = 0;
/// Converts user-defined enum to Qt equivalents
QFlags<Qt::AlignmentFlag> getAlignment (Alignment flag);
private:
/// Creates layout and assigns label and widget as appropriate
void createLayout (Orientation direction, bool isZeroMargin);
/// Creates label and widget according to passed definition
void buildLabelAndWidget (QWidget *widget, WidgetDef &def, bool noLabel);
signals:
/// outbound update signal
void signalUpdateItem (const QString &value);
public slots:
/// receives inbound updates
void slotUpdateWidget (const QString &value);
/// Overloads for outbound updates from derived widget signal
void slotUpdateItem (const QString &value);
void slotUpdateItem (bool value);
void slotUpdateItem (int value);
void slotUpdateItem (QListWidgetItem* current, QListWidgetItem* previous);
};
}
#endif // ABSTRACTWIDGET_HPP

@ -1,50 +0,0 @@
#include "blankpage.hpp"
#include <QList>
#include <QListView>
#include <QGroupBox>
#include <QRadioButton>
#include <QDockWidget>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QStyle>
#ifdef Q_OS_MAC
#include <QPlastiqueStyle>
#endif
#include "../../model/settings/usersettings.hpp"
#include "groupblock.hpp"
#include "toggleblock.hpp"
CSVSettings::BlankPage::BlankPage(QWidget *parent):
AbstractPage("Blank", parent)
{
}
CSVSettings::BlankPage::BlankPage(const QString &title, QWidget *parent):
AbstractPage(title, parent)
{
// Hacks to get the stylesheet look properly
#ifdef Q_OS_MAC
QPlastiqueStyle *style = new QPlastiqueStyle;
//profilesComboBox->setStyle(style);
#endif
setupUi();
}
void CSVSettings::BlankPage::setupUi()
{
QGroupBox *pageBox = new QGroupBox(this);
layout()->addWidget(pageBox);
}
void CSVSettings::BlankPage::initializeWidgets (const CSMSettings::SettingMap &settings)
{
//iterate each item in each blocks in this section
//validate the corresponding setting against the defined valuelist if any.
foreach (AbstractBlock *block, mAbstractBlocks)
block->updateSettings (settings);
}

@ -1,28 +0,0 @@
#ifndef BLANKPAGE_HPP
#define BLANKPAGE_HPP
#include "abstractpage.hpp"
class QGroupBox;
namespace CSVSettings {
class UserSettings;
class AbstractBlock;
/// Derived page with no widgets
/// Reference use only.
class BlankPage : public AbstractPage
{
public:
BlankPage (QWidget *parent = 0);
BlankPage (const QString &title, QWidget *parent);
void setupUi();
void initializeWidgets (const CSMSettings::SettingMap &settings);
};
}
#endif // BLANKPAGE_HPP

@ -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);
}

@ -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

@ -1,121 +0,0 @@
#include "customblock.hpp"
#include "groupblock.hpp"
#include "itemblock.hpp"
#include "proxyblock.hpp"
CSVSettings::CustomBlock::CustomBlock (QWidget *parent) : AbstractBlock (parent)
{
}
int CSVSettings::CustomBlock::build(GroupBlockDefList &defList, GroupBlockDefList::iterator *it)
{
int retVal = 0;
GroupBlockDefList::iterator defaultIt;
GroupBlockDefList::iterator listIt = defList.begin();
GroupBlockDefList::iterator proxyIt = defaultIt;
if (it)
listIt = *it;
ProxyBlock *proxyBlock = new ProxyBlock(getParent());
for (; listIt != defList.end(); ++listIt)
{
if (!(*listIt)->isProxy)
retVal = buildGroupBlock (*listIt);
else
{
mGroupList << proxyBlock;
proxyIt = listIt;
}
}
if (proxyIt != defaultIt)
retVal = buildProxyBlock (*proxyIt, proxyBlock);
return retVal;
}
CSVSettings::GroupBox *CSVSettings::CustomBlock::buildGroupBox (Orientation orientation)
{
GroupBox *box = new GroupBox (false, mBox);
createLayout (orientation, true, box);
return box;
}
int CSVSettings::CustomBlock::buildGroupBlock(GroupBlockDef *def)
{
GroupBlock *block = new GroupBlock (getParent());
mGroupList << block;
connect (block, SIGNAL (signalUpdateSetting(const QString &, const QString &)),
this, SLOT (slotUpdateSetting (const QString &, const QString &)));
return block->build(def);
}
int CSVSettings::CustomBlock::buildProxyBlock(GroupBlockDef *def, ProxyBlock *block)
{
if (def->settingItems.size() != 1)
return -1;
int retVal = block->build(def);
if (retVal != 0)
return retVal;
// The first settingItem is the proxy setting, containing the list of settings bound to it.
foreach (QStringList *list, *(def->settingItems.at(0)->proxyList))
{
QString proxiedBlockName = list->at(0);
//iterate each group in the custom block, matching it to each proxied setting
//and connecting it appropriately
foreach (GroupBlock *groupBlock, mGroupList)
{
ItemBlock *proxiedBlock = groupBlock->getItemBlock (proxiedBlockName);
if (proxiedBlock)
{
block->addSetting(proxiedBlock, list);
//connect the proxy block's update signal to the custom block's slot
connect (block, SIGNAL (signalUpdateSetting (const QString &, const QString &)),
this, SLOT (slotUpdateSetting (const QString &, const QString &)));
}
}
}
return 0;
}
CSMSettings::SettingList *CSVSettings::CustomBlock::getSettings()
{
CSMSettings::SettingList *settings = new CSMSettings::SettingList();
foreach (GroupBlock *block, mGroupList)
{
CSMSettings::SettingList *groupSettings = block->getSettings();
if (groupSettings)
settings->append(*groupSettings);
}
return settings;
}
bool CSVSettings::CustomBlock::updateSettings (const CSMSettings::SettingMap &settings)
{
bool success = true;
foreach (GroupBlock *block, mGroupList)
{
bool success2 = block->updateSettings (settings);
success = success && success2;
}
return success;
}

@ -1,47 +0,0 @@
#ifndef CUSTOMBLOCK_HPP
#define CUSTOMBLOCK_HPP
#include "abstractblock.hpp"
namespace CSVSettings
{
class ProxyBlock;
/// Base class for customized user preference setting blocks
/// Special block classes should be derived from CustomBlock
class CustomBlock : public AbstractBlock
{
protected:
GroupBlockList mGroupList;
public:
explicit CustomBlock (QWidget *parent = 0);
/// Update settings local to the block
bool updateSettings (const CSMSettings::SettingMap &settings);
/// Retrieve settings local to the block
CSMSettings::SettingList *getSettings();
/// construct the block using the passed definition
int build (GroupBlockDefList &defList, GroupBlockDefList::Iterator *it = 0);
protected:
/// construct the block groupbox
GroupBox *buildGroupBox (Orientation orientation);
private:
/// Construction function for creating a standard GroupBlock child
int buildGroupBlock(GroupBlockDef *def);
/// Construction function for creating a standard ProxyBlock child
int buildProxyBlock(GroupBlockDef *def, ProxyBlock *block);
};
}
#endif // CUSTOMBLOCK_HPP

@ -1,57 +0,0 @@
#include "datadisplayformatpage.hpp"
#include "groupblock.hpp"
#include "../../model/settings/usersettings.hpp"
CSVSettings::DataDisplayFormatPage::DataDisplayFormatPage(QWidget* parent) :
AbstractPage("Display Format", parent)
{
setupUi();
}
CSVSettings::GroupBlockDef *CSVSettings::DataDisplayFormatPage::setupDataDisplay( const QString &title)
{
GroupBlockDef *statusBlock = new GroupBlockDef(QString(title));
SettingsItemDef *statusItem = new SettingsItemDef (statusBlock->title, "Icon Only");
*(statusItem->valueList) << QString("Icon and Text") << QString("Icon Only") << QString("Text Only");
WidgetDef statusWidget (Widget_RadioButton);
statusWidget.valueList = statusItem->valueList;
statusItem->widget = statusWidget;
statusBlock->settingItems << statusItem;
statusBlock->isZeroMargin = false;
return statusBlock;
}
void CSVSettings::DataDisplayFormatPage::setupUi()
{
mAbstractBlocks << buildBlock<GroupBlock> (setupDataDisplay ("Record Status Display"));
mAbstractBlocks << buildBlock<GroupBlock> (setupDataDisplay ("Referenceable ID Type Display"));
foreach (AbstractBlock *block, mAbstractBlocks)
{
connect (block, SIGNAL (signalUpdateSetting (const QString &, const QString &)),
this, SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)) );
}
connect ( this,
SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)),
&(CSMSettings::UserSettings::instance()),
SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)));
}
void CSVSettings::DataDisplayFormatPage::initializeWidgets (const CSMSettings::SettingMap &settings)
{
//iterate each item in each blocks in this section
//validate the corresponding setting against the defined valuelist if any.
for (AbstractBlockList::Iterator it_block = mAbstractBlocks.begin();
it_block != mAbstractBlocks.end(); ++it_block)
(*it_block)->updateSettings (settings);
}

@ -1,33 +0,0 @@
#ifndef EDITORPAGE_HPP
#define EDITORPAGE_HPP
#include "support.hpp"
#include "abstractpage.hpp"
namespace CSVSettings
{
class DataDisplayFormatPage : public AbstractPage
{
Q_OBJECT
public:
explicit DataDisplayFormatPage(QWidget *parent = 0);
void initializeWidgets (const CSMSettings::SettingMap &settings);
void setupUi();
private:
/// User preference view of the record status delegate's icon / text setting
GroupBlockDef *setupDataDisplay(const QString &);
signals:
/// Signals up for changes to editor application-level settings
void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue);
public slots:
};
}
#endif // EDITORPAGE_HPP

@ -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();
}

@ -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

@ -1,53 +0,0 @@
#include "editorpage.hpp"
#include "groupblock.hpp"
#include "../../model/settings/usersettings.hpp"
CSVSettings::EditorPage::EditorPage(QWidget* parent) :
AbstractPage("Display Format", parent)
{
setupUi();
}
CSVSettings::GroupBlockDef *CSVSettings::EditorPage::setupRecordStatusDisplay()
{
GroupBlockDef *statusBlock = new GroupBlockDef(QString("Record Status Display"));
SettingsItemDef *statusItem = new SettingsItemDef (statusBlock->title, "Icon and Text");
*(statusItem->valueList) << QString("Icon and Text") << QString("Icon Only") << QString("Text Only");
WidgetDef statusWidget (Widget_RadioButton);
statusWidget.valueList = statusItem->valueList;
statusItem->widget = statusWidget;
statusBlock->settingItems << statusItem;
return statusBlock;
}
void CSVSettings::EditorPage::setupUi()
{
mAbstractBlocks << buildBlock<GroupBlock>(setupRecordStatusDisplay());
foreach (AbstractBlock *block, mAbstractBlocks)
{
connect (block, SIGNAL (signalUpdateSetting (const QString &, const QString &)),
this, SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)) );
}
connect ( this,
SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)),
&(CSMSettings::UserSettings::instance()),
SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)));
}
void CSVSettings::EditorPage::initializeWidgets (const CSMSettings::SettingMap &settings)
{
//iterate each item in each blocks in this section
//validate the corresponding setting against the defined valuelist if any.
for (AbstractBlockList::Iterator it_block = mAbstractBlocks.begin();
it_block != mAbstractBlocks.end(); ++it_block)
(*it_block)->updateSettings (settings);
}

@ -1,33 +0,0 @@
#ifndef EDITORPAGE_HPP
#define EDITORPAGE_HPP
#include "support.hpp"
#include "abstractpage.hpp"
namespace CSVSettings
{
class EditorPage : public AbstractPage
{
Q_OBJECT
public:
explicit EditorPage(QWidget *parent = 0);
void initializeWidgets (const CSMSettings::SettingMap &settings);
void setupUi();
private:
/// User preference view of the record status delegate's icon / text setting
GroupBlockDef *setupRecordStatusDisplay();
signals:
/// Signals up for changes to editor application-level settings
void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue);
public slots:
};
}
#endif // EDITORPAGE_HPP

@ -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;
}

@ -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

@ -1,108 +0,0 @@
#include "groupblock.hpp"
#include "itemblock.hpp"
CSVSettings::GroupBlock::GroupBlock (QWidget* parent)
: AbstractBlock (parent)
{}
CSVSettings::GroupBlock::GroupBlock (bool isVisible, QWidget *parent)
: AbstractBlock (isVisible, parent)
{}
int CSVSettings::GroupBlock::build (GroupBlockDef *def)
{
if (def->settingItems.size() == 0)
return -1;
int retVal = 0;
setVisible (def->isVisible);
mBox->setLayout(createLayout (def->widgetOrientation, def->isZeroMargin));
setObjectName (def->title);
mBox->setTitle (def->title);
foreach (SettingsItemDef *itemDef, def->settingItems)
{
ItemBlock *block = new ItemBlock (mBox);
if (block->build (*itemDef) < 0)
{
retVal = -2;
break;
}
mItemBlockList << block;
mBox->layout()->addWidget (block->getGroupBox());
connect (block, SIGNAL (signalUpdateSetting (const QString &, const QString &)),
this, SLOT (slotUpdateSetting (const QString &, const QString &) ));
}
return retVal;
}
CSMSettings::SettingList *CSVSettings::GroupBlock::getSettings()
{
CSMSettings::SettingList *settings = 0;
foreach (ItemBlock *block, mItemBlockList)
{
if (!settings)
settings = new CSMSettings::SettingList();
settings->append(*(block->getSettings ()));
}
return settings;
}
CSVSettings::ItemBlock *CSVSettings::GroupBlock::getItemBlock (const QString &name, ItemBlockList *blockList)
{
ItemBlock *retBlock = 0;
if (!blockList)
blockList = &mItemBlockList;
foreach (ItemBlock *block, *blockList)
{
if (block->objectName() == name)
{
retBlock = block;
break;
}
}
return retBlock;
}
CSVSettings::ItemBlock *CSVSettings::GroupBlock::getItemBlock (int index)
{
ItemBlock *retBlock = 0;
if (mItemBlockList.size() > index)
retBlock = mItemBlockList.at(index);
return retBlock;
}
bool CSVSettings::GroupBlock::updateSettings (const CSMSettings::SettingMap &settings)
{
bool success = true;
//update all non-proxy settings
foreach (ItemBlock *block, mItemBlockList)
{
CSMSettings::SettingContainer *setting = settings[block->objectName()];
if (setting)
{
bool success2 = block->update (setting->getValue());
success = success && success2;
}
}
return success;
}

@ -1,43 +0,0 @@
#ifndef GROUPBLOCK_HPP
#define GROUPBLOCK_HPP
#include <QList>
#include "abstractblock.hpp"
namespace CSVSettings
{
class ItemBlock;
/// Base class for group blocks.
/// Derived block classes should use CustomBlock
class GroupBlock : public AbstractBlock
{
ItemBlockList mItemBlockList;
public:
GroupBlock (QWidget* parent = 0);
GroupBlock (bool isVisible, QWidget *parent = 0);
/// build the gorup block based on passed definition
int build (GroupBlockDef *def);
/// update settings local to the group block
bool updateSettings (const CSMSettings::SettingMap &settings);
/// retrieve setting list local to the group block
CSMSettings::SettingList *getSettings();
/// retrieve item block by name from the passed list or local list
ItemBlock *getItemBlock (const QString &name, ItemBlockList *blockList = 0);
/// retrieve the item block by index from the local list
ItemBlock *getItemBlock (int index);
protected:
/// create block layout based on passed definition
int buildLayout (GroupBlockDef &def);
};
}
#endif // GROUPBLOCK_HPP

@ -1,56 +0,0 @@
#include "groupbox.hpp"
const QString CSVSettings::GroupBox::INVISIBLE_BOX_STYLE =
QString::fromUtf8("QGroupBox { border: 0px; padding 0px; margin: 0px;}");
CSVSettings::GroupBox::GroupBox(QWidget *parent) :
QGroupBox (parent)
{
initBox();
}
CSVSettings::GroupBox::GroupBox (bool isVisible, QWidget *parent) :
QGroupBox (parent)
{
initBox(isVisible);
}
void CSVSettings::GroupBox::initBox(bool isVisible)
{
setFlat (true);
VISIBLE_BOX_STYLE = styleSheet();
if (!isVisible)
setStyleSheet (INVISIBLE_BOX_STYLE);
}
bool CSVSettings::GroupBox::borderVisibile() const
{
return (styleSheet() != INVISIBLE_BOX_STYLE);
}
void CSVSettings::GroupBox::setTitle (const QString &title)
{
if (borderVisibile() )
{
QGroupBox::setTitle (title);
setMinimumWidth();
}
}
void CSVSettings::GroupBox::setBorderVisibility (bool value)
{
if (value)
setStyleSheet(VISIBLE_BOX_STYLE);
else
setStyleSheet(INVISIBLE_BOX_STYLE);
}
void CSVSettings::GroupBox::setMinimumWidth()
{
//set minimum width to accommodate title, if needed
//1.5 multiplier to account for bold title.
QFontMetrics fm (font());
int minWidth = fm.width(title());
QGroupBox::setMinimumWidth (minWidth * 1.5);
}

@ -1,28 +0,0 @@
#ifndef GROUPBOX_HPP
#define GROUPBOX_HPP
#include <QGroupBox>
namespace CSVSettings
{
/// Custom implementation of QGroupBox to be used with block classes
class GroupBox : public QGroupBox
{
static const QString INVISIBLE_BOX_STYLE;
QString VISIBLE_BOX_STYLE; //not a const...
public:
explicit GroupBox (QWidget *parent = 0);
explicit GroupBox (bool isVisible, QWidget *parent = 0);
void setTitle (const QString &title);
void setBorderVisibility (bool value);
bool borderVisibile() const;
private:
void setMinimumWidth();
void initBox(bool isVisible = true);
};
}
#endif // GROUPBOX_HPP

@ -1,115 +0,0 @@
#include "itemblock.hpp"
#include <QFontMetrics>
CSVSettings::ItemBlock::ItemBlock (QWidget* parent)
: mSetting (0), AbstractBlock (false, parent)
{
}
int CSVSettings::ItemBlock::build(SettingsItemDef &iDef)
{
buildItemBlock (iDef);
buildItemBlockWidgets (iDef);
return 0;
}
void CSVSettings::ItemBlock::buildItemBlockWidgets (SettingsItemDef &iDef)
{
WidgetDef wDef = iDef.widget;
QLayout *blockLayout = 0;
QString defaultValue = iDef.defaultValue;
switch (wDef.type)
{
case Widget_CheckBox:
case Widget_RadioButton:
foreach (QString item, *(iDef.valueList))
{
wDef.caption = item;
wDef.isDefault = (item == defaultValue);
blockLayout = buildWidget (item, wDef, blockLayout)->getLayout();
}
break;
case Widget_ComboBox:
case Widget_ListBox:
//assign the item's value list to the widget's value list.
//pass through to default to finish widget construction.
if (!wDef.valueList)
wDef.valueList = iDef.valueList;
default:
//only one instance of this non-list widget type.
//Set it's value to the default value for the item and build the widget.
if (wDef.value.isEmpty())
wDef.value = iDef.defaultValue;
buildWidget (iDef.name, wDef);
}
}
void CSVSettings::ItemBlock::buildItemBlock (SettingsItemDef &iDef)
{
QString defaultValue = iDef.defaultValue;
setObjectName(iDef.name);
mSetting = new CSMSettings::SettingsItem (objectName(),
iDef.hasMultipleValues, iDef.defaultValue,
parent());
if (iDef.valueList)
mSetting->setValueList(iDef.valueList);
if (!iDef.minMax.isEmpty())
mSetting->setValuePair(iDef.minMax);
}
bool CSVSettings::ItemBlock::update (const QString &value)
{
bool success = updateItem (value);
if (success)
signalUpdateWidget (value);
return success;
}
bool CSVSettings::ItemBlock::updateItem (const QString &value)
{
return mSetting->updateItem(value);
}
bool CSVSettings::ItemBlock::updateBySignal(const QString &name, const QString &value, bool &doEmit)
{
bool success = (mSetting->getValue() != value);
if (success)
success = updateItem(value);
return success;
}
CSMSettings::SettingList *CSVSettings::ItemBlock::getSettings ()
{
CSMSettings::SettingList *list = new CSMSettings::SettingList();
list->push_back(mSetting);
return list;
}
QString CSVSettings::ItemBlock::getValue() const
{
return mSetting->getValue();
}

@ -1,48 +0,0 @@
#ifndef ITEMBLOCK_HPP
#define ITEMBLOCK_HPP
#include "abstractblock.hpp"
namespace CSVSettings
{
class ItemBlock : public AbstractBlock
{
CSMSettings::SettingsItem *mSetting;
WidgetList mWidgetList;
public:
ItemBlock (QWidget* parent = 0);
/// pure virtual function not implemented
bool updateSettings (const CSMSettings::SettingMap &settings) { return false; }
CSMSettings::SettingList *getSettings ();
QString getValue () const;
/// item blocks encapsulate only one setting
int getSettingCount();
/// update setting value and corresponding widget
bool update (const QString &value);
/// virtual construction function
int build(SettingsItemDef &iDef);
private:
/// custom construction function
void buildItemBlock (SettingsItemDef& iDef);
void buildItemBlockWidgets (SettingsItemDef& iDef);
/// update the setting value
bool updateItem (const QString &);
/// callback function triggered when update to application level is signalled
bool updateBySignal (const QString &name, const QString &value, bool &doEmit);
};
}
#endif // ITEMBLOCK_HPP

@ -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)
{
updateView();
}
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);
}

@ -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

@ -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(),
SLOT (updateUserSetting (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);
}

@ -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

@ -1,152 +0,0 @@
#include "proxyblock.hpp"
#include "itemblock.hpp"
CSVSettings::ProxyBlock::ProxyBlock (QWidget *parent)
: GroupBlock (parent)
{
}
int CSVSettings::ProxyBlock::build (GroupBlockDef *proxyDef)
{
//get the list of pre-defined values for the proxy
mValueList = proxyDef->settingItems.at(0)->valueList;
bool success = GroupBlock::build(proxyDef);
//connect the item block of the proxy setting to the proxy-update slot
connect (getItemBlock(0), SIGNAL (signalUpdateSetting(const QString &, const QString &)),
this, SLOT (slotUpdateProxySetting (const QString &, const QString &)));
return success;
}
void CSVSettings::ProxyBlock::addSetting (ItemBlock *settingBlock, QStringList *proxyList)
{
//connect the item block of the proxied seting to the generic update slot
connect (settingBlock, SIGNAL (signalUpdateSetting(const QString &, const QString &)),
this, SLOT (slotUpdateProxySetting(const QString &, const QString &)));
mProxiedItemBlockList << settingBlock;
mProxyList << proxyList;
}
bool CSVSettings::ProxyBlock::updateSettings (const CSMSettings::SettingMap &settings)
{
return updateByProxiedSettings(&settings);
}
bool CSVSettings::ProxyBlock::updateBySignal(const QString &name, const QString &value, bool &doEmit)
{
doEmit = false;
return updateProxiedSettings();
}
void CSVSettings::ProxyBlock::slotUpdateProxySetting (const QString &name, const QString &value)
{
updateByProxiedSettings();
}
bool CSVSettings::ProxyBlock::updateProxiedSettings()
{
foreach (ItemBlock *block, mProxiedItemBlockList)
{
QString value = getItemBlock(0)->getValue();
bool success = false;
int i = 0;
//find the value index of the selected value in the proxy setting
for (; i < mValueList->size(); ++i)
{
success = (value == mValueList->at(i));
if (success)
break;
}
if (!success)
return false;
// update the containing the proxied item's name
foreach (QStringList *list, mProxyList)
{
if ( list->at(0) == block->objectName())
block->update (list->at(++i));
}
}
return true;
}
bool CSVSettings::ProxyBlock::updateByProxiedSettings(const CSMSettings::SettingMap *settings)
{
bool success = false;
int commonIndex = -1;
//update all proxy settings based on values from non-proxies
foreach (QStringList *list, mProxyList)
{
//Iterate each proxy item's proxied setting list, getting the current values
//Compare those value indices.
//If indices match, they correlate to one of the proxy's values in it's value list
//first value is always the name of the setting the proxy setting manages
QStringList::Iterator itProxyValue = list->begin();
QString proxiedSettingName = (*itProxyValue);
QString proxiedSettingValue = "";
itProxyValue++;
if (!settings)
{
//get the actual setting value
ItemBlock *block = getProxiedItemBlock (proxiedSettingName);
if (block)
proxiedSettingValue = block->getValue();
}
else
proxiedSettingValue = (*settings)[proxiedSettingName]->getValue();
int j = 0;
//iterate each value in the proxy string list
for (; itProxyValue != (list)->end(); ++itProxyValue)
{
success = ((*itProxyValue) == proxiedSettingValue);
if (success)
break;
j++;
}
//break if no match was found
if ( !success )
break;
if (commonIndex != -1)
success = (commonIndex == j);
else
commonIndex = j;
//break if indices were found, but mismatch
if (!success)
break;
}
//if successful, the proxied setting values match a pre-defined value in the
//proxy's value list. Set the proxy to that value index
if (success)
{
ItemBlock *block = getItemBlock(0);
if (block)
block->update (mValueList->at(commonIndex));
}
return success;
}
CSVSettings::ItemBlock *CSVSettings::ProxyBlock::getProxiedItemBlock (const QString &name)
{
return getItemBlock (name, &mProxiedItemBlockList);
}

@ -1,52 +0,0 @@
#ifndef PROXYBLOCK_HPP
#define PROXYBLOCK_HPP
#include "groupblock.hpp"
namespace CSVSettings
{
class ProxyBlock : public GroupBlock
{
Q_OBJECT
/// TODO: Combine mProxyItemBlockList and mProxyList.
ItemBlockList mProxiedItemBlockList;
ProxyList mProxyList;
QStringList *mValueList;
public:
explicit ProxyBlock (QWidget *parent = 0);
explicit ProxyBlock (ItemBlock *proxyItemBlock, QWidget *parent = 0);
/// Add a block that contains a proxied setting to the proxy block.
void addSetting (ItemBlock* settingBlock, QStringList *proxyList);
int build (GroupBlockDef *def);
CSMSettings::SettingList *getSettings() { return 0; }
/// Update settings local to the proxy block pushed from application level
bool updateSettings (const CSMSettings::SettingMap &settings);
/// callback function triggered when update to the application level is signaled.
bool updateBySignal (const QString &name, const QString &value, bool &doEmit);
private:
/// return the item block of a proxied setting
ItemBlock *getProxiedItemBlock (const QString &name);
/// update the proxy setting with data from the proxied settings
bool updateByProxiedSettings(const CSMSettings::SettingMap *settings = 0);
/// update proxied settings with data from the proxy setting
bool updateProxiedSettings();
private slots:
void slotUpdateProxySetting (const QString &name, const QString &value);
};
}
#endif // PROXYBLOCK_HPP

@ -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);
}

@ -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

@ -1 +0,0 @@
#include "settingwidget.hpp"

@ -1,214 +0,0 @@
#ifndef SETTINGWIDGET_HPP
#define SETTINGWIDGET_HPP
#include <QLabel>
#include <QCheckBox>
#include <QSpinBox>
#include <QLineEdit>
#include <QRadioButton>
#include <QComboBox>
#include <QListWidget>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include "abstractwidget.hpp"
namespace CSVSettings
{
/// Generic template for radiobuttons / checkboxes
template <typename T1>
class SettingWidget : public AbstractWidget
{
T1 *mWidget;
public:
explicit SettingWidget (WidgetDef &def, QLayout *layout, QWidget* parent = 0)
: AbstractWidget (layout, parent), mWidget (new T1 (parent))
{
mWidget->setText(def.caption);
build (mWidget, def, true);
mWidget->setChecked(def.isDefault);
connect (mWidget, SIGNAL (toggled (bool)),
this, SLOT (slotUpdateItem (bool)));
}
QWidget *widget() { return mWidget; }
private:
void updateWidget (const QString &value)
{
if ( value == mWidget->objectName() && !mWidget->isChecked() )
mWidget->setChecked (true);
}
};
/// spin box template
template <>
class SettingWidget <QSpinBox>: public AbstractWidget
{
QSpinBox *mWidget;
public:
SettingWidget (WidgetDef &def, QLayout *layout, QWidget *parent = 0)
: AbstractWidget (layout, parent), mWidget (new QSpinBox (parent))
{
def.caption += tr(" (%1 to %2)").arg(def.minMax->left).arg(def.minMax->right);
mWidget->setMaximum (def.minMax->right.toInt());
mWidget->setMinimum (def.minMax->left.toInt());
mWidget->setValue (def.value.toInt());
build (mWidget, def);
connect (mWidget, SIGNAL (valueChanged (int)),
this, SLOT (slotUpdateItem (int)));
mWidget->setAlignment (getAlignment(def.valueAlignment));
}
QWidget *widget() { return mWidget; }
private:
void updateWidget (const QString &value)
{
int intVal = value.toInt();
if (intVal >= mWidget->minimum() && intVal <= mWidget->maximum() && intVal != mWidget->value())
mWidget->setValue (intVal);
}
signals:
};
/// combo box template
template <>
class SettingWidget <QComboBox>: public CSVSettings::AbstractWidget
{
QComboBox *mWidget;
public:
explicit SettingWidget(WidgetDef &def, QLayout *layout, QWidget *parent = 0)
: AbstractWidget (layout, parent), mWidget (new QComboBox (parent))
{
int i = 0;
foreach (QString item, *(def.valueList))
{
mWidget->addItem (item);
if (item == def.value)
mWidget->setCurrentIndex(i);
i++;
}
build (mWidget, def);
connect (mWidget, SIGNAL (currentIndexChanged (const QString &)),
this, SLOT (slotUpdateItem (const QString &)));
//center the combo box items
mWidget->setEditable (true);
mWidget->lineEdit()->setReadOnly (true);
mWidget->lineEdit()->setAlignment (getAlignment(def.valueAlignment));
QFlags<Qt::AlignmentFlag> alignment = mWidget->lineEdit()->alignment();
for (int j = 0; j < mWidget->count(); j++)
mWidget->setItemData (j, QVariant(alignment), Qt::TextAlignmentRole);
}
QWidget *widget() { return mWidget; }
private:
void updateWidget (const QString &value)
{
if (mWidget->currentText() != value)
mWidget->setCurrentIndex(mWidget->findText(value));
}
};
/// line edit template
template <>
class SettingWidget <QLineEdit>: public CSVSettings::AbstractWidget
{
QLineEdit *mWidget;
public:
explicit SettingWidget(WidgetDef &def, QLayout *layout, QWidget *parent = 0)
: AbstractWidget (layout, parent), mWidget (new QLineEdit (parent))
{
if (!def.inputMask.isEmpty())
mWidget->setInputMask (def.inputMask);
mWidget->setText (def.value);
build (mWidget, def);
connect (mWidget, SIGNAL (textChanged (const QString &)),
this, SLOT (slotUpdateItem (const QString &)));
mWidget->setAlignment (getAlignment(def.valueAlignment));
}
QWidget *widget() { return mWidget; }
void updateWidget (const QString &value)
{
if (mWidget->text() != value)
mWidget->setText(value);
}
};
/// list widget template
/// \todo Not fully implemented. Only widget supporting multi-valued settings
template <>
class SettingWidget <QListWidget>: public CSVSettings::AbstractWidget
{
QListWidget *mWidget;
public:
explicit SettingWidget(WidgetDef &def, QLayout *layout, QWidget *parent = 0 )
: AbstractWidget (layout, parent), mWidget (new QListWidget (parent))
{
int i = 0;
foreach (QString item, *(def.valueList))
{
mWidget->addItem (item);
if (item == def.value) {}
i++;
}
build (mWidget, def);
}
QWidget *widget() { return mWidget; }
private:
void updateWidget (const QString &value) {}
};
}
#endif // SETTINGWIDGET_HPP

@ -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();
}

@ -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

@ -1 +0,0 @@
#include "support.hpp"

@ -1,206 +0,0 @@
#ifndef VIEW_SUPPORT_HPP
#define VIEW_SUPPORT_HPP
#include <QList>
#include <QStringList>
#include "../../model/settings/support.hpp"
namespace CSVSettings
{
struct WidgetDef;
class ItemBlock;
class GroupBlock;
struct GroupBlockDef;
typedef QList<GroupBlockDef *> GroupBlockDefList;
typedef QList<GroupBlock *> GroupBlockList;
typedef QList<ItemBlock *> ItemBlockList;
typedef QList<QStringList *> ProxyList;
typedef QList<WidgetDef *> WidgetList;
typedef QMap<QString, ItemBlock *> ItemBlockMap;
enum Orientation
{
Orient_Horizontal,
Orient_Vertical
};
enum WidgetType
{
Widget_CheckBox,
Widget_ComboBox,
Widget_LineEdit,
Widget_ListBox,
Widget_RadioButton,
Widget_SpinBox,
Widget_Undefined
};
enum Alignment
{
Align_Left = Qt::AlignLeft,
Align_Center = Qt::AlignHCenter,
Align_Right = Qt::AlignRight
};
/// definition struct for widgets
struct WidgetDef
{
/// type of widget providing input
WidgetType type;
/// width of caption label
int labelWidth;
/// width of input widget
int widgetWidth;
/// label / widget orientation (horizontal / vertical)
Orientation orientation;
/// input mask (line edit only)
QString inputMask;
/// label caption. Leave empty for multiple items. See BlockDef::captionList
QString caption;
/// widget value. Leave empty for multiple items. See BlockDef::valueList
QString value;
/// Min/Max QString value pair. If empty, assigned to property item value pair.
CSMSettings::QStringPair *minMax;
/// value list for list widgets. If left empty, is assigned to property item value list during block build().
QStringList *valueList;
/// determined at runtime
bool isDefault;
/// left / center / right-justify text in widget
Alignment valueAlignment;
/// left / center / right-justify widget in group box
Alignment widgetAlignment;
WidgetDef() : labelWidth (-1), widgetWidth (-1),
orientation (Orient_Horizontal),
isDefault (true), valueAlignment (Align_Center),
widgetAlignment (Align_Right),
inputMask (""), value (""),
caption (""), valueList (0)
{}
WidgetDef (WidgetType widgType)
: type (widgType), orientation (Orient_Horizontal),
caption (""), value (""), valueAlignment (Align_Center),
widgetAlignment (Align_Right),
labelWidth (-1), widgetWidth (-1),
valueList (0), isDefault (true)
{}
};
/// Defines the attributes of the setting as it is represented in the config file
/// as well as the UI elements (group box and widget) that serve it.
/// Only one widget may serve as the input widget for the setting.
struct SettingsItemDef
{
/// setting name
QString name;
/// list of valid values for the setting
QStringList *valueList;
/// Used to populate option widget captions or list widget item lists (see WidgetDef::caption / value)
QString defaultValue;
/// flag indicating multi-valued setting
bool hasMultipleValues;
/// minimum / maximum value pair
CSMSettings::QStringPair minMax;
/// definition of the input widget for this setting
WidgetDef widget;
/// general orientation of the widget / label for this setting
Orientation orientation;
/// list of settings and corresponding default values for proxy widget
ProxyList *proxyList;
SettingsItemDef() : name (""), defaultValue (""), orientation (Orient_Vertical), hasMultipleValues (false)
{}
SettingsItemDef (QString propName, QString propDefault, Orientation propOrient = Orient_Vertical)
: name (propName), defaultValue (propDefault), orientation (propOrient),
hasMultipleValues(false), valueList (new QStringList), proxyList ( new ProxyList)
{}
};
/// Generic container block
struct GroupBlockDef
{
/// block title
QString title;
/// list of captions for widgets at the block level (not associated with any particular setting)
QStringList captions;
/// list of widgets at the block level (not associated with any particular setting)
WidgetList widgets;
/// list of the settings which are subordinate to the setting block.
QList<SettingsItemDef *> settingItems;
/// general orientation of widgets in group block
Orientation widgetOrientation;
/// determines whether or not box border/title are visible
bool isVisible;
/// indicates whether or not this block defines a proxy block
bool isProxy;
/// generic default value attribute
QString defaultValue;
/// shows / hides margins
bool isZeroMargin;
GroupBlockDef (): title(""), widgetOrientation (Orient_Vertical), isVisible (true), isProxy (false), defaultValue (""), isZeroMargin (true)
{}
GroupBlockDef (QString blockTitle)
: title (blockTitle), widgetOrientation (Orient_Vertical), isProxy (false), isVisible (true), defaultValue (""), isZeroMargin (true)
{}
};
/// used to create unique, complex blocks
struct CustomBlockDef
{
/// block title
QString title;
/// default value for widgets unique to the custom block
QString defaultValue;
/// list of settings groups that comprise the settings within the custom block
GroupBlockDefList blockDefList;
/// orientation of the widgets within the block
Orientation blockOrientation;
CustomBlockDef (): title (""), defaultValue (""), blockOrientation (Orient_Horizontal)
{}
CustomBlockDef (const QString &blockTitle)
: title (blockTitle), defaultValue (""), blockOrientation (Orient_Horizontal)
{}
};
}
#endif // VIEW_SUPPORT_HPP

@ -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);
}

@ -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

@ -1,80 +0,0 @@
#include "toggleblock.hpp"
#include "groupblock.hpp"
#include "groupbox.hpp"
#include "itemblock.hpp"
CSVSettings::ToggleBlock::ToggleBlock(QWidget *parent) :
CustomBlock(parent)
{}
int CSVSettings::ToggleBlock::build(CustomBlockDef *def)
{
if (def->blockDefList.size()==0)
return -1;
QList<GroupBlockDef *>::Iterator it = def->blockDefList.begin();
//first def in the list is the def for the toggle block
GroupBlockDef *toggleDef = *it++;
if (toggleDef->captions.size() != def->blockDefList.size()-1 )
return -2;
if (toggleDef->widgets.size() == 0)
return -3;
//create the toogle block UI structure
QLayout *blockLayout = createLayout (def->blockOrientation, true);
GroupBox *propertyBox = buildGroupBox (toggleDef->widgetOrientation);
mBox->setLayout(blockLayout);
mBox->setTitle (toggleDef->title);
//build the blocks contained in the def list
//this manages proxy block construction.
//Any settings managed by the proxy setting
//must be included in the blocks defined in the list.
CustomBlock::build (def->blockDefList, &it);
for (GroupBlockList::iterator it = mGroupList.begin(); it != mGroupList.end(); ++it)
propertyBox->layout()->addWidget ((*it)->getGroupBox());
//build togle widgets, linking them to the settings
GroupBox *toggleBox = buildToggleWidgets (toggleDef, def->defaultValue);
blockLayout->addWidget(toggleBox);
blockLayout->addWidget(propertyBox);
blockLayout->setAlignment (propertyBox, Qt::AlignRight);
return 0;
}
CSVSettings::GroupBox *CSVSettings::ToggleBlock::buildToggleWidgets (GroupBlockDef *def, QString &defaultToggle)
{
GroupBox *box = new GroupBox (false, getParent());
QLayout *layout = createLayout (def->widgetOrientation, true, static_cast<QWidget *>(box));
for (int i = 0; i < def->widgets.size(); ++i)
{
QString caption = def->captions.at(i);
WidgetDef *wDef = def->widgets.at(i);
wDef->caption = caption;
wDef->widgetAlignment = Align_Left;
AbstractWidget *widg = buildWidget (caption, *wDef, layout, false);
GroupBlock *block = mGroupList.at(i);
//connect widget's update to the property block's enabled status
connect (widg->widget(), SIGNAL (toggled (bool)), block, SLOT (slotSetEnabled(bool)));
//enable the default toggle option
block->getGroupBox()->setEnabled( caption == defaultToggle );
layout = widg->getLayout();
}
return box;
}

@ -1,29 +0,0 @@
#ifndef TOGGLEBLOCK_HPP
#define TOGGLEBLOCK_HPP
#include <QObject>
#include "customblock.hpp"
namespace CSVSettings
{
class GroupBlock;
class GroupBox;
class ToggleWidget;
class ItemBlock;
class ToggleBlock : public CustomBlock
{
public:
explicit ToggleBlock(QWidget *parent = 0);
int build (CustomBlockDef *def);
private:
/// Constructor for toggle widgets that are specific to toggle block
/// Widgets are not a part of the user preference settings
GroupBox *buildToggleWidgets (GroupBlockDef *def, QString &defaultToggle);
};
}
#endif // TOGGLEBLOCK_HPP

@ -1,119 +0,0 @@
#include "usersettingsdialog.hpp"
#include <boost/filesystem/path.hpp>
#include <QApplication>
#include <QDesktopWidget>
#include <QWidget>
#include <QTabWidget>
#include <QMessageBox>
#include <QTextCodec>
#include <QFile>
#include <QPushButton>
#include <QDockWidget>
#include <QGridLayout>
#include <QApplication>
#include <QDesktopWidget>
#include "../../model/settings/support.hpp"
#include "datadisplayformatpage.hpp"
#include "windowpage.hpp"
#include "settingwidget.hpp"
CSVSettings::UserSettingsDialog::UserSettingsDialog(QMainWindow *parent) :
QMainWindow (parent), mStackedWidget (0)
{
setWindowTitle(QString::fromUtf8 ("User Settings"));
buildPages();
setWidgetStates ();
connect (mListWidget,
SIGNAL (currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
this,
SLOT (slotChangePage (QListWidgetItem*, QListWidgetItem*)));
QRect scr = QApplication::desktop()->screenGeometry();
QRect rect = geometry();
move (scr.center().x() - rect.center().x(), scr.center().y() - rect.center().y());
}
CSVSettings::UserSettingsDialog::~UserSettingsDialog()
{
}
void CSVSettings::UserSettingsDialog::closeEvent (QCloseEvent *event)
{
writeSettings();
}
void CSVSettings::UserSettingsDialog::setWidgetStates ()
{
CSMSettings::UserSettings::instance().loadSettings("opencs.cfg");
//iterate the tabWidget's pages (sections)
for (int i = 0; i < mStackedWidget->count(); i++)
{
//get the settings defined for the entire section
//and update widget
QString pageName = mStackedWidget->widget(i)->objectName();
const CSMSettings::SettingMap *settings = CSMSettings::UserSettings::instance().getSettings(pageName);
AbstractPage &page = getAbstractPage (i);
page.initializeWidgets(*settings);
}
}
void CSVSettings::UserSettingsDialog::buildPages()
{
//craete central widget with it's layout and immediate children
QWidget *centralWidget = new QWidget (this);
mListWidget = new QListWidget (centralWidget);
mStackedWidget = new QStackedWidget (centralWidget);
QGridLayout* dialogLayout = new QGridLayout();
mListWidget->setMinimumWidth(0);
mListWidget->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Expanding);
mStackedWidget->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);
dialogLayout->addWidget (mListWidget,0,0);
dialogLayout->addWidget (mStackedWidget,0,1, Qt::AlignTop);
centralWidget->setLayout (dialogLayout);
setCentralWidget (centralWidget);
setDockOptions (QMainWindow::AllowNestedDocks);
createPage<WindowPage>();
createPage<DataDisplayFormatPage>();
}
void CSVSettings::UserSettingsDialog::writeSettings()
{
QMap<QString, CSMSettings::SettingList *> settings;
for (int i = 0; i < mStackedWidget->count(); ++i)
{
AbstractPage &page = getAbstractPage (i);
settings [page.objectName()] = page.getSettings();
}
CSMSettings::UserSettings::instance().writeSettings(settings);
}
CSVSettings::AbstractPage &CSVSettings::UserSettingsDialog::getAbstractPage (int index)
{
return dynamic_cast<AbstractPage &> (*(mStackedWidget->widget (index)));
}
void CSVSettings::UserSettingsDialog::slotChangePage(QListWidgetItem *current, QListWidgetItem *previous)
{
if (!current)
current = previous;
if (!(current == previous))
mStackedWidget->setCurrentIndex (mListWidget->row(current));
}

@ -1,71 +0,0 @@
#ifndef USERSETTINGSDIALOG_H
#define USERSETTINGSDIALOG_H
#include <QMainWindow>
#include <QStackedWidget>
#include <QListWidgetItem>
#include <QApplication>
#include "../../model/settings/usersettings.hpp"
#include "../../model/settings/support.hpp"
class QHBoxLayout;
class AbstractWidget;
class QStackedWidget;
class QListWidget;
namespace CSVSettings {
class AbstractPage;
class UserSettingsDialog : public QMainWindow
{
Q_OBJECT
QListWidget *mListWidget;
QStackedWidget *mStackedWidget;
public:
UserSettingsDialog(QMainWindow *parent = 0);
~UserSettingsDialog();
private:
/// Settings are written on close
void closeEvent (QCloseEvent *event);
/// return the setting page by name
/// performs dynamic cast to AbstractPage *
AbstractPage &getAbstractPage (int index);
void setWidgetStates ();
void buildPages();
void writeSettings();
/// Templated function to create a custom user preference page
template <typename T>
void createPage ()
{
T *page = new T(mStackedWidget);
mStackedWidget->addWidget (&dynamic_cast<QWidget &>(*page));
new QListWidgetItem (page->objectName(), mListWidget);
//finishing touches
QFontMetrics fm (QApplication::font());
int textWidth = fm.width(page->objectName());
if ((textWidth + 50) > mListWidget->minimumWidth())
mListWidget->setMinimumWidth(textWidth + 50);
resize (mStackedWidget->sizeHint());
}
public slots:
/// Called when a different page is selected in the left-hand list widget
void slotChangePage (QListWidgetItem*, QListWidgetItem*);
};
}
#endif // USERSETTINGSDIALOG_H

@ -0,0 +1,223 @@
#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);
//push changes to model side
//update the view if the selection was set from the model side, not by the
//user
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(viewKey(), 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));
}

@ -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

@ -1,144 +0,0 @@
#include "windowpage.hpp"
#include <QList>
#include <QListView>
#include <QGroupBox>
#include <QRadioButton>
#include <QDockWidget>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QStyle>
#ifdef Q_OS_MAC
#include <QPlastiqueStyle>
#endif
#include "../../model/settings/usersettings.hpp"
#include "groupblock.hpp"
#include "toggleblock.hpp"
#include "../../view/settings/abstractblock.hpp"
CSVSettings::WindowPage::WindowPage(QWidget *parent):
AbstractPage("Window Size", parent)
{
// Hacks to get the stylesheet look properly
#ifdef Q_OS_MAC
QPlastiqueStyle *style = new QPlastiqueStyle;
//profilesComboBox->setStyle(style);
#endif
setupUi();
}
CSVSettings::GroupBlockDef * CSVSettings::WindowPage::buildDefinedWindowSize()
{
GroupBlockDef *block = new GroupBlockDef ( "Defined Size");
SettingsItemDef *widthByHeightItem = new SettingsItemDef ("Window Size", "640x480");
WidgetDef widthByHeightWidget = WidgetDef (Widget_ComboBox);
widthByHeightWidget.widgetWidth = 90;
*(widthByHeightItem->valueList) << "640x480" << "800x600" << "1024x768" << "1440x900";
QStringList *widthProxy = new QStringList;
QStringList *heightProxy = new QStringList;
(*widthProxy) << "Width" << "640" << "800" << "1024" << "1440";
(*heightProxy) << "Height" << "480" << "600" << "768" << "900";
*(widthByHeightItem->proxyList) << widthProxy << heightProxy;
widthByHeightItem->widget = widthByHeightWidget;
block->settingItems << widthByHeightItem;
block->isProxy = true;
block->isVisible = false;
return block;
}
CSVSettings::GroupBlockDef *CSVSettings::WindowPage::buildCustomWindowSize()
{
GroupBlockDef *block = new GroupBlockDef ("Custom Size");
//custom width
SettingsItemDef *widthItem = new SettingsItemDef ("Width", "640");
widthItem->widget = WidgetDef (Widget_LineEdit);
widthItem->widget.widgetWidth = 45;
widthItem->widget.inputMask = "9999";
//custom height
SettingsItemDef *heightItem = new SettingsItemDef ("Height", "480");
heightItem->widget = WidgetDef (Widget_LineEdit);
heightItem->widget.widgetWidth = 45;
heightItem->widget.caption = "x";
heightItem->widget.inputMask = "9999";
block->settingItems << widthItem << heightItem;
block->widgetOrientation = Orient_Horizontal;
block->isVisible = false;
return block;
}
CSVSettings::GroupBlockDef *CSVSettings::WindowPage::buildWindowSizeToggle()
{
GroupBlockDef *block = new GroupBlockDef (objectName());
// window size toggle
block->captions << "Pre-Defined" << "Custom";
block->widgetOrientation = Orient_Vertical;
block->isVisible = false;
//define a widget for each group in the toggle
for (int i = 0; i < 2; i++)
block->widgets << new WidgetDef (Widget_RadioButton);
block->widgets.at(0)->isDefault = false;
return block;
}
CSVSettings::CustomBlockDef *CSVSettings::WindowPage::buildWindowSize(GroupBlockDef *toggle_def,
GroupBlockDef *defined_def,
GroupBlockDef *custom_def)
{
CustomBlockDef *block = new CustomBlockDef(QString ("Window Size"));
block->blockDefList << toggle_def << defined_def << custom_def;
block->defaultValue = "Custom";
return block;
}
void CSVSettings::WindowPage::setupUi()
{
CustomBlockDef *windowSize = buildWindowSize(buildWindowSizeToggle(),
buildDefinedWindowSize(),
buildCustomWindowSize()
);
mAbstractBlocks << buildBlock<ToggleBlock> (windowSize);
foreach (AbstractBlock *block, mAbstractBlocks)
{
connect (block, SIGNAL (signalUpdateSetting (const QString &, const QString &)),
this, SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)) );
}
connect ( this,
SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)),
&(CSMSettings::UserSettings::instance()),
SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)));
}
void CSVSettings::WindowPage::initializeWidgets (const CSMSettings::SettingMap &settings)
{
//iterate each item in each blocks in this section
//validate the corresponding setting against the defined valuelist if any.
for (AbstractBlockList::Iterator it_block = mAbstractBlocks.begin();
it_block != mAbstractBlocks.end(); ++it_block)
(*it_block)->updateSettings (settings);
}

@ -1,34 +0,0 @@
#ifndef WINDOWPAGE_H
#define WINDOWPAGE_H
#include "abstractpage.hpp"
class QGroupBox;
namespace CSVSettings {
class UserSettings;
class AbstractBlock;
class WindowPage : public AbstractPage
{
Q_OBJECT
public:
WindowPage(QWidget *parent = 0);
void setupUi();
void initializeWidgets (const CSMSettings::SettingMap &settings);
///
GroupBlockDef *buildCustomWindowSize();
GroupBlockDef *buildDefinedWindowSize();
GroupBlockDef *buildWindowSizeToggle();
CustomBlockDef *buildWindowSize (GroupBlockDef *, GroupBlockDef *, GroupBlockDef *);
signals:
void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue);
};
}
#endif //WINDOWPAGE_H

@ -33,12 +33,13 @@ void CSVTools::ReportSubView::setEditLock (bool locked)
// ignored. We don't change document state anyway. // ignored. We don't change document state anyway.
} }
void CSVTools::ReportSubView::updateEditorSetting (const QString& key, const QString& value) void CSVTools::ReportSubView::updateUserSetting
(const QString &name, const QStringList &list)
{ {
mIdTypeDelegate->updateEditorSetting (key, value); mIdTypeDelegate->updateUserSetting (name, list);
} }
void CSVTools::ReportSubView::show (const QModelIndex& index) void CSVTools::ReportSubView::show (const QModelIndex& index)
{ {
focusId (mModel->getUniversalId (index.row()), ""); focusId (mModel->getUniversalId (index.row()), "");
} }

@ -39,7 +39,8 @@ namespace CSVTools
virtual void setEditLock (bool locked); virtual void setEditLock (bool locked);
virtual void updateEditorSetting (const QString&, const QString&); virtual void updateUserSetting
(const QString &, const QStringList &);
private slots: private slots:
@ -47,4 +48,4 @@ namespace CSVTools
}; };
} }
#endif #endif

@ -1,16 +1,26 @@
#include "datadisplaydelegate.hpp" #include "datadisplaydelegate.hpp"
#include "../../model/settings/usersettings.hpp"
#include <QApplication> #include <QApplication>
#include <QPainter> #include <QPainter>
CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values,
const IconList &icons, const IconList &icons,
QUndoStack &undoStack, QObject *parent) QUndoStack &undoStack,
: EnumDelegate (values, undoStack, parent), mDisplayMode (Mode_TextOnly), mIcons (icons) const QString &settingKey,
, mIconSize (QSize(16, 16)), mIconLeftOffset(3), mTextLeftOffset(8) QObject *parent)
: EnumDelegate (values, undoStack, parent), mDisplayMode (Mode_TextOnly),
mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3),
mTextLeftOffset(8), mSettingKey (settingKey)
{ {
mTextAlignment.setAlignment (Qt::AlignLeft | Qt::AlignVCenter ); mTextAlignment.setAlignment (Qt::AlignLeft | Qt::AlignVCenter );
buildPixmaps(); buildPixmaps();
QString value =
CSMSettings::UserSettings::instance().settingValue (settingKey);
updateDisplayMode(value);
} }
void CSVWorld::DataDisplayDelegate::buildPixmaps () void CSVWorld::DataDisplayDelegate::buildPixmaps ()
@ -89,6 +99,30 @@ void CSVWorld::DataDisplayDelegate::paintIcon (QPainter *painter, const QStyleOp
painter->drawPixmap (iconRect, mPixmaps.at(index).second); painter->drawPixmap (iconRect, mPixmaps.at(index).second);
} }
void CSVWorld::DataDisplayDelegate::updateUserSetting (const QString &name,
const QStringList &list)
{
if (list.isEmpty())
return;
QString value = list.at(0);
if (name == mSettingKey)
updateDisplayMode (value);
}
void CSVWorld::DataDisplayDelegate::updateDisplayMode (const QString &mode)
{
if (mode == "Icon and Text")
mDisplayMode = Mode_IconAndText;
else if (mode == "Icon Only")
mDisplayMode = Mode_IconOnly;
else if (mode == "Text Only")
mDisplayMode = Mode_TextOnly;
}
CSVWorld::DataDisplayDelegate::~DataDisplayDelegate() CSVWorld::DataDisplayDelegate::~DataDisplayDelegate()
{ {
mIcons.clear(); mIcons.clear();
@ -106,5 +140,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);
} }

@ -35,10 +35,14 @@ namespace CSVWorld
int mIconLeftOffset; int mIconLeftOffset;
int mTextLeftOffset; int mTextLeftOffset;
QString mSettingKey;
public: public:
explicit DataDisplayDelegate (const ValueList & values, explicit DataDisplayDelegate (const ValueList & values,
const IconList & icons, const IconList & icons,
QUndoStack& undoStack, QObject *parent); QUndoStack& undoStack,
const QString &settingKey,
QObject *parent);
~DataDisplayDelegate(); ~DataDisplayDelegate();
@ -53,8 +57,14 @@ namespace CSVWorld
/// offset the horizontal position of the text from the right edge of the icon. Default is 8 pixels. /// offset the horizontal position of the text from the right edge of the icon. Default is 8 pixels.
void setTextLeftOffset (int offset); void setTextLeftOffset (int offset);
///update the display mode for the delegate
void updateUserSetting (const QString &name, const QStringList &list);
private: private:
/// update the display mode based on a passed string
void updateDisplayMode (const QString &);
/// custom paint function for painting the icon. Mode_IconAndText and Mode_Icon only. /// custom paint function for painting the icon. Mode_IconAndText and Mode_Icon only.
void paintIcon (QPainter *painter, const QStyleOptionViewItem &option, int i) const; void paintIcon (QPainter *painter, const QStyleOptionViewItem &option, int i) const;

@ -4,30 +4,11 @@
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, parent) : DataDisplayDelegate (values, icons, undoStack,
"Display Format.Referenceable ID Type Display",
parent)
{} {}
bool CSVWorld::IdTypeDelegate::updateEditorSetting (const QString &settingName, const QString &settingValue)
{
/// \todo make the setting key a member variable, that is initialised from a constructor argument
if (settingName == "Referenceable ID Type Display")
{
if (settingValue == "Icon and Text")
mDisplayMode = Mode_IconAndText;
else if (settingValue == "Icon Only")
mDisplayMode = Mode_IconOnly;
else if (settingValue == "Text Only")
mDisplayMode = Mode_TextOnly;
return true;
}
return false;
}
CSVWorld::IdTypeDelegateFactory::IdTypeDelegateFactory() CSVWorld::IdTypeDelegateFactory::IdTypeDelegateFactory()
{ {
for (int i=0; i<CSMWorld::UniversalId::NumberOfTypes; ++i) for (int i=0; i<CSMWorld::UniversalId::NumberOfTypes; ++i)

@ -12,9 +12,6 @@ namespace CSVWorld
{ {
public: public:
IdTypeDelegate (const ValueList &mValues, const IconList &icons, QUndoStack& undoStack, QObject *parent); IdTypeDelegate (const ValueList &mValues, const IconList &icons, QUndoStack& undoStack, QObject *parent);
virtual bool updateEditorSetting (const QString &settingName, const QString &settingValue);
}; };
class IdTypeDelegateFactory : public DataDisplayDelegateFactory class IdTypeDelegateFactory : public DataDisplayDelegateFactory

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save