Vous avez reçu un message "Your GitLab account has been locked ..." ? Pas d'inquiétude : lisez cet article https://docs.gricad-pages.univ-grenoble-alpes.fr/help/unlock/

Commit 71eb27b9 authored by EXT Arnaud Clère's avatar EXT Arnaud Clère
Browse files

BindNative QVariant to allow QData*, QModel*, QSettings* to handle them

using runtime type information
parent 1f1d2814
......@@ -331,6 +331,7 @@ private:
// //////////////////////////////////////////////////////////////////////////
// Base Cur<TImpl> implementations for Read and Write BindMode
#include <QtCore/qvariant.h>
//#include <QtCore/qfloat16.h>
//#include <QtCore/qdatetime.h>
//#include <QtCore/quuid.h>
......@@ -366,6 +367,7 @@ struct IBind {
virtual bool _bind( float& r) = 0; //!< \warning Must return false instead of losing sign or digit
virtual bool _bind( double& r) = 0; //!< \warning Must return false instead of losing sign or digit
virtual bool _bind( QByteArray& r) = 0;
virtual bool _bind( QVariant& r) = 0;
// TODO QChar, QDateTime, QDate, QTime, QUuid (text or numerical)
......@@ -385,6 +387,7 @@ struct IBind {
virtual bool _bind(const float& r) = 0;
virtual bool _bind(const double& r) = 0;
virtual bool _bind(const QByteArray& r) = 0;
virtual bool _bind(const QVariant& r) = 0;
virtual bool _bind( QUtf8String&& r) = 0;
virtual bool _bind( QString&& r) = 0;
......@@ -400,6 +403,7 @@ struct IBind {
virtual bool _bind( float&& r) = 0;
virtual bool _bind( double&& r) = 0;
virtual bool _bind( QByteArray&& r) = 0;
virtual bool _bind( QVariant&& r) = 0;
virtual bool _bind( const char* u) = 0;
......@@ -433,6 +437,7 @@ template<> struct BindSupport< double> : BindNative {};
//template<> struct BindSupport< QTime> : BindNative {};
//template<> struct BindSupport< QUuid> : BindNative {};
template<> struct BindSupport< QByteArray> : BindNative {};
template<> struct BindSupport< QVariant> : BindNative {};
static char *qulltoa2(char *p, qulonglong n, int base=10)
{
......@@ -456,6 +461,8 @@ static char * qlltoa2(char *p, qlonglong n, int base=10)
return p;
}
#include <QtCore/qdatastream.h>
//! Base IBind implementation with BindMode::Write
struct IWriter : public IBind
{
......@@ -489,6 +496,57 @@ struct IWriter : public IBind
virtual bool _bind( float&& n) { static QUtf8String s; s.setNum(double(n),'g',std::numeric_limits< float>::max_digits10); return _bind(s.constData()); } // with specific precision
virtual bool _bind( double&& n) { static QUtf8String s; s.setNum( n ,'g',std::numeric_limits< double>::max_digits10); return _bind(s.constData()); } // with specific precision
virtual bool _bind( QByteArray&& s) { QUtf8String hex(s.size()*2+2+1,'\0'); hex.append("0x"); hex.append(s.toHex()); return _bind(hex.constData()); }
virtual bool _bind( QVariant&& src) {
if (src.canConvert<QVariantList>()) {
QSequentialIterable ts = src.value<QSequentialIterable>();
quint32 size=quint32(ts.size());
if (!_sequence(&size)) {
return false;
}
for (QVariant t : ts) {
if (!_item() || !_bind(QVariant(t))) {
return false;
}
}
return _out();
}
if (src.canConvert<QVariantMap >() ) { // TODO _meta({{qmColumns,"key,value"}}) _sequence() ...
QAssociativeIterable ts = src.value<QAssociativeIterable>();
quint32 size=quint32(ts.size());
if (!_record(&size)) {
return false;
}
QAssociativeIterable::const_iterator i = ts.begin();
const QAssociativeIterable::const_iterator end = ts.end();
for ( ; i != end; ++i) {
if (!_item(i.key().toString().toUtf8().constData()) || !_bind(QVariant(*i))) {
return false;
}
}
return _out();
}
if (src.isNull() ) return _null();
if (src.type()==QVariant::Bool ) return _bind(src.value< bool>());
if (src.type()==QVariant::String ) return _bind(src.value< QString>());
if (src.type()==QVariant::Char ) return _bind(src.toString());
if (src.type()==QVariant::ULongLong) return _bind(src.value< quint64>());
if (src.type()==QVariant::UInt ) return _bind(src.value<unsigned int>());
if (src.type()==QVariant::LongLong ) return _bind(src.value< qint64>());
if (src.type()==QVariant::Int ) return _bind(src.value< int>());
if (src.type()==QVariant::Double ) return _bind(src.value< double>());
// QDataStream format is the only Qt data format that is read-write and easily extensible by users
// It is binary and includes src.typeName() for QMetaType::User types
// QByteArray will be encoded a QVariant to avoid ambiguities when decoding bytes
QByteArray binaryVariant; QDataStream s(&binaryVariant, QIODevice::WriteOnly);
s << src;
if (s.status()==QDataStream::Ok) {
return _bind(binaryVariant);
}
return _null();
}
virtual bool _bind( QUtf8String& r) { QUtf8String copy(r); return _bind(std::move(copy)); }
virtual bool _bind( QString& r) { QString copy(r); return _bind(std::move(copy)); }
......@@ -504,6 +562,7 @@ struct IWriter : public IBind
virtual bool _bind( float& r) { float copy(r); return _bind(std::move(copy)); }
virtual bool _bind( double& r) { double copy(r); return _bind(std::move(copy)); }
virtual bool _bind( QByteArray& r) { QByteArray copy(r); return _bind(std::move(copy)); }
virtual bool _bind( QVariant& r) { QVariant copy(r); return _bind(std::move(copy)); }
virtual bool _bind(const QUtf8String& r) { QUtf8String copy(r); return _bind(std::move(copy)); }
virtual bool _bind(const QString& r) { QString copy(r); return _bind(std::move(copy)); }
......@@ -519,6 +578,7 @@ struct IWriter : public IBind
virtual bool _bind(const float& r) { float copy(r); return _bind(std::move(copy)); }
virtual bool _bind(const double& r) { double copy(r); return _bind(std::move(copy)); }
virtual bool _bind(const QByteArray& r) { QByteArray copy(r); return _bind(std::move(copy)); }
virtual bool _bind(const QVariant& r) { QVariant copy(r); return _bind(std::move(copy)); }
};
//! Base IBind implementations with BindMode::Read
......@@ -556,6 +616,29 @@ struct IReader : public IBind
}
return true;
}
virtual bool _bind( QVariant& dst) {
_setChoice(true);
quint32 size=0; QUtf8String key; QVariant item;
if (_sequence(&size)) { QVariantList l; while (_item( )) { l.append( _bind(item) ? item : QVariant()); } dst = l; return _out(); }
if (_record (&size)) { QVariantMap l; while (_item(key)) { l.insert(key, _bind(item) ? item : QVariant()); } dst = l; return _out(); }
bool b; if (_bind(b)) { dst = QVariant(b); return true; }
quint64 u; if (_bind(u)) { dst = QVariant(u); return true; }
qint64 l; if (_bind(l)) { dst = QVariant(l); return true; }
double d; if (_bind(d)) { dst = QVariant(d); return true; }
QByteArray binaryVariant; if (_bind(binaryVariant)) {
QVariant v;
QDataStream s(binaryVariant); s >> v;
if (s.status()==QDataStream::Ok) {
dst = v;
return true;
}
}
QString t; if (_bind(t)) { dst = QVariant(t); return true; }
_setChoice(false);
if (!_null()) _reportError("Expected boolean|decimal|bytes|text|sequence|record|null");
/**/ dst = QVariant( ); return true;
}
virtual bool _bind(const QUtf8String& k) { QUtf8String r; if (_bind(r) && k==r) return true; _reportError(qBindExpectedConstant); return false; }
virtual bool _bind(const QString& k) { QString r; if (_bind(r) && k==r) return true; _reportError(qBindExpectedConstant); return false; }
......@@ -571,6 +654,7 @@ struct IReader : public IBind
virtual bool _bind(const float& k) { float r; if (_bind(r) && k==r) return true; _reportError(qBindExpectedConstant); return false; } // TODO silent warning
virtual bool _bind(const double& k) { double r; if (_bind(r) && k==r) return true; _reportError(qBindExpectedConstant); return false; } // TODO silent warning
virtual bool _bind(const QByteArray& k) { QByteArray r; if (_bind(r) && k==r) return true; _reportError(qBindExpectedConstant); return false; }
virtual bool _bind(const QVariant& k) { QVariant r; if (_bind(r) && k==r) return true; _reportError(qBindExpectedConstant); return false; }
virtual bool _bind( QUtf8String&& k) { QUtf8String r; if (_bind(r) && k==r) return true; _reportError(qBindExpectedConstant); return false; }
virtual bool _bind( QString&& k) { QString r; if (_bind(r) && k==r) return true; _reportError(qBindExpectedConstant); return false; }
......@@ -586,6 +670,7 @@ struct IReader : public IBind
virtual bool _bind( float&& k) { float r; if (_bind(r) && k==r) return true; _reportError(qBindExpectedConstant); return false; } // TODO silent warning
virtual bool _bind( double&& k) { double r; if (_bind(r) && k==r) return true; _reportError(qBindExpectedConstant); return false; } // TODO silent warning
virtual bool _bind( QByteArray&& k) { QByteArray r; if (_bind(r) && k==r) return true; _reportError(qBindExpectedConstant); return false; }
virtual bool _bind( QVariant&& k) { QVariant r; if (_bind(r) && k==r) return true; _reportError(qBindExpectedConstant); return false; }
virtual bool _bind( const char* k) { QUtf8String r; if (_bind(r) && k==r) return true; _reportError(qBindExpectedConstant); return false; }
// TODO QStringView, QLatin1String(View), etc.
......
......@@ -105,6 +105,7 @@ protected:
bool _bind( qint64&& i) { return hidden() ? true : I<=d ? w._bind(std::move(i)) :
i<= qint64(std::numeric_limits< int>::max()) ? m->setData(current(), static_cast< int>(i)) // with QSpinBox delegate
: m->setData(current(), i ); }
bool _bind( QVariant&& t) { return hidden() ? true : I<=d ? static_cast<IWriter*>(&w)->_bind(QVariant(t)) : m->setData(current(), t); }
// TODO QDate*, QTime
// TODO QPixmap if metadata suggests a QMimeData image ?
......
......@@ -166,72 +166,3 @@ private:
QStack<Level> levels;
bool isChoice = false;
};
// //////////////////////////////////////////////////////////////////////////
// QBind<QVariant> example support for the set of IBind's BindNative types + other convenient types
template<>
struct QBind<QVariant> {
static Cursor bind(Val<Cursor>&& v, QVariant&& src) {
if (v->mode()==Write) {
if (src.canConvert<QVariantList>()) {
QSequentialIterable ts = src.value<QSequentialIterable>();
quint32 size=quint32(ts.size());
auto s(v.sequence(&size));
for (auto t : ts) {
s = s.bind(t);
}
return s;
}
if (src.canConvert<QVariantMap >() ) {
QAssociativeIterable ts = src.value<QAssociativeIterable>();
quint32 size=quint32(ts.size());
auto s(v.record(&size));
QAssociativeIterable::const_iterator i = ts.begin();
const QAssociativeIterable::const_iterator end = ts.end();
for ( ; i != end; ++i) {
QVariant t = *i;
s = s.bind(i.key().toString().toUtf8().constData(),t);
}
return s;
}
if (src.type()==QVariant::Bool ) return v.bind(src.value< bool>());
if (src.type()==QVariant::ByteArray) return v.bind(src.value< QByteArray>());
if (src.type()==QVariant::String ) return v.bind(src.value< QString>());
if (src.type()==QVariant::Char ) return v.bind(src.toString());
if (src.type()==QVariant::ULongLong) return v.bind(src.value< quint64>());
if (src.type()==QVariant::UInt ) return v.bind(src.value<unsigned int>());
if (src.type()==QVariant::LongLong ) return v.bind(src.value< qint64>());
if (src.type()==QVariant::Int ) return v.bind(src.value< int>());
if (src.type()==QVariant::Double ) return v.bind(src.value< double>());
return v.null();
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.null(); }
}
static Cursor bind(Val<Cursor>&& v, QVariant& dst) {
if (v->mode()==Write) {
return bind(std::move(v),std::move(dst));
}
else {
Cursor r;
{
QScopedChoice<Val<Cursor>> choice(v);
QVariantList a; if ((r = v.bind(a))) { dst = a ; return r; } // NB We cannot try QStringList before QVariantList as it will always work with our logical model...
QVariantMap o; if ((r = v.bind(o))) { dst = o ; return r; }
bool b; if ((r = v.bind(b))) { dst = QVariant(b); return r; }
quint64 u; if ((r = v.bind(u))) { dst = QVariant(u); return r; }
qint64 l; if ((r = v.bind(l))) { dst = QVariant(l); return r; }
double d; if ((r = v.bind(d))) { dst = QVariant(d); return r; }
QByteArray x; if ((r = v.bind(x))) { dst = QVariant(x); return r; }
QString t; if ((r = v.bind(t))) { dst = QVariant(t); return r; }
}
if (!(r = v.null())) r.reportError("Expected boolean|decimal|bytes|text|sequence|record|null");
/**/ dst = QVariant( ); return r;
}
}
};
// TODO convert builtin types which canConvert<QString> ?
......@@ -701,7 +701,7 @@ int main(int argc, char *argv[])
QStandardItemModel treeModel; QModelWriter<>(& treeModel ).meta({{qmChildren,"children"}/*,{qmColumns ,"names,age"}*/}).bind(persons);
QStandardItemModel tableModel; QModelWriter<>(& tableModel ).meta({{qmColumns ,"names,age,children"}}).bind(persons);
QStandardItemModel matrixModel; QModelWriter<>(&matrixModel,false).meta({{qmSizes,"4,3"}}).bind(transform);
QStandardItemModel matrixModel; QModelWriter<>(&matrixModel,false).meta({{qmSizes ,"4,3"}}).bind(transform);
QDialog dlg;
auto layout = new QHBoxLayout(&dlg); dlg.setLayout(layout);
......
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