Porting KCM modules from QtWidgets to QtQuick/Kirigami for GSOC 2022
I’ve been selected for GSOC this year. My task is to redesign and port the KCMs currently in Qt Widgets to QtQuick/Kirigami
Thanks, Nate and David for agreeing to mentor me.
Why do this ?
Before this, I was already working on KCM for setting gamma in KWin. The MR is in work progress because I decided to add these settings option into kscreen’s KCM instead of creating new one which is pending atm. So I had some prior experience with KCMs
When I first saw this task in ideas list as a user, I was like, why bother ? Qt Widgets already perform much better than Qt Quick. Apps and KCMs in Qt Widgets start instantaneously, compared to many Qt Quick/Kirigami apps and KCMs.
In Qt 6, there is work going on Strict QML and Tiny QML. This will significancy improve QML performance and development experience. There is already qmltc In Qt 6.3 in Tech Preview stage. It creates the C++ API for qml elements, so you don’t need to write JavaScript. There is also qmlsc which works behind the scenes (dev does not need to change code) which compiles JS to CPP.
So while QML suck (IMO) at the movement, the future of QML in Qt 6 looks promising. Also, as a dev, It’s really hard to understand the UI code of apps written in Qt Widgets.
This task will help Plasma migrate to Qt6, and then we can use all these improvements to improve performance and startup time of our qml code.
Progress report #1
In the last two weeks, I made a mock UI in kirigami/kdeclarative which does nothing
While making this, I encountered a weird bug in Qml which stalled my progress for days. If you use the new inline components in file named with QML Object Types, It gives you segmentation fault without any warning or error message. So it was really hard to find what’s going on. Clearing cache helped, but that’s not a good solution, so I decided to find why it happens. I got help from another fellow contributor on matrix. He made a YouTube Video of how we discovered the root cause of this bug. Bug is reported on bugreports.qt.io
After that, I encountered another weird behavior in KDeclarative which further stalled my progress
When pushing new page as filename, the context properties do not worked as I expected.
In following code,
id: root
property var gelement : SomeTem {}
...
function onClicked() {
kcm.push("Another.qml")
}
I was expecting to access the gelement
property in Another.qml
file
with gelement
or root.glement
as it worked before when using
ApplicationWindow and pageStack.push
This is wrong and also an antipattern and strict qml will properly forbid doing this.
I was very curious why this happens, so decided to investigate. After looking in KDeclarative code and not find anything, So I decide to create the vanilla Qt Quick Application with StackView.
It turns out that PageRow does some magic behind the scenes and
kcm.push
is not doing anything wrong.
//main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
Window {
id: root
width: 640
height: 480
visible: true
property string gt: "This is global text from page 1"
property alias stack: stackview
StackView {
id: stackview
anchors.fill: parent
Component.onCompleted: push("qrc:/Page1.qml")
}
}
//Page1.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
Page {
id: page1
property string textFromPage1: "text from page1"
property var page1p: page1
Column {
Label { text: "Page 1" }
Button {
text: "Page 2"
onClicked: {
stack.push("qrc:/Page2.qml")
}
}
}
}
//Page2.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
Page {
Label {
// text: gt // this work
text: page1p.textFromPage1 // this will not
}
}
If you run above code in gammaray,
you will find that both Page1.qml and Page2.qml
share the context of main.qml page which is why they both can access stack
But they both have their own context which they don’t share with each other.
My guess is that stack.push
function is called in context on main.qml
since stack
is in main.qml
While the last two weeks were not very productive, I learned many new things about Qml and KDeclarative and how it works internally.