Development/Tutorials/Plasma4/DataEngines (pt BR)

< Development‎ | Tutorials‎ | Plasma4
Revision as of 23:28, 17 January 2011 by Camilasan (Talk | contribs)

Jump to: navigation, search


Contents

Development/Tutorials/Plasma/DataEngines


Escrevendo uma Data Engine
Tutorial Series   Plasma Tutorial
Previous   C++, Qt, KDE4 development environment
What's Next  
Further Reading   DataEngine API, CMake Tutorials, Writing a Plasmoid (Tutorial)

Abstract

Data Engines fornecem uma interface padronizada para a visualização em diferentes data sources.

Este tutorial irá guiá-lo através da criação de um data engine simples. O exemplo que usaremos é uma versão simplificada do time data engine que vem com a instalação básica do plasma no kdebase-workspace.

O time data engine fornece a data atual e a hora para qualquer fuso horário que o sistema conheça. Ele é usado por todos os relógio plasmoids. O benefício óbvio é que não há necessidade para reimplementar a lógica para selecionar o fuso horário em casa relógio em plasmoid.

O Plasma Engine Explorer

Uma ferramenta muito útil para quem quer escrever um data engine é o Plasma Engine Explorer. Você pode usá-lo para ver como o data engine deveria funcionar em tempo de execução.

plasmaengineexplorer

Perto do topo da janela há um combobox para selecionar um data engine. Escolha o "time" engine. Agora você pode solicitar uma fonte. Experimente pedir a fonte "Local", com um intervalo de atualização de 500ms (duas vezes por segundo). Um único item, Local, devem ficar visíveis na lista de fontes. Clique no + do lado esquerdo para expandi-lo, e você deve ver a data, a hora, o fuso horário do continente e o fuso horário da cidade listada, junto com o tipo de cada um.

Plasma-engine-explorer-time.png

Selecione outros fusos horários, como "Europe / Paris" e "Ásia / Tóquio".

Depois de criar o seu data engine, lembre-se de testar usando o Plasma Engine Explorer!


O Código

O Arquivo Desktop

Cada data engine en precisa de um arquivo de descrição para dizer ao plasma como carregá-lo e o que é chamado.


plasma-engine-testtime.desktop [Desktop Entry] Name=Test Time Engine Comment=A duplicate of the Time Engine Type=Service

X-KDE-ServiceTypes=Plasma/DataEngine X-KDE-Library=plasma_engine_testtime X-Plasma-EngineName=testtime X-KDE-PluginInfo-Author=Aaron Seigo X-KDE-PluginInfo-Email=aseigo@kde.org X-KDE-PluginInfo-Name=testtime 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=LGPL X-KDE-PluginInfo-EnabledByDefault=true

As partes mais importantes são:

  • os campos Name, Comment e Type, são exigidos para todos os arquivos

.desktop.

  • o campo X-KDE-ServiceTypes, que diz ao plasma que este é um data engine.
  • o campo X-KDE-Library, que diz ao plasma como carregar o data engine - neste caso carregar plasma_engine_testtime.so do plugin folder.
  • o campo X-Plasma-EngineName, que diz ao plasma o qual é o nome do plugin exportado (setado pelo K_EXPORT_PLASMA_DATAENGINE).
  • o X-KDE-PluginInfo-Name é importante para DataEngines desde o 4.2, sem isso, o plasma não vai encontrar a sua DataEngine.

O arquivo Header

testtimeengine.h // the following header is required by the LGPL because // we are using the actual time engine code /*

*   Copyright 2007 Aaron Seigo <aseigo@kde.org>
*
*   This program is free software; you can redistribute it and/or modify
*   it under the terms of the GNU Library General Public License as
*   published by the Free Software Foundation; either version 2 or
*   (at your option) any later version.
*
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details
*
*   You should have received a copy of the GNU Library General Public
*   License along with this program; if not, write to the
*   Free Software Foundation, Inc.,
*   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

/ / um padrão de include para impedir problemas se o / / cabeçalho for incluído várias vezes

  1. ifndef TESTTIMEENGINE_H
  2. define TESTTIMEENGINE_H

/ / Precisamos do cabeçalho DataEngine, já que TestTimeEngine herda dele

  1. include <Plasma/DataEngine>

/**

* Fornece a data e hora atual para um determinado
* Fuso horário.
*
* "Local" é uma fonte especial que é um alias para o atual
* Fuso horário.
*/

class TestTimeEngine : public Plasma::DataEngine {

   // required since Plasma::DataEngine inherits QObject
   Q_OBJECT
   public:
       // cada engine precisa de um construtor com esses parâmetros
       TestTimeEngine(QObject* parent, const QVariantList& args);
   protected:
       // esta função virtual é chamada quando quando um novo source é requisitado
       bool sourceRequestEvent(const QString& name);
       // esta função virtual é chamada quando uma atualização automática
       // é disparada por um source existente (ex: quando um intervalo de //atualização é iniciado quando faz requisição a um source)
       bool updateSourceEvent(const QString& source);

};

  1. endif // TESTTIMEENGINE_H

A separate header file may seem a bit pointless for a plugin this small, but it is a good habit to get into.

Um arquivo header pode parecer um pouco inútil para um plugin deste tamanho, mas é um bom ter esse hábito.

Note that I don't put a K_EXPORT_PLASMA_DATAENGINE in the header file. When there is only one .cpp file in the project, there is no problem, but in larger plugins several files might include this header and there can only be one K_EXPORT_PLASMA_DATAENGINE in the project. If K_EXPORT_PLASMA_DATAENGINE is compiled in multiple times, you will get a linker error when compiling. Also note that the name should not end on "engine" (e.g. "testtimeengine"), because then Plasma does not find the DataEngine correctly.

Note que eu não coloco uma K_EXPORT_PLASMA_DATAENGINE no header. Quando houver apenas um arquivo .cpp no projeto, não há problema, mas plugins maiores diversos arquivos podem incluir esse header e só pode haver um K_EXPORT_PLASMA_DATAENGINE no projeto. Se K_EXPORT_PLASMA_DATAENGINE é compilado várias vezes, você obterá um erro de linker quando compilar. Observe também que o nome deveria não deveria terminar em "engine" (por exemplo, "testtimeengine"), porque o Plasma não consegue encontrar o DataEngine correto.

The Main Code

testtimeengine.cpp // the following header is required by the LGPL because // we are using the actual time engine code /*

*   Copyright 2007 Aaron Seigo <aseigo@kde.org>
*
*   This program is free software; you can redistribute it and/or modify
*   it under the terms of the GNU Library General Public License as
*   published by the Free Software Foundation; either version 2 or
*   (at your option) any later version.
*
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details
*
*   You should have received a copy of the GNU Library General Public
*   License along with this program; if not, write to the
*   Free Software Foundation, Inc.,
*   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
  1. include "testtimeengine.h"
  1. include <QDate>
  2. include <QTime>
  1. include <KSystemTimeZones>
  2. include <KDateTime>
  1. include <Plasma/DataContainer>

TestTimeEngine::TestTimeEngine(QObject* parent, const QVariantList& args)

   : Plasma::DataEngine(parent, args)

{

   // Ignoramos alguns argumentos - data engines não tem muito uso para eles
   Q_UNUSED(args)
   // Isso impede que applets usem um alto intervalo de atualização //desnecessariamente de um desnecessariamente e usando muita CPU.
   // No caso de um relógio que só tem precisão em segundos,
   // Um terço de um segundo deve ser mais do que suficiente.
   setMinimumPollingInterval(333);

}

bool TestTimeEngine::sourceRequestEvent(const QString &name) {

   // Nós não temos nenhum código especial para executar a
   // Primeira vez que uum source seja solicitado, por isso, basta chamar
   // updateSourceEvent().
   return updateSourceEvent(name);

}

bool TestTimeEngine::updateSourceEvent(const QString &name) {

   QString timezone;
   if (name == I18N_NOOP("Local")) {
       // Local é um caso especial - é só pegar a hora e data atual 
       setData(name, I18N_NOOP("Time"), QTime::currentTime());
       setData(name, I18N_NOOP("Date"), QDate::currentDate());
   } else {
       // First check the timezone is valid
       KTimeZone newTz = KSystemTimeZones::zone(name);
       if (!newTz.isValid()) {
           return false;
       }
       // Get the date and time
       KDateTime dt = KDateTime::currentDateTime(newTz);
       setData(name, I18N_NOOP("Time"), dt.time());
       setData(name, I18N_NOOP("Date"), dt.date());
   }
   return true;

}

// This does the magic that allows Plasma to load // this plugin. The first argument must match // the X-Plasma-EngineName in the .desktop file. K_EXPORT_PLASMA_DATAENGINE(testtime, TestTimeEngine)

// this is needed since TestTimeEngine is a QObject

  1. include "testtimeengine.moc"


Responding to Requests for Sources

The sourceRequestEvent() method is called the first time a source is loaded. You can use this to do any special processing that should be done the first time a source is created, but not when it is subsequently updated.

If a source is created with a polling interval, updateSourceEvent() will be called each time that interval expires. For example, if an applet requests a source "foo" with a polling interval of 500ms, sourceRequestEvent("foo") will be called initially, then half a second later, and every half a second after that, updateSourceEvent("foo") will be called.

Note, however, that applets do not have to set a polling interval and may instead simply wait for an engine to push data to it.


Controlling Update Frequency

There are a couple of methods for controlling updates. We use setMinimumPollingInterval(333) to prevent updateSourceEvent() being called more than three times a second for any given source. You can also enforce a specific update interval for all sources provided by this engine with setPollingInterval(), which takes a time in milliseconds as its only argument.

Responding to Outside Events

Polling does not make sense for all engines. Some engines, such as the device engine, respond to outside events. You can use setData() at any time to create or update a source. removeData() and removeSource() are also useful methods. For the applets that want to be informed when the sources change, without using polling, use dataUpdated. Use it by calling connectSource


Listing Potential Sources

Applets can request a list of the available sources for an engine. By default, this is just a list of every source that has been created (with setData() or addSource()) so far (and not removed, of course). However, you may wish to advertise sources but not actually create them. For example, we could advertise every timezone that the system knows about, but not actually create and populate the sources, since hardly any will actually be used.

This can be done by reimplementing virtual QStringList sources() const and returning a list of the names of all the available sources.


Initialisation

If you want to perform any initialisation beyond setting simple properties, such as populating sources, you cannot do it in the constructor, since the data engine has not been properly initialised at this point. Instead, reimplement the virtual void init() method.

For example, the tasks data engine uses the init() method to get a list of all the currently running tasks and creates sources for each of them.


More Control Over Data

The DataContainer class can be used to give you more control over updating data if you need it. The relevant methods of DataEngine are DataContainer* containerForSource(const QString& source), void addSource(DataContainer* source) and SourceDict containerDict() const.

Building It

The CMakeLists.txt file tells CMake how to build your plugin. The following file will work for this project:

  1. A name for the project

project(plasma-testtime)

  1. Find the required Libaries

find_package(KDE4 REQUIRED) include(KDE4Defaults)

add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS}) include_directories(

  ${CMAKE_SOURCE_DIR}
  ${CMAKE_BINARY_DIR}
  ${KDE4_INCLUDES}
  )
  1. We add our source code here

set(testtime_engine_SRCS testtimeengine.cpp)

  1. Now make sure all files get to the right place

kde4_add_plugin(plasma_engine_testtime ${testtime_engine_SRCS}) target_link_libraries(plasma_engine_testtime

                     ${KDE4_KDECORE_LIBS}
                     ${KDE4_PLASMA_LIBS})

install(TARGETS plasma_engine_testtime

       DESTINATION ${PLUGIN_INSTALL_DIR})

install(FILES plasma-engine-testtime.desktop

       DESTINATION ${SERVICES_INSTALL_DIR})


Testing

Run cmake -DCMAKE_BUILD_TYPE=debugfull -DCMAKE_INSTALL_PREFIX=$KDEDIR make make install

Replace $KDEDIR with your kde installation directory if $KDEDIR is not set.

Alternatively, you can run the following cmake -DCMAKE_BUILD_TYPE=debugfull make cp ./lib/plasma_engine_testtime.so $KDEDIR/lib/kde4 cp ./plasma-engine-testtime.desktop $KDEDIR/share/kde4/services/

Now run kbuildsycoca4 to tell KDE applications (including plasma and the plasma engine explorer) about the new desktop file.

Now you can test it as we did the time engine. Run plasmaengineexplorer --engine testtime

Note that if you change a data engine (or applet), the change will not register in any running applications. After modifying and reinstalling a data engine, to make plasma register the change you must run kbuildsycoca4 kquitapp plasma-desktop (or plasma-netbook, etc) plasma-desktop


KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V.Legal