Skip to content

Commit

Permalink
Machine editor, ini persistence and a bunch of bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
markwal committed Aug 17, 2015
1 parent 8910c30 commit 2fafef6
Show file tree
Hide file tree
Showing 12 changed files with 908 additions and 222 deletions.
2 changes: 1 addition & 1 deletion GPX
3 changes: 2 additions & 1 deletion GpxUi.pro
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ HEADERS += mainwindow.h \
build/version.h \
inih/ini.h \
iniedit.h \
machineeditor.h
machineeditor.h \
main.h

FORMS += mainwindow.ui \
rungpx.ui \
Expand Down
157 changes: 142 additions & 15 deletions iniedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ extern "C" {
#include <QTextStream>
QTextStream &qStdout();

Section::Section(IniEditor *pie): pie(pie)
{
ilineLast = pie->ll.end();
}

// readline callback for inih, turn a C callback into a C++ method call
char *IniEditor::inihReader(char *szBuffer, int cbBuffer, void *user)
{
Expand All @@ -28,25 +33,30 @@ int IniEditor::inihHandler(void *user, const char *szSection, const char *szName

char *IniEditor::parserReader(char *szBuffer, int cbBuffer)
{
if (fileParsing.atEnd())
if (file.atEnd())
return NULL;

qint64 cb = fileParsing.readLine(szLineParsing = szBuffer, cbBuffer);
if (cb == 0)
qint64 cb = file.readLine(szLineParsing = szBuffer, cbBuffer);
if (cb <= 0 || cb > cbBuffer)
return NULL;

if (szLineParsing[cb - 1] == '\n')
szLineParsing[cb - 1] = 0;
ll.append(Line(false, ll.count(), QString(), QString(), szLineParsing));
return szBuffer;
}

int IniEditor::parserHandler(const char *szSection, const char *szName, const char *szValue)
{
QString sSection(szSection);
if (sSectionParsing != sSection)
LineIterator iline = ll.end();
iline--;
if (sSectionParsing != sSection) {
sSectionParsing = sSection;
si[sSectionParsing].setParent(this);
si[sSectionParsing].ilineLast = iline;
}
if (szName[0]) {
LineIterator iline = ll.end();
iline--;
iline->fHasProperty = true;
QString s(szName);
iline->sName = s;
Expand All @@ -64,18 +74,23 @@ void IniEditor::clear()
fe = QFileDevice::NoError;
}

bool IniEditor::read(QString sPathname, ParserCallback pc = NULL, void *user = NULL)
void IniEditor::setFilename(const QString &sPathname)
{
file.setFileName(sPathname);
}

bool IniEditor::read(ParserCallback pc = NULL, void *user = NULL)
{
clear();
szLineParsing = NULL;
ilineParsing = 0;
sSectionParsing = ""; // fake section for front matter before first section
si[sSectionParsing].setParent(this);
parserCallback = pc;
this->user = user;

fileParsing.setFileName(sPathname);
if (!fileParsing.open(QIODevice::ReadOnly | QIODevice::Text)) {
fe = fileParsing.error();
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
fe = file.error();
return false;
}

Expand All @@ -85,10 +100,25 @@ bool IniEditor::read(QString sPathname, ParserCallback pc = NULL, void *user = N
}
// ignore parsing errors, allow editing of the rest, is that correct?

fileParsing.close();
file.close();
return true;
}

bool IniEditor::write()
{
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return false;

QTextStream ts(&file);
for (ConstLineIterator iline = ll.constBegin(); iline != ll.constEnd(); iline++) {
if (!iline->fDeleted)
ts << iline->sLine << "\n";
}

file.close();
return true;
}

void Section::dump() const
{
for (LineIndex::const_iterator il = li.constBegin(); il != li.constEnd(); il++) {
Expand All @@ -103,15 +133,34 @@ void IniEditor::dump() const
is.value().dump();
}

for (ConstLineIterator il = ll.constBegin(); il != ll.constEnd(); il++ ) {
qStdout() << il->sLine;
for (ConstLineIterator iline = ll.constBegin(); iline != ll.constEnd(); iline++ ) {
qStdout() << iline->sLine;
}
qStdout() << endl;
}

void Section::insert(const QString &sPropertyName, LineIterator il)
Section &IniEditor::section(QString s)
{
Section &sect = si[s];
if (sect.sName.isEmpty()) {
sect.setName(s);
sect.setParent(this);
}
return sect;
}

void Section::setParent(IniEditor *pie)
{
li.insert(sPropertyName, il);
if (pie != this->pie) {
this->pie = pie;
ilineLast = pie->ll.end();
}
}

void Section::insert(const QString &sPropertyName, LineIterator iline)
{
li.insert(sPropertyName, iline);
ilineLast = iline;
}

const QString Section::value(const QString &sPropertyName, const QString &sDefault) const
Expand All @@ -124,3 +173,81 @@ const QString Section::value(const QString &sPropertyName) const
{
return value(sPropertyName, QString::null);
}

int Section::intValue(const QString &sPropertyName, int iDefault) const
{
QString s = value(sPropertyName);
return s.isEmpty() ? iDefault : s.toInt();
}

double Section::value(const QString &sPropertyName, double dDefault) const
{
QString s = value(sPropertyName);
return s.isEmpty() ? dDefault : s.toDouble();
}

void Section::setValue(const QString &sPropertyName, const QString &s)
{
QString sComment = "";
LineIterator iline;
LineIndex::iterator il = li.find(sPropertyName);
if (il != li.end()) {
iline = il.value();

// preserve the comment
int ich = iline->sLine.indexOf(';');
if (ich > 0) {
while (ich > 0 && iline->sLine[ich].isSpace())
ich--;
sComment = iline->sLine.mid(ich);
}

// set the new line content
iline->sLine = QString("%1=%2%3").arg(iline->sName).arg(s).arg(sComment);
iline->sValue = s;
}
else {
iline = ilineLast;
if (iline == pie->ll.end())
pie->ll.append(Line(false, -1, "", "", QString("[%1]").arg(sName)));
else
iline++;
iline = pie->ll.insert(iline, Line(true, -1, sPropertyName, s,
QString("%1=%2").arg(sPropertyName).arg(s)));
insert(sPropertyName, iline);
}
}

void Section::remove(const QString &sPropertyName)
{
LineIndex::iterator il = li.find(sPropertyName);
if (il != li.end()) {
LineIterator iline = il.value();
li.erase(il);
iline->fDeleted = true;
}
}

void Section::setValue(const QString &sPropertyName, const QString &s, const QString &sDefault)
{
if (s == sDefault)
remove(sPropertyName);
else
setValue(sPropertyName, s);
}

void Section::setValue(const QString &sPropertyName, int i, int iDefault)
{
if (i == iDefault)
remove(sPropertyName);
else
setValue(sPropertyName, QString::number(i));
}

void Section::setValue(const QString &sPropertyName, double d, double dDefault, int cdecimals)
{
if (d == dDefault)
remove(sPropertyName);
else
setValue(sPropertyName, QString::number(d, 'f', cdecimals));
}
44 changes: 37 additions & 7 deletions iniedit.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,22 @@
#include <QLinkedList>
#include <QMap>
#include <QFile>
#include <QFileInfo>

class Line
{
public:
Line() {}
Line(bool fHasProperty, int iline, QString sName, QString sValue, QString sLine):
fHasProperty(fHasProperty), iline(iline), sName(sName), sValue(sValue), sLine(sLine) {}

bool fHasProperty;
fHasProperty(fHasProperty), iline(iline), sName(sName), sValue(sValue), sLine(sLine)
{
fDeleted = false;
}

struct {
bool fHasProperty : 1;
bool fDeleted : 1;
};
int iline;
QString sName;
QString sValue;
Expand All @@ -27,48 +34,71 @@ typedef LineList::iterator LineIterator;
typedef LineList::const_iterator ConstLineIterator;
typedef QMap<QString, LineIterator> LineIndex;

class IniEditor;

class Section
{
friend class IniEditor;

public:
Section() {}
Section(IniEditor *pie);
~Section() {}

void setParent(IniEditor *pie);
void setName(QString s) { sName = s; }

void insert(const QString &sPropertyName, LineIterator il);
const Line &getLine(const QString &sPropertyName);
void remove(const QString &sPropertyName);

const QString value(const QString &sPropertyName) const;
const QString value(const QString &sPropertyName, const QString &sDefault) const;
int intValue(const QString &sPropertyName, int iDefault) const;
double value(const QString &sPropertyName, double dDefault) const;
inline const QString operator[](const QString &sPropertyName) const { return value(sPropertyName); }

void setValue(const QString &sPropertyName, const QString &s);
void setValue(const QString &sPropertyName, const QString &s, const QString &sDefault);
void setValue(const QString &sPropertyName, int i, int iDefault);
void setValue(const QString &sPropertyName, double d, double dDefault, int cdecimals = 4);

void dump() const;

private:
QString sName;
LineIndex li;
LineIterator ilineLast;
IniEditor *pie; // parent
};

typedef QMap<QString, Section> SectionIndex;

class IniEditor
{
friend class Section;

public:
IniEditor() {}
~IniEditor() {}

typedef bool (*ParserCallback)(void *user, QString &sSection, Line &line);

void clear();
bool read(QString sPathname, ParserCallback pc, void *user);
void setFilename(const QString &sPathName);
bool read(ParserCallback pc, void *user);
bool write();
QFileDevice::FileError error() {return fe;}

const Section &section(QString s) {return si[s];}
Section &section(QString s);
void dump() const;

private:
SectionIndex si;
LineList ll;

QFileDevice::FileError fe;
QFile fileParsing;
QFile file;

char *szLineParsing;
int ilineParsing;
QString sSectionParsing;
Expand Down
Loading

0 comments on commit 2fafef6

Please sign in to comment.