Skip to content

Thursday, 7 August 2025

During all my time with KDE projects, I've never made an app from scratch.. Except now.

Today my first KDE app ever, KomoDo, was released on Flathub!

Screenshot of the KomoDo todo.txt application

It's a simple todo application for todo.txt format and parses todo.txt files into a list of cards. One task is one card.

The application has help sections for any of the rules todo.txt format follows, but you can use as many or as little of them as you want.

I wanted to go through in this blogpost about the process, or what I remember of it anyway. I've always just fixed bugs in Plasma or Frameworks or even in apps like Dolphin, but never made anything from scratch. So I thought that writing this down might be helpful for someone in similar position.

As with any KDE project, it's open source and the repository can be explored right here: utilities/komodo.

Starting up

Starting a Qt project using KDE libraries, especially QtQuick, is not that difficult in the end. KDE has really good documentation for starting up. I mostly followed this guide to get started: https://develop.kde.org/docs/getting-started/kirigami/setup-cpp/

There is also guides for Python and Rust if you wish to use those instead of C++.

I also highly recommend using kde-builder for building and running the applications. It makes things so much easier.

Other than that, there's not much to tell about the setup.

The project itself

Working on the application was not that bad either. I've worked on various C++ and QML files during my work on KDE software, so I had easy time getting into the flow.

I think the most difficult part for me was the CMake files: I couldn't really understand them or what they do, I mostly followed what other projects did and replicated them.

This of course caused me to do unnecessary things, like installing libraries I made for the app: TodoModel which the QML code uses to parse the todo.txt file and generate the view was accidentally installed among the system libraries, which was not ideal, since I'm not building a framework.

Luckily with tons of help and reviews from my friends in the KDE fam, we got CMake to build things nicely. Then with kde-builder the feedback loop of code->build->test was fast enough, especially in small app like this, that I could iterate on the application in a good pace.

I also had a lot of help from a friend with the CI and sysadmin stuff. That side of development is very confusing to me so I'm glad with the help. I dunno if you want to be named so I didn't, but you know who you are: Big thanks. :)

TodoModel

Since Qt is reliant on the model-view system, I had to make a "model" that parses the todo.txt file and spits out Todo objects, which can then be parsed by the QML code, which is the frontend code.

If you have never worked on model-view systems, it can take some time to understand. To me, the model-view as words was always a bit confusing: I would have understood it better if it was worded something like data-ui. But tech jargon has always been my weakest point.

The parsing is done by a RegExp nightmare I concocted with help of stack-overflow and tears.

Here it is, in its nightmarish glory, enjoy the nightmare fuel:

QStringLiteral("(?:^[ "
	"\\t]*(?P<Completion>x))|(?P<Priority>\\([A-Z]\\))|(?:(?P<FirstDate>"
	"\\d{4}-\\d\\d-\\d\\d)[ "
	"\\t]*(?P<SecondDate>\\d{4}-\\d\\d-\\d\\d)?)|(?P<Projects>\\B\\+[\\w\\d\\S]+)|(?P<"
	"Contexts>(?<=\\s)@[^\\s]+)|(?P<KeyValuePairs>[a-zA-Z]+:[\\S]*)");

Yyyeah. It's.. Something.

Testing

Due to the nightmare fuel that RegExp can be, I decided that unit testing would be great addition. So I fought with CMake a bit and then made myself a proper parser testing file.

Thankfully Qt has nice QTest library that can be used to create tests. They can be hard to parse at first, but when you understand how they work, they're really quick and easy to work with.

Testing saved my rear a few times during this project, especially when modifying anything parser related.

Look and feel

When the model worked fine, I started concentrating more on the look and feel of the app.

The application went through various phases: At first, everything was done through a dialog, except viewing the cards. It was kind of distracting that every time you wanted to modify or make new task, the application would pop things up.

Over time though, I think I got it into a good spot: Most actions can be done in the task list, but when user wants to delete a task, the app asks the user first if they are sure about it.

Then there is help menu and quick info for syntax related things.

Otherwise there's really no settings: I did not want to add any settings if I could avoid it. The only setting the app saves to config file is the file you opened last time.

I also consulted the KDE Human Interface Guidelines (HIG) few times, but it was never "in the way." It just helped me to make decisions sometimes when I wasn't sure what to do with the design.

Also my lovely wife @tecsiederp made the application the most adorable icon ever.

Cute green lizard holding a todo sign

Look at it. Just a lil guy.

Also, if you don't get your tasks done, he will get sad. So you better do those tasks!

It just makes me so happy and motivated to work on my tasks when I see this lil guy in my taskbar. :D

The icons however have to follow our guidelines, also mentioned in the HIG. Luckily my wife is good with SVG files, and if she wasn't I already had two people wanting to help me with it, which I very much appreciated. If I had to make an icon myself, it would.. Not be good. :P

Something I mostly struggled with though was getting a nice syntax highlighting for the task text. I wanted to use our KSyntaxHighlighting library, but it would not match all colorschemes: Users may use their own or third party colorscheme for the app, but the syntax highlighter does not have a colorscheme that matches it.. So it would look bit odd.

So I made my own simple one that appends some color tags to the string, and the QML engine does the rest. The text can have HTML tags like <span> in it which QML can parse automagically.

I think the app turned out to look pretty good. It also supports keyboard navigation for getting around the app. (Though there might be some bugs with it still.)

Releasing the app

KDE has documentation for the release process, so I just followed it to the letter. During the release process, I have to wait for at least 2 weeks for people to give me reviews, and so they did. And then I fixed things. And some more.

Eventually the app was good to go (though it was never directly told me, it was just implicitly agreed), and I followed the last bits of relese process, setting up signing keys and such.

And now it exists as a tarball here, so any interested distros can go grab it: https://download.kde.org/stable/komodo/1.0.0/

I also recommend this patch to go with it, to make sure it doesn't install the static libraries in the system: https://invent.kde.org/utilities/komodo/-/commit/57c6fa82719155bd32cb35b4c64cddae956c53e0

With Flathub, the submission process was rather painless in my opinion. I followed their requirements and submission documentation and it all just clicked together. Eventually someone was reviewing my PR and then.. The app is in Flathub. I had to make a patch for Flathub specifically, but it was also really painless so I didn't mind.

What it all mostly took from me is time. Otherwise it was just nice and easy.

More apps?

So at least in my experience, the whole process was rather easy. I didn't want to go into nitty gritty details too much.. Because I don't remember everything + you can see the source code + the process itself happens in the open.

I'm definitely interested in making more KDE apps, but also I have my game project(s).

And I really want to get back into gamedev. Like spend much more time into it.

At least now I have a todo app which fits my needs to keep track of the gamedev projects. :)

Thanks for reading! And if you're looking for new todo application, give KomoDo a try! :)

Monday, 4 August 2025

I write this in the wake of a personal attack against my work and a project that is near and dear to me. Instead of spreading vile rumors and hearsay, talk to me. I am not known to be ‘hard to talk to’ and am wide open for productive communication. I am disheartened and would like to share some thoughts of the importance of communication. Thanks for listening.

Open source development thrives on collaboration, shared knowledge, and mutual respect. Yet sometimes, the very passion that drives us to contribute can lead to misunderstandings and conflicts that harm both individuals and the projects we care about. As contributors, maintainers, and community members, we have a responsibility to foster environments where constructive dialogue flourishes.

The Foundation of Healthy Open Source Communities

At its core, open source is about people coming together to build something greater than what any individual could create alone. This collaborative spirit requires more than just technical skills—it demands emotional intelligence, empathy, and a commitment to treating one another with dignity and respect.

When disagreements arise—and they inevitably will—the manner in which we handle them defines the character of our community. Technical debates should focus on the merits of ideas, implementations, and approaches, not on personal attacks or character assassinations conducted behind closed doors.

The Importance of Direct Communication

One of the most damaging patterns in any community is when criticism travels through indirect channels while bypassing the person who could actually address the concerns. When we have legitimate technical disagreements or concerns about someone’s work, the constructive path forward is always direct, respectful communication.

Consider these approaches:

  • Address concerns directly: If you have technical objections to someone’s work, engage with them directly through appropriate channels
  • Focus on specifics: Critique implementations, documentation, or processes—not the person behind them
  • Assume good intentions: Most contributors are doing their best with the time and resources available to them
  • Offer solutions: Instead of just pointing out problems, suggest constructive alternatives

Supporting Contributors Through Challenges

Open source contributors often juggle their community involvement with work, family, and personal challenges. Many are volunteers giving their time freely, while others may be going through difficult periods in their lives—job searching, dealing with health issues, or facing other personal struggles.

During these times, our response as a community matters enormously. A word of encouragement can sustain someone through tough periods, while harsh criticism delivered thoughtlessly can drive away valuable contributors permanently.

Building Resilient Communities

Strong open source communities are built on several key principles:

Transparency in Communication: Discussions about technical decisions should happen in public forums where all stakeholders can participate and learn from the discourse.

Constructive Feedback Culture: Criticism should be specific, actionable, and delivered with the intent to improve rather than to tear down.

Recognition of Contribution: Every contribution, whether it’s code, documentation, bug reports, or community support, has value and deserves acknowledgment.

Conflict Resolution Processes: Clear, fair procedures for handling disputes help prevent minor disagreements from escalating into community-damaging conflicts.

The Long View

Many successful open source projects span decades, with contributors coming and going as their life circumstances change. The relationships we build and the culture we create today will determine whether these projects continue to attract and retain the diverse talent they need to thrive.

When we invest in treating each other well—even during disagreements—we’re investing in the long-term health of our projects and communities. We’re creating spaces where innovation can flourish because people feel safe to experiment, learn from mistakes, and grow together.

Moving Forward Constructively

If you find yourself in conflict with another community member, consider these steps:

  1. Take a breath: Strong emotions rarely lead to productive outcomes
  2. Seek to understand: What are the underlying concerns or motivations?
  3. Communicate directly: Reach out privately first, then publicly if necessary
  4. Focus on solutions: How can the situation be improved for everyone involved?
  5. Know when to step back: Sometimes the healthiest choice is to disengage from unproductive conflicts

A Call for Better

Open source has given us incredible tools, technologies, and opportunities. The least we can do in return is treat each other with the respect and kindness that makes these collaborative achievements possible.

Every contributor—whether they’re packaging software, writing documentation, fixing bugs, or supporting users—is helping to build something remarkable. Let’s make sure our communities are places where that work can continue to flourish, supported by constructive communication and mutual respect.

The next time you encounter work you disagree with, ask yourself: How can I make this better? How can I help this contributor grow? How can I model the kind of community interaction I want to see?

Our projects are only as strong as the communities that support them. Let’s build communities worthy of the amazing software we create together.

https://gofund.me/506c910c

Tellico 4.1.3 is available, with a few fixes.

Improvements

  • Updated SRU fetcher to allow POST requests (Bug 507265).
  • Updated SRU fetcher to recognize alternate Dublin Core schema.
  • Updated OpenLibrary source to fetch work author (Bug 504586).
  • Fixed a bug with reporting correct image location.

You click a link in your chat app, your browser with a hundred tabs comes to the front and opens that page. How hard can it be? Well, you probably know by now that Wayland, unlike X, doesn’t let one application force its idiot wishes on everyone else. In order for an application to bring its window to the front, it needs to make use of the XDG Activation protocol.

KWrite (text editor) window, window has no focus (colors are softened). Task bar with a couple of apps, KWrite icon has an orange background behind it, indicating KWrite is demanding attention
A KWrite window that failed to activate and instead is weeping bitterly for attention in the task bar

In essence, an application cannot take focus, it can only receive focus. In the example above, your chat app would request an XDG Activation token from the compositor. It then asks the system to open the given URL (typically launching the web browser) and sends along the token. The browser can then use this token to activate its window.

This token is just a magic string, it doesn’t matter how it gets from one application to another. Typically, a new application is launched with the XDG_ACTIVATION_TOKEN variable in its environment. When activating an existing one, an activation-token property is added to the platform_data dict sent via DBus. There’s also older protocols that weren’t designed with this in mind, such as Notifications, StatusNotifierItem (tray icons), or PolKit requests where we cannot change the existing method signatures. Here we instead added some way to set a token just before the actual call.

However, just because you have a token doesn’t mean you can raise your window! The compositor can invalidate your token at any time and reject your activation request. The idea is that the compositor gets enough information to decide whether the request is genuine or some application popping up a dialog in the middle of you typing something. A token request can include the surface that requests the activation, the input serial from the focus or mouse event that resulted in this request, and/or the application ID of the application that should be activated. While all of this is optional (and there can be valid reasons why you don’t have a particular piece of information at this time), the compositor is more likely to decline activation if the information is incomplete or doesn’t match what the requesting application provided.

A lot of places in Qt, KDE Frameworks, and other toolkits and applications have already been adjusted to this workflow and work seamlessly. For example, calling requestActivate on a QWindow will check if there is an XDG_ACTIVATION_TOKEN in the environment and use it, otherwise request one. Qt also does this automatically when the window opens to match the behavior of other platforms. Likewise, things like ApplicationLauncherJob and OpenUrlJob will automatically request a token before proceeding. On the other hand, KDBusService (for implementing single instance applications) automatically sets the corresponding environment variable when it received a token via DBus. Together this makes sure that most KDE applications just work out of the box.

You might be wondering: didn’t KWin-X11 have “focus stealing prevention”? It sure does. There’s a complicated set of heuristics based on _NET_WM_USER_TIME to judge whether the new window appeared as a result of explicit user interaction or is unsolicited. Remember how back in ye olde days, KWin’s focus stealing prevention would keep the Adobe Flash Player fullscreen window from showing ontop of the YouTube video you’re watching? Yeah, it’s not perfect. KWin can also only react on things that have already happened. For instance, when an application uses XSetInputFocus on a window from a different application, KWin will detect that and consider it a malicious request and restore previous focus but for a split second focus did change. If you want to know more, there’s a 200+ lines comment in activation.cpp in KWin’s git repo that explains it all. But then again the application could just do whatever it wants and bypass all of this.

“Window Behavior” configuration dialog, various window-related tabs and options, mouse cursor pointing at a combo box “Focus stealing prevention” whose current item is “Extreme”
Xtreme Focus Stealing Prevention™

Unfortunately, there’s still a few places that don’t do XDG Activation correctly. It didn’t matter much under X – in doubt we could just forceActiveWindow – but now we have to fix those scenarios properly! In order to test whether your application is well-behaved, use the latest git master branch of KWin and set “Focus Stealing Prevention” in Window Management settings to “Extreme”. This will make KWin activate a window if and only if it requests activation with a valid token.

Using this, over the past couple of days Xaver Hugl of KWin fame and I fixed a bunch of issues, including but not limited to:

  • Dolphin threw away its token before activating its main window when launching a new instance (activating an existing one worked fine)
  • KRunner, Kickoff, and other Plasmoid popups did not request activation at all
  • LayerShell-Qt now requests activation on show (to match Qt behavior)
  • LayerShell-Qt didn’t read the XDG_ACTIVATION_TOKEN from the environment when provided
  • Privileged clients, like Plasma and KGlobalAccel, were unable to request tokens in some situations
  • Modifier key presses no longer count towards focus stealing prevention: they’re often used as part of a global keyboard shortcut and don’t necessarily mean the user is interacting with the active window

Furthermore, the DBusRunner specification gained a SetActivationToken method which is called just before Run. Baloo (desktop search) runner now uses this to ensure opening files in an existing application window works. Likewise for the KClock runner bringing KClock to the front properly. I further improved the recent documents runner and places runner to send the file type to the OpenUrlJob so it doesn’t have to determine it again. This makes the job much quicker and avoids KRunner closing before the activation token is requested by the job. However, we have yet to find a proper solution for this in KRunner.

With all of this in place, we’ll likely switch on KWin’s focus stealing on Wayland at a low level and make it gradually stricter as applications are being fixed.

Intro

After adding the ability to drag and reposition the Selection Action Bar on the canvas last week, I spent this week improving that interaction. I tackled the issue where users could drag the toolbar completely off-screen, making it inaccessible. This week was all about keeping the toolbar within the canvas boundaries.

Side note: This week I also updated the UI to resemble the mockup concept provided from the community.

Obstacles to Implementation

During testing I noticed that without boundaries, the draggable toolbar could end up hidden and inaccessible especially after window or sidebar resizing. This would make it frustrating for users because they would have to find the missing toolbar or toggle the feature off and back on just to relocate it. I wanted to make the toolbar's positioning restricted to canvas boundaries to keep the toolbar within users' vision.

Find Canvas Boundaries

Looking into the code, I found that the canvasWidget had a property QRect rect() which holds the dimensions of the canvas. We can use these values as the boundaries.

Add Boundaries to Drag Event

With canvasBounds defined, we can limit the drag operation to stay within the canvas dimensions. Based on the current canvas dimensions and during a drag event, we update the horizontal and vertical limits of the toolbar position with the use of qBound which provides an upper and lower boundary for a value. So if the coordinates of the toolbar were to go past the boundaries, qBound would return the defined upper or lower boundary value. On top of canvas boundaries, it is important to include the dimensions of the toolbar and buffer room in the calculation to make sure the UI elements are accessible.

// updated drag event with canvas boundaries
QPoint newPos = mouseEvent->pos() - d->dragStartOffset;

 QRect canvasBounds = canvasWidget->rect();
 int actionBarWidth = 125;
 int actionBarHeight = 25;
 int bufferSpace = 5;
 newPos.setX(qBound(canvasBounds.left() + bufferSpace, newPos.x(), canvasBounds.right() - actionBarWidth - bufferSpace));
 newPos.setY(qBound(canvasBounds.top() + bufferSpace, newPos.y(), canvasBounds.bottom() - actionBarHeight - bufferSpace));

 d->dragRectPosition = newPos;
 canvasWidget->update();
 return true;

Conclusion

This week was focused on improving the user experience and accessibility of the Selection Action Bar. I learned about some great Qt tools, like the properties of QWidget and Qt helper functions like qBound to help solve my problem! In the coming final weeks, I'll continue adding action buttons based on the list provided by the community.

Contact

To anyone reading this, please feel free to reach out to me. I'm always open to suggestions and thoughts on how to improve as a developer and as a person.
Email: ross.erosales@gmail.com
Matrix: @rossr:matrix.org

Wednesday, 30 July 2025

The future is now!!

It’s been almost two years since my last update on this project, what changed? And if you aren’t familiar with what I’ve been working on, here’s a quick recap.

The hardware

Here is a graphics tablet I bought a few years ago now, the XP-Pen Artist 22R Pro:

Yeah this picture is years old by now, but it still looks the same…

It has a fatal flaw that a lot of non-Wacom tablets share though, it doesn’t work that well on Linux! To be more specific, it “works” but has a few problems:

  • You can’t rebind the pad buttons easily, because it starts in a “compatibility mode” that can only send pre-defined keyboard buttons.
  • Using the second stylus button prevents further stylus input. (Before I fixed that, I would train myself not to press that button 🙈)
  • The two dials do not function, and if they did they aren’t rebindable anyway.

That is not great, especially since it’s not the cheapest graphics tablet on the market. So it really sucks that artists can’t take advantage of all of it’s features on the best operating system. You can achieve some parity with Windows if you use XP-Pen’s proprietary user-space driver (which works on Wayland BTW.) This solution isn’t satisfying though - I want this thing to work out of the box, using open-source software ❤️

Linux

I have completed the patch for the kernel to add support for this specific tablet. After sitting it on it for a while (due to being busy with other things.) I’m happy to announce it’s merged and should be generally available in the upcoming Linux 6.17 release 🎉

Thank you to the original author Aren Villanueva who wrote the original DIGImend kernel driver. I took his work, rebased it on top of the existing uclogic driver and changed how the many keys and dials were handled among other changes. Some of this work was covered in previous entries in this series, if you’re interested.

What this means is regardless of your desktop environment, this tablet is properly initialized and all of the flaws listed in the hardware section will be fixed.

libwacom

I added a descriptor to libwacom for this tablet, which means it shows the correct configuration options under KDE Plasma and GNOME. For example, it will show that the pen has two buttons and not three (which is the fallback):

libinput

I added support for tablet dials in libinput. In layman terms, this means desktop environments like GNOME and KDE are now aware of this feature on your tablet. This has huge implications outside of this specific tablet, for example certain HUION devices also benefit from this. More information on how KDE Plasma uses this is explained in a later section.

Wayland

Thanks to work by Peter Hutterer, the Tablet protocol in Wayland now has support for tablet dials. What this means is that applications can now read tablet dial input and do whatever they want with it, like making it zoom in and out of a canvas.

KDE Plasma

Thanks to work by Nicolas Fella, KWin (the compositor in KDE Plasma) is now dial-aware and can send them to Wayland-enabled applications beginning in Plasma 6.4. Because of the aformentioned lack of application support however, I added a feature in KDE Plasma 6.5 to rebind dials to custom user actions:

Don’t mind the buggy-looking dialog, that is caused by a development version of Kirigami I was using.

The XP-PEN software allows you to do this too, so having a built-in solution in KDE Plasma would be great! I did just that, and added support for rebinding dials which will show up in the upcoming KDE Plasma 6.5 release. Making them user configurable is meant as a “bridge”, as I’m not aware of any applications supporting dials yet.

With this final piece - from top-to-bottom - the entire Linux graphics tablet stack can now take advantage of relative dials like any other hardware feature 🎉

Conclusion

I want to make it clear (especially if you don’t know me) that this isn’t some hack, or a rushed driver. This is thanks to years of effort, and from multiple parties and ecosystems. I also literally use this driver and KDE Plasma for my hobbies every day, I know it works first-hand.

I also hope this series showcases that the graphics tablet infrastructure in Linux is not stagnant, but actively being worked on by super-talented people every day. In a theoretical future distribution release that has Linux 6.17 and KDE Plasma 6.5, this tablet will work out-of-the-box. (And for other hardware, it’s only a matter of time!) We can make the Linux desktop not just usable for artists, but we can executing it better than anything else out there. No more crappy driver software, tablets will work out of the box on an operating system that actually respects you ❤️

To Nicolas, Peter and Aren - you can redeem a beer or drink of choice at your earliest convenience 🍻


If this series has been fascinating for you, then I highly suggest making plans to watch my Akademy 2025 talk in Berlin or online about bridging the gap for artists using Linux and KDE Plasma. I’m going to be covering the amazing progress - especially in our KDE Plasma 6.x series - that’s relevant to artists big and small, and also discuss plans for the long road ahead. You also need to follow the KDE account on Mastodon and Bluesky if you haven’t already, where we post announcements and sometimes call-to-actions like our recent push to contribute data about graphics tablet hardware!

I also want to remind everyone that one of KDE’s current goals is about input, and as it’s Goal Champion I’ve been volunteering and organizing to fix issues like the ones seen above. If you are having trouble with your graphics tablet on the KDE Plasma Wayland session (and it’s our fault) then we want to know! Or if you’re super happy with KDE and nothing is wrong, we wouldn’t mind hearing about that was well 🐸

If you’re still addicted to me hearing me talk about improving stuff, here is a sneak peek of the hardware I’m testing in KDE Plasma next:

Sorry that the HUION tracks fingerprints like crazy

But that’s for another time!

Tuesday, 29 July 2025

Intro

Apart from setting up a new open source project, it is important to understand how the application works in order to make the changes you need. In this blog I will go over how I find code, understand the application, and my progress so far with the Selection Action Bar.

Searching code

One Stop Shop for Searching

Command Line

grep -rn "<string_to_search>"

QTCreator

ctrl + f
crtl + shift + f

Debug in C++ code

qDebug() << "[Debug] <string_to_display_for_debugger> << <additional_parameters>;

Krita's codebase is massive, so don't expect to understand everything in one day. What is important is knowing how to find code you need to make the improvements you want. Above are some tools I use when looking for code. I would use the command line or QTCreator search functionality to reverse search strings that are displayed in Krita. This helps me find buttons, dropdowns, and tools. When I want to understand the functionality of the application, I will add qDebug in the code. This allows me to perform an action when Krtia is running and display debug information about the functions I added qDebug to.

Progress

Through the use of the the useful tools above, I was able to make the base UI of the floating toolbar in Krita by identifying QPainter class that created the Assistant Tool. I wanted to use Assistant tool as a reference and recreate a similar UI look. For quick learning purposes and proof of concept, when an Assistant Tool widget is active, the floating toolbar is also generated on screen.

Below is a proof of concept for the Selection Action Bar. I used QPainter to 'draw' onto the KisCanvas2 class. This is like using a paintbrush (QPainter) and painting on a canvas (KisCanvas2). There will still need to be some more UI clean up, however I wanted to present my learnings so far.

Conclusion

Making changes in Krita can be challenging, but by using a few simple tools it can make hours turn into minutes for searching what you need. Again, "the hardest part is finding the resources to be successful". I hope this blog post helps whoever is in need of searching Krita or any C++ codebase.

Contact

To anyone reading this, please feel free to reach out to me. I’m always open to suggestions and thoughts on how to improve as a developer and as a person.
Email: ross.erosales@gmail.com
Matrix: @rossr:matrix.org

Monday, 28 July 2025

Dear friends, family, and community,

I’m reaching out during a challenging time in my life to ask for your support. This year has been particularly difficult as I’ve been out of work for most of it due to a broken arm and a serious MRSA infection that required extensive treatment and recovery time.

Current Situation

While I’ve been recovering, I’ve been actively working to maintain and improve my professional skills by contributing to open source software projects. These contributions help me stay current with industry trends and demonstrate my ongoing commitment to my field, but unfortunately, they don’t provide the income I need to cover my basic living expenses.

Despite my efforts, I’m still struggling to secure employment, and I’m falling behind on essential bills including:

  • Rent/mortgage payments
  • Utilities
  • Medical expenses
  • Basic living costs

How You Can Help

Any financial assistance, no matter the amount, would make a meaningful difference in helping me stay afloat during this job search. Your support would allow me to:

  • Keep my housing stable
  • Maintain essential services
  • Focus fully on finding employment without the constant stress of unpaid bills
  • Continue contributing to the open source community

Moving Forward

I’m actively job searching and interviewing, and I’m confident that I’ll be back on my feet soon. Your temporary support during this difficult period would mean the world to me and help bridge the gap until I can secure stable employment.

If you’re able to contribute, GoFundMe . If you’re unable to donate, I completely understand, and sharing this request with others who might be able to help would be greatly appreciated.

Thank you for taking the time to read this and for considering helping me during this challenging time.

With gratitude, Scarlett

Intro

This week I focused on making the Selection Action Bar draggable directly on the canvas. This would let the user reposition the toolbar that is best for their workflow.

Obstacles to Implementation

Up to this point adding elements on Krita using Qt was straightforward however making these elements interact and respond to mouse click events needed some deeper diving. The goal of this part of the Selection Action Bar was to allow users to click and drag the tool to reposition it anywhere within the canvas. In order to implement this I asked myself some questions: Where does Qt handle click events? How can the UI elements dynamically update their position?

Event Filters and Mouse Events

Documentation Links https://doc.qt.io/qt-6/eventsandfilters.html
https://doc.qt.io/qt-5.15/events.html
https://doc.qt.io/qt-5/qobject.html#installEventFilter

My research led me to Qt’s event system. One of the key concepts I learned about was event filters. Event filters are able to intercept events that are sent to another object. In our case, we can intercept the click events that are sent to the canvas and process that event to update the positions of our floating toolbar.

Since canvas was passed in through the KisSelectionAssistantsDecoration class, we can install an event filter on the canvas object, specifically the canvasWidget to intercept the mouse events.

// install event filter on canvasWidget, so KisSelectionAssistantsDecoration class (aka 'this') can look at event first
canvasWidget->installEventFilter(this);

After learning about event filters, I needed to learn how to handle the mouse events. By distinguishing user inputs of MouseButtonPress, MouseMove, and MouseButtonRelease, I was able to update the position of the floating bar. To keep things simple, imagine a rectangle on a 2D grid. Between the top left point of the rectangle and a point we click inside the rectangle is called an offset. This offset is to make sure that when we click and drag from within the rectangle, we are updating the position of the rectangle. Get offset = mouse position (click) - rectangle position
Update rectangle position = mouse position (click + drag) - offset
Mouse button release = stop updating rectangle

Working concept

With this major change, the Selection Action Bar is starting to feel like a full feature. Currently, we are able to activate selection actions, move the toolbar to a desirable position on canvas, and toggle it on and off via Krita settings.

Conclusion

This week really pushed me to explore how to handle events and how to make elements move in Krita! As I continue building out the Selection Action Bar every week, I start to understand how complex a ‘simple’ change could be. Next week I plan to improve on the movement of the toolbar by restricting its dragging area within the canvas.

Contact

To anyone reading this, please feel free to reach out to me. I’m always open to suggestions and thoughts on how to improve as a developer and as a person. Email: ross.erosales@gmail.com Matrix: @rossr:matrix.org