You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
220 lines
6.2 KiB
C++
220 lines
6.2 KiB
C++
#include "inisettings.hpp"
|
|
|
|
#include <QDir>
|
|
|
|
#include <QTextStream>
|
|
#include <QFile>
|
|
#include <QStringList>
|
|
#include <QString>
|
|
#include <QRegExp>
|
|
#include <QDebug>
|
|
|
|
Wizard::IniSettings::IniSettings()
|
|
{
|
|
}
|
|
|
|
Wizard::IniSettings::~IniSettings()
|
|
{
|
|
}
|
|
|
|
QStringList Wizard::IniSettings::findKeys(const QString &text)
|
|
{
|
|
QStringList result;
|
|
|
|
foreach (const QString &key, mSettings.keys()) {
|
|
|
|
if (key.startsWith(text))
|
|
result << key;
|
|
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool Wizard::IniSettings::readFile(QTextStream &stream)
|
|
{
|
|
// Look for a square bracket, "'\\["
|
|
// that has one or more "not nothing" in it, "([^]]+)"
|
|
// and is closed with a square bracket, "\\]"
|
|
QRegExp sectionRe(QLatin1String("^\\[([^]]+)\\]"));
|
|
|
|
// 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(QLatin1String("^([^=]+)\\s*=\\s*(.+)$"));
|
|
|
|
QString currentSection;
|
|
|
|
while (!stream.atEnd())
|
|
{
|
|
const QString line(stream.readLine());
|
|
|
|
if (line.isEmpty() || line.startsWith(QLatin1Char(';')))
|
|
continue;
|
|
|
|
if (sectionRe.exactMatch(line))
|
|
{
|
|
currentSection = sectionRe.cap(1);
|
|
}
|
|
else if (keyRe.indexIn(line) != -1)
|
|
{
|
|
QString key = keyRe.cap(1).trimmed();
|
|
QString value = keyRe.cap(2).trimmed();
|
|
|
|
// Append the section, but only if there is one
|
|
if (!currentSection.isEmpty())
|
|
key = currentSection + QLatin1Char('/') + key;
|
|
|
|
mSettings[key] = QVariant(value);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Wizard::IniSettings::writeFile(const QString &path, QTextStream &stream)
|
|
{
|
|
// Look for a square bracket, "'\\["
|
|
// that has one or more "not nothing" in it, "([^]]+)"
|
|
// and is closed with a square bracket, "\\]"
|
|
QRegExp sectionRe(QLatin1String("^\\[([^]]+)\\]"));
|
|
|
|
// 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(QLatin1String("^([^=]+)\\s*=\\s*(.+)$"));
|
|
|
|
const QStringList keys(mSettings.keys());
|
|
|
|
QString currentSection;
|
|
QString buffer;
|
|
|
|
while (!stream.atEnd()) {
|
|
|
|
const QString line(stream.readLine());
|
|
|
|
if (line.isEmpty() || line.startsWith(QLatin1Char(';'))) {
|
|
buffer.append(line + QLatin1String("\n"));
|
|
continue;
|
|
}
|
|
|
|
if (sectionRe.exactMatch(line)) {
|
|
buffer.append(line + QLatin1String("\n"));
|
|
currentSection = sectionRe.cap(1);
|
|
} else if (keyRe.indexIn(line) != -1) {
|
|
QString key(keyRe.cap(1).trimmed());
|
|
QString lookupKey(key);
|
|
|
|
// Append the section, but only if there is one
|
|
if (!currentSection.isEmpty())
|
|
lookupKey = currentSection + QLatin1Char('/') + key;
|
|
|
|
buffer.append(key + QLatin1Char('=') + mSettings[lookupKey].toString() + QLatin1String("\n"));
|
|
mSettings.remove(lookupKey);
|
|
}
|
|
}
|
|
|
|
// Add the new settings to the buffer
|
|
QHashIterator<QString, QVariant> i(mSettings);
|
|
while (i.hasNext()) {
|
|
i.next();
|
|
|
|
QStringList fullKey(i.key().split(QLatin1Char('/')));
|
|
QString section(fullKey.at(0));
|
|
section.prepend(QLatin1Char('['));
|
|
section.append(QLatin1Char(']'));
|
|
QString key(fullKey.at(1));
|
|
|
|
int index = buffer.lastIndexOf(section);
|
|
if (index != -1) {
|
|
// Look for the next section
|
|
index = buffer.indexOf(QLatin1Char('['), index + 1);
|
|
|
|
if (index == -1 ) {
|
|
// We are at the last section, append it to the bottom of the file
|
|
buffer.append(QString("\n%1=%2").arg(key, i.value().toString()));
|
|
mSettings.remove(i.key());
|
|
continue;
|
|
} else {
|
|
// Not at last section, add the key at the index
|
|
buffer.insert(index - 1, QString("\n%1=%2").arg(key, i.value().toString()));
|
|
mSettings.remove(i.key());
|
|
}
|
|
|
|
} else {
|
|
// Add the section to the end of the file, because it's not found
|
|
buffer.append(QString("\n%1\n").arg(section));
|
|
i.previous();
|
|
}
|
|
}
|
|
|
|
// Now we reopen the file, this time we write
|
|
QFile file(path);
|
|
|
|
if (file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)) {
|
|
QTextStream in(&file);
|
|
in.setCodec(stream.codec());
|
|
|
|
// Write the updated buffer to an empty file
|
|
in << buffer;
|
|
file.flush();
|
|
file.close();
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Wizard::IniSettings::parseInx(const QString &path)
|
|
{
|
|
QFile file(path);
|
|
|
|
if (file.open(QIODevice::ReadOnly))
|
|
{
|
|
|
|
const QByteArray data(file.readAll());
|
|
const QByteArray pattern("\x21\x00\x1A\x01\x04\x00\x04\x97\xFF\x06", 10);
|
|
|
|
int i = 0;
|
|
while ((i = data.indexOf(pattern, i)) != -1) {
|
|
|
|
int next = data.indexOf(pattern, i + 1);
|
|
if (next == -1)
|
|
break;
|
|
|
|
QByteArray array(data.mid(i, (next - i)));
|
|
|
|
// Skip some invalid entries
|
|
if (array.contains("\x04\x96\xFF")) {
|
|
++i;
|
|
continue;
|
|
}
|
|
|
|
// Remove the pattern from the beginning
|
|
array.remove(0, 12);
|
|
|
|
int index = array.indexOf("\x06");
|
|
const QString section(array.left(index));
|
|
|
|
// Figure how many characters to read for the key
|
|
int lenght = array.indexOf("\x06", section.length() + 3) - (section.length() + 3);
|
|
const QString key(array.mid(section.length() + 3, lenght));
|
|
|
|
QString value(array.mid(section.length() + key.length() + 6));
|
|
|
|
// Add the value
|
|
setValue(section + QLatin1Char('/') + key, QVariant(value));
|
|
|
|
++i;
|
|
}
|
|
|
|
file.close();
|
|
} else {
|
|
qDebug() << "Failed to open INX file: " << path;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|