Language Selection

English French German Italian Portuguese Spanish

Kde Planet

Syndicate content Planet KDE
Planet KDE | English
Updated: 6 hours 56 min ago

Simplifying Grammar Checks for Manuals.

8 hours 45 min ago

Like most online manuals, the Krita manual has a contributor’s guide. It’s filled with things like “who is our assumed audience?”, “what is the dialect of English we should use?”, etc. It’s not a perfect guide, outdated in places, definitely, but I think it does it’s job.

So, sometimes I, who officially maintains the Krita manual, look at other project’s contributor’s guides. And usually what I find there is…

Style Guides

The purpose of a style guide is to obtain consistency in writing over the whole project. This can make the text easier to read and simpler to translate. In principle, the Krita manual also has a style guide, because it stipulates you should use American English. But when I find style guides in other projects it’s often filled with things like “active sentences, not passive sentences”, and “use the Oxford comma”.

Active sentences versus passive sentences always gets me. What it means is the difference between “dog bites man” and “man is bitten by dog”. The latter sentence is the one in the passive voice. There’s nothing grammatically incorrect about it. It’s a bit longer, sure, but on the other hand, there’s value in being able to rearrange the sentence like that. For a more Krita specific example, consider this:

“Pixels are stored in working memory. Working memory is limited by hardware.”

“Working memory stores the pixels. Hardware limits the working memory.”

The first example is two sentences in the passive voice, the latter two in the active. The passive voice example is longer, but it is also easier to read, as it groups the concepts together and introduces new concepts later in the paragraph. Because we grouped the concepts, we can even merge the sentences:

“Pixels are stored in working memory, which is limited by hardware.”

But surely, if so many manuals have this in their guide, maybe there is a reason for it? No, the reason it’s in so many manuals’ style guide, is because other manuals have it there. And the reason other manuals have it there, is because magazines and newspapers have it there. And the reason they have that, is because it is recommended by style guides like The Elements of Style. There is some(?) value for magazines and newspapers in avoiding the passive voice because it tends to result in longer sentences than the active voice, but for electronic manuals, I don’t see the point of worrying about things like these. We have an infinite word count, so maybe we should just use that to make the text easier to read?

The problem of copying style rules like this is also obfuscated by the fact a lot of people don’t really know how to write. In a lot of those cases, the style guide seems to be there to allow role playing that you are a serious documentation project, if not a case of ‘look busy’, and it can be very confusing to the person being proofread. I’ve accepted the need for active voice in my university papers, because I figured my teachers wanted to help me lower my word count. I stopped accepting it when I discovered they couldn’t actually identify the passive voice, pointing at paragraphs that needed no work.

This kind of insecurity-driven proofreading becomes especially troublesome when you consider that sometimes “incorrect” language is caused by the writer using a dialect. It makes sense to avoid dialect in documentation, as they contain specific language features that not everyone may know, but it’s a whole other thing entirely to tell people their dialect is wrong. So in these cases, it’s imperative the proofreader knows why certain rules are in place so they can communicate why something should be changed without making the dialect speaker insecure about their language use.

Furthermore, a lot of such style guide rules are filled with linguistic slang, which is abstract and often derived from Latin. People who are not confident in writing will find such terms very intimidating, as well as hard to understand, and this in turn leads to people being less likely to contribute. In a lot of those cases, we can actually identify the problems in question via a computer program. So maybe we should just do that, and not fill our contributor’s guide with scary linguistic terms?


Despite my relaxed approach to proofreading, I too have points at which I draw the line. In particular, there’s things like typos, missing punctuation, errant white-spaces. All these are pretty uncontroversial.

In the past, I’d occasionally run LanguageTool over the text. LanguageTool is a java based style and grammar checker licensed under LGPL 2.1. It has a plugin for LibreOffice, which I used a lot when writing university papers. However, by itself LanguageTool cannot recognize mark-up. To run it over the Krita documentation, I had to first run the text through pandoc to convert from reStructuredText to plain text, which was then fed to the LanguageTool jar.

I semi-automated this task via a bash script:

#!/bin/sh # Run this file inside the language tool folder. # First argument is the folder, second your mother tongue. for file in $(find $1 -iname "*.rst"); do pandoc -s $file -f rst -t plain -o ~/checkfile.txt echo $file echo $file >> ~/language_errors.txt # Run language tool for en-us, without multiple whitespace checking and without the m-dash suggestion rule, using the second argument as the mother tongue to check for false friends. java -jar languagetool-commandline.jar -l en-US -m $2 --json -d WHITESPACE_RULE,DASH_RULE[1] ~/checkfile.txt >> ~/language_errors.txt rm ~/checkfile.txt done

This worked pretty decently, though there were a lot of false positives (mitigated a bit by turning off some rules). It was also always a bit of a trick to find the precise location of the error, because the conversion to plaintext changed the position of the error.

I had to give up on this hacky method when we started to include python support, as that meant python code examples. And there was no way to tell pandoc to strip the code examples. So in turn that meant there were just too many false positives to wade through.

There is a way to handle mark-up, though, and that’s by writing a java wrapper around LanguageTool that parses through the marked-up text, and then tells LanguageTool which parts are markup and which parts can be analyzed as text. I kind of avoided doing this for a while because I had better things to do than to play with regexes, and my Java is very rusty.

One of the things that motivated me to look at it again was the appearance of the code quality widget in the Gitlab release notes. Because one of my problems is that notions of “incorrect” language can be used to bully people, I was looking for ways to indicate that everything LanguageTool puts out is considered a suggestion first and foremost. The code quality widget is just a tiny widget that hangs out underneath the merge request description, that says how many extra mistakes the merge request introduces, and is intended to be used with static analysis tools. It doesn’t block the MR, it doesn’t confuse the discussion, and it takes a JSON input, so I figured it’d the ideal candidate for something as trivial as style mistakes.

So, I started up eclipse, followed the instructions on using the Java api (intermissioned by me realizing I had never used maven and needing a quick tutorial), and I started writing regular expressions.

Reusing KSyntaxHighlighter?

So, people who know KDE’s many frameworks know that we have a collection of assorted regex and similar for a wide variety of mark up systems and languages, KSyntaxHighlighter, and it has support for reStructuredText. I had initially hoped I could just write something that could take the rest.xml file and use that to identify the mark up for LanguageTool.

Unfortunately, the regex needs of KSyntaxHighlighter is very different from the ones I need for LanguageTool. KSyntax needs to know whether we have entered a certain context based on the mark-up, but it doesn’t really need to identify the mark-up itself. For example, the mark up for strong in reStructuredText is **strong**.

The regular expression to detect this in rest.xml is \*\*[^\s].*\*\*, translated: Find a *, another *, a character that is not a space, a sequence of zero or more characters of any kind, another * and finally *.

What I ended up needing is: "(?<bStart>\*+?)(?<bText>[^\s][^\*]+?)(?<bEnd>\*+?)", translated: Find group of *, name it ‘bStart’, followed by a group that does not start with a space, and any number of characters after it that is not a *, name this ‘bText’, followed by a group of *, name this ‘bEnd’.

The bStart/bText/bEnd names allow me to append the groups separately to the AnnotatedTextBuilder:

if ("bStart") != null) { builder.addMarkup(line.substring(inlineMarkup.start("bStart"), inlineMarkup.end("bStart"))); handleReadingMarks(line.substring(inlineMarkup.start("bText"), inlineMarkup.end("bText"))); builder.addMarkup(line.substring(inlineMarkup.start("bEnd"), inlineMarkup.end("bEnd"))); }

So I had to abandon adopting the KSyntaxHighlighter format for this and do my own regexes.


Eventually, I had something that worked. I managed to get it to write the errors it found to a json file that should work the code quality widget. I also implemented an accepted words list, which at the very least took a third off the initial set of errors. I’ve managed to actually get it to find about 105 errors on the 5000 word KritaFAQ, most of which are misspelled brand names, but it also found missing commas and errant white-spaces.

A small sample of the error output:

{ "severity": "info", "fingerprint": "docs-krita-org/KritaFAQ.rst:8102:8106", "description": "Did you mean <suggestion>Wi-Fi<\/suggestion>? (This is the officially approved term by the Wi-Fi Alliance.) (``wifi``)", "check_name": "WIFI[1]", "location": { "path": "docs-krita-org/KritaFAQ.rst", "position": { "end": {"line": 176}, "begin": {"line": 176} }, "lines": {"begin": 176} }, "categories": ["Style"], "type": "issue", "content": "Type: Other, Category: Possible Typo, Position: 8102-8106 \n\nIt might be that your download got corrupted and is missing files (common with bad wifi and bad internet connection in general), in that case, try to find a better internet connection before trying to download again. \nProblem: Did you mean <suggestion>Wi-Fi<\/suggestion>? (This is the officially approved term by the Wi-Fi Alliance.) \nSuggestion: [Wi-Fi] \nExplanation: null" }, { "severity": "info", "fingerprint": "docs-krita-org/KritaFAQ.rst:8379:8388", "description": "Possible spelling mistake found. (``harddrive``)", "check_name": "MORFOLOGIK_RULE_EN_US", "location": { "path": "docs-krita-org/KritaFAQ.rst", "position": { "end": {"line": 177}, "begin": {"line": 177} }, "lines": {"begin": 177} }, "categories": ["Style"], "type": "issue", "content": "Type: Other, Category: Possible Typo, Position: 8379-8388 \n\nCheck whether your harddrive is full and reinstall Krita with at least 120 MB of empty space. \nProblem: Possible spelling mistake found. \nSuggestion: [hard drive] \nExplanation: null" }, { "severity": "minor", "fingerprint": "docs-krita-org/KritaFAQ.rst:8546:8550", "description": "Use a comma before 'and' if it connects two independent clauses (unless they are closely connected and short). (`` and``)", "check_name": "COMMA_COMPOUND_SENTENCE[1]", "location": { "path": "docs-krita-org/KritaFAQ.rst", "position": { "end": {"line": 177}, "begin": {"line": 177} }, "lines": {"begin": 177} }, "categories": ["Style"], "type": "issue", "content": "Type: Other, Category: Punctuation, Position: 8546-8550 \n\nIf not, and the problem still occurs, there might be something odd going on with your device and it's recommended to find a computer expert to diagnose what is the problem.\n \nProblem: Use a comma before 'and' if it connects two independent clauses (unless they are closely connected and short). \nSuggestion: [, and] \nExplanation: null" }

There’s still a number of issues. Some mark up is still not processed, I need to figure out how to calculate the column, and just simply that I am unhappy with the command line arguments (they’re positional only right now).

One of the things I am really worrying about is the severity of errors. Like I mentioned before, dialects often get targeted by things that determine “incorrect” language, and LanguageTool does have rules that target slang and dialect. Similarly, people tend to take suggestions from computers more readily without question, so, I’ll need to introduce some configuration.

  1. Configuration to turn rules on and off.
  2. Errors that are uncontroversial should be marked higher, so that people are less likely to assume all the errors should be fixed.

But that’ll be at a later point…

Now, you might be wondering: “Where is the actual screenshot of this thing working in the Gitlab UI?” Well, I haven’t gotten it to work there yet. Partially because the manual doesn’t have CI implemented yet (we’re waiting for KDE’s servers to be ready), and partially because I know nothing about CI and have barely got an idea of Java, and am kinda stuck?

But, I can run it for myself now, so I can at the least do some fixes myself. I put the code up here, bear in mind I don’t remember how to use Java at all, so if I am committing Java sins, please be patient with me. Hopefully, if we can get this to work, we can greatly simplify how we handle style and grammar mistakes like these during review, as well as simplifying contributor’s guides.

State of Native Big File Handling in Git

16 hours 55 min ago

After many struggles with using git LFS on repositories that need to store big files, I decided to spend some time on checking the status of the built-in partial clone functionality that could possibly let you achieve the same (as of git 2.30).

TL;DR: The building blocks are there, but server-side support is spotty and critical tooling is missing. It’s not very usable yet, but it’s getting there.

How partial clone works

Normally, when you clone a git repository, all file versions throughout the whole repository history are downloaded. If you have multiple revisions of multi-GB binary files, as we have in some projects, this becomes a problem.

Partial clone lets you download only a subset of objects in the repository and defer downloading the rest, until needed. Most of the time, it means checkout.

For example, to clone a repository with blobs in only the latest version of the default branch, you can do as follows:

git clone --filter=blob:none

The --filter part is crucial; it tells you what to include/omit. It’s called a filter-spec, across the git docs. The specifics of how you can filter are available in git help rev-list. You can filter based on blob size, location the in tree (slow! – guess why), or both.

The remote from which you cloned will be called a “promisor” remote, so-called because it promises to fulfill requests for missing objects when requested later:

[remote "origin"] url = fetch = +refs/heads/*:refs/remotes/origin/* promisor = true partialclonefilter = blob:limit=1048576 # limited to 1M

As you change branches, the required files will be downloaded on-demand during checkout.

Below is a video of a partial checkout in action. Notice how the actual files are downloaded during the checkout operation, and not during clone: Comparison

I checked out Linux kernel from the GitHub mirror, through regular and partial clone, and recorded some statistics:

As you can see, there are some tradeoffs. Checking out takes longer because the actual file content has to be downloaded, not just copied from object store. There are savings in terms of initial clone and repository size because you’re not storing a copy of various driver sources deprecated since the late 90s. The gains would be even more pronounced in repositories that store multiple versions of big binary files. Think evolving game assets or CI system output.

So what are the problems? Missing/incomplete/buggy server support

The server side needs to implement git v2 protocol. Many don’t do it yet, or do it in a limited manner.

No cleanup tool

As you check out new revisions with big files and download them, you will end up with lots of old data from the previous versions because it’s not cleaned up automatically. Git LFS has the git lfs prune tool. No such thing yet exists for partial clones. See this git mailing list thread.

No separate storage of big files on server side (yet)

Since you want server-side operations to happen quickly, it’s best to store the git repository on a very fast storage, which also happens to be expensive. It would be nice to store big files that don’t really need fast operations (you won’t do diffs on textures or sound files server-side) separately.

Christian Couder of GitLab is working on something around this. It’s already possible to have multiple promisor remotes queried in succession. For example, there could be separate promisor remote backed by a CDN or cloud storage (e.g. S3). However, servers will need to learn how to push the data there when users push their trees.

See this git mailing list thread.

Generally cumbersome UX

Since everything is fresh, you need to add some magical incantations to git commands to have it working. Ideally, some “recommended” filter should be stored server-side, so that users don’t have to come up with filter spec on their own, when cloning.


Below are some useful links, if you’d like to learn more about partial cloning in git:

Currently, a lot of effort around partial cloning is driven by Christian Couder of GitLab. You can follow some of the development under the following links:

If you would like to learn Git, KDAB offers an introductory training class.

About KDAB

If you like this article and want to read similar material, consider subscribing via our RSS feed.

Subscribe to KDAB TV for similar informative short video content.

KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.

The post State of Native Big File Handling in Git appeared first on KDAB.

Developer chat moving

18 hours 3 min ago

For years, most development discussion for Krita has happened on the #krita channel on the Freenode IRC network. IRC is a venerable chat system (that’s to say, it’s old and quirky) but it works very well for us because it’s free and open source software and because it treats chat as chat: it doesn’t keep logs for you if you’re not in the channel, there are many clients and interaction is simple and limited to just text.

However, the freenode IRC network is no longer a good host for our development work. The people currently managing the network are doing very strange things, and the people who used to manage the network have created a new network,

From today, if you want to chat to Krita’s developers and contributors, you’ll need to join the #krita channel on

Bridges with the Matrix network (a different, newer, more complex chat system) are in the works, and sometimes work, but sometimes don’t work. This means that if you join use Matrix to join the IRC channel people probably will see nothing of what you’re saying.

The post Developer chat moving appeared first on Krita.

C++ Coroutines, or "why are the templates failing aaaaaAAAAAAA"

Tuesday 15th of June 2021 06:41:40 AM

Qt's networking code has always been one of its more obtuse parts, requiring using signals for something that didn't quite seem right for them. A linear flow of code would become a jumbled mess of member functions and signal connections.

When developing Challah's netcode, I quickly realised this wasn't going to suffice for the large amount of it I was going to be writing. Thus begins my journey through signal hell, arriving at many bumps before I discovered that integrating Qt's networking stuff with coroutines is possible.

Stop Zero

If you're just here to see some cool coroutine code, you can look at for an single-file version of the tutorial in this blog-post, with a coroutine function already made and ready for you to play with. If you want something more full-fledged, look at

But if you want to know what's actually going on behind the scenes, continue reading.

Stop One: Don't Do This

Approach one that I took to get out of signal hell was a simple while loop:

while (!reply->isFinished()) { QCoreApplication::processEvents(); }

This is a bad idea. Strange graphical glitches, bugs, crashes, etc. lie behind this innocuous code. Don't do it. Forcibly spinning the event loop in a lot of places causes a lot of bugs.

Step Two: Callback Hell

So, what do you do if you want to write somewhat linear code without doing that? Callbacks.

QObject::connect(val, &QNetworkReply::finished, [val, callback]() { if (val->error() != QNetworkReply::NoError) { val->deleteLater(); callback({QStringLiteral("network failure(%1): %2").arg(val->error()).arg(val->errorString())}); return; } auto response = val->readAll(); protocol::chat::v1::CreateGuildResponse ret; if (!ret.ParseFromArray(response.constData(), response.length())) { val->deleteLater(); callback({QStringLiteral("error parsing response into protobuf")}); return; } val->deleteLater(); callback({ret}); return; });

Every time I had to call into the netcode, I would have to provide a std::function<void(std::variant<Result,Error>)>. It's passable for a single call, but chaining them quickly violates “happy path sticks to the left”, making you wonder if you're actually writing Python with how far indented your code is.

c->call([c](auto response) { c->call([c](auto response) { c->call([c](auto response) { c->call([c](auto response) { c->call([c](auto response) { }); }); }); }); });

Not good.

Step Three: Out of the Inferno, Into the Frying Pan

await/async as a mechanic in languages generally reduces the amount of callback hell you face by sugaring it for you. For example, in JS, this:

return fetch().then((it) => { return it.text })

is equivalent to this:

return await fetch().text

Both of these return the exact same thing to the caller, but one is much easier to deal with when chained.

For a while, C++ didn't have this. Of course, with C++20, coroutines with co_await & company are now available* in most compilers.

Diversion: That Asterisk

Coroutines are technically available in most compilers, but you're going to have to do a lot of compiler-specific dances in both your code and the build system in order to pass the correct flags to enable coroutines.

I use this snippet to handle clang & gcc:

#if defined(__clang__) #include <experimental/coroutine> namespace ns = std::experimental; #elif defined(__GNUC__) #include <coroutine> namespace ns = std; #endif

where ns is aliased to the namespace containing coroutine-related stuff. Also note that clang will probably fail to compile stuff due to experimental/coroutine being part of libc++ while the rest of your system probably uses gcc's libstdc++. So, for all intents and purposes, gcc is your only option with coroutines on Linux.


Unhelpful Documentation

When hacking on coroutines, I quickly realised: the available documentation on what they were was both young and immature, as well as unhelpful in what they did have. So, this blog post is going to document them.

Parts of the Coroutine

Coroutines are largely split into two parts: the “promise” and the “awaitable”.

The promise is responsible for handling the “internal” side of any coroutine: it's what provides the return value, its yield behaviour, handling unhandled exceptions, the “await transformer”, and some other things. All coroutines need to return one of these.

The awaitable handles the “external” side of the coroutine being co_awaited: it checks with the outside world whether or not the coroutine needs to suspend, listening to the outside world and reactivating the coroutine when it's ready, and providing the value received from the coroutine's completion.

As far as stuff that's directly interacting with coroutines goes, that's mostly it. However, there's still one type you need for an end-user API: the type returned by a coroutine, which is what the compiler uses to match your coroutine to a promise type.

SomeType a_coroutine() { auto foo = co_await another_thing(); // ... }

This SomeType is what I will be calling the “future” or the “task” type, as it's basically the QFuture of the QPromise (or QFutureInterface to speak in Qt5 parlance).

C++ coroutines are very much “bring your own runtime and types”, and thankfully, that's what Qt already has, making it perfect for integrating into coroutines.

A QML-friendly future

C++ coroutines are the perfect fix to a long-standing issue in QML: representing asynchronous results in the UI in a manner that being an object property or model data can't.

So, let's get to constructing the base of our coroutines, and a type that will be suitable for passing into QML.

For ease of use, we'll want this done as a copyable Q_GADGET type with implicitly shared data. This will help us later down the road when we're passing the future type through lambdas.

(For the sake of simplicity of teaching how coroutines work, I'll be doing a simple non-template future type that talks in QVariants and doesn't have success/failure states. If you want to see code with more type safety and success/failure states, you can check out

We'll start by defining our shared data & behaviour.

class Future { Q_GADGET struct Shared { QVariant result; std::function<void(QVariant)> then = [](QVariant) {}; bool done = false; }; QSharedPointer<Shared> d; public: Future() { d.reset(new Shared); } Future(const Future& other) { this->d = other.d; } };

This gives us a Future that is effectively a blob. First, let's define getters for done and result, so the outside world can actually tell what the current state of the Future is:

bool settled() const { return d->done; } QVariant result() const { return d->result; }

Now we need a way to say that the future is completed and a result is available.

void succeed(const QVariant& value) const { if (d->done) { return; } d->done = true; d->result = value; d->then(d->result); }

We don't want to trigger the callback again if we've already marked the future as done, so we abort early if we're already done.

You may notice that this function, despite being a setter semantically, is marked as const. This is mostly for ease of dealing with in lambdas later on.

Now, we need a way to register the callback function in the C++ side of things.

void then(std::function<void(QVariant)> then) const { d->then = then; if (d->done) { then(result()); } }

If the future is already done and you register a callback, you want to call it immediately. This is to handle situations like this:

Future fetch() { if (cache.has_thing()) { Future future; future.succeed(cache.get_thing(); return future; } // ... } void main() { fetch().then([](QVariant) { }); }

If we didn't invoke the callback in then(), the callback would never be triggered as the future was returned to the caller in an already succeeded status.

Since I promised a QML-friendly future type, we should implement that now.

Q_INVOKABLE void then(const QJSValue& it) { then([va = it](QVariant result) mutable {{va.engine()->toScriptValue(result)}); }); }

We add a Q_INVOKABLE overload that takes a QJSValue, as JS functions are represented as QJSValues in C++. We then have a lambda which we pass back into the other then function, taking the QVariant, transforming it into a QJSValue, and calling the JavaScript callback with the variant.

JS usage looks like this:

future.then((it) => { console.warn(it) })

If you've been following along, you should now have this class:

class Future { Q_GADGET struct Shared { QVariant result; std::function<void(QVariant)> then = [](QVariant) {}; bool done = false; }; QSharedPointer<Shared> d; public: Future() { d.reset(new Shared); } Future(const FutureBase& other) { this->d = other.d; } bool settled() const { return d->done; } QVariant result() const { return d->result; } void succeed(const QVariant& value) const { if (d->done) { return; } d->done = true; d->result = value; d->then(d->result); } void then(std::function<void(QVariant)> then) const { d->then = then; if (d->done) { then(result()); } } Q_INVOKABLE void then(const QJSValue& it) { then([va = it](QVariant result) mutable {{va.engine()->toScriptValue(result)}); }); } }; The Backing Promise

Of course, the above class doesn't make a coroutine. For this, we need to implement the promise type.

For placement options, you have two places where you can put this: inside the future type itself, or outside of the type in an explicit coroutine_traits template specialisation.

The former would look like this:

class Future { // ... struct promise_type { }; };

While the latter would look like this:

template<typename ...Args> struct ns::coroutine_traits<Future, Args...> { struct promise_type { }; };

(where ns is the namespace with the coroutine types, std:: on gcc or std::experimental on clang.)

The latter allows you to implement a promise type for any type, not just one that you have control of the declaration of.

For this blog post, I'll be going with the latter approach.

struct promise_type { };

One of the things we'll need in our promise type is a member variable to hold the future type.

struct promise_type { Future _future; };

Of course, the compiler doesn't know about this member function, so we need to start implementing the promise_type interface:

struct promise_type { Future _future; Future get_return_object() noexcept { return _future; } };

T get_return_object() noexcept is the exact type signature that needs to be implemented. We use noexcept here, as exceptions can cause a double free, and therefore, a crash.

Now, we need to implement two things: initial_suspend() and final_suspend(). These two functions are called at the start and end of your coroutine, and have to return a co_awaitable type.

In an expanded form, initialsuspend and finalsuspend look like this:

Future your_coroutine() { co_await promise.initial_suspend(); // coroutine body here... co_await promise.final_suspend(); }

You could theoretically return anything you want here, but you'll likely be sticking with ns::suspend_never, which is an awaitable value that resumes execution of the coroutine immediately when co_awaited, and what we'll be using for this blog post.

Add the implementation to your promise type:

ns::suspend_never initial_suspend() const noexcept { return {}; } ns::suspend_never final_suspend() const noexcept { return {}; }

Your promise is responsible for taking care of any values that are co_returned with the return_value function.

I recommend having two overloads: const T& (copy value) and T&& (move value).

For our promise_type, the implementation of those will simply look like this:

void return_value(const QVariant& value) noexcept { _future.succeed(value); } void return_value(QVariant &&value) noexcept { _future.succeed(std::move(value)); }

If your coroutine was returning something like a std::unique_ptr<T>, you would need the std::move in order to properly handle it, and thus why I say you should have this overload in your promise type.

With getreturnobject, initialsuspend, finalsuspend, and return_value, you only have one remaining function left to implement in your coroutine. It's quite simple.

void unhandled_exception() noexcept { }

This is what gets called in the catch block of a try/catch block catching exceptions that the coroutine might throw. Use std::current_exception() to access the exception.

For this blog post, we'll simply be doing Q_ASSERT("unhandled exception"); in our implementation.

With that, the promise type is complete. It should look something like this:

struct promise_type { Future _future; Future get_return_object() noexcept { return _future; } ns::suspend_never initial_suspend() const noexcept { return {}; } ns::suspend_never final_suspend() const noexcept { return {}; } void return_value(const QVariant& value) noexcept { _future.succeed(value); } void return_value(QVariant &&value) noexcept { _future.succeed(std::move(value)); } void unhandled_exception() noexcept { Q_ASSERT("unhandled exception"); } };

Remember that this needs to be within the Future type itself, or within the appropriate coroutine_traits overload.

The Awaitable

With the Future and promise completed, we don't have much left to do. We now need to implement operator co_await(Future) in order to allow the Future to be awaited.

Technically, we don't need the promise type to make a Future awaitable, only the Future and the co_await overload. Implementing a promise type allows your coroutine that's co_awaiting a Future to return another Future.

There's not really much to the co_await overload, so I'll just paste an implementation verbatim:

auto operator co_await(Future it) noexcept { struct Awaiter { Future future; bool await_ready() const noexcept { return future.settled(); } void await_suspend(ns::coroutine_handle<> cont) const { future.then([cont](QVariant) mutable { cont(); }); } QVariant await_resume() { return future.result(); } }; return Awaiter{ it }; }

co_await needs to return a type with the following methods:

bool await_ready() const noexcept: This function is called before suspending the coroutine to wait on the awaitable to resolve. If the function returns true, the coroutine continues execution without suspending. If the function returns false, it suspends and waits on the value.

Think back to the example of a function returning an already succeeded future to see why this is useful. If the future already holds a value, there's no need to waste time suspending the coroutine.

void await_suspend(ns::coroutine_handle<> callback) const: This function is called when the coroutine suspends with a coroutine handle passed in. For all intents and purposes, you can treat it as if it were a std::function holding a callback, except operator () resumes the coroutine instead of calling a function.

You call the coroutine_handle to resume the coroutine when whenever it's waiting on is ready, e.g. when the future in this example is marked as succeeded. You can connect this to just about anything, e.g. a QTimer::singleShot, a signal, using it as a callback, etc.

T await_resume() const: This is the value that gets assigned to the result of co_awaiting the expression:

auto it = co_await fetchFromNetwork(); // | // ^ this is the value from await_resume()

Annd with all three types implemented, you now have a QML-friendly future, a promise, and an awaitable.

A Brand New Washing Machine

With your new coroutine, you can do just about anything asynchronously. This is an example function that returns a future that will be fufilled in N miliseconds:

Future timer(int duration) { Future it; QTimer::singleShot(duration, [it]() { it.succeed({}); }); return it; }

Note that while it returns a Future, it is not a coroutine. It does not co_await. This is a completely normal function that you can call however you desire.

Making a coroutine using this function is easy:

Future thisIsACoroutine() { co_await timer(2000); co_return {}; }

Note that this function could not return void. The return type of a coroutine has to have an associated promise type, which void does not.

In a class exposed to QML...

class Singleton : public QObject { Q_OBJECT public: Q_INVOKABLE Future foo() { co_await timer(2000); co_return "i was returned by a coroutine"; }; };

This can be used like so:

Button { anchors.centerIn: parent text: "a coroutine!" onClicked: => { console.warn(val) }) }

This will output the following in your console 2 seconds after every time you press this button:

qml: "i was returned by a coroutine"

The inline code from this blog post can be found in a single-file format at Compile with C++20 and -fcoroutines-ts -stdlib=libc++ for clang, and -fcoroutines for gcc.

For a basic future+promise+awaitable deal, this is about all you need to know. However, the iceberg gets way deeper than that.

Stay tuned for more blog posts about the eldritch arcana you can pull off with coroutines. Next one will probably be about wrapping already-existing types such as a QNetworkReply* in order to make them co_await-able.

You can see more advanced (and arguably useful) code at

Contact Me

Note that I wrote this blog post at 2 in the morning. If there's anything that doesn't make sense, please feel free to come to me and ask for clarification.

Or, want to talk to me about other coroutine stuff I haven't discussed in this blog post (or anything else you might want to talk about)?

Contact me here:

Telegram: Matrix: (prefer unencrypted DMs)

Tags: #libre

KDE Plasma 5.22.1, Bugfix Release for June

Tuesday 15th of June 2021 12:00:00 AM

Tuesday, 15 June 2021. Today KDE releases a bugfix update to KDE Plasma 5, versioned 5.22.1.

Plasma 5.22 was released in June 2021 with many feature refinements and new modules to complete the desktop experience.

This release adds a week's worth of new translations and fixes from KDE's contributors. The bugfixes are typically small but important and include:

  • KWin: Platforms/drm: support NVidia as secondary GPU with CPU copy. Commit. Fixes bug #431062
  • Weather applet: Point bbcukmet to new location API. Commit. Fixes bug #430643
  • Wallpapers: Add milky way. Commit. Fixes bug #438349
View full changelog

Kdenlive 21.04.2 released

Monday 14th of June 2021 04:18:55 PM

The second maintenance release of the 21.04 series is out bringing missing keyframing support to effects (like glitch0r. scratchlines and charcoal) as well as the usual batch of bug fixes and usability improvements.

Full log

  • Remove duplicate line from last cherry-pick. Commit.
  • Hopefully proper patch to solve “white” rendering issues. Commit.
  • Fix resize clip end does not allow touching next clip. Commit.
  • Fix clip thumbs disappearing on timeline resize. Commit.
  • Fix timeline thumbnails not saved with project. Commit.
  • Don’t discard subtitle files on project fps change. Commit.
  • Update guides position on project’s fps change. Commit.
  • Fix delete selected clips not working on project opening. Commit.
  • Fix Chroma Key: Advanced edge mode normal was reset to hard. Commit.
  • Fix various frei0r effects losing parameter settings:. Commit.
  • Next try to fix keyframe view positon for mixes. Commit.
  • Revert “Fix keyframeview position in mixes”. Commit.
  • Fix keyframeview position in mixes. Commit.
  • Make effects keyframable: scratchlines, tcolor, lumaliftgaingamma. Commit. See bug #393668
  • Make effects keyframable: charcoal, dust, oldfilm, threshold.xml. Commit. See bug #393668
  • Make glitch0r effect keyframable. Commit. See bug #393668
  • Fix profile repository not properly refreshed after change. Commit.
  • Fix marker monitor overlayer flickers on hover. Commit.
  • Ensure timeline zoombar right handle is always visible. Commit.
  • Fix issue with duplicated title clips. Commit.
  • Fix effect sliders on right to left (rtl) layouts. Commit. Fixes bug #434981
  • Fix alignment of statusbar message label. Commit. Fixes bug #437113
  • Fix crash using filter with missing MLT metadata (vidstab in MLT 6.26.1). Commit.
  • Try to fix wrongly set color in titler. Commit.

digiKam: GSoC 2021 Week 1

Monday 14th of June 2021 05:59:00 AM

So, the first week of coding period has ended. It was exciting and full of challenges. I am happy that I am on the right track and making progress as I’ve promised. This is a small summary of the work done this week.

Getting rid of compiler warnings

digiKam has a really huge codebase. It is actively developed but a lot of code is old which contains deprecated Qt code which must be fixed before introducing Qt6. These are the classes which had issues in digiKam which are now fixed :-

  • QMap
  • QProcess
  • QHash
  • QMatrix
  • QLabel
  • QString
  • QFlag
  • QTimeLine
  • QTabletEvent
  • QWheelEvent
  • QButtonGroup
  • QPrinter
  • Some namespace changes like endl to Qt::endl

These patches can be found at my work branch

And these remain which I shall fix this week:

  • QSet
  • qrand() and qsrand()

Regression testing is important for my project. I patched an important class in the core of digiKam that was used by all filters in the image editor (The MR). This had a risk of introducing regression to filters. I wrote a new unit test to verify it did not.

In a nutshell, there are currently 6693 lines of build warnings on master. See this here

With the patches on my branch these warnings have reduced to 1830 lines! That’s a reduction of about 73%. See this here.

While this is not the best way to track progress but it still gives rough estimate. We now have much cleaner build outputs. This week, it will get smaller.

Thanks for reading!

First week of Google Summer of Code 2021

Sunday 13th of June 2021 11:02:29 PM

A year ago I’d just finished my History degree and I had no idea how to code. This year, I’m taking part in Google Summer of Code! I’m super happy to get the chance to learn more about how KDE software works, and to finally contribute to a project I’ve been using for years.

Over the summer, I’ll be working with KDE developers to create productivity-focused components for Plasma Mobile that work with Akonadi, KDE’s personal information management framework. Akonadi is a super useful piece of kit: it allows developers to tap into a user’s synchronised e-mails, contacts, calendars, providing a seamless experience in productivity tools. I’ll be working on this project with my mentor Carl Schwan, who also helped me during my time doing Season of KDE, and Devin Lin.

The state of affairs

Plasma Mobile is quickly shaping up to be a viable alternative to the Android/iOS duopoly, but it’s not quite there yet. KDE developers are hard at work, nailing the basics. KDE’s Plasma provides an incredibly solid foundation, though unfortunately many of the powerful desktop applications that the KDE community are not suitable for use on mobile devices.

This is mainly due to the fact they are built with a GUI framework called KXMLGui, which allows developers to create intricate and capable user interfaces for applications ranging from video editors to word processors to web browsers. Unfortunately, it’s not just made to be convergent — i.e., adaptable to different display sizes and interaction types (touch vs mouse and keyboard).

KDE’s projects are underpinned by Qt, an immensely powerful toolkit for C++ that lets you create UIs. Thanks to efforts by the Qt team, QML (a UI markup language) and Qt Quick (QML’s standard library) provide a new way of designing UIs that are built to adapt well to different device form factors. The big brained developers at KDE then developed Kirigami, a Qt Quick framework that makes it easy for a developer to bang out a pretty and convergent application usable on the desktop and on your phone (yes, this includes Android and iOS!).

However, Kirigami is still young, and the amount of applications that use it is still growing. Currently, there are a lack of productivity applications that take advantage of Akonadi.

Psst. Thinking of building a Kirigami app? Read the tutorials I wrote on KDE Develop.


Fortunately, people at KDE have already got the ball rolling. My mentor Carl Schwan started work on Kalendar, a Kirigami application that lets you display the events present in your Akonadi-synchronised calendars. However, Kalendar remains a proof-of-concept… for now.

My work for GSoC will focus on turning Kalendar into a fully-usable application that will let you view, add, and edit events in all the ways that a normal calendar application would, on both your PC and your phone. This involves figuring out how event ingestion and modification works in Akonadi, how Akonadi stores and retrieves data, and a lot of UI usability testing. By the end of the summer, we should be a lot closer to having a powerful calendar you can use with your fingertips on Plasma Mobile.

KDE Framework 5.84 - Expandable Tooltips

Sunday 13th of June 2021 05:26:00 PM

Starting with the KDE Frameworks 5.84 release, KXMLGUI based applications will feature expandable tooltips per default.

The matching merge request by Felix Ernst got merged today after 3 months ;=)

What are expandable tooltips at all?

Good question ;=)

In short: for stuff like menu & toolbar actions, it provides an easy way to access the “What’s This?” help.

Unlike before, where you need to manually trigger that via the “Shift-F1” shortcut and click around to try out which GUI elements provide at all this additional help, you will now first get a small tooltip with the normal tooltip content (if any) and a hint that with “Shift” you are able to get more help displayed.

For more details read the merge request.

A video is better than words ;=)

Felix provided a short video in the merge request to demonstrate the basic usage (based on the first implementation, some minor details got fine-tuned later).

Your browser does not support the video tag :P Why is that great?

With this feature the “What’s This?” help is a lot easier to discover. It actually makes now more sense then ever to provide it for more complex actions in your applications, people will really be able to find it.

And even nicer, as this is now done in KXMLGUI, all applications using this KDE Framework will automatically provide the new feature, like e.g. Kate ;=)


A matching thread for this can be found here on r/KDE.

Yet Another Week In Tok

Saturday 12th of June 2021 06:15:34 PM

Bon venon! Herzlich willkommen! o kama pona! Tok now has an improved welcoming sequence with improved visuals and user experience.

If you want to see this for yourself, you can now log out using the new log out menu option.


Once you're back in Tok, why not try out the new resizable chat list?

Or the toggleable sidebar?

Photo and Video Sidebar

Tok now lets you view photos and videos that have been sent in a chat in the sidebar.


You might realise with the help of the sidebar that there's something inappropriate in your chat.

Now, Tok will allow you to properly delete others' messages if you have the correct permissions.

You can also now choose to only delete messages for yourself in groups/chats where this is applicable.


There's a good chance you may want to scold someone for sending an inappropriate photo in your chat. Tok now provides autocompletion for mentions, making it faster to type out someone's username.


Tok now supports displaying GIFs in chat.


Tok has seen a lot of optimisations. Memory usage should now hover around or below the 100MB range idle, depending on how many photos, videos, GIFs, etc. are on your screen.


A lot of Tok's crashes have been fixed, especially ones pertaining to images.

Removed unneeded drums.

Obtaining Tok

Tok can be built from source from

The support/development room is at


Interested in contributing? Come on by the dev chat and say hello.

Tags: #libre

KDE Akademy 2021

Saturday 12th of June 2021 07:45:00 AM

In just six days, on Friday next week, KDE Akademy will start, bringing us eight days packed with presentations, workshops, meetings, BoFs and hanging out with friends.


I have two talks in the main program. The first one will be about the indoor map display component we built for KDE Itinerary, showing how this works as well as looking at what we can build on top of it.

The second talk is about the work on KDE’s Android release pipeline which I have written about here recently, looking at how this integrates with Craft and Binary Factory, as well as how this plays into KDE’s All About The Apps goal.


The bulk of Akademy aren’t talks but a large number of BoFs, workshops and meetings. I’m particularly looking forward to the following topics:

  • KF6: During the last KF6 Sprint we decided to review and revisit the KF6 timeline and branching strategy at Akademy.

  • Application releases and the deployment pipeline: That’s a sub-aspect of the All About The Apps goal, and ties in with my recent work on that for Android releases.

  • Energy efficient software: This includes analyzing, optimizing and continuously monitoring the energy consumption of applications, as well as things like the “Blauer Engel” eco certification.

And judging from past Akademys there will be a whole lot more interesting stuff that I don’t even have on the radar yet :)

Other Topics

Besides the scheduled sessions there’s of course also the hallway track. I’m hoping to gather some feedback for the ongoing work on API for looking up and localizing countries, country subdivisions and timezones there.

Usually I would also use that opportunity to chase people for travel document samples for KDE Itinerary’s data extractor, but that will unfortunately have to wait another year again.

See you at Akademy!

The best part of Akademy however is meeting old and new friends, even if just virtual. I’ll be around the entire time and hope to see many of you there!

If you haven’t done so, it’s not too late to sign up.

This week in KDE: Plasma 5.22 arrives but I bet you’ll want 5.23 once I show you this

Saturday 12th of June 2021 05:15:09 AM

This week Plasma 5.22 was released! Overall our focus on stability has paid off, and so far there are no major regressions reported; only a few medium-severity ones which have all already been fixed in Plasma 5.22.1 :). You can read the release announcement, or check out KDE developer Niccolò Venerandi’s lovely video about it:

But something much bigger happened as well: the next phase of the Breeze Evolution initiative was merged, providing a new style for buttons, menu items, checkboxes, radio buttons, sliders, and more! It’s beautiful:

This new style also fixes several bugs plaguing the old styling for these controls, such as sliders becoming invisible when located on a selected list item, and the “default button” of a dialog not being very visually obvious.

The work was implemented by Jan Blackquill in accordance with mockups made by Manuel Jesus de la Fuente and other members of the KDE VDG. It will make its debut in Plasma 5.23. There is a lot of time left to tweak the final appearance as needed, but overall I think it’s really nice and I hope you’re as excited about it as I am!

New Features

Thumbnails for files inside encrypted locations such as Plasma vaults are now generated and displayed as expected, but not saved, to eliminate a data leak (Marcin Gurtowski, Dolphin 21.08)

Kate’s LSP support now extends to the Dart programming language (Waqar Ahmed, Kate 21.08)

Konsole now supports the DECSET 1003 standard, which means that the features in terminal software such as vim which rely on mouse tracking now work (Luis Javier Merino Morán, Konsole 21.08)

This is not strictly speaking a KDE project, but it certainly affects us: the SDDM login manager can now be run as Wayland-native software without needing X11 at all! (Aleix Pol Gonzalez, SDDM 0.20)

Bugfixes & Performance Improvements

Konsole now correctly processes double right-click events (Luis Javier Merino Morán, Konsole 21.08)

emacs xterm-mouse-mode now works in Konsole (Luis Javier Merino Morán, Konsole 21.08)

In the Plasma Wayland Session, additional screens are now detected when using a multi-GPU setup (Xaver Hugl, Plasma 5.22.1)

The Network Speed widget once again works (David Redondo, Plasma 5.22.1)

The weather widget’s BBC weather data source now works again (they changed the API and we had to react to it) (Joe Dight, Plasma 5.22.1)

In the Plasma Wayland session, the transparent background beind Task Switchers is now always blurred as expected (Vlad Zahorodnii, Plasma 5.22.1)

In the Plasma System Monitor app, the “Get New Pages” view now opens in a nice overlay rather than a narrow squeezy column (Dan Leinir Turthra Jensen, Plasma 5.22.1)

Custom shortcuts for “Walk through applications” (bound to Alt+` by default) now work (Andrew Butirsky, Plasma 5.22.1)

The System Settings File Search page no longer sometimes shows a weird duplicated header (Marco Martin, Plasma 5.22.1)

The re-done Autostart page in System Settings now always shows the correct icon for applications set to run at login (Nicolas Fella, Plasma 5.22.1)

When using a lot of window rules, the System Settings Window Rules page is now much faster to load and display them (Ismael Asensio, Plasma 5.23)

Disabled pages in System Monitor no longer temporarily become un-disabled if its sidebar is collapsed into icons-only mode (Arjen Hiemstra, Frameworks 5.84)

Other User Interface Improvements

When entering Party Mode in Elisa, the playlist now automatically scrolls to the currently-playing song if it would otherwise be out of view, and also automatically scrolls the view as needed to make sure that any newly-playing songs remain in view (Tranter Madi, Elisa 21.08)

The “Get New [thing]” dialogs now handle situations like the server being down or slow more gracefully (Dan Leinir Turthra Jensen, Frameworks 5.84):

QtQuick apps using the Kirigami OverlaySheet component no longer let the sheet touch the edges of the window or screen (Devin Lin, Frameworks 5.84)

…And everything else

Keep in mind that this blog only covers the tip of the iceberg! Tons of KDE apps whose development I don’t have time to follow aren’t represented here, and I also don’t mention backend refactoring, improved test coverage, and other changes that are generally not user-facing. If you’re hungry for more, check out, where you can find blog posts by other KDE contributors detailing the work they’re doing.

How You Can Help

Have a look at to discover ways to be part of a project that really matters. Each contributor makes a huge difference in KDE; you are not a number or a cog in a machine! You don’t have to already be a programmer, either. I wasn’t when I got started. Try it, you’ll like it! We don’t bite!

Finally, consider making a tax-deductible donation to the KDE e.V. foundation.

KDE Ships Frameworks 5.83.0

Saturday 12th of June 2021 12:00:00 AM

Saturday, 12 June 2021

KDE today announces the release of KDE Frameworks 5.83.0.

KDE Frameworks are 83 addon libraries to Qt which provide a wide variety of commonly needed functionality in mature, peer reviewed and well tested libraries with friendly licensing terms. For an introduction see the KDE Frameworks release announcement.

This release is part of a series of planned monthly releases making improvements available to developers in a quick and predictable manner.

New in this version Baloo
  • Embed JSON metadata in KIOSlaves
  • Convert protocol files to JSON
  • [balooctl] Allow clearing a document which has been deleted
  • Add missing Qt5::DBus to qml plugin
Breeze Icons
  • Added new KMyMoney icon again with some extra tweaks
  • Add Goodvibes icon
  • Add an icon for skanpage
  • Tweaked the Rust mimetypes to better match the official branding (bug 434346)
  • Made links relative
  • Updated icons and added symlinks
  • Separated icons to -left and -right
Extra CMake Modules
  • Add LicenseRef-KDE-Accepted-GPL to license compatibility Matrix
  • ecm_gperf_generate(): add option for target arg to add the gen. source to
  • ecm_qt_declare_logging_category: catch alias targets before failing internally
  • Add module to find libmount
  • Drop FindFontConfig.cmake
  • Make sure that dir path exists before attempting to copy file
  • Attempt to find the Play store icon if it’s not explicitly set
  • Add address sanitizer for MSVC
  • ecm_create_qm_loader: support target as alternative argument
  • Don’t pass through list rich text elements, Google Play can’t handle those
  • Fix doc build with Sphinx 4
  • Use pkg_check_modules in FindTaglib.cmake
  • Find PkgConfig quietly
  • Handle text-less tags
  • ECMAddAppIcon: support target as argument
  • Fall back to English for missing translated elements
  • ECMSetupVersion: phase out deprecated *_VERSION_STRING CMake variables
  • Extend Android language mappings for translated metadata
  • Turns out the tier field was wrong, but not the subgroup
  • [KArchive] Use better wording for open error
  • Use imported target for ZLib
  • Allow sorting of todos by category (tag)
  • Use UTC times when calculating the transition dates of standard and dst phases
  • Remove conditional compilation for libical older than 3
  • Fix Compat-libical3-eGroupware.ics
  • Deprecate KLineEdit::passwordMode
  • kconfig_add_kcfg_files: catch alias targets before failing internally
  • Don’t write position data for maximized windows (bug 434116)
  • Deprecate KTipDatabase and KTipDialog
  • [KHamburgerMenu] Ignore native menus
  • Add KCommandBar - a hud-style dialog for quickly executing QActions
  • Allow setting email, phonenumber, impp from QML
  • [addressee] Add property for photo
  • Add properties to Picture
  • kcoreaddons_add_plugin: make SOURCES argument optional
  • KJob: if a delegate is already attached to a job, warn when setJob() is called
  • Make KAboutData::productName accessible for KCrash
  • Do not return duplicate plugins in KPluginLoader::findPlugins
  • Use target_sources() to add sources to targets
  • write metadata to a cache file when applicable
  • Pass Bugzilla product name to DrKonqi when explicitly set in the app
  • init rlp struct and don’t cast rlim_t to int
  • [KeySequenceItem] Display ampersands in shortcuts (bug 437718)
  • [ExtractionResult] Remove automatic mimetype determination
  • [ExternalWriter] Test property serialization
  • [ExternalExtractor/Writer] Avoid unnecessary map value lookup from key
  • [ExternalWriter] Fix infinite loop when serializing properties
  • Avoid leaking a QObject in ExternalWriter
  • [TaglibWriter] Fix memory leak when updating Cover images in ASF (WMA)
  • Revert “Prevent kglobalaccel5 getting activated on non-Plasma systems” (bug 437034)
KDE GUI Addons
  • Fix crash in keysequence recorder due to out of bound access
  • ki18n_wrap_ui: catch alias targets before failing internally
  • add std::chrono overload for addIdleTimeout
  • avif: Adjust for libavif breaking change
  • Enable HEIC plugin to save all ICC profiles
  • Color profile loading/saving fixes
  • xcf: Make sure offsets are not negative
  • xcf: Fix Stack-buffer-overflow WRITE on broken files
  • New job: KTerminalLauncherJob
  • Remove the cache KCM
  • Remove the Browser Identification KCM
  • Fix outdated URL for RAE Search Provider
  • KOpenWithDialog: expand category on selection (bug 437885)
  • Support wayland’s xdg_activation_v1
  • [kopenwithdialog] Show better error message when specifying a non-executable file (bug 437880)
  • Updating caching logic for thumbnails, to detect encrypted devices (bug 411919)
  • Port ioslave template to use JSON metadata
  • webshortcuts KCM: Remove unneeded rebuildKSycoca method call
  • Remove ServiceTypes property from webshortcuts
  • protocoltojson: Do not create empty array for ExtraNames value
  • kio_file: remove pmount-related code
  • Honor the port number when fetching favicons
  • [KCoreDirLister] Guard uiDelegate(), it might be null (bug 437153)
  • [src/widgets/kfileitemactions] Dont try to connect non-existing plugin
  • Improve strings for file/folder and URL link functionality
  • TCPSlaveBase: deprecate socket() and introduce tcpSocket()
  • Allow selecting directories in KFileWidget (bug 419874)
  • MimeTypeFinderJob: the StatJob details should include the mimetype (bug 398908)
  • kio_file: pass the absolute path to QMimeDatabase::mimeTypeForFile()
  • When finding a job delegate extension, also try the uiDelegate() of its parents (bug 436049)
  • Capture sender object in connect() call instead of using sender()
  • MimeTypeFinderJob: Resolve symlinks for a local file
  • Put compatibility code which uses KMimeTypeTrader in deprecation wrappers
  • PreviewJob: Create a larger SHM when necessary (bug 430862)
  • [KUrlNavigator] Improve presentation of search results
  • Port KFileItemActions::runPreferredApplications away from trader constraint
  • Port KFileItemActions::associatedApplications away from trader constraint
  • Update template app
  • [ActionTextField] Switch actions to use small sizing rather than smallMedium
  • fix(a11y): use semantically correct ellipses instead of semantically incorrect triple period
  • use ecm_generate_qmltypes cmake macro
  • SwipeNavigator hotfixes
  • Fix back button in layers not asking Page::backRequested first before closing the page
  • Split PageTab out of SwipeNavigator
  • Split TabViewLayout out of SwipeNavigator
  • [ActionTextField] Add more spacing between actions and text
  • Improve look of card by making border a bit more subble
  • [ActionTextField] Respect actions' enabled properties
  • Adapt BasicListItemTest.qml to new API
  • [BasicListItem] Offer vertical fill options for leading/trailing items
  • Fix non-atomic updating of PlatformTheme colours
  • Add BasicListItemTest case for leading+trailing items with skinny list items
  • [BasicListItem] Increase icon size when showing or reserving space for subtitle
  • [BasicListItem] Fix sizing for reserveSpaceForSubtitle: true case
  • Fix BasicListItem.reserveSpaceForSubtitle to take into account textSpacing
  • Fix rendering of small size borders of ShadowedTexture
  • Add new fadeContent property to BasicListItem (bug 436816)
  • Introduce Kirigami.Heading.type
  • Disconnect before destroying items (bug 436707)
  • [BasicListItem] Expose spacing between label and subtitle as property
  • [BasicListItem] Increase spacing between label and subtitle
  • Don’t unnecessarily use the std::function overload of qmlRegisterSingletonType
  • Ensure XmlLoader works in the expected, asynchronous fashion
  • Add functionality to have a local providers file
  • Don’t show Go to… action unless it has children
  • Fix opensearch parsing
  • Make Syndication optional and only build OPDS plugin when present
  • Change the role names in the search preset to custom ones
  • Add in tagfilters and filter out entries that are not openaccess for now
  • Add ‘restart’ search preset so people can go back to the search they started out with
  • Add recommended and subscription to the searchpreset types
  • Ensure to use the ‘self’ link relation for resolving relative urls
  • Add download size if said information is available
  • Add concept of search presets to hold navigation links for opds feed
  • Make sure the documents are valid feed documents
  • Add the start link as an entry so we can at the least always return to the root of the opds catalog
  • Fix some misunderstandings with Download Link information
  • Make caching work a bit better, and ensure it shows the installed entries
  • Make the download links a bit prettier
  • Try to implement the loading of new feeds from entries
  • Initial patch for opds support
  • Adjust help text for knewstuff-dialog
  • Engine: Deprecate configSearchLocations and setConfigLocationFallback methods
  • Make knewstuff-dialog work more reliable
  • KNSCore::Engine: Add method to list all available knsrc files
  • KNSCore::Question: Use nested event loop for waiting
  • Deprecate BrowserExtension::actionSlotMap()
  • Expose PersonsSortFilterProxyModel header
  • Fix DBus check
  • Implement monotonic cubic interpolation for line charts (bug 435268)
  • Prevent an infinite loop in LegendLayout when minTotalWidth equals available
  • Reduce severity of column not found to debug
  • Expose preferredWidth as a property on LegendLayout and Legend
  • RunnerManager::runnerMetaDataList: Do not return duplicate plugin IDs
  • Do not crash if there’s no Konsole
  • Launch KCMs in kcmshell5 if systemsettings5 is not installed
  • KToolInvocation: deprecate kdeinitExec()
  • Avoid bad negative search offsets
  • Fix vim cursor gets stuck with ‘b’
  • Limit shortcut context to active view for Reuse Word Above/Below (bug 352902)
  • ensure remove trailing spaces value is in range
  • Revert “Add option to keep spaces to the left of cursor when saving” (bug 433455)
  • Revert “Update remove-trailing-spaces modeline”
  • Revert “compute lastChar only if needed”
  • Revert “Use KTextEditor::Cursor instead of ints in removeTrailingSpaces”
  • Add “Transpose Words” feature (bug 436621)
  • Don’t apply the offset for the quoted regexp, as it is not zero-length
  • Fix on-the-fly spell checking with recent Qt (bug 436004)
  • fix :e for vi-mode to properly open non-local files, too
  • fix :e filename for untitled documents
  • Fixup registering text hint providers
  • Add a separator line after ‘Automatic Selection’
  • Ensure instances of derived Private classes are properly destructed
  • Un-overload KReplace::replace() signal
  • Use protocol files from plasma-wayland-protocols
  • Update Plasma Wayland Protocols dependency to 1.3.0
  • Do not emit Surface::leave twice when an output is removed
  • Ensure instances of derived Private classes are properly destructed
  • Fix crash in KSelectAction (bug 436808)
  • KFontChooser: always prepend the default font style in the styles list
  • Provide KWindowSystem::lastInputSerial
  • Include API for wayland’s xdg_activation_V1
  • Drop Qt5Widgets dependency if KWINDOWSYSTEM_NO_WIDGETS=ON
  • Add KCommandBar to KXMLGui-using apps by default
  • Remove the Attica requirement by using the store’s new links
  • Use new version-controlled enumerator deprecation warning macros
  • Ensure instances of derived Private classes are properly destructed
  • Don’t translate urls (bug 436052)
  • Make it compile with current flags
  • Fix missing definition for IPv6 property when building against older NM
  • IPv6Setting: add option to disable IPv6
  • fix(pppoe): add parent
Oxygen Icons
  • high def new version printer
  • more versions of the printer icon size 16x16
  • more size versions of preferences-kde-connect
Plasma Framework
  • Fix crash when there is already exactly 5 events displayed
  • Remove call to setClearBeforeRendering
  • Fix missing definition of HAVE_X11
  • Change qqc2-desktop-style Units.fontMetrics property to a FontMetrics
  • Support for blur behind plasmoids
  • Filter configure action out of overflow menu correctly
  • Allow building the project without deprecations
  • PC3 TabButton: Center align text without icon, use icon property
  • PC3 TabButton: Fix horizontal content alignment with max text width
  • Fix events appearing in year or decade view (bug 436999)
  • Check QAction enablement before triggering
  • Introduce new SVG element: menubaritem
  • Add sizeForLabels icon size to Units
  • Fix Label having non-integer sizes
  • [pluginloader] Deprecate listContainments and listContainmentsOfType
  • Deprecate PluginLoader::listContainmentsForMimeType
  • add missing signal is setConstraintHints
  • Allow ExpandableListItem to not be expandable when it has no valid actions
  • [dataengine] Emit sourceRemoved earlier (bug 435991)
  • [scrollview] Consider scroll bars when calculating implicit size
  • User HoverHandler instead of MouseArea
  • Ensure inherited PIMPL instances are properly destructed
  • Add Malayalam trigram
Syntax Highlighting
  • Rust syntax - Separate ControlFlow from Keywords
  • Fix perl qw< > highlighting
  • Update GAS syntax to highlight reg/instrs/jmp instrs
Security information

The released code has been GPG-signed using the following key: pub rsa2048/58D0EE648A48B3BB 2016-09-05 David Faure Primary key fingerprint: 53E6 B47B 45CE A3E0 D5B7 4577 58D0 EE64 8A48 B3BB

Plasma 5.22 available for Hirsute Hippo 21.04 in backports PPA

Friday 11th of June 2021 06:56:54 PM

We are pleased to announce that Plasma 5.22.0, is now available in our backports PPA for Kubuntu 21.04 Hirsute Hippo.

The release announcement detailing the new features and improvements in Plasma 5.22 can be found here.

To upgrade:

Add the following repository to your software sources list:


or if it is already added, the updates should become available via your preferred update method.

The PPA can be added manually in the Konsole terminal with the command:

sudo add-apt-repository ppa:kubuntu-ppa/backports

and packages then updated with

sudo apt full-upgrade


Please note that more bugfix releases are scheduled by KDE for Plasma 5.22, so while we feel these backports will be beneficial to enthusiastic adopters, users wanting to use a Plasma release with more rounds of stabilisation/bugfixes ‘baked in’ may find it advisable to stay with Plasma 5.21 as included in the original 21.04 (Hirsute) release.

The Kubuntu Backports PPA for 21.04 also currently contains newer versions of KDE Frameworks, Applications, and other KDE software. The PPA will also continue to receive updates of KDE packages other than Plasma.

Issues with Plasma itself can be reported on the KDE bugtracker [1]. In the case of packaging or other issues, please provide feedback on our mailing list [2], IRC [3], and/or file a bug against our PPA packages [4].

1. KDE bugtracker:
2. Kubuntu-devel mailing list:
3. Kubuntu IRC channels: #kubuntu & #kubuntu-devel on
4. Kubuntu ppa bugs:

Web Review, Week 2021-23

Friday 11th of June 2021 01:58:29 PM

Let’s go for my web review for the week 2021-23.

We’re All Paying for Someone Else’s 4-Hour Work Week, Not Ours | by Jessica Wildfire | May, 2021 | An Injustice!

Tags: economics

I read that book out of curiosity a long while ago. This post articulates quite well why I hated it. It’s built upon selfishness and inequalities.

Don’t let Social Media Think for You

Tags: tech, social-media, attention-economy

A good illustration on why social media are toxic for our thinking. They push us to focus on anecdotes and as such miss the big picture. No wonder everything got so polarized so quickly there.

Ban Biometric Surveillance - Access Now

Tags: tech, surveillance, facial-recognition

Very important open letter, this kind of biometric surveillance is becoming pervasive and should be stopped earlier than later.

Plasma 5.22 - KDE Community

Tags: tech, kde

Obviously thrilled to see this one released. This is a good one. :-)

Abstract Syntax Tree for Patching Code and Assessing Code Quality | Soroco Engineering

Tags: tech, python, quality, refactoring

AST tooling is great for porting code and code quality checks. Here are a couple of examples in python.

Don’t Feed the Thought Leaders - Earthly Blog

Tags: tech, management, forecasting, decision-making

Very interesting discussion about decision making and forecasting. I’m discovering Tetlock as he is mentioned and his findings are interesting in their own right as well.

So you messed up. Now what? - Jacob Kaplan-Moss

Tags: tech, project-management, estimates

Last part about estimates. Plenty of very good advises again on how to deal not meeting a deadline. Communicating the bad news early is key.

Stockdale Paradox — Why optimists don’t survive software projects | by Ben Hosking | Jun, 2021 | Dev Genius

Tags: tech, project-management, estimates

Excellent advises on project planning and management. It explains pretty well why being optimist in those areas will just drive your project through a wall.

Bye for now!

I'm back in the boat

Friday 11th of June 2021 12:00:00 AM

In mid-2014 I first heard about Jolla and Sailfish OS and immediately bought a Jolla 1; wrote apps; participated in the IGG campaign for Jolla Tablet; bought the TOHKBD2; applied for (and got) Jolla C.

Sounds like the beginning of a good story doesn’t it?

Well, by the beginning of 2017 I had sold everything (except the tablet, we all know what happened to that one).

So what happened?? I was a happy Sailfish user, but Jolla’s false promises disappointed me.

Yet, despite all that, I still think about Sailfish OS to this day. I think it’s because, despite some proprietary components, the ecosystem around Sailfish OS is ultimately open source. And that’s what interests me. It also got a fresh update which solves some of the problems that where there 5 years ago.

Nowadays, thanks to the community, Sailfish OS can be installed on many devices, even if with some less components, but I’m looking for that complete experience and so I asked on the forum if there was someone willing to sell his Xperia device with or without the license… and I got one for free. Better still, in exchange for some apps!

To decide which applications to create, I therefore took a look at that ecosystem. I started with the apps I use daily on Android and looked for the Sailfish OS alternative (spoiler: I’m impressed, good job guys!).

I am writing them all here because I am sure it will be useful to someone else:

  • AntennaPod (podcast app) -> PodQast
  • Ariane (gemini protocol browser)
  • AsteroidOS (AsteroidOS sync) -> Starfish
  • Connectbot (ssh client) -> built-in (Terminal)
  • Conversation (xmpp client) -> built-in (Messaging)
  • Davx5 (caldav/cardav) -> built-in (Account)
  • DroidShows (TV series) -> SeriesFinale
  • Element (Matrix client) -> Determinant
  • Endoscope (camera stream)
  • Fedilab (Mastodon client) -> Tooter
  • ForkHub (GitHub client) -> SailHub
  • FOSS Browser -> built-in (Browser)
  • FreeOTP -> SailOTP
  • Glider (hacker news reader) -> SailHN
  • K-9 Mail -> built-in (Mail)
  • KDE Connect (KDE sync) -> SailfishConnect
  • Keepassx (password manager) -> ownKeepass
  • Labcoat (GitLab client)
  • Lemmur (Lemmy client)
  • MasterPassword (password manager) -> MPW
  • MuPDF (PDF reader) -> built-in (Documents)
  • Newpipe (YouTube client) -> YTPlayer
  • Nextcloud (Nextcloud files) -> GhostCloud
  • Notes (Nextcloud notes) -> Nextcloud Notes
  • OCReader (Nextcloud RSS) -> Fuoten
  • OsmAnd~ (Maps) -> PureMaps
  • Printing (built-in) -> SeaPrint
  • QuickDic (dictionary) -> SailyDict
  • RedMoon (screen color temperature) -> Tint Overlay
  • RedReader (Reddit client) -> Quickddit
  • Signal -> Whisperfish
  • Syncthing (files sync) -> there’s the binary, no UI
  • Transdroid (Trasmission client) -> Clutch
  • Vinyl (music player) -> built-in (Mediaplayer)
  • VLC (NFS streaming) -> videoPlayer
  • WireGuard (VPN) -> there’s the binary, no UI
  • YetAnotherCallBlocker (call blocker) -> Phonehook

So, to me it looks like almost everything is there, except:

I’ve already started to write a UI for Syncthing, then maybe I could write the browser for the gemini protocol or rather the GitLab client?

Please consider a donation if you would like to support me (mention your favourite project!).

Many many thanks to Jörg who sent me his Sony Xperia 10 Plus! I hope I don’t disappoint him!

KDE Dev-Vlog 1: Gwenview becomes more pretty

Thursday 10th of June 2021 02:10:34 PM

KDE Dev-Vlog 1: Gwenview becomes more pretty

Hello! I've been contributing to KDE software for a while but this is the first blog post I am writing.

Over the last couple of weeks we have been improving the user interface of the default KDE image viewer Gwenview. Instead of just writing a text about the steps of turning a mockup into reality I made a video. I think it is way easier to show the evolution this way and it is also more fun for me personally. I think the video turned out great overall so please enjoy!

I went through the effort of writing English subtitles for this German video so I hope you won't mind reading them.

Strangely enough this is the first time the KDE community can see moving pictures of me even though I've been contributing for over two years now: I didn't have a webcam until recently and in-person events weren't possible because of Covid.

Graceful Downtime

Thursday 10th of June 2021 01:41:00 PM

Occasionally, services need to go down for some reason or another. That's just a thing that happens. Servers need software updates too, but what happens to the clients that need those services? Well, luckily we've got these HTTP Status responses, and one of those is the 503 response, which is described as meaning "Service Unavailable". The actual English interpretation of that is more akin to temporarily unavailable, and even better, if it is also paired with a "Retry-After" header, with a time sometime in the near-ish future, then we can reasonably assume that that what's happening is an expected downtime, or maintenance.

As of 5.84, KNewStuff will handle that on the various services it supports, and in particular the KDE Store (since that is accessed through the Attica library, which also got a bit of attention to allow for this introspection to be done).

What if error, but helpful?!

It's a small thing, but it means a lot to our users that they don't just sit there staring at something and then get a "lol it's broken" type message, when in fact we do know better what is going on. A side effect of putting in this bit of infrastructure in the library also means we now have somewhere to deal with other unfortunate networking situations in a more graceful manner - not done yet, of course, but we've got a starting point for it.

Just a little one this time, but i thought it was worth mentioning none the less. Not everything has to be huge or groundbreaking, sometimes "this little thing is nice for our users" is also good ;)

The word of the day is: Failure. Because that's something we have to deal with sometimes :)

KDE Gear 21.04.2

Thursday 10th of June 2021 09:30:00 AM

Over 120 individual programs plus dozens of programmer libraries and feature plugins are released simultaneously as part of KDE Gear.

Today they all get new bugfix source releases.

Distro and app store packagers should update their application packages.

Maui Weekly Report 12

Thursday 10th of June 2021 02:30:27 AM

Today, we bring you a new report on the Maui Project’s progress.

A month ago, we had our 1.2.2 stable release, and since then, we have been working on getting everything ready for the next big release, 2.0.

Here we want to share some of the highlights coming to the next stable release.

One of the most common requests we have had is publishing Maui Apps on the F-Droid store to distribute future package updates easily.

The plan is to have Maui apps on FlatHub, Google Play Store, AppImageHub, and F-Droid, and the news is that we are working to achieve this goal.

To track progress on this issue and jump in and help, you can follow this ticket:

Some of the Maui apps are already available on FlatHub, and the others are soon coming to the AppImageHub store:

To get the apps published to the KDE F-Droid store instance, we first need to build correctly under the KDE Binary factory. Maui Apps and Frameworks can be built using the KDE infrastructure services like the Android Docker; However, the output APK packages still have some issues, like missing Maui style and broken features, but it is an initial step.

The next task is to create Craft Blueprints (Python script files that help Craft compile projects in multiple platforms) for all of the apps and framework libraries to make it easier for KDE Binary Factory to deploy Android packages to the stores. This will eventually help to get the apps built for Windows and macOS as well.

MauiKit 1.2.2

Once again, the framework has been cleanup and has gone through clazy style checks and memory optimizations, on the road to becoming much more efficient.

  • Improved TabView workflow for dragging items between tabs.
  • TabView control now has a quick switcher dialog to jump between open tabs by only using the keyboard; this can be triggered on Nota with Ctrl+Space and Index with Ctrl+H.
  • A new SplitView and SplitViewItem controls have been added. All Maui apps now use it, and split views can be closed by dragging the split to a minimum closing threshold size.
  • Lighter GridItemTemplate and other delegates resulting in faster scrolling.
  • More thumbnail previews for text, PDF, audio, and fonts files on Linux.
  • More stable file tagging experience.
  • We moved the accounts component out of MauiKit Core.

You can watch the following video to preview some of the changes and highlights coming to the Maui Project:


To follow the Maui Project’s development or say hi, you can join us on Telegram:

We are present on Twitter and Mastodon:

Release cycle Release date 2021 2022 2023 February 1.2.1 2.1.1 2.2.2 May 1.2.2 2.1.2 3.0.0 August 2.0.0 2.2.0 3.1.0 November 2.1.0 2.2.1 3.1.1


The post Maui Weekly Report 12 appeared first on Nitrux — #YourNextOS.