====== Tutorial de Criação de Novos Módulos da TerraLib ======
**Autor:** Gilberto Ribeiro de Queiroz\\
**Data:** 16 de Abril, 2015
**Objetivo:** Este documento ensina de maneira rápida e prática como incluir novos módulos na plataforma TerraLib, incluindo a criação de plugins que possam ser disponibilizados na família de aplicativos TerraLib.
**Status:** //Em desenvolvimento//
===== Organizando os Fontes do Novo Módulo =====
Todos os módulos da TerraLib encontram-se na pasta ''src/terralib''. Neste exemplo iremos criar um novo módulo hipotético que lide com a extração de redes de drenagem. Nosso novo módulo será chamado de //Network Drainage// e será armazenado na pasta ''src/terralib/netdrain''.
Este novo módulo será formado por sua vez por outros três sub-módulos:
* **core:** contendo o código fonte das estruturas de dados e algoritmos que realizam a extração das redes de drenagem. Este módulo dará origem a uma biblioteca compartilhada, que pode ser utilizada de forma independente de uma aplicação específica.
* **qt:** contendo componentes gráficos desenvolvidos em Qt, que possibilite ao usuário selecionar camadas de informação e informar parâmetros para execução do algoritmo de extração de drenagem.
* **plugin:** implementará um conector com o //framework// de aplicação Qt da TerraLib que irá adicionar entradas na barra de menu e barra de botões das aplicações da família TerraLib. Este plugin será responsável, entre outras coisas, por preencher a lista de camadas de informação dos nossos componentes gráficos do outro módulo (netdrain::qt).
O código de cada um dos sub-módulos será colocado em uma pasta própria. Supondo que você esteja em um //shell// na raiz do repositório da TerraLib, vamos criar as seguintes pastas:
$ mkdir src/terralib/netdrain
$ mkdir src/terralib/netdrain/core
$ mkdir src/terralib/netdrain/qt
$ mkdir src/terralib/netdrain/plugin
Na pasta ''src/terralib/netdrain/core'' iremos colocar os arquivos: ''FlowAlg1.h'', ''FlowAlg1.cpp'', ''FlowAlg2.h'', ''FlowAlg2.cpp'', ''FlowUtils.h'' e ''FlowUtils.cpp''.
Na pasta ''src/terralib/netdrain/qt'' iremos incluir arquivos de código fonte para componentes Qt: ''FlowDialog.ui'', ''FlowDialog.h'' e ''FlowDialog.cpp''.
Na pasta ''src/terralib/netdrain/plugin'' iremos concentrar os códigos relativos a ligação dos nossos outros dois módulos à família de aplicativos. Neste exemplo, apenas o arquivo ''Plugin.cpp'' será necessário.
===== Registrando o Módulo netdrain::core no Build da TerraLib =====
Agora, precisamos criar um projeto de //build// para o módulo netdrain::core. Para isso, precisamos escrever um arquivo ''CMakeLists.txt'' como mostrado abaixo:
#
# Include path to all dependent libraries
#
include_directories(${Boost_INCLUDE_DIR})
#
# Export as DLL on Microsoft Windows
#
if(WIN32)
add_definitions(-DTENETDRAINCOREDLL)
endif()
#
# Select all the files for this project.
#
file(GLOB TERRALIB_SRC_FILES ${TERRALIB_ABSOLUTE_ROOT_DIR}/src/terralib/netdrain/core/*.cpp)
file(GLOB TERRALIB_HDR_FILES ${TERRALIB_ABSOLUTE_ROOT_DIR}/src/terralib/netdrain/core/*.h)
#
# Group files in specific folders for some IDEs (VC++, Xcode, Eclipse).
#
source_group("Source Files" FILES ${TERRALIB_SRC_FILES})
source_group("Header Files" FILES ${TERRALIB_HDR_FILES})
#
# Define the core module as a shared library.
#
add_library(terralib_mod_netdrain_core SHARED ${TERRALIB_SRC_FILES} ${TERRALIB_HDR_FILES})
#
# Link with dependent libraries and modules.
#
target_link_libraries(terralib_mod_netdrain_core terralib_mod_common terralib_mod_raster terralib_mod_geometry)
#
# Versioning the new module library on Unix-like systems.
#
set_target_properties(terralib_mod_netdrain_core
PROPERTIES VERSION ${TERRALIB_VERSION_MAJOR}.${TERRALIB_VERSION_MINOR}
SOVERSION ${TERRALIB_VERSION_MAJOR}.${TERRALIB_VERSION_MINOR}
INSTALL_NAME_DIR "@executable_path/../lib")
#
# Register module stuffs for installation.
#
install(TARGETS terralib_mod_netdrain_core
EXPORT terralib-targets
RUNTIME DESTINATION ${TERRALIB_DESTINATION_RUNTIME} COMPONENT runtime
LIBRARY DESTINATION ${TERRALIB_DESTINATION_LIBRARY} COMPONENT runtime
ARCHIVE DESTINATION ${TERRALIB_DESTINATION_ARCHIVE} COMPONENT runtime)
install(FILES ${TERRALIB_HDR_FILES}
DESTINATION ${TERRALIB_DESTINATION_HEADERS}/terralib/netdrain/core COMPONENT devel)
#
# Register module in CMake export file.
#
export(TARGETS terralib_mod_netdrain_core APPEND FILE ${CMAKE_BINARY_DIR}/terralib-exports.cmake)
Os texto iniciados com uma hash-tag (''#'') são comentários que explicam as partes importantes de um arquivo de //build// para um módulo.
Como o projeto de //build// da TerraLib encontra-se na pasta ''build/cmake'', crie uma pasta denominada de ''terralib_mod_netdrain_core'' neste local (''build/cmake/terralib_mod_netdrain_core'') e inclua o arquivo ''CMakeLists.txt'' nesta pasta.
Agora, precisamos registrar este novo módulo no arquivo principal do projeto de //build//. No arquivo ''build/cmake/CMakeLists.txt'', indique que o novo módulo deve ser usado pelo sistema de build, como mostrado abaixo:
...
CMAKE_DEPENDENT_OPTION(TERRALIB_MOD_EDIT_QT_ENABLED "Build Edit Qt module?" ON "TERRALIB_MOD_EDIT_CORE_ENABLED;TERRALIB_MOD_QT_WIDGETS_ENABLED" OFF)
CMAKE_DEPENDENT_OPTION(TERRALIB_MOD_QT_PLUGINS_EDIT_ENABLED "Build Edit Qt plugin?" ON "TERRALIB_MOD_PLUGIN_ENABLED;TERRALIB_MOD_QT_APF_ENABLED;TERRALIB_MOD_EDIT_QT_ENABLED" OFF)
if(QT_QCOLLECTIONGENERATOR_EXECUTABLE)
CMAKE_DEPENDENT_OPTION(TERRALIB_QHELP_ENABLED "Enable Qt-Help build?" ON "TERRALIB_QT_ENABLED;TERRALIB_MOD_QT_WIDGETS_ENABLED" OFF)
endif()
option(TERRALIB_MOD_NETWORK_DRAINAGE_CORE_ENABLED "Build Network Dranage Core module?" ON)
#
# build options for the TerraLib examples
#
CMAKE_DEPENDENT_OPTION(TERRALIB_EXAMPLE_ADO_ENABLED "Build the ADO example?" ON "WIN32;TERRALIB_BUILD_EXAMPLES_ENABLED;TERRALIB_MOD_DATAACCESS_ENABLED;TERRALIB_MOD_PLUGIN_ENABLED" OFF)
...
if(TERRALIB_MOD_QT_PLUGINS_EDIT_ENABLED)
add_subdirectory(terralib_mod_qt_plugins_edit)
endif()
if(TERRALIB_TERRAVIEW_ENABLED)
add_subdirectory(terraview)
endif()
if(TERRALIB_MOD_NETWORK_DRAINAGE_CORE_ENABLED)
add_subdirectory(terralib_mod_netdrain_core)
endif()
#
# build examples
#
if(TERRALIB_EXAMPLE_ADO_ENABLED)
add_subdirectory(terralib_example_ado)
endif()
...
No trecho acima incluímos duas instruções. A primeira:
option(TERRALIB_MOD_NETWORK_DRAINAGE_CORE_ENABLED "Build Network Dranage Core module?" ON)
irá criar a variável ''TERRALIB_MOD_NETWORK_DRAINAGE_CORE_ENABLED'' que será apresentada ao usuário do CMake-GUI com a mensagem informada. Esta variável irá nos dizer se o usuário irá ou não gerar o módulo.
A segunda instrução:
if(TERRALIB_MOD_NETWORK_DRAINAGE_CORE_ENABLED)
add_subdirectory(terralib_mod_netdrain_core)
endif()
irá adicionar o projeto de build.
===== Criando e Registrando o Módulo netdrain::plugin no Build da TerraLib =====
**OBS:** tem um erro nesta seção que classes derivadas do Object precisam de um .h para não ser necessário soluções ADOC!
Agora vamos criar um módulo denominado //netdrain::plugin// que conterá a interface do conector do nosso código aos aplicativos da família TerraLib por meio de um //plugin//.
Para criar um plugin em C++ precisamos criar e registar uma classe que deriva da classe base ''te::plugin::Plugin''. Podemos colocar a definição e registro desta classe em um arquivo C++ como o abaixo:
**Arquivo:** ''src/terralib/netdrain/plugin/Plugin.cpp''
// TerraLib
#include "../../../../common/Translator.h"
#include "../../../../common/Logger.h"
#include "../../../../plugin/Plugin.h"
#include "../../../af/ApplicationController.h"
// Qt
#include
#include
#include
#include
class Plugin : public QObject, public te::plugin::Plugin
{
Q_OBJECT
public:
Plugin(const te::plugin::PluginInfo& pluginInfo);
~Plugin();
void startup();
void shutdown();
protected slots:
void showWindow();
protected:
QAction* m_showWindow;
};
Plugin::Plugin(const te::plugin::PluginInfo& pluginInfo)
: QObject(), te::plugin::Plugin(pluginInfo), m_showWindow(0)
{
}
Plugin::~Plugin()
{
}
void Plugin::startup()
{
if(m_initialized)
return;
m_initialized = true;
}
void Plugin::shutdown()
{
if(!m_initialized)
return;
m_initialized = false;
}
void Plugin::showWindow()
{
}
PLUGIN_CALL_BACK_DECLARATION(TEQTPLUGINNETDRAINEXPORT);
PLUGIN_CALL_BACK_IMPL(Plugin)
Agora precisamos criar um arquivo contendo a descrição deste //plugin//. Este arquivo será usado pelas aplicações da TerraLib para carregar e apresentar informações sobre o //plugin// criado.
**Arquivo:** ''share/terralib/plugins/te.netdrain.teplg''
te.netdrain
Network Drainage
This plugin enables TerraLib 5 applications to process....
5.0.0-alpha.1
GNU Lesser General Public License v 3.0
Data Access
Terralib Team
terralib-team@terralib.org
mkdir build/cmake/terralib_mod_netdrain_plugin
Agora precisamos criar o arquivo ''CMakeLists.txt'' para registrar este //plugin// no sistema de build.
include_directories(${Boost_INCLUDE_DIR})
if(WIN32)
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS -DTEQTPLUGINNETDRAINDLL)
endif()
file(GLOB TERRALIB_SRC_FILES ${TERRALIB_ABSOLUTE_ROOT_DIR}/src/terralib/netdrain/plugin/*.cpp)
file(GLOB TERRALIB_HDR_FILES ${TERRALIB_ABSOLUTE_ROOT_DIR}/src/terralib/netdrain/plugin/*.h)
if(Qt5_FOUND)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(TERRALIB_FILES ${TERRALIB_SRC_FILES} ${TERRALIB_HDR_FILES})
add_library(terralib_mod_netdrain_plugin SHARED ${TERRALIB_FILES})
target_link_libraries(terralib_mod_netdrain_plugin terralib_mod_qt_widgets terralib_mod_qt_apf)
qt5_use_modules(terralib_mod_netdrain_plugin Widgets)
else()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include(${QT_USE_FILE})
include_directories(${QT_INCLUDE_DIR})
add_definitions(${QT_DEFINITIONS})
# moc'ing
set(TERRALIB_HDRS_TO_MOC_FILES ${TERRALIB_ABSOLUTE_ROOT_DIR}/src/terralib/netdrain/plugin/Plugin.h)
QT4_WRAP_CPP(TERRALIB_GEN_SRC_FILES ${TERRALIB_HDRS_TO_MOC_FILES})
set(TERRALIB_FILES ${TERRALIB_SRC_FILES} ${TERRALIB_HDR_FILES} ${TERRALIB_GEN_SRC_FILES})
add_library(terralib_mod_netdrain_plugin SHARED ${TERRALIB_FILES})
target_link_libraries(terralib_mod_netdrain_plugin terralib_mod_qt_widgets
terralib_mod_qt_apf
${QT_LIBRARIES})
endif()
set_target_properties(terralib_mod_netdrain_plugin
PROPERTIES VERSION ${TERRALIB_VERSION_MAJOR}.${TERRALIB_VERSION_MINOR}
SOVERSION ${TERRALIB_VERSION_MAJOR}.${TERRALIB_VERSION_MINOR}
INSTALL_NAME_DIR "@executable_path/../lib")
install(TARGETS terralib_mod_netdrain_plugin
EXPORT terralib-targets
RUNTIME DESTINATION ${TERRALIB_DESTINATION_RUNTIME} COMPONENT runtime
LIBRARY DESTINATION ${TERRALIB_DESTINATION_LIBRARY} COMPONENT runtime
ARCHIVE DESTINATION ${TERRALIB_DESTINATION_ARCHIVE} COMPONENT runtime)
install(FILES ${TERRALIB_HDR_FILES} ${TERRALIB_GEN_HDR_FILES}
DESTINATION ${TERRALIB_DESTINATION_HEADERS}/terralib/netdrain/plugin COMPONENT devel)
install(FILES ${TERRALIB_ABSOLUTE_ROOT_DIR}/share/terralib/plugins/te.netdrain.teplg
DESTINATION ${TERRALIB_DESTINATION_PLUGINS} COMPONENT runtime)
export(TARGETS terralib_mod_netdrain_plugin APPEND FILE ${CMAKE_BINARY_DIR}/terralib-exports.cmake)
Agora podemos registrar este script de build no ''CMakeLists.txt''...
option(TERRALIB_MOD_NETWORK_DRAINAGE_CORE_ENABLED "Build Network Dranage module?" ON)
CMAKE_DEPENDENT_OPTION(TERRALIB_MOD_NETWORK_DRAINAGE_PLUGIN_ENABLED "Build Network Dranage Plugin?" ON "TERRALIB_MOD_NETWORK_DRAINAGE_CORE_ENABLED" OFF)
if(TERRALIB_MOD_NETWORK_DRAINAGE_CORE_ENABLED)
add_subdirectory(terralib_mod_netdrain_core)
endif()
if(TERRALIB_MOD_NETWORK_DRAINAGE_PLUGIN_ENABLED)
add_subdirectory(terralib_mod_netdrain_plugin)
endif()