492 lines
18 KiB
C++
492 lines
18 KiB
C++
/*
|
|
QAD - Qt ADvanced
|
|
|
|
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef QPICONFIG_H
|
|
#define QPICONFIG_H
|
|
|
|
#include "qad_utils_export.h"
|
|
|
|
#include <QColor>
|
|
#include <QDebug>
|
|
#include <QFile>
|
|
#include <QPointF>
|
|
#include <QRectF>
|
|
#include <QStringList>
|
|
#include <QTextStream>
|
|
#include <QVector>
|
|
#include <cmath>
|
|
|
|
|
|
inline QByteArray QString2QByteArray(const QString & string) {
|
|
return string.isEmpty() ? QByteArray() : qUncompress(QByteArray::fromBase64(string.toLatin1()));
|
|
}
|
|
QAD_UTILS_EXPORT int QString2int(const QString & string);
|
|
inline QColor QString2QColor(const QString & string) {
|
|
return (string.left(1) == "#" ? QColor(string.right(string.length() - 1).toInt(0, 16)) : QColor(QString2int(string)));
|
|
}
|
|
QAD_UTILS_EXPORT QRect QString2QRect(const QString & string);
|
|
QAD_UTILS_EXPORT QRectF QString2QRectF(const QString & string);
|
|
QAD_UTILS_EXPORT QPoint QString2QPoint(const QString & string);
|
|
QAD_UTILS_EXPORT QPointF QString2QPointF(const QString & string);
|
|
|
|
inline QString QColor2QString(const QColor & color) {
|
|
QString s = color.name();
|
|
return "0x" + QString::number(color.alpha(), 16).rightJustified(2, '0') + s.right(s.length() - 1);
|
|
}
|
|
inline QString QPoint2QString(const QPoint & point) {
|
|
return QString::number(point.x()) + ";" + QString::number(point.y());
|
|
}
|
|
inline QString QPointF2QString(const QPointF & point) {
|
|
return QString::number(point.x()) + ";" + QString::number(point.y());
|
|
}
|
|
inline QString QByteArray2QString(const QByteArray & array) {
|
|
return array.isEmpty() ? QString() : QString(qCompress(array, 9).toBase64());
|
|
}
|
|
QAD_UTILS_EXPORT QString QRect2QString(const QRect & rect);
|
|
QAD_UTILS_EXPORT QString QRectF2QString(const QRectF & rect);
|
|
|
|
// clang-format off
|
|
#define QPICONFIG_GET_VALUE \
|
|
Entry & getValue(const QString & vname, const char * def, bool * exist = 0) {return getValue(vname, QString(def), exist);} \
|
|
Entry & getValue(const QString & vname, const QStringList & def, bool * exist = 0) {return getValue(vname, def.join("%|%"), exist);} \
|
|
Entry & getValue(const QString & vname, const bool def, bool * exist = 0) {return getValue(vname, QString::number(def), exist);} \
|
|
Entry & getValue(const QString & vname, const short def, bool * exist = 0) {return getValue(vname, QString::number(def), exist);} \
|
|
Entry & getValue(const QString & vname, const int def, bool * exist = 0) {return getValue(vname, QString::number(def), exist);} \
|
|
Entry & getValue(const QString & vname, const long def, bool * exist = 0) {return getValue(vname, QString::number(def), exist);} \
|
|
Entry & getValue(const QString & vname, const uchar def, bool * exist = 0) {return getValue(vname, QString::number(def), exist);} \
|
|
Entry & getValue(const QString & vname, const ushort def, bool * exist = 0) {return getValue(vname, QString::number(def), exist);} \
|
|
Entry & getValue(const QString & vname, const uint def, bool * exist = 0) {return getValue(vname, QString::number(def), exist);} \
|
|
Entry & getValue(const QString & vname, const ulong def, bool * exist = 0) {return getValue(vname, QString::number(def), exist);} \
|
|
Entry & getValue(const QString & vname, const float def, bool * exist = 0) {return getValue(vname, QString::number(def), exist);} \
|
|
Entry & getValue(const QString & vname, const double def, bool * exist = 0) {return getValue(vname, QString::number(def), exist);} \
|
|
Entry & getValue(const QString & vname, const QColor & def, bool * exist = 0) {return getValue(vname, QColor2QString(def), exist);} \
|
|
Entry & getValue(const QString & vname, const Qt::GlobalColor def, bool * exist = 0) {return getValue(vname, QColor(def), exist);} \
|
|
Entry & getValue(const QString & vname, const QRect & def, bool * exist = 0) {return getValue(vname, QRect2QString(def), exist);} \
|
|
Entry & getValue(const QString & vname, const QRectF & def, bool * exist = 0) {return getValue(vname, QRectF2QString(def), exist);} \
|
|
Entry & getValue(const QString & vname, const QPoint & def, bool * exist = 0) {return getValue(vname, QPoint2QString(def), exist);} \
|
|
Entry & getValue(const QString & vname, const QPointF & def, bool * exist = 0) {return getValue(vname, QPointF2QString(def), exist);} \
|
|
Entry & getValue(const QString & vname, const QByteArray & def, bool * exist = 0) {return getValue(vname, QByteArray2QString(def), exist);}
|
|
// clang-format on
|
|
|
|
class QAD_UTILS_EXPORT QPIConfig: public QFile {
|
|
friend class Entry;
|
|
friend class Branch;
|
|
friend class QPIConfigWidget;
|
|
|
|
public:
|
|
enum FileType {
|
|
Config,
|
|
XML
|
|
};
|
|
|
|
QPIConfig(const QString & path, QIODevice::OpenMode mode, QPIConfig::FileType type);
|
|
QPIConfig(const QString & path, QIODevice::OpenMode mode = QIODevice::ReadWrite);
|
|
QPIConfig(const QString & path, QPIConfig::FileType type);
|
|
QPIConfig(QString * str, QPIConfig::FileType type = QPIConfig::Config);
|
|
~QPIConfig();
|
|
|
|
void setFile(const QString & path, QIODevice::OpenMode mode = QIODevice::ReadWrite);
|
|
void setString(QString * str);
|
|
|
|
void setCodec(const char * codecName);
|
|
|
|
class Entry;
|
|
|
|
class QAD_UTILS_EXPORT Branch: public QVector<Entry *> {
|
|
friend class QPIConfig;
|
|
friend class Entry;
|
|
|
|
public:
|
|
Branch() { ; }
|
|
|
|
Entry & getValue(const QString & vname, const QString & def = QString(), bool * exist = 0);
|
|
QPICONFIG_GET_VALUE
|
|
|
|
Branch allLeaves();
|
|
Branch getValues(const QString & name);
|
|
Branch getLeaves();
|
|
Branch getBranches();
|
|
Branch & filter(const QString & f);
|
|
bool isEntryExists(const QString & name) const {
|
|
foreach(const Entry * i, *this)
|
|
if (entryExists(i, name)) return true;
|
|
return false;
|
|
}
|
|
int indexOf(const Entry * e) {
|
|
for (int i = 0; i < size(); ++i)
|
|
if (at(i) == e) return i;
|
|
return -1;
|
|
}
|
|
|
|
private:
|
|
bool entryExists(const Entry * e, const QString & name) const;
|
|
void allLeaves(Branch & b, Entry * e) {
|
|
foreach(Entry * i, e->_children) {
|
|
if (i->isLeaf())
|
|
b << i;
|
|
else
|
|
allLeaves(b, i);
|
|
}
|
|
}
|
|
|
|
static Entry _empty;
|
|
QString delim;
|
|
};
|
|
|
|
class QAD_UTILS_EXPORT Entry {
|
|
friend class QPIConfig;
|
|
friend class Branch;
|
|
friend class QPIConfigWidget;
|
|
friend class ConfigValueWidget;
|
|
|
|
public:
|
|
Entry() {
|
|
_parent = 0;
|
|
_line = -1;
|
|
}
|
|
|
|
Entry * parent() const { return _parent; }
|
|
int childCount() { return _children.size(); }
|
|
Branch & children() {
|
|
_children.delim = delim;
|
|
return _children;
|
|
}
|
|
Entry * child(const int index) const { return _children[index]; }
|
|
const Entry * findChild(const QString & name) const {
|
|
foreach(const Entry * i, _children)
|
|
if (i->_name == name) return i;
|
|
return 0;
|
|
}
|
|
Entry * findChild(const QString & name) {
|
|
foreach(Entry * i, _children)
|
|
if (i->_name == name) return i;
|
|
return 0;
|
|
}
|
|
bool isLeaf() const { return _children.empty(); }
|
|
|
|
const QString & name() const { return _name; }
|
|
const QString & value() const { return _value; }
|
|
const QString & type() const { return _type; }
|
|
const QString & comment() const { return _comment; }
|
|
|
|
Entry & setName(const QString & value) {
|
|
_name = value;
|
|
return *this;
|
|
}
|
|
Entry & setType(const QString & value) {
|
|
_type = value;
|
|
return *this;
|
|
}
|
|
Entry & setComment(const QString & value) {
|
|
_comment = value;
|
|
return *this;
|
|
}
|
|
Entry & setValue(const QString & value) {
|
|
_value = value;
|
|
return *this;
|
|
}
|
|
Entry & setValue(const QStringList & value) {
|
|
setValue(value.join("%|%"));
|
|
setType("l");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const char * value) {
|
|
setValue(QString(value));
|
|
setType("s");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const bool value) {
|
|
setValue(QString::number(value));
|
|
setType("b");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const short value) {
|
|
setValue(QString::number(value));
|
|
setType("n");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const int value) {
|
|
setValue(QString::number(value));
|
|
setType("n");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const long value) {
|
|
setValue(QString::number(value));
|
|
setType("n");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const uchar value) {
|
|
setValue(QString::number(value));
|
|
setType("n");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const ushort value) {
|
|
setValue(QString::number(value));
|
|
setType("n");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const uint value) {
|
|
setValue(QString::number(value));
|
|
setType("n");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const ulong value) {
|
|
setValue(QString::number(value));
|
|
setType("n");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const float value) {
|
|
setValue(QString::number(value));
|
|
setType("f");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const double value) {
|
|
setValue(QString::number(value));
|
|
setType("f");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const QColor & value) {
|
|
setValue(QColor2QString(value));
|
|
setType("c");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const Qt::GlobalColor & value) {
|
|
setValue(QColor(value));
|
|
return *this;
|
|
}
|
|
Entry & setValue(const QRect & value) {
|
|
setValue(QRect2QString(value));
|
|
setType("r");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const QRectF & value) {
|
|
setValue(QRectF2QString(value));
|
|
setType("a");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const QPoint & value) {
|
|
setValue(QPoint2QString(value));
|
|
setType("p");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const QPointF & value) {
|
|
setValue(QPointF2QString(value));
|
|
setType("v");
|
|
return *this;
|
|
}
|
|
Entry & setValue(const QByteArray & value) {
|
|
setValue(QByteArray2QString(value));
|
|
setType("s");
|
|
return *this;
|
|
}
|
|
|
|
Entry & getValue(const QString & vname, const QString & def = QString(), bool * exist = 0);
|
|
QPICONFIG_GET_VALUE
|
|
|
|
Branch getValues(const QString & vname);
|
|
|
|
bool isEntryExists(const QString & name) const { return entryExists(this, name); }
|
|
|
|
bool toBool() const {
|
|
return (_value.toLower().trimmed() == "true" || _value.toLower().trimmed() == "yes" || _value.toLower().trimmed() == "on" ||
|
|
_value.toInt() > 0);
|
|
}
|
|
char toChar() const { return (_value.isEmpty() ? 0 : _value[0].toLatin1()); }
|
|
short toShort() const { return _value.toShort(); }
|
|
int toInt() const { return QString2int(_value); }
|
|
long toLong() const { return QString2int(_value); }
|
|
uchar toUChar() const { return QString2int(_value); }
|
|
ushort toUShort() const { return QString2int(_value); }
|
|
uint toUInt() const { return QString2int(_value); }
|
|
ulong toULong() const { return QString2int(_value); }
|
|
float toFloat() const { return _value.toFloat(); }
|
|
double toDouble() const { return _value.toDouble(); }
|
|
QString toString() const { return _value; }
|
|
QStringList toStringList() const { return _value.split("%|%"); }
|
|
QColor toColor() const { return QString2QColor(_value); }
|
|
QRect toRect() const { return QString2QRect(_value); }
|
|
QRectF toRectF() const { return QString2QRectF(_value); }
|
|
QPoint toPoint() const { return QString2QPoint(_value); }
|
|
QPointF toPointF() const { return QString2QPointF(_value); }
|
|
QByteArray toByteArray() const { return QString2QByteArray(_value); }
|
|
|
|
private:
|
|
static bool compare(const QPIConfig::Entry * f, const QPIConfig::Entry * s) { return f->_line < s->_line; }
|
|
bool entryExists(const Entry * e, const QString & name) const;
|
|
void buildLine() { _all = _tab + _full_name + " = " + _value + " #" + _type + " " + _comment; }
|
|
void clear() {
|
|
_children.clear();
|
|
_name = _value = _type = _comment = _all = QString();
|
|
_line = 0;
|
|
_parent = 0;
|
|
}
|
|
void deleteBranch() {
|
|
foreach(Entry * i, _children) {
|
|
i->deleteBranch();
|
|
delete i;
|
|
}
|
|
}
|
|
|
|
static Entry _empty;
|
|
Entry * _parent;
|
|
Branch _children;
|
|
QString _tab;
|
|
QString _name;
|
|
QString _value;
|
|
QString _type;
|
|
QString _comment;
|
|
QString _all;
|
|
QString _full_name;
|
|
QString delim;
|
|
int _line;
|
|
};
|
|
|
|
Entry & getValue(const QString & vname, const QString & def = QString(), bool * exist = 0);
|
|
QPICONFIG_GET_VALUE
|
|
|
|
Branch getValues(const QString & vname);
|
|
|
|
void setValue(const QString & name, const QString & value, const QString & type = "s", bool write = true);
|
|
void setValue(const QString & name, const QStringList & value, bool write = true) { setValue(name, value.join("%|%"), "l", write); }
|
|
void setValue(const QString & name, const char * value, bool write = true) { setValue(name, QString(value), "s", write); }
|
|
void setValue(const QString & name, const bool value, bool write = true) { setValue(name, QString::number(value), "b", write); }
|
|
void setValue(const QString & name, const short value, bool write = true) { setValue(name, QString::number(value), "n", write); }
|
|
void setValue(const QString & name, const int value, bool write = true) { setValue(name, QString::number(value), "n", write); }
|
|
void setValue(const QString & name, const long value, bool write = true) { setValue(name, QString::number(value), "n", write); }
|
|
void setValue(const QString & name, const uchar value, bool write = true) { setValue(name, QString::number(value), "n", write); }
|
|
void setValue(const QString & name, const ushort value, bool write = true) { setValue(name, QString::number(value), "n", write); }
|
|
void setValue(const QString & name, const uint value, bool write = true) { setValue(name, QString::number(value), "n", write); }
|
|
void setValue(const QString & name, const ulong value, bool write = true) { setValue(name, QString::number(value), "n", write); }
|
|
void setValue(const QString & name, const float value, bool write = true) { setValue(name, QString::number(value), "f", write); }
|
|
void setValue(const QString & name, const double value, bool write = true) { setValue(name, QString::number(value), "f", write); }
|
|
void setValue(const QString & name, const QColor & value, bool write = true) { setValue(name, QColor2QString(value), "c", write); }
|
|
void setValue(const QString & name, const Qt::GlobalColor & value, bool write = true) { setValue(name, QColor(value), write); }
|
|
void setValue(const QString & name, const QRect & value, bool write = true) { setValue(name, QRect2QString(value), "r", write); }
|
|
void setValue(const QString & name, const QRectF & value, bool write = true) { setValue(name, QRectF2QString(value), "a", write); }
|
|
void setValue(const QString & name, const QPoint & value, bool write = true) { setValue(name, QPoint2QString(value), "p", write); }
|
|
void setValue(const QString & name, const QPointF & value, bool write = true) { setValue(name, QPointF2QString(value), "v", write); }
|
|
void setValue(const QString & name, const QByteArray & value, bool write = true) {
|
|
setValue(name, QByteArray2QString(value), "s", write);
|
|
}
|
|
|
|
Entry & rootEntry() { return root; }
|
|
int entriesCount() const { return childCount(&root); }
|
|
bool isEntryExists(const QString & name) const { return entryExists(&root, name); }
|
|
|
|
Branch allTree() {
|
|
Branch b;
|
|
foreach(Entry * i, root._children)
|
|
b << i;
|
|
return b;
|
|
}
|
|
Branch allLeaves();
|
|
int entryIndex(const QString & name);
|
|
|
|
QString getName(uint number) { return entryByIndex(number)._name; }
|
|
QString getValueByIndex(uint number) { return entryByIndex(number)._value; }
|
|
QChar getType(uint number) { return entryByIndex(number)._type[0]; }
|
|
QString getComment(uint number) { return entryByIndex(number)._comment; }
|
|
|
|
QPIConfig::Entry &
|
|
addEntry(const QString & name, const QString & value, const QString & type = "s", bool write = true, bool node = false);
|
|
void setName(uint number, const QString & name, bool write = true);
|
|
void setValue(uint number, const QString & value, bool write = true);
|
|
void setType(uint number, const QString & type, bool write = true);
|
|
void setComment(uint number, const QString & comment, bool write = true);
|
|
|
|
void removeEntry(const QString & name, bool write = true);
|
|
void removeEntry(uint number, bool write = true);
|
|
|
|
void clear();
|
|
void readAll();
|
|
void writeAll();
|
|
QString writeAllToString();
|
|
void readAllFromString(const QString & str);
|
|
|
|
const QString & delimiter() const { return delim; }
|
|
void setDelimiter(const QString & d) {
|
|
delim = d;
|
|
setEntryDelim(&root, d);
|
|
readAll();
|
|
}
|
|
|
|
private:
|
|
QPIConfig(const QString & path, QStringList dirs);
|
|
void init();
|
|
int childCount(const Entry * e) const {
|
|
int c = 0;
|
|
foreach(const Entry * i, e->_children)
|
|
c += childCount(i);
|
|
c += e->_children.size();
|
|
return c;
|
|
}
|
|
bool entryExists(const Entry * e, const QString & name) const;
|
|
void buildFullNames(Entry * e) {
|
|
foreach(Entry * i, e->_children) {
|
|
if (e != &root)
|
|
i->_full_name = e->_full_name + delim + i->_name;
|
|
else
|
|
i->_full_name = i->_name;
|
|
buildFullNames(i);
|
|
}
|
|
}
|
|
void allLeaves(Branch & b, Entry * e) {
|
|
foreach(Entry * i, e->_children) {
|
|
if ((!i->_value.isEmpty() && !i->isLeaf()) || i->isLeaf()) b << i;
|
|
allLeaves(b, i);
|
|
}
|
|
}
|
|
void setEntryDelim(Entry * e, const QString & d) {
|
|
foreach(Entry * i, e->_children)
|
|
setEntryDelim(i, d);
|
|
e->delim = d;
|
|
}
|
|
inline Entry & entryByIndex(const int index) {
|
|
Branch b = allLeaves();
|
|
if (index < 0 || index >= b.size()) return empty;
|
|
return *(b[index]);
|
|
}
|
|
void removeEntry(Branch & b, Entry * e);
|
|
void deleteEntry(Entry * e) {
|
|
foreach(Entry * i, e->_children)
|
|
deleteEntry(i);
|
|
delete e;
|
|
}
|
|
QString getPrefixFromLine(QString line, bool * exists);
|
|
void updateIncludes();
|
|
QString parseLine(QString v);
|
|
void parse(QString content = QString());
|
|
void setupCodec();
|
|
|
|
int centry;
|
|
bool internal;
|
|
QVector<QPIConfig *> includes, inc_devs;
|
|
Branch all_includes;
|
|
QFile * dev;
|
|
QStringList incdirs;
|
|
QString delim, *buffer, codec;
|
|
Entry root, empty;
|
|
uint lines;
|
|
QStringList other;
|
|
QTextStream stream;
|
|
FileType type;
|
|
};
|
|
|
|
#endif // QPICONFIG_H
|