Final changes for record status icon feature, incl. window size user

preference

1. Included updated status icons, added base.png
2. Added doxygen comments CSV / CSM Settings classes
3. Implemented Glorf's code for window size preference
4. Minor changes code that searches maps in CSV / CSM Settings classes
5. Removed CSVSettings::SamplePage class
6. Other minor code maintenance / improvements
actorid
graffy76 11 years ago
parent 965d93ea40
commit 101c147217

@ -78,7 +78,6 @@ opencs_units (view/settings
proxyblock
abstractwidget
usersettingsdialog
samplepage
editorpage
windowpage
)

@ -62,15 +62,9 @@ void CS::Editor::setupDataFiles()
mFileDialog.addFiles(path);
}
//Settings setup
QStringList settingFiles;
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
settingFiles.append(QString("opencs.cfg"));
settingFiles.append(userPath + QString("opencs.cfg"));
mUserSettings.setSettingsFiles(settingFiles);
mUserSettings.readSettings();
//load the settings into the userSettings instance.
const QString settingFileName = "opencs.cfg";
CSMSettings::UserSettings::instance().loadSettings(settingFileName);
}

@ -15,19 +15,31 @@ namespace CSMSettings
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
/// 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); }
};
}

@ -66,21 +66,10 @@ bool CSMSettings::SettingsItem::updateItem(int valueListIndex)
bool CSMSettings::SettingsItem::validate (const QString &value)
{
bool isValid = true;
//validation required only if a value list or min/max value pair has been provided
if (mValueList->size()>0)
{
for (QStringList::ConstIterator it = mValueList->begin(); it !=mValueList->end(); ++it)
{
isValid = ( value == *it);
if (isValid)
break;
}
}
bool isValid = (mValueList->find(value) != mValueList->end());
else if (mValuePair)
if (!isValid && mValuePair)
{
int numVal = value.toInt();

@ -7,6 +7,8 @@
namespace CSMSettings
{
/// Represents a setting including metadata
/// (valid values, ranges, defaults, and multivalue status
class SettingsItem : public SettingContainer
{
QStringPair *mValuePair;
@ -24,14 +26,24 @@ namespace CSMSettings
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);
/// retroeve 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) { mValuePair = new QStringPair(valuePair); }
inline bool isMultivalue () { return mIsMultiValue; }
@ -40,6 +52,11 @@ namespace CSMSettings
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
/// TODO: value list logic iterates QList. Should use find() instead.
bool validate (const QString &value);
};
}

@ -54,15 +54,7 @@ CSMSettings::UserSettings::~UserSettings()
mUserSettingsInstance = 0;
}
//QTextStream *CSMSettings::UserSettings::openFileStream (const QString &filePath, bool isReadOnly)
CSMSettings::SectionMap CSMSettings::UserSettings::getSettingsMap() const
{
return mSectionMap;
}
QFile *CSMSettings::UserSettings::openFile (const QString &filename) const
QTextStream *CSMSettings::UserSettings::openFileStream (const QString &filePath, bool isReadOnly) const
{
QFile *file = new QFile(filePath);
@ -105,10 +97,7 @@ QFile *CSMSettings::UserSettings::openFile (const QString &filename) const
}
bool CSMSettings::UserSettings::writeFile(QMap<QString, CSMSettings::SettingList *> &settings)
//bool CSMSettings::UserSettings::writeFile(QFile *file, QMap<QString, CSMSettings::SettingList *> &settings) const
bool CSMSettings::UserSettings::writeSettings(QMap<QString, CSMSettings::SettingList *> &settings)
{
QTextStream *stream = openFileStream(mPaths.back());
@ -130,10 +119,7 @@ bool CSMSettings::UserSettings::writeFile(QMap<QString, CSMSettings::SettingList
}
const CSMSettings::SectionMap &CSMSettings::UserSettings::getSettings()
//void CSMSettings::UserSettings::getSettings(QTextStream &stream, SectionMap &sections) const
const CSMSettings::SectionMap &CSMSettings::UserSettings::getSettings() const
{
return mSectionSettings;
}
@ -234,64 +220,20 @@ void CSMSettings::UserSettings::updateSettings (const QString &sectionName, cons
}
else
{
setting = (*settings)[settingName];
if (setting)
emit signalUpdateEditorSetting (setting->objectName(), setting->getValue());
}
}
void CSMSettings::UserSettings::readSettings()
{
CSMSettings::SectionMap sectionMap;
foreach (const QString &path, mSettingsFiles)
{
qDebug() << "Loading config file:" << qPrintable(path);
QFile file(path);
if (file.exists())
if (settings->find(settingName)!=settings->end())
{
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Error opening OpenCS configuration file"));
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(QObject::tr("<br><b>Could not open %0 for reading</b><br><br> \
Please make sure you have the right permissions \
and try again.<br>").arg(file.fileName()));
msgBox.exec();
return;
}
QTextStream stream(&file);
stream.setCodec(QTextCodec::codecForName("UTF-8"));
getSettings(stream, mSectionMap);
setting = settings->value(settingName);
emit signalUpdateEditorSetting (setting->objectName(), setting->getValue());
}
file.close();
}
}
void CSMSettings::UserSettings::setSettingsFiles(QStringList files)
{
mSettingsFiles = files;
}
QStringList CSMSettings::UserSettings::getSettingsFiles () const
{
return mSettingsFiles;
}
QString CSMSettings::UserSettings::getSettingValue(QString section, QString setting) const
QString CSMSettings::UserSettings::getSetting (const QString &section, const QString &setting) const
{
if(mSectionMap.find(section) == mSectionMap.end())
if(mSectionSettings.find(section) == mSectionSettings.end())
return QString();
CSMSettings::SettingMap *settings = mSectionMap.value(section);
CSMSettings::SettingMap *settings = mSectionSettings.value(section);
if(settings->find(setting) == settings->end())
return QString();
@ -301,7 +243,7 @@ QString CSMSettings::UserSettings::getSettingValue(QString section, QString sett
return settingContainer->getValue();
}
const CSMSettings::UserSettings& CSMSettings::UserSettings::instance()
CSMSettings::UserSettings& CSMSettings::UserSettings::instance()
{
assert(mUserSettingsInstance);
return *mUserSettingsInstance;

@ -27,56 +27,53 @@ namespace CSMSettings {
Q_OBJECT
SectionMap mSectionSettings;
UserSettings *mUserSettingsInstance;
static UserSettings *mUserSettingsInstance;
QStringList mPaths;
Files::ConfigurationManager mCfgMgr;
QString mReadOnlyMessage;
QString mReadWriteMessage;
public:
/// Singleton implementation
static UserSettings& instance();
UserSettings();
~UserSettings();
static const UserSettings& instance();
UserSettings (UserSettings const &); //not implemented
void operator= (UserSettings const &); //not implemented
void readSettings();
void setSettingsFiles(QStringList files);
/// Writes settings to the last loaded settings file
bool writeSettings(QMap<QString, SettingList *> &sections);
<<<<<<< HEAD
bool writeFile(QMap<QString, SettingList *> &sections);
const SectionMap &getSettings ();
/// 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).
/// TODO: Multi-valued settings are not fully implemented. Setting values
/// loaded in later files will always overwrite previously loaded values.
void loadSettings (const QString &fileName);
private:
/// Returns the entire map of settings across all sections
const SectionMap &getSettings () const;
UserSettings();
~UserSettings();
=======
QFile *openFile (const QString &) const;
bool writeFile(QFile *file, QMap<QString, SettingList *> &sections) const;
void getSettings (QTextStream &stream, SectionMap &settings) const;
QStringList getSettingsFiles () const;
CSMSettings::SectionMap getSettingsMap() const;
QString getSettingValue(QString section, QString setting) const;
/// Retrieves the value as a QString of the specified setting in the specified section
QString getSetting(const QString &section, const QString &setting) const;
private:
static UserSettings *mUserSettingsInstance;
CSMSettings::SectionMap mSectionMap;
QStringList mSettingsFiles;
>>>>>>> df1f1bd5c81d94a1ea2693000ec5dc589b069826
/// Opens a QTextStream from the provided path as read-only or read-write.
QTextStream *openFileStream (const QString &filePath, bool isReadOnly = false) const;
UserSettings (UserSettings const &); //not implemented
void operator= (UserSettings const &); //not implemented
QTextStream *openFileStream (const QString &filePath, bool isReadOnly = false);
/// Parses a setting file specified in filePath from the provided text stream.
void loadFromFile (const QString &filePath = "");
signals:
void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue);
};

@ -180,8 +180,9 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to
: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1),
mViewTotal (totalViews)
{
QString width = CSMSettings::UserSettings::instance().getSettingValue(QString("Window Size"), QString("Width"));
QString height = CSMSettings::UserSettings::instance().getSettingValue(QString("Window Size"), QString("Height"));
QString width = CSMSettings::UserSettings::instance().getSetting(QString("Window Size"), QString("Width"));
QString height = CSMSettings::UserSettings::instance().getSetting(QString("Window Size"), QString("Height"));
if(width==QString() || height==QString())
resize(800, 600);
else
@ -378,10 +379,31 @@ void CSVDoc::View::showUserSettings()
settingsDialog->show();
}
void CSVDoc::View::resizeViewWidth (int width)
{
if (width >= 0)
resize (width, geometry().height());
}
void CSVDoc::View::resizeViewHeight (int height)
{
if (height >= 0)
resize (geometry().width(), height);
}
void CSVDoc::View::updateEditorSetting (const QString &settingName, const QString &settingValue)
{
if (settingName == "Record Status Display")
{
foreach (QObject *view, mSubViewWindow.children())
{
if (view->objectName() == "subview")
dynamic_cast<CSVDoc::SubView *>(view)->updateEditorSetting (settingName, settingValue);
}
}
else if (settingName == "Width")
resizeViewWidth (settingValue.toInt());
else if (settingName == "Height")
resizeViewHeight (settingValue.toInt());
}

@ -70,6 +70,12 @@ namespace CSVDoc
void loadUserSettings();
/// User preference function
void resizeViewWidth (int width);
/// User preference function
void resizeViewHeight (int height);
public:
View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews);
@ -90,6 +96,7 @@ namespace CSVDoc
Operations *getOperations() const;
/// Function called by view manager when user preferences are updated
void updateEditorSetting (const QString &, const QString &);
signals:

@ -21,6 +21,7 @@
#include <QPushButton>
#include <QtGui/QApplication>
#include <QDebug>
void CSVDoc::ViewManager::updateIndices()
{
std::map<CSMDoc::Document *, std::pair<int, int> > documents;
@ -124,8 +125,6 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
connect (&CSMSettings::UserSettings::instance(), SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)),
this, SLOT (slotUpdateEditorSetting (const QString &, const QString &)));
CSMSettings::UserSettings::instance().loadSettings("opencs.cfg");
}
CSVDoc::ViewManager::~ViewManager()
@ -355,7 +354,10 @@ void CSVDoc::ViewManager::exitApplication (CSVDoc::View *view)
void CSVDoc::ViewManager::slotUpdateEditorSetting (const QString &settingName, const QString &settingValue)
{
if (settingName == "Record Status Display")
if (settingName == "Record Status Display" ||
settingName == "Width" || settingName == "Height")
{
foreach (CSVDoc::View *view, mViews)
view->updateEditorSetting (settingName, settingValue);
}
}

@ -73,6 +73,7 @@ namespace CSVDoc
void onExitWarningHandler(int state, CSMDoc::Document* document);
/// connected to update signal in UserSettings
void slotUpdateEditorSetting (const QString &, const QString &);
};

@ -38,27 +38,27 @@ CSVSettings::AbstractWidget *CSVSettings::AbstractBlock::buildWidget (const QStr
{
case Widget_RadioButton:
widg = createSettingWidget<QRadioButton> (def, layout);
widg = new SettingWidget<QRadioButton> (def, layout, mBox);
break;
case Widget_SpinBox:
widg = createSettingWidget<QSpinBox> (def, layout);
widg = new SettingWidget<QSpinBox> (def, layout, mBox);
break;
case Widget_CheckBox:
widg = createSettingWidget<QCheckBox> (def, layout);
widg = new SettingWidget<QCheckBox> (def, layout, mBox);
break;
case Widget_LineEdit:
widg = createSettingWidget<QLineEdit> (def, layout);
widg = new SettingWidget<QLineEdit> (def, layout, mBox);
break;
case Widget_ListBox:
widg = createSettingWidget<QListWidget> (def, layout);
widg = new SettingWidget<QListWidget> (def, layout, mBox);
break;
case Widget_ComboBox:
widg = createSettingWidget<QComboBox> (def, layout);
widg = new SettingWidget<QComboBox> (def, layout, mBox);
break;
default:

@ -11,6 +11,7 @@
namespace CSVSettings
{
/// Abstract base class for all blocks
class AbstractBlock : public QObject
{
Q_OBJECT
@ -31,40 +32,50 @@ namespace CSVSettings
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 which for the blocks 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;
template <typename T>
AbstractWidget *createSettingWidget (WidgetDef &wDef, QLayout *layout) const
{
return new SettingWidget<T> (wDef, layout, mBox);
}
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 functions outside the settings tab widget
/// signal to UserSettings instance
void signalUpdateSetting (const QString &propertyName, const QString &propertyValue);
/// signal to widget for updating widget value
void signalUpdateWidget (const QString & value);
//propertyName and propertyValue are for properties for which the updated setting acts as a proxy
/// ProxyBlock use only.
/// Name and value correspond to settings for which the block is a proxy.
void signalUpdateProxySetting (const QString &propertyName, const QString &propertyValue);
};
}

@ -29,16 +29,7 @@ CSVSettings::AbstractPage::AbstractPage(const QString &pageName, QWidget *parent
CSVSettings::AbstractPage::~AbstractPage()
{
}
/*
void CSVSettings::AbstractPage::setupUi()
{
// Hacks to get the stylesheet look properly
#ifdef Q_OS_MAC
QPlastiqueStyle *style = new QPlastiqueStyle;
//profilesComboBox->setStyle(style);
#endif
}
*/
CSMSettings::SettingList *CSVSettings::AbstractPage::getSettings()
{
CSMSettings::SettingList *settings = new CSMSettings::SettingList();

@ -14,6 +14,11 @@ 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
{
@ -30,14 +35,20 @@ namespace CSVSettings {
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)
{

@ -8,6 +8,7 @@ class QLayout;
namespace CSVSettings
{
/// Abstract base class for widgets which are used in user preferences dialog
class AbstractWidget : public QObject
{
Q_OBJECT
@ -16,45 +17,49 @@ namespace CSVSettings
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
/// retrieve layout for insertion into itemblock
QLayout *getLayout();
//create the derived widget instance
/// create the derived widget instance
void build (QWidget* widget, WidgetDef &def, bool noLabel = false);
//reference to the derived widget instance
/// reference to the derived widget instance
virtual QWidget *widget() = 0;
protected:
//called by inbound signal for type-specific widget udpates
/// Callback called by receiving slot for widget udpates
virtual void updateWidget (const QString &value) = 0;
//converts user-defined enum to Qt equivalents
/// Converts user-defined enum to Qt equivalents
QFlags<Qt::AlignmentFlag> getAlignment (Alignment flag);
private:
//widget initialization utilities
/// 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
/// outbound update signal
void signalUpdateItem (const QString &value);
public slots:
//inbound updates
/// receives inbound updates
void slotUpdateWidget (const QString &value);
//Outbound updates from derived widget signal
/// Overloads for outbound updates from derived widget signal
void slotUpdateItem (const QString &value);
void slotUpdateItem (bool value);
void slotUpdateItem (int value);

@ -20,16 +20,11 @@
CSVSettings::BlankPage::BlankPage(QWidget *parent):
AbstractPage("Blank", parent)
{
initPage();
}
CSVSettings::BlankPage::BlankPage(const QString &title, QWidget *parent):
AbstractPage(title, parent)
{
initPage();
}
void CSVSettings::BlankPage::initPage()
{
// Hacks to get the stylesheet look properly
#ifdef Q_OS_MAC

@ -10,6 +10,8 @@ namespace CSVSettings {
class UserSettings;
class AbstractBlock;
/// Derived page with no widgets
/// Reference use only.
class BlankPage : public AbstractPage
{
@ -20,9 +22,6 @@ namespace CSVSettings {
void setupUi();
void initializeWidgets (const CSMSettings::SettingMap &settings);
private:
void initPage();
};
}

@ -59,7 +59,7 @@ int CSVSettings::CustomBlock::buildGroupBlock(GroupBlockDef *def)
int CSVSettings::CustomBlock::buildProxyBlock(GroupBlockDef *def, ProxyBlock *block)
{
if (def->properties.size() != 1)
if (def->settingItems.size() != 1)
return -1;
int retVal = block->build(def);
@ -67,7 +67,8 @@ int CSVSettings::CustomBlock::buildProxyBlock(GroupBlockDef *def, ProxyBlock *bl
if (retVal != 0)
return retVal;
foreach (QStringList *list, *(def->properties.at(0)->proxyList))
// 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);

@ -8,6 +8,8 @@ namespace CSVSettings
class ProxyBlock;
/// Base class for customized user preference setting blocks
/// Special block classes should be derived from CustomBlock
class CustomBlock : public AbstractBlock
{
@ -19,17 +21,26 @@ namespace CSVSettings
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);
};
}

@ -3,13 +3,7 @@
#include "../../model/settings/usersettings.hpp"
CSVSettings::EditorPage::EditorPage(QWidget* parent) :
AbstractPage(parent)
{
setupUi();
}
CSVSettings::EditorPage::EditorPage (const QString &pageName, QWidget* parent)
: AbstractPage (pageName, parent)
AbstractPage("Editor", parent)
{
setupUi();
}
@ -26,7 +20,7 @@ CSVSettings::GroupBlockDef *CSVSettings::EditorPage::setupRecordStatusDisplay()
statusItem->widget = statusWidget;
statusBlock->properties << statusItem;
statusBlock->settingItems << statusItem;
return statusBlock;
}

@ -12,15 +12,18 @@ namespace CSVSettings
public:
explicit EditorPage(QWidget *parent = 0);
explicit EditorPage (const QString &pageName, 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:

@ -12,7 +12,7 @@ CSVSettings::GroupBlock::GroupBlock (bool isVisible, QWidget *parent)
int CSVSettings::GroupBlock::build (GroupBlockDef *def)
{
if (def->properties.size() == 0)
if (def->settingItems.size() == 0)
return -1;
int retVal = 0;
@ -24,7 +24,7 @@ int CSVSettings::GroupBlock::build (GroupBlockDef *def)
setObjectName (def->title);
mBox->setTitle (def->title);
foreach (SettingsItemDef *itemDef, def->properties)
foreach (SettingsItemDef *itemDef, def->settingItems)
{
ItemBlock *block = new ItemBlock (mBox);

@ -8,6 +8,8 @@ namespace CSVSettings
{
class ItemBlock;
/// Base class for group blocks.
/// Derived block classes should use CustomBlock
class GroupBlock : public AbstractBlock
{
ItemBlockList mItemBlockList;
@ -16,15 +18,24 @@ namespace CSVSettings
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);
};

@ -5,6 +5,7 @@
namespace CSVSettings
{
/// Custom implementation of QGroupBox to be used with block classes
class GroupBox : public QGroupBox
{
static const QString INVISIBLE_BOX_STYLE;

@ -15,22 +15,32 @@ namespace CSVSettings
ItemBlock (QWidget* parent = 0);
/// pure virtual function not implemneted
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);
};
}

@ -8,7 +8,7 @@ CSVSettings::ProxyBlock::ProxyBlock (QWidget *parent)
int CSVSettings::ProxyBlock::build (GroupBlockDef *proxyDef)
{
//get the list of pre-defined values for the proxy
mValueList = proxyDef->properties.at(0)->valueList;
mValueList = proxyDef->settingItems.at(0)->valueList;
bool success = GroupBlock::build(proxyDef);

@ -9,8 +9,7 @@ namespace CSVSettings
{
Q_OBJECT
//NOTE: mProxyItemBlockList and mProxyList
//should be combined into a value pair and stored in one list.
/// TODO: Combine mProxyItemBlockList and mProxyList.
ItemBlockList mProxiedItemBlockList;
ProxyList mProxyList;
QStringList *mValueList;
@ -20,17 +19,28 @@ namespace CSVSettings
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:

@ -44,7 +44,7 @@ void CSVSettings::SamplePage::setupUi()
///////////////////////////
SettingsItemDef *undoStackItem = new SettingsItemDef (undoStack->title, "32");
undoStack->properties << undoStackItem;
undoStack->settingItems << undoStackItem;
undoStackItem->minMax.left = "0";
undoStackItem->minMax.right = "64";
@ -59,7 +59,7 @@ void CSVSettings::SamplePage::setupUi()
/////////////////////////////////////
SettingsItemDef *topLevelItem = new SettingsItemDef (topLevelWindowCount->title, "100");
topLevelWindowCount->properties << topLevelItem;
topLevelWindowCount->settingItems << topLevelItem;
topLevelItem->minMax.left = "1";
topLevelItem->minMax.right = "256";
@ -80,7 +80,7 @@ void CSVSettings::SamplePage::setupUi()
reuseSubWidget.valueList = (reuseSubItem->valueList);
reuseSubWidget.widgetAlignment = Align_Left;
reuseSubwindow->properties << reuseSubItem;
reuseSubwindow->settingItems << reuseSubItem;
reuseSubItem->widget = reuseSubWidget;
///////////////////////////////
@ -98,7 +98,7 @@ void CSVSettings::SamplePage::setupUi()
heightItem->widget.widgetWidth = 45;
heightItem->widget.caption = "x";
customWindowSize->properties << widthItem << heightItem;
customWindowSize->settingItems << widthItem << heightItem;
customWindowSize->widgetOrientation = Orient_Horizontal;
customWindowSize->isVisible = false;
@ -119,7 +119,7 @@ void CSVSettings::SamplePage::setupUi()
widthByHeightItem->widget = widthByHeightWidget;
definedWindowSize->properties << widthByHeightItem;
definedWindowSize->settingItems << widthByHeightItem;
definedWindowSize->isProxy = true;
definedWindowSize->isVisible = false;

@ -16,7 +16,8 @@
namespace CSVSettings
{
//VALID FOR RADIOBUTTON / CHECKBOX (or other toggle widget with it's own label)
/// Generic template for radiobuttons / checkboxes
template <typename T1>
class SettingWidget : public AbstractWidget
{
@ -47,6 +48,7 @@ namespace CSVSettings
}
};
/// spin box template
template <>
class SettingWidget <QSpinBox>: public AbstractWidget
{
@ -90,6 +92,7 @@ namespace CSVSettings
};
/// combo box template
template <>
class SettingWidget <QComboBox>: public CSVSettings::AbstractWidget
{
@ -142,6 +145,7 @@ namespace CSVSettings
};
/// line edit template
template <>
class SettingWidget <QLineEdit>: public CSVSettings::AbstractWidget
{
@ -175,6 +179,8 @@ namespace CSVSettings
}
};
/// list widget template
/// TODO: Not fully implemented. Only widget supporting multi-valued settings
template <>
class SettingWidget <QListWidget>: public CSVSettings::AbstractWidget
{

@ -44,21 +44,44 @@ namespace CSVSettings
Align_Right = Qt::AlignRight
};
//template for defining the widget of a property.
/// definition struct for widgets
struct WidgetDef
{
WidgetType type; //type of widget providing input
int labelWidth; //width of caption label
int widgetWidth; //width of input widget
Orientation orientation; //label / widget orientation (horizontal / vertical)
QString inputMask; //input mask (line edit)
QString caption; //label caption. Leave empty for multiple items. See BlockDef::captionList
QString value; //widget value. Leave empty for multiple items. See BlockDef::valueList
CSMSettings::QStringPair *minMax; //Min/Max QString value pair. If empty, assigned to property item value pair.
QStringList *valueList; //value list for list widgets. If left empty, is assigned to property item value list during block build().
bool isDefault; //isDefault - determined at runtime.
Alignment valueAlignment; //left / center / right-justify text in widget
Alignment widgetAlignment; //left / center / right-justify widget in group box
/// 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),
@ -79,20 +102,34 @@ namespace CSVSettings
};
//Defines the attributes of the property 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 property.
/// 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
{
QString name; //property name
QStringList *valueList; //list of valid values for the property.
//Used to populate option widget captions or list widget item lists (see WidgetDef::caption / value)
/// 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;
CSMSettings::QStringPair minMax; //minimum / maximum value pair
WidgetDef widget; //definition of the input widget for this setting
Orientation orientation; //general orientation of the widget / label for this property
ProxyList *proxyList; //list of property and corresponding default values for proxy widget
/// 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)
{}
@ -104,18 +141,32 @@ namespace CSVSettings
};
//Hierarchically, this is a "sub-section" of properties within a section, solely for UI organization.
//Does not correlate to config file structure.
/// Generic container block
struct GroupBlockDef
{
QString title; //title of the block containing the property or properties of this sub-section
QStringList captions; //list of captions for widgets at the block level (not associated with any particular property)
WidgetList widgets; //list of widgets at the block level (not associated with any particular property)
QList<SettingsItemDef *> properties; //list of the property(ies) which are subordinate to the property block.
Orientation widgetOrientation; //general orientation of widgets in group block
bool isVisible; //determines whether or not box border/title are visible
bool isProxy; //indicates whether or not this block defines a proxy block
QString defaultValue; //generic default value attribute
/// 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;
GroupBlockDef (): title(""), widgetOrientation (Orient_Vertical), isVisible (true), isProxy (false), defaultValue ("")
{}
@ -125,11 +176,19 @@ namespace CSVSettings
{}
};
/// used to create unique, complex blocks
struct CustomBlockDef
{
/// block title
QString title;
QString defaultValue; //default value for widgets unique to the custom block
GroupBlockDefList blockDefList; //list of settings groups that comprise the settings within the custom block
/// 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)

@ -21,6 +21,8 @@ namespace CSVSettings
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);
};
}

@ -9,19 +9,15 @@
#include <QFile>
#include <QPushButton>
#include <QDockWidget>
<<<<<<< HEAD
#include <QGridLayout>
#include "blankpage.hpp"
#include "samplepage.hpp"
=======
#include <QDebug>
#include "blankpage.hpp"
#include "editorpage.hpp"
#include "windowpage.hpp"
#include "../../model/settings/support.hpp"
>>>>>>> df1f1bd5c81d94a1ea2693000ec5dc589b069826
#include "../../model/settings/support.hpp"
#include <boost/filesystem/path.hpp>
@ -32,12 +28,7 @@ CSVSettings::UserSettingsDialog::UserSettingsDialog(QMainWindow *parent) :
{
setWindowTitle(QString::fromUtf8 ("User Settings"));
buildPages();
<<<<<<< HEAD
setWidgetStates ();
=======
setWidgetStates (CSMSettings::UserSettings::instance().getSettingsMap());
>>>>>>> df1f1bd5c81d94a1ea2693000ec5dc589b069826
positionWindow ();
connect (mListWidget,
SIGNAL (currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
@ -63,11 +54,12 @@ void CSVSettings::UserSettingsDialog::setWidgetStates ()
for (int i = 0; i < mStackedWidget->count(); i++)
{
//get the settings defined for the entire section
CSMSettings::SettingMap *settings = sectionSettings [mStackedWidget->widget(i)->objectName()];
//and update widget
QString pageName = mStackedWidget->widget(i)->objectName();
//if found, initialize the page's widgets
if (settings)
if (sectionSettings.find(pageName) != sectionSettings.end())
{
CSMSettings::SettingMap *settings = sectionSettings.value(pageName);
AbstractPage *page = getAbstractPage (i);
page->initializeWidgets(*settings);
}
@ -97,62 +89,11 @@ void CSVSettings::UserSettingsDialog::buildPages()
setCentralWidget (centralWidget);
setDockOptions (QMainWindow::AllowNestedDocks);
//uncomment to test with sample editor page.
<<<<<<< HEAD
// TODO: Reimplement sample page using createPage function
//createPage<SamplePage>("Sample");
createPage<EditorPage>("Editor");
=======
//createSamplePage();
/*createPage<BlankPage>("Page1");
>>>>>>> df1f1bd5c81d94a1ea2693000ec5dc589b069826
createPage<BlankPage>("Page2");
createPage<BlankPage>("Page3");*/
createWindowPage();
}
void CSVSettings::UserSettingsDialog::createSamplePage()
{
//add pages to stackedwidget and items to listwidget
CSVSettings::AbstractPage *page
= new CSVSettings::SamplePage(this);
mStackedWidget->addWidget (page);
connect ( page,
SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)),
&(CSMSettings::UserSettings::instance()),
SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)));
createPage<WindowPage>();
createPage<EditorPage>();
new QListWidgetItem (page->objectName(), mListWidget);
}
void CSVSettings::UserSettingsDialog::createWindowPage()
{
//add pages to stackedwidget and items to listwidget
CSVSettings::AbstractPage *page
= new CSVSettings::WindowPage(this);
mStackedWidget->addWidget (page);
new QListWidgetItem (page->objectName(), mListWidget);
connect ( page, SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)),
&(CSMSettings::UserSettings::instance()), SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)));
}
<<<<<<< HEAD
=======
void CSVSettings::UserSettingsDialog::positionWindow ()
{
QRect scr = QApplication::desktop()->screenGeometry();
move(scr.center().x() - (width() / 2), scr.center().y() - (height() / 2));
}
>>>>>>> df1f1bd5c81d94a1ea2693000ec5dc589b069826
void CSVSettings::UserSettingsDialog::writeSettings()
{
QMap<QString, CSMSettings::SettingList *> settings;
@ -162,15 +103,7 @@ void CSVSettings::UserSettingsDialog::writeSettings()
AbstractPage *page = getAbstractPage (i);
settings [page->objectName()] = page->getSettings();
}
<<<<<<< HEAD
CSMSettings::UserSettings::instance().writeFile(settings);
=======
QStringList paths = CSMSettings::UserSettings::instance().getSettingsFiles();
CSMSettings::UserSettings::instance().writeFile(CSMSettings::UserSettings::instance().openFile(paths.back()), settings);
>>>>>>> df1f1bd5c81d94a1ea2693000ec5dc589b069826
CSMSettings::UserSettings::instance().writeSettings(settings);
}
CSVSettings::AbstractPage *CSVSettings::UserSettingsDialog::getAbstractPage (int index)

@ -33,33 +33,27 @@ namespace CSVSettings {
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 positionWindow ();
void writeSettings();
void createSamplePage();
//Pages
void createWindowPage();
/// Templated function to create a custom user preference page
template <typename T>
void createPage (const QString &title)
void createPage ()
{
T *page = new T(title, this);
T *page = new T(mStackedWidget);
mStackedWidget->addWidget (dynamic_cast<QWidget *>(page));
new QListWidgetItem (page->objectName(), mListWidget);
//finishing touches
if (mStackedWidget->sizeHint().width() < 640)
mStackedWidget->sizeHint().setWidth(640);
if (mStackedWidget->sizeHint().height() < 480)
mStackedWidget->sizeHint().setHeight(480);
QFontMetrics fm (QApplication::font());
int textWidth = fm.width(page->objectName());
@ -70,6 +64,8 @@ namespace CSVSettings {
}
public slots:
/// Called when a different page is selected in the left-hand list widget
void slotChangePage (QListWidgetItem*, QListWidgetItem*);
};

@ -16,6 +16,7 @@
#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)
@ -29,35 +30,10 @@ CSVSettings::WindowPage::WindowPage(QWidget *parent):
setupUi();
}
void CSVSettings::WindowPage::setupUi()
CSVSettings::GroupBlockDef * CSVSettings::WindowPage::buildDefinedWindowSize()
{
GroupBlockDef customWindowSize (QString ("Custom Window Size"));
GroupBlockDef definedWindowSize (QString ("Pre-Defined Window Size"));
GroupBlockDef windowSizeToggle (QString ("Window Size"));
CustomBlockDef windowSize (QString ("Window Size"));
///////////////////////////////
//custom window size properties
///////////////////////////////
//custom width
SettingsItemDef *widthItem = new SettingsItemDef ("Width", "640");
widthItem->widget = WidgetDef (Widget_LineEdit);
widthItem->widget.widgetWidth = 45;
//custom height
SettingsItemDef *heightItem = new SettingsItemDef ("Height", "480");
heightItem->widget = WidgetDef (Widget_LineEdit);
heightItem->widget.widgetWidth = 45;
heightItem->widget.caption = "x";
customWindowSize.properties << widthItem << heightItem;
customWindowSize.widgetOrientation = Orient_Horizontal;
customWindowSize.isVisible = false;
GroupBlockDef *block = new GroupBlockDef ( "Defined Size");
//pre-defined
SettingsItemDef *widthByHeightItem = new SettingsItemDef ("Window Size", "640x480");
WidgetDef widthByHeightWidget = WidgetDef (Widget_ComboBox);
widthByHeightWidget.widgetWidth = 90;
@ -73,27 +49,72 @@ void CSVSettings::WindowPage::setupUi()
widthByHeightItem->widget = widthByHeightWidget;
definedWindowSize.properties << widthByHeightItem;
definedWindowSize.isProxy = true;
definedWindowSize.isVisible = false;
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;
//custom height
SettingsItemDef *heightItem = new SettingsItemDef ("Height", "480");
heightItem->widget = WidgetDef (Widget_LineEdit);
heightItem->widget.widgetWidth = 45;
heightItem->widget.caption = "x";
block->settingItems << widthItem << heightItem;
block->widgetOrientation = Orient_Horizontal;
block->isVisible = false;
return block;
}
CSVSettings::GroupBlockDef *CSVSettings::WindowPage::buildWindowSizeToggle()
{
GroupBlockDef *block = new GroupBlockDef ("Window Size");
// window size toggle
windowSizeToggle.captions << "Pre-Defined" << "Custom";
windowSizeToggle.widgetOrientation = Orient_Vertical;
windowSizeToggle.isVisible = false;
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++)
windowSizeToggle.widgets << new WidgetDef (Widget_RadioButton);
block->widgets << new WidgetDef (Widget_RadioButton);
windowSizeToggle.widgets.at(0)->isDefault = false;
block->widgets.at(0)->isDefault = false;
windowSize.blockDefList << &windowSizeToggle << &definedWindowSize << &customWindowSize;
windowSize.defaultValue = "Custom";
return block;
}
CSVSettings::CustomBlockDef *CSVSettings::WindowPage::buildWindowSize(GroupBlockDef *toggle_def,
GroupBlockDef *defined_def,
GroupBlockDef *custom_def)
{
CustomBlockDef *block = new CustomBlockDef(QString ("Window Size"));
QGridLayout *pageLayout = new QGridLayout(this);
block->blockDefList << toggle_def << defined_def << custom_def;
block->defaultValue = "Custom";
setLayout (pageLayout);
return block;
}
void CSVSettings::WindowPage::setupUi()
{
CustomBlockDef *windowSize = buildWindowSize(buildWindowSizeToggle(),
buildDefinedWindowSize(),
buildCustomWindowSize()
);
mAbstractBlocks << buildBlock<ToggleBlock> (windowSize);
@ -102,8 +123,15 @@ void CSVSettings::WindowPage::setupUi()
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

@ -21,6 +21,12 @@ namespace CSVSettings {
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);
};

@ -10,6 +10,7 @@ CSVWorld::RecordStatusDelegate::RecordStatusDelegate(QUndoStack &undoStack, QObj
mModifiedIcon = new QIcon (":./modified.png");
mAddedIcon = new QIcon (":./added.png");
mDeletedIcon = new QIcon (":./removed.png");
mBaseIcon = new QIcon (":./base.png");
mIconSize = 16;
//Offset values are most likely device-dependent.
@ -38,6 +39,7 @@ void CSVWorld::RecordStatusDelegate::paint (QPainter *painter, const QStyleOptio
{
case 0: // State_BaseOnly
text = "Base";
icon = mBaseIcon;
break;
case 1: // State_Modified

@ -21,6 +21,7 @@ namespace CSVWorld
QIcon *mModifiedIcon;
QIcon *mAddedIcon;
QIcon *mDeletedIcon;
QIcon *mBaseIcon;
int mStatusDisplay;

@ -4,5 +4,6 @@
<file>added.png</file>
<file>modified.png</file>
<file>removed.png</file>
<file>base.png</file>
</qresource>
</RCC>

Loading…
Cancel
Save