Playing with DBus and KDE applications (Part 2)

Updates

The following updates have been applied:

2022-01-26:
  • Warning box about the qdbus filename alternative

In a previous article I introduced the DBus technology and provided some examples built around the Klipper service to integrate the clipboard area within our scripts.

In this article, we will first introduce an approach to evaluate service names and paths that may vary as the application that register them is launched, and then we will see other useful DBus services and how to take advantage of them within our scripts.

Variable service names and paths

Not all the applications run as a single instance as Klipper does. To make a long story short there are applications that:

  • run multiple windows for each instance;
  • open a new tab for each content;
  • a mix of them, creating multiple multi-tab windows.

The difference between the two approaches, multiple windows vs. multiple tabs, is in the middle of the need for better memory management and interface usability.

A multiple tab application might be more or less comfortable to handle different contents at once, but for sure some memory location is saved if the same interface is instantiated once.

Some applications implement both approaches because usability is way more important than memory saving.

What’s important to know is how all that affects the D-Bus service to aim at every session created and correctly apply the wanted method:

  1. Multiple service name might be created containing a common static part separated from a numeric code by a dash - character (i.e. org.kde.konsole-1334, org.kde.kdialog-4821, org.kde.okular-54220, …), that code is the process id of the application itself;
  2. new paths might be added for each tab opened having a consecutive number as suffix (i.e. /Sessions/1, /Sessions/2, /Sessions/3, and so on).

Until we play in a terminal this is not an issue because we can manually detect the change just by typing the first part and completing with the Tab key, but in a script, we must find a method to gather the same parameters.

Warning!!!

In some KDE versions there is qtdbus-qt5 in place of qdbus, but the old file is still available and can be linked under the home bin path:

ln -s /usr/lib64/qt5/bin/qdbus ~/bin/qdbus

Otherwise just replace the qdbus filename with qtdbus-qt5 in the examples below.

To get the list of service names we can query the bus using a wildcard after the static part:

$ qdbus org.kde.konsole-*

or use the pgrep command to get all the possible PIDs:

$ pgrep konsole

At this point we can wrap all the values in a variable to reuse within our script, or select the first or the last item:

service_names=$(qdbus org.kde.konsole-*)
first=$(qdbus org.kde.konsole-* | head -n 1)
last=$(qdbus org.kde.konsole-* | tail -n 1)

In the second case instead, we might use the grep command to collect the available paths dynamically added:

$ qdbus org.kde.konsole-2428 | grep "/Sessions/[0-9]\+"

This is how we store the paths in a variable:

session_paths=$(qdbus org.kde.konsole-2428 | grep "/Sessions/[0-9]\+")

However, as we will see later, there is another way to get the sessions list and the current session in particular.

Wrapping up, the Konsole applications used in the examples above registers a service name for each running window, and a new session is added as a new service path for each opened tab or frame splitting.

We will see how Konsole and Yakuake share interesting D-Bus methods that might result useful to integrate within our service menus.

Konsole

Dolphin itself integrates a terminal that can be recalled pushing the key, and with the <Shift + F4> combination it is also able to open a Konsole terminal in the current path.

What Dolphin can’t do is to open a path, in the current or in a new session, using a running instance of Konsole.

On the other hand, the Konsole D-Bus offers methods to list and manipulate sessions within the opened windows.

For brevity, I will refer to the Konsole service name with the variable $service_name filled as seen above, and to the session path using the variable $session_path which contains one of the values of the $session_paths aforementioned (/Sessions/1, /Sessions/2, …).

Just to take confidence with it, let see a set of methods from the /Windows/1 path.

This path is rather standard and doesn’t change, it gives precious info about the sessions:

$ qdbus $service_name /Windows/1 org.kde.konsole.Window.sessionList

We can also get the current session index:

$ qdbus $service_name /Windows/1 org.kde.konsole.Window.currentSession

And open a new session:

$ qdbus $service_name /Windows/1 org.kde.konsole.Window.newSession

Having the current session id in a variable is as simple as:

session_id=$(qdbus $service_name /Windows/1 org.kde.konsole.Window.currentSession)

At this point, we have everything to open the current path in the current Konsole session and to do that we will run it as a command using the runCommand method:

$ qdbus $service_name /Sessions/$session_id runCommand "cd '/some/path'"

Thus, we can open a new session in the same window, without launching a new Konsole instance, and change the path with the aforementioned method:

$ session_id=$(qdbus $service_name /Windows/1 newSession)

$ qdbus $service_name /Sessions/$session_id runCommand "cd '/some/path'"

Unfortunately at the moment, I am writing this article some important methods are missing: those which allow splitting a terminal horizontally or vertically, methods that are implemented in the Yakuake terminal D-Bus service.

Yakuake

Yakuake and Konsole services are very similar also because Yakuake uses the same KDE component instantiated by Konsole to emulate a terminal inside its windows. That said the all the methods underneath the /Sessions/XXX path are the same, while in Yakuake the /Windows/XXX path looks a duplicate of /Sessions/XXX.

Querying the Yakuake D-Bus service will be easier:

  • The service name doesn’t change and it will be always org.kde.yakuake;
  • the methods used are collected under the fixed path /yakuake/sessions.

Another important difference to keep in mind is that Yakuake associates each session to a tab, and for each session, there is one or more terminals depending on how many frames it has been split.

So to open a path in the current terminal in the current session the code required is simpler than before:

$ qdbus org.kde.yakuake /yakuake/sessions org.kde.yakuake.runCommand "cd '/some/path'"

To open a path in a new tab or session instead:

$ qdbus org.kde.yakuake /yakuake/sessions org.kde.yakuake.addSession

$ qdbus org.kde.yakuake /yakuake/sessions org.kde.yakuake.runCommand "cd '/some/path'"

If we want to split the current terminal, we must first know its id

$ terminal_id=$(qdbus org.kde.yakuake /yakuake/sessions activeTerminalId)

Then, to split it vertically and open a path in the right terminal:

$ qdbus org.kde.yakuake /yakuake/sessions splitTerminalLeftRight $terminal_id 

$ qdbus org.kde.yakuake /yakuake/sessions runCommand "cd '/some/path'"

A similar approach is used to split the terminal horizontally and open the path in the bottom panel:

$ qdbus org.kde.yakuake /yakuake/sessions splitTerminalTopBottom $terminal_id

$ qdbus org.kde.yakuake /yakuake/sessions runCommand "cd '/some/path'"

There are also some other methods to add a session and split it vertically, horizontally, or both all at once:

$ qdbus org.kde.yakuake /yakuake/sessions addSessionTwoVertical

$ qdbus org.kde.yakuake /yakuake/sessions addSessionTwoHorizontal

$ qdbus org.kde.yakuake /yakuake/sessions addSessionQuad

Terminal and session ids can be listed with:

$ qdbus org.kde.yakuake /yakuake/sessions terminalIdList

$ qdbus org.kde.yakuake /yakuake/sessions sessionIdList

A terminal can be removed:

$ qdbus org.kde.yakuake /yakuake/sessions removeTerminal $terminal_id

And a session and its associated tab, can be brought to front:

$ qdbus org.kde.yakuake /yakuake/sessions raiseSession $session_id

The last method I want to share allows to toggle the window:

$ qdbus org.kde.yakuake /yakuake/window toggleWindowState

Final thoughts

We this article I provided all the hints to easily handle a particular kind of D-Bus service, those with variable names and paths, but the amount of D-Bus services worthing a look doesn’t end up here, indeed there are other applications that provide interesting methods, all them will be a matter of a new article.


Creative Commons License This work is licensed under a Creative Commons Attribution-NoCommercial-ShareAlike 4.0 International License


Follow-up articles


Leave a Comment