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.