Debugging Qt Quick 2 - Console API

Qt Quick brings a lot of flexibility and speed to development. Traditionally one had to do the "compile, package, deploy, run" cycle over and over again, whereas with Qt Quick you can now do incremental changes to your source even at runtime! In Qt Creator, we are trying to leverage the power of Qt Quick, version by version. However, as with any programming language there is a downside. Script compilation errors are runtime errors in QML, sometimes you're trying to wrap your mind around QtDeclarative binding loops, JavaScript has many dark corners that you don't want to be caught in and so on... All these potential pitfalls mean that a good debugger, profiler and inspector are weapons you really want to have :)

The focus in this blog post is on debugging and the most straightforward debugging technique: The console API. Chances are high that you've already used it in your first helloworld.qml file, since console.log() is a part of it. We recently updated Qt 5 with some of the most useful methods from the FireBug console API (a defacto standard in web browsers).

Logging

We've been supporting console.log and console.debug since Qt Quick 1.0. The print() from QtScript days still works but as it has a slightly different meaning, when you execute it in JavaScript code in a web browser, it should be left alone. In Qt 5 we added a few more logging functions. All the calls are directly forwarded to its Qt counterparts:

JavaScript function Qt/C++ counterpart
console.log() qDebug()
console.debug() qDebug()
console.info() qDebug()
console.warn() qWarning()
console.error() qCritical()

Yes, at the moment, console.log(), console.debug(), and console.info() have the same functionality! Since they are some of the most often used methods and can be found in countless JavaScript code snippets on the net, we're supporting them. Maybe it's also food for thought that we should add an additional log level to qlogging.h ;)

Profiling

Ever wondered about how long a particular code path takes? Take for example the logic in your onCompleted method.

Component.onCompleted() {
console.time("onCompleted");
// ...
console.timeEnd("onCompleted");
}

will print the time in milliseconds. The string argument is both an identifier for the particular measurement (you can also make interleaved measurements) and the prefix for the output:

onCompleted: 401ms

For a more in-depth analysis there's console.profile(), console.profileEnd().

Component.onCompleted() {
console.profile();
}
Component.onDestruction() {
console.profileEnd();
}

The API pair profiles both the state of the QDeclarativeEngine as well as V8 method calls. However, to retrieve the data you have to attach the QML Profiler tool to your application before calling console.profileEnd() else the profiling data is lost. Christiaan Janssen has already described the QML Profiler tool that ships with Qt Creator in a previous post here. A standalone profiler tool is available in Qt 5 that saves the profiling data in a file. This file can then be read using Qt Creator.

Still More...

We have also introduced the following APIs:

console.assert() : To test an expression and print an optional message and the stack trace of JavaScript execution if the expression evaluates to false.

console.exception(): Prints an error message and the stack trace of JavaScript execution.

console.trace(): Prints a stack trace of JavaScript execution at the point where it is called.

console.count(): Prints the number of times this function is called along with a user provided message.

Script Console - New Avatar

The QML console was first introduced in Qt Creator 2.1. However, it was a simplified console limited to evaluating simple expressions. We felt that Qt Quick2 developers need a more advanced console to unleash the power of QML.

We introduce to you the new avatar of the QML Console a.k.a. Script Console.

 

QML Console

Apart from evaluating expressions, the Script Console shows the debug output, both Qt debug messages and JavaScript console messages, in a pretty way ;) You can use the filter buttons located in the top right corner to view logs that appeal to you. For example, if you want to see only the errors, then de-select the info and warning buttons and Voilà! The debug output also shows the file and line info and clicking on it opens the relevant file in the editor with the cursor on the particular line. No more do you need to add context info in your output messages to locate them in your source code. Also you can always rely on the Find toolbar to search for text in the console.

JavaScript objects and arrays are shown in an expandable tree in the console. The current context, which is used to evaluate the expressions,  is displayed in the status bar. The Script Console can be used even when not on a debug break to inspect and evaluate QML elements and expressions. The Script Console also supports multi-line input. It also remembers your previous inputs so that you don't need to type that really long expression again.

The best thing is that you do not have to wait for too long as the Script Console will be a part of Qt Creator 2.5.

What's missing?

We haven't implemented the methods dealing with the console so far, just because they don't make too much sense when your console is just the command line. For example, it would be hard to implement console.clear() in a portable way ;) We left out console.group(), console.groupCollapsed(), console.groupEnd(), console.table(), console.dir(), console.dirXml() for similar reasons.

The Script Console in Qt Creator is WIP.  Currently, QML objects and arrays are not shown in a tree. The console still needs polishing and do expect more features in later versions.

We are eager to hear your wish list and your experiences with the console. You can contact us via the qtcreator mailing list or on IRC at the freenode server, channel #qt-creator.


Blog Topics:

Comments