 Hello everyone, thanks for joining this session about native desktop styling with the KitQuick controls 2. In this presentation, we'll talk about our plans for the future here at the Qt Company UI team for creating desktop applications with controls 2. I'll also show what we have done so far for the upcoming Qt 6 release and I'll even throw in a little demo in the end. The short summary is that we plan to ramp up support providing desktop applications with controls 2 using both QML and C++. Okay, let's take a brief look at the current situation. Controls 1 was our first goal at providing a UI framework using QML. All the controls were more or less written 100% in QML without much C++ and at that time QML was pretty new for everyone also for us, which meant that we didn't really know what to expect with regards to performance. So the styling API ended up being quite inefficient by design I would say. It created a lot of Q objects and had many fat delegates that used JavaScript introspection and bindings to style the controls. On top of this, we had a linking dependency to widgets to offer native styling and widget based dialogues from QML and without the QML compiling support we had today, it was all ended up as a rather slow and messy approach and on top of it all, it didn't scale well when used on embedded hardware. But at one point we had to rethink the whole solution. In controls 2 we basically shifted most of the implementation from QML to C++ and we only left the delegates to be written in QML. Everything else like API, control logic, event handling and so forth is done in C++. This reduces memory footprint, gives an easier code flow and will simply execute faster. We also use file selectors to help resolve the style, which means that we kept up another layer of indirection compared to controls 1. And Qtsex will further improve on the style selection logic so that more can be done during compile time instead of runtime. But what has really been missing in controls 2 so far is support for native styling. Control 2 was really written to solve the situation on embedded hardware and since we have widgets for desktop we have sort of accepted the fact that controls 2 has been a bit behind in that area. When in the real world this boils down to available human resources and priorities and not like a good will. But now that control 1 has been deprecated since Qt 5.12 and will even be removed from the base installation with Qt 6, this is no longer really acceptable. So what we have planned for future is to do a major lift for using controls 2 on the desktop. First of all we need to offer native styles in both macOS and Windows. On Linux the fusion style has been available for a long time already and we know that users of Qt like to use C++. So in the near future we also plan to open up and make the API score Qt Quick and Controls to public. We'll make use of the new property system in Qt 6 for creating bindings in C++ as a part of this effort. But how the API will end up look like is a bit early to say but it might mean being able to write controls application using C++ only or at least it will give you a proper API to interface with the controls from C++. In parallel to this we need to provide more desktop-centric controls, not only the ones that we have in widgets today, like doc widgets or MDI areas and such but also native design patterns like a combined sign bar and tool bar on macOS or the ribbon on Windows for example. And we need native dialogues and menus, we should do this by using the platform team plugin like widgets do today which means that if a desktop already has a Qt platform team plugin written for widgets it should continue to work also for controls. So our first big goal is basically to let controls become just as good alternative as widgets for doing desktop development and hopefully even better the time. But compared to widgets there are a lot of things missing in controls. So I mean we have no illusions that this will be done in the day. With the current staffing this will take some years. But to kick things off for Qt 6 we have started by porting the existing Q style to your controls too. I will talk a bit more about that in the next slides. We have also changed how the application style is resolved. Up to now an application would always need to specify which style to use otherwise you would get to default style. There are various ways of setting the style from using command line options to using the C++ API. But from now on if no style is specified we'll ask the platform team which style to use in exactly the same fashion that we do with widgets. So if we're on Linux the default platform theme will return fusion and on Windows it will be the window style. And because the default style will no longer be chosen by default with this change the default style has also been renamed to basic style in Qt 6. Work has also been done for Qt 6 to let us resolve more of the styling dependencies during compile time. For every style you now have the option to specify the fallback style when the style is built. macOS style for example has the fusion style set as backup as fallback sorry and the fusion style has the basic style as fallback. This way every style has a dependency chain that is known already after compile time which basically means less loopable style as it's during runtime. To get native styling to controls you use Qstyle for drawing like several other projects have basically done before us even our own project controls one. But where we differ now is that instead of sharing Qstyle with widgets we make an exclusive copy just for controls. And this might sound odd as some would say that using just one implementation of Qstyle with ease then maintains burden between widgets and controls. But the reason we do this is to fold first of all we don't want to break widgets and they cannot factor Qstyle out of widgets without breaking the API not only as Qstyle references the widgets in the public API but it also uses enums and constants directly from the widgets themselves. So if you factored Qstyle out to for example Qt GUI we would break all the existing third-party styles out there and also risk regressions for our own internal styles and this would not be very welcome for users that value Qt stability over time. And the other reason for making copies is that we want the freedom to change the implementation wherever we see fits. I mean there are many ways where we can optimize the Qstyle copy going forward to better fit the Qt Wixim graph and the controls to styling API. And we want to be able to do so without being constrained or worried about keeping compatibility with widgets. I would also like to stress that we don't necessarily want the native styles to look exactly like widgets. In many cases we would for example use a hybrid approach where we use QML to add more animations that fading impacts on top of Qstyle. I mean what we really want is for the native style to look as native as possible and not necessarily look like widgets. So let's take a little look behind the scenes at the implementation. As said we have copied Qstyle into the control stripper story repository as you can see here on the right side. This includes in this first version most of the same hierarchy of classes and tools that we have for widgets. But to avoid a name clash we have wrapped it all inside a name space called Qt Quick Controls 2 or QQ C2. On the left side of the slide we have QML control. In this case a comma box. All controls have a delegate property that takes care of rendering it. And when a native style is in use the delegate will be an instance of a Qt Quick style item. A style item is a simpler subclass of a Qt Quick item that can draw any primitive from Qstyle on the texture in the scene where you can be a comma box button background slider handle or in this case a comma box. So let's take a little sort of look at the style item comma box in the middle here to see how any machine is actually produced. First it will get a call to calculate geometry from Qt Quick style item. Style item comma box will then use Qstyle to calculate values such as the content margins padding and the implicit size of the control. This in return will be used by Qt Quick style item up here to create a Q image or Q painter and then call paint event. Paint event will draw the control using Qstyle equal to have a sum in widgets and when it's time for Qt Quick to render the comma box the image will be converted to texture and placed in the scene graph. The style item will also get a call to calculate geometry at startup. Here we can set up all the necessary connections to the Qt comma box basically and this will be used to detect whenever something changes like if there's a mouse person in the comma box and that will force the repaint basically of the texture. Result of all this can be seen here at the bottom. Note that we only we don't draw the contents here we only draw the background and this is a pattern that we use for all controls for several reasons. First of all by not drawing the contents we can reuse the same texture for all comma boxes. We just scroll one small version of the background until what is called a nine patch image which can be scaled to any size and then we can reuse it for all controls of the same type in the application and secondly we want to avoid drawing text using Qstyle and Qpainter since we want all text in a QML application to be rendered the same way. Mixing those two can produce an inconsistent look basically. To see how the contents are drawn instead we need to take a look at the comma box here at the left. This is our QML part of a comma box looks like on the inside. When you add a comma box to your UI from QML this is the component that will be picked up by the native style and instantiated. The cryptic t.combobox on top here is the C++ base class that contains all the event handling and control object that I briefly talked about in the previous slide which you don't need to worry about now. What we should focus on are the delegates here and the comma box has two of them. The content item and the background. The background is here and the instance of style item comma box the one I talked about in the previous slide. The style item comma box is at the end of the day a normal QML item that happens to grow itself using Qstyle and for the other they'll get the content item which is a normal text fill basically. The implicit size of the content item here is provided as input to the style item comma box and it will use this information to calculate the implicit size of the background taking the content size into account. It doesn't grow the contents but it needs to know the size to calculate the correct implicit size for the background as well and then we'll let the implicit size of the background also be the implicit size of the whole control and the result can be seen here at the bottom. The slide has been converted a little bit wrong here but you can see at least the control down here. Here we have a comma box with contents with a scale of nine patch background texture behind it which looks like it should look. By respecting the split between the foreground and the background the application is free to override any of the delegates and this goes for all styles not only for many of the ones. In the application shown here we create a comma box and assign in a custom content item with a green background which you can see here and this will basically override the default foreground that was set from the previous slide. In general we do recommend though that you either set both a custom foreground and a custom background or none of them otherwise you'll risk an implicit look if you're actually supposed to run on top of different platform styles. As you might have noticed we're not coping the fusion style from widgets. Controls2 already has a fusion style which is which is written in QML and we don't think Qstyle is the best way to create the style for Controls2 in general. It only makes sense when you need to use a native platform API to draw native controls and primitives and the images at runtime basically. On macOS for example we use appkits to draw in the cells and then it's used to cure images. If you don't use any native APIs you're actually better off drawing the images by other means or using QML directly like the fusion style will be in Controls2 and that actually brings me to an important point. I mean we don't only introduce a second API for styling in Controls2 it already has a great styling API from before and we don't want to support and maintain a second styling API. So for that reason the CopioQ style would be a private implementation detail in the Controls repo and not the public styling API for everyone to use. Okay so what about widgets? There might be somebody asking about that. What will this mean for widgets? And the short answer is absolutely nothing. I mean widgets will continue to be maintained as modus before nothing will change. Hopefully one day Composite will be in such a good shape that you will prefer using it over just widgets for your new desktop projects but that will be up to you. They're not enforcing this on anyone. All right so in the end I'm just going to show how the Controls2 application will look with the next up where we are now in Qt6. I'll see if I can share my screen. Yeah cool. All right so this is a normal Controls2 application with a tab bar and tab button and a lot of controls so I can start this up with the fusion style which is already in Controls2. Here it is. Nothing spectacular. Test buttons, checkboxes, radio buttons, winboxes, text fields, text areas, double boxes and so forth. And now I can also start this up with macro style. This. And here we go. Here we have the max style. Buttons, checkboxes, radio buttons. I'm not sure if this come if you can actually see this over the video link but here you can see we're also fading the scroll bars which you don't do for widgets. This is a pretty easy thing to do in QML right so here we halfway draw the slider or the scroll bar with Q style and then we do some extra top logic on top from QML to make it fade in and out. Here we have the combo box and you see there's still some drawing artifacts for the respective focus rights. They're going to work on those before the final release so this is a very beta state right now. All right this is all I got. I guess I have some time for questions too. Yeah let's take it to Q&A then. If you click the shared notes on the sidebar you will see quite a few questions. Good up to you. Please answer any of them in the order you design. Oh okay let's start from the top then. Okay here on Plasma we have our own platform style. What can we do for that? We would need to be able to implement styles for this Q-style Q-style fork. Yeah and that's what you have to do anyway. I mean even if we try to share Q-style with widgets and you have a third-party style that works with widgets. I mean noted for that to work there cannot be any references to Q-widgets inside that style. Otherwise you have to link your application to widgets like maybe Controls1 and we are not going to go down that route. We don't want to control the application you need to link the widgets. So we had to anyway refactor that style and remove all the notions of widgets out of it and we don't think that is the right way to go for styling Controls application to in the first place. We wanted to write the QML using QML to write the style. That's what QML is great for. So I mean it's a pity I would love that too that you can take any third-party style and just make it work for Controls as well. But that is not going to work with this project. Okay if I understood this question correctly. I jumped to question two. Why Q-painter? I'm just throwing away all that one to just all GPU accelerated rendering. Yeah I mean the Q-widget Q-image is only a temporary step. I mean we create the Q-image and we put the Q-painter on it. Because that is the API that Q-style understands. It takes the Q-painter and it draws something somewhere. I mean this can probably be optimized a way later which is why I said we need to have the freedom to optimize this even further. But currently we just draw the control onto a Q-image once and then we convert it to a nine patch texture node in the scene graph. And from there on it's of course accelerated fully. Alright question three. Are there any plans to make Q-painter Controls 2 use proper Windows? Yeah yeah I mean I said that on slide three or four. I mean that's some of the things we need to look at very shortly actually. And we need to use the platform team plugin to create native dialogues and native menus. And I don't know Katie in and out. I guess you have your own platform styling plugin that provides an 85.log and native style name and so forth. And so it would be good if you can pick that up that information and we use it also for controls. Yeah exactly. So that is the motivation right? We want to look we ask Q-painter basically the same question like widgets do. I mean which style does this platform prefer? It's a fusion style it's another style. And we'll respect that whatever it returns. And we will ask it whenever we need to create a native dialogue and or native menus or anything that the team can provide. There is some text typing here at the same time so this I mean this I'm not sure which part you're asking now the QPA stuff it's not that it's semi-public it's not public with API. If you're talking about the Q-style copy the fork basically that we do in Controls 2 that will not be public API now. Because as I said we don't want to introduce a second styling in Controls. This is not the motivation for us we just want to provide native styling. And the low-hanging fruit for us how to do that is to just take what we got in Q-style already and use that as a as a drawing tool basically. So it's an implementation detail and we we want to I mean Q-style is inefficient in many ways and it draws the background it draws the foreground it draws all the primitives like frames and styling writes and all those separately and for many things like in on the Mac style we can draw the whole button in one go on the native platform. So Q-style is not very optimized for how we want to things to work in Controls and for that reason we need to have this freedom going forward now to to basically chop out everything that is slowing us down and things that we want to do differently. So this we are not going to make this public. Okay I just I think I jumped to question four now. How are we supposed to implement our own styles like Breeze which is currently a Q-style when it's private too? I mean if you want to implement the style for Controls 2 you need to use the Controls 2 styling API basically. So if you only have Breeze for widgets right now then you would need to implement Breeze in using the QML styling API. This is not the answer for that part. What is the plan for Linux? That's question five. I mean when we started out this project we were also thinking about porting the Fusion style from Q-style on par with how we would port the Mac style and Windows style but then we saw that we already have the Fusion style and Fusion in Controls 2 actually better. So the Fusion style is currently our answer to desktop styling for widgets also for widgets. And of course we will prioritize Linux equal to Windows and Mac OS. So okay question six will text controls have context menu like QTextEdit it has? I mean there are many controls missing in Controls 2 we have in widgets today and likewise there are many controls in Controls 2 today that we're missing widgets like a range page slider for example and there are a lot of controls that are missing in general from native platforms like a search field and many others that I'm popping to mind right now. So this is things we need to work in for the future but we have a few people this will take some time but surely this is what we are going to work on.