Commit 0266b674 authored by EXT Arnaud Clère's avatar EXT Arnaud Clère
Browse files

Added qmColor role to QModel*

parent 1d59218e
......@@ -124,6 +124,8 @@ static QName qmChildren = "children"; //!< name of a sequence of records with re
//! Name of current data
static QName qmName = "name";
static QName qmColor = "color" ; //!< comma-separated names
// //////////////////////////////////////////////////////////////////////////
// QBind<T,TResult>
......@@ -201,10 +203,11 @@ public:
template<typename T> T_ bind (T& t, T&& defaultT) { return outer->_bind(QBindDefault<T>{t,defaultT})? std::move(outer) : T_ (); }
// Custom bind support
/**/ T_ bindWith( QBindLambda customBind) { return customBind( std::move(unsafeThis())) ? std::move(outer) : T_(); }
template<typename T> T_ bind (T& t, QBindFunction<T> customBind) { return customBind(t, std::move(unsafeThis())) ? std::move(outer) : T_(); }
/**/ T_ with ( QBindLambda customBind) { return customBind( std::move(unsafeThis())) ? std::move(outer) : T_(); }
template<typename T> T_ with (T& t, QBindFunction<T> customBind) { return customBind(t, std::move(unsafeThis())) ? std::move(outer) : T_(); }
// Literal metadata support
/**/ Val<T_> meta(QName n, QUtf8String m) { return meta({{n,m}}); }
/**/ Val<T_> meta (QMetaData&& m) { return meta ( m); }
/**/ Seq<T_> sequence( quint32 s) { return sequence(&s); }
/**/ Rec<T_> record ( quint32 s) { return record (&s); }
......@@ -245,8 +248,8 @@ public:
template<typename T> Rec<T_> bind (T& t, T&& defaultT) { return item().bind(t,std::forward<T>(defaultT)); }
// Custom bind support
/**/ Seq<T_> bindWith( QBindSeqLambda customBind) { return bool(customBind( std::move(unsafeThis()))) ? std::move(*this) : Seq<T_>(); }
template<class Ts> Seq<T_> bind (Ts& ts, QBindSeqFunction<Ts> customBind) { return bool(customBind(ts, std::move(unsafeThis()))) ? std::move(*this) : Seq<T_>(); }
/**/ Seq<T_> with ( QBindSeqLambda customBind) { return bool(customBind( std::move(unsafeThis()))) ? std::move(*this) : Seq<T_>(); }
template<class Ts> Seq<T_> with (Ts& ts, QBindSeqFunction<Ts> customBind) { return bool(customBind(ts, std::move(unsafeThis()))) ? std::move(*this) : Seq<T_>(); }
template<class Ts> Seq<T_> forEach (Ts& ts, TResult(*)( typename Ts::value_type&, Val<TResult>&&)
, bool (*)(const typename Ts::value_type&) = [](const typename Ts::value_type&) { return true; });
......@@ -287,8 +290,8 @@ public:
template<typename T> Rec<T_> bind (QName n, T& t, T&& defaultT) { return item(n).bind(t,std::forward<T>(defaultT)); }
// Custom bind support
/**/ Rec<T_> bindWith(QName n, QBindLambda customBind) { return item(n).bindWith( customBind); }
template<typename T> Rec<T_> bind (QName n, T& t, QBindFunction<T> customBind) { return item(n).bind (t, customBind); }
/**/ Rec<T_> with (QName n, QBindLambda customBind) { return item(n).with ( customBind); }
template<typename T> Rec<T_> with (QName n, T& t, QBindFunction<T> customBind) { return item(n).bind (t, customBind); }
private:
template<typename T, class TResult, typename TEnabledIf> friend struct QBind;
Val<TResult> unsafeItem(QUtf8String& n) noexcept { return outer->_item(n) ? Val<TResult>(outer._unsafeCopy()) : Val<TResult>(); }
......
......@@ -44,6 +44,7 @@
#include <QtCore/qabstractitemmodel.h>
#include <QtCore/qvariant.h>
#include <QtCore/qbuffer.h>
#include <QtGui/qcolor.h>
#include "QBind_impl.h"
#include "QJson_impl.h"
......@@ -89,7 +90,12 @@ protected:
}
}
}
else if (I<=d) {
else if (C==d) {
if (meta.find(qmColor)!=meta.end()) {
m->setData(current(),QColor(meta[qmColor].constData()),Qt::ForegroundRole);
}
}
else {
w._meta(meta);
}
}
......
......@@ -297,24 +297,25 @@ By convention:
The latest customized binds require using ad-hoc std::function (mimicking Python list comprehensions)
```cpp
QStandardItemModel custom;
QModelWriter<>(&custom).sequence().bindFrom([&](Seq<Cursor>&& s)->Seq<Cursor> {
for (auto&& p : persons) { // Iterating on persons only works for Write
s = s // Required to keep working with active Cursor
QModelWriter<>(&custom).sequence().with([&](Seq<Cursor>&& s) {
for (auto&& person : persons) { // Read would require looping while !s.item()
s = s // To keep working with the active Cursor
.record()
.bind("first name", p.firstName)
.sequence("phones")
.bindFrom([&](Seq<Cursor>&& s)->Seq<Cursor> {
for (auto&& phone : p.phones) {
.item("first name")
.meta(qmColor, person.age >= 42 ? "green" : "blue")
.bind(person.firstName)
.item("office phone")
.with([&](Val<Cursor>&& v) {
for (auto&& phone : person.phones) {
if (phone._t == Phone::Office) {
s = s.bind(phone._n);
return v.bind(phone._n);
}
}
return std::move(s);
return v.null();
})
.out()
.out();
}
return std::move(s);
return std::move(s); // So caller stops calling IBind if user function was unable to keep track of the active Cursor
});
```
......
......@@ -959,7 +959,7 @@ Seq<Cursor> flatten(QList<Person>& ps, Seq<Cursor>&& s) {
.bind("first name", p.firstName )
.bind("height(ft)", p.height*3.28)
.out()
.bind(p.children, flatten);
.with(p.children, flatten);
}
return std::move(s);
};
......@@ -989,7 +989,7 @@ void doGuiExample() {
QModelWriter<>(& tableModel ).meta({{qmColumns , "names,age"} }).bind(persons);
// Various possible designs for flexible custom bind
#if 1
#if 0
// Design that works for Read/Write but requires several cumbersome functions
QModelWriter<>(&customModel).sequence().forEach(persons, [](Person& p, Val<Cursor>&& item)->Cursor {
return item
......@@ -1004,12 +1004,15 @@ void doGuiExample() {
});
#else
// More expressive design similar to Python list comprehensions that does not work by default for Read/Write
QModelWriter<>(&customModel).sequence().bindWith([&](Seq<Cursor>&& s) { // See https://stackoverflow.com/questions/18889028/a-positive-lambda-what-sorcery-is-this
QModelWriter<>(&customModel).sequence().with([&](Seq<Cursor>&& s) { // See https://stackoverflow.com/questions/18889028/a-positive-lambda-what-sorcery-is-this
for (auto&& person : persons) { // Read would require looping while !s.item()
s = s // To keep working with the active Cursor
.record()
.bind("first name", person.firstName)
.bindWith("office phone", [&](Val<Cursor>&& v) {
.item("first name")
.meta(qmColor, person.age >= 42 ? "green" : "blue")
.bind(person.firstName)
.item("office phone")
.with([&](Val<Cursor>&& v) {
for (auto&& phone : person.phones) {
if (phone._t == Phone::Office) {
return v.bind(phone._n);
......@@ -1023,7 +1026,7 @@ void doGuiExample() {
});
#endif
// The same design allows flattening trees into a sequence
QModelWriter<>(& flatModel).sequence().bind(persons, flatten);
QModelWriter<>(& flatModel).sequence().with(persons, flatten);
QDialog dlg;
auto layout = new QHBoxLayout(&dlg); dlg.setLayout(layout);
......
tests/QBind/qstandardmodel.PNG

15.4 KB | W: | H:

tests/QBind/qstandardmodel.PNG

16 KB | W: | H:

tests/QBind/qstandardmodel.PNG
tests/QBind/qstandardmodel.PNG
tests/QBind/qstandardmodel.PNG
tests/QBind/qstandardmodel.PNG
  • 2-up
  • Swipe
  • Onion skin
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