====== 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()