Development/Tutorials/Plasma4/GettingStarted (es): Difference between revisions

From KDE TechBase
(translation to spanish)
 
(9 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{Template:I18n/Language Navigation Bar|Development/Tutorials/Plasma/GettingStarted}}


{{TutorialBrowser|
{{TutorialBrowser_(es)|


series=Plasma Tutorial|
series=Tutorial de Plasma|


name=Creating your first Plasmoid|
name=Creando tu primer Plasmoid|


pre=[http://mindview.net/Books/TICPP/ThinkingInCPP2e.html C++], [http://www.trolltech.com/products/qt/ Qt], [[Getting_Started/Build/KDE4|KDE4 development environment]]|
pre=[http://mindview.net/Books/TICPP/ThinkingInCPP2e.html C++], [http://www.trolltech.com/products/qt/ Qt], [[Getting_Started/Build/KDE4|entorno de desarrollo de KDE4]]|


next=|  
next=|  
Line 13: Line 12:
reading=[[Development/Tutorials/CMake|CMake]]
reading=[[Development/Tutorials/CMake|CMake]]
}}
}}
==Abstract==
==Resumen==
This tutorial needs KDE 4.1 (trunk) to build.
Este tutorial necesita KDE 4.2 (trunk) para poder construirlo.  
We are going to create a simple plasmoid in this tutorial. To keep things simple, we will only create a static plasmoid which will contain the following items:  
En este tutorial vamos a crear un simple plasmoid. Para hacer las cosas faciles, sólo crearemos un plasmoid estático que contendrá los siguientes elementos:


* An SVG Image
* Una imagen SVG
* Icon
* Icono
* Some nice text
* Un texto


[[image:creatingyourfirstplasmoid1.png|frame|center]]
[[image:creatingyourfirstplasmoid1.png|frame|center]]


== The Code ==
== El Código ==
=== The .desktop file ===
=== El archivo .desktop ===
Every Plasmoid needs a .desktop file to tell plasma how it should be started and what name it carries.  
Cada Plasmoid necesita un archivo .desktop para indicarle a Plasma como debe iniciarlo y que nombre tomará.


'''plasma-applet-tutorial1.desktop'''
'''plasma-applet-tutorial1.desktop'''
<code ini>
<syntaxhighlight lang="ini">
[Desktop Entry]
[Desktop Entry]
Name=Tutorial 1
Name=Tutorial 1
Line 45: Line 44:
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true
X-KDE-PluginInfo-EnabledByDefault=true
</code>
</syntaxhighlight>


The most important bits are the '''X-KDE-Library''' and '''X-KDE-PluginInfo-Name''', they are the "glue" between your class and plasma, without it, nothing will start. For '''X-KDE-PluginInfo-Category''', refer to the [[Projects/Plasma/PIG | PIG]].
Las partes mas importantes son '''X-KDE-Library''' y '''X-KDE-PluginInfo-Name''', ellas son el "pegamento" entre tu clase y plasma, sin ellos, no se iniciará nada. '''X-KDE-PluginInfo-Category''' se refiere a [[Projects/Plasma/PIG | PIG]].


=== The header file ===
=== El archivo cabecera ===
This is the example header file. Comments have been added in the code for clarity.
Aquí tienes el archivo cabecera de este tutorial. Se han añadido Los comentarios por claridad.


'''plasma-tutorial1.h'''
'''plasma-tutorial1.h'''
<code cppqt>
<syntaxhighlight lang="cpp-qt">
// Here we avoid loading the header multiple times
// Evitamos cargar la cabecera varias veces
#ifndef Tutorial1_HEADER
#ifndef Tutorial1_HEADER
#define Tutorial1_HEADER
#define Tutorial1_HEADER
// We need the Plasma Applet headers
// Necesitamos las cabeceras de Plasma Applet
#include <KIcon>
#include <Plasma/Applet>
#include <Plasma/Applet>
#include <Plasma/Svg>
#include <Plasma/Svg>
 
#include <KIcon>
 
class QSizeF;
class QSizeF;
   
   
// Define our plasma Applet
// Definimos nuestro applet de plasma
class PlasmaTutorial1 : public Plasma::Applet
class PlasmaTutorial1 : public Plasma::Applet
{
{
     Q_OBJECT
     Q_OBJECT
     public:
     public:
        // Basic Create/Destroy
// Constructor/Destructor básico
         PlasmaTutorial1(QObject *parent, const QVariantList &args);
         PlasmaTutorial1(QObject *parent, const QVariantList &args);
         ~PlasmaTutorial1();
         ~PlasmaTutorial1();
   
   
         // The paintInterface procedure paints the applet to screen
         // El procedimiento paintInterface dibuja el applet en la pantalla
         void paintInterface(QPainter *painter,
         void paintInterface(QPainter *painter,
                 const QStyleOptionGraphicsItem *option,
                 const QStyleOptionGraphicsItem *option,
Line 85: Line 84:
};
};
   
   
// This is the command that links your applet to the .desktop file
// Esta es la orden que enlaza el applet con el archivo .desktop
K_EXPORT_PLASMA_APPLET(tutorial1, PlasmaTutorial1)
K_EXPORT_PLASMA_APPLET(tutorial1, PlasmaTutorial1)
#endif
#endif
</code>
</syntaxhighlight>


==== QRectF boundingRect() ====
==== QRectF boundingRect() ====
The <tt>boundingRect()</tt> function tells plasma the actual size of the plasmoid. This is important because we need to know how much space is taken on the screen.  
La función <tt>boundingRect()</tt> le dice a plasma el tamaño actual del plasmoid. Esto es importante porque necesitamos saber cuanto espacio se ocupa en la pantalla.
{{tip|
{{tip_(es)|
If you have issues with your plasmoid leaving pixels behind when dragging, this is usually a result of an incorrect boundingRect()
Si tienes problemas con tu plasmoid dejando pixeles atras cuando lo arrastras, se trata por lo general de un boundingRect() incorrecto.
}}
}}


==== void paintInterface(QRectF contentsRect) ====
==== void paintInterface(QRectF contentsRect) ====
This can be considered the main function since it paints the plasmoid on to the screen. Here, you define how you want your plasmoid to look.
Puede considerarse la función principal, ya que dibuja el plasmoid en la pantalla. Aquí defines que aspecto quieres que tenga tu plasmoid.
You should only paint in the boundaries defined by contentsRect and avoid using geometry(). When a plasmoid does not have a standard background, e.g. when it's disabled with a setBackgroundHints() call or it's in the panel, geometry() and boundingRect() behave the same; however, when the standard background is enabled (the usual case), the appplet will have a margin where it should not be painted
Solo debes dibujar en los límites definidos por contentsRect y evitar usar geometry(). Cuando un plasmoid no tiene un fondo estándar, por ejemplo, si se ha desactivado mediante la llamada setBackgroundHints() o está en el panel, geometry() y boundingRect() se comportan igual; sin embargo, cuando el fondo estándar está activado (el caso habitual), el applet tendrá un margen donde no debería pintarse.


==== K_EXPORT_PLASMA_APPLET ( <name>, <class> ) ====
==== K_EXPORT_PLASMA_APPLET ( <name>, <class> ) ====
This is a small but very important part that links your classname to the applet name in the .desktop file. If your applet doesn't seem to get loaded, there may be a difference between this declaration and your .desktop file
Es una pequeña parte pero muy importante ya que enlaza tu clase con el nombre del applet del archivo .desktop. Si tu applet parece que no se carga, puede ser que haya una diferencia entre esta declaración y tu archivo .desktop.


{{tip|
{{tip_(es)|K_EXPORT_PLASMA_APPLET añade "plasma_applet_", por favor presta atención cuando establezcas el nombre en tu archivo .desktop para evitar una diferencia de nombres.
The K_EXPORT_PLASMA_APPLET adds "plasma_applet_", please pay attention to this when setting up your .desktop file to avoid a name difference
}}
}}


=== The actual work file ===
=== plasma-tutorial1.cpp ===
Here is the body of the function, again with a lot of comments in between.
<syntaxhighlight lang="cpp-qt">#include "plasma-tutorial1.h"
 
'''plasma-tutorial1.cpp'''
<code cppqt>
#include "plasma-tutorial1.h"
#include <QPainter>
#include <QPainter>
#include <QFontMetrics>
#include <QFontMetrics>
Line 121: Line 115:
   
   
PlasmaTutorial1::PlasmaTutorial1(QObject *parent, const QVariantList &args)
PlasmaTutorial1::PlasmaTutorial1(QObject *parent, const QVariantList &args)
    : Plasma::Applet(parent, args),
: Plasma::Applet(parent, args),
    m_svg(this),
m_svg(this),
    m_icon("document")
m_icon("document")
{
{
    m_svg.setImagePath("widgets/background");
m_svg.setImagePath("widgets/background");
    // this will get us the standard applet background, for free!
// Establecerá el fondo por defecto del applet, gratis!
    setBackgroundHints(DefaultBackground);
setBackgroundHints(DefaultBackground);
    resize(200, 200);
resize(400, 400);
}
}
 


PlasmaTutorial1::~PlasmaTutorial1()
PlasmaTutorial1::~PlasmaTutorial1()
{
{
    if (hasFailedToLaunch()) {
if (hasFailedToLaunch()) {
        // Do some cleanup here
// Hacer algo de limpieza aquí
    } else {
} else {
        // Save settings
// Guardar la configuracion
    }
}
}
}


void PlasmaTutorial1::init()
void PlasmaTutorial1::init()
{
{
// Una pequeña demostracion de la función setFailedToLaunch
    // A small demonstration of the setFailedToLaunch function
if (m_icon.isNull()) {
    if (m_icon.isNull()) {
setFailedToLaunch(true, "Sin mundo al que decir hola");
        setFailedToLaunch(true, "No world to say hello");
}
    }
}  
}  
   
   
Line 154: Line 147:
         const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
         const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
{
{
    p->setRenderHint(QPainter::SmoothPixmapTransform);
p->setRenderHint(QPainter::SmoothPixmapTransform);
    p->setRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing);
    // Now we draw the applet, starting with our svg
// Ahora dibujamos el applet, empezando por nuestro svg
    m_svg.resize((int)contentsRect.width(), (int)contentsRect.height());
m_svg.resize((int)contentsRect.width(), (int)contentsRect.height());
    m_svg.paint(p, (int)contentsRect.left(), (int)contentsRect.top());
m_svg.paint(p, (int)contentsRect.left(), (int)contentsRect.top());
    // We place the icon and text
// Colocamos el icono y el texto
    p->drawPixmap(7, 0, m_icon.pixmap((int)contentsRect.width(),(int)contentsRect.width()-14));
p->drawPixmap(7, 0, m_icon.pixmap((int)contentsRect.width(), (int)contentsRect.width() - 14));
    p->save();
p->save();
    p->setPen(Qt::white);
p->setPen(Qt::white);
    p->drawText(contentsRect,
p->drawText(contentsRect, Qt::AlignBottom | Qt::AlignHCenter, "Hola Plasmoid!");
                Qt::AlignBottom | Qt::AlignHCenter,
p->restore();
                "Hello Plasmoid!");
    p->restore();
}
}
   
   
#include "plasma-tutorial1.moc"
#include "plasma-tutorial1.moc"
</code>
</syntaxhighlight>


==== Plasma/Svg ====
==== Plasma/Svg ====
As you can see in the example code we are using the {{class|Plasma::Svg}} object, there are some important things to note here.
Como se puede ver en el código de ejemplo estamos usando el objeto {{class|Plasma::Svg}}, que tiene algunas cosas importantes a señalar.


First we're using a relative path '''widgets/background''' which causes {{class|Plasma::Svg}} to use {{class|Plasma::Theme}} to locate the SVG data. While {{class|Plasma::Svg}} does support loading arbitrary files when passed an absolute path, use relative paths from the theme as often as possible as it makes Plasma skinable and the individual plasmoids look like a combined whole instead of a group of separate unrelated applications. You can see a list of available image components on the [[Projects/Plasma/Theme|Plasma Theme page]].
En primer lugar estamos usando una ruta relativa a '''widgets/background''' que obliga a {{class|Plasma::Svg}} a usar {{class|Plasma::Theme}} para localizar el archivo SVG. Si bien {{class|Plasma::Svg}} da soporte para cargar archivos pasandole una ruta absoluta, usa rutas relativas para el tema siempre que sea posible, ya que esto hace que Plasma soporte estilos y que los plasmoids individuales tengan el mismo aspecto, en vez de un grupo de aplicaciones sin relación alguna. Puedes ver una lista de los componentes de imagen disponibles en [[Projects/Plasma/Theme|temas de Plasma]].


In either mode, {{class|Plasma::Svg}} can be used to draw a subset of the SVG file by passing it an element id that appears in the SVG document. As a good example, if you open the clock.svg file that ships with the default theme, you will see that it has a background, 3 handles (hour, minute and seconds) and a foreground (the glass). Due to the ability to put all the elements in one file the SVG file shows a clock. This is much nicer for artists compared to editing 5 separate files that they have to imagine on top of each other, and much nicer for performance as only one SVG renderer and one file read from disk is necessary.
Por otro lado, {{class|Plasma::Svg}} se puede usar para dibujar un subconjunto del archivo SVG pasandole un elemento identificador que aparezca en el documento SVG. Un buen ejemplo es el archivo clock.svg que viene en el tema por defecto, verás que tiene un fondo, tres agujas (hora, minuto y segundo) y un primer plano. Esto es mucho mas agradable para los artistas esta metodologia comparado con editar 5 archivos por separado, ya que tendrian que imaginar los archivos svg unos encima de otros, y mucho mejor para el rendimiento ya que solo se renderiza un archivo y solo se hace una lectura de archivo del disco.


==== setBackgroundHints(DefaultBackground) ====
==== setBackgroundHints(DefaultBackground) ====
Since drawing a background is a common function there is fast and easier way of doing it. By adding <tt>setBackgroundHints(DefaultBackground)</tt> to the code, the default Plasma background gets drawn behind your plasmoid. This not only saves you time and code, but creates a more consistent presentation for the user.
Desde que dibujar el fondo es una función común, esta es mas rapida y fácil de hacer. Añadiendo <tt>setBackgroundHints(DefaultBackground)</tt> al código, el fondo por defecto de Plasma se dibuja detras de tu plasmoid. No solo te ahorra tiempo y código, sino que crea una presentación mas consistente para el usurario.
 
==== El método init() ====
En el constructor solo notificas a Plasma el fondo y el archivo de configuración (si existiese). También puedes establecer el tamaño inicial en el constructor. Despues de esto, Plasma se ocupará de cualquier cambio de tamaño y de que nunca tengas que preocuparte por él. En el método <tt>init()</tt> inicializas todo lo que necesite ser inicializado, como leer los datos del archivo de configuración por ejemplo.


==== The init() method ====
In the constructor you only tell plasma about the background and configuration file if any. You also set the start size in the constructor. After that, plasma will take care of any resizing and you never have to worry about size. In the <tt>init()</tt> method you initialize everything that needs to be initialize such as reading config data for example.


==== hasFailedToLaunch() ====
==== hasFailedToLaunch() ====
If for some reason, the applet fails to get up on its feet (the library couldn't be loaded, necessary hardware support wasn't found, etc..) this method returns true. Using this function gives your application a chance to cleanup before quiting.  
Si por alguna razón el applet fallara al iniciarlo (la biblioteca no pudo cargarse, necesario soporte hardware que no se ha encontrado, etc..) este método devolvería true. Usar esta función proporciona a tu aplicación la oportunidad de limpiar lo que sea necesario antes de cerrarse.


==== setFailedToLaunch(bool, QString) ====
==== setFailedToLaunch(bool, QString) ====
When your application is unable to start, this function allows you to inform Plasma and give an optional reason why. Plasma will then draw a standardized error interface to inform the user of the situation and your applet will not be called upon to do any drawing on its own from that point forward. If your plasmoid becomes more complex and depends on multiple factors this is the nicest way to cleanup.
Cuando tu aplicación no esta en condiciones de iniciarse, esta función te permite informar a Plasma y dar un motivo del porque. Entonces Plasma lanzará una interfaz estándar de error para informar al usuario de la situación y en tu applet no se dibujará nada mas a partir de ese punto. Si tu plasmoid se convierte en algo mas complejo y depende de multiples factores, este método es la manera mas adecuada para limpiar lo que sea necesario.


==== dataUpdated ====
==== dataUpdated ====
If you would connect to any of plasma's data-engines you would have to implement a function called dataUpdated in your plasmoid. The latter is called if the data-engine sends you data, i.e. your plasmoid should recalculate its contents.
Si quisieras conectar tu applet a cualquiera de los data-engines de plasma, deberías implementar una función de nombre dataUpdate en tu plasmoid. Se llama a esta función si el data-engine te envia datos, es decir, tu plasmoid debería recalcular su contenido.


==== Determine the applet size and geometry: geometry() and contentsRect() ====
==== Determinar el tamaño y la geometría del applet: geometry() y contentsRect() ====
If you need to know, in your applet code, what the applet size and geometry is, call contentsRect() and contentsRect().size(). Avoid calling geometry() and size() because they don't take into account the margin's size set by the applets default background.
Si necesitas saber, en tu código, que tamaño y geometria que tiene el applet, puedes llamar a contentsRect() y a contentsRect().size().
Also avoid using absolute numbers to position items in the applet like QPoint(0, 0) to indicate the top-left point of your applet, instead use contentsRect().topLeft().
Evita llamar a geometry() y size() porque en el cálculo no se tiene en cuenta el tamaño del margen establecido por el fondo por defecto del applet.
También evita usar números absolutos para situar los elementos en el applet, como QPoint(0, 0) para indicar el punto superior izquierdo de tu applet, en vez de esto usa contentsRect().topLeft().


=== Building it all, the CMakeLists.txt ===
=== Construir el applet: CMakeLists.txt ===
Finally, to put everything together you need to build everything. To tell cmake what needs to go where there is the CMakeLists.txt file.
Por último, para poner todo junto necesitas construirlo todo. Para decirle a cmake que necesita tenemos el archivo CMakeLists.txt  


For more details on CMake please read [[Development/Tutorials/CMake]]
Para mas detalles de CMake lee por favor [[Development/Tutorials/CMake]].


<code bash>
<syntaxhighlight lang="bash">
# Project Needs a name ofcourse
# El proyecto necesita un nombre
project(plasma-tutorial1)
project(plasma-tutorial1)
 
# Find the required Libaries
# Encuentra las bibliotecas necesarias
find_package(KDE4 REQUIRED)
find_package(KDE4 REQUIRED)
include(KDE4Defaults)
include(KDE4Defaults)
find_package(Plasma REQUIRED)
 
add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
include_directories(
include_directories(
Line 220: Line 212:
   ${KDE4_INCLUDES}
   ${KDE4_INCLUDES}
   )
   )
 
# We add our source code here
# Añadimos nuestro código fuente aqui
set(tutorial1_SRCS plasma-tutorial1.cpp)
set(tutorial1_SRCS plasma-tutorial1.cpp)
 
# Now make sure all files get to the right place
# Ahora nos aseguramos de poner todos los archivos en su lugar
kde4_add_plugin(plasma_applet_tutorial1 ${tutorial1_SRCS})
kde4_add_plugin(plasma_applet_tutorial1 ${tutorial1_SRCS})
target_link_libraries(plasma_applet_tutorial1  
target_link_libraries(plasma_applet_tutorial1  
                       ${PLASMA_LIBS} ${KDE4_KDEUI_LIBS})
                       ${KDE4_PLASMA_LIBS} ${KDE4_KDEUI_LIBS})
 
install(TARGETS plasma_applet_tutorial1
install(TARGETS plasma_applet_tutorial1
         DESTINATION ${PLUGIN_INSTALL_DIR})
         DESTINATION ${PLUGIN_INSTALL_DIR})
 
install(FILES plasma-applet-tutorial1.desktop
install(FILES plasma-applet-tutorial1.desktop
         DESTINATION ${SERVICES_INSTALL_DIR})
         DESTINATION ${SERVICES_INSTALL_DIR})
</code>
</syntaxhighlight>


== Testing the Applet ==
== Testeando el Applet ==
If your current Development Environment differs from the Test Installation, you have to run cmake with -DCMAKE_INSTALL_PREFIX=/usr/lib/kde4/ (replace with your $KDEDIR). Then run make. If succesfull the applet can be installed by running sudo make install
Si tu actual entorno de desarrollo difiere de la instalacion de KDE4, tienes que ejecutar cmake con -DCMAKE_INSTALL_PREFIX=/usr/lib/kde4/ (reemplazar por tu $KDEDIR). Luego ejecuta make. Si todo fue bien, puedes instalar el applet ejecutando ''sudo make install'' o:
or
* cp ./lib/plasma_applet_tutorial1.so $KDEDIR/lib  
* cp ./lib/plasma_applet_tutorial1.so $KDEDIR/lib  
* cp ./plasma-applet-tutorial1.desktop $KDEDIR/share/kde4/services/
* cp ./plasma-applet-tutorial1.desktop $KDEDIR/share/kde4/services/


and run kbuildsycoca4 (so that KDE apps will know about the new desktop files).
y ejecuta kbuildsycoca4 (hará que todas las aplicacionesde KDE se enteren de los nuevos arvhivos desktop).
In order to test your Applet you can use the '''plasmoidviewer''' program:
Para testear tu Applet puedes usar el programa ''plasmoidviewer'':
<code bash>
<syntaxhighlight lang="bash">
plasmoidviewer applet_name
plasmoidviewer nombre_applet
</code>
</syntaxhighlight>
 
Incluso puedes ver el applet en un pequeño escritorio mediante:
Where '''applet_name''' is the value specified into .desktop for the '''X-KDE-PluginInfo-Name''' key.
<syntaxhighlight lang="bash">
plasmoidviewer -c escritorio nombre_applet
</syntaxhighlight>
Donde ''nombre_applet'' es el valor especificado en el campo '''X-KDE-PluginsInfo-Name''' del archivo .desktop.


Otherwise you can restart plasma, so the Applet will be displayed in the Applet Browser:  
También puedes reiniciar plasma, así el Applet se mostrará en el navegador de Applets:
<code bash>
<syntaxhighlight lang="bash">
kbuildsycoca4
kbuildsycoca4
kquitapp plasma
kquitapp plasma # en trunk (KDE 4.3): kquitapp plasma-desktop
plasma  
plasma         # en trunk (KDE 4.3): plasma-desktop
</code>
</syntaxhighlight>


If that doesn't work you will have to restart your KDE session by logging out and back in.
Si esto no funciona tendras que reiniciar tu sesión KDE.

Revision as of 23:27, 11 September 2014

Creando tu primer Plasmoid
Serie   Tutorial de Plasma
Requisitos previos   C++, Qt, entorno de desarrollo de KDE4
Siguiente  
Lectura avanzada   CMake

Resumen

Este tutorial necesita KDE 4.2 (trunk) para poder construirlo. En este tutorial vamos a crear un simple plasmoid. Para hacer las cosas faciles, sólo crearemos un plasmoid estático que contendrá los siguientes elementos:

  • Una imagen SVG
  • Icono
  • Un texto

El Código

El archivo .desktop

Cada Plasmoid necesita un archivo .desktop para indicarle a Plasma como debe iniciarlo y que nombre tomará.

plasma-applet-tutorial1.desktop

[Desktop Entry]
Name=Tutorial 1
Comment=Plasma Tutorial 1
Type=Service

X-KDE-ServiceTypes=Plasma/Applet
X-KDE-Library=plasma_applet_tutorial1
X-KDE-PluginInfo-Author=Bas Grolleman
X-KDE-PluginInfo-Email=[email protected]
X-KDE-PluginInfo-Name=tutorial1
X-KDE-PluginInfo-Version=0.1
X-KDE-PluginInfo-Website=http://plasma.kde.org/
X-KDE-PluginInfo-Category=Examples
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true

Las partes mas importantes son X-KDE-Library y X-KDE-PluginInfo-Name, ellas son el "pegamento" entre tu clase y plasma, sin ellos, no se iniciará nada. X-KDE-PluginInfo-Category se refiere a PIG.

El archivo cabecera

Aquí tienes el archivo cabecera de este tutorial. Se han añadido Los comentarios por claridad.

plasma-tutorial1.h

// Evitamos cargar la cabecera varias veces
#ifndef Tutorial1_HEADER
#define Tutorial1_HEADER
// Necesitamos las cabeceras de Plasma Applet
#include <Plasma/Applet>
#include <Plasma/Svg>

#include <KIcon>
  
class QSizeF;
 
// Definimos nuestro applet de plasma
class PlasmaTutorial1 : public Plasma::Applet
{
    Q_OBJECT
    public:
		// Constructor/Destructor básico
        PlasmaTutorial1(QObject *parent, const QVariantList &args);
        ~PlasmaTutorial1();
 
        // El procedimiento paintInterface dibuja el applet en la pantalla
        void paintInterface(QPainter *painter,
                const QStyleOptionGraphicsItem *option,
                const QRect& contentsRect);
	void init();

    private:
        Plasma::Svg m_svg;
        KIcon m_icon;
};
 
// Esta es la orden que enlaza el applet con el archivo .desktop
K_EXPORT_PLASMA_APPLET(tutorial1, PlasmaTutorial1)
#endif

QRectF boundingRect()

La función boundingRect() le dice a plasma el tamaño actual del plasmoid. Esto es importante porque necesitamos saber cuanto espacio se ocupa en la pantalla.

noframe
noframe

Si tienes problemas con tu plasmoid dejando pixeles atras cuando lo arrastras, se trata por lo general de un boundingRect() incorrecto.

Consejo


void paintInterface(QRectF contentsRect)

Puede considerarse la función principal, ya que dibuja el plasmoid en la pantalla. Aquí defines que aspecto quieres que tenga tu plasmoid. Solo debes dibujar en los límites definidos por contentsRect y evitar usar geometry(). Cuando un plasmoid no tiene un fondo estándar, por ejemplo, si se ha desactivado mediante la llamada setBackgroundHints() o está en el panel, geometry() y boundingRect() se comportan igual; sin embargo, cuando el fondo estándar está activado (el caso habitual), el applet tendrá un margen donde no debería pintarse.

K_EXPORT_PLASMA_APPLET ( <name>, <class> )

Es una pequeña parte pero muy importante ya que enlaza tu clase con el nombre del applet del archivo .desktop. Si tu applet parece que no se carga, puede ser que haya una diferencia entre esta declaración y tu archivo .desktop.


noframe
noframe
K_EXPORT_PLASMA_APPLET añade "plasma_applet_", por favor presta atención cuando establezcas el nombre en tu archivo .desktop para evitar una diferencia de nombres.
Consejo


plasma-tutorial1.cpp

#include "plasma-tutorial1.h"
#include <QPainter>
#include <QFontMetrics>
#include <QSizeF>
 
#include <plasma/svg.h>
#include <plasma/theme.h>
 
PlasmaTutorial1::PlasmaTutorial1(QObject *parent, const QVariantList &args)
	: Plasma::Applet(parent, args),
	m_svg(this),
	m_icon("document")
{
	m_svg.setImagePath("widgets/background");
	// Establecerá el fondo por defecto del applet, gratis!
	setBackgroundHints(DefaultBackground);
	resize(400, 400);
}


PlasmaTutorial1::~PlasmaTutorial1()
{
	if (hasFailedToLaunch()) {
		// Hacer algo de limpieza aquí
	} else {
		// Guardar la configuracion
	}
}

void PlasmaTutorial1::init()
{
	// Una pequeña demostracion de la función setFailedToLaunch
	if (m_icon.isNull()) {
		setFailedToLaunch(true, "Sin mundo al que decir hola");
	}
} 
 
 
void PlasmaTutorial1::paintInterface(QPainter *p,
        const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
{
	p->setRenderHint(QPainter::SmoothPixmapTransform);
	p->setRenderHint(QPainter::Antialiasing);
	
	// Ahora dibujamos el applet, empezando por nuestro svg
	m_svg.resize((int)contentsRect.width(), (int)contentsRect.height());
	m_svg.paint(p, (int)contentsRect.left(), (int)contentsRect.top());
	
	// Colocamos el icono y el texto
	p->drawPixmap(7, 0, m_icon.pixmap((int)contentsRect.width(), (int)contentsRect.width() - 14));
	p->save();
	p->setPen(Qt::white);
	p->drawText(contentsRect, Qt::AlignBottom | Qt::AlignHCenter, "Hola Plasmoid!");
	p->restore();
}
 
#include "plasma-tutorial1.moc"

Plasma/Svg

Como se puede ver en el código de ejemplo estamos usando el objeto Plasma::Svg, que tiene algunas cosas importantes a señalar.

En primer lugar estamos usando una ruta relativa a widgets/background que obliga a Plasma::Svg a usar Plasma::Theme para localizar el archivo SVG. Si bien Plasma::Svg da soporte para cargar archivos pasandole una ruta absoluta, usa rutas relativas para el tema siempre que sea posible, ya que esto hace que Plasma soporte estilos y que los plasmoids individuales tengan el mismo aspecto, en vez de un grupo de aplicaciones sin relación alguna. Puedes ver una lista de los componentes de imagen disponibles en temas de Plasma.

Por otro lado, Plasma::Svg se puede usar para dibujar un subconjunto del archivo SVG pasandole un elemento identificador que aparezca en el documento SVG. Un buen ejemplo es el archivo clock.svg que viene en el tema por defecto, verás que tiene un fondo, tres agujas (hora, minuto y segundo) y un primer plano. Esto es mucho mas agradable para los artistas esta metodologia comparado con editar 5 archivos por separado, ya que tendrian que imaginar los archivos svg unos encima de otros, y mucho mejor para el rendimiento ya que solo se renderiza un archivo y solo se hace una lectura de archivo del disco.

setBackgroundHints(DefaultBackground)

Desde que dibujar el fondo es una función común, esta es mas rapida y fácil de hacer. Añadiendo setBackgroundHints(DefaultBackground) al código, el fondo por defecto de Plasma se dibuja detras de tu plasmoid. No solo te ahorra tiempo y código, sino que crea una presentación mas consistente para el usurario.

El método init()

En el constructor solo notificas a Plasma el fondo y el archivo de configuración (si existiese). También puedes establecer el tamaño inicial en el constructor. Despues de esto, Plasma se ocupará de cualquier cambio de tamaño y de que nunca tengas que preocuparte por él. En el método init() inicializas todo lo que necesite ser inicializado, como leer los datos del archivo de configuración por ejemplo.


hasFailedToLaunch()

Si por alguna razón el applet fallara al iniciarlo (la biblioteca no pudo cargarse, necesario soporte hardware que no se ha encontrado, etc..) este método devolvería true. Usar esta función proporciona a tu aplicación la oportunidad de limpiar lo que sea necesario antes de cerrarse.

setFailedToLaunch(bool, QString)

Cuando tu aplicación no esta en condiciones de iniciarse, esta función te permite informar a Plasma y dar un motivo del porque. Entonces Plasma lanzará una interfaz estándar de error para informar al usuario de la situación y en tu applet no se dibujará nada mas a partir de ese punto. Si tu plasmoid se convierte en algo mas complejo y depende de multiples factores, este método es la manera mas adecuada para limpiar lo que sea necesario.

dataUpdated

Si quisieras conectar tu applet a cualquiera de los data-engines de plasma, deberías implementar una función de nombre dataUpdate en tu plasmoid. Se llama a esta función si el data-engine te envia datos, es decir, tu plasmoid debería recalcular su contenido.

Determinar el tamaño y la geometría del applet: geometry() y contentsRect()

Si necesitas saber, en tu código, que tamaño y geometria que tiene el applet, puedes llamar a contentsRect() y a contentsRect().size(). Evita llamar a geometry() y size() porque en el cálculo no se tiene en cuenta el tamaño del margen establecido por el fondo por defecto del applet. También evita usar números absolutos para situar los elementos en el applet, como QPoint(0, 0) para indicar el punto superior izquierdo de tu applet, en vez de esto usa contentsRect().topLeft().

Construir el applet: CMakeLists.txt

Por último, para poner todo junto necesitas construirlo todo. Para decirle a cmake que necesita tenemos el archivo CMakeLists.txt

Para mas detalles de CMake lee por favor Development/Tutorials/CMake.

# El proyecto necesita un nombre
project(plasma-tutorial1)
 
# Encuentra las bibliotecas necesarias
find_package(KDE4 REQUIRED)
include(KDE4Defaults)
 
add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
include_directories(
   ${CMAKE_SOURCE_DIR}
   ${CMAKE_BINARY_DIR}
   ${KDE4_INCLUDES}
   )
 
# Añadimos nuestro código fuente aqui
set(tutorial1_SRCS plasma-tutorial1.cpp)
 
# Ahora nos aseguramos de poner todos los archivos en su lugar
kde4_add_plugin(plasma_applet_tutorial1 ${tutorial1_SRCS})
target_link_libraries(plasma_applet_tutorial1 
                      ${KDE4_PLASMA_LIBS} ${KDE4_KDEUI_LIBS})
 
install(TARGETS plasma_applet_tutorial1
        DESTINATION ${PLUGIN_INSTALL_DIR})
 
install(FILES plasma-applet-tutorial1.desktop
        DESTINATION ${SERVICES_INSTALL_DIR})

Testeando el Applet

Si tu actual entorno de desarrollo difiere de la instalacion de KDE4, tienes que ejecutar cmake con -DCMAKE_INSTALL_PREFIX=/usr/lib/kde4/ (reemplazar por tu $KDEDIR). Luego ejecuta make. Si todo fue bien, puedes instalar el applet ejecutando sudo make install o:

  • cp ./lib/plasma_applet_tutorial1.so $KDEDIR/lib
  • cp ./plasma-applet-tutorial1.desktop $KDEDIR/share/kde4/services/

y ejecuta kbuildsycoca4 (hará que todas las aplicacionesde KDE se enteren de los nuevos arvhivos desktop). Para testear tu Applet puedes usar el programa plasmoidviewer:

plasmoidviewer nombre_applet

Incluso puedes ver el applet en un pequeño escritorio mediante:

plasmoidviewer -c escritorio nombre_applet

Donde nombre_applet es el valor especificado en el campo X-KDE-PluginsInfo-Name del archivo .desktop.

También puedes reiniciar plasma, así el Applet se mostrará en el navegador de Applets:

kbuildsycoca4
kquitapp plasma # en trunk (KDE 4.3): kquitapp plasma-desktop
plasma          # en trunk (KDE 4.3): plasma-desktop

Si esto no funciona tendras que reiniciar tu sesión KDE.