Development/Tutorials/SuperKaramba: Difference between revisions

    From KDE TechBase
    m (Text replace - "</code>" to "</syntaxhighlight>")
     
    (67 intermediate revisions by 4 users not shown)
    Line 12: Line 12:
    * [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/ Examples] Some examples SuperKaramba ships with. See also the [http://www.kde-look.org/index.php?xcontentmode=38 Themes] and [http://www.biodesign.com.ar/blog/?cat=2 More Themes].
    * [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/ Examples] Some examples SuperKaramba ships with. See also the [http://www.kde-look.org/index.php?xcontentmode=38 Themes] and [http://www.biodesign.com.ar/blog/?cat=2 More Themes].


    [[Image:skplasmaapplet.png]]
    [[Image:skplasmaapplet.jpg]]
    This screenshot shows the  [http://www.kde-look.org/content/show.php/Aero+AIO?content=24626 Aero AI] Karamba Theme running on KDE4 as [[Projects/Plasma|Plasmoid]] (aka Plasma Applet).
    This screenshot shows the  [http://www.kde-look.org/content/show.php/Aero+AIO?content=24626 Aero AIO] Karamba Theme running on KDE4 as [[Projects/Plasma|Plasmoid]] (aka Plasma Applet).
     
    ==Commands, Meters and Sensors==
     
    SuperKaramba does differ between 3 kind of elements. Commands define something  that should be done (actions), meters are used to display something (GUI widgets) while sensors are to get something (data delivery).
     
    * A list of [http://netdragon.sourceforge.net/sgeneral.html General Commands] that you can put in your theme file. This includes tags that define the widget shape, set default fonts, and create click-areas that launch programs.
    * A list of [http://netdragon.sourceforge.net/smeters.html Meters] that you can put in your theme file. This includes meters display the values of sensors. Meters can auto-update.
    * A list of [http://netdragon.sourceforge.net/ssensors.html Sensors] that you can put in your theme file. Sensors allow you to display system properties automatically. There are sensors to display the status of everything from memory use to the results of shell scripts. See here also the [[#Plasma::DataEngine_as_SuperKaramba_Sensor|Plasma::DataEngine as SuperKaramba Sensor]] chapter.


    ==Basic Tutorial for Theme Creators==
    ==Basic Tutorial for Theme Creators==
    Line 23: Line 31:
    The theme files, those files with the fileextension *.theme, are text files that contain layout information and information about the values that will be shown.
    The theme files, those files with the fileextension *.theme, are text files that contain layout information and information about the values that will be shown.


    ====Commands, Meters and Sensors====
    ====Theme File Samples====
     
    * A list of [http://netdragon.sourceforge.net/sgeneral.html General Commands] that you can put in your theme file. This includes tags that define the widget shape, set default fonts, and create click-areas that launch programs.
    * A list of [http://netdragon.sourceforge.net/smeters.html Meters] that you can put in your theme file. This includes meters display the values of sensors. Meters can auto-update.
    * A list of [http://netdragon.sourceforge.net/ssensors.html Sensors] that you can put in your theme file. Sensors allow you to display system properties automatically. There are sensors to display the status of everything from memory use to the results of shell scripts
     
    ====Samples====


    The simplest form of Karamba is to load a file containing the word karamba. This will give you a empty transparent window with the size 300x300. A better idea is to enter something like this in a file:
    The simplest form of Karamba is to load a file containing the word karamba. This will give you a empty transparent window with the size 300x300. A better idea is to enter something like this in a file:
    Line 55: Line 57:
    image x=10 y=270 path="picture.png"
    image x=10 y=270 path="picture.png"
    </pre>
    </pre>
    An introduction to the format parameter:
    An introduction to the format parameter for a text meter:
    <pre>
    <pre>
    text x=10 y=330 sensor=memory format="You have %tm MB memory"
    text x=10 y=330 sensor=memory format="You have %tm MB memory"
    </pre>
    Using of a the "time" Plasma::DataEngine:
    <pre>
    text x=0 y=0 sensor=plasma engine="time" source="Local" format="%Date %Time"
    </pre>
    </pre>


    Line 91: Line 97:
    First, you need the [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/template.py template.py] or the [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/template.rb template.rb] or the [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/template.js template.js] template script file, depending on what scripting language you like to use. Download this file to where your theme file is. Now rename those just downloaded template file from template.py to mytheme.py or from template.rb to mytheme.rb where mytheme is the name of your theme. For example, if you wrote a coolbar.theme and like to use use Python, renamed the just downloaded template.py to coolbar.py and put it in the same directory as coolbar.theme.
    First, you need the [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/template.py template.py] or the [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/template.rb template.rb] or the [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/template.js template.js] template script file, depending on what scripting language you like to use. Download this file to where your theme file is. Now rename those just downloaded template file from template.py to mytheme.py or from template.rb to mytheme.rb where mytheme is the name of your theme. For example, if you wrote a coolbar.theme and like to use use Python, renamed the just downloaded template.py to coolbar.py and put it in the same directory as coolbar.theme.


    Now, lets open up your coolbar.py (or coolbar.rb or whatever you named it to) scripting file. Look for the event callback that reacts to mouse movement. In the case you choosed Python as your prefered scripting language, it may look like this:
    Now, lets open up your coolbar.py (or coolbar.rb or whatever you named it to) scripting file. Look for the event callback that reacts to mouse movement. If you chose Python as your prefered scripting language, it may look like this:


    <code python>
    <syntaxhighlight lang="python">
    #This gets called everytime our widget is clicked.
    #This gets called everytime our widget is clicked.
    #Notes
    #Notes
    Line 110: Line 116:
         #want to run complex piece of code everytime the mouse moves.
         #want to run complex piece of code everytime the mouse moves.
         pass
         pass
    </code>
    </syntaxhighlight>


    Notice how the template gives your instructions on what data each callback gives you. In this case, you can see that you will know the x and y co-ordinates of the mouse, the button being held down (if any), and a reference to your widget.
    Notice how the template gives your instructions on what data each callback gives you. In this case, you can see that you will know the x and y co-ordinates of the mouse, the button being held down (if any), and a reference to your widget.
    Line 122: Line 128:


    Here is how the callback might look after you add some code to it:
    Here is how the callback might look after you add some code to it:
    <code python>
    <syntaxhighlight lang="python">
    def widgetMouseMoved(widget, x, y, button):
    def widgetMouseMoved(widget, x, y, button):
         myText = karamba.getThemeText(widget, "mouseText")
         myText = karamba.getThemeText(widget, "mouseText")
         karamba.changeText(widget, myText, "mouse at %s:%s" % (x,y))
         karamba.changeText(widget, myText, "mouse at %s:%s" % (x,y))
    </code>
    </syntaxhighlight>


    This Python scripting code simply changes the text called "mouseText" (which we defiend in our theme file) to tell us the current position of the mouse.
    This Python scripting code simply changes the text called "mouseText" (which we defined in our theme file) to tell us the current position of the mouse.


    How did I know what parameters karamba.changeText() and karamba.getThemeText() used? How did I even know those functions existed in the first place? Well, thats what the [[Projects/SuperKaramba/API|API]] tells you. The API and the template.py or template.rb script file basically contain everything you could ever need to know to write your own theme.
    How did I know what parameters karamba.changeText() and karamba.getThemeText() used? How did I even know those functions existed in the first place? Well, thats what the [[Projects/SuperKaramba/API|API]] tells you. The API and the template.py or template.rb script file basically contain everything you could ever need to know to write your own theme.


    ====Testing!====
    ===Testing!===
    To test your new Python or Ruby scripting code, just open your theme file in SuperKaramba.
    To test your new Python or Ruby scripting code, just open your theme file in SuperKaramba.


    Line 138: Line 144:


    You DO NOT need to compile your scripting code. SuperKaramba will do that automatically and tell you about any errors. In fact, you can't run your .py or .rb file directly in regular python because it doesn't know anything about the karamba.* functions. Those functions only exist inside of SuperKaramba's Python and Ruby interpreters. But you are for sure able to just use SuperKaramba as your interpreter direct from within the commandline. Just start SuperKaramba with something like:
    You DO NOT need to compile your scripting code. SuperKaramba will do that automatically and tell you about any errors. In fact, you can't run your .py or .rb file directly in regular python because it doesn't know anything about the karamba.* functions. Those functions only exist inside of SuperKaramba's Python and Ruby interpreters. But you are for sure able to just use SuperKaramba as your interpreter direct from within the commandline. Just start SuperKaramba with something like:
    <code bash>
    <syntaxhighlight lang="bash">
    superkaramba ./coolbar.theme
    superkaramba ./coolbar.theme
    </code>
    </syntaxhighlight>


    To ease the development, SuperKaramba will automatically reload your theme when you save your changes to the theme file or the script file. This allows you to see your modifications immediately without reloading the theme manually.
    To ease the development, SuperKaramba will automatically reload your theme when you save your changes to the theme file or the script file. This allows you to see your modifications immediately without reloading the theme manually.
    Line 150: Line 156:
    ===SuperKaramba on KDE4===
    ===SuperKaramba on KDE4===


    While we where able to see a lot of rumours and speculations regarding SuperKaramba and it's role on KDE4, it's planned to continue to support SuperKaramba and it's unique feature-set, the bunches of themes that do already exist and those that will be written. We will stay backward-compatible and rocking stable, improve the feature-set as needed and wish you fun with the result: the next generation of SuperKaramba :)
    While we were able to see a lot of rumours and speculations regarding SuperKaramba and it's role on KDE4, it's planned to continue to support SuperKaramba and it's unique feature-set, the bunches of themes that do already exist and those that will be written. We will stay backward-compatible and rocking stable, improve the feature-set as needed and wish you fun with the result: the next generation of SuperKaramba :)


    ===SuperKaramba as Plasma Applet===
    ===SuperKaramba and Plasma===


    SuperKaramba runs as standalonea-application - just run the superkaramba-bin - as well as [[Projects/Plasma|Plasma]] Applet.
    SuperKaramba runs as standalonea-application - just run the program "superkaramba" - as well as [[Projects/Plasma|Plasma]] Applet embedded into the Plasma Workspace. Also SuperKaramba provides full and transparent access to the Plasma::DataEngine's with it's sensor functionality.


    * [http://www.kdedevelopers.org/node/2903 screenshot]
    See also the [[Development/Tutorials/SuperKaramba#Plasma|Plasma script samples]] section.
    * [http://kross.dipe.org/skapplet.mpeg screencast], 2.4MB, mpeg4


    ===Scripting Interpreter Backends===
    ===Scripting Interpreter Backends===
    Line 167: Line 172:
    As described at the Python Enhancement Proposal [http://www.python.org/peps/pep-0263.html Defining Python Source Code Encodings] it is recommed to start a python script file with following both lines:
    As described at the Python Enhancement Proposal [http://www.python.org/peps/pep-0263.html Defining Python Source Code Encodings] it is recommed to start a python script file with following both lines:


    <code python>
    <syntaxhighlight lang="python">
    #!/usr/bin/env superkaramba-bin
    #!/usr/bin/env superkaramba
    # coding: utf-8
    # coding: utf-8
    </code>
    </syntaxhighlight>


    The first line is the shebang that causes Unix-like operating systems to execute the script file using the SuperKaramba interpreter. You are then able to start the karamba script with;
    The first line is the shebang that causes Unix-like operating systems to execute the script file using the SuperKaramba interpreter. You are then able to start the karamba script with;
    <code>
    <syntaxhighlight lang="text">
    chmod 755 myKaramba.py
    chmod 755 myKaramba.py
    ./myKaramba.py
    ./myKaramba.py
    </code>
    </syntaxhighlight>
    The second line defines that the script file is encoded with utf-8 or whatever the script fiel is actualy encoded in. This seems to be needed at least with Python >=2.5.
    The second line defines that the script file is encoded with utf-8 or whatever the script file is actualy encoded in. This seems to be needed at least with Python >=2.5.


    ==Script Samples==
    ==Script Samples==
    Line 187: Line 192:
    theme written in Ruby. The theme just displays the current time in a RichText widget.
    theme written in Ruby. The theme just displays the current time in a RichText widget.


    <code ruby>
    <syntaxhighlight lang="ruby">
    require 'karamba'
    require 'karamba'


    Line 202: Line 207:
         Karamba.redrawWidget(widget)
         Karamba.redrawWidget(widget)
    end
    end
    </code>
    </syntaxhighlight>


    The initWidget method will be called once if the widget got initialized. Here we setup the RichText widget where we display the current time in. The widgetUpdated will be called each second once (the interval is defined in the [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/rubyclock/clock.theme?view=markup clock.theme] themefile) and just updates the text display in the RichText widget with the new time.
    The initWidget method will be called once if the widget got initialized. Here we setup the RichText widget where we display the current time in. The widgetUpdated will be called each second once (the interval is defined in the [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/rubyclock/clock.theme?view=markup clock.theme] themefile) and just updates the text display in the RichText widget with the new time.
    Line 208: Line 213:
    Let's take a look at another theme. The [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/text/text.py?view=markup text.py] theme written in Python just displays some text widgets. We take this as example to create our own script, that does the same as the [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/rubyclock/clock.rb?view=markup clock.rb] above, that is to display the current time within a text widget.
    Let's take a look at another theme. The [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/text/text.py?view=markup text.py] theme written in Python just displays some text widgets. We take this as example to create our own script, that does the same as the [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/rubyclock/clock.rb?view=markup clock.rb] above, that is to display the current time within a text widget.


    <code python>
    <syntaxhighlight lang="python">
    import karamba, time
    import karamba, time


    Line 226: Line 231:
         karamba.changeText(widget, text, getTime())
         karamba.changeText(widget, text, getTime())
         karamba.redrawWidget(widget)
         karamba.redrawWidget(widget)
    </code>
    </syntaxhighlight>


    In the initWidget method we create our text widget that is updated once per second (or per interval as defined in the matching theme file) at the widgetUpdated method to display the new current time.
    In the initWidget method we create our text widget that is updated once per second (or per interval as defined in the matching theme file) at the widgetUpdated method to display the new current time.
    Line 233: Line 238:


    There we have the currentTime() function that returns the current time as string. That function is used within the initWidget() and the widgetUpdated() functions to display the current time within a textwidget.
    There we have the currentTime() function that returns the current time as string. That function is used within the initWidget() and the widgetUpdated() functions to display the current time within a textwidget.
    <code javascript>
    <syntaxhighlight lang="javascript">
    var text = 0;
    var text = 0;


    Line 255: Line 260:
         karamba.redrawWidget(widget)
         karamba.redrawWidget(widget)
    }
    }
    </code>
    </syntaxhighlight>


    See also...
    See also...
    Line 267: Line 272:
    The following sample Python script demonstrates how to display a messagebox.
    The following sample Python script demonstrates how to display a messagebox.


    <code python>
    <syntaxhighlight lang="python">
    import karamba, Kross
    import karamba, Kross


    Line 276: Line 281:
         elif button == 2: #middle
         elif button == 2: #middle
             forms.showMessageBox("Error","Caption","Message")
             forms.showMessageBox("Error","Caption","Message")
    </code>
    </syntaxhighlight>


    While the next sample Python script displays a dialog with an embedded "Open File" widget.
    While the next sample Python script displays a dialog with an embedded "Open File" widget.


    <code python>
    <syntaxhighlight lang="python">
    import karamba, Kross
    import karamba, Kross


    Line 295: Line 300:
         if result:
         if result:
             print openwidget.selectedFile()
             print openwidget.selectedFile()
    </code>
    </syntaxhighlight>


    For sure you are also able to use those handy UI-files the QtDesigner produces like demonstrated on the sample below.
    For sure you are also able to use those handy UI-files the QtDesigner produces like demonstrated on the sample below.


    <code python>
    <syntaxhighlight lang="python">
    import karamba, os, Kross
    import karamba, os, Kross


    Line 313: Line 318:
             # lineedit-widget that has the name MyLineEdit
             # lineedit-widget that has the name MyLineEdit
             print infoswidget["MyLineEdit"].text
             print infoswidget["MyLineEdit"].text
    </code>
    </syntaxhighlight>
     
    ===Embed KHTML Webbrowser===
     
    Starting with Qt 4.4 and KDE 4.1 SuperKaramba is able to embed any kind of QWidgets into the canvas that is used to display something. That means, you are able to add a QLabel, a QPushButton or any other widget just direct into your Karambas.
     
    The following python sample code, which is also available as [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/WebBrowser/webbrowser.py?view=markup webbrowser.py], demonstrates this by embedding a full webbrowser into your Karamba by using the [[Projects/SuperKaramba/API#CanvasWidget|CanvasWidget]] functionality.


    ===Control KSpread===
    <syntaxhighlight lang="python">
    #!/usr/bin/env superkaramba
    # coding: utf-8
     
    import karamba, Kross
    khtml_part = None
     
    def initWidget(widget):
        # the Kross forms module does provide methods to create
        # widgets for us. You are for example able to load a UI
        # file, create layouts or just any other supported widget.
        forms = Kross.module("forms")
        frame = forms.createWidget("QWidget")
        forms.createLayout(frame, "QHBoxLayout")
        # here we load the KHTML KPart that is our full powered
        # webbrowser widget.
        khtml_part = forms.loadPart(frame, "libkhtmlpart")
        khtml_part.javaScriptEnabled = True
        khtml_part.javaEnabled = False
        khtml_part.pluginsEnabled = False
        # now we add the frame to our widget and will earn a
        # proxywidget for it.
        proxywidget = karamba.createCanvasWidget(widget, frame)
        # the following lines demonstrate, how to control the
        # webbrowser using the JavaScript language. The KHTML
        # KPart does provide different signals we are able to
        # connect our own functions too. Just see here the
        # kdelibs/khtml/khtmlpart.h file.
        def selectionChanged():
            print khtml_part.executeScript("window.scrollBy(0,50);");
        khtml_part.connect("selectionChanged()", selectionChanged)
        # and finally we like to load an url and display something.
        khtml_part.openUrl("http://www.kde.org")
     
    def widgetClosed(widget):
        # if the job is done, we may like to free our KPart again.
        if khtml_part:
            khtml_part.delayedDestruct()
    </syntaxhighlight>
     
    ===KSpread===


    The following sample uses KSpread to read a OpenDocument spreadsheet file and to display it within a table.
    The following sample uses KSpread to read a OpenDocument spreadsheet file and to display it within a table.
    Line 323: Line 374:
    While the sample is written in Python, the other supported backends like Ruby are able to access the whole same rich API.
    While the sample is written in Python, the other supported backends like Ruby are able to access the whole same rich API.


    <code python>
    <syntaxhighlight lang="python">
    import karamba, Kross
    import karamba, Kross


    Line 362: Line 413:
         karamba.setRichTextWidth(widget, richtext, 345)
         karamba.setRichTextWidth(widget, richtext, 345)
         karamba.redrawWidget(widget)
         karamba.redrawWidget(widget)
    </code>
    </syntaxhighlight>


    See also...
    See also...
    Line 373: Line 424:
    The following python script shows how to use [http://www.riverbankcomputing.co.uk/pyqt/ PyQt] which provides the nice Qt-API pythonized. The sample just displays a "hello world" dialog if you click on the widget.
    The following python script shows how to use [http://www.riverbankcomputing.co.uk/pyqt/ PyQt] which provides the nice Qt-API pythonized. The sample just displays a "hello world" dialog if you click on the widget.


    <code python>
    <syntaxhighlight lang="python">
    import karamba
    import karamba
    from PyQt4 import QtCore, QtGui
    from PyQt4 import QtCore, QtGui
    Line 388: Line 439:
         dialog = Dialog()
         dialog = Dialog()
         dialog.exec_()
         dialog.exec_()
    </code>
    </syntaxhighlight>


    See also...
    See also...
    Line 398: Line 449:
    You are also able to use the default toolkit Python comes with, that is TkInter. The following sample just displays a TkInter "hello world" dialog if you click on the widget.
    You are also able to use the default toolkit Python comes with, that is TkInter. The following sample just displays a TkInter "hello world" dialog if you click on the widget.


    <code python>
    <syntaxhighlight lang="python">
    import karamba
    import karamba
    from Tkinter import *
    from Tkinter import *
    Line 407: Line 458:
         w.pack()
         w.pack()
         root.mainloop()
         root.mainloop()
    </code>
    </syntaxhighlight>


    See also...
    See also...
    Line 418: Line 469:
    The following sample script written in Ruby demonstrates that you are able to use [http://rubyforge.org/projects/korundum/ QtRuby/Korundum] within your Ruby scripts.
    The following sample script written in Ruby demonstrates that you are able to use [http://rubyforge.org/projects/korundum/ QtRuby/Korundum] within your Ruby scripts.


    <code ruby>
    <syntaxhighlight lang="ruby">
    require 'karamba'
    require 'karamba'
    require 'Qt'
    require 'Qt'
    Line 433: Line 484:
         dialog.exec
         dialog.exec
    end
    end
    </code>
    </syntaxhighlight>


    The script does implement only the widgetClicked function that got called if the user clicks on the widget. What we do within that function is to create an instance of the Dialog class that implements a QDialog using QtRuby and then execute that modal dialog.
    The script does implement only the widgetClicked function that got called if the user clicks on the widget. What we do within that function is to create an instance of the Dialog class that implements a QDialog using QtRuby and then execute that modal dialog.
    Line 445: Line 496:
    The following sample script written in Python just prints a list with services available via [http://dbus.freedesktop.org/ D-Bus];
    The following sample script written in Python just prints a list with services available via [http://dbus.freedesktop.org/ D-Bus];


    <code python>
    <syntaxhighlight lang="python">
    import karamba, dbus
    import karamba, dbus


    Line 461: Line 512:
         karamba.setRichTextWidth(widget, richtext, 500)
         karamba.setRichTextWidth(widget, richtext, 500)
         karamba.redrawWidget(widget)
         karamba.redrawWidget(widget)
    </code>
    </syntaxhighlight>


    While the following Python script uses [http://dbus.freedesktop.org/ D-Bus] to display a list with all the devices accessible with [http://www.freedesktop.org/wiki/Software/hal HAL];
    The following Python script uses [http://dbus.freedesktop.org/ D-Bus] to display a list with all the devices accessible with [http://www.freedesktop.org/wiki/Software/hal HAL];


    <code python>
    <syntaxhighlight lang="python">
    import karamba, dbus
    import karamba, dbus


    Line 481: Line 532:
         karamba.setRichTextWidth(widget, richtext, 500)
         karamba.setRichTextWidth(widget, richtext, 500)
         karamba.redrawWidget(widget)
         karamba.redrawWidget(widget)
    </code>
    </syntaxhighlight>


    While those both samples are going the most easy way to just synchronously call dbus functionality, you are also able to asynchronously call methods or just write a dbus-server by using the with python dbus supported Qt main event-loop as shown in the dbus-python tutorial below - but don't wonder that the samples printed there may not run since it seems the dbus-python module got largely refactored while the with it shipped documentation did not :-/
    While those both samples are going the most easy way to just synchronously call dbus functionality, you are also able to asynchronously call methods or just write a dbus-server by using the with python dbus supported Qt main event-loop as shown in the dbus-python tutorial below - but don't wonder that the samples printed there may not run since it seems the dbus-python module got largely refactored while the with it shipped documentation did not :-/
    Line 489: Line 540:
    * [https://trac.luon.net/data/ruby-dbus/tutorial Ruby D-Bus Tutorial]
    * [https://trac.luon.net/data/ruby-dbus/tutorial Ruby D-Bus Tutorial]
    * [http://webcvs.freedesktop.org/hal/hal/doc/spec/hal-spec.html?view=co HAL Specification]
    * [http://webcvs.freedesktop.org/hal/hal/doc/spec/hal-spec.html?view=co HAL Specification]
    ===Plasma===
    Following scripts are showing how to use the Plasma functionality in SuperKaramba.
    See also...
    * [[Projects/Plasma|Plasma Project]]
    * [http://kross.dipe.org/skapplet.png screenshot]
    * [http://kross.dipe.org/skapplet.mpeg screencast], 2.4MB, mpeg4
    * [http://www.kdedevelopers.org/node/2907 SuperKaramba and Plasma, Part 2]
    * [http://www.kdedevelopers.org/node/3305 SuperKaramba and Plasma Packages]
    * [http://websvn.kde.org/trunk/KDE/kdeutils/superkaramba/examples/plasmaAppletClock/ AppletClock sample]
    ====Plasma::DataEngine as SuperKaramba Sensor====
    Following Python sample demonstrates usage of the Plasma::DataEngine functionality by using the TimeEngine to display the current local time.
    <syntaxhighlight lang="python">
    import karamba
    def initWidget(widget):
        karamba.resizeWidget(widget, 400, 400)
        text = karamba.createText(widget, 10, 10, 380, 380)
        engine = karamba.getPlasmaSensor(widget, "time", "Local")
        connector = engine.connectSource("Local", text)
        connector.setFormat('%Date %Time')
    </syntaxhighlight>
    You are also able to provide an own handle that defines what should be done if the Plasma::DataEngine has new or updated data for an widget or a meter.
    <syntaxhighlight lang="python">
    # Import the SuperKaramba module.
    import karamba
    # This method got called by SuperKaramba on initialization.
    def initWidget(widget):
        karamba.resizeWidget(widget, 400, 400)
        # Create the text-widget (aka meter).
        text = karamba.createText(widget, 10, 10, 380, 380)
        # Create the Plasma::DataEngine sensor.
        engine = karamba.getPlasmaSensor(widget, "time", "Local")
        # Connect the text-widget with the engine.
        connector = engine.connectSource("Local", text)
        # An own handler for the connector.
        def func(source,data):
            # Only display the current time but not the data["Date"].
            karamba.changeText(widget, text, data["Time"])
        # Set empty source else the sourceUpdated() signal will not
        # be emitted.
        connector.setSource("")
        # Connect the sourceUpdated() signal with the handler.
        connector.connect("sourceUpdated(QString,QVariantMap)",func)
    </syntaxhighlight>
    ====Plasma in a SuperKaramba Theme====
    And here is the shortest version that needs only one single line of text. Just put following line into a SuperKaramba theme file;
    <syntaxhighlight lang="text">
    text x=0 y=0 sensor=plasma engine="time" source="Local" format="%Date %Time" poperties="reportSeconds:true,someOtherIntProperty:815"
    </syntaxhighlight>
    ====Plasma and SuperKaramba====
    Now lets take a more detailed look at a longer sample that uses SuperKaramba and the PlasmaApplet module. While the sample above runs in all cases, the following sample does not cause the used PlasmaApplet module will be only available if SuperKaramba is running as Plasma Applet. If you are running SuperKaramba as standalone application this wan't work (is there interest for this? - but both ways provide the same rich API functionality to work with Plasma::DataEngine's anyway).
    <syntaxhighlight lang="python">
    # Import the needed modules.
    import karamba, PlasmaApplet
    # Fetch the TimeEngine Plasma::DataEngine object.
    engine = PlasmaApplet.dataEngine("time")
    # We like to update it each second.
    engine.setProperty("reportSeconds", True)
    # Following lines are here to demonstrate that we are also able
    # to dynamic handle the sources. It's not needed for this sample.
    #def sourceAdded(source):
    #    print "sourceAdded '%s'" % source
    #def sourceRemoved(source):
    #    print "sourceRemoved '%s'" % source
    #def sourceUpdated(source,data):
    #    print "sourceUpdated '%s' '%s'" % (source,data)
    #engine.connect("sourceAdded(QString)", sourceAdded)
    #engine.connect("sourceRemoved(QString)", sourceRemoved)
    #engine.connect("sourceUpdated(QString,QVariantMap)", sourceUpdated)
    # Connect with the TimeEngine's source named "Local"
    engine.connectSource("Local")
    # This is the richedit widget we use to display something.
    text = None
    # This method just returns some text to display.
    def getText():
        t = "name: %s\n" % PlasmaApplet.name()
        t += "category: %s\n" % PlasmaApplet.category()
        t += "boundingRect: %s\n" % PlasmaApplet.boundingRect()
        t += "sources: %s\n" % engine.sources()
        t += "data: %s\n" % engine.query("Local")
        return t
    # This method got called by SuperKaramba on initialization.
    def initWidget(widget):
        global text
        karamba.resizeWidget(widget, 400, 400)
        text = karamba.createText(widget, 10, 10, 380, 380, getText())
        karamba.redrawWidget(widget)
    # This method got called by SuperKaramba on update.
    def widgetUpdated(widget):
        global text
        karamba.changeText(widget, text, getText())
        karamba.redrawWidget(widget)
    </syntaxhighlight>
    Following does the same as the sample above but connects the time Plasma::DataEngine with a meter-widget of SuperKaramba. The script will run once and compared to the sample above it's not needed to provide a widgetUpdated function but SuperKaramba will take care of updating the meter if the time Plasma::DataEngine provides new/updated data.
    <syntaxhighlight lang="python">
    # Import the needed modules.
    import karamba, PlasmaApplet
    # Fetch the TimeEngine Plasma::DataEngine object.
    engine = PlasmaApplet.dataEngine("time")
    # We like to update it each second.
    engine.setProperty("reportSeconds", True)
    # This method got called by SuperKaramba on initialization.
    def initWidget(widget):
        global engine
        karamba.resizeWidget(widget, 400, 400)
        # Create the text-meter widget.
        text = karamba.createText(widget, 10, 10, 380, 380, "")
        # Connect the dataengine with the text-meter.
        connector = engine.connectSource("Local", text)
        # Set the formatting. This is how the data should be
        # displayed. The local time-engine source provides the
        # '%Date' and the '%Time' values.
        connector.setFormat('Date: %Date\nTime: %Time')
       
        # Following lines are here to demonstrate that you are also
        # able to implement an own handler for the connector.
        #def func(source,data):
        #    karamba.changeText(widget, text, data["Time"])
        # Set empty source else the sourceUpdated() signal will not
        # be emitted.
        #connector.setSource("")
        # Connect the sourceUpdated() signal with the handler.
        #connector.connect("sourceUpdated(QString,QVariantMap)",func)
       
        karamba.redrawWidget(widget)
    </syntaxhighlight>

    Latest revision as of 20:56, 29 June 2011

    SuperKaramba

    Intro

    SuperKaramba is a tool that allows one to easily create functionality enhancement modules on a KDE desktop. Such modules are interactive programs written in Python, Ruby or KDE JavaScript that are usually embedded directly into the background and do not disturb the normal view of the desktop.

    Links

    This screenshot shows the Aero AIO Karamba Theme running on KDE4 as Plasmoid (aka Plasma Applet).

    Commands, Meters and Sensors

    SuperKaramba does differ between 3 kind of elements. Commands define something that should be done (actions), meters are used to display something (GUI widgets) while sensors are to get something (data delivery).

    • A list of General Commands that you can put in your theme file. This includes tags that define the widget shape, set default fonts, and create click-areas that launch programs.
    • A list of Meters that you can put in your theme file. This includes meters display the values of sensors. Meters can auto-update.
    • A list of Sensors that you can put in your theme file. Sensors allow you to display system properties automatically. There are sensors to display the status of everything from memory use to the results of shell scripts. See here also the Plasma::DataEngine as SuperKaramba Sensor chapter.

    Basic Tutorial for Theme Creators

    Themes in SuperKaramba consist of two parts. A theme file that defines the shape and size of the theme, and possibly many other things and a script file that adds interactivity to the theme. Basically, whenever an event happens, such as the user clicking the mouse on your theme, a function is called in your script file to let you react to the event.

    Creating the Theme File

    The theme files, those files with the fileextension *.theme, are text files that contain layout information and information about the values that will be shown.

    Theme File Samples

    The simplest form of Karamba is to load a file containing the word karamba. This will give you a empty transparent window with the size 300x300. A better idea is to enter something like this in a file:

    karamba x=30 y=30 w=400 h=200 interval=2000
    

    This will bring up a window at 30,30 with the size 400x200, and the window will refresh every 2000 milliseconds = 2 seconds.

    The graphics elements of Karamba are called meters. The meters can be connected to sensors. A sensor can get, e.g., the current CPU load, the uptime, the date, and a lot of other things. It is also possible to display the output of an external program in a meter.

    Creating a meter is not that hard. A text label can be created by putting this line in the file:

    text x=10 y=10 value="This is a test"
    

    To add some more spice we connect a sensor to a meter:

    text x=15 y=25 sensor=uptime
    

    A graph that logs the CPU load can be made like this:

    graph x=10 y=40 w=200 h=60 sensor=cpu 
    

    Adding an image (the path is either relative to the configuration file or an absolute path):

    image x=10 y=270 path="picture.png"
    

    An introduction to the format parameter for a text meter:

    text x=10 y=330 sensor=memory format="You have %tm MB memory"
    

    Using of a the "time" Plasma::DataEngine:

    text x=0 y=0 sensor=plasma engine="time" source="Local" format="%Date %Time"
    

    Please note that only one meter per line in the configuration file is allowed. No spaces are allowed around the '=' characters.

    Notes

    In Karamba all the graphic elements inside one configuration file have the same refresh rate. So it could be wise to split up a configuration into smaller parts, if different parts need different refresh times. An area showing a log file, for example, probably does not need the same refresh rate as an area showing the CPU load. The refresh rate of the sensors can be set individually. Also Karamba does not work with backgrounds without a picture, i.e., solid color, gradient, or pattern. One can get around this bug by creating a transparent PNG image (the size can be 1x1 pixel) and selecting this as the background picture.

    Creating the Script File

    The script file adds interactivity to the theme and can be written using the Python, Ruby or the KDE JavaScript language.

    Super-Quick Start

    1. Make a theme file like described at the "Creating the Theme File" chapter above.
    2. Download the template.py or the template.rb or the template.js script file, depending on what scripting language you like to use, and rename this file to match your theme file.
    3. Fill in all the callbacks in the script file that you want to handle. The template files just contain all callbacks, but you can safly remove those you don't need or just leave them in.
    4. Use the API Reference to know what commands to use to fill in the callbacks.
    5. Finally save your script file and open your theme file in SuperKaramba to test it!

    Regular Guide for "Mere Mortals"

    Now lets add interactivity to your theme file. If you have not written a theme file yet, you need to do that first like described at the "Creating the Theme File" chapter above. It will define the size, location on screen, and other basic elements of your theme.

    Event-based Programming

    Now that you have a basic theme file, load it with SuperKaramba. If there is nothing defined in the theme file other than size and location, you will have made an empty, transparent square that might be hard to find on the desktop. Let's assume you have made a basic theme that just shows a few images in small area. To make your theme do anything interesting, it needs to be able to react to events.

    Basically, an event is anything that can happen that SuperKaramba knows how to handle. Some examples are: the user moves or clicks the mouse, a new program is started on the desktop, a certain amount of time has passed, etc. So to make your theme do something, you add Python or Ruby scripting code to the event callback that corresponds to the event to which you want to react. This is not nearly as hard as it sounds.

    First, you need the template.py or the template.rb or the template.js template script file, depending on what scripting language you like to use. Download this file to where your theme file is. Now rename those just downloaded template file from template.py to mytheme.py or from template.rb to mytheme.rb where mytheme is the name of your theme. For example, if you wrote a coolbar.theme and like to use use Python, renamed the just downloaded template.py to coolbar.py and put it in the same directory as coolbar.theme.

    Now, lets open up your coolbar.py (or coolbar.rb or whatever you named it to) scripting file. Look for the event callback that reacts to mouse movement. If you chose Python as your prefered scripting language, it may look like this:

    #This gets called everytime our widget is clicked.
    #Notes
    #  widget = reference to our widget
    #  x = x position (relative to our widget)
    #  y = y position (relative to our widget)
    #  botton = button being held:
    #      0 = No Mouse Button
    #      1 = Left Mouse Button
    #      2 = Middle Mouse Button
    #      3 = Right Mouse Button, but this will never happen
    #          because the right mouse button brings up the
    #          Karamba menu.
    def widgetMouseMoved(widget, x, y, button):
        #Warning: Don't do anything too intensive here since you don't
        #want to run complex piece of code everytime the mouse moves.
        pass
    

    Notice how the template gives your instructions on what data each callback gives you. In this case, you can see that you will know the x and y co-ordinates of the mouse, the button being held down (if any), and a reference to your widget.

    Delete the line that says pass and add in some code. This code will run whenever the mouse is moved over your widget. But you say, "What in the world am I supposed to write to make something happen?". Good question! Go on to the next section below!

    How to "make stuff happen" from your script file

    SuperKaramba has a powerful API (Application Programmer's Interface). This is just a fancy way of saying SuperKaramba has a bunch of special commands you can run from your Python or your Ruby scripting code to make something happen in your theme. All of the commands are listed in one big list:

    Here is how the callback might look after you add some code to it:

    def widgetMouseMoved(widget, x, y, button):
        myText = karamba.getThemeText(widget, "mouseText")
        karamba.changeText(widget, myText, "mouse at %s:%s" % (x,y))
    

    This Python scripting code simply changes the text called "mouseText" (which we defined in our theme file) to tell us the current position of the mouse.

    How did I know what parameters karamba.changeText() and karamba.getThemeText() used? How did I even know those functions existed in the first place? Well, thats what the API tells you. The API and the template.py or template.rb script file basically contain everything you could ever need to know to write your own theme.

    Testing!

    To test your new Python or Ruby scripting code, just open your theme file in SuperKaramba.

    You DO NOT open your .py or .rb file in SuperKaramba! Open the .theme file and if a matching .py or .rb file is found, it will be automatically loaded.

    You DO NOT need to compile your scripting code. SuperKaramba will do that automatically and tell you about any errors. In fact, you can't run your .py or .rb file directly in regular python because it doesn't know anything about the karamba.* functions. Those functions only exist inside of SuperKaramba's Python and Ruby interpreters. But you are for sure able to just use SuperKaramba as your interpreter direct from within the commandline. Just start SuperKaramba with something like:

    superkaramba ./coolbar.theme
    

    To ease the development, SuperKaramba will automatically reload your theme when you save your changes to the theme file or the script file. This allows you to see your modifications immediately without reloading the theme manually.

    Have fun making themes!

    FAQ

    SuperKaramba on KDE4

    While we were able to see a lot of rumours and speculations regarding SuperKaramba and it's role on KDE4, it's planned to continue to support SuperKaramba and it's unique feature-set, the bunches of themes that do already exist and those that will be written. We will stay backward-compatible and rocking stable, improve the feature-set as needed and wish you fun with the result: the next generation of SuperKaramba :)

    SuperKaramba and Plasma

    SuperKaramba runs as standalonea-application - just run the program "superkaramba" - as well as Plasma Applet embedded into the Plasma Workspace. Also SuperKaramba provides full and transparent access to the Plasma::DataEngine's with it's sensor functionality.

    See also the Plasma script samples section.

    Scripting Interpreter Backends

    SuperKaramba uses the Kross scripting framework to provide scripting with Python, Ruby and JavaScript as described at the Interpreter plugins section.

    Defining Python Source Code Encodings

    As described at the Python Enhancement Proposal Defining Python Source Code Encodings it is recommed to start a python script file with following both lines:

    #!/usr/bin/env superkaramba
    # coding: utf-8
    

    The first line is the shebang that causes Unix-like operating systems to execute the script file using the SuperKaramba interpreter. You are then able to start the karamba script with;

    chmod 755 myKaramba.py
    ./myKaramba.py
    

    The second line defines that the script file is encoded with utf-8 or whatever the script file is actualy encoded in. This seems to be needed at least with Python >=2.5.

    Script Samples

    A clock with Ruby, Python and JavaScript

    Let's take a look at one of them, the clock.rb theme written in Ruby. The theme just displays the current time in a RichText widget.

    require 'karamba'
    
    def initWidget(widget)
        Karamba.resizeWidget(widget, 300, 120)
        @richtext = Karamba.createRichText(widget, Time.now.to_s)
        Karamba.moveRichText(widget, @richtext, 10, 10)
        Karamba.setRichTextWidth(widget, @richtext, 280)
        Karamba.redrawWidget(widget)
    end
    
    def widgetUpdated(widget)
        Karamba.changeRichText(widget, @richtext, Time.now.to_s)
        Karamba.redrawWidget(widget)
    end
    

    The initWidget method will be called once if the widget got initialized. Here we setup the RichText widget where we display the current time in. The widgetUpdated will be called each second once (the interval is defined in the clock.theme themefile) and just updates the text display in the RichText widget with the new time.

    Let's take a look at another theme. The text.py theme written in Python just displays some text widgets. We take this as example to create our own script, that does the same as the clock.rb above, that is to display the current time within a text widget.

    import karamba, time
    
    text = None
    
    def getTime():
        return time.strftime("%Y-%M-%d %H:%M.%S")
    
    def initWidget(widget):
        global text
        text = karamba.createText(widget, 10, 10, 200, 120, getTime())
        karamba.moveText(widget, richtext, 10, 10)
        karamba.redrawWidget(widget)
    
    def widgetUpdated(widget):
        global text
        karamba.changeText(widget, text, getTime())
        karamba.redrawWidget(widget)
    

    In the initWidget method we create our text widget that is updated once per second (or per interval as defined in the matching theme file) at the widgetUpdated method to display the new current time.

    The clock.js sample provides us with the same sample written using the JavaScript language.

    There we have the currentTime() function that returns the current time as string. That function is used within the initWidget() and the widgetUpdated() functions to display the current time within a textwidget.

    var text = 0;
    
    function currentTime() {
        var now = new Date();
        var hours = now.getHours();
        hours = hours < 10 ? '0' + hours : hours;
        var mins = now.getMinutes();
        mins = mins < 10 ? '0' + mins : mins;
        var secs = now.getSeconds();
        secs = secs < 10 ? '0' + secs : secs;
        return hours + ':' + mins + '.' + secs;
    }
    
    function initWidget(widget) {
        text = karamba.createText(widget,0,20,200,20,currentTime());
    }
    
    function widgetUpdated(widget) {
        karamba.changeText(widget,text,currentTime());
        karamba.redrawWidget(widget)
    }
    

    See also...

    Forms and Modules

    Modules are libraries loaded on demand provided by Kross. One of them is the forms module that implements some basic dialog and widget functionality. To display just a simple messagebox or load widgets from a UI-file those module can be used within all supported scripting languages.

    The following sample Python script demonstrates how to display a messagebox.

    import karamba, Kross
    
    def widgetClicked(widget, x, y, button):
        forms = Kross.module("forms")
        if button == 1: #left
            forms.showMessageBox("Information","Caption","Message")
        elif button == 2: #middle
            forms.showMessageBox("Error","Caption","Message")
    

    While the next sample Python script displays a dialog with an embedded "Open File" widget.

    import karamba, Kross
    
    def widgetClicked(widget, x, y, button):
        forms = Kross.module("forms")
        dialog = forms.createDialog("MyDialog")
        dialog.setButtons("Ok|Cancel")
        openpage = dialog.addPage("Open","Open File","fileopen")
        openwidget = forms.createFileWidget(
            openpage, "kfiledialog:///openfile")
        openwidget.setMode("Opening")
        openwidget.setFilter("*.txt|Text Files\n*|All Files")
        result = dialog.exec_loop()
        if result:
            print openwidget.selectedFile()
    

    For sure you are also able to use those handy UI-files the QtDesigner produces like demonstrated on the sample below.

    import karamba, os, Kross
    
    def widgetClicked(widget, x, y, button):
        forms = Kross.module("forms")
        dialog = forms.createDialog("Sample")
        infospage = dialog.addPage("Title","Caption","iconname")
        # the ui-file is in the same directory our script is in
        uifile = os.path.join(karamba.getThemePath(),"my.ui")
        infoswidget = forms.createWidgetFromUIFile(infospage, uifile)
        if dialog.exec_loop():
            # here we print the content of the in the ui-file defined
            # lineedit-widget that has the name MyLineEdit
            print infoswidget["MyLineEdit"].text
    

    Embed KHTML Webbrowser

    Starting with Qt 4.4 and KDE 4.1 SuperKaramba is able to embed any kind of QWidgets into the canvas that is used to display something. That means, you are able to add a QLabel, a QPushButton or any other widget just direct into your Karambas.

    The following python sample code, which is also available as webbrowser.py, demonstrates this by embedding a full webbrowser into your Karamba by using the CanvasWidget functionality.

    #!/usr/bin/env superkaramba
    # coding: utf-8
    
    import karamba, Kross
    khtml_part = None
    
    def initWidget(widget):
        # the Kross forms module does provide methods to create
        # widgets for us. You are for example able to load a UI
        # file, create layouts or just any other supported widget.
        forms = Kross.module("forms")
        frame = forms.createWidget("QWidget")
        forms.createLayout(frame, "QHBoxLayout")
        # here we load the KHTML KPart that is our full powered
        # webbrowser widget.
        khtml_part = forms.loadPart(frame, "libkhtmlpart")
        khtml_part.javaScriptEnabled = True
        khtml_part.javaEnabled = False
        khtml_part.pluginsEnabled = False
        # now we add the frame to our widget and will earn a
        # proxywidget for it.
        proxywidget = karamba.createCanvasWidget(widget, frame)
        # the following lines demonstrate, how to control the
        # webbrowser using the JavaScript language. The KHTML
        # KPart does provide different signals we are able to
        # connect our own functions too. Just see here the
        # kdelibs/khtml/khtmlpart.h file.
        def selectionChanged():
            print khtml_part.executeScript("window.scrollBy(0,50);");
        khtml_part.connect("selectionChanged()", selectionChanged)
        # and finally we like to load an url and display something.
        khtml_part.openUrl("http://www.kde.org")
    
    def widgetClosed(widget):
        # if the job is done, we may like to free our KPart again.
        if khtml_part:
            khtml_part.delayedDestruct()
    

    KSpread

    The following sample uses KSpread to read a OpenDocument spreadsheet file and to display it within a table.

    For this we are loading the KSpread Scripting library and control it. Compared to dbus we don't need a running KSpread instance but just load and use the library direct (so, you still need to have KSpread installed).

    While the sample is written in Python, the other supported backends like Ruby are able to access the whole same rich API.

    import karamba, Kross
    
    # The OpenDocument spreadsheet file to read.
    filename = "/home/kde4/kspreaddocument.ods"
    
    # This is called when your widget is initialized
    def initWidget(widget):
        # Fetch the KSpread module.
        kspread = Kross.module("kspread")
        if not kspread:
            raise "KSpread is not installed"
        # Try to open the file.
        if not kspread.openUrl(filename):
            raise "Failed to open %s" % filename
        # Get the sheet we like to display.
        sheet = kspread.sheetByName( kspread.sheetNames()[0] )
        text = "<table>\n"
        # Iterate now through all cells on the sheet.
        for row in range(1, sheet.lastRow() + 1):
            # Put the content of the row into the record-list.
            record = []
            for col in range(sheet.lastColumn() + 1, 1, -1):
                value = sheet.text(col, row)
                if value or len(record) > 0:
                    record.insert(0,value)
            # If the record has at least one cell print it.
            if len(record) > 0:
                text += "<tr>"
                for r in record:
                    text += "<td>%s</td>" % r
                text += "</tr>\n"
        text += "</table>\n"
    
        # Create the richtext widget to display the text.
        richtext = karamba.createRichText(widget, text)
        karamba.moveRichText(widget, richtext, 10, 10)
        karamba.setRichTextWidth(widget, richtext, 345)
        karamba.redrawWidget(widget)
    

    See also...

    PyQt with Python

    The following python script shows how to use PyQt which provides the nice Qt-API pythonized. The sample just displays a "hello world" dialog if you click on the widget.

    import karamba
    from PyQt4 import QtCore, QtGui
    
    def initWidget(widget):
        karamba.resizeWidget(widget, 200, 200)
    
    def widgetClicked(widget, x, y, button):
        class Dialog(QtGui.QDialog):
            def __init__(self):
                QtGui.QWidget.__init__(self)
                label = QtGui.QLabel(self)
                label.setText("Hello World")
        dialog = Dialog()
        dialog.exec_()
    

    See also...

    TkInter with Python

    You are also able to use the default toolkit Python comes with, that is TkInter. The following sample just displays a TkInter "hello world" dialog if you click on the widget.

    import karamba
    from Tkinter import *
    
    def widgetClicked(widget, x, y, button):
        root = Tk()
        w = Label(root, text="Hello, world!")
        w.pack()
        root.mainloop()
    

    See also...

    QtRuby/Korundum with Ruby

    The following sample script written in Ruby demonstrates that you are able to use QtRuby/Korundum within your Ruby scripts.

    require 'karamba'
    require 'Qt'
    
    class Dialog < Qt::Dialog
        def initialize
            super()
            self.windowTitle = 'Hello World'
        end
    end
    
    def widgetClicked(widget, x, y, button)
        dialog = Dialog.new
        dialog.exec
    end
    

    The script does implement only the widgetClicked function that got called if the user clicks on the widget. What we do within that function is to create an instance of the Dialog class that implements a QDialog using QtRuby and then execute that modal dialog.

    See also...

    D-Bus

    The following sample script written in Python just prints a list with services available via D-Bus;

    import karamba, dbus
    
    def initWidget(widget):
        bus = dbus.SystemBus()
        dbus_object = bus.get_object(
            'org.freedesktop.DBus','/org/freedesktop/DBus')
        dbus_iface = dbus.Interface(
            dbus_object, 'org.freedesktop.DBus')
        services = dbus_iface.ListNames()
        text = "".join( ["%s<br>" % s for s in services] )
        karamba.resizeWidget(widget, 520, 520)
        richtext = karamba.createRichText(widget, text)
        karamba.moveRichText(widget, richtext, 10, 10)
        karamba.setRichTextWidth(widget, richtext, 500)
        karamba.redrawWidget(widget)
    

    The following Python script uses D-Bus to display a list with all the devices accessible with HAL;

    import karamba, dbus
    
    def initWidget(widget):
        bus = dbus.SystemBus()
        dbus_object = bus.get_object(
            'org.freedesktop.Hal','/org/freedesktop/Hal/Manager')
        dbus_iface = dbus.Interface(
            dbus_object, 'org.freedesktop.Hal.Manager')
        devices = dbus_iface.GetAllDevices()
        text = "".join( ["%s<br>" % d for d in devices] )
        karamba.resizeWidget(widget, 520, 520)
        richtext = karamba.createRichText(widget, text)
        karamba.moveRichText(widget, richtext, 10, 10)
        karamba.setRichTextWidth(widget, richtext, 500)
        karamba.redrawWidget(widget)
    

    While those both samples are going the most easy way to just synchronously call dbus functionality, you are also able to asynchronously call methods or just write a dbus-server by using the with python dbus supported Qt main event-loop as shown in the dbus-python tutorial below - but don't wonder that the samples printed there may not run since it seems the dbus-python module got largely refactored while the with it shipped documentation did not :-/

    See also...

    Plasma

    Following scripts are showing how to use the Plasma functionality in SuperKaramba.

    See also...

    Plasma::DataEngine as SuperKaramba Sensor

    Following Python sample demonstrates usage of the Plasma::DataEngine functionality by using the TimeEngine to display the current local time.

    import karamba
    def initWidget(widget):
        karamba.resizeWidget(widget, 400, 400)
        text = karamba.createText(widget, 10, 10, 380, 380)
        engine = karamba.getPlasmaSensor(widget, "time", "Local")
        connector = engine.connectSource("Local", text)
        connector.setFormat('%Date %Time')
    

    You are also able to provide an own handle that defines what should be done if the Plasma::DataEngine has new or updated data for an widget or a meter.

    # Import the SuperKaramba module.
    import karamba
    # This method got called by SuperKaramba on initialization.
    def initWidget(widget):
        karamba.resizeWidget(widget, 400, 400)
        # Create the text-widget (aka meter).
        text = karamba.createText(widget, 10, 10, 380, 380)
        # Create the Plasma::DataEngine sensor.
        engine = karamba.getPlasmaSensor(widget, "time", "Local")
        # Connect the text-widget with the engine.
        connector = engine.connectSource("Local", text)
        # An own handler for the connector.
        def func(source,data):
            # Only display the current time but not the data["Date"].
            karamba.changeText(widget, text, data["Time"])
        # Set empty source else the sourceUpdated() signal will not
        # be emitted.
        connector.setSource("")
        # Connect the sourceUpdated() signal with the handler.
        connector.connect("sourceUpdated(QString,QVariantMap)",func)
    

    Plasma in a SuperKaramba Theme

    And here is the shortest version that needs only one single line of text. Just put following line into a SuperKaramba theme file;

    text x=0 y=0 sensor=plasma engine="time" source="Local" format="%Date %Time" poperties="reportSeconds:true,someOtherIntProperty:815"
    


    Plasma and SuperKaramba

    Now lets take a more detailed look at a longer sample that uses SuperKaramba and the PlasmaApplet module. While the sample above runs in all cases, the following sample does not cause the used PlasmaApplet module will be only available if SuperKaramba is running as Plasma Applet. If you are running SuperKaramba as standalone application this wan't work (is there interest for this? - but both ways provide the same rich API functionality to work with Plasma::DataEngine's anyway).

    # Import the needed modules.
    import karamba, PlasmaApplet
    # Fetch the TimeEngine Plasma::DataEngine object.
    engine = PlasmaApplet.dataEngine("time")
    # We like to update it each second.
    engine.setProperty("reportSeconds", True)
    
    # Following lines are here to demonstrate that we are also able
    # to dynamic handle the sources. It's not needed for this sample.
    #def sourceAdded(source):
    #    print "sourceAdded '%s'" % source
    #def sourceRemoved(source):
    #    print "sourceRemoved '%s'" % source
    #def sourceUpdated(source,data):
    #    print "sourceUpdated '%s' '%s'" % (source,data)
    #engine.connect("sourceAdded(QString)", sourceAdded)
    #engine.connect("sourceRemoved(QString)", sourceRemoved)
    #engine.connect("sourceUpdated(QString,QVariantMap)", sourceUpdated)
    
    # Connect with the TimeEngine's source named "Local"
    engine.connectSource("Local")
    
    # This is the richedit widget we use to display something.
    text = None
    
    # This method just returns some text to display.
    def getText():
        t = "name: %s\n" % PlasmaApplet.name()
        t += "category: %s\n" % PlasmaApplet.category()
        t += "boundingRect: %s\n" % PlasmaApplet.boundingRect()
        t += "sources: %s\n" % engine.sources()
        t += "data: %s\n" % engine.query("Local")
        return t
    
    # This method got called by SuperKaramba on initialization.
    def initWidget(widget):
        global text
        karamba.resizeWidget(widget, 400, 400)
        text = karamba.createText(widget, 10, 10, 380, 380, getText())
        karamba.redrawWidget(widget)
    
    # This method got called by SuperKaramba on update.
    def widgetUpdated(widget):
        global text
        karamba.changeText(widget, text, getText())
        karamba.redrawWidget(widget)
    

    Following does the same as the sample above but connects the time Plasma::DataEngine with a meter-widget of SuperKaramba. The script will run once and compared to the sample above it's not needed to provide a widgetUpdated function but SuperKaramba will take care of updating the meter if the time Plasma::DataEngine provides new/updated data.

    # Import the needed modules.
    import karamba, PlasmaApplet
    # Fetch the TimeEngine Plasma::DataEngine object.
    engine = PlasmaApplet.dataEngine("time")
    # We like to update it each second.
    engine.setProperty("reportSeconds", True)
    
    # This method got called by SuperKaramba on initialization.
    def initWidget(widget):
        global engine
        karamba.resizeWidget(widget, 400, 400)
    
        # Create the text-meter widget.
        text = karamba.createText(widget, 10, 10, 380, 380, "")
    
        # Connect the dataengine with the text-meter.
        connector = engine.connectSource("Local", text)
    
        # Set the formatting. This is how the data should be
        # displayed. The local time-engine source provides the
        # '%Date' and the '%Time' values.
        connector.setFormat('Date: %Date\nTime: %Time')
        
        # Following lines are here to demonstrate that you are also
        # able to implement an own handler for the connector.
        #def func(source,data):
        #    karamba.changeText(widget, text, data["Time"])
        # Set empty source else the sourceUpdated() signal will not
        # be emitted.
        #connector.setSource("")
        # Connect the sourceUpdated() signal with the handler.
        #connector.connect("sourceUpdated(QString,QVariantMap)",func)
        
        karamba.redrawWidget(widget)