== App Developer Week -- Widgetcraft: The Art of Creating Plasma Widgets -- apachelogger -- Mon, Apr 11th, 2011 == {{{#!irc [20:01] salut, bonjour and welcome to an introduction to Widgetcraft oh my :) [20:01] ...also known as the art of creating Plasma Widgets. [20:01] my name is Harald Sitter and I am developer of KDEish things [20:02] for this session you will need a couple of packages and any handy editor you like === ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || Event: Ubuntu App Developer Week - Current Session: Widgetcraft: The Art of Creating Plasma Widgets - Instructors: apachelogger [20:02] sudo apt-get install kdebase-workspace-bin kdebase-runtime plasma-dataengines-workspace [20:02] Logs for this session will be available at http://irclogs.ubuntu.com/2011/04/11/%23ubuntu-classroom.html following the conclusion of the session. [20:02] this comand will make sure you get the packages necessary [20:02] if the editor can do syntax highlighting for javascript it would be good :) [20:02] meanwhile I am going to talk a bit about the technology we are going to work with [20:03] plasma is the technology most people refer to as "the KDE desktop" [20:03] or "the KDE workspace" if you will [20:03] Plasma is just about everything you see when you log into a newly installed KDE system (such as Kubuntu ;)) [20:04] it is the wallpaper, and the panel at the bottom, and every icon and element within that panel and so on [20:04] it comes in many amazing favors and creating new ones is not all that difficult [20:04] by favors I mean specific versions of plasma for different form factors (i.e. devices) [20:05] currently there are plasma versions for desktop system, netbook systems, mobile devices (such as phones) and even tablets [20:05] although the latter 2 are actually more like tech previews and not terribly usable at this time [20:06] plasma widgets are widgets for plasma (surprise ;)) [20:06] they are also called plasmoids... in particular plasma widget usually means a widget that can run in plasma [20:06] this includes apple dashboard widgets, google gadgets and native plasma widgets [20:07] those native widgets are the ones called plasmiods [20:08] plamoids make best usage of plasma's abilities and can be writen in javascript (including qml in KDE 4.6+), c++, ruby and python [20:08] however only javascript and c++ are builtin (thus always available) [20:08] so, usually you want to use on of those [20:09] personally I would even go as far as saying that javascript is the weapon of choice unless you have good reasons to choose anoter language [20:09] the reason for this is that javascript is of course easier to deploy (as it does not need compliation compared to c++) and is always available on every plasma system (unlike ruby and python) [20:10] we also use javscript in this session ;) [20:10] plasmoids are distributed as so called "plasmagik packages" (what a name!) [20:11] they essentially contain one metadata file to describe the plasmoid at hand as well as code, images and other magic files [20:11] for more information have a look at http://community.kde.org/Plasma/Package [20:11] QUESTION: can we use Qt/C++ [20:12] as explained, one can use C++, however there is no particular gain from this for the usual plasmoid [20:12] as the javascript API iis very powerful [20:12] If there are no moar questions we can move on to hacking [20:13] a common step when creating a new plasmoid is setting up the folder structure, for this you can use this magic command sequence of mine: }}} {{{#!highlight bash NAME=dont-blink # Set a shell variable mkdir -p $NAME/contents/code/ # Create everything up to the code dir. touch $NAME/metadata.desktop # Create the metadata file, which contains name and description... touch $NAME/contents/code/main.js # Create main code file of the plasmoid. }}} {{{#!irc [20:13] this will create a bare setup for a new plasmoid [20:13] in the folder dont-blink [20:14] QUESTION: can we create plasmoids in Ubuntu/Gnome and of course, test it on Kubuntu? [20:14] yes [20:14] testing can be done in gnome too [20:14] however unfortunately at this point there is no actual widget integration, so the plasmoids will only work in KDE with Plasma [20:15] movig on [20:15] first we will need to setup our metadata file [20:15] http://people.ubuntu.com/~apachelogger/uadw/04.11/dont-blink/metadata.desktop [20:15] is a good starting point [20:15] I believe the file is pretty easy to understand, it simply defines the general properties of our plasmoid [20:16] name, license, author, version etc. [20:16] usually you will want to change at least Name and X-KDE-PluginInfo-Name [20:16] now we can already get our hands dirty [20:17] Pleaes open the contents/code/main.js code file in your editor. [20:17] let's start with a semi-helloworld thing :) }}} {{{#!cplusplus // First create a layout we can stuff things into layout = new LinearLayout(plasmoid); // layouts are very handy as we can put just about anything in there // and they will automagically figure out how to align stuff // (well, almost automagically ;)) // Then create a label to display our text label = new Label(plasmoid); // Add the label to the layout layout.addItem(label); // Set the text of our Label label.text = 'Don\'t Even Blink'; // Done }}} {{{#!irc [20:18] not terribly difficult, right? :) [20:19] you can now run this using plasmoidviewer . or plasmoidviewer PATHTOTHEPLASMOID (depending on where you are in a terminal right now). [20:19] this works on both KDE and GNOME [20:19] and XFCE and .... [20:20] plasmoidviewer is a very nice app to test plasmiods as you do not need to install the plasmoid to test it [20:20] Here is a trick. If you have KDE 4.5 (default on Kubuntu 10.10) you will have a new command called 'plasma-windowed' using this command you can run most Plasmoids just like any other application in a window, is that not brilliant? [20:20] for example you can try that on our new plasmoid [20:21] or if you have the facebook plasmoid installed, you can try it with that [20:21] very handy to run plasmoids as sort-of real applications [20:21] I hope everyone got our first code working by now [20:22] maybe let us continue with a buttons [20:22] buttons are cool [20:22] oh, in case you have not noticed, code lines are always indeted by 4 characters for your reading pleasure }}} {{{#!cplusplus // Create a new button button = new PushButton; // Add the button to our layout layout.addItem(button); // Give the button some text button.text = 'Do not EVER click me'; }}} {{{#!irc [20:23] if you try the plasmoid now you will notice quite the sillyness [20:23] the layout placed the button next to the text [20:24] not so awesome :( [20:24] and apachelogger claimed layouts are awesome -.- [20:24] oh well [20:24] easily fixable [20:24] the problem is that the layout by default tries to place things next to each other rather than align them vertically }}} {{{#!cplusplus // Switch our layout to vertical alignment layout.orientation = QtVertical; }}} {{{#!irc [20:24] now this should look *much* better [20:25] well [20:25] our button does not do anythign yet [20:25] that is a bit boring I might say ... and useless [20:26] hwo about adding an image into the mix ? ;) [20:26] QUESTION: why is it QtVertical? and not just Vertical like other widgets? [20:27] QtVertical is actually coming from Qt and not from Plasma, as to avoid name clashes in the future I suppose it got prefixed with Qt ;) [20:27] generally speaking layout orientation in C++ Qt is also an enum in the Qt namespace, so it looks pretty much the same [20:27] but now for our image [20:28] if you still have the same terminal you created the bare folder structure in you can use the following: }}} {{{#!highlight bash mkdir -p $NAME/contents/images/ wget -O $NAME/contents/images/troll.png http://people.ubuntu.com/~apachelogger/uadw/04.11/dont-blink/contents/images/troll.png }}} {{{#!irc [20:28] otherwise jsut navigate to your plasmoid folder, go to contents and create an images folder, then download http://people.ubuntu.com/~apachelogger/uadw/04.11/dont-blink/contents/images/troll.png into that folder [20:29] Now for the code... }}} {{{#!cplusplus // Labels can also contain images, so we will use a label again troll = new Label(plasmoid); // But this time we set an image. The image path is constructed automatically by us // telling it in what directory it is and what name it has troll.image = plasmoid.file("images", "troll.png"); // So that our image fits in we need to tell the label to consume // as much space as possible and necessary troll.sizePolicy = QSizePolicy(QSizePolicyMaximum, QSizePolicyMaximum); // We only want to show the image after the user dared pressing the button, // so we set it not visible and also do not add it to our layout troll.visible = false; }}} {{{#!irc [20:30] that will not actually do anything [20:30] as the troll is set to invisible by default [20:31] we only show it once the user clicked on the button [20:32] so this leads us to a very interesting part of Plasma in specific and Qt in particular [20:32] connecting a state change on one thing to an action [20:32] usually in Qt we call this the signal and slot system [20:33] in javascript plasmoids we have almost the same thing, in fact it is even simpler than in standard c++ [20:33] so [20:33] let us try that }}} {{{#!cplusplus // First add a function to handle clicking on the button function onClick() { // within that function we put our logic for changing the visibility of our troll // Either the troll is shown or it is not... // If it is visible -> hide it if (troll.visible) { }}} {{{#!irc [20:35] ah, this is getting complicated [20:35] lets stop here for a bit [20:35] so, our troll can be visible and invisible and we change this via .visible and we read it via .visible [20:36] this might be a bit confusing for those of us who drive ourselfs crazy with C++ ;) [20:37] however, it is really something very Qt [20:37] Qt adds property functionality to objects, which is really what we are seeing here [20:37] our label has a property visibile [20:37] and this property has a "setter" and a "getter" [20:38] depending on the context we can therefore use .visible as getter or setter [20:38] very handy :D [20:38] (as we will have some QML sessions later this week ... this is also how QML elements work for the better part ;)) [20:38] now, moving on... [20:39] we were writing our onClick function, in particular the logic for when the troll is already visible }}} {{{#!cplusplus // Make it invisible troll.visible = false; // And remove it from the layout, so that it does not take up space layout.removeItem(troll); // I think changing the visibility should be clear now ... // but that removing there is a bit confusing // * apachelogger apparently did not prepare very well :P // so let me show you the rest of the onClick function and explain this afterwards } else { // If it is not visible -> show it // Once our button gets clicked we want to show an image. troll.visible = true; // Finally we add the new image to our layout, so it gets properly aligned layout.addItem(troll); } } }}} {{{#!irc [20:40] so, depending on the state of visibility we simply do inverted actions [20:40] possibly you noticed earlier on that we did not add the troll to our layout [20:41] this was very intentional [20:41] as soon as you add something to your layout it will usually consume space [20:41] visible or not [20:41] so, whenver our troll is not visible it also must not be part of the layout [20:41] hence the logic in our onClick [20:42] if visible -> make invisbile and remove from layout || if invisible -> make visible and add to layout [20:42] the daring programmer will now try this and complain that it is not working [20:42] oh my [20:43] we did not yet define that onClick should do something upon button click }}} {{{#!cplusplus [20:43] // Now we just tell our button that once it was clicked it shall run our function [20:43] button.clicked.connect(onClick); }}} {{{#!irc [20:44] well then [20:44] for me it works \o/ [20:44] very useful plasmoid we created there :D [20:45] you can find a version of this I created earlier here : http://people.ubuntu.com/~apachelogger/uadw/04.11/dont-blink/ [20:46] it also contains additional magic that should trigger a notification on click and display your location as detected by gps or ip lookup ;) [20:46] now that we have a wonderful plasmoid we will need to package it properly [20:47] as mentioned earlier, plasmoids are distributed in super cool special packages [20:47] although.... [20:47] actually they are just zip files with .plasmoid as suffix [20:47] so let us create such a nice package from our plasmoid [20:48] if you are still in the same terminal we started off with, the following should do the job: }}} {{{#!highlight bash cd $NAME && zip -r ../$NAME.plasmoid . && cd .. }}} {{{#!irc [20:48] $NAME is simply the name of our plasmoid, so you can easy enough create the zip manually too :) [20:49] please note that plasma does expect the contents and metadata to be in the top level of the zip though, so you must not package the plasmoid directory (in our case dont-blink) but only the files [20:49] that is really what that fancy zip command there does [20:50] Once you have your plasmoid you can install it using the regular graphical ways on your plasma version or by using the command line tool plasmapkg. [20:50] plasmapkg -i $NAME.plasmoid [20:50] now the plasmoid should show up in your widget listing. [20:50] consequently you should be able to use plasmoidviewer $NAME and plasma-windowed $NAME to view the plasmoid without plasma [20:51] QUESTION: are there any particular style guidelines for writing code for plasmoids beyond what you have shown us? for those that are used to MVC kinda stuff [20:51] not really [20:51] if you are using C++ you can do just about anything ... in the future the javascript plasmoids will use QML quite a bit (you will hear about QML later this week) [20:52] There are 10 minutes remaining in the current session. [20:52] QML usually wants people to use Qt's Model/View system (which is pretty close to MVC) [20:52] especially if you are working with lists of course :) [20:52] QUESTION: will it be possible to compress the package with bzip2 in the futur? [20:53] not planned in particular, but if you ask in #plasma I am sure someone could tell you whether that would be desirable [20:53] as plasmoids are usually atomic it does not make much a difference though [20:53] any other questions? [20:54] if not, then let me give you some additonal resources where you can find handy super nice things :) [20:54] Where the Plasma community collects its information: http://community.kde.org/Plasma [20:54] General tutorials on JavaScript Plasmoids: http://techbase.kde.org/Development/Tutorials/Plasma#Plasma_Programming_with_JavaScript [20:54] Plasma and KDE development examples: http://quickgit.kde.org/?p=kdeexamples.git&a=summary [20:54] Some general guidelines for Plasmoid programming: http://community.kde.org/Plasma/PlasmoidGuidelines [20:55] Information on Plasma packages: http://community.kde.org/Plasma/Package [20:55] AND [20:55] last, but not least [20:55] *super important* [20:55] the JavaScript API: http://techbase.kde.org/Development/Tutorials/Plasma/JavaScript/API [20:55] if you compare this API to what you can do in C++ you will notice that the JavaScript API is really sufficient for most things :) [20:56] On IRC you can get help in #plasma most of the time [20:56] Good luck with creating your brilliant Plasmoids :) [20:56] you can find me in just about every KDE and Kubuntu IRC channel after the sessions if you have any additional questions [20:57] There are 5 minutes remaining in the current session. [20:58] if you are interested in KDE software development I'd like to direct your attention to the KDE development session tomorrow, the various QML sessions and my talk on multimedia in Qt and KDE on friday :) [20:58] thanks everyone for joining and have a nice day }}}