Console for Plasma DevTools
2022-06-09 Update: I’ve published the code at https://github.com/Zren/QmlDevTools.
Since my last update, I’ve added a console to the devtools window. QML doesn’t have an “exec” function but you can dynamically create components with a string. So we just put our string inside the Component.onCompleted
event handler. Here’s my current exec function.
function exec(str) {
if (str.trim().length == 0) {
return
}
outputView.input(str)
var comp = 'import QtQuick 2.0; QtObject {\n'
comp += 'Component.onCompleted: {\n'
comp += 'try {\n'
var parsedStr = str.trim()
parsedStr = parsedStr.replace('console.log(', 'outputView.log(')
parsedStr = parsedStr.replace('$0', 'elementsView.selectedObj')
var str1 = parsedStr.substr(0, parsedStr.lastIndexOf('\n') - 1)
var str2 = parsedStr.substr(parsedStr.lastIndexOf('\n') + 1)
comp += str1
comp += 'var _result = ('
comp += str2
comp += ')\n'
comp += 'outputView.output(_result)\n'
comp += '} catch (e) {\n'
comp += 'outputView.error(e)\n'
comp += '}\n'
comp += 'destroy()\n'
comp += '}\n'
comp += '}\n'
try {
Qt.createQmlObject(comp, outputView)
} catch (e) {
outputView.error(e)
}
}
Notice that we replace console.log(
with a reference to outputView.log(
so that the user can still use the familiar function without printing to plasmashell’s stdout. I may overload the console
reference later since currently this method doesn’t support console.log.apply(console, ['asdf', 1, 2, 3])
but is simple enough for now.
We also replace $0
with a reference to the selected item in the elements view like Chrome does. We don’t really need $1, $2, etc (2nd+3rd last selected item) but it’d be trivial to have the ElementsView remember a selection history.
If we eventually add autocompletion, we can focus on refactoring and doing things correctly.
Another feature I implemented was animating propety changes in the ElementsView.
I had to do a number of refactoring in the property view since I was doing a very naive update (1 property change will cause it to check every property). I needed to bind()
the property we’re updating and store all the singal handlers we connect with so that we can disconnect them later.
var keys = Object.keys(target)
for (var i in keys) {
var key = keys[i]
if (Util.isChangedSignal(target, key)) {
var propKey = key.substr(0, key.length - 'Changed'.length)
propListeners[key] = propertyUpdated.bind(propertyTreeView, propKey)
target[key].connect(propListeners[key])
}
}
I recently found out that the panels and the desktop have seperate RootItems so we won’t be able to debug the desktop and panel’s at the same time (we’ll need 2 widgets).
Next up I think I’ll work on parsing the “DOM” and creating shortcuts to all the plasma containments and applets.