Commit 99d363dc authored by EXT Arnaud Clère's avatar EXT Arnaud Clère

WIP move error handling to user's hands

parent d523f5ea
This diff is collapsed.
This diff is collapsed.
......@@ -59,9 +59,6 @@ class QModelBind : public QAbstractValue
public:
QModelBind(QAbstractItemModel* m, bool rowFirst=true) : m(m), rowFirst(rowFirst) { Q_ASSERT(m); }
struct Error { QIdentifierLiteral error; QModelIndex index; QValueStatus zap(QValue&& value) { QByteArray u(error.utf8()); for (; index.isValid(); index=index.parent()) u.append('/').append(QByteArray::number(index.row())).append(',').append(QByteArray::number(index.column())); return value.bind(QUtf8Data(u)); } };
QVector<Error> errors;
QValue value() { return QValueStatus(this).value(); }
protected:
enum : int {
......@@ -157,7 +154,15 @@ protected:
virtual bool tryBind( QByteArray& r) { return tryBind(QByteArray(r)); }
virtual bool tryBind( QVariant& r) { return tryBind( QVariant(r)); }
virtual void _reportError(QIdentifierLiteral n) { errors.append(Error{n, parent}); }
void reportError(QIdentifierLiteral e, QString context = QString()) {
if (errorHandler) {
QString path;
for (auto current = parent; parent.isValid(); current = current.parent()) {
path.prepend(QString('/').append(current.row()).append(',').append(current.column()));
}
errorHandler(e, path.append(context));
}
}
virtual QAbstractValue* itemBind() = 0;
......@@ -210,6 +215,8 @@ protected:
QList<QByteArray> columnNames;
bool metaColumnNames=false;
QVector<int> sizes;
QValueErrorHandler errorHandler = QValueErrorHandler();
};
// --------------------------------------------------------------------------
......@@ -306,7 +313,7 @@ protected:
row++; col=0;
return true;
}
_reportError(qBindIgnoredItem);
reportError(qBindIgnoredItem);
return false;
}
return true;
......@@ -321,7 +328,7 @@ protected:
row=0; col++;
return true;
}
_reportError(qBindIgnoredItem);
reportError(qBindIgnoredItem);
return false;
}
return true;
......@@ -352,7 +359,7 @@ protected:
col=columnNames.indexOf(n.utf8());
// TODO if (max(dimension())<=col) col=-1;
if (col<0) {
_reportError(qBindIgnoredItem);
reportError(qBindIgnoredItem);
}
}
return true;
......@@ -369,7 +376,7 @@ protected:
}
else {
// TODO if (rowNames...
_reportError(qBindIgnoredItemName);
reportError(qBindIgnoredItemName);
return true;
}
}
......@@ -502,7 +509,7 @@ protected:
if (col < m->columnCount()) {
return true;
}
_reportError(qBindIgnoredItem);
reportError(qBindIgnoredItem);
return false;
}
return true;
......@@ -520,7 +527,7 @@ protected:
row=0; col++;
return true;
}
_reportError(qBindIgnoredItem);
reportError(qBindIgnoredItem);
return false;
}
return true;
......@@ -553,7 +560,7 @@ protected:
}
// TODO if (max(dimension())<=col) col=-1;
if (col<0) {
_reportError(qBindIgnoredItem);
reportError(qBindIgnoredItem);
}
return true;
}
......@@ -566,7 +573,7 @@ protected:
}
else if (n!=childrenName) {
// TODO if (rowNames...
_reportError(qBindIgnoredItemName);
reportError(qBindIgnoredItemName);
return true;
}
else { return true; }
......@@ -598,12 +605,12 @@ protected:
// TODO QDate*, QTime
// TODO QPixmap if metadata suggests a QMimeData image ?
virtual bool tryBind( qint8& n) { qint64 l; if (!tryBind(l)) return false; if (l<std::numeric_limits< qint8>::min() || std::numeric_limits< qint8>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n= qint8(l); return true; }
virtual bool tryBind( quint8& n) { quint64 l; if (!tryBind(l)) return false; if ( std::numeric_limits< quint8>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n= quint8(l); return true; }
virtual bool tryBind( qint16& n) { qint64 l; if (!tryBind(l)) return false; if (l<std::numeric_limits< qint16>::min() || std::numeric_limits< qint16>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n= qint16(l); return true; }
virtual bool tryBind( quint16& n) { quint64 l; if (!tryBind(l)) return false; if ( std::numeric_limits<quint16>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n=quint16(l); return true; }
virtual bool tryBind( qint32& n) { qint64 l; if (!tryBind(l)) return false; if (l<std::numeric_limits< qint32>::min() || std::numeric_limits< qint32>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n= qint32(l); return true; }
virtual bool tryBind( quint32& n) { quint64 l; if (!tryBind(l)) return false; if ( std::numeric_limits<quint32>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n=quint32(l); return true; }
virtual bool tryBind( qint8& n) { qint64 l; if (!tryBind(l)) return false; if (l<std::numeric_limits< qint8>::min() || std::numeric_limits< qint8>::max()<l) { reportError(qBindExpectedSmallerNumber); return false; } n= qint8(l); return true; }
virtual bool tryBind( quint8& n) { quint64 l; if (!tryBind(l)) return false; if ( std::numeric_limits< quint8>::max()<l) { reportError(qBindExpectedSmallerNumber); return false; } n= quint8(l); return true; }
virtual bool tryBind( qint16& n) { qint64 l; if (!tryBind(l)) return false; if (l<std::numeric_limits< qint16>::min() || std::numeric_limits< qint16>::max()<l) { reportError(qBindExpectedSmallerNumber); return false; } n= qint16(l); return true; }
virtual bool tryBind( quint16& n) { quint64 l; if (!tryBind(l)) return false; if ( std::numeric_limits<quint16>::max()<l) { reportError(qBindExpectedSmallerNumber); return false; } n=quint16(l); return true; }
virtual bool tryBind( qint32& n) { qint64 l; if (!tryBind(l)) return false; if (l<std::numeric_limits< qint32>::min() || std::numeric_limits< qint32>::max()<l) { reportError(qBindExpectedSmallerNumber); return false; } n= qint32(l); return true; }
virtual bool tryBind( quint32& n) { quint64 l; if (!tryBind(l)) return false; if ( std::numeric_limits<quint32>::max()<l) { reportError(qBindExpectedSmallerNumber); return false; } n=quint32(l); return true; }
virtual bool tryBind( QUtf8Data& r) { if (hidden()) return true; if (I<=d) return itemBind()->tryBind(r); QVariant v=read(); if (v.type()!=QVariant ::String ) return false; r=QUtf8Data(v.toString().toUtf8()); return true; }
virtual bool tryBind( QString& r) { if (hidden()) return true; if (I<=d) return itemBind()->tryBind(r); QVariant v=read(); if (v.type()!=QVariant ::String ) return false; r= v.toString () ; return true; }
......
......@@ -96,9 +96,6 @@ public:
Q_ENABLE_MOVE(QSettingsReader, std::swap(isChoice, o.isChoice); )
QSettingsReader(QSettings* s) : settings(s) { Q_ASSERT(s); levels.push(Level(qBindExpectedItem)); }
struct Error { QIdentifierLiteral error; QAsciiData path; QValueStatus zap(QValue&& value) { return value.bind(QUtf8Data(error.utf8()+' '+path.utf8())); } };
QVector<Error> errors;
QAsciiData currentPath() {
QByteArray path;
Q_FOREACH(Level l, levels) {
......@@ -130,20 +127,19 @@ protected:
bool tryBind( float& t) { return set(t, qBindExpectedDecimal ); }
bool tryBind( double& t) { return set(t, qBindExpectedDecimal ); }
bool trySequence(quint32* =nullptr) { if (levels.last().isGroup) { levels.push(Level( )); return true; } _reportError(qBindExpectedSequence); return false; }
bool tryRecord (quint32* =nullptr) { if (levels.last().isGroup) { levels.push(Level(qBindExpectedItem)); return true; } _reportError(qBindExpectedRecord ); return false; }
bool tryNull ( ) { if (settings->value(key()).isNull()) { return true; } _reportError(qBindExpectedNull ); return false; }
bool trySequence(quint32* =nullptr) { if (levels.last().isGroup) { levels.push(Level( )); return true; } reportError(qBindExpectedSequence); return false; }
bool tryRecord (quint32* =nullptr) { if (levels.last().isGroup) { levels.push(Level(qBindExpectedItem)); return true; } reportError(qBindExpectedRecord ); return false; }
bool tryNull ( ) { if (settings->value(key()).isNull()) { return true; } reportError(qBindExpectedNull ); return false; }
bool tryItem(QIdentifier& k) { levels.last().key=k ; return true; }
bool tryItem( ) { levels.last().idx++ ; return true; }
bool tryOut ( ) { levels.pop(); settings->endGroup(); return true; }
bool _isOk() const noexcept { return settings; }
void _setChoice(bool v) { isChoice=v; }
void _reportError(QIdentifierLiteral error) { if (!isChoice) errors.append(Error{ error, currentPath() }); }
void reportError(QIdentifierLiteral error, QString context = QString()) { if (errorHandler) errorHandler(error, QString(currentPath().latin1()).append(context)); }
private:
template<typename T>
bool set(T& t, QIdentifierLiteral error) { QVariant v = settings->value(key()); if (v.convert(qMetaTypeId<T>())) { t = v.value<T>(); return true; } _reportError(error); return false; }
bool set(T& t, QIdentifierLiteral error) { QVariant v = settings->value(key()); if (v.convert(qMetaTypeId<T>())) { t = v.value<T>(); return true; } reportError(error); return false; }
QString key() {
Q_ASSERT(!levels.isEmpty());
return !levels.last().key.isNull()
......
This diff is collapsed.
......@@ -120,10 +120,7 @@ class QVariantVisitor : public QAbstractValueReader
public:
Q_ENABLE_MOVE_DEFAULT(QVariantVisitor)
QVariantVisitor(const QVariant* v) : value(v) { Q_ASSERT(v); }
void reset(const QVariant* v) { value=v; Q_ASSERT(v); levels.resize(0); errors.resize(0); }
struct Error { QIdentifierLiteral error; QAsciiData path; template<class T> T bind(QVal<T>&& value) { return value.bind(QUtf8Data(error.utf8()+' '+path.utf8())); } };
QVector<Error> errors;
void reset(const QVariant* v) { value=v; Q_ASSERT(v); levels.resize(0); }
QAsciiData currentPath() {
QByteArray path;
......@@ -137,54 +134,52 @@ protected:
// TODO Support _meta to be able to cache and restitute all metadata as well as data+datatype
template<typename T>
bool tryBind(T& t) { if (current()->type()==qMetaTypeId<T>()) { t = current()->value<T>(); return true; } _reportError(QIdentifierLiteral("ExpectedDeclaredMetatypeT")); return false; }
bool tryBind(T& t) { if (current()->type()==qMetaTypeId<T>()) { t = current()->value<T>(); return true; } reportError(QIdentifierLiteral("ExpectedDeclaredMetatypeT")); return false; }
bool tryBind( QUtf8Data& t) { if (current()->userType() // TODO ->type() if QUtf8Data lands into Qt
==qMetaTypeId< QUtf8Data>()) { t = current()->value< QUtf8Data>(); return true; } _reportError(qBindExpectedText ); return false; }
bool tryBind( QString& t) { if (current()->type()==qMetaTypeId< QString>()) { t = current()->value< QString>(); return true; } _reportError(qBindExpectedText ); return false; }
bool tryBind( bool& t) { if (current()->type()==qMetaTypeId< bool>()) { t = current()->value< bool>(); return true; } _reportError(qBindExpectedBoolean ); return false; }
bool tryBind(QByteArray& t) { if (current()->type()==qMetaTypeId<QByteArray>()) { t = current()->value<QByteArray>(); return true; } _reportError(qBindExpectedBytes ); return false; }
==qMetaTypeId< QUtf8Data>()) { t = current()->value< QUtf8Data>(); return true; } reportError(qBindExpectedText ); return false; }
bool tryBind( QString& t) { if (current()->type()==qMetaTypeId< QString>()) { t = current()->value< QString>(); return true; } reportError(qBindExpectedText ); return false; }
bool tryBind( bool& t) { if (current()->type()==qMetaTypeId< bool>()) { t = current()->value< bool>(); return true; } reportError(qBindExpectedBoolean ); return false; }
bool tryBind(QByteArray& t) { if (current()->type()==qMetaTypeId<QByteArray>()) { t = current()->value<QByteArray>(); return true; } reportError(qBindExpectedBytes ); return false; }
// Convert numerical types to strictly larger ones // TODO convert all compatible values
bool tryBind( qint8& t) { if (current()->type()==qMetaTypeId< qint8>()) { t = current()->value< qint8>(); return true; } _reportError(qBindExpectedInteger ); return false; }
bool tryBind( qint8& t) { if (current()->type()==qMetaTypeId< qint8>()) { t = current()->value< qint8>(); return true; } reportError(qBindExpectedInteger ); return false; }
bool tryBind( qint16& t) { if (current()->type()==qMetaTypeId< qint8>()||
current()->type()==qMetaTypeId< qint16>()) { t = current()->value< qint16>(); return true; } _reportError(qBindExpectedInteger ); return false; }
current()->type()==qMetaTypeId< qint16>()) { t = current()->value< qint16>(); return true; } reportError(qBindExpectedInteger ); return false; }
bool tryBind( qint32& t) { if (current()->type()==qMetaTypeId< qint8>()||
current()->type()==qMetaTypeId< qint16>()||
current()->type()==qMetaTypeId< qint32>()) { t = current()->value< qint32>(); return true; } _reportError(qBindExpectedInteger ); return false; }
current()->type()==qMetaTypeId< qint32>()) { t = current()->value< qint32>(); return true; } reportError(qBindExpectedInteger ); return false; }
bool tryBind( qint64& t) { if (current()->type()==qMetaTypeId< qint8>()||
current()->type()==qMetaTypeId< qint16>()||
current()->type()==qMetaTypeId< qint32>()||
current()->type()==qMetaTypeId< qint64>()) { t = current()->value< qint64>(); return true; } _reportError(qBindExpectedInteger ); return false; }
bool tryBind( quint8& t) { if (current()->type()==qMetaTypeId< quint8>()) { t = current()->value< quint8>(); return true; } _reportError(qBindExpectedPositiveInteger); return false; }
current()->type()==qMetaTypeId< qint64>()) { t = current()->value< qint64>(); return true; } reportError(qBindExpectedInteger ); return false; }
bool tryBind( quint8& t) { if (current()->type()==qMetaTypeId< quint8>()) { t = current()->value< quint8>(); return true; } reportError(qBindExpectedPositiveInteger); return false; }
bool tryBind( quint16& t) { if (current()->type()==qMetaTypeId< quint8>()||
current()->type()==qMetaTypeId< quint16>()) { t = current()->value< quint16>(); return true; } _reportError(qBindExpectedPositiveInteger); return false; }
current()->type()==qMetaTypeId< quint16>()) { t = current()->value< quint16>(); return true; } reportError(qBindExpectedPositiveInteger); return false; }
bool tryBind( quint32& t) { if (current()->type()==qMetaTypeId< quint8>()||
current()->type()==qMetaTypeId< quint16>()||
current()->type()==qMetaTypeId< quint32>()) { t = current()->value< quint32>(); return true; } _reportError(qBindExpectedPositiveInteger); return false; }
current()->type()==qMetaTypeId< quint32>()) { t = current()->value< quint32>(); return true; } reportError(qBindExpectedPositiveInteger); return false; }
bool tryBind( quint64& t) { if (current()->type()==qMetaTypeId< quint8>()||
current()->type()==qMetaTypeId< quint16>()||
current()->type()==qMetaTypeId< quint32>()||
current()->type()==qMetaTypeId< quint64>()) { t = current()->value< quint64>(); return true; } _reportError(qBindExpectedPositiveInteger); return false; }
bool tryBind( float& t) { if (current()->type()==qMetaTypeId< float>()) { t = current()->value< float>(); return true; } _reportError(qBindExpectedDecimal ); return false; }
current()->type()==qMetaTypeId< quint64>()) { t = current()->value< quint64>(); return true; } reportError(qBindExpectedPositiveInteger); return false; }
bool tryBind( float& t) { if (current()->type()==qMetaTypeId< float>()) { t = current()->value< float>(); return true; } reportError(qBindExpectedDecimal ); return false; }
bool tryBind( double& t) { if (current()->type()==qMetaTypeId< float>()||
current()->type()==qMetaTypeId< double>()) { t = current()->value< double>(); return true; } _reportError(qBindExpectedDecimal ); return false; }
current()->type()==qMetaTypeId< double>()) { t = current()->value< double>(); return true; } reportError(qBindExpectedDecimal ); return false; }
bool trySequence(quint32* =nullptr) { if (current()->type()==QVariant::List ) { levels.push(Level()); return true; } _reportError(qBindExpectedSequence); return false; }
bool tryRecord (quint32* =nullptr) { if (current()->type()==QVariant::Map ) { levels.push(Level()); return true; } _reportError(qBindExpectedRecord ); return false; }
bool tryNull ( ) { if (current()->isNull() ) { return true; } _reportError(qBindExpectedNull ); return false; }
bool trySequence(quint32* =nullptr) { if (current()->type()==QVariant::List ) { levels.push(Level()); return true; } reportError(qBindExpectedSequence); return false; }
bool tryRecord (quint32* =nullptr) { if (current()->type()==QVariant::Map ) { levels.push(Level()); return true; } reportError(qBindExpectedRecord ); return false; }
bool tryNull ( ) { if (current()->isNull() ) { return true; } reportError(qBindExpectedNull ); return false; }
bool tryItem(QIdentifier& k) { levels.last().key=k; return (levels.last().item = current(1)->toMap ().value(QString(levels.last().key.latin1()), QVariant())).isValid(); }
bool tryItem( ) { levels.last().idx++; return (levels.last().item = current(1)->toList().value( levels.last().idx , QVariant())).isValid(); }
bool tryOut ( ) { levels.pop() ; return true; }
bool _isOk() const noexcept { return value; }
void _setChoice(bool v) { isChoice=v; }
void _reportError(QIdentifierLiteral error) { if (!isChoice) errors.append(Error{ error, currentPath() }); }
void reportError(QIdentifierLiteral error, QString context = QString()) { if (errorHandler) errorHandler(error, QString(currentPath().latin1()).append(context)); }
private:
const QVariant* current(unsigned outer=0) const { return unsigned(levels.size())-outer <= 0 ? value : &(levels[unsigned(levels.size())-outer-1].item); }
const QVariant* value;
struct Level { QIdentifier key=QIdentifier(); int idx=-1; QVariant item; Level() = default; };
QStack<Level> levels;
bool isChoice = false;
};
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment