Development/Tutorials/Plasma4/DataEngines (pt BR): Difference between revisions

    From KDE TechBase
    No edit summary
    No edit summary
    (11 intermediate revisions by 2 users not shown)
    Line 1: Line 1:
    {{Template:I18n/Language Navigation Bar|Development/Tutorials/Plasma/DataEngines}}


    {{TutorialBrowser|
    {{TutorialBrowser|
    Line 13: Line 12:
    reading=[http://api.kde.org/4.x-api/kdelibs-apidocs/plasma/html/classPlasma_1_1DataEngine.html DataEngine API], [[Development/Tutorials/CMake|CMake Tutorials]], [[Development/Tutorials/Plasma/GettingStarted|Writing a Plasmoid (Tutorial)]]
    reading=[http://api.kde.org/4.x-api/kdelibs-apidocs/plasma/html/classPlasma_1_1DataEngine.html DataEngine API], [[Development/Tutorials/CMake|CMake Tutorials]], [[Development/Tutorials/Plasma/GettingStarted|Writing a Plasmoid (Tutorial)]]
    }}
    }}


    ==Abstract==
    ==Abstract==


    DataEngines fornecem uma interface padronizada para a visualização em diferentes data sources.
    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 do tempo que vem com a instalação básica do plasma no kdebase-workspace.
    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.
     
    The time data engine provides the current date and time for any timezone that the system knows about.  It is used by every one of the many clock plasmoids.  The obvious benefit of this is that there is no need to reimplement the logic for selecting timezones in every clock plasmoid.


    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 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.
    Line 28: Line 23:
    ==O Plasma Engine Explorer==
    ==O Plasma Engine Explorer==


    A very useful tool for anyone writing data engines is the Plasma engine explorer. You can use it to see how the time data engine should work now by running
    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.
    <code bash>
     
    <syntaxhighlight lang="bash">
    plasmaengineexplorer
    plasmaengineexplorer
    </code>
    </syntaxhighlight>


    Near the top of the window is a drop-down box for selecting a data engine. Choose the "time" engine. You can now request a source.  Try requesting the "Local" source, with an update interval of 500ms (twice a second). A single item, Local, should be visible in the sources list. Click the + on the left to expand it, and you should get the date, time, timezone, timezone continent and timezone city listed, together with the type for each.
    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.


    [[Image:Plasma-engine-explorer-time.png]]
    [[Image:Plasma-engine-explorer-time.png]]


    Have a play with selecting other timezones, such as "Europe/Paris" and "Asia/Tokyo".
    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!
     


    Remember to test your data engine using the Plasma engine explorer when you have created it!
    ==O Código==


    ===O Arquivo Desktop===


    ==The Code==


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


    Every data engine needs a description file to tell plasma how to load it and what it is called.


    '''plasma-engine-testtime.desktop'''
    '''plasma-engine-testtime.desktop'''
    <code ini>
    <syntaxhighlight lang="ini">
    [Desktop Entry]
    [Desktop Entry]
    Name=Test Time Engine
    Name=Test Time Engine
    Line 67: Line 71:
    X-KDE-PluginInfo-License=LGPL
    X-KDE-PluginInfo-License=LGPL
    X-KDE-PluginInfo-EnabledByDefault=true
    X-KDE-PluginInfo-EnabledByDefault=true
    </code>
    </syntaxhighlight>


    The most important bits are:
    As partes mais importantes são:
    * the Name, Comment and Type fields, which are required for all desktop files
    * os campos Name, Comment e Type, são exigidos para todos os arquivos
    * the X-KDE-ServiceTypes field, which tells plasma that this is a data engine
    .desktop.
    * the X-KDE-Library field, which tells plasma how to load the data engine - in this case by loading plasma_engine_testtime.so from the plugin folder
    * o campo X-KDE-ServiceTypes, que diz ao plasma que este é um data engine.
    * the X-Plasma-EngineName field, which tells plasma what the exported plugin name is (as given to K_EXPORT_PLASMA_DATAENGINE)
    * o campo X-KDE-Library, que diz ao plasma como carregar o data engine - neste caso carregar plasma_engine_testtime.so do plugin folder.
    * the X-KDE-PluginInfo-Name is important for DataEngines since 4.2, without it, plasma will not find your DataEngine
    * 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===
    ===The Header File===


    '''testtimeengine.h'''
    '''testtimeengine.h'''
    <code cppqt>
    <syntaxhighlight lang="cpp-qt">
    // the following header is required by the LGPL because
    // the following header is required by the LGPL because
    // we are using the actual time engine code
    // we are using the actual time engine code
    Line 102: Line 106:
      */
      */


    // a standard include guard to prevent problems if the
    //um padrão de include para impedir problemas se o
    // header is included multiple times
    // cabeçalho for incluído várias vezes
    #ifndef TESTTIMEENGINE_H
    #ifndef TESTTIMEENGINE_H
    #define TESTTIMEENGINE_H
    #define TESTTIMEENGINE_H


    // We need the DataEngine header, since we are inheriting it
    // Precisamos do cabeçalho DataEngine, já que TestTimeEngine herda dele
    #include <Plasma/DataEngine>
    #include <Plasma/DataEngine>


    /**
    /**
      * This engine provides the current date and time for a given
      * Fornece a data e hora atual para um determinado
      * timezone.
      * Fuso horário.
      *
      *
      * "Local" is a special source that is an alias for the current
      * "Local" é uma fonte especial que é um alias para o atual
      * timezone.
      * Fuso horário.
      */
      */
    class TestTimeEngine : public Plasma::DataEngine
    class TestTimeEngine : public Plasma::DataEngine
    Line 123: Line 127:


         public:
         public:
             // every engine needs a constructor with these arguments
             // cada engine precisa de um construtor com esses parâmetros
             TestTimeEngine(QObject* parent, const QVariantList& args);
             TestTimeEngine(QObject* parent, const QVariantList& args);


         protected:
         protected:
             // this virtual function is called when a new source is requested
             // esta função virtual é chamada quando quando um novo source é requisitado
             bool sourceRequestEvent(const QString& name);
             bool sourceRequestEvent(const QString& name);


             // this virtual function is called when an automatic update
             // esta função virtual é chamada quando uma atualização automática
             // is triggered for an existing source (ie: when a valid update
             // é disparada por um source existente (ex: quando um intervalo de //atualização é iniciado quando faz requisição a um source)
            // interval is set when requesting a source)
             bool updateSourceEvent(const QString& source);
             bool updateSourceEvent(const QString& source);
    };
    };


    #endif // TESTTIMEENGINE_H
    #endif // TESTTIMEENGINE_H
    </code>
    </syntaxhighlight>


    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.
    Note que eu não coloco uma K_EXPORT_PLASMA_DATAENGINE no header.
    Also note that the name should '''not''' end on "engine" (e.g. "testtimeengine"), because then Plasma does not find the DataEngine correctly.
    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===
    ===Main Code===


    '''testtimeengine.cpp'''
    '''testtimeengine.cpp'''
    <code cppqt>
    <syntaxhighlight lang="cpp-qt">
    // the following header is required by the LGPL because
    // the following header is required by the LGPL because
    // we are using the actual time engine code
    // we are using the actual time engine code
    Line 182: Line 189:
         : Plasma::DataEngine(parent, args)
         : Plasma::DataEngine(parent, args)
    {
    {
         // We ignore any arguments - data engines do not have much use for them
         // Ignoramos alguns argumentos - data engines não tem muito uso para eles
         Q_UNUSED(args)
         Q_UNUSED(args)


         // This prevents applets from setting an unnecessarily high
         // Isso impede que applets usem um alto intervalo de atualização //desnecessariamente de um desnecessariamente e usando muita CPU.
        // update interval and using too much CPU.
         // No caso de um relógio que só tem precisão em segundos,
         // In the case of a clock that only has second precision,
         // Um terço de um segundo deve ser mais do que suficiente.
         // a third of a second should be more than enough.
         setMinimumPollingInterval(333);
         setMinimumPollingInterval(333);
    }
    }
    Line 194: Line 200:
    bool TestTimeEngine::sourceRequestEvent(const QString &name)
    bool TestTimeEngine::sourceRequestEvent(const QString &name)
    {
    {
         // We do not have any special code to execute the
         // Nós não temos nenhum código especial para executar a
         // first time a source is requested, so we just call
         // Primeira vez que uum source seja solicitado, por isso, basta chamar
         // updateSourceEvent().
         // updateSourceEvent().
         return updateSourceEvent(name);
         return updateSourceEvent(name);
    Line 205: Line 211:


         if (name == I18N_NOOP("Local")) {
         if (name == I18N_NOOP("Local")) {
             // Local is a special case - we just get the current time and date
             // Local é um caso especial - é só pegar a hora e data atual
             setData(name, I18N_NOOP("Time"), QTime::currentTime());
             setData(name, I18N_NOOP("Time"), QTime::currentTime());
             setData(name, I18N_NOOP("Date"), QDate::currentDate());
             setData(name, I18N_NOOP("Date"), QDate::currentDate());
         } else {
         } else {
             // First check the timezone is valid
             // Primeiro verifica se o fuso horario é válido
             KTimeZone newTz = KSystemTimeZones::zone(name);
             KTimeZone newTz = KSystemTimeZones::zone(name);
             if (!newTz.isValid()) {
             if (!newTz.isValid()) {
    Line 215: Line 221:
             }
             }


             // Get the date and time
             // Pegando a data e hora
             KDateTime dt = KDateTime::currentDateTime(newTz);
             KDateTime dt = KDateTime::currentDateTime(newTz);
             setData(name, I18N_NOOP("Time"), dt.time());
             setData(name, I18N_NOOP("Time"), dt.time());
    Line 223: Line 229:
    }
    }


    // This does the magic that allows Plasma to load
    // Isso faz a mágica que permite o Plasma carregar
    // this plugin. The first argument must match
    // este plugin. O primeiro argumento deve corresponder
    // the X-Plasma-EngineName in the .desktop file.
    // ao X-Plasma-EngineName in the .desktop file.
    K_EXPORT_PLASMA_DATAENGINE(testtime, TestTimeEngine)
    K_EXPORT_PLASMA_DATAENGINE(testtime, TestTimeEngine)


    // this is needed since TestTimeEngine is a QObject
    // Isto é necessário uma vez que é um TestTimeEngine QObject
    #include "testtimeengine.moc"
    #include "testtimeengine.moc"
    </code>
    </syntaxhighlight>




    ====Responding to Requests for Sources====
    ====Responding to Requests for Sources====


    The <tt>sourceRequestEvent()</tt> 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.
    O <tt>sourceRequestEvent()</tt> método é chamado pela primeira vez quando um source é carregado. Você pode usar isso para fazer qualquer processamento especial que deve ser feito pela primeira vez uma fonte é criada, mas não quando ele é atualizado posteriormente.


    If a source is created with a polling interval, <tt>updateSourceEvent()</tt> will be called each time that interval expires. For example, if an applet requests a source "foo" with a polling interval of 500ms, <tt>sourceRequestEvent("foo")</tt> will be called initially, then half a second later, and every half a second after that, <tt>updateSourceEvent("foo")</tt> will be called.
    Se um source é criado com um intervalo de pesquisa, <tt>updateSourceEvent()</tt> será chamado a cada intervalo de tempo em que expira. Por exemplo, se um applet solicita o source "foo", com um intervalo de pesquisa de 500ms, <tt>sourceRequestEvent("foo")</tt> serão chamados, inicialmente, em seguida, meio segundo mais tarde, e a cada meio segundo depois que <tt>updateSourceEvent("foo") </ tt> for chamado.


    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.
    Note, no entanto, que os applets não têm que definir um intervalo de pesquisa e
    podem simplesmente esperar por uma engine para passar os dados para ele.


    ====Controlando a frequência de atualização====


    ====Controlling Update Frequency====
    Há alguns métodos para controlar as atualizações. Usamos <tt>setMinimumPollingInterval(333)</tt> para evitar <tt>updateSourceEvent()</tt>
    a ser chamado mais de três vezes por segundo por qualquer source.
    Você também pode aplicar um intervalo de atualização específica para todos os
    sources fornecidos por esta engine com <tt>setPollingInterval()</tt>, que leva
    um tempo em milissegundos como seu único argumento.


    There are a couple of methods for controlling updates.  We use <tt>setMinimumPollingInterval(333)</tt> to prevent <tt>updateSourceEvent()</tt> 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 <tt>setPollingInterval()</tt>, which takes a time in milliseconds as its only argument.
    ====Respondendo a eventos externos====


    ====Responding to Outside Events====
    Pesquisa não faz sentido para todos as engines. Alguns mecanismos, como uma engine do dispositivo, responder a eventos externos. Você pode usar <tt>setData()</tt> a qualquer momento para criar ou atualizar um source.
    <tt>removeData()</ tt> e <tt>removeSource()</tt> também são métodos úteis. Para os applets que quiser ser informado quando o source muda, sem usar pesquisa,
    use <tt>dataUpdated</tt>. Use-o chamando <tt>connectSource</tt>.


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


    ====Listando potenciais sources====


    ====Listing Potential Sources====
    Applets podem solicitar uma lista das fontes disponíveis para uma engine. Por padrão, esta é apenas uma lista de todos os sources que foram criados (com <tt> setData()</ tt> ou <tt>addSource()</ tt>) até agora (e não retirados, é claro). No entanto, você pode querer procurar sources, mas na verdade não criá-los. Por
    exemplo, podemos procurar para cada fuso horário que o sistema conhece, mas não
    realmente criar e preencher os sources, já que dificilmente será usado realmente.


    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 <tt>setData()</tt> or <tt>addSource()</tt>) 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.
    Isso pode ser feito reimplementando <tt>virtual QStringList sources() const</tt> e devolvendo uma lista dos nomes de todas as fontes disponíveis.


    This can be done by reimplementing <tt>virtual QStringList sources() const</tt> and returning a list of the names of all the available sources.
    ====Inicialização====


    Se você quiser executar qualquer inicialização além de propriedades
    simples, como popular sources, você não pode fazê-lo no construtor, já
    que a data engine não foi devidamente inicializado neste momento. Em vez
    disso, reimplemente método <tt>virtual void init()</tt>.


    ====Initialisation====
    Por exemplo, o tasks data engine utiliza método <tt>init()</tt>
    para obter uma lista de todas as tarefas em execução e cria sources para cada uma delas.


    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 <tt>virtual void init()</tt> method.


    For example, the tasks data engine uses the <tt>init()</tt> method to get a list of all the currently running tasks and creates sources for each of them.
    ====Mais controle sobre os dados====


    O <tt>DataContainer</tt> da classe pode ser usado para dar mais controle
    sobre a atualização de dados se você precisar dele. Os métodos de <tt>DataEngine</tt> são <tt>DataContainer* containerForSource(const QString& source)</tt>, <tt>void addSource(DataContainer* source)</tt> e <tt>SourceDict containerDict() const</tt>.


    ====More Control Over Data====
    ===Building===


    The <tt>DataContainer</tt> class can be used to give you more control over updating data if you need it. The relevant methods of <tt>DataEngine</tt> are <tt>DataContainer* containerForSource(const QString& source)</tt>, <tt>void addSource(DataContainer* source)</tt> and <tt>SourceDict containerDict() const</tt>.
    O arquivo CMakeLists.txt diz ao CMake como construir o seu plugin. O arquivo seguinte vai trabalhar para este projeto:


    ===Building It===
    <syntaxhighlight lang="bash">
     
    # Um nome para o projeto
    The CMakeLists.txt file tells CMake how to build your plugin.  The following file will work for this project:
     
    <code bash>
    # A name for the project
    project(plasma-testtime)
    project(plasma-testtime)


    # Find the required Libaries
    # Encontre as Libraries requisitadas
    find_package(KDE4 REQUIRED)
    find_package(KDE4 REQUIRED)
    include(KDE4Defaults)
    include(KDE4Defaults)
    Line 288: Line 306:
       )
       )


    # We add our source code here
    # Adicionamos nossos fontes aqui
    set(testtime_engine_SRCS testtimeengine.cpp)
    set(testtime_engine_SRCS testtimeengine.cpp)


    # Now make sure all files get to the right place
    # Agora certifique-se de todos os arquivos estão no lugar certo
    kde4_add_plugin(plasma_engine_testtime ${testtime_engine_SRCS})
    kde4_add_plugin(plasma_engine_testtime ${testtime_engine_SRCS})
    target_link_libraries(plasma_engine_testtime
    target_link_libraries(plasma_engine_testtime
    Line 302: Line 320:
    install(FILES plasma-engine-testtime.desktop
    install(FILES plasma-engine-testtime.desktop
             DESTINATION ${SERVICES_INSTALL_DIR})
             DESTINATION ${SERVICES_INSTALL_DIR})
    </code>
    </syntaxhighlight>




    ==Testing==
    ==Testando==


    Run
    Execute:
    <code bash>
    <syntaxhighlight lang="bash">
    cmake -DCMAKE_BUILD_TYPE=debugfull -DCMAKE_INSTALL_PREFIX=$KDEDIR
    cmake -DCMAKE_BUILD_TYPE=debugfull -DCMAKE_INSTALL_PREFIX=$KDEDIR
    make
    make
    make install
    make install
    </code>
    </syntaxhighlight>


    Replace <tt>$KDEDIR</tt> with your kde installation directory if <tt>$KDEDIR</tt> is not set.
    Substitua <tt>$KDEDIR</tt> com o diretório de instalação do KDE se <tt>$KDEDIR </tt> não está definido.


    Alternatively, you can run the following
    Alternativamente, você pode executar o seguinte:
    <code bash>
    <syntaxhighlight lang="bash">
    cmake -DCMAKE_BUILD_TYPE=debugfull
    cmake -DCMAKE_BUILD_TYPE=debugfull
    make
    make
    cp ./lib/plasma_engine_testtime.so $KDEDIR/lib/kde4
    cp ./lib/plasma_engine_testtime.so $KDEDIR/lib/kde4
    cp ./plasma-engine-testtime.desktop $KDEDIR/share/kde4/services/
    cp ./plasma-engine-testtime.desktop $KDEDIR/share/kde4/services/
    </code>
    </syntaxhighlight>


    Now run <tt>kbuildsycoca4</tt> to tell KDE applications (including plasma and the plasma engine explorer) about the new desktop file.
    Agora execute <tt>kbuildsycoca4</tt> para contar para as aplicações do KDE (incluindo o plasma e o plasma engine explorer) sobre o novo arquivo .desktop.


    Now you can test it as we did the time engine. Run
    Agora você pode testá-lo, como fizemos com o time engine. Execute:
    <code bash>
    <syntaxhighlight lang="bash">
    plasmaengineexplorer --engine testtime
    plasmaengineexplorer --engine testtime
    </code>
    </syntaxhighlight>
     
    Note que se você alterar uma data engine (ou applet), a mudança não irá
    registrar em todos os aplicativos em execução. Após a modificação e reinstalação
    de uma data engine, para fazer plasma registrar a mudança que você deve
    executar:


    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
    <syntaxhighlight lang="bash">
    <code bash>
    kbuildsycoca4
    kbuildsycoca4
    kquitapp plasma-desktop (or plasma-netbook, etc)
    kquitapp plasma-desktop (or plasma-netbook, etc)
    plasma-desktop
    plasma-desktop
    </code>
    </syntaxhighlight>

    Revision as of 16:41, 19 July 2012

    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.

    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=[email protected]
    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 <[email protected]>
     *
     *   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
    #ifndef TESTTIMEENGINE_H
    #define TESTTIMEENGINE_H
    
    // Precisamos do cabeçalho DataEngine, já que TestTimeEngine herda dele
    #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);
    };
    
    #endif // TESTTIMEENGINE_H
    

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

    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.

    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 <[email protected]>
     *
     *   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.
     */
    
    #include "testtimeengine.h"
    
    #include <QDate>
    #include <QTime>
    
    #include <KSystemTimeZones>
    #include <KDateTime>
    
    #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 {
            // Primeiro verifica se o fuso horario é válido
            KTimeZone newTz = KSystemTimeZones::zone(name);
            if (!newTz.isValid()) {
                return false;
            }
    
            // Pegando a data e hora
            KDateTime dt = KDateTime::currentDateTime(newTz);
            setData(name, I18N_NOOP("Time"), dt.time());
            setData(name, I18N_NOOP("Date"), dt.date());
        }
        return true;
    }
    
    // Isso faz a mágica que permite o Plasma carregar
    // este plugin. O primeiro argumento deve corresponder 
    // ao X-Plasma-EngineName in the .desktop file.
    K_EXPORT_PLASMA_DATAENGINE(testtime, TestTimeEngine)
    
    // Isto é necessário uma vez que é um TestTimeEngine QObject
    #include "testtimeengine.moc"
    


    Responding to Requests for Sources

    O sourceRequestEvent() método é chamado pela primeira vez quando um source é carregado. Você pode usar isso para fazer qualquer processamento especial que deve ser feito pela primeira vez uma fonte é criada, mas não quando ele é atualizado posteriormente.

    Se um source é criado com um intervalo de pesquisa, updateSourceEvent() será chamado a cada intervalo de tempo em que expira. Por exemplo, se um applet solicita o source "foo", com um intervalo de pesquisa de 500ms, sourceRequestEvent("foo") serão chamados, inicialmente, em seguida, meio segundo mais tarde, e a cada meio segundo depois que updateSourceEvent("foo") </ tt> for chamado.

    Note, no entanto, que os applets não têm que definir um intervalo de pesquisa e podem simplesmente esperar por uma engine para passar os dados para ele.

    Controlando a frequência de atualização

    Há alguns métodos para controlar as atualizações. Usamos setMinimumPollingInterval(333) para evitar updateSourceEvent() a ser chamado mais de três vezes por segundo por qualquer source. Você também pode aplicar um intervalo de atualização específica para todos os sources fornecidos por esta engine com setPollingInterval(), que leva um tempo em milissegundos como seu único argumento.

    Respondendo a eventos externos

    Pesquisa não faz sentido para todos as engines. Alguns mecanismos, como uma engine do dispositivo, responder a eventos externos. Você pode usar setData() a qualquer momento para criar ou atualizar um source. removeData()</ tt> e removeSource() também são métodos úteis. Para os applets que quiser ser informado quando o source muda, sem usar pesquisa, use dataUpdated. Use-o chamando connectSource.


    Listando potenciais sources

    Applets podem solicitar uma lista das fontes disponíveis para uma engine. Por padrão, esta é apenas uma lista de todos os sources que foram criados (com setData()</ tt> ou addSource()</ tt>) até agora (e não retirados, é claro). No entanto, você pode querer procurar sources, mas na verdade não criá-los. Por exemplo, podemos procurar para cada fuso horário que o sistema conhece, mas não realmente criar e preencher os sources, já que dificilmente será usado realmente.

    Isso pode ser feito reimplementando virtual QStringList sources() const e devolvendo uma lista dos nomes de todas as fontes disponíveis.

    Inicialização

    Se você quiser executar qualquer inicialização além de propriedades simples, como popular sources, você não pode fazê-lo no construtor, já que a data engine não foi devidamente inicializado neste momento. Em vez disso, reimplemente método virtual void init().

    Por exemplo, o tasks data engine utiliza método init() para obter uma lista de todas as tarefas em execução e cria sources para cada uma delas.


    Mais controle sobre os dados

    O DataContainer da classe pode ser usado para dar mais controle sobre a atualização de dados se você precisar dele. Os métodos de DataEngine são DataContainer* containerForSource(const QString& source), void addSource(DataContainer* source) e SourceDict containerDict() const.

    Building

    O arquivo CMakeLists.txt diz ao CMake como construir o seu plugin. O arquivo seguinte vai trabalhar para este projeto:

    # Um nome para o projeto
    project(plasma-testtime)
    
    # Encontre as Libraries requisitadas
    find_package(KDE4 REQUIRED)
    include(KDE4Defaults)
    
    add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
    include_directories(
       ${CMAKE_SOURCE_DIR}
       ${CMAKE_BINARY_DIR}
       ${KDE4_INCLUDES}
       )
    
    # Adicionamos nossos fontes aqui
    set(testtime_engine_SRCS testtimeengine.cpp)
    
    # Agora certifique-se de todos os arquivos estão no lugar certo
    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})
    


    Testando

    Execute:

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

    Substitua $KDEDIR com o diretório de instalação do KDE se $KDEDIR não está definido.

    Alternativamente, você pode executar o seguinte:

    cmake -DCMAKE_BUILD_TYPE=debugfull
    make
    cp ./lib/plasma_engine_testtime.so $KDEDIR/lib/kde4
    cp ./plasma-engine-testtime.desktop $KDEDIR/share/kde4/services/
    

    Agora execute kbuildsycoca4 para contar para as aplicações do KDE (incluindo o plasma e o plasma engine explorer) sobre o novo arquivo .desktop.

    Agora você pode testá-lo, como fizemos com o time engine. Execute:

    plasmaengineexplorer --engine testtime
    

    Note que se você alterar uma data engine (ou applet), a mudança não irá registrar em todos os aplicativos em execução. Após a modificação e reinstalação de uma data engine, para fazer plasma registrar a mudança que você deve executar:

    kbuildsycoca4
    kquitapp plasma-desktop (or plasma-netbook, etc)
    plasma-desktop