Tuesday, June 7, 2011

Tutorial: Plasma+QML

 In this tutorial I will attempt to teach you how to write a simple plasma widget using qml technology. I hope you find this informative! And I am sure some of the expert plasma widget developers will be able to offer some excellent additions to this tutorial in the comments!  Before you start, I'd recommend you familiarize yourself with QML using this site: QDeclarative Introduction
(This post has some color coded sections, I am not sure that they will render properly on the planet, so if you feel you the color coding would help and you can't see it you may have to come to the blog itself.)


I.  Setting Up
   First thing is first, we need to setup the directory where we will be creating the widget.
  1. Create a directory with the name of the widget we will call ours in this example "plasma-qml"
  2. Create  a text file inside this directory called metadata.desktop
  3. Create a directory inside the plasma-qml directory called "contents" 
  4. Create a directory inside "contents" called "ui
  5. Create a text file inside "ui" called "main.qml"
We could actually create all the folders automatically using  the following command in a console:  mkdir -p plasma-qml/contents/ui


Now we've set up the basic file structure for the widget. You'll notice there are only two editable items in what we've created, the .desktop file and the .qml file. The .desktop file will contain basic information about the plasma widget. The .qml file is where we will put the actual code for the widget. More complex plasma widgets will likely have more files in them.

II. metadata.desktop
 Set the contents of the metadata.desktop file as follows. 
 [Desktop Entry]
Name=Plasma-QML
Comment=A test widget for Plasma using QML
Icon=chronometer

X-Plasma-API=declarativeappletscript
X-Plasma-MainScript=ui/main.qml
X-Plasma-DefaultSize=200,100

X-KDE-PluginInfo-Author=Ahmed Ghonim
X-KDE-PluginInfo-Email=zrchrn@gmail.com
X-KDE-PluginInfo-Website=zrchrn.blogspot.com
X-KDE-PluginInfo-Category=Examples
X-KDE-PluginInfo-Name=org.kde.Plasma-qml
X-KDE-PluginInfo-Version=0.1

X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true
X-KDE-ServiceTypes=Plasma/Applet
Type=Service
  The first block deals with the name, description, and icon of the plasmoid. This is important for what users will see when they are trying to add your plasmoid.  
  The second block deals with what type of widget it is, where the main script is, how big the default widget size should be.  If it was written in python it would say "X-Plasma-API=python" 
  The remaining blocks are mostly self explanatory please refer to techbase.kde.org for more information.

III. main.qml
 Now to the meat and potates of the whole thing. What you all have been waiting for, the actual code that does something!

 import Qt 4.7
 import org.kde.plasma.graphicswidgets 0.1 as PlasmaWidgets

Item {
 id: 'item'
 PlasmaWidgets.PushButton {
  id:btn1
  anchors { left: parent.left
                    bottom: parent.bottom
                    top: parent.top
                  }
  text: "This is a Button!"
  onClicked: {print("hello Konsole") ;  lbl.text= " hello label"}
                                                    }

 PlasmaWidgets.Label {
  id: lbl
  anchors { right: parent.right
                    bottom: parent.bottom
                    top: parent.top
                    left: btn1.right
                  }
  text: " This is a Label!"
                                         }
 }
  The main differences between this and the QML examples you read about are:
   1. import org.kde.plasma.graphicswidgets 0.1 as PlasmaWidgets
      this line imports Plasma's graphicswidgets such as PushButtons and Labels so that we can use them in our widget.
   2. PlasmaWidgets.PushButton  (also PlasmaWidgets.Label)
      these aren't QML widgets so we must have the import line listed above to use these.
 Please feel free to ask questions in the comments section about the rest of this code I feel that would be easier than attempting to explain it which would probably be better done in a QML specific tutorial and most of which has been adequately done in the linked QML tutorial. 

IV. Testing
 Now lets test this! Using a console go into the "plasma-qml" directory and  enter the following command: plasmoidviewer
This should give you a preview of your plasmoid. If there is an error  it will display that instead, read the error and find the offending code and fix it.

V. Installing
  To install this we would go to the console. Inside the "plasma-qml" directory  enter the following command: plasmapkg -i ./

 Next run kbuildsycoca4 by entering the command in a console (I'm not sure if this always necessary).

  Now you can add the Plasma-Qml widget like you would any other! Congratulations you have created and installed your first Plasma widget!
As an exercise try making a calculator widget.

IV. References
    I used the following tutorials and this one is based on them. Please use them for more information. In general techbase.kde.org is your main resource for kde development.
       Techbase Plamsa/QML
       Techbase Plasma/Javascript
       For more on QML examples

Update:
From Daker Fernandes Pinheiro: "It's important to let clear that once the Plasma Components http://codecereal.blogspot.com/2011/05/plasma-components.html is ready, the QWidgetProxy solution will be deprecated. These components must follow a common API: http://bugreports.qt.nokia.com/browse/QTCOMPONENTS-200. As I explain in the post, many of these items already can be used, and I'm planning to integrate the done components in master branch in a few weeks."

     

7 comments:

  1. Thanks for this tutorial.
    When I try to install the plasmoid. plasmapkg tells me the he wasn't able to create the folder /home/XXXXXX/.kde/share/apps/plasma/plasmoids//org.kde.Plasma-qml/contents
    I can manually create the path... do you know what's happening ?

    ReplyDelete
  2. It's important to let clear that once the Plasma Components http://codecereal.blogspot.com/2011/05/plasma-components.html is ready, the QWidgetProxy solution will be deprecated. These components must follow a common API: http://bugreports.qt.nokia.com/browse/QTCOMPONENTS-200. As I explain in the post, many of these items already can be used, and I'm planning to integrate the done components in master branch in a few weeks.

    ReplyDelete
  3. @ Anonymous: Hmm, I'm not sure but that sounds like it might be a permissions error but I can't be sure, can you post the actual error? Also were you able to test the widget successfully before installing?

    @Pinheiro yup I updated to add your comments (I hope you don't mind). Thanks!

    ReplyDelete
  4. I have a little question, what does the "print()" statement actually does, couldn't find it in the qml tutorial, they only use console.log().

    ReplyDelete
  5. @damipereira
    Good question! It basically prints to the console. You could just use console.log(). I used print() as it is more obvious to people who know python. To be honest I'm not even sure where I first saw it being used or of any detailed differences. I am only recently learning "javascript".

    ReplyDelete
  6. Thanks for the answer, and something obvious (might be useful to mention), you need qt 4.7 to run this.
    1 unrelated question: do you know how long is qml startup? For example in the case of a kickoff qml replacement

    ReplyDelete
  7. Not sure to be honest. I don't know that it would be noticeable.

    ReplyDelete