How to break your code porting from Q_PRIVATE_SLOT to context & function object based connection

TL;DR Beware of connections to function objects accessing class members which could be triggered during execution of subclass destructor methods.

Oh, those name-based signal/slot connections feel outdated!

So you are a happy embracer of Qt’s new QObject signal/slot connection way of coding based on function-pointer or functor objects, like myself. This compile-time check of signals and slots feels just so much better. And thus you also port any existing code to it. Including some which uses the pimpl approach for some public classes, borrowing Qt’s macros Q_PRIVATE_SLOT, Q_D & Co.:

class MyWidgetPrivate;

class MyWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MyWidget(QWidget *parent);
    // [...]
    // setting a QWidget-subclass to be used as custom form in this widget
    void setForm(Form *form);
private:
    const QScopedPointer d_ptr;
    Q_PRIVATE_SLOT(d_func(), void handleFormDeleted())
};

// implementation side:

class MyWidgetPrivate
{
// [...]
public:
    void handleFormDeleted() { /*...*/ }
};

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
    , d_ptr(new MyWidgetPrivate)
{
    // [...]
}

void MyWidget::setForm(Form *form)
{
    Q_D(MyWidget);
    // [...]
    connect(form, SIGNAL(destroyed()), this, SLOT(handleFormDeleted()));
}

Got some time, let’s modernize the code

The old code calls to be changed into using a connection from the destroyed signal to a lambda expression calling handleFormDeleted() directly on the private object, with MyWidget instance as context object, thus removing the need for that Q_PRIVATE_SLOT:

class MyWidgetPrivate;

class MyWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MyWidget(QWidget *parent);
    // [...]
    // setting a QWidget-subclass to be used as custom form in this widget
    void setForm(Form *form);
private:
    const QScopedPointer d_ptr;
};


// implementation side:

class MyWidgetPrivate
{
// [...]
public:
    void handleFormDeleted() { /*...*/ }
};

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
    , d_ptr(new MyWidgetPrivate)
{
    // [...]
}

void MyWidget::setForm(Form *form)
{
    Q_D(MyWidget);
    // [...]
    connect(form, &QObject::destroyed,
            this, [this] { Q_D(MyWidget); d->handleFormDeleted(); });
}

Looks fine & compiles. Code feels more future-proof with the compiler now warning if some signal or slots got changed/removed.

Ooops, crashing now?

Just… nooos, it sometimes crashes now, in the destructor of MyWidget. How that on this innocent looking change?

Reading once more closely the documentation of QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection) we notice the remark:

The connection will automatically disconnect if the sender or the context is destroyed. However, you should take care that any objects used within the function object are still alive when the signal is emitted.

Which subtly hints to the problem we now have: if the form instance is set as child widget of the MyWidget instance, it will be deleted when ~QWidget() is run as part of the MyWidget destructor. And then emit the destroyed signal. At that point in time this as seen by the function object no longer is a proper MyWidget instance. And things go *boom*.

The old string-based connection as well as the member-function-pointer-based one handle that case for us, by some QObject magic using virtual methods which catch that the receiver no longer is a MyWidget and somehow then just drop the slot call (got lost in the code details, but it is something like this).
While with the new function-object-based connection that one will only become automatically inactive by being destroyed if the ~QObject destructor of either sender or receiver is reached. So having a longer lifetime, which can come a bit unexpected to some.

Fixing the modern times, unsure how

Lesson learned: do not blindly port code to the context & function object based connection. Instead beware of the additional traps which there are given that the function object is an independent complex object and not just a member function pointer. I will have to revisit quite some code where I might have missed this trap with the subclass destructor methods :/
As I seemed not the only one hit by this, I filed QTBUG-71432: “API dox of context & function object using QObject::connect should hint about destructor issues” so other people like me might be saved from this from the start.

Curious to learn about best practices for private slots and non-string-based connections. Thus happy to hear about proposals/hints in the comments.

(Update: text now using C++ standard lingo term “function object” instead of “functor”)

Advertisements

Happy 20th anniversary, KDevelop

It’s exactly 20 years ago to the day, that on an equinox as well the first announcement of a KDevelop snapshot, the 0.1 Alpha, was made:

List: kde-announce
Subject: ANNOUNCE: kdevelop-0.1.tar.gz
From: konold () alpha ! tat ! physik ! uni-tuebingen ! de
Date: 1998-09-22 15:50:19

Dear KDE Enthusiast,

the KDE Team is pleased to announce the availability of:

kdevelop-0.1.tar.gz

It can be found at
ftp://ftp.kde.org/pub/kde/unstable/apps/ide/kdevelop-0.1.tar.gz

and at our U.S mirror site
ftp://ftp.us.kde.org/pub/kde/unstable/apps/ide/kdevelop-0.1.tar.gz.

it will probably appear firstly at
ftp://ftp.de.kde.org/pub/kde/unstable/apps/ide/kdevelop-0.1.tar.gz.

Here follows the LSM:

Begin3
Title: KDevelop
Version: 0.1 Alpha
Entered-date: 22 Sep 1998
Description: an IDE for X/Qt/KDE
Keywords: IDE, KDE, X11, Qt, development
Author: Sandy Meier, Stefan Heidrich, Stefan Bartel
Maintained-by: Sandy Meier
Primary-site: http​://www.cs.uni-potsdam.de/~smeier/kdevelop/kdevelop-0.1.tar.gz
Home-page: http​://www.cs.uni-potsdam.de/~smeier/kdevelop/index.html
Original-site: http​://www.cs.uni-potsdam.de/~smeier/kdevelop/kdevelop-0.1.tar.gz
Platform: Linux, needs Qt 1.4 and the kde libs
Copying-policy: GNU Public License
End

20 years of getting feature by feature, sometimes first of its kind, being partially rewritten, getting ported from Qt1 to Qt2 to Qt3 to Qt4 to now Qt5, being made run on non-Linux platforms, seeing hand-overs of maintainers.
At its 20th anniversary KDevelop, now to be called an extensible cross-platform IDE for C, C++, Python, PHP and other languages, continues to provide developers a very reliable and powerful environment to get their code work done. While being inviting to enhance their tool, KDevelop, itself, being a FLOSS software and with no company agenda attached.

I have been a happy user of KDevelop all the years, and currently am giving back to it by doing some development and feature additions.
Be a happy user as well, and then one giving back.
Looking forward to more 20 years, and then some.

KDevelop, ensuring development equity, by day and night. πŸ™‚

From code to related bug report or review in just a hover & click

When working on existing code bases, now and then one reads code that raises some questions and the desire for more context, to understand the purpose or the intention of that code. Context like the commit message, the author, the commit date, or some review discussion of the commit or some bug report or feature request the commit was done for.

In the Beginning There Were Raw Commit Ids…

KDevelop, the extensible cross-platform IDE for C, C++, Python, PHP and other languages, has supported showing line-by-line commit data annotations since many years, starting by showing the commit id and in the tooltip info like author, date and message.
See here a screenshot from the KDevelop 4.1 Dot article (2010):

Annotations border in KDevelop 4.1

Then There Were Year and Author…

Not everyone was capable to deal with raw commit ids, also is it just a reference to the actual metadata, so since some versions of KDevelop the annotation border was changed to show the author name and the commit year instead.
See here a screenshot how it looks by the example of upcoming KDevelop 5.3:

Annotations border in KDevelop 5.3

Soon We Might Get the Message and More

While year and author are already interesting info about a commit, if one is looking at a bunch of lines coming from different commits, it can be unpleasant having always to do some explicit action to get further data, like the commit message, by moving the mouse to trigger the tooltip. And with the recent trend in screen sizes, there often is some vertical space left asking to get its Return-On-Investment πŸ˜‰ .
More, if in the raw commit message displayed in the tooltip some review discussion or bug report is mentioned, one has to remember the review id or bug id and manually navigate to e.g. the respective web page. Again unpleasant if having to do this multiple times.

End of last year two patches have been started with the goal to improve those things:

The first patch would extend KTextEditor by a new class AbstractAnnotationItemDelegate (modelled after QAbstractItemDelegate), which then gives KDevelop and other potential API users full independent flexibility to decide on which data about annotations to render and how, as developers and users prefer by the time.
The second patch would change KDevelop to make use of that delegate option and change what is rendered for a start: for groups of consecutive lines from the same commit the first would show the commit message summary line, with the age of the commit, a second line would show the author. And it would make use of the KDevelop::ActiveToolTip class (as also used e.g. for code type information tooltips), which allows the user to interact with the content of the tooltip, like copying text or clicking links in the commit message, which would be shown enriched with links where feasible.
The latter though currently misses some support from the KDevelop git plugin, which only delivers the message summary line in the data model (due to making use of git blame --porcelain, possibly needs rewrite using libgit2 instead of parsing git output). So tooltips for now still only show the summary line as before at least with git (did not test the other VCS plugins yet).
See here a screenshot how it looks with the patches applied to master branches of KTextEditor & KDevelop (and some example complete commit message text for demoing what is possible):

Annotations border in a future KDevelop?

Please Help to See If It Is Good

Work on those patches has been picked up again the last week, and they have now reached Merge Candidate state and are ready for final review, targeting KTextEditor of KF 5.52 (to be merged right after tagging 5.51) and KDevelop 5.4.

If you are interested in this feature, please consider to help now by testing those patches and/or reviewing their code (see links to patches above), so the feature will be good once it arrives at users like yourself πŸ™‚

Improve your C++ code in KDevelop with Clang-Tidy

You might be aware of Clang-Tidy, the clang-based C++ β€œlinter” tool which allows static analysis of your code, including fixing it automatically where possible.
And you remember the introduction of the “Analyzer run mode” with version 5.1 of KDevelop, the extensible cross-platform IDE for C, C++, Python, PHP and other languages.

While development of a separate KDevelop plugin for the integration of Clang-Tidy was started in 2016, named kdev-clang-tidy, activity stalled after some time, with other things in life to do.
One good thing about Copyleft software is that where somebody left others can pick up and continue: with Clang-Tidy getting more and more useful, there has been new motivation to have such integration with KDevelop, and after some bits of code pushing here we are now, looking at the first released versions of kdev-clang-tidy with basic functionality, which already helped to improve some code bases.

The latest release 0.3 enables KDevelop users to do this:

  • running clang-tidy on a single file, subdirectories or the whole project, with the result shown in the Problems tool view, invokable from file context menus and main menu (Analyzer section)
  • per-project config UI:
    • free field for additional command line parameters to clang-tidy
    • checkbox whether to include system headers in the check
    • toggle between using .clang-tidy files or options in the config UI:
      • header filter regular expression
      • opt-in list of checks

See kdev-clang-tidy 0.3 in activity in some screenshots, here with KDevelop 5.3 pre-beta:

Configure Clang-Tidy globally
Configure Clang-Tidy for a project
Running Clang-Tidy on a subdirectory of a project (here the Clazy integration plugin part of upcoming KDevelop 5.3)

(And yes, in the screenshots one can spot upcoming support for another static code analyzer, clazy, which will be shipped as part of upcoming KDevelop 5.3, more on that soon in another blog post)

The current version 0.3 of kdev-clang-tidy can be built against the versions 5.2, upcoming 5.3 and the current development branch (master) of KDevelop.

Learn more about the kdev-clang-tidy plugin from its README.md file, e.g. how to build it, how to package it, how to use it, where to report issues, and what the planned roadmap is.

The latest released kdev-clang-tidy version is currently also included in the Nightly AppImage builds of the current stable KDevelop code version (which already switched to the 5.3 branch).

Templates to create your own Plasma Wallpaper plugin

More than just a painting on the wall

As you might know, the very background of a Plasma workspace, a.k.a “wallpaper”, is painted by a special kind of full-screen applet, in Plasma terms “wallpaper plugin”. These wallpaper plugins not only allow to do static display of e.g. a given picture, but also some dynamically changing display, even interactively controlled by the user.
One can select the type of the wallpaper by selecting between available wallpaper plugins in the settings of the workspace. A default Plasma installation usually provides wallpaper plugins for at least the types “Color”, “Image”, and “Slideshow” (sources in plasma-workspace repository), and can also have “Picture of the Day” as well as the animated graphic wallpapers “Haneau” & “Hunyango” (sources in kdeplasma-addons repository).

Bring your own wallpaper

One of the Plasma concepts being customizability, one of course can write their own wallpaper plugin for a complete custom look and behaviour of the background.

So people have done. And not only for demoing the power of QtQuick2 and the OpenGL backends with some interactive fireworks wallpaper (sound effects there though left to user as by example of linked video πŸ˜‰ ).
One can find e.g. wallpaper plugins like “Video wallpaper” or “Ken Burns effect slideshow” in the “Plasma Wallpaper plugins” category in store.kde.org. Or soon use (again) the Marble-based “World Map wallpaper” (sadly got broken unnoticed and only restored in time for KDE Applications 18.04). Or in the future find relaxation with the animated Asciiquarium.

Then there is also the Plasma wallpaper plugin example with animated falling tree leaves (sources in plasma-framework repository).

Templates for some DIY in the hobby room/garage

To help you implementing your own idea for a wallpaper plugin, the Plasma libraries part of KDE Frameworks are providing you with a Plasma wallpaper plugin template in the kapptemplate format, as supported by KAppTemplate or KDevelop. It is usually part of the additional development package in Linux distributions (e.g. “plasma-framework-devel”). Starting with upcoming KDE Frameworks version 5.45 this month there will be even two versions, the existing template for a QML-only version and one new template for a version where one wants to include other compiled code using an own QML extension plugin (get this template already here).

With such templates, an initial running version of your own wallpaper plugin is just a few steps away. Create a new project from the template, e.g. with KAppTemplate…

Creating a new Plasma Wallpaper plugin from a template using the KAppTemplate application

… then follow the README in the created sources to build and install the wallpaper plugin. Both templates generate some sample code which shows some configurable text in the middle of the wall, eh, background. So open the settings dialog, select the new wallpaper plugin, enter some text in the sample configuration field and apply…

Configure the new Plasma Wallpaper plugin

And then go and make the Plasma wall all yours πŸ™‚

Present your images from the couch with Gwenview, MPRIS & KDE Connect

((Okular contributors, take a note of the end))

KDE Applications 18.04 Feature Freeze is setting in. Or: reminder to do finally that feature you always wanted to implement.

This time for me it’s remote control for presentation-like media shows. Think slideshows of images/videolets e.g with the image browser Gwenview, or presentations given with the document viewer Okular. Would be nice to do this from across the room or stage, being deep in your comfortable furniture or when standing by the auditorium, would it not?

There is your wireless input controllers to help you. But…

… we want more, like:

  • seeing ourselves the notes for the current slide
  • seeing a preview what is coming up
  • being able to jump straight to a picture or slide without everyone seeing our desperate search for that in the overview list (avoiding also spoilers with not yet shown ones)

Obvious idea: use your smartphone as rich remote control. Just write a controller app which talks to your app on the computer running the presentation. Profit.

Though only profit for the given app. Would it not be nicer if there were some standard interfaces, so remote controllers would work across applications? We have seen that before, for music and movie players. In the FLOSS world there is e.g. the Media Player Remote Interfacing Specification (MPRIS). And if we think about it, “media” is an abstraction, one which also can cover images & slides. Though the rest of the spec then uses concepts and terms which are rather bound to typical music players, like “track” or “playlist”.
So not usable for our purpose. Or? If we ignore the actual terms, we find we can map their abstract data model with some flexibility onto the data model of a simple one-dimensional slide-by-slide/image-by-image presentation. And by doing so instantly can get access to the existing MPRIS controllers, allowing us to walk through the slides, going fullscreen, start playing & pausing and so on. Controllers like e.g. the MPRIS-based media controller plugin for KDE Connect.

So it’s just adding a MPRIS-wrapper to e.g. Gwenview or Okular, and we have some initial working remote controllers for them. Now this sounds fancy to have, no?

And for Gwenview, I can happily report that by some hard review work of Henrik F. a first version has just been merged. Shipping to everyone as part of KDE Applications 18.04.

For Okular we have a similar patch. Though it needs some good souls to give it a complete review in the next 7 days, otherwise it will miss out for the upcoming release and be at least delayed some more four months.

The patches should be also interesting to adapt for photo management applications like Digikam or KPhotoAlbum.
So want to give your vacation report to your friends while sitting next to them on the couch as well? Have a look at those two patches and try to adapt them for those applications, you will see it is rather simple value and action forwarding code πŸ™‚

KMarkdownWebView 0.5.0

KMarkdownWebView 0.5.0 has been released.

Example: KMarkdownWebView KParts plugin used by Ark (using Oxygen theme for some retro look πŸ™‚ )

The KMarkdownWebView software is for the rendered display of Markdown documents, using web technologies. It implements a C++/Qt-based wrapper around a local webpage with a JavaScript library (“marked”) which creates HTML from the plain text in Markdown format passed in.
The software contains

  • a KParts plugin for rendered display of Markdown files, which enables KParts-using applications (like the archiving tool Ark or the file manager Krusader) to show Markdown files in the target format.
  • a Markdown file KIO thumbnail generator plugin, which allows KIO-powered file managers & dialogs to show thumbnails and previews of files in Markdown format in the target format (currently only available when building against QtWebKit)

The KMarkdownWebView KParts plugin is also prepared for improved experience with the KTextEditor Document Preview plugin for KTextEditor-based applications like the editor Kate and IDE KDevelop.

KMarkdownWebView can be built with either QtWebEngine (preferred by the build system) or QtWebKit. Pass -DUSE_QTWEBKIT=TRUE to CMake to enforce the use of QtWebKit.

Changes since 0.4.0

  • Update of “marked” source copy to latest release v0.3.12
  • Translations updated for some languages (fi, fr, sl)

Download sources

Download from: https://download.kde.org/stable/kmarkdownwebview/0.5.0/src/

sha256: 84bcc4b2626109241633a52ee5cd203105fd2488277b478572a3a5b593d3de42 kmarkdownwebview-0.5.0.tar.xz

Signed with my PGP key
E191 FD5B E6F4 6870 F09E 82B2 024E 7FB4 3D01 5474
Friedrich W. H. Kossebau
kmarkdownwebview-0.5.0.tar.xz.sig