Difference between revisions of "Development/Tutorials/Plasma/ContainmentAction"

Jump to: navigation, search
(See also)
 
(15 intermediate revisions by one user not shown)
Line 1: Line 1:
You can use Plasma ContainmentAction e.g. for Context Menus on your Plasma Desktop. They will run as plugins meaning you can add and remove them after compilation. If they exist, their name will be stored in [[Development/Tutorials/Desktop_File|.desktop files]].
+
You can use Plasma ContainmentAction e.g. for Context Menus on your Plasma Desktop. They will run as plugins meaning you can add and remove them after compilation. If they exist, their name will be stored in [[Development/Tutorials/Desktop_File|.desktop files]]. ContainmentActions can only be written in C++ or QML, not in other Plasma programming languages, e.g. NOT in javascript.
 +
 
 +
= Example =
 +
We will now create a simple example for Plasma ContainmentAction plugins. The code can be downloaded at https://github.com/tstaerk/kde-contextmenu/tree/tutorial. It creates a custom context menu that looks like this:
 +
 
 +
[[File:Snapshot-kde-contextmenu-2.png]]
 +
 
 +
The code is here:
 +
 
 +
== kde-contextmenu.desktop ==
 +
[Desktop Entry]
 +
Name=KDE Context Menu
 +
Type=Service
 +
Icon=favorites
 +
Comment=Simple application launcher
 +
 +
ServiceTypes=Plasma/ContainmentActions
 +
 +
X-KDE-Library=kde-contextmenu
 +
X-KDE-PluginInfo-Author=R. Hacker
 +
X-KDE-PluginInfo-Email=hacker@home.org
 +
X-KDE-PluginInfo-Name=kde-contextmenu
 +
X-KDE-PluginInfo-Version=pre0.1
 +
X-KDE-PluginInfo-Website=http://techbase.kde.org
 +
X-KDE-PluginInfo-EnabledByDefault=true
 +
 
 +
The '''''Name''''' will show up later in this article when you select your context menu.
 +
 
 +
If you want to know which '''''ServiceTypes''''' exist, you can find out with the Linux command
 +
ls `kde4-config --prefix`/share/kde4/servicetypes
 +
 
 +
== CMakeLists.txt ==
 +
<pre>
 +
project(kde-contextmenu)
 +
 
 +
set(KDE_MIN_VERSION "4.3.85") # for the < 4.2 macro
 +
find_package(KDE4 4.3.85 REQUIRED)
 +
 
 +
include(MacroLibrary)
 +
include(KDE4Defaults)
 +
 
 +
add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
 +
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES})
 +
 
 +
set(contextmenu_SRCS
 +
    launch.cpp
 +
)
 +
 
 +
kde4_add_plugin(kde-contextmenu ${contextmenu_SRCS})
 +
target_link_libraries(kde-contextmenu ${KDE4_PLASMA_LIBS} ${KDE4_KIO_LIBS})
 +
 
 +
install(TARGETS kde-contextmenu DESTINATION ${PLUGIN_INSTALL_DIR})
 +
install(FILES kde-contextmenu.desktop DESTINATION ${SERVICES_INSTALL_DIR})
 +
</pre>
 +
 
 +
== launch.h ==
 +
<pre>
 +
#ifndef CONTEXTMENU_HEADER
 +
#define CONTEXTMENU_HEADER
 +
 
 +
#include <plasma/containmentactions.h>
 +
 
 +
class QAction;
 +
class KMenu;
 +
 
 +
class ConTextMenu : public Plasma::ContainmentActions
 +
{
 +
    Q_OBJECT
 +
    public:
 +
        ConTextMenu(QObject* parent, const QVariantList& args);
 +
        ~ConTextMenu();
 +
 
 +
        void init(const KConfigGroup &config);
 +
 
 +
        void contextEvent(QEvent *event);
 +
        //returns true if something (other than a separator) was successfully added
 +
        bool addApps(QMenu *menu);
 +
 
 +
    public slots:
 +
        void switchTo(QAction *action);
 +
 
 +
    protected:
 +
        void makeMenu();
 +
 
 +
    private:
 +
        KMenu *m_menu;
 +
        QAction *m_action;
 +
};
 +
 
 +
K_EXPORT_PLASMA_CONTAINMENTACTIONS(favorites, ConTextMenu)
 +
 
 +
#endif
 +
</pre>
 +
 
 +
== launch.cpp ==
 +
<pre>
 +
#include "launch.h"
 +
 
 +
#include <QGraphicsSceneMouseEvent>
 +
#include <QGraphicsSceneWheelEvent>
 +
#include <QFileInfo>
 +
 
 +
#include <KDebug>
 +
#include <KIcon>
 +
#include <KMenu>
 +
 
 +
#include <Plasma/DataEngine>
 +
#include <Plasma/Containment>
 +
#include <Plasma/Service>
 +
 
 +
ConTextMenu::ConTextMenu(QObject *parent, const QVariantList &args)
 +
    : Plasma::ContainmentActions(parent, args)
 +
    , m_action(new QAction(this))
 +
{
 +
    m_menu = new KMenu();
 +
    connect(m_menu, SIGNAL(triggered(QAction*)), this, SLOT(switchTo(QAction*)));
 +
 
 +
    m_action->setMenu(m_menu);
 +
}
 +
 
 +
ConTextMenu::~ConTextMenu()
 +
{
 +
    delete m_menu;
 +
}
 +
 
 +
void ConTextMenu::init(const KConfigGroup &)
 +
{
 +
}
 +
 
 +
void ConTextMenu::contextEvent(QEvent *event)
 +
{
 +
    makeMenu();
 +
    m_menu->adjustSize();
 +
    m_menu->exec(popupPosition(m_menu->size(), event));
 +
}
 +
 
 +
void ConTextMenu::makeMenu()
 +
{
 +
    m_menu->clear();
 +
    addApps(m_menu);
 +
}
 +
 
 +
bool ConTextMenu::addApps(QMenu *menu)
 +
{
 +
    QAction* action = menu->addAction(KIcon("system-run"), "Open a console");
 +
    action->setData("kde4-konsole.desktop");
 +
 
 +
    action = menu->addAction(KIcon("firefox"), "Surf the web");
 +
    action->setData("firefox.desktop");
 +
   
 +
    action = menu->addAction(KIcon("ksnapshot"), "Take a screenshot");
 +
    action->setData("kde4-ksnapshot.desktop");
 +
    return true;
 +
}
 +
 
 +
void ConTextMenu::switchTo(QAction *action)
 +
{
 +
    QString source = action->data().toString();
 +
    kDebug() << source;
 +
    Plasma::Service *service = dataEngine("apps")->serviceForSource(source);
 +
    if (service)
 +
    {
 +
        service->startOperationCall(service->operationDescription("launch"));
 +
    }
 +
}
 +
 
 +
#include "launch.moc"
 +
</pre>
 +
 
 +
== Install it ==
 +
Compile, link and install it using the command
 +
cmake -DCMAKE_INSTALL_PREFIX=`kde4-config --prefix` . && make -j8 && make install
 +
 
 +
== Test it ==
 +
To test it, have your system re-discover its .desktop files by running the command
 +
kbuildsycoca4
 +
Then right-click onto your desktop, select "Folder View Settings" -> Mouse Actions and the context menu:
 +
 
 +
[[File:Snapshot-kde-contextmenu-1.png]]
 +
 
 +
Then click "Apply". You will see the config file ~/.kde4/share/config/plasma-desktop-appletsrc changes. Next time when you middle-click (or whatever you selected) onto your desktop, your own context menu will appear:
 +
 
 +
[[File:Snapshot-kde-contextmenu-2.png]]
  
 
= Debugging =
 
= Debugging =
Line 5: Line 187:
 
  kdebugdialog --fullmode
 
  kdebugdialog --fullmode
 
search for "plasma" and direct kDebug's output to /tmp/whatever.txt
 
search for "plasma" and direct kDebug's output to /tmp/whatever.txt
 +
 +
= See also =
 +
* [http://quickgit.kde.org/?p=kde-workspace.git&a=tree&f=plasma%2Fgeneric%2Fcontainmentactions Source code: ContainmentActions from kde-workspace]
 +
* [http://www.staerk.de/thorsten/Kde-contextmenu kde-contextmenu's home page]

Latest revision as of 12:22, 9 March 2013

You can use Plasma ContainmentAction e.g. for Context Menus on your Plasma Desktop. They will run as plugins meaning you can add and remove them after compilation. If they exist, their name will be stored in .desktop files. ContainmentActions can only be written in C++ or QML, not in other Plasma programming languages, e.g. NOT in javascript.

Contents

[edit] Example

We will now create a simple example for Plasma ContainmentAction plugins. The code can be downloaded at https://github.com/tstaerk/kde-contextmenu/tree/tutorial. It creates a custom context menu that looks like this:

Snapshot-kde-contextmenu-2.png

The code is here:

[edit] kde-contextmenu.desktop

[Desktop Entry]
Name=KDE Context Menu
Type=Service
Icon=favorites
Comment=Simple application launcher

ServiceTypes=Plasma/ContainmentActions

X-KDE-Library=kde-contextmenu
X-KDE-PluginInfo-Author=R. Hacker
X-KDE-PluginInfo-Email=hacker@home.org
X-KDE-PluginInfo-Name=kde-contextmenu
X-KDE-PluginInfo-Version=pre0.1
X-KDE-PluginInfo-Website=http://techbase.kde.org
X-KDE-PluginInfo-EnabledByDefault=true

The Name will show up later in this article when you select your context menu.

If you want to know which ServiceTypes exist, you can find out with the Linux command

ls `kde4-config --prefix`/share/kde4/servicetypes

[edit] CMakeLists.txt

project(kde-contextmenu)

set(KDE_MIN_VERSION "4.3.85") # for the < 4.2 macro
find_package(KDE4 4.3.85 REQUIRED)

include(MacroLibrary)
include(KDE4Defaults)

add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES})

set(contextmenu_SRCS
    launch.cpp
)

kde4_add_plugin(kde-contextmenu ${contextmenu_SRCS})
target_link_libraries(kde-contextmenu ${KDE4_PLASMA_LIBS} ${KDE4_KIO_LIBS})

install(TARGETS kde-contextmenu DESTINATION ${PLUGIN_INSTALL_DIR})
install(FILES kde-contextmenu.desktop DESTINATION ${SERVICES_INSTALL_DIR})

[edit] launch.h

#ifndef CONTEXTMENU_HEADER
#define CONTEXTMENU_HEADER

#include <plasma/containmentactions.h>

class QAction;
class KMenu;

class ConTextMenu : public Plasma::ContainmentActions
{
    Q_OBJECT
    public:
        ConTextMenu(QObject* parent, const QVariantList& args);
        ~ConTextMenu();

        void init(const KConfigGroup &config);

        void contextEvent(QEvent *event);
        //returns true if something (other than a separator) was successfully added
        bool addApps(QMenu *menu);

    public slots:
        void switchTo(QAction *action);

    protected:
        void makeMenu();

    private:
        KMenu *m_menu;
        QAction *m_action;
};

K_EXPORT_PLASMA_CONTAINMENTACTIONS(favorites, ConTextMenu)

#endif

[edit] launch.cpp

#include "launch.h"

#include <QGraphicsSceneMouseEvent>
#include <QGraphicsSceneWheelEvent>
#include <QFileInfo>

#include <KDebug>
#include <KIcon>
#include <KMenu>

#include <Plasma/DataEngine>
#include <Plasma/Containment>
#include <Plasma/Service>

ConTextMenu::ConTextMenu(QObject *parent, const QVariantList &args)
    : Plasma::ContainmentActions(parent, args)
    , m_action(new QAction(this))
{
    m_menu = new KMenu();
    connect(m_menu, SIGNAL(triggered(QAction*)), this, SLOT(switchTo(QAction*)));

    m_action->setMenu(m_menu);
}

ConTextMenu::~ConTextMenu()
{
    delete m_menu;
}

void ConTextMenu::init(const KConfigGroup &)
{
}

void ConTextMenu::contextEvent(QEvent *event)
{
    makeMenu();
    m_menu->adjustSize();
    m_menu->exec(popupPosition(m_menu->size(), event));
}

void ConTextMenu::makeMenu()
{
    m_menu->clear();
    addApps(m_menu);
}

bool ConTextMenu::addApps(QMenu *menu)
{
    QAction* action = menu->addAction(KIcon("system-run"), "Open a console");
    action->setData("kde4-konsole.desktop");

    action = menu->addAction(KIcon("firefox"), "Surf the web");
    action->setData("firefox.desktop");
    
    action = menu->addAction(KIcon("ksnapshot"), "Take a screenshot");
    action->setData("kde4-ksnapshot.desktop");
    return true;
}

void ConTextMenu::switchTo(QAction *action)
{
    QString source = action->data().toString();
    kDebug() << source;
    Plasma::Service *service = dataEngine("apps")->serviceForSource(source);
    if (service)
    {
        service->startOperationCall(service->operationDescription("launch"));
    }
}

#include "launch.moc"

[edit] Install it

Compile, link and install it using the command

cmake -DCMAKE_INSTALL_PREFIX=`kde4-config --prefix` . && make -j8 && make install

[edit] Test it

To test it, have your system re-discover its .desktop files by running the command

kbuildsycoca4

Then right-click onto your desktop, select "Folder View Settings" -> Mouse Actions and the context menu:

Snapshot-kde-contextmenu-1.png

Then click "Apply". You will see the config file ~/.kde4/share/config/plasma-desktop-appletsrc changes. Next time when you middle-click (or whatever you selected) onto your desktop, your own context menu will appear:

Snapshot-kde-contextmenu-2.png

[edit] Debugging

To debug your Plasma ContainmentAction call

kdebugdialog --fullmode

search for "plasma" and direct kDebug's output to /tmp/whatever.txt

[edit] See also


This page was last modified on 9 March 2013, at 12:22. This page has been accessed 2,565 times. Content is available under Creative Commons License SA 3.0 as well as the GNU Free Documentation License 1.2.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V.Legal