Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
MODMED
modmedLog
Commits
d61e9ac9
Commit
d61e9ac9
authored
Jul 08, 2019
by
EXT Arnaud Clère
Browse files
WIP
parent
84232b5b
Changes
3
Hide whitespace changes
Inline
Side-by-side
tests/QBind/QBind_impl.h
View file @
d61e9ac9
...
...
@@ -54,7 +54,7 @@ protected: \
Class& operator=(Class&& o) noexcept { if (this!=&o) { Statements } return *this; }
#include <QtCore/qbytearray.h>
//!
<
Explicitely utf8 encoded string of char
//! Explicitely utf8 encoded string of char
class
QUtf8String
:
public
QByteArray
{
public:
...
...
@@ -199,9 +199,12 @@ public:
/**/
Seq
<
T_
>
sequence
(
quint32
s
)
{
return
sequence
(
&
s
);
}
/**/
Rec
<
T_
>
record
(
quint32
s
)
{
return
record
(
&
s
);
}
// Sequence comprehension support
T_
bindSequence
(
QBindSeqFunction
<
TResult
>
customBind
)
{
return
sequence
().
bindFrom
(
customBind
).
out
();
}
// Shortcuts
template
<
typename
T
>
Seq
<
T_
>
operator
<<
(
T
&&
t
)
{
return
sequence
().
bind
(
std
::
forward
<
T
>
(
t
));
}
// stream compatible
/**/
Rec
<
T_
>
record
(
QName
n
)
{
return
meta
({{
qmName
,
n
}}).
record
();
}
template
<
typename
T
>
Seq
<
T_
>
operator
<<
(
T
&&
t
)
{
return
sequence
().
bind
(
std
::
forward
<
T
>
(
t
));
}
// stream compatible
/**/
Rec
<
T_
>
record
(
QName
n
)
{
return
meta
({{
qmName
,
n
}}).
record
();
}
private:
T_
outer
=
T_
();
//!< moved context of current traversal up to TResult that will point to the value itself (be it a QIODevice or QCborValue)
};
...
...
@@ -225,8 +228,6 @@ public:
Val
<
Seq
<
T_
>>
item
()
{
return
outer
->
_item
()
?
Val
<
Seq
<
T_
>>
(
std
::
move
(
*
this
))
:
Val
<
Seq
<
T_
>>
();
}
// Shortcuts
template
<
class
Ts
,
typename
TItem
=
typename
Ts
::
value_type
>
/**/
Seq
<
T_
>
from
(
Ts
&
,
typename
T_
::
TResult
(
*
)(
TItem
&
,
Val
<
typename
T_
::
TResult
>&&
),
bool
(
*
)(
const
TItem
&
)
=
[](
const
TItem
&
){
return
true
;
});
/**/
Seq
<
Seq
<
T_
>>
sequence
(
quint32
*
s
=
nullptr
)
{
return
item
().
sequence
(
s
);
}
/**/
Rec
<
Seq
<
T_
>>
record
(
quint32
*
s
=
nullptr
)
{
return
item
().
record
(
s
);
}
/**/
Seq
<
T_
>
null
(
)
{
return
item
().
null
(
);
}
...
...
@@ -235,7 +236,10 @@ public:
template
<
typename
T
>
Rec
<
T_
>
bind
(
T
&
t
,
T
&&
defaultT
)
{
return
item
().
bind
(
t
,
std
::
forward
<
T
>
(
defaultT
));
}
// Sequence comprehension support
Seq
<
T_
>
bindFrom
(
QBindSeqFunction
<
TResult
>
customBind
)
{
customBind
(
std
::
move
(
unsafeThis
()));
return
std
::
move
(
*
this
);
}
template
<
class
Ts
>
Seq
<
T_
>
from
(
Ts
&
,
TResult
(
*
)(
typename
Ts
::
value_type
&
,
Val
<
TResult
>&&
),
bool
(
*
)(
const
typename
Ts
::
value_type
&
)
=
[](
const
typename
Ts
::
value_type
&
)
{
return
true
;
});
Seq
<
T_
>
bindFrom
(
QBindSeqFunction
<
TResult
>
customBind
)
{
return
bool
(
customBind
(
std
::
move
(
unsafeThis
())))
?
std
::
move
(
*
this
)
:
Seq
<
T_
>
();
}
/**/
T_
bindSequence
(
QBindSeqFunction
<
TResult
>
customBind
)
{
return
item
().
bindSequence
(
customBind
);
}
// Stream compatible shortcut
template
<
typename
T
>
Seq
<
T_
>
operator
<<
(
T
&&
t
)
{
return
item
().
bind
(
std
::
forward
<
T
>
(
t
));
}
...
...
@@ -266,6 +270,9 @@ public:
Val
<
Rec
<
T_
>>
item
(
QUtf8String
&
n
)
{
return
outer
->
_item
(
n
)
?
Val
<
Rec
<
T_
>>
(
std
::
move
(
*
this
))
:
Val
<
Rec
<
T_
>>
();
}
Val
<
Rec
<
T_
>>
item
(
QName
n
)
{
return
outer
->
_item
(
n
)
?
Val
<
Rec
<
T_
>>
(
std
::
move
(
*
this
))
:
Val
<
Rec
<
T_
>>
();
}
// Sequence comprehension support
T_
bindSequence
(
QName
n
,
QBindSeqFunction
<
TResult
>
customBind
)
{
return
item
(
n
).
bindSequence
(
customBind
);
}
// Shortcuts
/**/
Seq
<
Rec
<
T_
>>
sequence
(
QName
n
,
quint32
*
s
=
nullptr
)
{
return
item
(
n
).
sequence
(
s
);
}
/**/
Rec
<
Rec
<
T_
>>
record
(
QName
n
,
quint32
*
s
=
nullptr
)
{
return
item
(
n
).
record
(
s
);
}
...
...
@@ -766,10 +773,10 @@ public:
// QBind partial specializations (generic on TResult, usually not on v->mode() for dynamically-sized or builtin types)
template
<
class
T_
>
template
<
class
Ts
,
typename
TItem
>
// = Ts::value_type
template
<
class
Ts
>
Seq
<
T_
>
Seq
<
T_
>::
from
(
Ts
&
ts
,
typename
T_
::
TResult
(
*
itemBind
)(
TItem
&
,
Val
<
typename
T
_
::
TResult
>&&
),
bool
(
*
itemPredicate
)(
const
TItem
&
))
{
TResult
(
*
itemBind
)(
typename
T
s
::
value_type
&
,
Val
<
TResult
>&&
),
bool
(
*
itemPredicate
)(
const
typename
Ts
::
value_type
&
))
{
if
((
*
this
)
->
mode
()
==
Write
)
{
for
(
auto
&&
t
:
ts
)
{
if
(
itemPredicate
(
t
))
{
...
...
@@ -782,7 +789,7 @@ Seq<T_> Seq<T_>::from(Ts& ts,
auto
&&
i
=
ts
.
begin
();
Val
<
typename
T_
::
TResult
>
item
;
while
((
item
=
unsafeItem
()))
{
TItem
newItem
;
typename
Ts
::
value_type
newItem
;
if
(
itemBind
(
newItem
,
std
::
move
(
item
))
&&
itemPredicate
(
newItem
))
{
if
(
i
!=
ts
.
end
())
{
*
i
=
newItem
;
...
...
tests/QBind/QModel_impl.h
View file @
d61e9ac9
...
...
@@ -64,8 +64,9 @@ class QModelWriter : public IWriter
public:
QModelWriter
(
QAbstractItemModel
*
m
,
bool
rowFirst
=
true
)
:
m
(
m
),
rowFirst
(
rowFirst
),
w
(
&
io
)
{
Q_ASSERT
(
m
);
}
Seq
<
Cursor
>
sequence
(
)
{
return
Cursor
(
this
).
value
().
sequence
(
);
}
Val
<
Cursor
>
meta
(
QMetaData
&&
m
)
{
return
Cursor
(
this
).
value
().
meta
(
m
);
}
/**/
Cursor
bindSequence
(
QBindSeqFunction
<
Cursor
>
customBind
)
{
return
Cursor
(
this
).
value
().
bindSequence
(
customBind
);
}
Seq
<
Cursor
>
sequence
(
)
{
return
Cursor
(
this
).
value
().
sequence
();
}
Val
<
Cursor
>
meta
(
QMetaData
&&
m
)
{
return
Cursor
(
this
).
value
().
meta
(
m
);
}
protected:
void
_meta
(
QMetaData
&
meta
)
{
if
(
T
==
d
)
{
...
...
tests/QBind/main.cpp
View file @
d61e9ac9
...
...
@@ -959,7 +959,7 @@ Seq<Cursor>&& flatten(const QList<Person>& ps, Seq<Cursor>&& s) {
.
bind
(
"first name"
,
p
.
firstName
)
.
bind
(
"height(ft)"
,
p
.
height
*
3.28
)
.
out
()
.
bindFrom
([
&
](
Seq
<
Cursor
>&&
s
){
.
bindFrom
([
&
](
Seq
<
Cursor
>&&
s
)
->
Seq
<
Cursor
>&&
{
return
std
::
move
(
flatten
(
p
.
children
,
std
::
move
(
s
)));
});
}
...
...
@@ -991,46 +991,42 @@ void doGuiExample() {
QModelWriter
<>
(
&
tableModel
).
meta
({{
qmColumns
,
"names,age"
}
}).
bind
(
persons
);
// Various possible designs for flexible custom bind
#if
0
#if
1
// Safest design that works for Read/Write but requires several cumbersome functions
QModelWriter<>(&customModel).sequence().from
<QList<Person>,Person>
(persons, [](Person& p, Val<Cursor>&& item){ // ADL cannot deduce Person
QModelWriter
<>
(
&
customModel
).
sequence
().
from
(
persons
,
[](
Person
&
p
,
Val
<
Cursor
>&&
item
)
->
Cursor
{
// ADL cannot deduce Person
return
item
.
record
()
.
bind
(
"first name"
,
p
.
firstName
)
.sequence("phones").from
<QVector<Phone>,Phone>
(p.phones,
.
sequence
(
"phones"
).
from
(
p
.
phones
,
[](
Phone
&
phone
,
Val
<
Cursor
>&&
item
){
return
item
.
bind
(
phone
.
_n
);
},
[](
const
Phone
&
phone
){
return
phone
.
_t
==
Phone
::
Office
;
})
.out()
.out();
});
// automagically closed while cast to returned Cursor type
});
#else
// More powerful design similar to Py
h
ton list comprehensions that does not work by default for Read/Write
QModelWriter
<>
(
&
customModel
).
s
equence
(
).
bindFrom
(
[
&
](
Seq
<
Cursor
>&&
s
){
for
(
auto
&&
p
:
persons
)
{
//
Iterating on persons only works for Write
s
=
s
//
Required t
o keep working with active Cursor
// More powerful design similar to Pyt
h
on list comprehensions that does not work by default for Read/Write
QModelWriter
<>
(
&
customModel
).
bindS
equence
([
&
](
Seq
<
Cursor
>&&
s
)
->
Seq
<
Cursor
>&&
{
for
(
auto
&&
p
:
persons
)
{
//
Read would require looping while !s.item()
s
=
s
//
T
o keep working with
the
active Cursor
.
record
()
.
bind
(
"first name"
,
p
.
firstName
)
.
sequence
(
"phones"
)
.
bindFrom
([
&
]
(
Seq
<
Cursor
>&&
s
)
{
.
bind
(
"first name"
,
p
.
firstName
)
.
bindSequence
(
"phones"
,
[
&
](
Seq
<
Cursor
>&&
s
)
->
Seq
<
Cursor
>&&
{
for
(
auto
&&
phone
:
p
.
phones
)
{
if
(
phone
.
_t
==
Phone
::
Office
)
{
s
=
s
.
bind
(
phone
.
_n
);
}
}
return
std
::
move
(
s
);
})
.
out
()
.
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
});
#endif
// The same design allows flattening trees into a sequence
QModelWriter
<>
(
&
flatModel
).
s
equence
(
).
bindFrom
(
[
&
](
Seq
<
Cursor
>&&
s
){
QModelWriter
<>
(
&
flatModel
).
bindS
equence
([
&
](
Seq
<
Cursor
>&&
s
)
->
Seq
<
Cursor
>&&
{
return
std
::
move
(
flatten
(
persons
,
std
::
move
(
s
)));
});
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment