Bash – Expand KDE activities concept to the shell

bashkdekde-activities

Sometimes, I use KDE, and one of the things that I like the most in KDE 4 is the activity concept. At work, it is very useful because I often work on several different projects during one day. Switching to another activity enables me to change the widgets, so that I can have access to folders related to the current project, for instance.

I've decided to use this concept in the shell, so I have coded a small bash function called "switch", which sets aliases useful for the current project, e.g. alias cdwww=~/public_html/current_project/www , and so on.

My question is : Is there a way I can synchronise KDE activities with shell activities, that is calling 'switch myproj' on every opened terminal when switching to activity 'myproj' through KDE and vice versa (bonus question)?

Another question : how do I make my newly created aliases work in all consoles? Is there a way I can detect every opened terminal in konsole or in gnome-terminal and execute my function in it?

EDIT: here is the switch function, located at the end of my .bashrc file, feel free to comment:

function switch() {

    if [ ! -d ~/.switch ]
    then
        mkdir ~/.switch
    fi

    if [ ! -f ~/.switch/proj.save ]
    then
        touch ~/.switch/proj.save
    fi

    echo "$1" > ~/.switch/proj.save

    case $1 in
    meddispar )
        echo "Switching to meddispar..."

        echo "setting cdproj alias"
        alias cdproj="cd ~/public_html/onp/"

        echo "setting cdwww alias"
        alias cdwww="cd ~/public_html/onp/www/"

        echo "setting cc alias"
        alias cc="cdwww && php bin/php/ezcache.php --clear-all --purge && cd -"
    ;;
    darjeeling )
        echo "Switching to darjeeling..."

        echo "setting cdproj alias"
        alias cdproj="cd ~/public_html/darjeeling/"

        echo "setting cdwww alias"
        alias cdwww="cd ~/public_html/darjeeling/www/"

        echo "setting cc alias"
        alias cc="rm -rf ~/public_html/darjeeling/www/var/cache/*"
    ;;
    * )
        echo "'$1'? WTF?"
        rm ~/.switch/proj.save
    ;;
    esac
}
if [ -f ~/.switch/proj.save ]
then
     switch `cat ~/.switch/proj.save`
fi

As per Gilles' answer, here is what I have got:

greg@tiny :) ~ > qdbus |ack ctivity
 org.kde.ActivityController-1949
 org.kde.ActivityManager
greg@tiny :) ~ > qdbus org.kde.ActivityManager 
/
/ActivityManager
/MainApplication
/StatusNotifierWatcher
/connections
/kbuildsycoca
/kded
/kxkb
/modules
/modules/StatusNotifierWatcher
/modules/activitymanager
/modules/device_automounter
/modules/dnssdwatcher
/modules/favicons
/modules/freespacenotifier
/modules/keyboard
/modules/khotkeys
/modules/kpackagekitd
/modules/kremotecontroldaemon
/modules/ktimezoned
/modules/kwrited
/modules/nepomuksearchmodule
/modules/networkmanagement
/modules/networkstatus
/modules/powerdevil
/modules/randrmonitor
/modules/remotedirnotify
/modules/solidautoeject
/modules/statusnotifierwatcher
/org
/org/freedesktop
/org/freedesktop/PowerManagement
/org/freedesktop/PowerManagement/Inhibit
/org/kde
/org/kde/networkmanagement
/org/kde/networkmanagement/Activatable
/org/kde/networkmanagement/Activatable/10
/org/kde/networkmanagement/Activatable/11
/org/kde/networkmanagement/Activatable/12
/org/kde/networkmanagement/Activatable/13
/org/kde/networkmanagement/Activatable/14
/org/kde/networkmanagement/Activatable/15
/org/kde/networkmanagement/Activatable/16
/org/kde/networkmanagement/Activatable/17
/org/kde/networkmanagement/Activatable/2
/org/kde/networkmanagement/Activatable/3
/org/kde/networkmanagement/Activatable/4
/org/kde/networkmanagement/Activatable/5
/org/kde/networkmanagement/Activatable/6
/org/kde/networkmanagement/Activatable/7
/org/kde/networkmanagement/Activatable/8
greg@tiny :) ~ > qdbus org.kde.ActivityManager /ActivityManager
method QStringList org.kde.ActivityManager.ActivitiesForResource(QString uri)
method QString org.kde.ActivityManager.ActivityIcon(QString id)
method QString org.kde.ActivityManager.ActivityName(QString id)
signal void org.kde.ActivityManager.ActivityNameChanged(QString id, QString name)
method QString org.kde.ActivityManager.AddActivity(QString name)
method QStringList org.kde.ActivityManager.AvailableActivities()
method QString org.kde.ActivityManager.CurrentActivity()
signal void org.kde.ActivityManager.CurrentActivityChanged(QString id)
method bool org.kde.ActivityManager.IsBackstoreAvailable()
method void org.kde.ActivityManager.RegisterActivityController(QString service)
method void org.kde.ActivityManager.RegisterResourceWindow(uint wid, QString uri)
method QStringList org.kde.ActivityManager.RegisteredActivityControllers()
method void org.kde.ActivityManager.RemoveActivity(QString id)
method void org.kde.ActivityManager.SetActivityIcon(QString id, QString name)
method void org.kde.ActivityManager.SetActivityName(QString id, QString name)
method bool org.kde.ActivityManager.SetCurrentActivity(QString id)
method void org.kde.ActivityManager.UnregisterResourceWindow(uint wid, QString uri)
method QString org.kde.ActivityManager._allInfo()
method QString org.kde.ActivityManager._serviceIteration()
method QDBusVariant org.freedesktop.DBus.Properties.Get(QString interface_name, QString property_name)
method QVariantMap org.freedesktop.DBus.Properties.GetAll(QString interface_name)
method void org.freedesktop.DBus.Properties.Set(QString interface_name, QString property_name, QDBusVariant value)
method QString org.freedesktop.DBus.Introspectable.Introspect()
greg@tiny :) ~ > qdbus org.kde.ActivityController-1949 /ActivityController 
method void org.kde.ActivityController.ActivityAdded(QString id)
method void org.kde.ActivityController.ActivityRemoved(QString id)
method void org.kde.ActivityController.ResourceWindowRegistered(uint wid, QString uri)
method void org.kde.ActivityController.ResourceWindowUnregistered(uint wid, QString uri)
method QDBusVariant org.freedesktop.DBus.Properties.Get(QString interface_name, QString property_name)
method QVariantMap org.freedesktop.DBus.Properties.GetAll(QString interface_name)
method void org.freedesktop.DBus.Properties.Set(QString interface_name, QString property_name, QDBusVariant value)
method QString org.freedesktop.DBus.Introspectable.Introspect()

EDIT : I completely rewrote my script using python, and now the whole project is available here : https://github.com/greg0ire/switch

Best Answer

Controlling KDE activities via dbus

KDE can be controlled from the command line with qdbus. The general syntax is qdbus COMPONENT PATH METHOD ARGUMENT1... where COMPONENT is typically something like org.freedesktop.Foo or org.kde.Bar, PATH denotes a class exposed by the component, METHOD is the name of a particular action in that class, and there may be further arguments depending on the method.

Here are commands for KDE ≥4.7 to list activities, to get the current activity, and to set the current activity.

qdbus org.kde.kactivitymanagerd /ActivityManager org.kde.ActivityManager.ListActivities
qdbus org.kde.kactivitymanagerd /ActivityManager org.kde.ActivityManager.CurrentActivity
qdbus org.kde.kactivitymanagerd /ActivityManager org.kde.ActivityManager.SetCurrentActivity "activity identifier "

Finding out what dbus can do

KDE's dbus documentation is very poor. Each class is minimally documented, e.g. Activity, DesktopCorona). But you'll probably have to experiment and perhaps read the source (there are links in the API documentation pages) to find out what is available.

If you type qdbus with up to two arguments, it will list the possibilities for the next argument. The following shell snippet lists all available Qt-dbus methods:

for x in $(qdbus | sed '/^:/d'); do
  for y in $(qdbus $x); do
    qdbus $x $y | sed "s~^~$x $y ~"
  done
done 2>/dev/null >qdbus.list

Another way to explore the dbus tree is qdbusviewer in the Qt development tools. There is also a Python qt-dbus interface as part of PyQt.

Getting the shell to react

To make a shell react to external events, the best you can reasonably do is make it check something before displaying a prompt. Bash runs $PROMPT_COMMAND before displaying a prompt, and zsh executes the precmd function. So you can look up the current KDE activity and do something if it's changed from the last time you looked.

Related Question