1
00:00:11,417 --> 00:00:14,157
Hints to tooling the runtime didn't actually do

2
00:00:14,157 --> 00:00:17,957
anything with those type annotations since

3
00:00:17,957 --> 00:00:21,757
six seven they are actually enforced so if

4
00:00:21,757 --> 00:00:25,417
you now pass a string into this add function the

5
00:00:25,417 --> 00:00:32,977
string is the javascript course to it you'll be delighted but uh i had basically

6
00:00:32,977 --> 00:00:38,657
no other choice i'm making using the javascript type questions there so that's

7
00:00:38,657 --> 00:00:42,177
what it is and yeah Yeah, why do we use them?

8
00:00:42,337 --> 00:00:46,877
As I mentioned before, so that like, A,

9
00:00:47,057 --> 00:00:53,617
you yourself and anybody else who reads the code later can grasp what was the

10
00:00:53,617 --> 00:00:58,637
intention of the code and the tooling can make sense of it and compile it to C++.

11
00:01:04,197 --> 00:01:08,057
And of course you can also use var if you don't actually know the type,

12
00:01:08,197 --> 00:01:11,617
but you should use it sparingly.

13
00:01:15,737 --> 00:01:18,557
Related to that, we also have type assertions now.

14
00:01:19,217 --> 00:01:24,457
They've also been around since 5.15, and it was an interesting ride.

15
00:01:24,857 --> 00:01:33,837
In 5.15, they didn't do anything at runtime, like if you passed a type to this

16
00:01:33,837 --> 00:01:37,797
s here, for example, with the font, that was not a font, but a rect,

17
00:01:38,757 --> 00:01:43,857
it would just go on and try to get the family property from rect,

18
00:01:43,957 --> 00:01:45,177
which doesn't work in this case.

19
00:01:45,257 --> 00:01:49,397
But let's say you have rect and point, and you take out the x property,

20
00:01:49,537 --> 00:01:53,117
and it would just work, besides not being the right type.

21
00:01:56,497 --> 00:02:03,977
So since 6.2, they are actually checked, for object types at least.

22
00:02:04,917 --> 00:02:10,597
So, in the second example with the getX, if you pass something else than an

23
00:02:10,597 --> 00:02:11,817
item into this function,

24
00:02:12,717 --> 00:02:18,497
the as expression will evaluate to null and that will result in a JavaScript

25
00:02:18,497 --> 00:02:23,477
expression, no matter if the type that you actually have there has a property X or not.

26
00:02:24,317 --> 00:02:27,677
And, uh, since six, six, um,

27
00:02:27,917 --> 00:02:31,197
we also do things with them if

28
00:02:31,197 --> 00:02:36,477
the right-hand side is value type and as somebody has pointed out to me,

29
00:02:36,537 --> 00:02:41,557
uh, those were some horribly wrong things because as you know,

30
00:02:41,617 --> 00:02:43,097
we have JavaScript type coercion,

31
00:02:43,177 --> 00:02:45,557
we should use JavaScript type coercion there, right?

32
00:02:45,957 --> 00:02:50,917
So if we can construct a font from whatever you've passed there,

33
00:02:50,997 --> 00:02:52,317
we should construct a font, right?

34
00:02:53,944 --> 00:02:58,064
Well, no, but luckily, it never worked.

35
00:02:58,524 --> 00:03:02,644
Like most of the time, it didn't work because it accidentally fell back to the

36
00:03:02,644 --> 00:03:05,824
object type coercion produced null, which it also shouldn't do.

37
00:03:06,204 --> 00:03:10,144
But that's not so bad because null is close enough to undefined,

38
00:03:10,204 --> 00:03:11,644
which it should actually return there.

39
00:03:12,104 --> 00:03:16,764
And so since 6.8, we got that right, but we couldn't straight out fix it because

40
00:03:16,764 --> 00:03:18,064
of backwards compatibility.

41
00:03:18,064 --> 00:03:24,004
Therefore, if you're going to use type assertions for value types,

42
00:03:24,204 --> 00:03:28,084
use this nice pragma there and avoid any surprises.

43
00:03:34,284 --> 00:03:39,064
And then we have generalized group properties. Generalized group properties are quite mouthful.

44
00:03:40,184 --> 00:03:45,644
And as mentioned, you don't actually have to know what it is unless you want

45
00:03:45,644 --> 00:03:46,784
to implement some yourself.

46
00:03:49,004 --> 00:03:53,544
Most prominently, we use this to fix property changes.

47
00:03:53,884 --> 00:03:59,404
If you look at the first property changes we have there, there is a property,

48
00:03:59,604 --> 00:04:02,304
a binding on opacity in there.

49
00:04:03,004 --> 00:04:10,464
Now, the type property changes, as far as I know, does not have a property opacity, does it?

50
00:04:11,104 --> 00:04:17,484
So, the QMAC cache game would say, no, I cannot compile this, what is that?

51
00:04:18,244 --> 00:04:22,524
You don't have a property opacity there. And the way it works at runtime is,

52
00:04:22,584 --> 00:04:30,184
there's a custom parser that gets not the compiled bytecode of that property

53
00:04:30,184 --> 00:04:33,044
changes, but one source code, the AST.

54
00:04:33,224 --> 00:04:38,264
It runs through the AST and fixes this to not point to the property change itself,

55
00:04:38,464 --> 00:04:39,984
but to the target you've specified.

56
00:04:40,344 --> 00:04:44,564
But that's all all custom code hidden inside the property changes implementation.

57
00:04:46,544 --> 00:04:51,504
And so what we could have done in the compiler is like special case property

58
00:04:51,504 --> 00:04:57,664
changes, and then special case connections and binding and state changes and anchor changes.

59
00:04:58,164 --> 00:05:00,204
No, I wasn't going to go there.

60
00:05:01,244 --> 00:05:02,684
And so we came up with something else.

61
00:05:03,844 --> 00:05:07,784
And that is the generalist group properties, which we can use in all those places.

62
00:05:07,784 --> 00:05:13,864
And generally, it's good properties is a construct where we have on the left-hand

63
00:05:13,864 --> 00:05:18,464
side an ID and then a property on that.

64
00:05:18,604 --> 00:05:21,264
And you can install a binding on the result.

65
00:05:21,424 --> 00:05:25,184
And that is typed because now we know the left-hand side here is an ID root.

66
00:05:25,764 --> 00:05:30,964
OK, we can look up that ID and the Qubit cache knows that ahead of time already.

67
00:05:32,204 --> 00:05:37,004
And then we look at that and see opacity. Oh, yeah, there's an item. It has opacity.

68
00:05:37,784 --> 00:05:42,984
And we know what that is, it's double, and so we can install a binding on that, and that just works.

69
00:05:45,086 --> 00:05:50,326
So we have that now in binding and in property changes. And it works nice.

70
00:05:50,606 --> 00:05:55,446
And it's not only easier for tooling, but it's also nicer to read, in my opinion.

71
00:05:56,106 --> 00:05:57,846
And simplifies the syntax some.

72
00:05:59,786 --> 00:06:05,406
And yeah, we haven't done it anywhere else because the other cases weren't so widespread and so bad.

73
00:06:05,786 --> 00:06:09,666
But it should be generalized to the other cases too.

74
00:06:11,886 --> 00:06:16,326
On the other hand, there's a related concept in connections.

75
00:06:16,586 --> 00:06:20,706
In connections, we don't generally want to do that. Or sometimes we want to do that.

76
00:06:21,026 --> 00:06:25,506
But generally, we don't want to do that because if you have a connections element,

77
00:06:25,786 --> 00:06:30,386
the most common thing is you don't actually know the target in advance.

78
00:06:30,466 --> 00:06:32,006
You can reassign the target.

79
00:06:32,206 --> 00:06:34,306
So an ID wouldn't do that.

80
00:06:35,686 --> 00:06:39,346
And as you can see in the first example with connections here,

81
00:06:39,346 --> 00:06:40,586
that's basically the same thing.

82
00:06:40,726 --> 00:06:47,306
There's an onExchanged signal handler here, and yeah, connections does not have a signal.

83
00:06:47,826 --> 00:06:54,826
Exchanged. That does not exist. And what we did there is a.

84
00:06:56,086 --> 00:07:02,026
Mechanism that loosely couples a member in the connections element that you

85
00:07:02,026 --> 00:07:07,666
newly define to some functionality that's behind it.

86
00:07:07,806 --> 00:07:15,786
But the member we defined there, that function on yChanged is valid already in plain QML.

87
00:07:15,886 --> 00:07:17,706
You don't need a custom parser for that.

88
00:07:17,946 --> 00:07:22,766
And the connections element then goes through its functions and checks,

89
00:07:22,866 --> 00:07:27,786
oh, is there something that looks like a signal handler and that matches my target?

90
00:07:28,186 --> 00:07:29,786
And then it detaches that.

91
00:07:30,706 --> 00:07:34,906
That. And that is basically the other side.

92
00:07:35,046 --> 00:07:40,726
Either you know the element you referred to in advance, then you can use generalized

93
00:07:40,726 --> 00:07:44,186
group properties, or you don't, then you can use a technique like that.

94
00:07:44,806 --> 00:07:48,966
And that's basically so far only implemented in connections,

95
00:07:49,286 --> 00:07:54,146
but we have to do the same thing for binding and property changes, et cetera, too.

96
00:07:54,926 --> 00:07:58,526
But in connections, again, that was the worst first thing because everybody

97
00:07:58,526 --> 00:08:02,126
uses connections so i'm happy we we have got it in there.

98
00:08:06,818 --> 00:08:12,358
And then another thing you can do in QML these days is named value types.

99
00:08:12,898 --> 00:08:21,198
Now I do have a little bit of C++ code here because it's relatively unknown thing so far.

100
00:08:22,358 --> 00:08:25,558
So from C++ you can register types

101
00:08:25,558 --> 00:08:31,438
that are not QObjects these days and you can give them your own names so you

102
00:08:31,438 --> 00:08:37,818
see this wrapped in type here and with this QML value type macro you can tell

103
00:08:37,818 --> 00:08:42,778
the tooling okay this is a value type called lowercase wrapped int.

104
00:08:43,498 --> 00:08:48,478
Value types have to have lowercase names for various reasons don't give them

105
00:08:48,478 --> 00:08:54,698
uppercase names or it will slap you around and then and And then you can use

106
00:08:54,698 --> 00:09:03,418
that like font or rect or all the other value types we already have built into Qt QML and Qt Quick.

107
00:09:03,978 --> 00:09:08,958
So, for example, you can assign things to or you can read out its I member here.

108
00:09:11,278 --> 00:09:17,578
And then on top of that, since 6.5, you can also have value types you can construct.

109
00:09:19,118 --> 00:09:26,418
For that, we have an extra macro QML constructible value, and you have to make

110
00:09:26,418 --> 00:09:27,798
the constructor QInvocable.

111
00:09:28,418 --> 00:09:34,258
And then tooling and the engine will figure out, oh yeah, I can call this constructor.

112
00:09:34,518 --> 00:09:36,958
It has to be a constructor of one argument.

113
00:09:38,358 --> 00:09:44,978
And then basically, if you have the right kind of type on binding on it,

114
00:09:45,098 --> 00:09:47,878
it will automatically construct the value

115
00:09:47,878 --> 00:09:54,438
type yeah because I

116
00:09:54,438 --> 00:09:58,978
didn't want to make that automatic because people might have constructors invocable

117
00:09:58,978 --> 00:10:04,558
constructors on their random types around the place and that you want QL to

118
00:10:04,558 --> 00:10:10,258
either like me if that's actually wanted the automatic conversion to do the

119
00:10:10,258 --> 00:10:13,038
conversion or to warn about it if If you do this,

120
00:10:13,238 --> 00:10:17,538
like, uh, assign it into it, magic in QML, right?

121
00:10:18,318 --> 00:10:23,078
Because that's otherwise that's quite magic. So I wanted to make it explicit.

122
00:10:28,932 --> 00:10:35,672
And on top of that, you can also have structured value types these days.

123
00:10:35,912 --> 00:10:39,672
Structured value types work kind of like constructable value types,

124
00:10:39,932 --> 00:10:47,032
but you can also construct them from a JavaScript object where just all the

125
00:10:47,032 --> 00:10:53,632
properties are assigned one by one from the members of the JavaScript object.

126
00:10:53,852 --> 00:10:59,612
And it doesn't have like a JavaScript object literal.

127
00:10:59,912 --> 00:11:04,872
It can be anything that looks like an object in JavaScript. So it can be another value type instance.

128
00:11:05,092 --> 00:11:08,032
It can be an object type. It can even be an array.

129
00:11:08,572 --> 00:11:14,692
The only thing it needs to have is some kind of properties that can be extracted

130
00:11:14,692 --> 00:11:16,572
to populate the other type.

131
00:11:16,792 --> 00:11:20,372
So this is like, again, somewhat dangerous. and that's

132
00:11:20,372 --> 00:11:24,232
why I made it a separate separate macro

133
00:11:24,232 --> 00:11:39,872
too yes value types cannot have signals but my a each value type is a member

134
00:11:39,872 --> 00:11:43,712
of some object type via some path of other value types types,

135
00:11:43,792 --> 00:11:53,492
and so the QML runtime simulates notifiability via notifying on the.

136
00:11:56,272 --> 00:11:59,512
Outermost property that's a property of an object type. So yes,

137
00:11:59,652 --> 00:12:02,552
you can have onIChange there. It works.

138
00:12:03,172 --> 00:12:08,472
It's somewhat, it's a bit complicated and a bit expensive, but it's not so bad.

139
00:12:13,892 --> 00:12:21,172
You can change a lot to do that. To do what? The signal. Yeah.

140
00:12:22,752 --> 00:12:27,812
But if you have a signal, you need identity. So in order to connect the signal

141
00:12:27,812 --> 00:12:33,032
to something, you need an identity on the left side, and that needs to be stable.

142
00:12:33,332 --> 00:12:38,032
But if you have value type, and that's assigned recursively to some property,

143
00:12:38,272 --> 00:12:43,112
and you change whatever that is, it might get reallocated. Yes.

144
00:12:43,932 --> 00:12:45,172
So that's why it doesn't work.

145
00:12:50,372 --> 00:12:53,572
Now, container types. Container types

146
00:12:53,572 --> 00:12:58,072
are funny in QML. As a historical artifact, we have too many of them.

147
00:12:59,112 --> 00:13:00,712
We have JavaScript arrays.

148
00:13:01,892 --> 00:13:06,432
That's because we need to build a JavaScript. We have various other JavaScript

149
00:13:06,432 --> 00:13:09,592
things that look like arrays. I'm going to ignore those for now.

150
00:13:10,112 --> 00:13:14,552
But they generally have the same API as JavaScript arrays, so it's not so bad.

151
00:13:15,332 --> 00:13:19,812
And then we have our own QML list types.

152
00:13:20,372 --> 00:13:25,212
There's QKML list property that in Qt 5 worked quite different.

153
00:13:26,012 --> 00:13:30,612
And there is various lists,

154
00:13:30,852 --> 00:13:37,472
QLists and standard vectors that are manually exposed or were manually exposed

155
00:13:37,472 --> 00:13:42,792
to QML in special case in various interesting ways.

156
00:13:43,852 --> 00:13:47,412
And some of them had a similar API to JavaScript array.

157
00:13:47,412 --> 00:13:53,552
And some of them had some random crafts and queue object list was special and

158
00:13:53,552 --> 00:13:57,752
queue variant list was special and all there was like,

159
00:13:57,892 --> 00:14:03,032
yeah, I was getting lots of bugs because why can I use push on this container?

160
00:14:03,192 --> 00:14:08,352
But if I use push on that container, then this happens. And so I went and fixed it.

161
00:14:09,692 --> 00:14:15,732
So, JS array is the reference here.

162
00:14:15,852 --> 00:14:20,072
Like everything should, because we are basically locked into JavaScript,

163
00:14:20,452 --> 00:14:24,112
everything should have the same API as JavaScript array, right?

164
00:14:27,792 --> 00:14:31,132
And that's what I did in 6.5.

165
00:14:32,272 --> 00:14:36,472
Everything that looks like an array works like an array. Yay.

166
00:14:37,552 --> 00:14:43,272
And most of the special casing is gone. You automatically get the right types registered.

167
00:14:43,592 --> 00:14:48,332
If you register an object type, you get QQMList property of that object type for free.

168
00:14:48,812 --> 00:14:55,392
And if you register a value type, you can get QList of that value type for free.

169
00:14:55,392 --> 00:15:05,292
And since 6.0, you can also do the thing we used to do in Qt 5 with standard

170
00:15:05,292 --> 00:15:08,852
vector int and standard vector bool and whatnot. You can do that yourself.

171
00:15:09,232 --> 00:15:12,892
There's a macro code QML sequential container.

172
00:15:13,152 --> 00:15:21,212
And that will just expose the type to QML the way all those containers are exposed.

173
00:15:23,992 --> 00:15:27,392
And that latter thing can only expose anonymous containers.

174
00:15:27,552 --> 00:15:33,372
So you cannot define properties of that, but if some C++ type has a property

175
00:15:33,372 --> 00:15:38,372
of that or returns something like that from a method or accepts something like

176
00:15:38,372 --> 00:15:40,972
that as arguments to a method,

177
00:15:41,232 --> 00:15:47,712
you can pass it through and you can treat it like an array in QML.

178
00:15:49,940 --> 00:15:57,240
And then I thought, yeah, we have lots of interesting things as models for various views.

179
00:15:57,700 --> 00:16:04,280
Like we have a list model thing with like an interesting custom parser on list

180
00:16:04,280 --> 00:16:06,800
element that I don't quite know what to do with yet.

181
00:16:07,360 --> 00:16:12,100
And then we have abstract item model that can be passed through there and like

182
00:16:12,100 --> 00:16:15,460
plain integers and various things.

183
00:16:15,600 --> 00:16:19,520
And you'd expect that any kind of list like thing would work there.

184
00:16:19,940 --> 00:16:24,440
But in Qt 5, not everything worked there. Only special things worked.

185
00:16:25,240 --> 00:16:34,000
And so after fixing all the list inconsistencies, I went and fixed the model data too.

186
00:16:34,840 --> 00:16:39,320
So anything that looks like a JavaScript array, anything list-like,

187
00:16:40,080 --> 00:16:43,380
you can use as a model to all our views now.

188
00:16:44,120 --> 00:16:48,320
So for example, here we have a list of size,

189
00:16:48,320 --> 00:16:59,080
the size value type as model to repeater and then you can have a required property

190
00:16:59,080 --> 00:17:05,980
width and that just works and then yes Yes.

191
00:17:05,980 --> 00:17:14,380
If I do now lists as models, if I then change a single value in the list, will I have a list?

192
00:17:15,220 --> 00:17:21,580
Yes. Yes, in general, yes, because you're reassigning your list then with value type lists.

193
00:17:22,060 --> 00:17:29,440
With QKML list property, you don't have to reassign the whole list, but you are...

194
00:17:31,240 --> 00:17:36,060
Yeah, but that won't work. you still have to signal the change somehow and you

195
00:17:36,060 --> 00:17:38,240
can only signal the change for the whole list,

196
00:17:38,760 --> 00:17:42,440
and so too bad yes does

197
00:17:42,440 --> 00:17:48,880
delegator delegate chooser does it work on this list yeah delegate chooser is

198
00:17:48,880 --> 00:17:53,740
one one step removed from this machinery so it should work unless there's a

199
00:17:53,740 --> 00:18:01,360
bug somewhere i haven't i haven't checked but i tried last time and it seems to only work with,

200
00:18:03,040 --> 00:18:06,220
Oh, that's interesting. Can you write me a bug report for that, please?

201
00:18:08,380 --> 00:18:09,060
Thank you.

202
00:18:14,416 --> 00:18:21,636
Yeah, and then the other thing I recognized is you can now have required optional

203
00:18:21,636 --> 00:18:26,296
properties, as contradictory as that sounds. But you can see that here.

204
00:18:26,976 --> 00:18:31,276
We can say, okay, we have a required property rect model data.

205
00:18:31,436 --> 00:18:37,276
Model data is the thing that captures the whole model data passed to the delegate. get.

206
00:18:37,456 --> 00:18:52,156
And since rect is a structured value type, it gets populated property by property.

207
00:18:52,376 --> 00:18:56,236
And rect happens to have properties width and height.

208
00:18:56,416 --> 00:19:02,216
So what you get there is a bunch of rects that are always at the 0,

209
00:19:02,296 --> 00:19:05,736
0 point and have a certain width and height.

210
00:19:07,336 --> 00:19:14,976
As specified by the size. So that's a pretty neat thing, and it just came for free.

211
00:19:18,639 --> 00:19:26,899
Now, having done all of that, there's a lot of other stuff still left to do.

212
00:19:28,019 --> 00:19:36,899
One thing to do about the whole type safety machinery is we need some way to

213
00:19:36,899 --> 00:19:38,199
express function types.

214
00:19:38,399 --> 00:19:44,759
So like some callables, basically, because that's what people struggle with mostly right now.

215
00:19:44,759 --> 00:19:47,899
You have like several different types that

216
00:19:47,899 --> 00:19:51,939
all have some function in common and you

217
00:19:51,939 --> 00:19:54,919
have a qml interface that takes one or

218
00:19:54,919 --> 00:19:59,739
the qml property that takes one of those types and you want to call the common

219
00:19:59,739 --> 00:20:04,699
function on that duck typing basically and in order in order to resolve that

220
00:20:04,699 --> 00:20:07,599
we need some kind of like a function

221
00:20:07,599 --> 00:20:12,779
type you can put on the right hand side of an uh of a type of a type

222
00:20:12,899 --> 00:20:19,259
assertion, so that you can still type safely call any of those functions.

223
00:20:20,339 --> 00:20:23,779
That's pretty high on the list. And the same thing, some types,

224
00:20:23,919 --> 00:20:25,619
basically the same thing.

225
00:20:26,359 --> 00:20:31,479
You have like one of those types and my property might carry any of those,

226
00:20:31,579 --> 00:20:38,679
but only like those three, not more than them. And that's also to resolve duck typing.

227
00:20:39,119 --> 00:20:41,279
Very, very common thing in QML.

228
00:20:42,779 --> 00:20:47,359
And then we have like those value types

229
00:20:47,359 --> 00:20:54,819
and list types have a drawback as noticed just here a minute ago if you were

230
00:20:54,819 --> 00:21:00,039
assigned to them you like have to assign the whole thing and for lists unfortunately

231
00:21:00,039 --> 00:21:04,439
that means you have to copy the whole list and you don't want to do that all

232
00:21:04,499 --> 00:21:08,939
the time, so I'm thinking about like having a year extra,

233
00:21:09,039 --> 00:21:15,939
extra attribute to Q underscore property that gives an internal pointer to the

234
00:21:15,939 --> 00:21:17,519
thing so that we don't have to

235
00:21:17,519 --> 00:21:23,259
always change or always like copy the whole thing in order to update it.

236
00:21:25,058 --> 00:21:30,698
And that especially helps with recursive data structures where you have a list

237
00:21:30,698 --> 00:21:35,358
of value types that themselves have other value types as members, etc.

238
00:21:35,658 --> 00:21:41,238
You can probably imagine how terrible that is if you then update some member

239
00:21:41,238 --> 00:21:45,138
integer i in the innermost instance of that.

240
00:21:45,298 --> 00:21:48,478
So don't do that yet. Use it for simple things.

241
00:21:49,698 --> 00:21:54,478
And yeah, as mentioned before, another Another thing we need to do is finish

242
00:21:54,478 --> 00:21:59,218
generalized group properties and loose coupling to cover all the various elements

243
00:21:59,218 --> 00:22:01,058
we have there, and not only the worst ones.

244
00:22:04,238 --> 00:22:11,158
And once we get to a fixed binding that way, we can also put in support for

245
00:22:11,158 --> 00:22:12,918
bidirectional bindings.

246
00:22:12,978 --> 00:22:19,058
That seems to be a very, very commonly requested feature.

247
00:22:20,498 --> 00:22:28,718
And then, so far, value types can only be defined in C++, as you have seen there.

248
00:22:28,858 --> 00:22:33,978
It would, of course, be very nice if you could also define them in QML,

249
00:22:34,158 --> 00:22:36,198
like you can do with object types.

250
00:22:38,158 --> 00:22:42,618
And those are the things that I'm pretty sure about how to do.

251
00:22:44,038 --> 00:22:47,858
Then, what is next is like things people have complained about,

252
00:22:48,038 --> 00:22:49,718
especially like KDE people.

253
00:22:52,398 --> 00:22:55,878
And I'm not sure about how to fix that.

254
00:22:56,698 --> 00:23:01,678
One of those is context properties. Yeah, we all know context properties are

255
00:23:01,678 --> 00:23:07,218
kind of nice because you just mesh some object into the root context of the

256
00:23:07,218 --> 00:23:08,698
engine and it shows up everywhere.

257
00:23:09,398 --> 00:23:13,598
And it's so easy. Yeah, great. But QML and QSK doesn't see it,

258
00:23:13,618 --> 00:23:15,018
and QMLint doesn't see it,

259
00:23:15,078 --> 00:23:20,438
and QMLLS doesn't see it because you've hidden it somewhere in your main CPP

260
00:23:20,438 --> 00:23:25,618
inside an inner loop of 13 like depth, yeah.

261
00:23:28,038 --> 00:23:32,358
So that needs some fixing. I don't know how to do it yet, but it needs some fixing.

262
00:23:33,908 --> 00:23:43,108
And another thing I don't quite know yet is writing model data from delegates.

263
00:23:43,448 --> 00:23:48,048
So if you look at the example with the unification of model data here,

264
00:23:48,568 --> 00:23:53,648
yeah, you can have a type model data in your delegate, but that's a property of a delegate.

265
00:23:53,888 --> 00:23:57,768
And if you write to it, well, you write to it, you have a different value in

266
00:23:57,768 --> 00:24:02,408
your delegate, but it doesn't propagate back to the model. And so far,

267
00:24:02,428 --> 00:24:08,048
you can write back to the model by looking up the model and writing into it.

268
00:24:08,928 --> 00:24:14,668
But it would, of course, be nice if you could do that directly from the delegate.

269
00:24:14,828 --> 00:24:19,348
If the delegate could just write to some representation of its piece of data,

270
00:24:19,528 --> 00:24:21,608
and that would propagate back to the model.

271
00:24:21,988 --> 00:24:25,908
That is so far not doable in a type-safe way.

272
00:24:27,728 --> 00:24:39,528
And finally, you may have noticed in my example with, where did I put that?

273
00:24:41,308 --> 00:24:49,928
Here, that I had to put font or rather Qt Quick into this type namespace QQ.

274
00:24:51,128 --> 00:24:53,748
And does anybody know why I did that?

275
00:25:04,385 --> 00:25:10,625
Yes, to make the type font addressable here, because value types are by default

276
00:25:10,625 --> 00:25:14,745
not addressable, and for a reason, because if they were addressable,

277
00:25:14,905 --> 00:25:16,045
they would shadow properties,

278
00:25:16,385 --> 00:25:21,005
and value types as well as properties are lowercase, so that would be disastrous.

279
00:25:21,005 --> 00:25:27,765
Disastrous and therefore I have to like put it at a type namespace so that I

280
00:25:27,765 --> 00:25:34,245
don't have to look it up unqualified and qualify qualified thing of the type

281
00:25:34,245 --> 00:25:36,685
namespace it works but that is.

282
00:25:38,565 --> 00:25:48,745
Inconvenient who oh yeah yeah um and so one thing to do about that is just redesign

283
00:25:49,045 --> 00:25:53,505
the lookup hierarchy so that the types are not at the top of it,

284
00:25:53,565 --> 00:25:56,065
but somewhere further down below the properties.

285
00:25:56,405 --> 00:26:05,445
That is not as simple as it sounds, because between the types and the things

286
00:26:05,445 --> 00:26:08,085
further down are all the contexts and all the scopes,

287
00:26:08,125 --> 00:26:12,085
all the way out to the root context of the engine,

288
00:26:12,225 --> 00:26:15,305
and we have to thread it in somewhere in there.

289
00:26:16,385 --> 00:26:20,285
Yeah, I don't have a solution for that yet, but it needs a solution.

290
00:26:21,525 --> 00:26:27,305
Yeah. And that's basically what I wanted to say here.

291
00:26:27,505 --> 00:26:29,905
And now I hear we have 10 minutes for questions.

292
00:26:42,622 --> 00:26:42,882
Yes?

293
00:26:46,142 --> 00:26:49,282
One of the ones that we get. Okay.

294
00:26:54,782 --> 00:27:00,482
It's on. One thing I've... One thing I've... Testing.

295
00:27:00,622 --> 00:27:04,762
One thing I've noticed clients do is,

296
00:27:07,422 --> 00:27:15,342
they often want to use models within the QML space. And sometimes those models are rather complex.

297
00:27:15,722 --> 00:27:23,562
They want them to contain nested data. And I haven't found a good way to do

298
00:27:23,562 --> 00:27:28,002
that and still have it be somewhat optimized by the QML compiler.

299
00:27:28,942 --> 00:27:30,562
Any inputs on that?

300
00:27:31,882 --> 00:27:36,682
One way you can do that is write your own abstract item model, of course.

301
00:27:36,822 --> 00:27:42,842
You can put in anything there and you can return a queue object as some piece of data somewhere and,

302
00:27:43,442 --> 00:27:46,842
have another model in there that gives you

303
00:27:46,842 --> 00:27:51,082
the full flexibility all right and another

304
00:27:51,082 --> 00:27:54,842
thing you can do is like use the new support for

305
00:27:54,842 --> 00:28:01,662
lists with some care to not like copy the list too often and what i've shown

306
00:28:01,662 --> 00:28:06,422
there with list of value types also works with list of object types So it might

307
00:28:06,422 --> 00:28:11,602
help or with lists of JavaScript objects, but don't do that.

308
00:28:12,762 --> 00:28:14,822
All right. Sounds good. Thank you.

309
00:28:17,222 --> 00:28:17,922
Yes.

310
00:28:20,942 --> 00:28:26,802
Okay, two questions. The first one is about the type annotations.

311
00:28:26,942 --> 00:28:34,442
I know type annotations are awesome, but if you need marks in testing,

312
00:28:35,142 --> 00:28:45,082
that's going to be a problem because, for example, you need an object of type,

313
00:28:45,202 --> 00:28:50,542
of a specific type that maybe does network I.O.

314
00:28:50,702 --> 00:28:55,442
But in testing, you don't want to actually invoke the network I.O.,

315
00:28:55,442 --> 00:28:59,702
so you use a mock type instead.

316
00:29:00,442 --> 00:29:04,722
Then if you annotate the type to be the concrete type,

317
00:29:04,722 --> 00:29:07,822
you won't be able to use

318
00:29:07,822 --> 00:29:11,282
the mock type in testing right there is

319
00:29:11,282 --> 00:29:14,782
a fairly blunt way to work

320
00:29:14,782 --> 00:29:18,242
around that and that would be have a different

321
00:29:18,242 --> 00:29:23,102
qml module that exposes this like network type for your testing that you have

322
00:29:23,102 --> 00:29:29,722
in real in production so basically write the second qml module that has a a

323
00:29:29,722 --> 00:29:35,922
different network interaction type that's just mock and then test with that in the import,

324
00:29:37,158 --> 00:29:40,438
And when you ship for production, you replace it with the actual module.

325
00:29:41,958 --> 00:29:50,258
Okay. And another thing is about the lifetime of QObjects.

326
00:29:50,818 --> 00:29:56,838
As a JavaScript programmer, I feel it's really confusing and sometimes surprising

327
00:29:56,838 --> 00:30:06,778
when some things that got passed into the function can just become new at any time.

328
00:30:07,158 --> 00:30:19,298
Like, even a URL list from a drop event, it can go become new at the next tick of the event loop.

329
00:30:20,298 --> 00:30:24,658
Is there any plan to, say, work around this?

330
00:30:25,778 --> 00:30:27,538
What do you mean, become new?

331
00:30:28,878 --> 00:30:32,738
Like, so it's a URL list from a drop event.

332
00:30:32,738 --> 00:30:45,918
And say we want to extract the first URL and the second URL whenever the user clicks a button.

333
00:30:46,098 --> 00:30:54,418
And when the user clicks the first button, the URL list is there.

334
00:30:55,818 --> 00:30:58,158
And then it disappeared.

335
00:31:00,818 --> 00:31:04,038
Because it was an argument to some event

336
00:31:04,038 --> 00:31:07,058
handler and uh no how does how

337
00:31:07,058 --> 00:31:11,078
does it disappear this is like the url

338
00:31:11,078 --> 00:31:15,658
list comes from a drop event yeah yeah

339
00:31:15,658 --> 00:31:18,778
and that goes past yeah that

340
00:31:18,778 --> 00:31:25,498
is an argument to some method or some and like i passed it like i passed the

341
00:31:25,498 --> 00:31:37,618
url list into another function and I say display the filename when the user has clicked a button.

342
00:31:37,978 --> 00:31:46,218
And when the, I guess maybe the event got destroyed.

343
00:31:46,718 --> 00:31:51,098
Well, generally in JavaScript, whenever you hold onto something somewhere,

344
00:31:51,418 --> 00:31:55,838
it should not be garbage collected because that's the whole point of the garbage

345
00:31:55,838 --> 00:32:01,338
collector, that it marks things that are still in use, it does not collect them.

346
00:32:01,458 --> 00:32:05,478
So if you found an instance where something got collected despite you still

347
00:32:05,478 --> 00:32:09,998
holding a reference to it somewhere, then that's a bug. You should write me another bug report.

348
00:32:10,418 --> 00:32:18,238
Wait, this is pretty common across my QML experience because if it's like a

349
00:32:18,238 --> 00:32:22,298
QObject, it got destroyed when their parent is destroyed.

350
00:32:24,558 --> 00:32:27,518
Ah, and it was a property of a QObject you have there.

351
00:32:28,518 --> 00:32:32,698
Well, oh. Yeah, it is a property. We have to look at that in more detail.

352
00:32:32,798 --> 00:32:35,458
Maybe you can show me the code and then I can see what it does.

353
00:32:49,618 --> 00:32:53,978
So I have two questions. One is why is it not going via the new operator?

354
00:32:54,398 --> 00:32:57,978
Like using us to create things feels a bit weird.

355
00:32:58,258 --> 00:33:03,338
And the other one is are there any plans to like integrate those value types

356
00:33:03,338 --> 00:33:05,378
with like type conversions?

357
00:33:05,518 --> 00:33:10,478
So like I can have a type and then if I pass it into a function which expects

358
00:33:10,478 --> 00:33:12,158
a string, I get the string.

359
00:33:12,478 --> 00:33:15,398
Or if I use it as a number and I can do calculations.

360
00:33:15,798 --> 00:33:19,178
Like think of a coffee recipe or

361
00:33:19,178 --> 00:33:22,498
a value where you have like five liters and

362
00:33:22,498 --> 00:33:25,718
on C++ you make like structs and std even

363
00:33:25,718 --> 00:33:29,178
has like std kilo and whatnot but in

364
00:33:29,178 --> 00:33:32,098
representing that in QML is very hard because QML has

365
00:33:32,098 --> 00:33:37,298
no idea what this struct is it can do to string but you can't really do any

366
00:33:37,298 --> 00:33:43,438
maths and numbering and stuff with it easily so first question why do we why

367
00:33:43,438 --> 00:33:49,238
do we not use new for creating value types well Well, we do,

368
00:33:49,378 --> 00:33:54,718
but I'm not telling you right now because it might be a bad idea to remove it again.

369
00:33:56,098 --> 00:34:03,638
And second question, besides toString, there's also value of in JavaScript.

370
00:34:03,878 --> 00:34:10,838
We don't support that yet as invocable function, but that would be the way to convert to numbers.

371
00:34:11,618 --> 00:34:15,778
And I kind of have it on my radar to do that sometime, but yeah,

372
00:34:15,778 --> 00:34:18,278
I have a lot of stuff to do. Thank you.

373
00:34:23,278 --> 00:34:25,758
Okay, I guess time's up.