<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://alex1701c.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://alex1701c.github.io/" rel="alternate" type="text/html" /><updated>2025-09-21T07:46:17+00:00</updated><id>https://alex1701c.github.io/feed.xml</id><title type="html">Alexander’s homepage</title><subtitle>Blog about variout things, mostly KDE related</subtitle><author><name>Alexander Lohnau</name></author><entry><title type="html">Akademy 2025, Talks, BOFs, Döner</title><link href="https://alex1701c.github.io/2025/09/21/akademy-2025.html" rel="alternate" type="text/html" title="Akademy 2025, Talks, BOFs, Döner" /><published>2025-09-21T00:00:00+00:00</published><updated>2025-09-21T00:00:00+00:00</updated><id>https://alex1701c.github.io/2025/09/21/akademy-2025</id><content type="html" xml:base="https://alex1701c.github.io/2025/09/21/akademy-2025.html"><![CDATA[<p>Like every year, one of the highlights is Akademy! This time we were in Berlin, making it quite easy to get there from Hamburg:)
The weather was surprisingly nice, especially when heading out in the evening to try lots of different restaurants.
And of course - since being in Berlin - you gotta try a local Döner there :D.</p>

<p>One talk I was particularly surprised about was Saturday’s keynote “Open by Design: How Governments Can Lead the Shift to Digital Sovereignty” by Alexander Rosenthal.
Besides the information about OpenSource-Software being used on different levels of federal/state/local, the aspects of OpenData.
This made me realize that software is not the only thing one should focus on being open.<br />
Also, the huge amount of memes in the slides made the talk super refreshing and a nice start into Akademy!</p>

<p>Nate’s talk “Minding the Big Picture: Opportunity From Chaos” also fit this topic. OpenSource can provide a stable foundation
and reduced dependence on individual companies.</p>

<p>My main development focus and also the most frequent topic of the blog is the Clazy project. Akademy is a good occasion to tell other people about it.
So I took the occasion and held a fast-track talk about Clazy to tell how awesome and useful it is.<br />
It was also quite good to get people talking about it and share their ideas/problems.</p>

<p>I also did a decent amount of coding on Clazy. This included a request from aacid about Clazy not working properly with a Qt variant
that is build into a specific namespace. This was quite the rabbithole, but I managed to get the passing tests from 50% to 90%.
The last few edgecases are not as relevant if most of Clazy works properly.
For the use-arrow-operator-instead-of-data a false-positive is fixed where the check complains if you do a <code class="language-plaintext highlighter-rouge">.data()</code> call and then cast the pointer.
This is in most cases needed, if not, clang-tidy should warn about unneeded casts.<br />
Finally, fixits for detaching-temporary and detaching-member are more reliable when multiple calls are chained.</p>

<p>The biggest surprise though came at the Akademy awards. I am very honored to have received one, this left me quite speechless.</p>

<p><img src="/assets/img/award.png" alt="" />
<em>Me finally catching some words after getting the Award &lt;3</em></p>

<p>This also means I am responsible for choosing the person for next year’s award. So you better get busy doing cool stuff 😎👀.</p>

<p>Finally, I want to thank everyone who helped organize Akademy and made it as awesome as it was!</p>]]></content><author><name>Alexander Lohnau</name></author><category term="KDE" /><category term="Akademy" /><summary type="html"><![CDATA[Like every year, one of the highlights is Akademy! This time we were in Berlin, making it quite easy to get there from Hamburg:) The weather was surprisingly nice, especially when heading out in the evening to try lots of different restaurants. And of course - since being in Berlin - you gotta try a local Döner there :D.]]></summary></entry><entry><title type="html">Changing Maintainership of Clazy</title><link href="https://alex1701c.github.io/2025/09/11/maintainership.html" rel="alternate" type="text/html" title="Changing Maintainership of Clazy" /><published>2025-09-11T00:00:00+00:00</published><updated>2025-09-11T00:00:00+00:00</updated><id>https://alex1701c.github.io/2025/09/11/maintainership</id><content type="html" xml:base="https://alex1701c.github.io/2025/09/11/maintainership.html"><![CDATA[<h3 id="becoming-the-official-maintainer-of-clazy">Becoming the official Maintainer of Clazy</h3>

<p>During this year’s Akademy in Berlin, I gave a talk about the awesome features &amp; usecases of Clazy.
Afterwards, I also talked with Ivan Čukić and the topic of maintainership. Sérgio Martins was the original author and long
time maintainer. Ivan took over the role for a while, but since I became quite active in the project, he thought it would be a good idea for me to be the official maintainer.</p>

<p>I am very honored that he transferred maintainership of Clazy to me. I’ll do my best to continue pushing the project forward.
Also thanks to Sérgio and Ivan for their previous work and KDAB for supporting it. Also thanks to all the other people who have contributed so far!</p>

<p>In case you want to get started in Clazy development, your contributions are welcome! Feel free to reach out to me if you have issues with getting started :)</p>]]></content><author><name>Alexander Lohnau</name></author><category term="Clazy" /><category term="Clang-Tidy" /><summary type="html"><![CDATA[Becoming the official Maintainer of Clazy]]></summary></entry><entry><title type="html">Bringing together Clazy and Clang-Tidy</title><link href="https://alex1701c.github.io/2025/07/27/clazy-clangtidy.html" rel="alternate" type="text/html" title="Bringing together Clazy and Clang-Tidy" /><published>2025-07-27T00:00:00+00:00</published><updated>2025-07-27T00:00:00+00:00</updated><id>https://alex1701c.github.io/2025/07/27/clazy-clangtidy</id><content type="html" xml:base="https://alex1701c.github.io/2025/07/27/clazy-clangtidy.html"><![CDATA[<h1 id="-clazy-now-integrates-with-clang-tidy">🎉 Clazy Now Integrates with Clang-Tidy!</h1>

<p>I am excited to announce a major improvement to the Clazy project: <strong>Clazy now integrates seamlessly with Clang-Tidy</strong>!</p>

<h2 id="-one-toolchain-all-the-checks">🧩 One Toolchain, All the Checks</h2>

<p>Clazy now provides a plugin (on Unix <code class="language-plaintext highlighter-rouge">ClazyClangTidy.so</code>) that allows all its checks to run inside <code class="language-plaintext highlighter-rouge">clang-tidy</code>, unifying your static analysis workflow.
You no longer need to run two separate tools — just configure Clazy’s checks through <code class="language-plaintext highlighter-rouge">clang-tidy</code> itself.</p>

<p>This change needed quite a few refactorings to make the existing Clazy codebase more adaptable.
In total, changes were spread out to 9 different pull requests to gradually implement the needed changes.
Besides implementing the functionality, the testsuite was also adapted to ensure Clazy’s <code class="language-plaintext highlighter-rouge">clang-tidy</code> provides proper results.</p>

<h3 id="-how-to-use">✅ How to Use</h3>

<p>To load the plugin:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>clang-tidy <span class="nt">-load</span><span class="o">=</span>ClazyClangTidy.so ...
</code></pre></div></div>

<blockquote>
  <p>🔒 If the plugin isn’t in a standard library path, either add it to your <code class="language-plaintext highlighter-rouge">LD_LIBRARY_PATH</code> or provide an absolute path to the plugin file.</p>
</blockquote>

<p>Unfortunately, Clang-Tidy needs to have Clazy checks enabled explicitly and does not have a concept of “levels” to group checks.
While wildcards like <code class="language-plaintext highlighter-rouge">clazy-*</code> would also work, it enables all manual-level checks. Those have more false positives and can hurt performance.</p>

<p>As a helper, you can export environment variables containing the check names to concatenate the desired combination:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">CLAZY_LEVEL0</span><span class="o">=</span>clazy-overloaded-signal,clazy-connect-by-name,clazy-connect-non-signal,clazy-qstring-comparison-to-implicit-char,clazy-wrong-qevent-cast,clazy-lambda-in-connect,clazy-lambda-unique-connection,clazy-qdatetime-utc,clazy-qgetenv,clazy-qstring-insensitive-allocation,clazy-fully-qualified-moc-types,clazy-unused-non-trivial-variable,clazy-connect-not-normalized,clazy-mutable-container-key,clazy-qenums,clazy-qmap-with-pointer-key,clazy-qstring-ref,clazy-strict-iterators,clazy-writing-to-temporary,clazy-container-anti-pattern,clazy-qcolor-from-literal,clazy-qfileinfo-exists,clazy-qstring-arg,clazy-empty-qstringliteral,clazy-qt-macros,clazy-temporary-iterator,clazy-wrong-qglobalstatic,clazy-lowercase-qml-type-name,clazy-no-module-include,clazy-use-static-qregularexpression
<span class="nb">export </span><span class="nv">CLAZY_LEVEL1</span><span class="o">=</span>clazy-auto-unexpected-qstringbuilder,clazy-connect-3arg-lambda,clazy-const-signal-or-slot,clazy-detaching-temporary,clazy-foreach,clazy-incorrect-emit,clazy-install-event-filter,clazy-non-pod-global-static,clazy-post-event,clazy-qdeleteall,clazy-qlatin1string-non-ascii,clazy-qproperty-without-notify,clazy-qstring-left,clazy-range-loop-detach,clazy-range-loop-reference,clazy-returning-data-from-temporary,clazy-rule-of-two-soft,clazy-child-event-qobject-cast,clazy-virtual-signal,clazy-overridden-signal,clazy-qhash-namespace,clazy-skipped-base-method,clazy-readlock-detaching
<span class="nb">export </span><span class="nv">CLAZY_LEVEL2</span><span class="o">=</span>clazy-ctor-missing-parent-argument,clazy-base-class-event,clazy-copyable-polymorphic,clazy-function-args-by-ref,clazy-function-args-by-value,clazy-global-const-char-pointer,clazy-implicit-casts,clazy-missing-qobject-macro,clazy-missing-typeinfo,clazy-old-style-connect,clazy-qstring-allocations,clazy-returning-void-expression,clazy-rule-of-three,clazy-virtual-call-ctor,clazy-static-pmf
</code></pre></div></div>

<p>Checks in Clang-Tidy can be disabled when prefixing them with “-“, whereas Clazy uses “no-“ prefixes.
An example clang-tidy command to use all level0 checks, with <code class="language-plaintext highlighter-rouge">overloaded-signal</code> being disabled and the <code class="language-plaintext highlighter-rouge">qt-keywords</code> manual check being enabled:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>clang-tidy <span class="nt">-load</span><span class="o">=</span>ClazyClangTidy.so <span class="se">\</span>
<span class="nt">-checks</span><span class="o">=</span><span class="s2">"</span><span class="nv">$CLAZY_LEVEL0</span><span class="s2">,-overloaded-signal,qt-keywords"</span> <span class="se">\</span>
<span class="nt">-p</span> my_build_dir mydir/<span class="k">**</span>.cpp
</code></pre></div></div>

<p>In case you want to speed up linting in the project, <code class="language-plaintext highlighter-rouge">run-clang-tidy</code> can be used for parallel execution.</p>

<h3 id="-limitations--tricks">🚧✨ Limitations &amp; Tricks</h3>

<p>Unlike using Clazy directly, clang-tidy has its own filter mechanism to only emit warnings from files that were provided as an input.
This means if a warning is emitted from a header file and not the “.cpp” file you provide as an input, Clang-Tidy will suppress it.
To see those warnings <code class="language-plaintext highlighter-rouge">-header-filter=".*"</code> can be added to the command.</p>

<h3 id="-getting-it--feedback">💡💬 Getting it &amp; Feedback</h3>

<p>The Clang-Tidy plugin is currently not released, and some additional development on various checks is happening.
For trying it out, one has to compile the project from source. It is just a simple CMake setup - promise ;)
See the instructions for more details: <a href="https://invent.kde.org/sdk/clazy/#build-instructions">https://invent.kde.org/sdk/clazy/#build-instructions</a></p>

<p>Any feedback and contributions are appreciated - let’s make Clazy better together 😎.
Please report bugs or suggestions on <a href="https://bugs.kde.org/enter_bug.cgi?product=clazy">https://bugs.kde.org/enter_bug.cgi?product=clazy</a> or <a href="https://invent.kde.org/sdk/clazy/-/issues">https://invent.kde.org/sdk/clazy/-/issues</a>.</p>]]></content><author><name>Alexander Lohnau</name></author><category term="Clazy" /><category term="Clang-Tidy" /><summary type="html"><![CDATA[🎉 Clazy Now Integrates with Clang-Tidy!]]></summary></entry><entry><title type="html">Clazy 1.15 Released – New Checks, Better Stability</title><link href="https://alex1701c.github.io/2025/06/15/clazy-release.html" rel="alternate" type="text/html" title="Clazy 1.15 Released – New Checks, Better Stability" /><published>2025-06-15T00:00:00+00:00</published><updated>2025-06-15T00:00:00+00:00</updated><id>https://alex1701c.github.io/2025/06/15/clazy-release</id><content type="html" xml:base="https://alex1701c.github.io/2025/06/15/clazy-release.html"><![CDATA[<p>🎉 <strong>New Clazy Release: Stability Boost &amp; New Checks!</strong></p>

<p>We’re excited to roll out a new Clazy release packed with bug fixes, a new check, and improvements to existing checks.
This release included 34 commits from 5 contributors.</p>

<hr />

<h2 id="-new-features--improvements">🔍 New Features &amp; Improvements</h2>

<ul>
  <li>
    <p><strong>New Check: <code class="language-plaintext highlighter-rouge">readlock-detaching</code></strong><br />
Detects unsafe and likely unwanted detachment of member-containers while holding a read lock.
For example, when calling <code class="language-plaintext highlighter-rouge">.first()</code> on the mutable member instead of <code class="language-plaintext highlighter-rouge">.constFirst()</code></p>
  </li>
  <li>
    <p><strong>Expanded Support for Detaching Checks</strong><br />
Additional methods now covered when checking for detaching temporary or member lists/maps.
This includes reverse iterators on many Qt containers and <code class="language-plaintext highlighter-rouge">keyValueBegin</code>/<code class="language-plaintext highlighter-rouge">keyValueEnd</code> on QMap.
All those methods have <code class="language-plaintext highlighter-rouge">const</code> counterparts that allow you to avoid detaching.</p>
  </li>
  <li>
    <p><strong>Internal Changes</strong>
With this release, Clang 19 or later is a required dependency. All older versions needed compatibility logic
and were not thouroughly tested on CI. In case you are on an older Version of a Debian based distro, consider
using https://apt.llvm.org/ and compile Clazy from source ;)</p>
  </li>
</ul>

<hr />

<h2 id="-bug-fixes">🐞 Bug Fixes</h2>

<ul>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">install-event-filter</code></strong>: Fixed crash when no child exists at the given depth.<br />
<a href="https://bugs.kde.org/show_bug.cgi?id=464372">BUG: 464372</a></p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">fully-qualified-moc-types</code></strong>: Now properly evaluates <code class="language-plaintext highlighter-rouge">enum</code> and <code class="language-plaintext highlighter-rouge">enum class</code> types.<br />
<a href="https://bugs.kde.org/show_bug.cgi?id=423780">BUG: 423780</a></p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">qstring-comparison-to-implicit-char</code></strong>: Fixed and edgecase where assumptions about function definition were fragile.<br />
<a href="https://bugs.kde.org/show_bug.cgi?id=502458">BUG: 502458</a></p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">fully-qualified-moc-types</code></strong>: Now evaluates complex signal expressions like <code class="language-plaintext highlighter-rouge">std::bitset&lt;int(8)&gt;</code> without crashing.
<a href="https://invent.kde.org/sdk/clazy/-/issues/28">#28</a></p>
  </li>
  <li>
    <p><strong><code class="language-plaintext highlighter-rouge">qvariant-template-instantiation</code></strong>: Crash fixed for certain template patterns when using pointer types.</p>
  </li>
</ul>

<hr />

<p>Also, thanks to Christoph Grüninger, Johnny Jazeix, Marcel Schneider and Andrey Rodionov for contributing to this release!</p>]]></content><author><name>Alexander Lohnau</name></author><summary type="html"><![CDATA[🎉 New Clazy Release: Stability Boost &amp; New Checks!]]></summary></entry><entry><title type="html">Reworking and porting my KRunner plugins</title><link href="https://alex1701c.github.io/2025/01/03/krunner-plugins.html" rel="alternate" type="text/html" title="Reworking and porting my KRunner plugins" /><published>2025-01-03T00:00:00+00:00</published><updated>2025-01-03T00:00:00+00:00</updated><id>https://alex1701c.github.io/2025/01/03/krunner-plugins</id><content type="html" xml:base="https://alex1701c.github.io/2025/01/03/krunner-plugins.html"><![CDATA[<h3 id="reworking-and-porting-my-krunner-plugins">Reworking and porting my KRunner plugins</h3>

<p>Writing KRunner plugins was my first real developer experience with KDE. I started out right after graduating from school in 2019.
Since then, I continued to maintain my plugins and correct some of the code-crimes that have been committed.
This continued adding some features, removing too obscure features, getting user feedback and also making
sure the plugins are easy to install without too much developer knowlege being needed.
By maintaining the KRunner framework, I also deprecated lots of API and provided cleaner alternatives as part of the efforts for KDE Frameworks 6.
Those changes had to be applied to all the plugins. I also contributed to other developer’s plugins that I found useful.</p>

<p>In this post, I will give you an overview of the different plugins and show you, how they may be useful to your workflow.<br />
All the below mentioned Plugins are compatible with Plasma5 and Plasma6, meaning even users of LTS distributions can utilize them.
KRunner plugins also work in the normal application launchers - meaning you should really give those a look!</p>

<h5 id="emojirunner">EmojiRunner</h5>

<p>This is a utility to search and copy emojis. On X11, you may paste them using xdolib.
To ensure you get the emojis you like the most quickly, it is possible to configure favorites in the dialog.
Custom emoji, emoji+text entries and aliases can also be added in the config module.</p>

<p><img src="https://raw.githubusercontent.com/alex1701c/Screenshots/master/EmojiRunner/global_search_with_actions.png" alt="" /><br />
<em>https://github.com/alex1701c/EmojiRunner/</em></p>

<h5 id="jetbrains-plugin">JetBrains plugin</h5>

<p>While I love Kate and neovim for doing code editing, having JetBrains IDEs is amazing when working on bigger Java/JavaScript projects.
To improve the integration into KDE Plasma, the KRunner plugin searches for the installed JetBrains IDEs and reads the recently opened projects of them.
Those can be shown and filtered in KRunner. This allows one to directly launch the right project from KRunner!</p>

<p>Sometimes one may find oneself navigating projects in Dolphin. For this case, a context menu counterpart exists.
In there, you find the options to open the folder in the installed JetBrains IDEs. In case the folder is known as a project, the options are presented at the top-level.</p>

<p><img src="https://raw.githubusercontent.com/alex1701c/Screenshots/master/JetBrainsRunner/multible_projects.png" alt="" /><br />
<em>https://github.com/alex1701c/JetBrainsRunner</em><br />
<em>https://github.com/alex1701c/JetBrainsDolphinPlugin</em></p>

<h5 id="vscodecodium-workspaces-integration-plugin">VSCode/Codium workspaces integration plugin</h5>

<p>Next to opening recent JetBrains projects, this plugin allows one to open workspaces configured in VSCode.
It is pretty straightforward - just install the “Project Manager” plugin in VSCode or Codium, add a few projects and enjoy opening them directly from KRunner.</p>

<p><img src="https://raw.githubusercontent.com/alex1701c/Screenshots/master/VSCodeProjectsRunner/app_overview.png" alt="" /><br />
<em>https://github.com/alex1701c/krunner-vscodeprojects/</em></p>

<h5 id="firefox-plugin">Firefox plugin</h5>

<p>Having multiple profiles in Firefox may be useful for separating the work one is doing, managing different extensions or different settings.
However, switching between them is rather annoying. Manually adding actions to the desktop file may work, but is rather cumbersome and not as flexible.</p>

<p>This plugin allows you to integrate Firefox profiles automatically in KRunner. It also allows for sorting, opening private windows as actions and also adds them to the desktop file.
Meaning, you can right-click on Firefox in the taskbar or the launcher and have the actions there available.</p>

<p><img src="https://raw.githubusercontent.com/alex1701c/Screenshots/master/FirefoxProfileRunner/runner_profiles_overview.png" alt="" /><br />
<em>https://github.com/alex1701c/krunner-firefox</em></p>

<h5 id="nordvpn-plugin">NordVPN plugin</h5>

<p>This plugin allows you to easily connect to NordVPN servers, disconnect and view the status. A configurable status is available in KRunner or an extended one when clicking/pressing enter on the respective result.
When connecting, a country, city or specific server may be entered.<br />
It is no advertisement or recommendation! Just saying :D</p>

<p><img src="https://raw.githubusercontent.com/alex1701c/Screenshots/master/NordVPNKrunner/connect_default.png" alt="" /><br />
<em>https://github.com/alex1701c/NordVPNKrunner/</em></p>

<h5 id="tmuxrunner">TmuxRunner</h5>

<p>Tmux is a terminal multiplexer that allows you to have multiple terminals in the same window (split screen, or multiple “tabs”). You may also detach from it without killing the processes.
This is one of the advantages of using it instead or in addition to for example Konsole’s tabs.</p>

<p>Keeping track of the sessions might be a bit hard though. To solve this issue, this plugin provides an overview of the currently active sessions and allows you to create new ones with optionally a specified name.
The sessions will be opened in the configured terminal - by default Konsole.</p>

<p><img src="https://raw.githubusercontent.com/alex1701c/Screenshots/master/TmuxRunner/overviewtmux.png" alt="" /><br />
<em>https://github.com/alex1701c/TmuxRunner</em></p>

<h5 id="quickwebshortcuts">QuickWebShortcuts</h5>

<p>While I have given the official webshortcuts quite a bit of love over the years, there may be some things lacking.
For example, there is always the separator character (colon or space) that separates your query from the provided search, like “dd:testme”. With this plugin, you only need to type one out. Additionally, it can provide search suggestions!</p>

<p><img src="https://raw.githubusercontent.com/alex1701c/Screenshots/master/QuickWebShortcuts/search_suggestions_demo.png" alt="" /><br />
<em>https://github.com/alex1701c/QuickWebShortcuts</em></p>

<h5 id="veracryptrunner">VeracryptRunner</h5>

<p>This plugin allows one to add and search mount configurations for Verarcrypt. This includes file/device paths, display name, mount path and keyfiles.
Optionally, on X11, the password can be read and entered directly using the command line “pass” password manager.</p>

<h5 id="other-mentions">Other mentions</h5>

<p>I have the one or other, maybe less useful plugin. Like an integration for KWallet or a little timer utility.<br />
For users of VirtualBox, https://github.com/alvanieto/vbox-runner can be very useful. I contributed a merge requests to allow the plugin to work with KF5 and KF6.</p>]]></content><author><name>Alexander Lohnau</name></author><category term="KDE" /><category term="KRunner" /><summary type="html"><![CDATA[Reworking and porting my KRunner plugins]]></summary></entry><entry><title type="html">Welcome to My Blog</title><link href="https://alex1701c.github.io/2024/11/24/welcome-to-my-blog.html" rel="alternate" type="text/html" title="Welcome to My Blog" /><published>2024-11-24T00:00:00+00:00</published><updated>2024-11-24T00:00:00+00:00</updated><id>https://alex1701c.github.io/2024/11/24/welcome-to-my-blog</id><content type="html" xml:base="https://alex1701c.github.io/2024/11/24/welcome-to-my-blog.html"><![CDATA[<p>Heyho together!</p>

<p>I am from now on writing my posts on GitHub pages. Apart from it being useful to keep my posts versioned using git, I had some issues with my previous blog.
The idea was to simply use write.as and publish a post from time to time. This worked well except for more than a month ago me wanting to do a post about my KRunner plugins.
It naturally contained a lot of links and thus the publishing was prevented and even the account blocked due to apparent spam. There was no response via mail for over a month.</p>

<p>So here we are not on another blog where I hopefully write more often and also be able to spent more time on KDE!</p>]]></content><author><name>Alexander Lohnau</name></author><summary type="html"><![CDATA[Heyho together!]]></summary></entry><entry><title type="html">Akademy 2024 in Würzburg</title><link href="https://alex1701c.github.io/2024/09/13/akademy-2024.html" rel="alternate" type="text/html" title="Akademy 2024 in Würzburg" /><published>2024-09-13T00:00:00+00:00</published><updated>2024-09-13T00:00:00+00:00</updated><id>https://alex1701c.github.io/2024/09/13/akademy-2024</id><content type="html" xml:base="https://alex1701c.github.io/2024/09/13/akademy-2024.html"><![CDATA[<h3 id="akademy-2024-in-würzburg---it-was-a-blast">Akademy 2024 in Würzburg - it was a blast</h3>

<p>My second Akademy and has ended just yesterday. It was an amazing and productive time again!
Apart from familiar faces I know from last year’s Akademy or the Plasma sprint last year in Augsburg, I met plenty of new faces.
Some of which I of course had contact in KDE before, but only in the digital world.</p>

<p>One of the best parts was again the day trip with the KDE Community. While it was a bit rainy, we for sure made the best of it and saw the beautiful city of “Rothenburg ob der Tauber”. The view from the town hall tower was very beautiful:<br />
<img src="https://i.imgur.com/CshP6rx.jpeg" alt="" /></p>

<p>The talks were also quite interesting and highlighted how many facades the KDE Community has. Apart from the lightning talks being great again, the “QML in Qt6” talk was quite valuable, because I did not manage to follow up closely on the latest improvements.<br />
The talks and BOFs related to the KDE goals were also quite beneficial in getting a good impression in what direction we want to go.</p>

<p>Since we had so many interesting talks, it was not possible to join all of them. What I will follow up on later are the talks “Pythonizing Qt” and “C++, Rust and Qt: Easier than you think”.</p>

<p>Albert Astals Cid and I gave a lightning talk together about JSON linting (my part) and QML linting (his part). We were only able to touch the surface in the given time, but had some productive discussions and follow-up questions afterward. I will create a post about the JSON validation/JSON schema topic in the future, since I am still working on some aspects of this.</p>

<p>It has been great again to also do some hacking together and discuss ideas in-person. I will miss being able to say “Let’s discuss this at Akademy?” on merge requests ;).<br />
I did quite a bit of hacking on KRunner, linting/formatting related tooling and also <a href="https://invent.kde.org/sdk/clazy/">Clazy</a>.<br />
This can also be seen on my GitLab history that has turned a bit more blue and thus active:<br />
<img src="https://i.imgur.com/vdFtASF.png" alt="GitLab activity" /></p>

<p>What was a great improvement over the last Akademy were the chicken noises to make sure people stay within the time of their talk!
To better improve on that, we should maybe get some real chicken next year 🥚🐣🐔. The talks on how to apply for funding in KDE might contain useful info when working towards this ;)
PS: My life-long profile picture on GitHub/GitLab is of the super cute chicken I had 🥰.</p>

<p><img src="https://i.imgur.com/bPlxgwp.jpeg" alt="Chicken picture" /></p>]]></content><author><name>Alexander Lohnau</name></author><summary type="html"><![CDATA[Akademy 2024 in Würzburg - it was a blast]]></summary></entry><entry><title type="html">Improving the qcolor-from-literal Clazy check</title><link href="https://alex1701c.github.io/2024/01/20/clazy-qcolor.html" rel="alternate" type="text/html" title="Improving the qcolor-from-literal Clazy check" /><published>2024-01-20T00:00:00+00:00</published><updated>2024-01-20T00:00:00+00:00</updated><id>https://alex1701c.github.io/2024/01/20/clazy-qcolor</id><content type="html" xml:base="https://alex1701c.github.io/2024/01/20/clazy-qcolor.html"><![CDATA[<h3 id="improving-the-qcolor-from-literal-clazy-check">Improving the qcolor-from-literal Clazy check</h3>

<p>For all of you who don’t know, <a href="https://invent.kde.org/sdk/clazy/">Clazy</a> is a clang compiler plugin that adds checks for Qt semantics.
I have it as my default compiler, because it gives me useful hints when writing or working with preexisting code.
Recently, I decided to give working on the project a try! One bigger contribution of mine was to the qcolor-from-literal check, which is a performance optimization.
A <code class="language-plaintext highlighter-rouge">QColor</code> object has different constructors, this check is about the string constructor. It may accept standardized colors like “lightblue”, but also color patterns.
Those can have different formats, but all provide an RGB value and optionally transparency. Having Qt parse this as a string causes performance overhead compared to alternatives.</p>

<h4 id="fixits-for-rgbrgba-patterns">Fixits for RGB/RGBA patterns</h4>
<p>When using a color pattern like “#123” or “#112233”, you may simply replace the string parameter with an integer providing the same value.
Rather than getting a generic warning about using this other constructor, a more specific warning with a replacement text (called fixit) is emitted.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>testf4ile.cpp:92:16: warning: The QColor ctor taking RGB int value is cheaper than one taking string literals [-Wclazy-qcolor-from-literal]
        QColor("#123");
               ^~~~~~
               0x112233
testfile.cpp:93:16: warning: The QColor ctor taking RGB int value is cheaper than one taking string literals [-Wclazy-qcolor-from-lite
        QColor("#112233");
               ^~~~~~~~~
               0x112233
</code></pre></div></div>

<p>In case a transparency parameter is specified, the fixit and message are adjusted:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>testfile.cpp:92:16: warning: The QColor ctor taking ints is cheaper than one taking string literals [-Wclazy-qcolor-from-literal]
        QColor("#9931363b");
               ^~~~~~~~~~~
               0x31, 0x36, 0x3b, 0x99
</code></pre></div></div>

<h4 id="warnings-for-invalid-color-patterns">Warnings for invalid color patterns</h4>
<p>Next to providing fixits for more optimized code, the check now verifies that the provided pattern is valid regarding the length and contained characters.
Without this addition, an invalid pattern would be silently ignored or cause an improper fixit to be suggested.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.../qcolor-from-literal/main.cpp:21:28: warning: Pattern length does not match any supported one by QColor, check the documentation [-Wclazy-qcolor-from-literal]
    QColor invalidPattern1("#0000011112222");
                           ^
.../qcolor-from-literal/main.cpp:22:28: warning: QColor pattern may only contain hexadecimal digits [-Wclazy-qcolor-from-literal]
    QColor invalidPattern2("#G00011112222");
</code></pre></div></div>

<h4 id="fixing-a-misleading-warning-for-more-precise-patterns">Fixing a misleading warning for more precise patterns</h4>
<p>In case a “#RRRGGGBBB” or “#RRRRGGGGBBBB” pattern is used, the message would previously suggest using the constructor taking ints.
This would however result in an invalid QColor, because the range from 0-255 is exceeded. QRgba64 should be used instead, which provides higher precision.</p>

<hr />

<p>I hope you find this new or rather improved feature of Clazy useful! I utilized the fixits in Kirigami, see https://invent.kde.org/frameworks/kirigami/-/commit/8e4a5fb30cc014cfc7abd9c58bf3b5f27f468168.
Doing the change manually in Kirigami would have been way faster, but less fun. Also, we wouldn’t have ended up with better tooling :)</p>]]></content><author><name>Alexander Lohnau</name></author><summary type="html"><![CDATA[Improving the qcolor-from-literal Clazy check]]></summary></entry><entry><title type="html">Cleaning up KDE’s metadata - the little things matter too</title><link href="https://alex1701c.github.io/2024/01/02/kde-json-metadata.html" rel="alternate" type="text/html" title="Cleaning up KDE’s metadata - the little things matter too" /><published>2024-01-02T00:00:00+00:00</published><updated>2024-01-02T00:00:00+00:00</updated><id>https://alex1701c.github.io/2024/01/02/kde-json-metadata</id><content type="html" xml:base="https://alex1701c.github.io/2024/01/02/kde-json-metadata.html"><![CDATA[<h2 id="cleaning-up-kdes-metadata---the-little-things-matter-too">Cleaning up KDE’s metadata - the little things matter too</h2>

<p>Lots of my KDE contributions revolve around plugin code and their metadata, meaning I have a good overview of where and how metadata is used.
In this post, I will highlight some recent changes and show you how to utilize them in your Plasma Applets and KRunner plugins!</p>

<h3 id="applet-and-containment-metadata">Applet and Containment metadata</h3>

<p>Applets (or Widgets) are one of Plasma’s main selling points regarding customizability.
Next to user-visible information like the name, description and categories, there is a need for some technical metadata properties.
This includes <code class="language-plaintext highlighter-rouge">X-Plasma-API-Minimum-Version</code> for the compatible versions, the ID and the package structure, which should always be “Plasma/Applet”.</p>

<p>For integrating with the system tray, applets had to specify the <code class="language-plaintext highlighter-rouge">X-Plasma-NotificationArea</code> and <code class="language-plaintext highlighter-rouge">X-Plasma-NotificationAreaCategory</code> properties.
The first one says that it may be shown in the system tray and the second one says in which category it belongs. But since we don’t want any applets
without categories in there, the first value is redundant and may be omitted! Also, it was treated like a boolean value, but only <code class="language-plaintext highlighter-rouge">"true"</code> or <code class="language-plaintext highlighter-rouge">"false"</code> were expected.
I stumbled upon this when correcting the types in metadata files.<br />
This was noticed due to preparations for improving the JSON linting we have in KDE. I will resume working on it and might also blog about it :).</p>

<p>What most applets in KDE specify is <code class="language-plaintext highlighter-rouge">X-KDE-MainScript</code>, which determines the entrypoint of the applet.
This is usually “ui/main.qml”, but in some cases the value differs. When working with applets, it is confusing to first have to look at the
metadata in order to find the correct file. This key was removed in Plasma6 and the file is always <code class="language-plaintext highlighter-rouge">ui/main.qml</code>.
Since this was the default value for the property, you may even omit it for Plasma5.<br />
The same filename convention is also enforced for QML config modules (KCMs).</p>

<p>What all applets needed to specify was <code class="language-plaintext highlighter-rouge">X-Plasma-API</code>. This is typically set to <code class="language-plaintext highlighter-rouge">"declarativeappletscript"</code>,
but we de facto never used its value, but enforced it being present. This was historically needed because in Plasma4, applets could
be written in other scripting languages. From Plasma6 onward, you may omit this key.</p>

<p>In the Plasma repositories, this allowed me to clean up over 200 lines of JSON data.</p>

<h4 id="metadatadesktop-files-of-plasma5-addons">metadata.desktop files of Plasma5 addons</h4>

<p>Just in case you were wondering: We have migrated from metadata.desktop files to only metadata.json files in Plasma6.
This makes providing metadata more consistent and efficient. In case your projects still use the old format, you can run <code class="language-plaintext highlighter-rouge">desktoptojson -i pathto/metadata.desktop</code>
and remove the file afterward.<br />
See https://develop.kde.org/docs/plasma/widget/properties/#kpackagestructure for more detailed information. You can even do the conversion when targeting Plasma5 users!</p>

<h3 id="default-object-path-for-krunner-dbus-plugins">Default object path for KRunner DBus plugins</h3>

<p>Another nice addition is that “/runner” will now be the default object path. This means you can omit this one key.
Check out the template to get started: https://invent.kde.org/frameworks/krunner/-/tree/master/templates/runner6python.
DBus-Runners that worked without deprecations in Plasma5 will continue to do so in Plasma6!
For C++ plugins, I will make a porting guide like blog post soonish, because I have started porting my own plugins to work with Plasma6.</p>

<hr />

<p>Finally, I want to wish you all a happy and productive new year!</p>]]></content><author><name>Alexander Lohnau</name></author><summary type="html"><![CDATA[Cleaning up KDE’s metadata - the little things matter too]]></summary></entry><entry><title type="html">Reworking Recent Files search for Plasma 6</title><link href="https://alex1701c.github.io/2023/10/26/krunner-recentfiles.html" rel="alternate" type="text/html" title="Reworking Recent Files search for Plasma 6" /><published>2023-10-26T00:00:00+00:00</published><updated>2023-10-26T00:00:00+00:00</updated><id>https://alex1701c.github.io/2023/10/26/krunner-recentfiles</id><content type="html" xml:base="https://alex1701c.github.io/2023/10/26/krunner-recentfiles.html"><![CDATA[<h2 id="reworking-recent-files-search-for-plasma-6">Reworking Recent Files search for Plasma 6</h2>

<p>For Plasma 6, lots of KRunner plugins and framework functionalities were improved.
I took quite a bit of time to work on the recent files search plugin used by KRunner and Plasmas application launchers like Kickoff. This included performance improvements, usability improvements and technical refactorings.</p>

<p>Let’s start off with the usability improvements: While the runner was named “Recent Files”, it still provided results for directories.
In Dolphin on the other hand, “Recent Locations” are a separate location you may access next to “Recent Files”.
Luckily, functionality for only querying files already exists in the KActivities-Stats framework :).<br />
The search for files was also improved. Natalie Clarius added some time ago a patch to avoid false positives when the query is part of the file path.
For example, when you type for “myfile” and “/home/user/myfiles/test” was a recent file, this file would be returned by the KActivities-Stats framework.
With Natalie’s logic, those files would not be shown in KRunner, but still they fill out the limit of recent files we want to query.
Of course, one could look for more files in case we discarded too many, but that can cause a performance penalty due to additional SQL queries.<br />
Instead, I have added the ability to filter by the filename in KActivities-Stats. This means false positives are always avoided, and you will for sure get the results you are looking for!</p>

<p>Another useful, but not yet user-facing change is special handling for queries shorter than 3 characters. For those queries, a substring check would cause too many unintended results to be useful.
Instead, the filename must start with your given query. Similar to how the Applications-runner handles it.
There are plans to make this feature more easily accessible, but for now, it can only be done on the command line using <code class="language-plaintext highlighter-rouge">krunner --runner=krunner_recentdocuments</code>.</p>

<p><img src="https://i.imgur.com/PhMaas4.png" alt="Example of single-plugin mode" /><br />
<em>Screenshot of KRunner in single-plugin mode with the recent files plugin</em></p>

<p>The final issue that everyone will benefit from being fixed is a memory leak. This means for each letter typed, the runner would allocate a bit more RAM for results from the query. This can add up over time in KRunner and Plasmashell.
The KActivities-Stats that were “leaking” also caused CPU overhead, because they were notified about changes to the recent files list – even though they were never used again.<br />
Luckily, you don’t have to worry about that at all from now on :).</p>

<h3 id="optimizations">Optimizations</h3>

<p>Let us start with the small improvements: In my previous posts, I mentioned that constructing a QueryMatch object before being sure that the
current item (application or systemsettings module) matches, causes a performance overhead.
The same applied to the recent files plugin, because we discarded some files due to the false positive detection mentioned above.<br />
Getting the filename was also optimized/simplified, because instead of using Qt API to get the filename from the URL, we can just use the resource title from KActivities-Stats.<br />
String comparisons were speed up by reusing the results. For example, when checking if the filename contains the query, we can get the resulting index. If that index is 0, the query is contained and the filename also starts with it.
Meaning we’d only do one string comparison for each recent file instead of up to 4.</p>

<p>Getting the appropriate icon is also way faster, because previously a method from KIO was used, which gets the file path, checks some extra cases, but usually gets the icon for the determined mime type.
Because the extra cases were not relevant when only allowing files, we can directly get the icon for the respective mimetype. Luckily, we don’t even need to determine the mimetype, because the model already contains it.</p>

<h4 id="reusing-previously-fetched-data">Reusing previously fetched data</h4>
<p>This is the most interesting part and was my original idea to improve performance: In KDE Frameworks 6, each runner lives in its own thread. Meaning, one may access member variables in a thread safe way.
The data we want to reuse is the KActivities-Stats ResultsModel. This contains paths and additional metadata of recently used files. The number of files is limited to 20, which is the maximum number of entries is KRunner.<br />
Implementing was straightforward: If one previously typed “firef” and after that “firefox”, the previous model can be reused as long as the limit of 20 did not exceed the previously found results.
In addition to reusing the data, it is required to check the filenames again, because a file called “firef.test” should not match a query called “firefox”.
Due to the preexisting logic to determine the match relevance, this is minimal additional work.<br />
When measuring the real-world impact, it is important to note that fetching results from KActivities SQLite database is the most expensive part. Accessing the model is relatively cheap.
Meaning the longer your queries are and if long as the number of results was not exceeded, your performance gains will be significant!</p>

<p><img src="https://i.imgur.com/9x605pY.png" alt="Unoptimized" />
<em>Profiling of the unoptimized version, loading the correct Icon takes a large porting of CPU cycles</em>
<img src="https://i.imgur.com/bCxklII.png" alt="Optimized" />
<em>Optimized version, CPU cycles are significantly reduced and loading of icons is barely distinguishable from other, minor costs</em></p>

<p>In benchmarks, one is able to see that the CPU cycles with this patch are roundabout the same among the different measurements, whereas the CPU cycles before this patch correlated with the length of the query.
The query was typed in letter by letter, keep in mind that the runner skips queries shorter than 3 characters unless the single runner mode is activated.
For benchmarks, I decided against activating this mode, because it is not the normal usecase.</p>

<table>
  <thead>
    <tr>
      <th>Query</th>
      <th>CPU Cycles before</th>
      <th>CPU Cycles with change</th>
      <th>Reduction</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>mytextfile</td>
      <td>1.73E+10</td>
      <td>3.592E+09</td>
      <td>79%</td>
    </tr>
    <tr>
      <td>user</td>
      <td>8.291E+09</td>
      <td>3.148E+09</td>
      <td>62%</td>
    </tr>
    <tr>
      <td>firefox</td>
      <td>1.325E+10</td>
      <td>3.601E+09</td>
      <td>73%</td>
    </tr>
  </tbody>
</table>]]></content><author><name>Alexander Lohnau</name></author><summary type="html"><![CDATA[Reworking Recent Files search for Plasma 6]]></summary></entry></feed>