Selaa lähdekoodia

Added "code snippet" support.

The ctkFunctionCompileSnippets CMake function can be used to compile
code snippets in a given directory. This is useful for including
code in doxygen files which is certain to compile.

Added one snippet for an Event Admin introduction.
Sascha Zelzer 13 vuotta sitten
vanhempi
commit
4369ec706e

+ 65 - 0
CMake/ctkFunctionCompileSnippets.cmake

@@ -0,0 +1,65 @@
+
+#! Compile code snippets from a given directory
+#!
+#! This CMake function globs all files called \e main.cpp in the
+#! directory given by <code>snippet_path</code> and creates
+#! an executable for each found main.cpp.
+#!
+#! If a \e files.cmake file exists in the same directory where a
+#! main.cpp file was found, it is included. This function assumes
+#! that the files.cmake file sets a list named \e snippet_src_files
+#! containing a list of files which should be compiled into the
+#! executable. If no files.cmake file is found, all files in the
+#! directory are compiled into the executable.
+#!
+#! This function uses all additionally passed arguments as link
+#! dependencies for the created executable.
+#!
+function(ctkFunctionCompileSnippets snippet_path)
+
+  # get all files called "main.cpp"
+  file(GLOB_RECURSE main_cpp_list "${snippet_path}/main.cpp")
+
+  foreach(main_cpp_file ${main_cpp_list})
+    # get the directory containing the main.cpp file
+    get_filename_component(main_cpp_dir "${main_cpp_file}" PATH)
+    
+    set(snippet_src_files )
+    
+    # If there exists a "files.cmake" file in the snippet directory,
+    # include it and assume it sets the variable "snippet_src_files"
+    # to a list of source files for the snippet.
+    if(EXISTS "${main_cpp_dir}/files.cmake")
+      include("${main_cpp_dir}/files.cmake")
+      set(_tmp_src_files ${snippet_src_files})
+      set(snippet_src_files )
+      foreach(_src_file ${_tmp_src_files})
+        if(IS_ABSOLUTE ${_src_file})
+          list(APPEND snippet_src_files ${_src_file})
+        else()
+          list(APPEND snippet_src_files ${main_cpp_dir}/${_src_file})
+        endif()
+      endforeach()
+    else()
+      # glob all files in the directory and add them to the snippet src list
+      file(GLOB_RECURSE snippet_src_files "${main_cpp_dir}/*")
+    endif()
+    
+    # Uset the top-level directory name as the executable name
+    string(REPLACE "/" ";" main_cpp_dir_tokens "${main_cpp_dir}")
+    list(GET main_cpp_dir_tokens -1 snippet_exec_name)
+    set(snippet_target_name "Snippet-${snippet_exec_name}")
+    add_executable(${snippet_target_name} ${snippet_src_files})
+    if(ARGN)
+      target_link_libraries(${snippet_target_name} ${ARGN})
+    endif()
+    set_target_properties(${snippet_target_name} PROPERTIES
+      RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/snippets"
+      ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/snippets"
+      LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/snippets"
+      OUTPUT_NAME ${snippet_exec_name}
+    )
+    
+  endforeach()
+
+endfunction()

+ 1 - 0
CMakeLists.txt

@@ -199,6 +199,7 @@ include(CMake/ctkFunctionCheckCompilerFlags.cmake)
 include(CMake/ctkFunctionGetIncludeDirs.cmake)
 include(CMake/ctkFunctionGetLibraryDirs.cmake)
 include(CMake/ctkFunctionGetGccVersion.cmake)
+include(CMake/ctkFunctionCompileSnippets.cmake)
 
 #-----------------------------------------------------------------------------
 # Testing

+ 2 - 1
Documentation/Doxyfile.txt.in

@@ -705,6 +705,7 @@ EXCLUDE_PATTERNS       = moc_*.cxx \
                          */Testing/* \
                          */Utilities/* \
                          */Widgets/Plugins/* \
+                         */Snippets/* \
                          @CTK_ADDITIONAL_EXCLUDE_PATTERN@
 
 # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
@@ -719,7 +720,7 @@ EXCLUDE_SYMBOLS        =
 # directories that contain example code fragments that are included (see
 # the \include command).
 
-EXAMPLE_PATH           =
+EXAMPLE_PATH           = @CTK_SOURCE_DIR@/Libs/PluginFramework/Documentation/Snippets/
 
 # If the value of the EXAMPLE_PATH tag contains directories, you can use the
 # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp

+ 4 - 0
Libs/PluginFramework/CMakeLists.txt

@@ -162,4 +162,8 @@ endif()
 # Testing
 if(BUILD_TESTING)
   add_subdirectory(Testing)
+
+  # Compile source code snippets
+  add_subdirectory(Documentation/Snippets)
+
 endif()

+ 4 - 0
Libs/PluginFramework/Documentation/Snippets/CMakeLists.txt

@@ -0,0 +1,4 @@
+if(BUILD_TESTING)
+  include_directories(${CTKPluginFramework_SOURCE_DIR})
+  ctkFunctionCompileSnippets("${CMAKE_CURRENT_SOURCE_DIR}" CTKPluginFramework)
+endif()

+ 157 - 0
Libs/PluginFramework/Documentation/Snippets/EventAdmin-Intro/ctkSnippetReportManager.h

@@ -0,0 +1,157 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#ifndef CTKSNIPPETREPORTMANAGER_H
+#define CTKSNIPPETREPORTMANAGER_H
+
+#include <ctkPluginContext.h>
+#include <ctkServiceReference.h>
+
+#include <service/event/ctkEventAdmin.h>
+#include <service/event/ctkEventHandler.h>
+
+#include <ctkPluginFrameworkLauncher.h>
+
+#include <QTime>
+
+class Report
+{
+public:
+  QString getTitle() const { return "dummy"; }
+  QString getAbsolutePath() const { return "dummy"; }
+};
+
+//! [Event Handler service]
+class ReportEventHandler : public QObject, public ctkEventHandler
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkEventHandler)
+
+public:
+
+  void handleEvent(const ctkEvent& event)
+  {
+    QString reportTitle = event.getProperty("title").toString();
+    QString reportPath = event.getProperty("path").toString();
+
+    // sendReportByEmail(reportTitle, reportPath);
+    qDebug() << "title:" << reportTitle << "path:" << reportPath;
+  }
+};
+//! [Event Handler service]
+
+//! [Event Handler slot]
+class ReportEventHandlerUsingSlots : public QObject
+{
+  Q_OBJECT
+
+public slots:
+
+  void handleEvent(const ctkEvent& event)
+  {
+    QString reportTitle = event.getProperty("title").toString();
+    QString reportPath = event.getProperty("path").toString();
+
+    // sendReportByEmail(reportTitle, reportPath);
+    qDebug() << "[slot] title:" << reportTitle << "path:" << reportPath;
+  }
+};
+//! [Event Handler slot]
+
+class ReportManager : public QObject
+{
+  Q_OBJECT
+
+public:
+
+  //! [Register signal]
+  ReportManager(ctkPluginContext* context)
+  {
+    ctkServiceReference ref = context->getServiceReference<ctkEventAdmin>();
+    if (ref)
+    {
+      ctkEventAdmin* eventAdmin = context->getService<ctkEventAdmin>(ref);
+      // Using Qt::DirectConnection is equivalent to ctkEventAdmin::sendEvent()
+      eventAdmin->publishSignal(this, SIGNAL(reportGeneratedSignal(ctkDictionary)),
+                                "com/acme/reportgenerator/GENERATED", Qt::DirectConnection);
+    }
+  }
+  //! [Register signal]
+
+  //! [Emit signal]
+  void reportGenerated(const Report& report)
+  {
+    ctkDictionary properties;
+    properties["title"] = report.getTitle();
+    properties["path"] = report.getAbsolutePath();
+    properties["time"] = QTime::currentTime();
+    emit reportGeneratedSignal(properties);
+  }
+  //! [Emit signal]
+
+  //! [Publish event]
+  void reportGenerated(const Report& report, ctkPluginContext* context)
+  {
+    ctkServiceReference ref = context->getServiceReference<ctkEventAdmin>();
+    if (ref)
+    {
+      ctkEventAdmin* eventAdmin = context->getService<ctkEventAdmin>(ref);
+
+      ctkDictionary properties;
+      properties["title"] = report.getTitle();
+      properties["path"] = report.getAbsolutePath();
+      properties["time"] = QTime::currentTime();
+
+      ctkEvent reportGeneratedEvent("com/acme/reportgenerator/GENERATED", properties);
+      eventAdmin->sendEvent(reportGeneratedEvent);
+    }
+  }
+  //! [Publish event]
+
+  void reportGeneratedAsync(const Report& report, ctkPluginContext* context)
+  {
+    ctkServiceReference ref = context->getServiceReference<ctkEventAdmin>();
+    if (ref)
+    {
+      ctkEventAdmin* eventAdmin = context->getService<ctkEventAdmin>(ref);
+
+      ctkDictionary properties;
+      properties["title"] = report.getTitle();
+      properties["path"] = report.getAbsolutePath();
+      properties["time"] = QTime::currentTime();
+
+      //! [Publish event async]
+      ctkEvent reportGeneratedEvent("com/acme/reportgenerator/GENERATED", properties);
+      eventAdmin->postEvent(reportGeneratedEvent);
+      //! [Publish event async]
+    }
+  }
+
+  //! [Declare signal]
+signals:
+
+  void reportGeneratedSignal(const ctkDictionary&);
+  //! [Declare signal]
+
+};
+
+#endif // CTKSNIPPETREPORTMANAGER_H

+ 13 - 0
Libs/PluginFramework/Documentation/Snippets/EventAdmin-Intro/files.cmake

@@ -0,0 +1,13 @@
+set(snippet_src_files
+  main.cpp
+  ctkSnippetReportManager.h
+)
+
+set(_moc_files
+  ctkSnippetReportManager.h
+)
+
+foreach(_moc_file ${_moc_files})
+  QT4_WRAP_CPP(snippet_src_files EventAdmin-Intro/${_moc_file}
+               OPTIONS -f${CMAKE_CURRENT_SOURCE_DIR}/EventAdmin-Intro/${_moc_file})
+endforeach()

+ 64 - 0
Libs/PluginFramework/Documentation/Snippets/EventAdmin-Intro/main.cpp

@@ -0,0 +1,64 @@
+
+#include <ctkPluginConstants.h>
+#include <service/event/ctkEventConstants.h>
+
+#include <QCoreApplication>
+#include <QDir>
+
+#include "ctkSnippetReportManager.h"
+
+// dummy main
+int main(int argc, char** argv)
+{
+  QCoreApplication myApp(argc, argv);
+
+  QString tmpPath = QDir::tempPath() + "/snippet-eventadmin-intro";
+  ctkProperties fwProps;
+  fwProps[ctkPluginConstants::FRAMEWORK_STORAGE] = tmpPath;
+  fwProps[ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN] = ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT;
+  fwProps["org.commontk.pluginfw.debug.resolve"] = true;
+  fwProps["org.commontk.pluginfw.debug.service_reference"] = true;
+  fwProps["org.commontk.pluginfw.debug.errors"] = true;
+  fwProps["org.commontk.pluginfw.debug.pluginfw"] = true;
+  fwProps["org.commontk.pluginfw.debug.lazy_activation"] = true;
+  ctkPluginFrameworkLauncher::setFrameworkProperties(fwProps);
+  ctkPluginFrameworkLauncher::start("org.commontk.eventadmin");
+
+  ctkPluginContext* pluginContext = ctkPluginFrameworkLauncher::getPluginContext();
+
+  ReportManager reportManager(pluginContext);
+
+  //! [Event Handler service registration]
+  ReportEventHandler eventHandler;
+  ctkDictionary props;
+  props[ctkEventConstants::EVENT_TOPIC] = "com/acme/reportgenerator/GENERATED";
+  pluginContext->registerService<ctkEventHandler>(&eventHandler, props);
+  //! [Event Handler service registration]
+
+  // You can also use a wildcard in the final character of the EVENT_TOPIC
+  //! [Event Handler service registration wildcard]
+  props[ctkEventConstants::EVENT_TOPIC] = "com/acme/reportgenerator/*";
+  pluginContext->registerService<ctkEventHandler>(&eventHandler, props);
+  //! [Event Handler service registration wildcard]
+
+  // Or you could use a filter expression (using LDAP syntax)
+  //! [Event Handler service registration filter]
+  props[ctkEventConstants::EVENT_TOPIC] = "com/acme/reportgenerator/GENERATED";
+  props[ctkEventConstants::EVENT_FILTER] = "(title=samplereport)";
+  pluginContext->registerService<ctkEventHandler>(&eventHandler, props);
+  //! [Event Handler service registration filter]
+
+  //! [Event Handler service registration slot]
+  ReportEventHandlerUsingSlots eventHandlerUsingSlots;
+  ctkDictionary propsForSlot;
+  propsForSlot[ctkEventConstants::EVENT_TOPIC] = "com/acme/reportgenerator/*";
+  ctkServiceReference ref = pluginContext->getServiceReference<ctkEventAdmin>();
+  if (ref)
+  {
+    ctkEventAdmin* eventAdmin = pluginContext->getService<ctkEventAdmin>(ref);
+    eventAdmin->subscribeSlot(&eventHandlerUsingSlots, SLOT(handleEvent(ctkEvent)), propsForSlot);
+  }
+  //! [Event Handler service registration slot]
+
+  reportManager.reportGenerated(Report());
+}