├── .clang-format ├── .clang-tidy ├── .gitignore ├── CMakeLists.txt ├── COPYING ├── MANIFEST.md ├── README.md ├── cmake ├── Modules │ ├── CMakeParseArgumentsCopy.cmake │ ├── displayConfig.cmake │ └── targetConfig.cmake.in └── cmake_uninstall.cmake.in ├── docs ├── CMakeLists.txt ├── README.display └── doxygen │ ├── CMakeLists.txt │ ├── Doxyfile.in │ ├── doxyxml │ ├── __init__.py │ ├── base.py │ ├── doxyindex.py │ ├── generated │ │ ├── __init__.py │ │ ├── compound.py │ │ ├── compoundsuper.py │ │ ├── index.py │ │ └── indexsuper.py │ └── text.py │ ├── other │ ├── group_defs.dox │ └── main_page.dox │ ├── pydoc_macros.h │ └── update_pydoc.py ├── examples ├── SimpleTextDisplayTest.grc ├── TextMessageTest.grc ├── display_text_msg.grc └── display_text_sink.grc ├── gnuradio-display.pc.in ├── grc ├── CMakeLists.txt ├── display_show_image.block.yml ├── display_show_text.block.yml └── display_text_msg.block.yml ├── include └── display │ ├── CMakeLists.txt │ ├── api.h │ ├── display_text_msg.h │ ├── show_image.h │ └── show_text.h ├── lib ├── CMakeLists.txt ├── display_text_msg_impl.cc ├── display_text_msg_impl.h ├── qa_display_text_msg.cc ├── qa_show_image.cc ├── qa_show_text.cc ├── show_image_impl.cc ├── show_image_impl.h ├── show_text_impl.cc ├── show_text_impl.h ├── show_text_window.cc ├── show_text_window.h ├── showpngpicture.cc ├── showpngpicture.h └── showpngpicture.ui └── python ├── CMakeLists.txt ├── __init__.py ├── bindings ├── CMakeLists.txt ├── README.md ├── bind_oot_file.py ├── display_text_msg_python.cc ├── docstrings │ ├── README.md │ ├── display_text_msg_pydoc_template.h │ ├── show_image_pydoc_template.h │ └── show_text_pydoc_template.h ├── header_utils.py ├── python_bindings.cc ├── show_image_python.cc └── show_text_python.cc ├── qa_display_text_msg.py ├── qa_show_image.py └── qa_show_text.py /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -4 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlinesLeft: true 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: false 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: All 15 | AllowShortIfStatementsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: false 20 | AlwaysBreakTemplateDeclarations: true 21 | BinPackArguments: false 22 | BinPackParameters: false 23 | BreakBeforeBraces: Custom 24 | BraceWrapping: 25 | AfterClass: true 26 | AfterControlStatement: false 27 | AfterEnum: false 28 | AfterFunction: true 29 | AfterNamespace: false 30 | AfterObjCDeclaration: false 31 | AfterStruct: false 32 | AfterUnion: false 33 | BeforeCatch: false 34 | BeforeElse: false 35 | IndentBraces: false 36 | BreakBeforeBinaryOperators: None 37 | BreakBeforeTernaryOperators: true 38 | BreakConstructorInitializersBeforeComma: false 39 | BreakAfterJavaFieldAnnotations: false 40 | BreakStringLiterals: true 41 | ColumnLimit: 90 42 | CommentPragmas: '^ IWYU pragma:' 43 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 44 | ConstructorInitializerIndentWidth: 4 45 | ContinuationIndentWidth: 4 46 | Cpp11BracedListStyle: false 47 | DerivePointerAlignment: false 48 | DisableFormat: false 49 | ExperimentalAutoDetectBinPacking: false 50 | ForEachMacros: 51 | - foreach 52 | - Q_FOREACH 53 | - BOOST_FOREACH 54 | IncludeCategories: 55 | - Regex: '^"(gnuradio)/' 56 | Priority: 1 57 | - Regex: '^<(gnuradio)/' 58 | Priority: 2 59 | - Regex: '^<(boost)/' 60 | Priority: 98 61 | - Regex: '^<[a-z]*>$' 62 | Priority: 99 63 | - Regex: '^".*"$' 64 | Priority: 0 65 | - Regex: '.*' 66 | Priority: 10 67 | 68 | IncludeIsMainRegex: '(Test)?$' 69 | IndentCaseLabels: false 70 | IndentWidth: 4 71 | IndentWrappedFunctionNames: false 72 | JavaScriptQuotes: Leave 73 | JavaScriptWrapImports: true 74 | KeepEmptyLinesAtTheStartOfBlocks: true 75 | MacroBlockBegin: '' 76 | MacroBlockEnd: '' 77 | MaxEmptyLinesToKeep: 2 78 | NamespaceIndentation: None 79 | ObjCBlockIndentWidth: 2 80 | ObjCSpaceAfterProperty: false 81 | ObjCSpaceBeforeProtocolList: true 82 | PenaltyBreakBeforeFirstCallParameter: 19 83 | PenaltyBreakComment: 300 84 | PenaltyBreakFirstLessLess: 120 85 | PenaltyBreakString: 1000 86 | PenaltyExcessCharacter: 1000000 87 | PenaltyReturnTypeOnItsOwnLine: 60 88 | PointerAlignment: Left 89 | ReflowComments: true 90 | SortIncludes: true 91 | SpaceAfterCStyleCast: false 92 | SpaceAfterTemplateKeyword: true 93 | SpaceBeforeAssignmentOperators: true 94 | SpaceBeforeParens: ControlStatements 95 | SpaceInEmptyParentheses: false 96 | SpacesBeforeTrailingComments: 1 97 | SpacesInAngles: false 98 | SpacesInContainerLiterals: true 99 | SpacesInCStyleCastParentheses: false 100 | SpacesInParentheses: false 101 | SpacesInSquareBrackets: false 102 | Standard: Cpp11 103 | TabWidth: 8 104 | UseTab: Never 105 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: '-*,misc-throw-by-value-catch-by-reference,misc-static-assert,readability-container-size-empty,modernize-use-override' 3 | # Not in here: modernize-use-emplace, since that basically broke all things it touched 4 | WarningsAsErrors: '' 5 | HeaderFilterRegex: '\.(cc|c|cpp|h|hpp)$' 6 | AnalyzeTemporaryDtors: false 7 | FormatStyle: file 8 | CheckOptions: 9 | ... 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build*/ 2 | Makefile 3 | *.o 4 | moc_* 5 | qrc_* 6 | ui_* 7 | examples/*.py 8 | docs/doxygen/doxyxml/__pycache__/ 9 | docs/doxygen/doxyxml/generated/__pycache__/ 10 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011,2012,2014,2016,2018 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-display 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | ######################################################################## 10 | # Project setup 11 | ######################################################################## 12 | cmake_minimum_required(VERSION 3.8) 13 | project(gr-display CXX C) 14 | enable_testing() 15 | 16 | # Install to PyBOMBS target prefix if defined 17 | if(DEFINED ENV{PYBOMBS_PREFIX}) 18 | set(CMAKE_INSTALL_PREFIX $ENV{PYBOMBS_PREFIX}) 19 | message(STATUS "PyBOMBS installed GNU Radio. Setting CMAKE_INSTALL_PREFIX to $ENV{PYBOMBS_PREFIX}") 20 | endif() 21 | 22 | # Select the release build type by default to get optimization flags 23 | if(NOT CMAKE_BUILD_TYPE) 24 | set(CMAKE_BUILD_TYPE "Release") 25 | message(STATUS "Build type not specified: defaulting to release.") 26 | endif(NOT CMAKE_BUILD_TYPE) 27 | set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") 28 | 29 | # Make sure our local CMake Modules path comes first 30 | list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules) 31 | # Set the version information here 32 | set(VERSION_MAJOR 3) 33 | set(VERSION_API 10) 34 | set(VERSION_ABI 0) 35 | set(VERSION_PATCH 0) 36 | 37 | # First find gnuradio to get access to required cmake modules 38 | 39 | find_package(Gnuradio "3.10" REQUIRED runtime blocks fft filter qtgui) 40 | 41 | cmake_policy(SET CMP0011 NEW) 42 | 43 | # Enable generation of compile_commands.json for code completion engines 44 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 45 | 46 | ######################################################################## 47 | # Compiler settings 48 | ######################################################################## 49 | set(GCC_MIN_VERSION "8.3.0") 50 | include(GrCompilerSettings) 51 | ######################################################################## 52 | # Install directories 53 | ######################################################################## 54 | include(GrVersion) 55 | find_package(Qt5Widgets REQUIRED ) 56 | 57 | find_package(PythonLibs 3) 58 | include(GrPython) 59 | GR_PYTHON_CHECK_MODULE("PyQt5" PyQt5 True PYQT5_FOUND) 60 | include(GrPlatform) #define LIB_SUFFIX 61 | 62 | if(NOT CMAKE_MODULES_DIR) 63 | set(CMAKE_MODULES_DIR lib${LIB_SUFFIX}/cmake) 64 | endif(NOT CMAKE_MODULES_DIR) 65 | 66 | set(GR_INCLUDE_DIR include/display) 67 | set(GR_CMAKE_DIR ${CMAKE_MODULES_DIR}/display) 68 | set(GR_PKG_DATA_DIR ${GR_DATA_DIR}/${CMAKE_PROJECT_NAME}) 69 | set(GR_PKG_DOC_DIR ${GR_DOC_DIR}/${CMAKE_PROJECT_NAME}) 70 | set(GR_PKG_CONF_DIR ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d) 71 | set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME}) 72 | 73 | ######################################################################## 74 | # On Apple only, set install name and use rpath correctly, if not already set 75 | ######################################################################## 76 | if(APPLE) 77 | if(NOT CMAKE_INSTALL_NAME_DIR) 78 | set(CMAKE_INSTALL_NAME_DIR 79 | ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE 80 | PATH "Library Install Name Destination Directory" FORCE) 81 | endif(NOT CMAKE_INSTALL_NAME_DIR) 82 | if(NOT CMAKE_INSTALL_RPATH) 83 | set(CMAKE_INSTALL_RPATH 84 | ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE 85 | PATH "Library Install RPath" FORCE) 86 | endif(NOT CMAKE_INSTALL_RPATH) 87 | if(NOT CMAKE_BUILD_WITH_INSTALL_RPATH) 88 | set(CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE 89 | BOOL "Do Build Using Library Install RPath" FORCE) 90 | endif(NOT CMAKE_BUILD_WITH_INSTALL_RPATH) 91 | endif(APPLE) 92 | 93 | ######################################################################## 94 | # Find gnuradio build dependencies 95 | ######################################################################## 96 | find_package(Doxygen) 97 | 98 | ######################################################################## 99 | # PyBind11 Related 100 | ######################################################################## 101 | 102 | find_package(pybind11 REQUIRED) 103 | execute_process( 104 | COMMAND "${PYTHON_EXECUTABLE}" -c 105 | "try:\n import numpy\n import os\n inc_path = numpy.get_include()\n if os.path.exists(os.path.join(inc_path, 'numpy', 'arrayobject.h')):\n print(inc_path, end='')\nexcept:\n pass" 106 | OUTPUT_VARIABLE PYTHON_NUMPY_INCLUDE_DIR) 107 | 108 | include(GrComponent) 109 | GR_REGISTER_COMPONENT("python-support" ENABLE_PYTHON 110 | PYTHONLIBS_FOUND 111 | pybind11_FOUND 112 | ) 113 | if(ENABLE_PYTHON) 114 | add_definitions(-DENABLE_PYTHON) 115 | endif() 116 | ######################################################################## 117 | # Setup doxygen option 118 | ######################################################################## 119 | if(DOXYGEN_FOUND) 120 | option(ENABLE_DOXYGEN "Build docs using Doxygen" ON) 121 | else(DOXYGEN_FOUND) 122 | option(ENABLE_DOXYGEN "Build docs using Doxygen" OFF) 123 | endif(DOXYGEN_FOUND) 124 | 125 | ######################################################################## 126 | # Create uninstall target 127 | ######################################################################## 128 | configure_file( 129 | ${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in 130 | ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 131 | @ONLY) 132 | 133 | add_custom_target(uninstall 134 | ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 135 | ) 136 | 137 | ######################################################################## 138 | # Add subdirectories 139 | ######################################################################## 140 | add_subdirectory(include/display) 141 | add_subdirectory(lib) 142 | add_subdirectory(docs) 143 | if(ENABLE_PYTHON) 144 | add_subdirectory(python) 145 | endif() 146 | add_subdirectory(grc) 147 | 148 | ######################################################################## 149 | # Install cmake search helper for this library 150 | ######################################################################## 151 | 152 | install(FILES cmake/Modules/displayConfig.cmake 153 | DESTINATION ${CMAKE_MODULES_DIR}/display 154 | ) 155 | -------------------------------------------------------------------------------- /MANIFEST.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | title: gr-display 4 | 5 | brief: A small qt based addon for gnuradio 6 | 7 | tags: 8 | 9 | gui, display, png images, ascii, lcd display 10 | 11 | author: - Volker Schroer 12 | 13 | copyright_owner: - Volker Schroer 14 | 15 | dependencies: 16 | 17 | - gnuradio (>= 3.9.0) with pybind 18 | - gr-qtgui 19 | - qt5 20 | 21 | repo: https://github.com/dl1ksv/gr-display.git 22 | 23 | gr-display is a small qt based addon for gnuradio. 24 | 25 | It contains three components: 26 | 27 | show_image - to display png images. 28 | 29 | show_text - to display ascii characters as text in a qt window. 30 | 31 | display_text_msg - display a message containing text 32 | 33 | I use show_image to receive and display some weather- satellite pictures with the funcube dongle 34 | and gnuradio. 35 | 36 | You'll find them in 37 | Custom - Display in grc. 38 | 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## gr-display is a small qt based addon for gnuradio. 3 | 4 | It contains three components: 5 | 6 | + show_image : display png images. 7 | 8 | + show_text : display ascii characters as text in a qt window. 9 | 10 | + display_text_msg : display a message containing text, or a message of type u8vector 11 | 12 | Messages of type u8vector are provided by gr_satellites decoder, for example. 13 | 14 | I use show_image to receive and display some weather- satellite pictures with the funcube dongle 15 | and gnuradio. 16 | 17 | 18 | You'll find them in: 19 | 20 | 21 | Custom 22 | 23 | Display 24 | 25 | 26 | 1. **Dependencies:** 27 | 28 | + gnuradio ( >= 3.10) with pybind11 29 | 30 | + gr-qtgui 31 | 32 | + qt5 33 | 34 | 35 | 2. **Installation** 36 | 37 | Get the latest code from https://github.com/dl1ksv/gr-display 38 | 39 | The build process is cmake based. So change to the code directory. 40 | 41 | There 42 | 43 | $mkdir build 44 | 45 | $cd build 46 | 47 | $cmake -DCMAKE_INSTALL_PREFIX= < where gnuradio is installed > ../ 48 | 49 | $make 50 | 51 | $sudo make install 52 | 53 | After that you'll find in grc in DL1KSV / Display 54 | 55 | - Display a text message 56 | - PNG Image sink 57 | - Text sink. 58 | 59 | 60 | ++++ If you are unsure about where gnuradio is installed run 61 | 62 | gnuradio-config-info --prefix 63 | 64 | 65 | **Hint:** 66 | You can install gr-display to an other directory than gnuradio. But then you have to add 67 | the location of your python modules to the PYTHONPATH environment variable and add the location of 68 | the lib to the LD_LIBRARY_PATH environment variable. 69 | 70 | To see the newly created blocks in grc you have to set the local_blocks_path entry in ~/.gnuradio/config.conf. 71 | Example: If you choose /usr/local/oot as installation directory, you have to set 72 | local_blocks_path = /usr/local/oot/share/gnuradio/grc/blocks 73 | 74 | 75 | 3. **Changes** 76 | 77 | Two additional parameters where introduced: 78 | 79 | - splitlength 80 | If splitlength > 0 , a linebreak is inserted if the linelength exceeds splitlength characters. 81 | - maxlines 82 | Restricts the display height to maxlines rows 83 | 84 | These parameters where introduced to avoid display problems on heavy load and very long lines. 85 | 86 | An autofocus option was added, so you always see new text, if this option is enabled. 87 | 88 | 89 | 90 | 4. **To do** 91 | 92 | Perhaps do some simple image processing like rotating before saving. 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /cmake/Modules/CMakeParseArgumentsCopy.cmake: -------------------------------------------------------------------------------- 1 | # CMAKE_PARSE_ARGUMENTS( args...) 2 | # 3 | # CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions for 4 | # parsing the arguments given to that macro or function. 5 | # It processes the arguments and defines a set of variables which hold the 6 | # values of the respective options. 7 | # 8 | # The argument contains all options for the respective macro, 9 | # i.e. keywords which can be used when calling the macro without any value 10 | # following, like e.g. the OPTIONAL keyword of the install() command. 11 | # 12 | # The argument contains all keywords for this macro 13 | # which are followed by one value, like e.g. DESTINATION keyword of the 14 | # install() command. 15 | # 16 | # The argument contains all keywords for this macro 17 | # which can be followed by more than one value, like e.g. the TARGETS or 18 | # FILES keywords of the install() command. 19 | # 20 | # When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the 21 | # keywords listed in , and 22 | # a variable composed of the given 23 | # followed by "_" and the name of the respective keyword. 24 | # These variables will then hold the respective value from the argument list. 25 | # For the keywords this will be TRUE or FALSE. 26 | # 27 | # All remaining arguments are collected in a variable 28 | # _UNPARSED_ARGUMENTS, this can be checked afterwards to see whether 29 | # your macro was called with unrecognized parameters. 30 | # 31 | # As an example here a my_install() macro, which takes similar arguments as the 32 | # real install() command: 33 | # 34 | # function(MY_INSTALL) 35 | # set(options OPTIONAL FAST) 36 | # set(oneValueArgs DESTINATION RENAME) 37 | # set(multiValueArgs TARGETS CONFIGURATIONS) 38 | # cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) 39 | # ... 40 | # 41 | # Assume my_install() has been called like this: 42 | # my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub) 43 | # 44 | # After the cmake_parse_arguments() call the macro will have set the following 45 | # variables: 46 | # MY_INSTALL_OPTIONAL = TRUE 47 | # MY_INSTALL_FAST = FALSE (this option was not used when calling my_install() 48 | # MY_INSTALL_DESTINATION = "bin" 49 | # MY_INSTALL_RENAME = "" (was not used) 50 | # MY_INSTALL_TARGETS = "foo;bar" 51 | # MY_INSTALL_CONFIGURATIONS = "" (was not used) 52 | # MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL" 53 | # 54 | # You can the continue and process these variables. 55 | # 56 | # Keywords terminate lists of values, e.g. if directly after a one_value_keyword 57 | # another recognized keyword follows, this is interpreted as the beginning of 58 | # the new option. 59 | # E.g. my_install(TARGETS foo DESTINATION OPTIONAL) would result in 60 | # MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION would 61 | # be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefore. 62 | 63 | #============================================================================= 64 | # Copyright 2010 Alexander Neundorf 65 | # 66 | # Distributed under the OSI-approved BSD License (the "License"); 67 | # see accompanying file Copyright.txt for details. 68 | # 69 | # This software is distributed WITHOUT ANY WARRANTY; without even the 70 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 71 | # See the License for more information. 72 | #============================================================================= 73 | # (To distribute this file outside of CMake, substitute the full 74 | # License text for the above reference.) 75 | 76 | 77 | if(__CMAKE_PARSE_ARGUMENTS_INCLUDED) 78 | return() 79 | endif() 80 | set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE) 81 | 82 | 83 | function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames) 84 | # first set all result variables to empty/FALSE 85 | foreach(arg_name ${_singleArgNames} ${_multiArgNames}) 86 | set(${prefix}_${arg_name}) 87 | endforeach(arg_name) 88 | 89 | foreach(option ${_optionNames}) 90 | set(${prefix}_${option} FALSE) 91 | endforeach(option) 92 | 93 | set(${prefix}_UNPARSED_ARGUMENTS) 94 | 95 | set(insideValues FALSE) 96 | set(currentArgName) 97 | 98 | # now iterate over all arguments and fill the result variables 99 | foreach(currentArg ${ARGN}) 100 | list(FIND _optionNames "${currentArg}" optionIndex) # ... then this marks the end of the arguments belonging to this keyword 101 | list(FIND _singleArgNames "${currentArg}" singleArgIndex) # ... then this marks the end of the arguments belonging to this keyword 102 | list(FIND _multiArgNames "${currentArg}" multiArgIndex) # ... then this marks the end of the arguments belonging to this keyword 103 | 104 | if(${optionIndex} EQUAL -1 AND ${singleArgIndex} EQUAL -1 AND ${multiArgIndex} EQUAL -1) 105 | if(insideValues) 106 | if("${insideValues}" STREQUAL "SINGLE") 107 | set(${prefix}_${currentArgName} ${currentArg}) 108 | set(insideValues FALSE) 109 | elseif("${insideValues}" STREQUAL "MULTI") 110 | list(APPEND ${prefix}_${currentArgName} ${currentArg}) 111 | endif() 112 | else(insideValues) 113 | list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg}) 114 | endif(insideValues) 115 | else() 116 | if(NOT ${optionIndex} EQUAL -1) 117 | set(${prefix}_${currentArg} TRUE) 118 | set(insideValues FALSE) 119 | elseif(NOT ${singleArgIndex} EQUAL -1) 120 | set(currentArgName ${currentArg}) 121 | set(${prefix}_${currentArgName}) 122 | set(insideValues "SINGLE") 123 | elseif(NOT ${multiArgIndex} EQUAL -1) 124 | set(currentArgName ${currentArg}) 125 | set(${prefix}_${currentArgName}) 126 | set(insideValues "MULTI") 127 | endif() 128 | endif() 129 | 130 | endforeach(currentArg) 131 | 132 | # propagate the result variables to the caller: 133 | foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames}) 134 | set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE) 135 | endforeach(arg_name) 136 | set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE) 137 | 138 | endfunction(CMAKE_PARSE_ARGUMENTS _options _singleArgs _multiArgs) 139 | -------------------------------------------------------------------------------- /cmake/Modules/displayConfig.cmake: -------------------------------------------------------------------------------- 1 | INCLUDE(FindPkgConfig) 2 | PKG_CHECK_MODULES(PC_DISPLAY display) 3 | 4 | FIND_PATH( 5 | DISPLAY_INCLUDE_DIRS 6 | NAMES display/api.h 7 | HINTS $ENV{DISPLAY_DIR}/include 8 | ${PC_DISPLAY_INCLUDEDIR} 9 | PATHS ${CMAKE_INSTALL_PREFIX}/include 10 | /usr/local/include 11 | /usr/include 12 | ) 13 | 14 | FIND_LIBRARY( 15 | DISPLAY_LIBRARIES 16 | NAMES gnuradio-display 17 | HINTS $ENV{DISPLAY_DIR}/lib 18 | ${PC_DISPLAY_LIBDIR} 19 | PATHS ${CMAKE_INSTALL_PREFIX}/lib 20 | ${CMAKE_INSTALL_PREFIX}/lib64 21 | /usr/local/lib 22 | /usr/local/lib64 23 | /usr/lib 24 | /usr/lib64 25 | ) 26 | 27 | include("${CMAKE_CURRENT_LIST_DIR}/displayTarget.cmake") 28 | 29 | INCLUDE(FindPackageHandleStandardArgs) 30 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(DISPLAY DEFAULT_MSG DISPLAY_LIBRARIES DISPLAY_INCLUDE_DIRS) 31 | MARK_AS_ADVANCED(DISPLAY_LIBRARIES DISPLAY_INCLUDE_DIRS) 32 | -------------------------------------------------------------------------------- /cmake/Modules/targetConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # SPDX-License-Identifier: GPL-3.0-or-later 6 | # 7 | 8 | include(CMakeFindDependencyMacro) 9 | 10 | set(target_deps "@TARGET_DEPENDENCIES@") 11 | foreach(dep IN LISTS target_deps) 12 | find_dependency(${dep}) 13 | endforeach() 14 | include("${CMAKE_CURRENT_LIST_DIR}/@TARGET@Targets.cmake") 15 | -------------------------------------------------------------------------------- /cmake/cmake_uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | # http://www.vtk.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F 2 | 3 | list(APPEND CMAKE_MODULE_PATH "@CMAKE_INSTALL_PREFIX@/lib/cmake/gnuradio") 4 | IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 5 | MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") 6 | ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 7 | 8 | FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) 9 | STRING(REGEX REPLACE "\n" ";" files "${files}") 10 | FOREACH(file ${files}) 11 | MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") 12 | IF(EXISTS "$ENV{DESTDIR}${file}") 13 | EXEC_PROGRAM( 14 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 15 | OUTPUT_VARIABLE rm_out 16 | RETURN_VALUE rm_retval 17 | ) 18 | IF(NOT "${rm_retval}" STREQUAL 0) 19 | MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") 20 | ENDIF(NOT "${rm_retval}" STREQUAL 0) 21 | ELSEIF(IS_SYMLINK "$ENV{DESTDIR}${file}") 22 | EXEC_PROGRAM( 23 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 24 | OUTPUT_VARIABLE rm_out 25 | RETURN_VALUE rm_retval 26 | ) 27 | IF(NOT "${rm_retval}" STREQUAL 0) 28 | MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") 29 | ENDIF(NOT "${rm_retval}" STREQUAL 0) 30 | ELSE(EXISTS "$ENV{DESTDIR}${file}") 31 | MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") 32 | ENDIF(EXISTS "$ENV{DESTDIR}${file}") 33 | ENDFOREACH(file) 34 | -------------------------------------------------------------------------------- /docs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-display 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | ######################################################################## 10 | # Setup dependencies 11 | ######################################################################## 12 | find_package(Doxygen) 13 | 14 | ######################################################################## 15 | # Begin conditional configuration 16 | ######################################################################## 17 | if(ENABLE_DOXYGEN) 18 | 19 | ######################################################################## 20 | # Add subdirectories 21 | ######################################################################## 22 | add_subdirectory(doxygen) 23 | 24 | endif(ENABLE_DOXYGEN) 25 | -------------------------------------------------------------------------------- /docs/README.display: -------------------------------------------------------------------------------- 1 | This is the display-write-a-block package meant as a guide to building 2 | out-of-tree packages. To use the display blocks, the Python namespaces 3 | is in 'display', which is imported as: 4 | 5 | import display 6 | 7 | See the Doxygen documentation for details about the blocks available 8 | in this package. A quick listing of the details can be found in Python 9 | after importing by using: 10 | 11 | help(display) 12 | -------------------------------------------------------------------------------- /docs/doxygen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-display 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | ######################################################################## 10 | # Create the doxygen configuration file 11 | ######################################################################## 12 | file(TO_NATIVE_PATH ${CMAKE_SOURCE_DIR} top_srcdir) 13 | file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR} top_builddir) 14 | file(TO_NATIVE_PATH ${CMAKE_SOURCE_DIR} abs_top_srcdir) 15 | file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR} abs_top_builddir) 16 | 17 | set(HAVE_DOT ${DOXYGEN_DOT_FOUND}) 18 | set(enable_html_docs YES) 19 | set(enable_latex_docs NO) 20 | set(enable_xml_docs YES) 21 | 22 | configure_file( 23 | ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in 24 | ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 25 | @ONLY) 26 | 27 | set(BUILT_DIRS ${CMAKE_CURRENT_BINARY_DIR}/xml ${CMAKE_CURRENT_BINARY_DIR}/html) 28 | 29 | ######################################################################## 30 | # Make and install doxygen docs 31 | ######################################################################## 32 | add_custom_command( 33 | OUTPUT ${BUILT_DIRS} 34 | COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 35 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 36 | COMMENT "Generating documentation with doxygen" 37 | ) 38 | 39 | add_custom_target(doxygen_target ALL DEPENDS ${BUILT_DIRS}) 40 | 41 | install(DIRECTORY ${BUILT_DIRS} DESTINATION ${GR_PKG_DOC_DIR}) 42 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010 Free Software Foundation, Inc. 3 | # 4 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 5 | # This file is a part of gr-display 6 | # 7 | # SPDX-License-Identifier: GPL-3.0-or-later 8 | # 9 | # 10 | """ 11 | Python interface to contents of doxygen xml documentation. 12 | 13 | Example use: 14 | See the contents of the example folder for the C++ and 15 | doxygen-generated xml used in this example. 16 | 17 | >>> # Parse the doxygen docs. 18 | >>> import os 19 | >>> this_dir = os.path.dirname(globals()['__file__']) 20 | >>> xml_path = this_dir + "/example/xml/" 21 | >>> di = DoxyIndex(xml_path) 22 | 23 | Get a list of all top-level objects. 24 | 25 | >>> print([mem.name() for mem in di.members()]) 26 | [u'Aadvark', u'aadvarky_enough', u'main'] 27 | 28 | Get all functions. 29 | 30 | >>> print([mem.name() for mem in di.in_category(DoxyFunction)]) 31 | [u'aadvarky_enough', u'main'] 32 | 33 | Check if an object is present. 34 | 35 | >>> di.has_member(u'Aadvark') 36 | True 37 | >>> di.has_member(u'Fish') 38 | False 39 | 40 | Get an item by name and check its properties. 41 | 42 | >>> aad = di.get_member(u'Aadvark') 43 | >>> print(aad.brief_description) 44 | Models the mammal Aadvark. 45 | >>> print(aad.detailed_description) 46 | Sadly the model is incomplete and cannot capture all aspects of an aadvark yet. 47 | 48 | This line is uninformative and is only to test line breaks in the comments. 49 | >>> [mem.name() for mem in aad.members()] 50 | [u'aadvarkness', u'print', u'Aadvark', u'get_aadvarkness'] 51 | >>> aad.get_member(u'print').brief_description 52 | u'Outputs the vital aadvark statistics.' 53 | 54 | """ 55 | from __future__ import unicode_literals 56 | 57 | from .doxyindex import DoxyIndex, DoxyFunction, DoxyParam, DoxyClass, DoxyFile, DoxyNamespace, DoxyGroup, DoxyFriend, DoxyOther 58 | 59 | def _test(): 60 | import os 61 | this_dir = os.path.dirname(globals()['__file__']) 62 | xml_path = this_dir + "/example/xml/" 63 | di = DoxyIndex(xml_path) 64 | # Get the Aadvark class 65 | aad = di.get_member('Aadvark') 66 | aad.brief_description 67 | import doctest 68 | return doctest.testmod() 69 | 70 | if __name__ == "__main__": 71 | _test() 72 | 73 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/base.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010 Free Software Foundation, Inc. 3 | # 4 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 5 | # This file is a part of gr-display 6 | # 7 | # SPDX-License-Identifier: GPL-3.0-or-later 8 | # 9 | # 10 | """ 11 | A base class is created. 12 | 13 | Classes based upon this are used to make more user-friendly interfaces 14 | to the doxygen xml docs than the generated classes provide. 15 | """ 16 | from __future__ import print_function 17 | from __future__ import unicode_literals 18 | 19 | import os 20 | import pdb 21 | 22 | from xml.parsers.expat import ExpatError 23 | 24 | from .generated import compound 25 | 26 | 27 | class Base(object): 28 | 29 | class Duplicate(Exception): 30 | pass 31 | 32 | class NoSuchMember(Exception): 33 | pass 34 | 35 | class ParsingError(Exception): 36 | pass 37 | 38 | def __init__(self, parse_data, top=None): 39 | self._parsed = False 40 | self._error = False 41 | self._parse_data = parse_data 42 | self._members = [] 43 | self._dict_members = {} 44 | self._in_category = {} 45 | self._data = {} 46 | if top is not None: 47 | self._xml_path = top._xml_path 48 | # Set up holder of references 49 | else: 50 | top = self 51 | self._refs = {} 52 | self._xml_path = parse_data 53 | self.top = top 54 | 55 | @classmethod 56 | def from_refid(cls, refid, top=None): 57 | """ Instantiate class from a refid rather than parsing object. """ 58 | # First check to see if its already been instantiated. 59 | if top is not None and refid in top._refs: 60 | return top._refs[refid] 61 | # Otherwise create a new instance and set refid. 62 | inst = cls(None, top=top) 63 | inst.refid = refid 64 | inst.add_ref(inst) 65 | return inst 66 | 67 | @classmethod 68 | def from_parse_data(cls, parse_data, top=None): 69 | refid = getattr(parse_data, 'refid', None) 70 | if refid is not None and top is not None and refid in top._refs: 71 | return top._refs[refid] 72 | inst = cls(parse_data, top=top) 73 | if refid is not None: 74 | inst.refid = refid 75 | inst.add_ref(inst) 76 | return inst 77 | 78 | def add_ref(self, obj): 79 | if hasattr(obj, 'refid'): 80 | self.top._refs[obj.refid] = obj 81 | 82 | mem_classes = [] 83 | 84 | def get_cls(self, mem): 85 | for cls in self.mem_classes: 86 | if cls.can_parse(mem): 87 | return cls 88 | raise Exception(("Did not find a class for object '%s'." \ 89 | % (mem.get_name()))) 90 | 91 | def convert_mem(self, mem): 92 | try: 93 | cls = self.get_cls(mem) 94 | converted = cls.from_parse_data(mem, self.top) 95 | if converted is None: 96 | raise Exception('No class matched this object.') 97 | self.add_ref(converted) 98 | return converted 99 | except Exception as e: 100 | print(e) 101 | 102 | @classmethod 103 | def includes(cls, inst): 104 | return isinstance(inst, cls) 105 | 106 | @classmethod 107 | def can_parse(cls, obj): 108 | return False 109 | 110 | def _parse(self): 111 | self._parsed = True 112 | 113 | def _get_dict_members(self, cat=None): 114 | """ 115 | For given category a dictionary is returned mapping member names to 116 | members of that category. For names that are duplicated the name is 117 | mapped to None. 118 | """ 119 | self.confirm_no_error() 120 | if cat not in self._dict_members: 121 | new_dict = {} 122 | for mem in self.in_category(cat): 123 | if mem.name() not in new_dict: 124 | new_dict[mem.name()] = mem 125 | else: 126 | new_dict[mem.name()] = self.Duplicate 127 | self._dict_members[cat] = new_dict 128 | return self._dict_members[cat] 129 | 130 | def in_category(self, cat): 131 | self.confirm_no_error() 132 | if cat is None: 133 | return self._members 134 | if cat not in self._in_category: 135 | self._in_category[cat] = [mem for mem in self._members 136 | if cat.includes(mem)] 137 | return self._in_category[cat] 138 | 139 | def get_member(self, name, cat=None): 140 | self.confirm_no_error() 141 | # Check if it's in a namespace or class. 142 | bits = name.split('::') 143 | first = bits[0] 144 | rest = '::'.join(bits[1:]) 145 | member = self._get_dict_members(cat).get(first, self.NoSuchMember) 146 | # Raise any errors that are returned. 147 | if member in set([self.NoSuchMember, self.Duplicate]): 148 | raise member() 149 | if rest: 150 | return member.get_member(rest, cat=cat) 151 | return member 152 | 153 | def has_member(self, name, cat=None): 154 | try: 155 | mem = self.get_member(name, cat=cat) 156 | return True 157 | except self.NoSuchMember: 158 | return False 159 | 160 | def data(self): 161 | self.confirm_no_error() 162 | return self._data 163 | 164 | def members(self): 165 | self.confirm_no_error() 166 | return self._members 167 | 168 | def process_memberdefs(self): 169 | mdtss = [] 170 | for sec in self._retrieved_data.compounddef.sectiondef: 171 | mdtss += sec.memberdef 172 | # At the moment we lose all information associated with sections. 173 | # Sometimes a memberdef is in several sectiondef. 174 | # We make sure we don't get duplicates here. 175 | uniques = set([]) 176 | for mem in mdtss: 177 | converted = self.convert_mem(mem) 178 | pair = (mem.name, mem.__class__) 179 | if pair not in uniques: 180 | uniques.add(pair) 181 | self._members.append(converted) 182 | 183 | def retrieve_data(self): 184 | filename = os.path.join(self._xml_path, self.refid + '.xml') 185 | try: 186 | self._retrieved_data = compound.parse(filename) 187 | except ExpatError: 188 | print('Error in xml in file %s' % filename) 189 | self._error = True 190 | self._retrieved_data = None 191 | 192 | def check_parsed(self): 193 | if not self._parsed: 194 | self._parse() 195 | 196 | def confirm_no_error(self): 197 | self.check_parsed() 198 | if self._error: 199 | raise self.ParsingError() 200 | 201 | def error(self): 202 | self.check_parsed() 203 | return self._error 204 | 205 | def name(self): 206 | # first see if we can do it without processing. 207 | if self._parse_data is not None: 208 | return self._parse_data.name 209 | self.check_parsed() 210 | return self._retrieved_data.compounddef.name 211 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/doxyindex.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010 Free Software Foundation, Inc. 3 | # 4 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 5 | # This file is a part of gr-display 6 | # 7 | # SPDX-License-Identifier: GPL-3.0-or-later 8 | # 9 | # 10 | """ 11 | Classes providing more user-friendly interfaces to the doxygen xml 12 | docs than the generated classes provide. 13 | """ 14 | from __future__ import absolute_import 15 | from __future__ import unicode_literals 16 | 17 | import os 18 | 19 | from .generated import index 20 | from .base import Base 21 | from .text import description 22 | 23 | class DoxyIndex(Base): 24 | """ 25 | Parses a doxygen xml directory. 26 | """ 27 | 28 | __module__ = "gnuradio.utils.doxyxml" 29 | 30 | def _parse(self): 31 | if self._parsed: 32 | return 33 | super(DoxyIndex, self)._parse() 34 | self._root = index.parse(os.path.join(self._xml_path, 'index.xml')) 35 | for mem in self._root.compound: 36 | converted = self.convert_mem(mem) 37 | # For files and namespaces we want the contents to be 38 | # accessible directly from the parent rather than having 39 | # to go through the file object. 40 | if self.get_cls(mem) == DoxyFile: 41 | if mem.name.endswith('.h'): 42 | self._members += converted.members() 43 | self._members.append(converted) 44 | elif self.get_cls(mem) == DoxyNamespace: 45 | self._members += converted.members() 46 | self._members.append(converted) 47 | else: 48 | self._members.append(converted) 49 | 50 | 51 | def generate_swig_doc_i(self): 52 | """ 53 | %feature("docstring") gr_make_align_on_samplenumbers_ss::align_state " 54 | Wraps the C++: gr_align_on_samplenumbers_ss::align_state"; 55 | """ 56 | pass 57 | 58 | 59 | class DoxyCompMem(Base): 60 | 61 | 62 | kind = None 63 | 64 | def __init__(self, *args, **kwargs): 65 | super(DoxyCompMem, self).__init__(*args, **kwargs) 66 | 67 | @classmethod 68 | def can_parse(cls, obj): 69 | return obj.kind == cls.kind 70 | 71 | def set_descriptions(self, parse_data): 72 | bd = description(getattr(parse_data, 'briefdescription', None)) 73 | dd = description(getattr(parse_data, 'detaileddescription', None)) 74 | self._data['brief_description'] = bd 75 | self._data['detailed_description'] = dd 76 | 77 | def set_parameters(self, data): 78 | vs = [ddc.value for ddc in data.detaileddescription.content_] 79 | pls = [] 80 | for v in vs: 81 | if hasattr(v, 'parameterlist'): 82 | pls += v.parameterlist 83 | pis = [] 84 | for pl in pls: 85 | pis += pl.parameteritem 86 | dpis = [] 87 | for pi in pis: 88 | dpi = DoxyParameterItem(pi) 89 | dpi._parse() 90 | dpis.append(dpi) 91 | self._data['params'] = dpis 92 | 93 | 94 | class DoxyCompound(DoxyCompMem): 95 | pass 96 | 97 | class DoxyMember(DoxyCompMem): 98 | pass 99 | 100 | class DoxyFunction(DoxyMember): 101 | 102 | __module__ = "gnuradio.utils.doxyxml" 103 | 104 | kind = 'function' 105 | 106 | def _parse(self): 107 | if self._parsed: 108 | return 109 | super(DoxyFunction, self)._parse() 110 | self.set_descriptions(self._parse_data) 111 | self.set_parameters(self._parse_data) 112 | if not self._data['params']: 113 | # If the params weren't set by a comment then just grab the names. 114 | self._data['params'] = [] 115 | prms = self._parse_data.param 116 | for prm in prms: 117 | self._data['params'].append(DoxyParam(prm)) 118 | 119 | brief_description = property(lambda self: self.data()['brief_description']) 120 | detailed_description = property(lambda self: self.data()['detailed_description']) 121 | params = property(lambda self: self.data()['params']) 122 | 123 | Base.mem_classes.append(DoxyFunction) 124 | 125 | 126 | class DoxyParam(DoxyMember): 127 | 128 | __module__ = "gnuradio.utils.doxyxml" 129 | 130 | def _parse(self): 131 | if self._parsed: 132 | return 133 | super(DoxyParam, self)._parse() 134 | self.set_descriptions(self._parse_data) 135 | self._data['declname'] = self._parse_data.declname 136 | 137 | @property 138 | def description(self): 139 | descriptions = [] 140 | if self.brief_description: 141 | descriptions.append(self.brief_description) 142 | if self.detailed_description: 143 | descriptions.append(self.detailed_description) 144 | return '\n\n'.join(descriptions) 145 | 146 | brief_description = property(lambda self: self.data()['brief_description']) 147 | detailed_description = property(lambda self: self.data()['detailed_description']) 148 | name = property(lambda self: self.data()['declname']) 149 | 150 | class DoxyParameterItem(DoxyMember): 151 | """A different representation of a parameter in Doxygen.""" 152 | 153 | def _parse(self): 154 | if self._parsed: 155 | return 156 | super(DoxyParameterItem, self)._parse() 157 | names = [] 158 | for nl in self._parse_data.parameternamelist: 159 | for pn in nl.parametername: 160 | names.append(description(pn)) 161 | # Just take first name 162 | self._data['name'] = names[0] 163 | # Get description 164 | pd = description(self._parse_data.get_parameterdescription()) 165 | self._data['description'] = pd 166 | 167 | description = property(lambda self: self.data()['description']) 168 | name = property(lambda self: self.data()['name']) 169 | 170 | 171 | class DoxyClass(DoxyCompound): 172 | 173 | __module__ = "gnuradio.utils.doxyxml" 174 | 175 | kind = 'class' 176 | 177 | def _parse(self): 178 | if self._parsed: 179 | return 180 | super(DoxyClass, self)._parse() 181 | self.retrieve_data() 182 | if self._error: 183 | return 184 | self.set_descriptions(self._retrieved_data.compounddef) 185 | self.set_parameters(self._retrieved_data.compounddef) 186 | # Sectiondef.kind tells about whether private or public. 187 | # We just ignore this for now. 188 | self.process_memberdefs() 189 | 190 | brief_description = property(lambda self: self.data()['brief_description']) 191 | detailed_description = property(lambda self: self.data()['detailed_description']) 192 | params = property(lambda self: self.data()['params']) 193 | 194 | Base.mem_classes.append(DoxyClass) 195 | 196 | 197 | class DoxyFile(DoxyCompound): 198 | 199 | __module__ = "gnuradio.utils.doxyxml" 200 | 201 | kind = 'file' 202 | 203 | def _parse(self): 204 | if self._parsed: 205 | return 206 | super(DoxyFile, self)._parse() 207 | self.retrieve_data() 208 | self.set_descriptions(self._retrieved_data.compounddef) 209 | if self._error: 210 | return 211 | self.process_memberdefs() 212 | 213 | brief_description = property(lambda self: self.data()['brief_description']) 214 | detailed_description = property(lambda self: self.data()['detailed_description']) 215 | 216 | Base.mem_classes.append(DoxyFile) 217 | 218 | 219 | class DoxyNamespace(DoxyCompound): 220 | 221 | __module__ = "gnuradio.utils.doxyxml" 222 | 223 | kind = 'namespace' 224 | 225 | def _parse(self): 226 | if self._parsed: 227 | return 228 | super(DoxyNamespace, self)._parse() 229 | self.retrieve_data() 230 | self.set_descriptions(self._retrieved_data.compounddef) 231 | if self._error: 232 | return 233 | self.process_memberdefs() 234 | 235 | Base.mem_classes.append(DoxyNamespace) 236 | 237 | 238 | class DoxyGroup(DoxyCompound): 239 | 240 | __module__ = "gnuradio.utils.doxyxml" 241 | 242 | kind = 'group' 243 | 244 | def _parse(self): 245 | if self._parsed: 246 | return 247 | super(DoxyGroup, self)._parse() 248 | self.retrieve_data() 249 | if self._error: 250 | return 251 | cdef = self._retrieved_data.compounddef 252 | self._data['title'] = description(cdef.title) 253 | # Process inner groups 254 | grps = cdef.innergroup 255 | for grp in grps: 256 | converted = DoxyGroup.from_refid(grp.refid, top=self.top) 257 | self._members.append(converted) 258 | # Process inner classes 259 | klasses = cdef.innerclass 260 | for kls in klasses: 261 | converted = DoxyClass.from_refid(kls.refid, top=self.top) 262 | self._members.append(converted) 263 | # Process normal members 264 | self.process_memberdefs() 265 | 266 | title = property(lambda self: self.data()['title']) 267 | 268 | 269 | Base.mem_classes.append(DoxyGroup) 270 | 271 | 272 | class DoxyFriend(DoxyMember): 273 | 274 | __module__ = "gnuradio.utils.doxyxml" 275 | 276 | kind = 'friend' 277 | 278 | Base.mem_classes.append(DoxyFriend) 279 | 280 | 281 | class DoxyOther(Base): 282 | 283 | __module__ = "gnuradio.utils.doxyxml" 284 | 285 | kinds = set(['variable', 'struct', 'union', 'define', 'typedef', 'enum', 286 | 'dir', 'page', 'signal', 'slot', 'property']) 287 | 288 | @classmethod 289 | def can_parse(cls, obj): 290 | return obj.kind in cls.kinds 291 | 292 | Base.mem_classes.append(DoxyOther) 293 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/generated/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Contains generated files produced by generateDS.py. 3 | 4 | These do the real work of parsing the doxygen xml files but the 5 | resultant classes are not very friendly to navigate so the rest of the 6 | doxyxml module processes them further. 7 | """ 8 | from __future__ import unicode_literals 9 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/generated/compound.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Generated Mon Feb 9 19:08:05 2009 by generateDS.py. 5 | """ 6 | from __future__ import absolute_import 7 | from __future__ import unicode_literals 8 | 9 | 10 | from xml.dom import minidom 11 | from xml.dom import Node 12 | 13 | import sys 14 | 15 | from . import compoundsuper as supermod 16 | from .compoundsuper import MixedContainer 17 | 18 | 19 | class DoxygenTypeSub(supermod.DoxygenType): 20 | def __init__(self, version=None, compounddef=None): 21 | supermod.DoxygenType.__init__(self, version, compounddef) 22 | 23 | def find(self, details): 24 | 25 | return self.compounddef.find(details) 26 | 27 | supermod.DoxygenType.subclass = DoxygenTypeSub 28 | # end class DoxygenTypeSub 29 | 30 | 31 | class compounddefTypeSub(supermod.compounddefType): 32 | def __init__(self, kind=None, prot=None, id=None, compoundname='', title='', basecompoundref=None, derivedcompoundref=None, includes=None, includedby=None, incdepgraph=None, invincdepgraph=None, innerdir=None, innerfile=None, innerclass=None, innernamespace=None, innerpage=None, innergroup=None, templateparamlist=None, sectiondef=None, briefdescription=None, detaileddescription=None, inheritancegraph=None, collaborationgraph=None, programlisting=None, location=None, listofallmembers=None): 33 | supermod.compounddefType.__init__(self, kind, prot, id, compoundname, title, basecompoundref, derivedcompoundref, includes, includedby, incdepgraph, invincdepgraph, innerdir, innerfile, innerclass, innernamespace, innerpage, innergroup, templateparamlist, sectiondef, briefdescription, detaileddescription, inheritancegraph, collaborationgraph, programlisting, location, listofallmembers) 34 | 35 | def find(self, details): 36 | 37 | if self.id == details.refid: 38 | return self 39 | 40 | for sectiondef in self.sectiondef: 41 | result = sectiondef.find(details) 42 | if result: 43 | return result 44 | 45 | 46 | supermod.compounddefType.subclass = compounddefTypeSub 47 | # end class compounddefTypeSub 48 | 49 | 50 | class listofallmembersTypeSub(supermod.listofallmembersType): 51 | def __init__(self, member=None): 52 | supermod.listofallmembersType.__init__(self, member) 53 | supermod.listofallmembersType.subclass = listofallmembersTypeSub 54 | # end class listofallmembersTypeSub 55 | 56 | 57 | class memberRefTypeSub(supermod.memberRefType): 58 | def __init__(self, virt=None, prot=None, refid=None, ambiguityscope=None, scope='', name=''): 59 | supermod.memberRefType.__init__(self, virt, prot, refid, ambiguityscope, scope, name) 60 | supermod.memberRefType.subclass = memberRefTypeSub 61 | # end class memberRefTypeSub 62 | 63 | 64 | class compoundRefTypeSub(supermod.compoundRefType): 65 | def __init__(self, virt=None, prot=None, refid=None, valueOf_='', mixedclass_=None, content_=None): 66 | supermod.compoundRefType.__init__(self, mixedclass_, content_) 67 | supermod.compoundRefType.subclass = compoundRefTypeSub 68 | # end class compoundRefTypeSub 69 | 70 | 71 | class reimplementTypeSub(supermod.reimplementType): 72 | def __init__(self, refid=None, valueOf_='', mixedclass_=None, content_=None): 73 | supermod.reimplementType.__init__(self, mixedclass_, content_) 74 | supermod.reimplementType.subclass = reimplementTypeSub 75 | # end class reimplementTypeSub 76 | 77 | 78 | class incTypeSub(supermod.incType): 79 | def __init__(self, local=None, refid=None, valueOf_='', mixedclass_=None, content_=None): 80 | supermod.incType.__init__(self, mixedclass_, content_) 81 | supermod.incType.subclass = incTypeSub 82 | # end class incTypeSub 83 | 84 | 85 | class refTypeSub(supermod.refType): 86 | def __init__(self, prot=None, refid=None, valueOf_='', mixedclass_=None, content_=None): 87 | supermod.refType.__init__(self, mixedclass_, content_) 88 | supermod.refType.subclass = refTypeSub 89 | # end class refTypeSub 90 | 91 | 92 | 93 | class refTextTypeSub(supermod.refTextType): 94 | def __init__(self, refid=None, kindref=None, external=None, valueOf_='', mixedclass_=None, content_=None): 95 | supermod.refTextType.__init__(self, mixedclass_, content_) 96 | 97 | supermod.refTextType.subclass = refTextTypeSub 98 | # end class refTextTypeSub 99 | 100 | class sectiondefTypeSub(supermod.sectiondefType): 101 | 102 | 103 | def __init__(self, kind=None, header='', description=None, memberdef=None): 104 | supermod.sectiondefType.__init__(self, kind, header, description, memberdef) 105 | 106 | def find(self, details): 107 | 108 | for memberdef in self.memberdef: 109 | if memberdef.id == details.refid: 110 | return memberdef 111 | 112 | return None 113 | 114 | 115 | supermod.sectiondefType.subclass = sectiondefTypeSub 116 | # end class sectiondefTypeSub 117 | 118 | 119 | class memberdefTypeSub(supermod.memberdefType): 120 | def __init__(self, initonly=None, kind=None, volatile=None, const=None, raise_=None, virt=None, readable=None, prot=None, explicit=None, new=None, final=None, writable=None, add=None, static=None, remove=None, sealed=None, mutable=None, gettable=None, inline=None, settable=None, id=None, templateparamlist=None, type_=None, definition='', argsstring='', name='', read='', write='', bitfield='', reimplements=None, reimplementedby=None, param=None, enumvalue=None, initializer=None, exceptions=None, briefdescription=None, detaileddescription=None, inbodydescription=None, location=None, references=None, referencedby=None): 121 | supermod.memberdefType.__init__(self, initonly, kind, volatile, const, raise_, virt, readable, prot, explicit, new, final, writable, add, static, remove, sealed, mutable, gettable, inline, settable, id, templateparamlist, type_, definition, argsstring, name, read, write, bitfield, reimplements, reimplementedby, param, enumvalue, initializer, exceptions, briefdescription, detaileddescription, inbodydescription, location, references, referencedby) 122 | supermod.memberdefType.subclass = memberdefTypeSub 123 | # end class memberdefTypeSub 124 | 125 | 126 | class descriptionTypeSub(supermod.descriptionType): 127 | def __init__(self, title='', para=None, sect1=None, internal=None, mixedclass_=None, content_=None): 128 | supermod.descriptionType.__init__(self, mixedclass_, content_) 129 | supermod.descriptionType.subclass = descriptionTypeSub 130 | # end class descriptionTypeSub 131 | 132 | 133 | class enumvalueTypeSub(supermod.enumvalueType): 134 | def __init__(self, prot=None, id=None, name='', initializer=None, briefdescription=None, detaileddescription=None, mixedclass_=None, content_=None): 135 | supermod.enumvalueType.__init__(self, mixedclass_, content_) 136 | supermod.enumvalueType.subclass = enumvalueTypeSub 137 | # end class enumvalueTypeSub 138 | 139 | 140 | class templateparamlistTypeSub(supermod.templateparamlistType): 141 | def __init__(self, param=None): 142 | supermod.templateparamlistType.__init__(self, param) 143 | supermod.templateparamlistType.subclass = templateparamlistTypeSub 144 | # end class templateparamlistTypeSub 145 | 146 | 147 | class paramTypeSub(supermod.paramType): 148 | def __init__(self, type_=None, declname='', defname='', array='', defval=None, briefdescription=None): 149 | supermod.paramType.__init__(self, type_, declname, defname, array, defval, briefdescription) 150 | supermod.paramType.subclass = paramTypeSub 151 | # end class paramTypeSub 152 | 153 | 154 | class linkedTextTypeSub(supermod.linkedTextType): 155 | def __init__(self, ref=None, mixedclass_=None, content_=None): 156 | supermod.linkedTextType.__init__(self, mixedclass_, content_) 157 | supermod.linkedTextType.subclass = linkedTextTypeSub 158 | # end class linkedTextTypeSub 159 | 160 | 161 | class graphTypeSub(supermod.graphType): 162 | def __init__(self, node=None): 163 | supermod.graphType.__init__(self, node) 164 | supermod.graphType.subclass = graphTypeSub 165 | # end class graphTypeSub 166 | 167 | 168 | class nodeTypeSub(supermod.nodeType): 169 | def __init__(self, id=None, label='', link=None, childnode=None): 170 | supermod.nodeType.__init__(self, id, label, link, childnode) 171 | supermod.nodeType.subclass = nodeTypeSub 172 | # end class nodeTypeSub 173 | 174 | 175 | class childnodeTypeSub(supermod.childnodeType): 176 | def __init__(self, relation=None, refid=None, edgelabel=None): 177 | supermod.childnodeType.__init__(self, relation, refid, edgelabel) 178 | supermod.childnodeType.subclass = childnodeTypeSub 179 | # end class childnodeTypeSub 180 | 181 | 182 | class linkTypeSub(supermod.linkType): 183 | def __init__(self, refid=None, external=None, valueOf_=''): 184 | supermod.linkType.__init__(self, refid, external) 185 | supermod.linkType.subclass = linkTypeSub 186 | # end class linkTypeSub 187 | 188 | 189 | class listingTypeSub(supermod.listingType): 190 | def __init__(self, codeline=None): 191 | supermod.listingType.__init__(self, codeline) 192 | supermod.listingType.subclass = listingTypeSub 193 | # end class listingTypeSub 194 | 195 | 196 | class codelineTypeSub(supermod.codelineType): 197 | def __init__(self, external=None, lineno=None, refkind=None, refid=None, highlight=None): 198 | supermod.codelineType.__init__(self, external, lineno, refkind, refid, highlight) 199 | supermod.codelineType.subclass = codelineTypeSub 200 | # end class codelineTypeSub 201 | 202 | 203 | class highlightTypeSub(supermod.highlightType): 204 | def __init__(self, class_=None, sp=None, ref=None, mixedclass_=None, content_=None): 205 | supermod.highlightType.__init__(self, mixedclass_, content_) 206 | supermod.highlightType.subclass = highlightTypeSub 207 | # end class highlightTypeSub 208 | 209 | 210 | class referenceTypeSub(supermod.referenceType): 211 | def __init__(self, endline=None, startline=None, refid=None, compoundref=None, valueOf_='', mixedclass_=None, content_=None): 212 | supermod.referenceType.__init__(self, mixedclass_, content_) 213 | supermod.referenceType.subclass = referenceTypeSub 214 | # end class referenceTypeSub 215 | 216 | 217 | class locationTypeSub(supermod.locationType): 218 | def __init__(self, bodystart=None, line=None, bodyend=None, bodyfile=None, file=None, valueOf_=''): 219 | supermod.locationType.__init__(self, bodystart, line, bodyend, bodyfile, file) 220 | supermod.locationType.subclass = locationTypeSub 221 | # end class locationTypeSub 222 | 223 | 224 | class docSect1TypeSub(supermod.docSect1Type): 225 | def __init__(self, id=None, title='', para=None, sect2=None, internal=None, mixedclass_=None, content_=None): 226 | supermod.docSect1Type.__init__(self, mixedclass_, content_) 227 | supermod.docSect1Type.subclass = docSect1TypeSub 228 | # end class docSect1TypeSub 229 | 230 | 231 | class docSect2TypeSub(supermod.docSect2Type): 232 | def __init__(self, id=None, title='', para=None, sect3=None, internal=None, mixedclass_=None, content_=None): 233 | supermod.docSect2Type.__init__(self, mixedclass_, content_) 234 | supermod.docSect2Type.subclass = docSect2TypeSub 235 | # end class docSect2TypeSub 236 | 237 | 238 | class docSect3TypeSub(supermod.docSect3Type): 239 | def __init__(self, id=None, title='', para=None, sect4=None, internal=None, mixedclass_=None, content_=None): 240 | supermod.docSect3Type.__init__(self, mixedclass_, content_) 241 | supermod.docSect3Type.subclass = docSect3TypeSub 242 | # end class docSect3TypeSub 243 | 244 | 245 | class docSect4TypeSub(supermod.docSect4Type): 246 | def __init__(self, id=None, title='', para=None, internal=None, mixedclass_=None, content_=None): 247 | supermod.docSect4Type.__init__(self, mixedclass_, content_) 248 | supermod.docSect4Type.subclass = docSect4TypeSub 249 | # end class docSect4TypeSub 250 | 251 | 252 | class docInternalTypeSub(supermod.docInternalType): 253 | def __init__(self, para=None, sect1=None, mixedclass_=None, content_=None): 254 | supermod.docInternalType.__init__(self, mixedclass_, content_) 255 | supermod.docInternalType.subclass = docInternalTypeSub 256 | # end class docInternalTypeSub 257 | 258 | 259 | class docInternalS1TypeSub(supermod.docInternalS1Type): 260 | def __init__(self, para=None, sect2=None, mixedclass_=None, content_=None): 261 | supermod.docInternalS1Type.__init__(self, mixedclass_, content_) 262 | supermod.docInternalS1Type.subclass = docInternalS1TypeSub 263 | # end class docInternalS1TypeSub 264 | 265 | 266 | class docInternalS2TypeSub(supermod.docInternalS2Type): 267 | def __init__(self, para=None, sect3=None, mixedclass_=None, content_=None): 268 | supermod.docInternalS2Type.__init__(self, mixedclass_, content_) 269 | supermod.docInternalS2Type.subclass = docInternalS2TypeSub 270 | # end class docInternalS2TypeSub 271 | 272 | 273 | class docInternalS3TypeSub(supermod.docInternalS3Type): 274 | def __init__(self, para=None, sect3=None, mixedclass_=None, content_=None): 275 | supermod.docInternalS3Type.__init__(self, mixedclass_, content_) 276 | supermod.docInternalS3Type.subclass = docInternalS3TypeSub 277 | # end class docInternalS3TypeSub 278 | 279 | 280 | class docInternalS4TypeSub(supermod.docInternalS4Type): 281 | def __init__(self, para=None, mixedclass_=None, content_=None): 282 | supermod.docInternalS4Type.__init__(self, mixedclass_, content_) 283 | supermod.docInternalS4Type.subclass = docInternalS4TypeSub 284 | # end class docInternalS4TypeSub 285 | 286 | 287 | class docURLLinkSub(supermod.docURLLink): 288 | def __init__(self, url=None, valueOf_='', mixedclass_=None, content_=None): 289 | supermod.docURLLink.__init__(self, mixedclass_, content_) 290 | supermod.docURLLink.subclass = docURLLinkSub 291 | # end class docURLLinkSub 292 | 293 | 294 | class docAnchorTypeSub(supermod.docAnchorType): 295 | def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): 296 | supermod.docAnchorType.__init__(self, mixedclass_, content_) 297 | supermod.docAnchorType.subclass = docAnchorTypeSub 298 | # end class docAnchorTypeSub 299 | 300 | 301 | class docFormulaTypeSub(supermod.docFormulaType): 302 | def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): 303 | supermod.docFormulaType.__init__(self, mixedclass_, content_) 304 | supermod.docFormulaType.subclass = docFormulaTypeSub 305 | # end class docFormulaTypeSub 306 | 307 | 308 | class docIndexEntryTypeSub(supermod.docIndexEntryType): 309 | def __init__(self, primaryie='', secondaryie=''): 310 | supermod.docIndexEntryType.__init__(self, primaryie, secondaryie) 311 | supermod.docIndexEntryType.subclass = docIndexEntryTypeSub 312 | # end class docIndexEntryTypeSub 313 | 314 | 315 | class docListTypeSub(supermod.docListType): 316 | def __init__(self, listitem=None): 317 | supermod.docListType.__init__(self, listitem) 318 | supermod.docListType.subclass = docListTypeSub 319 | # end class docListTypeSub 320 | 321 | 322 | class docListItemTypeSub(supermod.docListItemType): 323 | def __init__(self, para=None): 324 | supermod.docListItemType.__init__(self, para) 325 | supermod.docListItemType.subclass = docListItemTypeSub 326 | # end class docListItemTypeSub 327 | 328 | 329 | class docSimpleSectTypeSub(supermod.docSimpleSectType): 330 | def __init__(self, kind=None, title=None, para=None): 331 | supermod.docSimpleSectType.__init__(self, kind, title, para) 332 | supermod.docSimpleSectType.subclass = docSimpleSectTypeSub 333 | # end class docSimpleSectTypeSub 334 | 335 | 336 | class docVarListEntryTypeSub(supermod.docVarListEntryType): 337 | def __init__(self, term=None): 338 | supermod.docVarListEntryType.__init__(self, term) 339 | supermod.docVarListEntryType.subclass = docVarListEntryTypeSub 340 | # end class docVarListEntryTypeSub 341 | 342 | 343 | class docRefTextTypeSub(supermod.docRefTextType): 344 | def __init__(self, refid=None, kindref=None, external=None, valueOf_='', mixedclass_=None, content_=None): 345 | supermod.docRefTextType.__init__(self, mixedclass_, content_) 346 | supermod.docRefTextType.subclass = docRefTextTypeSub 347 | # end class docRefTextTypeSub 348 | 349 | 350 | class docTableTypeSub(supermod.docTableType): 351 | def __init__(self, rows=None, cols=None, row=None, caption=None): 352 | supermod.docTableType.__init__(self, rows, cols, row, caption) 353 | supermod.docTableType.subclass = docTableTypeSub 354 | # end class docTableTypeSub 355 | 356 | 357 | class docRowTypeSub(supermod.docRowType): 358 | def __init__(self, entry=None): 359 | supermod.docRowType.__init__(self, entry) 360 | supermod.docRowType.subclass = docRowTypeSub 361 | # end class docRowTypeSub 362 | 363 | 364 | class docEntryTypeSub(supermod.docEntryType): 365 | def __init__(self, thead=None, para=None): 366 | supermod.docEntryType.__init__(self, thead, para) 367 | supermod.docEntryType.subclass = docEntryTypeSub 368 | # end class docEntryTypeSub 369 | 370 | 371 | class docHeadingTypeSub(supermod.docHeadingType): 372 | def __init__(self, level=None, valueOf_='', mixedclass_=None, content_=None): 373 | supermod.docHeadingType.__init__(self, mixedclass_, content_) 374 | supermod.docHeadingType.subclass = docHeadingTypeSub 375 | # end class docHeadingTypeSub 376 | 377 | 378 | class docImageTypeSub(supermod.docImageType): 379 | def __init__(self, width=None, type_=None, name=None, height=None, valueOf_='', mixedclass_=None, content_=None): 380 | supermod.docImageType.__init__(self, mixedclass_, content_) 381 | supermod.docImageType.subclass = docImageTypeSub 382 | # end class docImageTypeSub 383 | 384 | 385 | class docDotFileTypeSub(supermod.docDotFileType): 386 | def __init__(self, name=None, valueOf_='', mixedclass_=None, content_=None): 387 | supermod.docDotFileType.__init__(self, mixedclass_, content_) 388 | supermod.docDotFileType.subclass = docDotFileTypeSub 389 | # end class docDotFileTypeSub 390 | 391 | 392 | class docTocItemTypeSub(supermod.docTocItemType): 393 | def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): 394 | supermod.docTocItemType.__init__(self, mixedclass_, content_) 395 | supermod.docTocItemType.subclass = docTocItemTypeSub 396 | # end class docTocItemTypeSub 397 | 398 | 399 | class docTocListTypeSub(supermod.docTocListType): 400 | def __init__(self, tocitem=None): 401 | supermod.docTocListType.__init__(self, tocitem) 402 | supermod.docTocListType.subclass = docTocListTypeSub 403 | # end class docTocListTypeSub 404 | 405 | 406 | class docLanguageTypeSub(supermod.docLanguageType): 407 | def __init__(self, langid=None, para=None): 408 | supermod.docLanguageType.__init__(self, langid, para) 409 | supermod.docLanguageType.subclass = docLanguageTypeSub 410 | # end class docLanguageTypeSub 411 | 412 | 413 | class docParamListTypeSub(supermod.docParamListType): 414 | def __init__(self, kind=None, parameteritem=None): 415 | supermod.docParamListType.__init__(self, kind, parameteritem) 416 | supermod.docParamListType.subclass = docParamListTypeSub 417 | # end class docParamListTypeSub 418 | 419 | 420 | class docParamListItemSub(supermod.docParamListItem): 421 | def __init__(self, parameternamelist=None, parameterdescription=None): 422 | supermod.docParamListItem.__init__(self, parameternamelist, parameterdescription) 423 | supermod.docParamListItem.subclass = docParamListItemSub 424 | # end class docParamListItemSub 425 | 426 | 427 | class docParamNameListSub(supermod.docParamNameList): 428 | def __init__(self, parametername=None): 429 | supermod.docParamNameList.__init__(self, parametername) 430 | supermod.docParamNameList.subclass = docParamNameListSub 431 | # end class docParamNameListSub 432 | 433 | 434 | class docParamNameSub(supermod.docParamName): 435 | def __init__(self, direction=None, ref=None, mixedclass_=None, content_=None): 436 | supermod.docParamName.__init__(self, mixedclass_, content_) 437 | supermod.docParamName.subclass = docParamNameSub 438 | # end class docParamNameSub 439 | 440 | 441 | class docXRefSectTypeSub(supermod.docXRefSectType): 442 | def __init__(self, id=None, xreftitle=None, xrefdescription=None): 443 | supermod.docXRefSectType.__init__(self, id, xreftitle, xrefdescription) 444 | supermod.docXRefSectType.subclass = docXRefSectTypeSub 445 | # end class docXRefSectTypeSub 446 | 447 | 448 | class docCopyTypeSub(supermod.docCopyType): 449 | def __init__(self, link=None, para=None, sect1=None, internal=None): 450 | supermod.docCopyType.__init__(self, link, para, sect1, internal) 451 | supermod.docCopyType.subclass = docCopyTypeSub 452 | # end class docCopyTypeSub 453 | 454 | 455 | class docCharTypeSub(supermod.docCharType): 456 | def __init__(self, char=None, valueOf_=''): 457 | supermod.docCharType.__init__(self, char) 458 | supermod.docCharType.subclass = docCharTypeSub 459 | # end class docCharTypeSub 460 | 461 | class docParaTypeSub(supermod.docParaType): 462 | def __init__(self, char=None, valueOf_=''): 463 | supermod.docParaType.__init__(self, char) 464 | 465 | self.parameterlist = [] 466 | self.simplesects = [] 467 | self.content = [] 468 | 469 | def buildChildren(self, child_, nodeName_): 470 | supermod.docParaType.buildChildren(self, child_, nodeName_) 471 | 472 | if child_.nodeType == Node.TEXT_NODE: 473 | obj_ = self.mixedclass_(MixedContainer.CategoryText, 474 | MixedContainer.TypeNone, '', child_.nodeValue) 475 | self.content.append(obj_) 476 | elif child_.nodeType == Node.ELEMENT_NODE and \ 477 | nodeName_ == "ref": 478 | obj_ = supermod.docRefTextType.factory() 479 | obj_.build(child_) 480 | self.content.append(obj_) 481 | elif child_.nodeType == Node.ELEMENT_NODE and \ 482 | nodeName_ == 'parameterlist': 483 | obj_ = supermod.docParamListType.factory() 484 | obj_.build(child_) 485 | self.parameterlist.append(obj_) 486 | elif child_.nodeType == Node.ELEMENT_NODE and \ 487 | nodeName_ == 'simplesect': 488 | obj_ = supermod.docSimpleSectType.factory() 489 | obj_.build(child_) 490 | self.simplesects.append(obj_) 491 | 492 | 493 | supermod.docParaType.subclass = docParaTypeSub 494 | # end class docParaTypeSub 495 | 496 | 497 | 498 | def parse(inFilename): 499 | doc = minidom.parse(inFilename) 500 | rootNode = doc.documentElement 501 | rootObj = supermod.DoxygenType.factory() 502 | rootObj.build(rootNode) 503 | return rootObj 504 | 505 | 506 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/generated/index.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Generated Mon Feb 9 19:08:05 2009 by generateDS.py. 5 | """ 6 | from __future__ import absolute_import 7 | from __future__ import unicode_literals 8 | 9 | from xml.dom import minidom 10 | 11 | import os 12 | import sys 13 | from . import compound 14 | 15 | from . import indexsuper as supermod 16 | 17 | class DoxygenTypeSub(supermod.DoxygenType): 18 | def __init__(self, version=None, compound=None): 19 | supermod.DoxygenType.__init__(self, version, compound) 20 | 21 | def find_compounds_and_members(self, details): 22 | """ 23 | Returns a list of all compounds and their members which match details 24 | """ 25 | 26 | results = [] 27 | for compound in self.compound: 28 | members = compound.find_members(details) 29 | if members: 30 | results.append([compound, members]) 31 | else: 32 | if details.match(compound): 33 | results.append([compound, []]) 34 | 35 | return results 36 | 37 | supermod.DoxygenType.subclass = DoxygenTypeSub 38 | # end class DoxygenTypeSub 39 | 40 | 41 | class CompoundTypeSub(supermod.CompoundType): 42 | def __init__(self, kind=None, refid=None, name='', member=None): 43 | supermod.CompoundType.__init__(self, kind, refid, name, member) 44 | 45 | def find_members(self, details): 46 | """ 47 | Returns a list of all members which match details 48 | """ 49 | 50 | results = [] 51 | 52 | for member in self.member: 53 | if details.match(member): 54 | results.append(member) 55 | 56 | return results 57 | 58 | supermod.CompoundType.subclass = CompoundTypeSub 59 | # end class CompoundTypeSub 60 | 61 | 62 | class MemberTypeSub(supermod.MemberType): 63 | 64 | def __init__(self, kind=None, refid=None, name=''): 65 | supermod.MemberType.__init__(self, kind, refid, name) 66 | 67 | supermod.MemberType.subclass = MemberTypeSub 68 | # end class MemberTypeSub 69 | 70 | 71 | def parse(inFilename): 72 | 73 | doc = minidom.parse(inFilename) 74 | rootNode = doc.documentElement 75 | rootObj = supermod.DoxygenType.factory() 76 | rootObj.build(rootNode) 77 | 78 | return rootObj 79 | 80 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/generated/indexsuper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # 4 | # Generated Thu Jun 11 18:43:54 2009 by generateDS.py. 5 | # 6 | 7 | from __future__ import print_function 8 | from __future__ import unicode_literals 9 | 10 | import sys 11 | 12 | from xml.dom import minidom 13 | from xml.dom import Node 14 | 15 | import six 16 | 17 | # 18 | # User methods 19 | # 20 | # Calls to the methods in these classes are generated by generateDS.py. 21 | # You can replace these methods by re-implementing the following class 22 | # in a module named generatedssuper.py. 23 | 24 | try: 25 | from generatedssuper import GeneratedsSuper 26 | except ImportError as exp: 27 | 28 | class GeneratedsSuper(object): 29 | def format_string(self, input_data, input_name=''): 30 | return input_data 31 | def format_integer(self, input_data, input_name=''): 32 | return '%d' % input_data 33 | def format_float(self, input_data, input_name=''): 34 | return '%f' % input_data 35 | def format_double(self, input_data, input_name=''): 36 | return '%e' % input_data 37 | def format_boolean(self, input_data, input_name=''): 38 | return '%s' % input_data 39 | 40 | 41 | # 42 | # If you have installed IPython you can uncomment and use the following. 43 | # IPython is available from http://ipython.scipy.org/. 44 | # 45 | 46 | ## from IPython.Shell import IPShellEmbed 47 | ## args = '' 48 | ## ipshell = IPShellEmbed(args, 49 | ## banner = 'Dropping into IPython', 50 | ## exit_msg = 'Leaving Interpreter, back to program.') 51 | 52 | # Then use the following line where and when you want to drop into the 53 | # IPython shell: 54 | # ipshell(' -- Entering ipshell.\nHit Ctrl-D to exit') 55 | 56 | # 57 | # Globals 58 | # 59 | 60 | ExternalEncoding = 'ascii' 61 | 62 | # 63 | # Support/utility functions. 64 | # 65 | 66 | def showIndent(outfile, level): 67 | for idx in range(level): 68 | outfile.write(' ') 69 | 70 | def quote_xml(inStr): 71 | s1 = (isinstance(inStr, six.string_types) and inStr or 72 | '%s' % inStr) 73 | s1 = s1.replace('&', '&') 74 | s1 = s1.replace('<', '<') 75 | s1 = s1.replace('>', '>') 76 | return s1 77 | 78 | def quote_attrib(inStr): 79 | s1 = (isinstance(inStr, six.string_types) and inStr or 80 | '%s' % inStr) 81 | s1 = s1.replace('&', '&') 82 | s1 = s1.replace('<', '<') 83 | s1 = s1.replace('>', '>') 84 | if '"' in s1: 85 | if "'" in s1: 86 | s1 = '"%s"' % s1.replace('"', """) 87 | else: 88 | s1 = "'%s'" % s1 89 | else: 90 | s1 = '"%s"' % s1 91 | return s1 92 | 93 | def quote_python(inStr): 94 | s1 = inStr 95 | if s1.find("'") == -1: 96 | if s1.find('\n') == -1: 97 | return "'%s'" % s1 98 | else: 99 | return "'''%s'''" % s1 100 | else: 101 | if s1.find('"') != -1: 102 | s1 = s1.replace('"', '\\"') 103 | if s1.find('\n') == -1: 104 | return '"%s"' % s1 105 | else: 106 | return '"""%s"""' % s1 107 | 108 | 109 | class MixedContainer(object): 110 | # Constants for category: 111 | CategoryNone = 0 112 | CategoryText = 1 113 | CategorySimple = 2 114 | CategoryComplex = 3 115 | # Constants for content_type: 116 | TypeNone = 0 117 | TypeText = 1 118 | TypeString = 2 119 | TypeInteger = 3 120 | TypeFloat = 4 121 | TypeDecimal = 5 122 | TypeDouble = 6 123 | TypeBoolean = 7 124 | def __init__(self, category, content_type, name, value): 125 | self.category = category 126 | self.content_type = content_type 127 | self.name = name 128 | self.value = value 129 | def getCategory(self): 130 | return self.category 131 | def getContenttype(self, content_type): 132 | return self.content_type 133 | def getValue(self): 134 | return self.value 135 | def getName(self): 136 | return self.name 137 | def export(self, outfile, level, name, namespace): 138 | if self.category == MixedContainer.CategoryText: 139 | outfile.write(self.value) 140 | elif self.category == MixedContainer.CategorySimple: 141 | self.exportSimple(outfile, level, name) 142 | else: # category == MixedContainer.CategoryComplex 143 | self.value.export(outfile, level, namespace,name) 144 | def exportSimple(self, outfile, level, name): 145 | if self.content_type == MixedContainer.TypeString: 146 | outfile.write('<%s>%s' % (self.name, self.value, self.name)) 147 | elif self.content_type == MixedContainer.TypeInteger or \ 148 | self.content_type == MixedContainer.TypeBoolean: 149 | outfile.write('<%s>%d' % (self.name, self.value, self.name)) 150 | elif self.content_type == MixedContainer.TypeFloat or \ 151 | self.content_type == MixedContainer.TypeDecimal: 152 | outfile.write('<%s>%f' % (self.name, self.value, self.name)) 153 | elif self.content_type == MixedContainer.TypeDouble: 154 | outfile.write('<%s>%g' % (self.name, self.value, self.name)) 155 | def exportLiteral(self, outfile, level, name): 156 | if self.category == MixedContainer.CategoryText: 157 | showIndent(outfile, level) 158 | outfile.write('MixedContainer(%d, %d, "%s", "%s"),\n' % \ 159 | (self.category, self.content_type, self.name, self.value)) 160 | elif self.category == MixedContainer.CategorySimple: 161 | showIndent(outfile, level) 162 | outfile.write('MixedContainer(%d, %d, "%s", "%s"),\n' % \ 163 | (self.category, self.content_type, self.name, self.value)) 164 | else: # category == MixedContainer.CategoryComplex 165 | showIndent(outfile, level) 166 | outfile.write('MixedContainer(%d, %d, "%s",\n' % \ 167 | (self.category, self.content_type, self.name,)) 168 | self.value.exportLiteral(outfile, level + 1) 169 | showIndent(outfile, level) 170 | outfile.write(')\n') 171 | 172 | 173 | class _MemberSpec(object): 174 | def __init__(self, name='', data_type='', container=0): 175 | self.name = name 176 | self.data_type = data_type 177 | self.container = container 178 | def set_name(self, name): self.name = name 179 | def get_name(self): return self.name 180 | def set_data_type(self, data_type): self.data_type = data_type 181 | def get_data_type(self): return self.data_type 182 | def set_container(self, container): self.container = container 183 | def get_container(self): return self.container 184 | 185 | 186 | # 187 | # Data representation classes. 188 | # 189 | 190 | class DoxygenType(GeneratedsSuper): 191 | subclass = None 192 | superclass = None 193 | def __init__(self, version=None, compound=None): 194 | self.version = version 195 | if compound is None: 196 | self.compound = [] 197 | else: 198 | self.compound = compound 199 | def factory(*args_, **kwargs_): 200 | if DoxygenType.subclass: 201 | return DoxygenType.subclass(*args_, **kwargs_) 202 | else: 203 | return DoxygenType(*args_, **kwargs_) 204 | factory = staticmethod(factory) 205 | def get_compound(self): return self.compound 206 | def set_compound(self, compound): self.compound = compound 207 | def add_compound(self, value): self.compound.append(value) 208 | def insert_compound(self, index, value): self.compound[index] = value 209 | def get_version(self): return self.version 210 | def set_version(self, version): self.version = version 211 | def export(self, outfile, level, namespace_='', name_='DoxygenType', namespacedef_=''): 212 | showIndent(outfile, level) 213 | outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) 214 | self.exportAttributes(outfile, level, namespace_, name_='DoxygenType') 215 | if self.hasContent_(): 216 | outfile.write('>\n') 217 | self.exportChildren(outfile, level + 1, namespace_, name_) 218 | showIndent(outfile, level) 219 | outfile.write('\n' % (namespace_, name_)) 220 | else: 221 | outfile.write(' />\n') 222 | def exportAttributes(self, outfile, level, namespace_='', name_='DoxygenType'): 223 | outfile.write(' version=%s' % (self.format_string(quote_attrib(self.version).encode(ExternalEncoding), input_name='version'), )) 224 | def exportChildren(self, outfile, level, namespace_='', name_='DoxygenType'): 225 | for compound_ in self.compound: 226 | compound_.export(outfile, level, namespace_, name_='compound') 227 | def hasContent_(self): 228 | if ( 229 | self.compound is not None 230 | ): 231 | return True 232 | else: 233 | return False 234 | def exportLiteral(self, outfile, level, name_='DoxygenType'): 235 | level += 1 236 | self.exportLiteralAttributes(outfile, level, name_) 237 | if self.hasContent_(): 238 | self.exportLiteralChildren(outfile, level, name_) 239 | def exportLiteralAttributes(self, outfile, level, name_): 240 | if self.version is not None: 241 | showIndent(outfile, level) 242 | outfile.write('version = %s,\n' % (self.version,)) 243 | def exportLiteralChildren(self, outfile, level, name_): 244 | showIndent(outfile, level) 245 | outfile.write('compound=[\n') 246 | level += 1 247 | for compound in self.compound: 248 | showIndent(outfile, level) 249 | outfile.write('model_.compound(\n') 250 | compound.exportLiteral(outfile, level, name_='compound') 251 | showIndent(outfile, level) 252 | outfile.write('),\n') 253 | level -= 1 254 | showIndent(outfile, level) 255 | outfile.write('],\n') 256 | def build(self, node_): 257 | attrs = node_.attributes 258 | self.buildAttributes(attrs) 259 | for child_ in node_.childNodes: 260 | nodeName_ = child_.nodeName.split(':')[-1] 261 | self.buildChildren(child_, nodeName_) 262 | def buildAttributes(self, attrs): 263 | if attrs.get('version'): 264 | self.version = attrs.get('version').value 265 | def buildChildren(self, child_, nodeName_): 266 | if child_.nodeType == Node.ELEMENT_NODE and \ 267 | nodeName_ == 'compound': 268 | obj_ = CompoundType.factory() 269 | obj_.build(child_) 270 | self.compound.append(obj_) 271 | # end class DoxygenType 272 | 273 | 274 | class CompoundType(GeneratedsSuper): 275 | subclass = None 276 | superclass = None 277 | def __init__(self, kind=None, refid=None, name=None, member=None): 278 | self.kind = kind 279 | self.refid = refid 280 | self.name = name 281 | if member is None: 282 | self.member = [] 283 | else: 284 | self.member = member 285 | def factory(*args_, **kwargs_): 286 | if CompoundType.subclass: 287 | return CompoundType.subclass(*args_, **kwargs_) 288 | else: 289 | return CompoundType(*args_, **kwargs_) 290 | factory = staticmethod(factory) 291 | def get_name(self): return self.name 292 | def set_name(self, name): self.name = name 293 | def get_member(self): return self.member 294 | def set_member(self, member): self.member = member 295 | def add_member(self, value): self.member.append(value) 296 | def insert_member(self, index, value): self.member[index] = value 297 | def get_kind(self): return self.kind 298 | def set_kind(self, kind): self.kind = kind 299 | def get_refid(self): return self.refid 300 | def set_refid(self, refid): self.refid = refid 301 | def export(self, outfile, level, namespace_='', name_='CompoundType', namespacedef_=''): 302 | showIndent(outfile, level) 303 | outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) 304 | self.exportAttributes(outfile, level, namespace_, name_='CompoundType') 305 | if self.hasContent_(): 306 | outfile.write('>\n') 307 | self.exportChildren(outfile, level + 1, namespace_, name_) 308 | showIndent(outfile, level) 309 | outfile.write('\n' % (namespace_, name_)) 310 | else: 311 | outfile.write(' />\n') 312 | def exportAttributes(self, outfile, level, namespace_='', name_='CompoundType'): 313 | outfile.write(' kind=%s' % (quote_attrib(self.kind), )) 314 | outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) 315 | def exportChildren(self, outfile, level, namespace_='', name_='CompoundType'): 316 | if self.name is not None: 317 | showIndent(outfile, level) 318 | outfile.write('<%sname>%s\n' % (namespace_, self.format_string(quote_xml(self.name).encode(ExternalEncoding), input_name='name'), namespace_)) 319 | for member_ in self.member: 320 | member_.export(outfile, level, namespace_, name_='member') 321 | def hasContent_(self): 322 | if ( 323 | self.name is not None or 324 | self.member is not None 325 | ): 326 | return True 327 | else: 328 | return False 329 | def exportLiteral(self, outfile, level, name_='CompoundType'): 330 | level += 1 331 | self.exportLiteralAttributes(outfile, level, name_) 332 | if self.hasContent_(): 333 | self.exportLiteralChildren(outfile, level, name_) 334 | def exportLiteralAttributes(self, outfile, level, name_): 335 | if self.kind is not None: 336 | showIndent(outfile, level) 337 | outfile.write('kind = "%s",\n' % (self.kind,)) 338 | if self.refid is not None: 339 | showIndent(outfile, level) 340 | outfile.write('refid = %s,\n' % (self.refid,)) 341 | def exportLiteralChildren(self, outfile, level, name_): 342 | showIndent(outfile, level) 343 | outfile.write('name=%s,\n' % quote_python(self.name).encode(ExternalEncoding)) 344 | showIndent(outfile, level) 345 | outfile.write('member=[\n') 346 | level += 1 347 | for member in self.member: 348 | showIndent(outfile, level) 349 | outfile.write('model_.member(\n') 350 | member.exportLiteral(outfile, level, name_='member') 351 | showIndent(outfile, level) 352 | outfile.write('),\n') 353 | level -= 1 354 | showIndent(outfile, level) 355 | outfile.write('],\n') 356 | def build(self, node_): 357 | attrs = node_.attributes 358 | self.buildAttributes(attrs) 359 | for child_ in node_.childNodes: 360 | nodeName_ = child_.nodeName.split(':')[-1] 361 | self.buildChildren(child_, nodeName_) 362 | def buildAttributes(self, attrs): 363 | if attrs.get('kind'): 364 | self.kind = attrs.get('kind').value 365 | if attrs.get('refid'): 366 | self.refid = attrs.get('refid').value 367 | def buildChildren(self, child_, nodeName_): 368 | if child_.nodeType == Node.ELEMENT_NODE and \ 369 | nodeName_ == 'name': 370 | name_ = '' 371 | for text__content_ in child_.childNodes: 372 | name_ += text__content_.nodeValue 373 | self.name = name_ 374 | elif child_.nodeType == Node.ELEMENT_NODE and \ 375 | nodeName_ == 'member': 376 | obj_ = MemberType.factory() 377 | obj_.build(child_) 378 | self.member.append(obj_) 379 | # end class CompoundType 380 | 381 | 382 | class MemberType(GeneratedsSuper): 383 | subclass = None 384 | superclass = None 385 | def __init__(self, kind=None, refid=None, name=None): 386 | self.kind = kind 387 | self.refid = refid 388 | self.name = name 389 | def factory(*args_, **kwargs_): 390 | if MemberType.subclass: 391 | return MemberType.subclass(*args_, **kwargs_) 392 | else: 393 | return MemberType(*args_, **kwargs_) 394 | factory = staticmethod(factory) 395 | def get_name(self): return self.name 396 | def set_name(self, name): self.name = name 397 | def get_kind(self): return self.kind 398 | def set_kind(self, kind): self.kind = kind 399 | def get_refid(self): return self.refid 400 | def set_refid(self, refid): self.refid = refid 401 | def export(self, outfile, level, namespace_='', name_='MemberType', namespacedef_=''): 402 | showIndent(outfile, level) 403 | outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) 404 | self.exportAttributes(outfile, level, namespace_, name_='MemberType') 405 | if self.hasContent_(): 406 | outfile.write('>\n') 407 | self.exportChildren(outfile, level + 1, namespace_, name_) 408 | showIndent(outfile, level) 409 | outfile.write('\n' % (namespace_, name_)) 410 | else: 411 | outfile.write(' />\n') 412 | def exportAttributes(self, outfile, level, namespace_='', name_='MemberType'): 413 | outfile.write(' kind=%s' % (quote_attrib(self.kind), )) 414 | outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) 415 | def exportChildren(self, outfile, level, namespace_='', name_='MemberType'): 416 | if self.name is not None: 417 | showIndent(outfile, level) 418 | outfile.write('<%sname>%s\n' % (namespace_, self.format_string(quote_xml(self.name).encode(ExternalEncoding), input_name='name'), namespace_)) 419 | def hasContent_(self): 420 | if ( 421 | self.name is not None 422 | ): 423 | return True 424 | else: 425 | return False 426 | def exportLiteral(self, outfile, level, name_='MemberType'): 427 | level += 1 428 | self.exportLiteralAttributes(outfile, level, name_) 429 | if self.hasContent_(): 430 | self.exportLiteralChildren(outfile, level, name_) 431 | def exportLiteralAttributes(self, outfile, level, name_): 432 | if self.kind is not None: 433 | showIndent(outfile, level) 434 | outfile.write('kind = "%s",\n' % (self.kind,)) 435 | if self.refid is not None: 436 | showIndent(outfile, level) 437 | outfile.write('refid = %s,\n' % (self.refid,)) 438 | def exportLiteralChildren(self, outfile, level, name_): 439 | showIndent(outfile, level) 440 | outfile.write('name=%s,\n' % quote_python(self.name).encode(ExternalEncoding)) 441 | def build(self, node_): 442 | attrs = node_.attributes 443 | self.buildAttributes(attrs) 444 | for child_ in node_.childNodes: 445 | nodeName_ = child_.nodeName.split(':')[-1] 446 | self.buildChildren(child_, nodeName_) 447 | def buildAttributes(self, attrs): 448 | if attrs.get('kind'): 449 | self.kind = attrs.get('kind').value 450 | if attrs.get('refid'): 451 | self.refid = attrs.get('refid').value 452 | def buildChildren(self, child_, nodeName_): 453 | if child_.nodeType == Node.ELEMENT_NODE and \ 454 | nodeName_ == 'name': 455 | name_ = '' 456 | for text__content_ in child_.childNodes: 457 | name_ += text__content_.nodeValue 458 | self.name = name_ 459 | # end class MemberType 460 | 461 | 462 | USAGE_TEXT = """ 463 | Usage: python .py [ -s ] 464 | Options: 465 | -s Use the SAX parser, not the minidom parser. 466 | """ 467 | 468 | def usage(): 469 | print(USAGE_TEXT) 470 | sys.exit(1) 471 | 472 | 473 | def parse(inFileName): 474 | doc = minidom.parse(inFileName) 475 | rootNode = doc.documentElement 476 | rootObj = DoxygenType.factory() 477 | rootObj.build(rootNode) 478 | # Enable Python to collect the space used by the DOM. 479 | doc = None 480 | sys.stdout.write('\n') 481 | rootObj.export(sys.stdout, 0, name_="doxygenindex", 482 | namespacedef_='') 483 | return rootObj 484 | 485 | 486 | def parseString(inString): 487 | doc = minidom.parseString(inString) 488 | rootNode = doc.documentElement 489 | rootObj = DoxygenType.factory() 490 | rootObj.build(rootNode) 491 | # Enable Python to collect the space used by the DOM. 492 | doc = None 493 | sys.stdout.write('\n') 494 | rootObj.export(sys.stdout, 0, name_="doxygenindex", 495 | namespacedef_='') 496 | return rootObj 497 | 498 | 499 | def parseLiteral(inFileName): 500 | doc = minidom.parse(inFileName) 501 | rootNode = doc.documentElement 502 | rootObj = DoxygenType.factory() 503 | rootObj.build(rootNode) 504 | # Enable Python to collect the space used by the DOM. 505 | doc = None 506 | sys.stdout.write('from index import *\n\n') 507 | sys.stdout.write('rootObj = doxygenindex(\n') 508 | rootObj.exportLiteral(sys.stdout, 0, name_="doxygenindex") 509 | sys.stdout.write(')\n') 510 | return rootObj 511 | 512 | 513 | def main(): 514 | args = sys.argv[1:] 515 | if len(args) == 1: 516 | parse(args[0]) 517 | else: 518 | usage() 519 | 520 | 521 | 522 | 523 | if __name__ == '__main__': 524 | main() 525 | #import pdb 526 | #pdb.run('main()') 527 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/text.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010 Free Software Foundation, Inc. 3 | # 4 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 5 | # This file is a part of gr-display 6 | # 7 | # SPDX-License-Identifier: GPL-3.0-or-later 8 | # 9 | # 10 | """ 11 | Utilities for extracting text from generated classes. 12 | """ 13 | from __future__ import unicode_literals 14 | 15 | def is_string(txt): 16 | if isinstance(txt, str): 17 | return True 18 | try: 19 | if isinstance(txt, str): 20 | return True 21 | except NameError: 22 | pass 23 | return False 24 | 25 | def description(obj): 26 | if obj is None: 27 | return None 28 | return description_bit(obj).strip() 29 | 30 | def description_bit(obj): 31 | if hasattr(obj, 'content'): 32 | contents = [description_bit(item) for item in obj.content] 33 | result = ''.join(contents) 34 | elif hasattr(obj, 'content_'): 35 | contents = [description_bit(item) for item in obj.content_] 36 | result = ''.join(contents) 37 | elif hasattr(obj, 'value'): 38 | result = description_bit(obj.value) 39 | elif is_string(obj): 40 | return obj 41 | else: 42 | raise Exception('Expecting a string or something with content, content_ or value attribute') 43 | # If this bit is a paragraph then add one some line breaks. 44 | if hasattr(obj, 'name') and obj.name == 'para': 45 | result += "\n\n" 46 | return result 47 | -------------------------------------------------------------------------------- /docs/doxygen/other/group_defs.dox: -------------------------------------------------------------------------------- 1 | /*! 2 | * \defgroup block GNU Radio DISPLAY C++ Signal Processing Blocks 3 | * \brief All C++ blocks that can be used from the DISPLAY GNU Radio 4 | * module are listed here or in the subcategories below. 5 | * 6 | */ 7 | 8 | -------------------------------------------------------------------------------- /docs/doxygen/other/main_page.dox: -------------------------------------------------------------------------------- 1 | /*! \mainpage 2 | 3 | Welcome to the GNU Radio DISPLAY Block 4 | 5 | This is the intro page for the Doxygen manual generated for the DISPLAY 6 | block (docs/doxygen/other/main_page.dox). Edit it to add more detailed 7 | documentation about the new GNU Radio modules contained in this 8 | project. 9 | 10 | */ 11 | -------------------------------------------------------------------------------- /docs/doxygen/pydoc_macros.h: -------------------------------------------------------------------------------- 1 | #ifndef PYDOC_MACROS_H 2 | #define PYDOC_MACROS_H 3 | 4 | #define __EXPAND(x) x 5 | #define __COUNT(_1, _2, _3, _4, _5, _6, _7, COUNT, ...) COUNT 6 | #define __VA_SIZE(...) __EXPAND(__COUNT(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1)) 7 | #define __CAT1(a, b) a##b 8 | #define __CAT2(a, b) __CAT1(a, b) 9 | #define __DOC1(n1) __doc_##n1 10 | #define __DOC2(n1, n2) __doc_##n1##_##n2 11 | #define __DOC3(n1, n2, n3) __doc_##n1##_##n2##_##n3 12 | #define __DOC4(n1, n2, n3, n4) __doc_##n1##_##n2##_##n3##_##n4 13 | #define __DOC5(n1, n2, n3, n4, n5) __doc_##n1##_##n2##_##n3##_##n4##_##n5 14 | #define __DOC6(n1, n2, n3, n4, n5, n6) __doc_##n1##_##n2##_##n3##_##n4##_##n5##_##n6 15 | #define __DOC7(n1, n2, n3, n4, n5, n6, n7) \ 16 | __doc_##n1##_##n2##_##n3##_##n4##_##n5##_##n6##_##n7 17 | #define DOC(...) __EXPAND(__EXPAND(__CAT2(__DOC, __VA_SIZE(__VA_ARGS__)))(__VA_ARGS__)) 18 | 19 | #endif // PYDOC_MACROS_H -------------------------------------------------------------------------------- /docs/doxygen/update_pydoc.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010-2012 Free Software Foundation, Inc. 3 | # 4 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 5 | # This file is a part of gnuradio 6 | # 7 | # SPDX-License-Identifier: GPL-3.0-or-later 8 | # 9 | # 10 | """ 11 | Updates the *pydoc_h files for a module 12 | Execute using: python update_pydoc.py xml_path outputfilename 13 | 14 | The file instructs Pybind11 to transfer the doxygen comments into the 15 | python docstrings. 16 | 17 | """ 18 | from __future__ import unicode_literals 19 | 20 | import os, sys, time, glob, re, json 21 | from argparse import ArgumentParser 22 | 23 | from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile 24 | from doxyxml import DoxyOther, base 25 | 26 | def py_name(name): 27 | bits = name.split('_') 28 | return '_'.join(bits[1:]) 29 | 30 | def make_name(name): 31 | bits = name.split('_') 32 | return bits[0] + '_make_' + '_'.join(bits[1:]) 33 | 34 | 35 | class Block(object): 36 | """ 37 | Checks if doxyxml produced objects correspond to a gnuradio block. 38 | """ 39 | 40 | @classmethod 41 | def includes(cls, item): 42 | if not isinstance(item, DoxyClass): 43 | return False 44 | # Check for a parsing error. 45 | if item.error(): 46 | return False 47 | friendname = make_name(item.name()) 48 | is_a_block = item.has_member(friendname, DoxyFriend) 49 | # But now sometimes the make function isn't a friend so check again. 50 | if not is_a_block: 51 | is_a_block = di.has_member(friendname, DoxyFunction) 52 | return is_a_block 53 | 54 | class Block2(object): 55 | """ 56 | Checks if doxyxml produced objects correspond to a new style 57 | gnuradio block. 58 | """ 59 | 60 | @classmethod 61 | def includes(cls, item): 62 | if not isinstance(item, DoxyClass): 63 | return False 64 | # Check for a parsing error. 65 | if item.error(): 66 | return False 67 | is_a_block2 = item.has_member('make', DoxyFunction) and item.has_member('sptr', DoxyOther) 68 | return is_a_block2 69 | 70 | 71 | def utoascii(text): 72 | """ 73 | Convert unicode text into ascii and escape quotes and backslashes. 74 | """ 75 | if text is None: 76 | return '' 77 | out = text.encode('ascii', 'replace') 78 | # swig will require us to replace blackslash with 4 backslashes 79 | # TODO: evaluate what this should be for pybind11 80 | out = out.replace(b'\\', b'\\\\\\\\') 81 | out = out.replace(b'"', b'\\"').decode('ascii') 82 | return str(out) 83 | 84 | 85 | def combine_descriptions(obj): 86 | """ 87 | Combines the brief and detailed descriptions of an object together. 88 | """ 89 | description = [] 90 | bd = obj.brief_description.strip() 91 | dd = obj.detailed_description.strip() 92 | if bd: 93 | description.append(bd) 94 | if dd: 95 | description.append(dd) 96 | return utoascii('\n\n'.join(description)).strip() 97 | 98 | def format_params(parameteritems): 99 | output = ['Args:'] 100 | template = ' {0} : {1}' 101 | for pi in parameteritems: 102 | output.append(template.format(pi.name, pi.description)) 103 | return '\n'.join(output) 104 | 105 | entry_templ = '%feature("docstring") {name} "{docstring}"' 106 | def make_entry(obj, name=None, templ="{description}", description=None, params=[]): 107 | """ 108 | Create a docstring key/value pair, where the key is the object name. 109 | 110 | obj - a doxyxml object from which documentation will be extracted. 111 | name - the name of the C object (defaults to obj.name()) 112 | templ - an optional template for the docstring containing only one 113 | variable named 'description'. 114 | description - if this optional variable is set then it's value is 115 | used as the description instead of extracting it from obj. 116 | """ 117 | if name is None: 118 | name=obj.name() 119 | if hasattr(obj,'_parse_data') and hasattr(obj._parse_data,'definition'): 120 | name=obj._parse_data.definition.split(' ')[-1] 121 | if "operator " in name: 122 | return '' 123 | if description is None: 124 | description = combine_descriptions(obj) 125 | if params: 126 | description += '\n\n' 127 | description += utoascii(format_params(params)) 128 | docstring = templ.format(description=description) 129 | 130 | return {name: docstring} 131 | 132 | 133 | def make_class_entry(klass, description=None, ignored_methods=[], params=None): 134 | """ 135 | Create a class docstring key/value pair. 136 | """ 137 | if params is None: 138 | params = klass.params 139 | output = {} 140 | output.update(make_entry(klass, description=description, params=params)) 141 | for func in klass.in_category(DoxyFunction): 142 | if func.name() not in ignored_methods: 143 | name = klass.name() + '::' + func.name() 144 | output.update(make_entry(func, name=name)) 145 | return output 146 | 147 | 148 | def make_block_entry(di, block): 149 | """ 150 | Create class and function docstrings of a gnuradio block 151 | """ 152 | descriptions = [] 153 | # Get the documentation associated with the class. 154 | class_desc = combine_descriptions(block) 155 | if class_desc: 156 | descriptions.append(class_desc) 157 | # Get the documentation associated with the make function 158 | make_func = di.get_member(make_name(block.name()), DoxyFunction) 159 | make_func_desc = combine_descriptions(make_func) 160 | if make_func_desc: 161 | descriptions.append(make_func_desc) 162 | # Get the documentation associated with the file 163 | try: 164 | block_file = di.get_member(block.name() + ".h", DoxyFile) 165 | file_desc = combine_descriptions(block_file) 166 | if file_desc: 167 | descriptions.append(file_desc) 168 | except base.Base.NoSuchMember: 169 | # Don't worry if we can't find a matching file. 170 | pass 171 | # And join them all together to make a super duper description. 172 | super_description = "\n\n".join(descriptions) 173 | # Associate the combined description with the class and 174 | # the make function. 175 | output = {} 176 | output.update(make_class_entry(block, description=super_description)) 177 | output.update(make_entry(make_func, description=super_description, 178 | params=block.params)) 179 | return output 180 | 181 | def make_block2_entry(di, block): 182 | """ 183 | Create class and function docstrings of a new style gnuradio block 184 | """ 185 | # For new style blocks all the relevant documentation should be 186 | # associated with the 'make' method. 187 | class_description = combine_descriptions(block) 188 | make_func = block.get_member('make', DoxyFunction) 189 | make_description = combine_descriptions(make_func) 190 | description = class_description + "\n\nConstructor Specific Documentation:\n\n" + make_description 191 | # Associate the combined description with the class and 192 | # the make function. 193 | output = {} 194 | output.update(make_class_entry( 195 | block, description=description, 196 | ignored_methods=['make'], params=make_func.params)) 197 | makename = block.name() + '::make' 198 | output.update(make_entry( 199 | make_func, name=makename, description=description, 200 | params=make_func.params)) 201 | return output 202 | 203 | def get_docstrings_dict(di, custom_output=None): 204 | 205 | output = {} 206 | if custom_output: 207 | output.update(custom_output) 208 | 209 | # Create docstrings for the blocks. 210 | blocks = di.in_category(Block) 211 | blocks2 = di.in_category(Block2) 212 | 213 | make_funcs = set([]) 214 | for block in blocks: 215 | try: 216 | make_func = di.get_member(make_name(block.name()), DoxyFunction) 217 | # Don't want to risk writing to output twice. 218 | if make_func.name() not in make_funcs: 219 | make_funcs.add(make_func.name()) 220 | output.update(make_block_entry(di, block)) 221 | except block.ParsingError: 222 | sys.stderr.write('Parsing error for block {0}\n'.format(block.name())) 223 | raise 224 | 225 | for block in blocks2: 226 | try: 227 | make_func = block.get_member('make', DoxyFunction) 228 | make_func_name = block.name() +'::make' 229 | # Don't want to risk writing to output twice. 230 | if make_func_name not in make_funcs: 231 | make_funcs.add(make_func_name) 232 | output.update(make_block2_entry(di, block)) 233 | except block.ParsingError: 234 | sys.stderr.write('Parsing error for block {0}\n'.format(block.name())) 235 | raise 236 | 237 | # Create docstrings for functions 238 | # Don't include the make functions since they have already been dealt with. 239 | funcs = [f for f in di.in_category(DoxyFunction) 240 | if f.name() not in make_funcs and not f.name().startswith('std::')] 241 | for f in funcs: 242 | try: 243 | output.update(make_entry(f)) 244 | except f.ParsingError: 245 | sys.stderr.write('Parsing error for function {0}\n'.format(f.name())) 246 | 247 | # Create docstrings for classes 248 | block_names = [block.name() for block in blocks] 249 | block_names += [block.name() for block in blocks2] 250 | klasses = [k for k in di.in_category(DoxyClass) 251 | if k.name() not in block_names and not k.name().startswith('std::')] 252 | for k in klasses: 253 | try: 254 | output.update(make_class_entry(k)) 255 | except k.ParsingError: 256 | sys.stderr.write('Parsing error for class {0}\n'.format(k.name())) 257 | 258 | # Docstrings are not created for anything that is not a function or a class. 259 | # If this excludes anything important please add it here. 260 | 261 | return output 262 | 263 | def sub_docstring_in_pydoc_h(pydoc_files, docstrings_dict, output_dir, filter_str=None): 264 | if filter_str: 265 | docstrings_dict = {k: v for k, v in docstrings_dict.items() if k.startswith(filter_str)} 266 | 267 | with open(os.path.join(output_dir,'docstring_status'),'w') as status_file: 268 | 269 | for pydoc_file in pydoc_files: 270 | if filter_str: 271 | filter_str2 = "::".join((filter_str,os.path.split(pydoc_file)[-1].split('_pydoc_template.h')[0])) 272 | docstrings_dict2 = {k: v for k, v in docstrings_dict.items() if k.startswith(filter_str2)} 273 | else: 274 | docstrings_dict2 = docstrings_dict 275 | 276 | 277 | 278 | file_in = open(pydoc_file,'r').read() 279 | for key, value in docstrings_dict2.items(): 280 | file_in_tmp = file_in 281 | try: 282 | doc_key = key.split("::") 283 | # if 'gr' in doc_key: 284 | # doc_key.remove('gr') 285 | doc_key = '_'.join(doc_key) 286 | regexp = r'(__doc_{} =\sR\"doc\()[^)]*(\)doc\")'.format(doc_key) 287 | regexp = re.compile(regexp, re.MULTILINE) 288 | 289 | (file_in, nsubs) = regexp.subn(r'\1'+value+r'\2', file_in, count=1) 290 | if nsubs == 1: 291 | status_file.write("PASS: " + pydoc_file + "\n") 292 | except KeyboardInterrupt: 293 | raise KeyboardInterrupt 294 | except: # be permissive, TODO log, but just leave the docstring blank 295 | status_file.write("FAIL: " + pydoc_file + "\n") 296 | file_in = file_in_tmp 297 | 298 | output_pathname = os.path.join(output_dir, os.path.basename(pydoc_file).replace('_template.h','.h')) 299 | # FIXME: Remove this debug print 300 | print('output docstrings to {}'.format(output_pathname)) 301 | with open(output_pathname,'w') as file_out: 302 | file_out.write(file_in) 303 | 304 | def copy_docstring_templates(pydoc_files, output_dir): 305 | with open(os.path.join(output_dir,'docstring_status'),'w') as status_file: 306 | for pydoc_file in pydoc_files: 307 | file_in = open(pydoc_file,'r').read() 308 | output_pathname = os.path.join(output_dir, os.path.basename(pydoc_file).replace('_template.h','.h')) 309 | # FIXME: Remove this debug print 310 | print('copy docstrings to {}'.format(output_pathname)) 311 | with open(output_pathname,'w') as file_out: 312 | file_out.write(file_in) 313 | status_file.write("DONE") 314 | 315 | def argParse(): 316 | """Parses commandline args.""" 317 | desc='Scrape the doxygen generated xml for docstrings to insert into python bindings' 318 | parser = ArgumentParser(description=desc) 319 | 320 | parser.add_argument("function", help="Operation to perform on docstrings", choices=["scrape","sub","copy"]) 321 | 322 | parser.add_argument("--xml_path") 323 | parser.add_argument("--bindings_dir") 324 | parser.add_argument("--output_dir") 325 | parser.add_argument("--json_path") 326 | parser.add_argument("--filter", default=None) 327 | 328 | return parser.parse_args() 329 | 330 | if __name__ == "__main__": 331 | # Parse command line options and set up doxyxml. 332 | args = argParse() 333 | if args.function.lower() == 'scrape': 334 | di = DoxyIndex(args.xml_path) 335 | docstrings_dict = get_docstrings_dict(di) 336 | with open(args.json_path, 'w') as fp: 337 | json.dump(docstrings_dict, fp) 338 | elif args.function.lower() == 'sub': 339 | with open(args.json_path, 'r') as fp: 340 | docstrings_dict = json.load(fp) 341 | pydoc_files = glob.glob(os.path.join(args.bindings_dir,'*_pydoc_template.h')) 342 | sub_docstring_in_pydoc_h(pydoc_files, docstrings_dict, args.output_dir, args.filter) 343 | elif args.function.lower() == 'copy': 344 | pydoc_files = glob.glob(os.path.join(args.bindings_dir,'*_pydoc_template.h')) 345 | copy_docstring_templates(pydoc_files, args.output_dir) 346 | 347 | 348 | -------------------------------------------------------------------------------- /examples/SimpleTextDisplayTest.grc: -------------------------------------------------------------------------------- 1 | options: 2 | parameters: 3 | author: dl1ksv 4 | catch_exceptions: 'True' 5 | category: '[GRC Hier Blocks]' 6 | cmake_opt: '' 7 | comment: '' 8 | copyright: '' 9 | description: '' 10 | gen_cmake: 'On' 11 | gen_linking: dynamic 12 | generate_options: qt_gui 13 | hier_block_src_path: '.:' 14 | id: displayTest 15 | max_nouts: '0' 16 | output_language: python 17 | placement: (0,0) 18 | qt_qss_theme: '' 19 | realtime_scheduling: '' 20 | run: 'True' 21 | run_command: '{python} -u {filename}' 22 | run_options: prompt 23 | sizing_mode: fixed 24 | thread_safe_setters: '' 25 | title: Simple Test 26 | states: 27 | bus_sink: false 28 | bus_source: false 29 | bus_structure: null 30 | coordinate: [8, 8] 31 | rotation: 0 32 | state: enabled 33 | 34 | blocks: 35 | - name: samp_rate 36 | id: variable 37 | parameters: 38 | comment: '' 39 | value: '32000' 40 | states: 41 | bus_sink: false 42 | bus_source: false 43 | bus_structure: null 44 | coordinate: [184, 12] 45 | rotation: 0 46 | state: enabled 47 | - name: blocks_throttle_0 48 | id: blocks_throttle 49 | parameters: 50 | affinity: '' 51 | alias: '' 52 | comment: '' 53 | ignoretag: 'True' 54 | maxoutbuf: '0' 55 | minoutbuf: '0' 56 | samples_per_second: samp_rate 57 | type: byte 58 | vlen: '1' 59 | states: 60 | bus_sink: false 61 | bus_source: false 62 | bus_structure: null 63 | coordinate: [528, 412.0] 64 | rotation: 0 65 | state: true 66 | - name: blocks_vector_source_x_0 67 | id: blocks_vector_source_x 68 | parameters: 69 | affinity: '' 70 | alias: '' 71 | comment: '' 72 | maxoutbuf: '0' 73 | minoutbuf: '0' 74 | repeat: 'False' 75 | tags: '[]' 76 | type: byte 77 | vector: ([i+32 for i in range(64)] ) 78 | vlen: '1' 79 | states: 80 | bus_sink: false 81 | bus_source: false 82 | bus_structure: null 83 | coordinate: [256, 364.0] 84 | rotation: 0 85 | state: true 86 | - name: show_text_0 87 | id: show_text 88 | parameters: 89 | affinity: '' 90 | alias: '' 91 | comment: '' 92 | gui_hint: '' 93 | label: Test 94 | states: 95 | bus_sink: false 96 | bus_source: false 97 | bus_structure: null 98 | coordinate: [816, 428.0] 99 | rotation: 0 100 | state: true 101 | 102 | connections: 103 | - [blocks_throttle_0, '0', show_text_0, '0'] 104 | - [blocks_vector_source_x_0, '0', blocks_throttle_0, '0'] 105 | 106 | metadata: 107 | file_format: 1 108 | -------------------------------------------------------------------------------- /examples/TextMessageTest.grc: -------------------------------------------------------------------------------- 1 | options: 2 | parameters: 3 | author: dl1ksv 4 | catch_exceptions: 'True' 5 | category: '[GRC Hier Blocks]' 6 | cmake_opt: '' 7 | comment: '' 8 | copyright: '' 9 | description: '' 10 | gen_cmake: 'On' 11 | gen_linking: dynamic 12 | generate_options: qt_gui 13 | hier_block_src_path: '.:' 14 | id: Messagetext 15 | max_nouts: '0' 16 | output_language: python 17 | placement: (0,0) 18 | qt_qss_theme: '' 19 | realtime_scheduling: '' 20 | run: 'True' 21 | run_command: '{python} -u {filename}' 22 | run_options: prompt 23 | sizing_mode: fixed 24 | thread_safe_setters: '' 25 | title: Test a test message 26 | window_size: (1000,1000) 27 | states: 28 | bus_sink: false 29 | bus_source: false 30 | bus_structure: null 31 | coordinate: [8, 8] 32 | rotation: 0 33 | state: enabled 34 | 35 | blocks: 36 | - name: samp_rate 37 | id: variable 38 | parameters: 39 | comment: '' 40 | value: '32000' 41 | states: 42 | bus_sink: false 43 | bus_source: false 44 | bus_structure: null 45 | coordinate: [184, 12] 46 | rotation: 0 47 | state: enabled 48 | - name: blocks_message_debug_0 49 | id: blocks_message_debug 50 | parameters: 51 | affinity: '' 52 | alias: '' 53 | comment: '' 54 | en_uvec: 'True' 55 | states: 56 | bus_sink: false 57 | bus_source: false 58 | bus_structure: null 59 | coordinate: [1320, 104.0] 60 | rotation: 0 61 | state: true 62 | - name: blocks_message_strobe_0 63 | id: blocks_message_strobe 64 | parameters: 65 | affinity: '' 66 | alias: '' 67 | comment: '' 68 | maxoutbuf: '0' 69 | minoutbuf: '0' 70 | msg: pmt.intern("Gutta cavat lapidem non vi sed saepe cadendo") 71 | period: '1000' 72 | states: 73 | bus_sink: false 74 | bus_source: false 75 | bus_structure: null 76 | coordinate: [824, 272.0] 77 | rotation: 0 78 | state: true 79 | - name: qtgui_display_text_msg_0 80 | id: qtgui_display_text_msg 81 | parameters: 82 | affinity: '' 83 | alias: '' 84 | comment: '' 85 | gui_hint: '' 86 | label: ' "Header"' 87 | messagekey: TEST 88 | splitlength: '42' 89 | states: 90 | bus_sink: false 91 | bus_source: false 92 | bus_structure: null 93 | coordinate: [1072, 412.0] 94 | rotation: 0 95 | state: true 96 | 97 | connections: 98 | - [blocks_message_strobe_0, strobe, blocks_message_debug_0, print] 99 | - [blocks_message_strobe_0, strobe, qtgui_display_text_msg_0, text] 100 | 101 | metadata: 102 | file_format: 1 103 | grc_version: v3.11.0.0git-84-g6963cf5a 104 | -------------------------------------------------------------------------------- /examples/display_text_msg.grc: -------------------------------------------------------------------------------- 1 | options: 2 | parameters: 3 | author: dl1ksv 4 | catch_exceptions: 'True' 5 | category: '[GRC Hier Blocks]' 6 | cmake_opt: '' 7 | comment: '' 8 | copyright: '' 9 | description: '' 10 | gen_cmake: 'On' 11 | gen_linking: dynamic 12 | generate_options: qt_gui 13 | hier_block_src_path: '.:' 14 | id: Messagetext 15 | max_nouts: '0' 16 | output_language: python 17 | placement: (0,0) 18 | qt_qss_theme: '' 19 | realtime_scheduling: '' 20 | run: 'True' 21 | run_command: '{python} -u {filename}' 22 | run_options: prompt 23 | sizing_mode: fixed 24 | thread_safe_setters: '' 25 | title: Display a test message 26 | window_size: (1000,1000) 27 | states: 28 | bus_sink: false 29 | bus_source: false 30 | bus_structure: null 31 | coordinate: [8, 8] 32 | rotation: 0 33 | state: enabled 34 | 35 | blocks: 36 | - name: samp_rate 37 | id: variable 38 | parameters: 39 | comment: '' 40 | value: '32000' 41 | states: 42 | bus_sink: false 43 | bus_source: false 44 | bus_structure: null 45 | coordinate: [184, 12] 46 | rotation: 0 47 | state: enabled 48 | - name: blocks_message_debug_0 49 | id: blocks_message_debug 50 | parameters: 51 | affinity: '' 52 | alias: '' 53 | comment: '' 54 | en_uvec: 'True' 55 | states: 56 | bus_sink: false 57 | bus_source: false 58 | bus_structure: null 59 | coordinate: [1320, 104.0] 60 | rotation: 0 61 | state: enabled 62 | - name: blocks_message_strobe_0 63 | id: blocks_message_strobe 64 | parameters: 65 | affinity: '' 66 | alias: '' 67 | comment: '' 68 | maxoutbuf: '0' 69 | minoutbuf: '0' 70 | msg: pmt.intern('Gutta cavat lapidem non vi sed saepe cadendo manus manum lavat') 71 | period: '1000' 72 | states: 73 | bus_sink: false 74 | bus_source: false 75 | bus_structure: null 76 | coordinate: [704, 236.0] 77 | rotation: 0 78 | state: true 79 | - name: display_text_msg_0 80 | id: display_text_msg 81 | parameters: 82 | affinity: '' 83 | alias: '' 84 | comment: '' 85 | gui_hint: '' 86 | label: ' Received text message' 87 | maxlines: '6' 88 | messagekey: TEXT 89 | splitlength: '42' 90 | states: 91 | bus_sink: false 92 | bus_source: false 93 | bus_structure: null 94 | coordinate: [1200, 276.0] 95 | rotation: 0 96 | state: true 97 | 98 | connections: 99 | - [blocks_message_strobe_0, strobe, blocks_message_debug_0, print] 100 | - [blocks_message_strobe_0, strobe, display_text_msg_0, text] 101 | 102 | metadata: 103 | file_format: 1 104 | grc_version: v3.11-compat-xxx-xunknown 105 | -------------------------------------------------------------------------------- /examples/display_text_sink.grc: -------------------------------------------------------------------------------- 1 | options: 2 | parameters: 3 | author: dl1ksv 4 | catch_exceptions: 'True' 5 | category: '[GRC Hier Blocks]' 6 | cmake_opt: '' 7 | comment: '' 8 | copyright: '' 9 | description: '' 10 | gen_cmake: 'On' 11 | gen_linking: dynamic 12 | generate_options: qt_gui 13 | hier_block_src_path: '.:' 14 | id: display_text 15 | max_nouts: '0' 16 | output_language: python 17 | placement: (0,0) 18 | qt_qss_theme: '' 19 | realtime_scheduling: '' 20 | run: 'True' 21 | run_command: '{python} -u {filename}' 22 | run_options: prompt 23 | sizing_mode: fixed 24 | thread_safe_setters: '' 25 | title: Display text in a window 26 | window_size: (1000,1000) 27 | states: 28 | bus_sink: false 29 | bus_source: false 30 | bus_structure: null 31 | coordinate: [8, 8] 32 | rotation: 0 33 | state: enabled 34 | 35 | blocks: 36 | - name: samp_rate 37 | id: variable 38 | parameters: 39 | comment: '' 40 | value: '32000' 41 | states: 42 | bus_sink: false 43 | bus_source: false 44 | bus_structure: null 45 | coordinate: [184, 12] 46 | rotation: 0 47 | state: enabled 48 | - name: blocks_throttle_0 49 | id: blocks_throttle 50 | parameters: 51 | affinity: '' 52 | alias: '' 53 | comment: '' 54 | ignoretag: 'True' 55 | maxoutbuf: '0' 56 | minoutbuf: '0' 57 | samples_per_second: samp_rate 58 | type: byte 59 | vlen: '1' 60 | states: 61 | bus_sink: false 62 | bus_source: false 63 | bus_structure: null 64 | coordinate: [704, 196.0] 65 | rotation: 0 66 | state: true 67 | - name: blocks_vector_source_x_0 68 | id: blocks_vector_source_x 69 | parameters: 70 | affinity: '' 71 | alias: '' 72 | comment: '' 73 | maxoutbuf: '0' 74 | minoutbuf: '0' 75 | repeat: 'True' 76 | tags: '[]' 77 | type: byte 78 | vector: 3*list("Gutta cavat lapidem non vi sed saepe cadendo\n0123456789\n\n".encode()) 79 | vlen: '1' 80 | states: 81 | bus_sink: false 82 | bus_source: false 83 | bus_structure: null 84 | coordinate: [416, 176.0] 85 | rotation: 0 86 | state: true 87 | - name: show_text_0 88 | id: show_text 89 | parameters: 90 | affinity: '' 91 | alias: '' 92 | comment: '' 93 | gui_hint: '' 94 | label: Text Display 95 | maxlines: '100' 96 | splitlength: '40' 97 | states: 98 | bus_sink: false 99 | bus_source: false 100 | bus_structure: null 101 | coordinate: [968, 180.0] 102 | rotation: 0 103 | state: true 104 | 105 | connections: 106 | - [blocks_throttle_0, '0', show_text_0, '0'] 107 | - [blocks_vector_source_x_0, '0', blocks_throttle_0, '0'] 108 | 109 | metadata: 110 | file_format: 1 111 | grc_version: v3.11.0.0git-215-g0843df86 112 | -------------------------------------------------------------------------------- /gnuradio-display.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/@GR_LIBRARY_DIR@ 4 | includedir=${prefix}/@GR_INCLUDE_DIR@/display 5 | 6 | Name: @CPACK_PACKAGE_NAME@ 7 | Description: @CPACK_PACKAGE_DESCRIPTION_SUMMARY@ 8 | URL: http://github.com/dl1ksv/ 9 | Version: @CPACK_PACKAGE_VERSION@ 10 | Requires: gnuradio >= 3.7 11 | 12 | Requires: gnuradio-runtime 13 | Libs: -L${libdir} -lgnuradio-display 14 | Cflags: -I${includedir} 15 | -------------------------------------------------------------------------------- /grc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-display 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | install(FILES 10 | display_text_msg.block.yml 11 | display_show_image.block.yml 12 | display_show_text.block.yml DESTINATION share/gnuradio/grc/blocks 13 | ) 14 | -------------------------------------------------------------------------------- /grc/display_show_image.block.yml: -------------------------------------------------------------------------------- 1 | id: show_image 2 | label: PNG Image Sink 3 | category: '[DL1KSV]/Display' 4 | 5 | parameters: 6 | 7 | - id: imagewidth 8 | label: Image width 9 | dtype: int 10 | default: 2080 11 | 12 | - id: imageheight 13 | label: Image height 14 | dtype: int 15 | default: 1400 16 | 17 | - id: displaybottomup 18 | label: Display bottom up 19 | dtype: enum 20 | default: 'False' 21 | options: ['True', 'False'] 22 | option_labels: ['Yes', 'No'] 23 | 24 | - id: gui_hint 25 | label: GUI Hint 26 | dtype: gui_hint 27 | hide: part 28 | 29 | inputs: 30 | - domain: stream 31 | label: in 32 | dtype: byte 33 | 34 | - domain: stream 35 | label: ctrl 36 | dtype: byte 37 | 38 | asserts: 39 | - ${imagewidth > 0 } 40 | - ${imageheight > 0} 41 | 42 | templates: 43 | imports: |- 44 | from PyQt5 import Qt 45 | from gnuradio import qtgui 46 | import display 47 | import sip 48 | 49 | make: |- 50 | <% 51 | win = 'self._%s_win'%id 52 | %>\ 53 | display.show_image( ${imagewidth}, ${imageheight} ) 54 | self.${id}.displayBottomUp(${displaybottomup}) 55 | self._${id}_win = sip.wrapinstance(self.${id}.qwidget(), Qt.QWidget) 56 | ${gui_hint() % win} 57 | 58 | documentation: |- 59 | 60 | Image width: The number of pixels per line 61 | Image height: The maximal number of lines of the image. If this number will be overrun, the last line will be overwritten. 62 | Display bottom up: Choose, if the image is painted botton up or top down. ( Usefull for displaying NOAA images ) 63 | 64 | port in: The input stream 65 | port ctrl: The sink starts to display on first non zero byte received on this port. You could feed a squelch value here or a filter sync pulse. 66 | If not needed, just feed the input stream here, too. 67 | 68 | The GUI hint can be used to position the widget within the application. The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. Both the tab specification and the grid position are optional. 69 | file_format: 1 70 | 71 | 72 | -------------------------------------------------------------------------------- /grc/display_show_text.block.yml: -------------------------------------------------------------------------------- 1 | id: show_text 2 | label: Text Sink 3 | category: '[DL1KSV]/Display' 4 | 5 | parameters: 6 | 7 | - id: label 8 | label: Label 9 | dtype: string 10 | - id: splitlength 11 | label: "Maximum line length" 12 | dtype: int 13 | default: 0 14 | - id: maxlines 15 | label: "Maximum of lines" 16 | dtype: int 17 | default: 100 18 | - id: gui_hint 19 | label: GUI Hint 20 | dtype: gui_hint 21 | hide: part 22 | 23 | inputs: 24 | - domain: stream 25 | label: in 26 | dtype: byte 27 | 28 | asserts: 29 | - ${splitlength >= 0} 30 | - ${maxlines >= 2} 31 | 32 | templates: 33 | imports: |- 34 | from PyQt5 import Qt 35 | from gnuradio import qtgui 36 | import display 37 | import sip 38 | 39 | make: |- 40 | <% 41 | win = 'self._%s_win'%id 42 | %>\ 43 | display.show_text(${label}, ${splitlength}, ${maxlines}) 44 | self._${id}_win = sip.wrapinstance(self.${id}.qwidget(), Qt.QWidget) 45 | ${gui_hint() % win} 46 | 47 | documentation: |- 48 | 49 | Label: You can insert a header text. Usefull if you have several text sinks. 50 | Maximum line length: 0 use only nl chars of the input stream to switch to next line. 51 | >0 Switch to next line, if maximum line characters without any nl char were received. 52 | Maximum of lines: Maximal number of lines, that can be displayed in the scroll area. 53 | 54 | The GUI hint can be used to position the widget within the application. The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. Both the tab specification and the grid position are optional. 55 | 56 | file_format: 1 57 | -------------------------------------------------------------------------------- /grc/display_text_msg.block.yml: -------------------------------------------------------------------------------- 1 | id: display_text_msg 2 | label: Display a text message 3 | flags: [ python ] 4 | 5 | category: '[DL1KSV]/Display' 6 | 7 | parameters: 8 | - id: label 9 | label: Label 10 | dtype: string 11 | default: ' ""' 12 | - id: messagekey 13 | label: "Message key" 14 | dtype: string 15 | default: 'text' 16 | - id: splitlength 17 | label: "Maximum line length" 18 | dtype: int 19 | default: 80 20 | - id: maxlines 21 | label: "Maximum of lines" 22 | dtype: int 23 | default: 100 24 | - id: gui_hint 25 | label: GUI Hint 26 | dtype: gui_hint 27 | hide: part 28 | 29 | inputs: 30 | - domain: message 31 | id: text 32 | optional: true 33 | 34 | asserts: 35 | - ${splitlength >= 0} 36 | - ${maxlines >= 2} 37 | 38 | templates: 39 | imports: |- 40 | from PyQt5 import Qt 41 | import display 42 | import sip 43 | make: |- 44 | <% 45 | win = 'self._%s_win'%id 46 | %>\ 47 | display.text_msg(${label}, ${messagekey}, ${splitlength}) 48 | ${win} = sip.wrapinstance(self.${id}.qwidget(), Qt.QWidget) 49 | ${gui_hint() % win} 50 | 51 | documentation: |- 52 | 53 | Label: You can insert a header text. Usefull if you have several text sinks 54 | Message key: The key of the message, may be empty. 55 | Maximum line length: 0 use only nl chars of the input stream to switch to next line. 56 | >0 Switch to next line, if maximum line characters without any nl char were received. 57 | Maximum of lines: Maximal number of lines, that can be displayed in the scroll area. 58 | 59 | The GUI hint can be used to position the widget within the application. The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. Both the tab specification and the grid position are optional. 60 | 61 | file_format: 1 62 | -------------------------------------------------------------------------------- /include/display/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011,2012 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-display 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | ######################################################################## 10 | # Install public header files 11 | ######################################################################## 12 | install(FILES 13 | api.h 14 | display_text_msg.h 15 | show_image.h 16 | show_text.h DESTINATION include/display 17 | ) 18 | -------------------------------------------------------------------------------- /include/display/api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * GNU Radio is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * GNU Radio is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GNU Radio; see the file COPYING. If not, write to 18 | * the Free Software Foundation, Inc., 51 Franklin Street, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | #ifndef INCLUDED_DISPLAY_API_H 23 | #define INCLUDED_DISPLAY_API_H 24 | 25 | #include 26 | 27 | #ifdef gnuradio_display_EXPORTS 28 | # define DISPLAY_API __GR_ATTR_EXPORT 29 | #else 30 | # define DISPLAY_API __GR_ATTR_IMPORT 31 | #endif 32 | 33 | #endif /* INCLUDED_DISPLAY_API_H */ 34 | -------------------------------------------------------------------------------- /include/display/display_text_msg.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2022 Volker Schroer 4 | * 5 | * SPDX-License-Identifier: GPL-3.0-or-later 6 | * 7 | */ 8 | 9 | #ifndef INCLUDED_DISPLAY_TEXT_MSG_H 10 | #define INCLUDED_DISPLAY_TEXT_MSG_H 11 | 12 | #ifdef ENABLE_PYTHON 13 | #pragma push_macro("slots") 14 | #undef slots 15 | #include "Python.h" 16 | #pragma pop_macro("slots") 17 | #endif 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | namespace gr { 27 | namespace display { 28 | 29 | /*! 30 | * \brief Create a QT Text box widget (QLabel) where the values are posted as a message. 31 | * \ingroup display 32 | * 33 | * \details 34 | * This block creates a QT Text box widget that manages data 35 | * through message passing interfaces. It is derived from the 36 | * gnuradio Message Edit Box 37 | * 38 | * Message Ports: 39 | * 40 | * - text (input): 41 | * Accepts text messages to be displayed 42 | * 43 | */ 44 | class DISPLAY_API text_msg : virtual public block 45 | { 46 | public: 47 | typedef std::shared_ptr sptr; 48 | 49 | /*! 50 | * \brief Constructs the Edit box block. 51 | * 52 | * \param label Header text of the window 53 | * usefull if using several windows 54 | * \param message_key name of the message key or empty 55 | * \param splitlength enter newline after splitlength 56 | * characters without newline 57 | * \param maxlines maximum number of lines that 58 | * can be displayed in the scrollarea 59 | * \param parent a QWidget parent in the QT app. 60 | * 61 | */ 62 | static sptr make(const std::string& label, 63 | const std::string& message_key, 64 | int splitlength = 80, 65 | int maxlines = 100, 66 | QWidget* parent = nullptr); 67 | 68 | virtual void exec_() = 0; 69 | virtual QWidget* qwidget() = 0; 70 | }; 71 | 72 | } /* namespace display */ 73 | } /* namespace gr */ 74 | 75 | #endif /* INCLUDED_DISPLAY_TEXT_MSG_H */ 76 | -------------------------------------------------------------------------------- /include/display/show_image.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2022 Volker Schroer, DL1KSV 4 | * 5 | * SPDX-License-Identifier: GPL-3.0-or-later 6 | * 7 | */ 8 | 9 | 10 | #ifndef INCLUDED_DISPLAY_SHOW_IMAGE_H 11 | #define INCLUDED_DISPLAY_SHOW_IMAGE_H 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | class ShowPngPicture; 19 | 20 | namespace gr { 21 | namespace display { 22 | 23 | /*! 24 | * \brief display a grayscaled ( png ) image 25 | * \ingroup display 26 | * 27 | * \details 28 | * This block displays an grayscaled image in a 29 | * scrollable window 30 | * The image may be saved as png image to the filesystem 31 | * 32 | */ 33 | class DISPLAY_API show_image : virtual public sync_block 34 | { 35 | public: 36 | typedef std::shared_ptr sptr; 37 | 38 | /*! 39 | * \brief Build an image sink 40 | * 41 | * \param imagewidth Width of the image 42 | * \param imageheight Maximum height of image 43 | * \param parent a QWidget parent widget, may be nullptr 44 | * 45 | */ 46 | static sptr make(int imagewidth, int imageheight, QWidget* parent = nullptr); 47 | 48 | virtual void exec_() = 0; 49 | virtual QWidget* qwidget() = 0; 50 | 51 | virtual void displayBottomUp(bool direction) = 0; 52 | }; 53 | 54 | } // namespace display 55 | } // namespace gr 56 | 57 | #endif /* INCLUDED_DISPLAY_SHOW_IMAGE_H */ 58 | -------------------------------------------------------------------------------- /include/display/show_text.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2022 Volker Schroer, DL1KSV 4 | * 5 | * SPDX-License-Identifier: GPL-3.0-or-later 6 | * 7 | */ 8 | 9 | #ifndef INCLUDED_DISPLAY_SHOW_TEXT_H 10 | #define INCLUDED_DISPLAY_SHOW_TEXT_H 11 | 12 | #ifdef ENABLE_PYTHON 13 | #pragma push_macro("slots") 14 | #undef slots 15 | #include "Python.h" 16 | #pragma pop_macro("slots") 17 | #endif 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #include 25 | 26 | // class QApplication; 27 | 28 | namespace gr { 29 | namespace display { 30 | 31 | /*! 32 | * \brief Create a QT Text sink, where the values are received as stream. 33 | * \ingroup display 34 | * 35 | * \details 36 | * This is a QT-based graphical sink that display simply ascii text in a scrollable 37 | * window 38 | */ 39 | class DISPLAY_API show_text : virtual public sync_block 40 | { 41 | public: 42 | typedef std::shared_ptr sptr; 43 | 44 | /*! 45 | * \brief Build a graphical sink to display ascii text 46 | * 47 | * \param label Header text of the window 48 | * usefull if using several windows 49 | * \param splitlength enter newline after splitlength 50 | * characters without newline 51 | * \param maxlines maximum number of lines that 52 | * can be displayed in the scrollarea 53 | * \param parent a QWidget parent in the QT app. 54 | */ 55 | static sptr make(const std::string& label, 56 | int splitlength = 80, 57 | int maxlines = 100, 58 | QWidget* parent = nullptr); 59 | virtual QWidget* qwidget() = 0; 60 | virtual void exec_() = 0; 61 | }; 62 | 63 | } // namespace display 64 | } // namespace gr 65 | 66 | #endif /* INCLUDED_DISPLAY_SHOW_TEXT_H */ 67 | -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011,2012,2016,2018,2019 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-display 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | ######################################################################## 10 | # Setup library 11 | ######################################################################## 12 | include(GrPlatform) #define LIB_SUFFIX 13 | include(GrMiscUtils) 14 | include(GrPython) 15 | 16 | 17 | ######################################################################## 18 | # Set QT generation stuff 19 | ######################################################################## 20 | set(display_moc_hdrs 21 | showpngpicture.h 22 | show_text_window.h 23 | ) 24 | 25 | QT5_WRAP_CPP(display_moc_srcs ${display_moc_hdrs}) 26 | QT5_WRAP_UI(display_ui_hdrs showpngpicture.ui) 27 | 28 | list(APPEND display_sources 29 | ${display_moc_srcs} 30 | ${display_ui_hdrs} 31 | show_image_impl.cc 32 | showpngpicture.cc 33 | show_text_impl.cc 34 | show_text_window.cc 35 | display_text_msg_impl.cc 36 | ) 37 | 38 | set(display_sources "${display_sources}" PARENT_SCOPE) 39 | if(NOT display_sources) 40 | MESSAGE(STATUS "No C++ sources... skipping lib/") 41 | return() 42 | endif(NOT display_sources) 43 | 44 | add_library(gnuradio-display SHARED ${display_sources}) 45 | target_link_libraries(gnuradio-display PUBLIC 46 | gnuradio::gnuradio-runtime 47 | gnuradio::gnuradio-blocks 48 | Qt5::Widgets 49 | Python::Python) 50 | target_include_directories(gnuradio-display 51 | PUBLIC $ 52 | PUBLIC $ 53 | PRIVATE 54 | ${CMAKE_CURRENT_BINARY_DIR} 55 | ) 56 | set_target_properties(gnuradio-display PROPERTIES DEFINE_SYMBOL "gnuradio_display_EXPORTS") 57 | 58 | if(APPLE) 59 | set_target_properties(gnuradio-display PROPERTIES 60 | INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib" 61 | ) 62 | endif(APPLE) 63 | 64 | ######################################################################## 65 | # Install built library files 66 | ######################################################################## 67 | include(GrMiscUtils) 68 | GR_LIBRARY_FOO(gnuradio-display) 69 | 70 | ######################################################################## 71 | # Print summary 72 | ######################################################################## 73 | message(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}") 74 | message(STATUS "Building for version: ${VERSION} / ${LIBVER}") 75 | 76 | ######################################################################## 77 | # Build and register unit test 78 | ######################################################################## 79 | include(GrTest) 80 | 81 | # If your unit tests require special include paths, add them here 82 | #include_directories() 83 | # List all files that contain Boost.UTF unit tests here 84 | list(APPEND test_display_sources 85 | qa_show_text.cc 86 | qa_show_image.cc 87 | qa_display_text_msg.cc 88 | ) 89 | # Anything we need to link to for the unit tests go here 90 | list(APPEND GR_TEST_TARGET_DEPS gnuradio-display) 91 | 92 | if(NOT test_display_sources) 93 | MESSAGE(STATUS "No C++ unit tests... skipping") 94 | return() 95 | endif(NOT test_display_sources) 96 | 97 | foreach(qa_file ${test_display_sources}) 98 | GR_ADD_CPP_TEST("display_${qa_file}" 99 | ${CMAKE_CURRENT_SOURCE_DIR}/${qa_file} 100 | ) 101 | endforeach(qa_file) 102 | -------------------------------------------------------------------------------- /lib/display_text_msg_impl.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2016 Free Software Foundation, Inc. 4 | * 5 | * This file is part of GNU Radio 6 | * 7 | * GNU Radio is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3, or (at your option) 10 | * any later version. 11 | * 12 | * GNU Radio is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with GNU Radio; see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, 20 | * Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #ifdef HAVE_CONFIG_H 24 | #include "config.h" 25 | #endif 26 | 27 | #include "display_text_msg_impl.h" 28 | 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | namespace gr { 35 | namespace display { 36 | 37 | text_msg::sptr text_msg::make(const std::string& label, 38 | const std::string& message_key, 39 | int splitlength, 40 | int maxlines, 41 | QWidget* parent) 42 | { 43 | return gnuradio::make_block_sptr( 44 | label, message_key, splitlength, maxlines, parent); 45 | } 46 | 47 | text_msg_impl::text_msg_impl(const std::string& label, 48 | const std::string& message_key, 49 | int splitlength, 50 | int maxlines, 51 | QWidget* parent) 52 | : block("text_msg", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)) 53 | { 54 | // Required now for Qt; argc must be greater than 0 and argv 55 | // must have at least one valid character. Must be valid through 56 | // life of the qApplication: 57 | // http://harmattan-dev.nokia.com/docs/library/html/qt4/qapplication.html 58 | d_argc = 1; 59 | d_argv = new char; 60 | d_argv[0] = '\0'; 61 | 62 | if (qApp != nullptr) { 63 | d_qApplication = qApp; 64 | } else { 65 | d_qApplication = new QApplication(d_argc, &d_argv); 66 | } 67 | 68 | d_text = new show_text_window(splitlength, maxlines, parent); 69 | d_text->setHeader(QString(label.c_str())); 70 | if (message_key.empty()) 71 | d_message_key = pmt::PMT_NIL; 72 | else 73 | d_message_key = pmt::string_to_symbol(message_key); 74 | d_splitlength = splitlength; 75 | message_port_register_in(pmt::mp("text")); 76 | set_msg_handler(pmt::mp("text"), 77 | [this](pmt::pmt_t msg) { this->text_msg_impl::set_value(msg); }); 78 | } 79 | 80 | text_msg_impl::~text_msg_impl() { delete d_argv; } 81 | 82 | 83 | void text_msg_impl::exec_() { d_qApplication->exec(); } 84 | 85 | QWidget* text_msg_impl::qwidget() { return (QWidget*)d_text; } 86 | 87 | #ifdef ENABLE_PYTHON 88 | PyObject* text_msg_impl::pyqwidget() 89 | { 90 | PyObject* w = PyLong_FromVoidPtr((void*)d_text); 91 | PyObject* retarg = Py_BuildValue("N", w); 92 | return retarg; 93 | } 94 | #else 95 | void* text_msg_impl::pyqwidget() { return nullptr; } 96 | #endif 97 | void text_msg_impl::set_value(pmt::pmt_t val) 98 | { 99 | 100 | std::string xs; 101 | 102 | if (pmt::is_pair(val)) { // Check, if we received a pair 103 | pmt::pmt_t key = pmt::car(val); 104 | if (pmt::eq(key, d_message_key)) { 105 | pmt::pmt_t msg = pmt::cdr(val); 106 | if (pmt::is_symbol(msg)) { 107 | xs = pmt::symbol_to_string(msg); 108 | } else { 109 | if (pmt::is_u8vector(msg)) { 110 | size_t len; 111 | const uint8_t* c = pmt::u8vector_elements(msg, len); 112 | d_logger->warn("Found a vector of length = {:d} ", len); 113 | for (size_t i = 0; i < len; i++) { 114 | xs += c[i]; 115 | if (c[i] == '\n') 116 | d_logger->warn("Newline found at {:d}", i); 117 | } 118 | xs += '\n'; 119 | } else { 120 | d_logger->warn( 121 | "Message pair did not contain a valid text message or vector"); 122 | return; 123 | } 124 | } 125 | } else { 126 | d_logger->warn("Message must have the key = {:s} ; got {:s}.", 127 | pmt::write_string(d_message_key), 128 | pmt::write_string(key)); 129 | return; 130 | } 131 | } else { 132 | if (pmt::is_symbol(val)) { 133 | xs = pmt::symbol_to_string(val); 134 | } else { 135 | d_logger->warn("Did not find a valid message"); 136 | return; 137 | } 138 | } 139 | if (d_splitlength <= 0) // Do not split 140 | d_text->set_text(xs.c_str(), xs.size()); 141 | else { 142 | std::string::size_type length = xs.size(); 143 | std::string::size_type idx; 144 | std::string::size_type pos; 145 | std::string sub; 146 | 147 | for (pos = 0; pos < length;) { 148 | sub = xs.substr(pos, d_splitlength); 149 | idx = sub.find('\n'); 150 | if (idx == std::string::npos) // NL not found ! 151 | { 152 | sub.append("\n"); 153 | d_text->set_text(sub.c_str(), sub.size()); 154 | pos += d_splitlength; 155 | } else // NL found at idx 156 | { 157 | d_text->set_text(sub.substr(0, idx).c_str(), idx + 1); 158 | pos += idx + 1; 159 | } 160 | } 161 | } 162 | } 163 | 164 | 165 | } // namespace display 166 | } /* namespace gr */ 167 | -------------------------------------------------------------------------------- /lib/display_text_msg_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2016 Free Software Foundation, Inc. 4 | * 5 | * This file is part of GNU Radio 6 | * 7 | * GNU Radio is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3, or (at your option) 10 | * any later version. 11 | * 12 | * GNU Radio is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with GNU Radio; see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, 20 | * Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #ifndef INCLUDED_DISPLAY_TEXT_MSG_IMPL_H 24 | #define INCLUDED_DISPLAY_TEXT_MSG_IMPL_H 25 | 26 | #include "show_text_window.h" 27 | #include 28 | #include 29 | 30 | namespace gr { 31 | namespace display { 32 | 33 | class DISPLAY_API text_msg_impl : public text_msg 34 | { 35 | 36 | public: 37 | text_msg_impl(const std::string& label, 38 | const std::string& message_key, 39 | int splitlength, 40 | int maxlines, 41 | QWidget* parent); 42 | ~text_msg_impl(); 43 | 44 | void exec_(); 45 | QApplication* d_qApplication; 46 | QWidget* qwidget(); 47 | 48 | PyObject* pyqwidget(); 49 | 50 | void set_value(pmt::pmt_t val); 51 | 52 | private: 53 | int d_argc; 54 | char* d_argv; 55 | show_text_window* d_text; 56 | int d_splitlength; 57 | pmt::pmt_t d_message_key; 58 | }; 59 | 60 | } // namespace display 61 | } /* namespace gr */ 62 | 63 | #endif /* INCLUDED_DISPLAY_TEXT_MSG_IMPL_H */ 64 | -------------------------------------------------------------------------------- /lib/qa_display_text_msg.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2020 dl1ksv. 4 | * 5 | * SPDX-License-Identifier: GPL-3.0-or-later 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace gr { 13 | namespace display { 14 | 15 | BOOST_AUTO_TEST_CASE(test_display_text_msg_replace_with_specific_test_name) 16 | { 17 | // Put test here 18 | } 19 | 20 | } /* namespace display */ 21 | } /* namespace gr */ 22 | -------------------------------------------------------------------------------- /lib/qa_show_image.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2020 dl1ksv. 4 | * 5 | * SPDX-License-Identifier: GPL-3.0-or-later 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace gr { 13 | namespace display { 14 | 15 | BOOST_AUTO_TEST_CASE(test_show_image_replace_with_specific_test_name) 16 | { 17 | // Put test here 18 | } 19 | 20 | } /* namespace display */ 21 | } /* namespace gr */ 22 | -------------------------------------------------------------------------------- /lib/qa_show_text.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2020 dl1ksv. 4 | * 5 | * SPDX-License-Identifier: GPL-3.0-or-later 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace gr { 13 | namespace display { 14 | 15 | BOOST_AUTO_TEST_CASE(test_show_text_replace_with_specific_test_name) 16 | { 17 | // Put test here 18 | } 19 | 20 | } /* namespace display */ 21 | } /* namespace gr */ 22 | -------------------------------------------------------------------------------- /lib/show_image_impl.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2013 <+YOU OR YOUR COMPANY+>. 4 | * 5 | * This is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3, or (at your option) 8 | * any later version. 9 | * 10 | * This software is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this software; see the file COPYING. If not, write to 17 | * the Free Software Foundation, Inc., 51 Franklin Street, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #ifdef HAVE_CONFIG_H 22 | #include "config.h" 23 | #endif 24 | 25 | 26 | #include "show_image_impl.h" 27 | #include "showpngpicture.h" 28 | #include 29 | 30 | namespace gr { 31 | namespace display { 32 | 33 | show_image::sptr show_image::make(int imagewidth, int imageheight, QWidget* parent) 34 | { 35 | return gnuradio::get_initial_sptr( 36 | new show_image_impl(imagewidth, imageheight, parent)); 37 | } 38 | 39 | /* 40 | * The private constructor 41 | */ 42 | show_image_impl::show_image_impl(int imagewidth, int imageheight, QWidget* parent) 43 | : gr::sync_block("show_image", 44 | gr::io_signature::make(2, 2, sizeof(char)), 45 | gr::io_signature::make(0, 0, 0)), 46 | d_width(imagewidth), 47 | d_height(imageheight), 48 | d_parent(parent) 49 | { 50 | d_main_gui = NULL; 51 | if (qApp != NULL) { 52 | d_qApplication = qApp; 53 | } else { 54 | int argc = 1; 55 | char* argv = new char; 56 | argv[0] = '\0'; 57 | d_qApplication = new QApplication(argc, &argv); 58 | } 59 | d_main_gui = new ShowPngPicture(d_width, d_height, d_parent); 60 | d_triggered = false; 61 | } 62 | 63 | /* 64 | * Our virtual destructor. 65 | */ 66 | show_image_impl::~show_image_impl() {} 67 | 68 | int show_image_impl::work(int noutput_items, 69 | gr_vector_const_void_star& input_items, 70 | gr_vector_void_star& output_items) 71 | { 72 | const unsigned char* in = (const unsigned char*)input_items[0]; 73 | const char* ctrl = (const char*)input_items[1]; 74 | 75 | gr::thread::scoped_lock lock(d_setlock); 76 | 77 | if (d_triggered) { 78 | // Do signal processing 79 | d_main_gui->setPixel(in, noutput_items); 80 | } else { 81 | int i = 0; 82 | while (i < noutput_items && ctrl[i] == 0) { 83 | i++; 84 | } 85 | if (i < noutput_items) { 86 | d_triggered = true; 87 | d_main_gui->setPixel(in + i, noutput_items - i); 88 | } 89 | } 90 | // Tell runtime system how many output items we produced. 91 | return noutput_items; 92 | } 93 | 94 | void show_image_impl::displayBottomUp(bool direction) 95 | { 96 | d_main_gui->presetBottomUp(direction); 97 | } 98 | 99 | QWidget* show_image_impl::qwidget() { return d_main_gui; } 100 | 101 | void show_image_impl::exec_() { d_qApplication->exec(); } 102 | 103 | } /* namespace display */ 104 | } /* namespace gr */ 105 | -------------------------------------------------------------------------------- /lib/show_image_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2013 <+YOU OR YOUR COMPANY+>. 4 | * 5 | * This is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3, or (at your option) 8 | * any later version. 9 | * 10 | * This software is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this software; see the file COPYING. If not, write to 17 | * the Free Software Foundation, Inc., 51 Franklin Street, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #ifndef INCLUDED_DISPLAY_SHOW_IMAGE_IMPL_H 22 | #define INCLUDED_DISPLAY_SHOW_IMAGE_IMPL_H 23 | 24 | #include 25 | 26 | #include 27 | 28 | namespace gr { 29 | namespace display { 30 | 31 | class DISPLAY_API show_image_impl : public show_image 32 | { 33 | private: 34 | /* Variables */ 35 | 36 | int nx_samples; 37 | int d_width; 38 | int d_height; 39 | QWidget* d_parent; 40 | 41 | bool d_triggered; 42 | ShowPngPicture* d_main_gui; 43 | 44 | 45 | public: 46 | show_image_impl(int imagewidth, int imageheight, QWidget* parent); 47 | ~show_image_impl(); 48 | 49 | void displayBottomUp(bool direction); 50 | 51 | QApplication* d_qApplication; 52 | 53 | void exec_() override; 54 | QWidget* qwidget() override; 55 | 56 | // Where all the action really happens 57 | int work(int noutput_items, 58 | gr_vector_const_void_star& input_items, 59 | gr_vector_void_star& output_items); 60 | }; 61 | 62 | } // namespace display 63 | } // namespace gr 64 | 65 | #endif /* INCLUDED_DISPLAY_SHOW-IMAGE_IMPL_H */ 66 | -------------------------------------------------------------------------------- /lib/show_text_impl.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2013 Volker Schroer, DL1KSV. 4 | * 5 | * This is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3, or (at your option) 8 | * any later version. 9 | * 10 | * This software is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this software; see the file COPYING. If not, write to 17 | * the Free Software Foundation, Inc., 51 Franklin Street, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #ifdef HAVE_CONFIG_H 22 | #include "config.h" 23 | #endif 24 | 25 | 26 | #include "show_text_impl.h" 27 | #include "show_text_window.h" 28 | #include 29 | 30 | 31 | #include 32 | 33 | namespace gr { 34 | namespace display { 35 | 36 | show_text::sptr 37 | show_text::make(const std::string& label, int splitlength, int maxlines, QWidget* parent) 38 | { 39 | return gnuradio::make_block_sptr( 40 | label, splitlength, maxlines, parent); 41 | } 42 | 43 | /* 44 | * The private constructor 45 | */ 46 | show_text_impl::show_text_impl(const std::string& label, 47 | int splitlength, 48 | int maxlines, 49 | QWidget* parent) 50 | : gr::sync_block("show_text", 51 | gr::io_signature::make(1, 1, sizeof(char)), 52 | gr::io_signature::make(0, 0, 0)), 53 | d_splitlength(splitlength), 54 | d_parent(parent) 55 | { 56 | d_main_gui = nullptr; 57 | d_argv = nullptr; 58 | if (qApp != nullptr) { 59 | d_qApplication = qApp; 60 | } else { 61 | int argc = 1; 62 | d_argv = new char; 63 | d_argv[0] = '\0'; 64 | 65 | d_qApplication = new QApplication(argc, &d_argv); 66 | } 67 | d_main_gui = new show_text_window(d_splitlength, maxlines, d_parent); 68 | d_main_gui->setHeader(QString(label.c_str())); 69 | } 70 | 71 | /* 72 | * Our virtual destructor. 73 | */ 74 | show_text_impl::~show_text_impl() 75 | { 76 | if (d_argv != nullptr) 77 | delete d_argv; 78 | } 79 | 80 | int show_text_impl::work(int noutput_items, 81 | gr_vector_const_void_star& input_items, 82 | gr_vector_void_star& output_items) 83 | { 84 | const char* in = (const char*)input_items[0]; 85 | 86 | gr::thread::scoped_lock lock(d_setlock); 87 | 88 | // Tell runtime system how many output items we produced. 89 | d_main_gui->set_text(in, noutput_items); 90 | return noutput_items; 91 | } 92 | 93 | void show_text_impl::exec_() { d_qApplication->exec(); } 94 | 95 | QWidget* show_text_impl::qwidget() { return d_main_gui; } 96 | 97 | } /* namespace display */ 98 | } /* namespace gr */ 99 | -------------------------------------------------------------------------------- /lib/show_text_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2013 Volker Schroer, DL1KSV. 4 | * 5 | * This is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3, or (at your option) 8 | * any later version. 9 | * 10 | * This software is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this software; see the file COPYING. If not, write to 17 | * the Free Software Foundation, Inc., 51 Franklin Street, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | #ifndef INCLUDED_DISPLAY_SHOW_TEXT_IMPL_H 21 | #define INCLUDED_DISPLAY_SHOW_TEXT_IMPL_H 22 | 23 | #include 24 | #include 25 | 26 | class show_text_window; 27 | 28 | namespace gr { 29 | namespace display { 30 | 31 | class show_text_impl : public show_text 32 | { 33 | private: 34 | int d_splitlength; 35 | QWidget* d_parent; 36 | show_text_window* d_main_gui; 37 | char* d_argv; 38 | 39 | public: 40 | show_text_impl(const std::string& label, 41 | int splitlength, 42 | int maxlines, 43 | QWidget* parent); 44 | ~show_text_impl(); 45 | 46 | QApplication* d_qApplication; 47 | 48 | void exec_() override; 49 | QWidget* qwidget() override; 50 | 51 | // Where all the action really happens 52 | int work(int noutput_items, 53 | gr_vector_const_void_star& input_items, 54 | gr_vector_void_star& output_items); 55 | }; 56 | 57 | } // namespace display 58 | } // namespace gr 59 | 60 | #endif /* INCLUDED_DISPLAY_SHOW_TEXT_IMPL_H */ 61 | -------------------------------------------------------------------------------- /lib/show_text_window.cc: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2022 by Volker Schroer, DL1KSV * 3 | * * 4 | * This program is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU General Public License as published by * 6 | * the Free Software Foundation; either version 2 of the License, or * 7 | * (at your option) any later version. * 8 | * * 9 | * This program is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 12 | * GNU General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | 20 | #include "show_text_window.h" 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | 29 | show_text_window::show_text_window(int splitlength, int maxlines, QWidget* parent) 30 | : QWidget(parent) 31 | { 32 | /** Build gui */ 33 | // Header text 34 | d_vertical_layout = new QVBoxLayout(this); 35 | d_label = new QLabel(this); 36 | d_label->setText(""); 37 | 38 | d_vertical_layout->addWidget(d_label); 39 | 40 | // Scroll Area 41 | d_display_area = new QScrollArea(this); 42 | 43 | d_display_area->setLineWidth(3); 44 | d_display_area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); 45 | d_display_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); 46 | d_display_area->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); 47 | d_display_area->setWidgetResizable(true); 48 | d_display_area->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignTop); 49 | 50 | d_vertical_layout->addWidget(d_display_area); 51 | 52 | d_d_display_box = new QWidget(); 53 | d_display_area->setWidget(d_d_display_box); 54 | d_lines_layout = new QVBoxLayout(d_d_display_box); 55 | d_lines_layout->setSpacing(0); 56 | d_lines_layout->setContentsMargins(0, 0, 0, 0); 57 | 58 | d_horizontal_layout = new QHBoxLayout(); 59 | d_clear = new QPushButton(QString("Clear"), this); 60 | 61 | d_horizontal_layout->addWidget(d_clear); 62 | 63 | d_horizontal_spacer = 64 | new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); 65 | 66 | d_horizontal_layout->addItem(d_horizontal_spacer); 67 | 68 | d_auto_focus = new QRadioButton(QString("Auto Focus"), this); 69 | 70 | d_auto_focus->setChecked(true); 71 | 72 | d_horizontal_layout->addWidget(d_auto_focus); 73 | 74 | d_horizontal_spacer_2 = 75 | new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); 76 | 77 | d_horizontal_layout->addItem(d_horizontal_spacer_2); 78 | 79 | d_save = new QPushButton(QString("Save text to file"), this); 80 | 81 | 82 | d_horizontal_layout->addWidget(d_save); 83 | 84 | 85 | d_vertical_layout->addLayout(d_horizontal_layout); 86 | 87 | connect(d_clear, SIGNAL(clicked()), this, SLOT(clearText())); 88 | connect(d_save, SIGNAL(clicked()), this, SLOT(text2File())); 89 | connect(d_auto_focus, SIGNAL(toggled(bool)), this, SLOT(autofocus_enable(bool))); 90 | 91 | d_splitlength = splitlength; 92 | d_maxlines = maxlines; 93 | d_linecount = 0; 94 | d_line_to_be_continued = false; 95 | 96 | d_lines = new QLabel*[maxlines]; 97 | d_autofocus = true; 98 | d_auto_focus->setChecked(d_autofocus); 99 | 100 | // Setup lines 101 | for (unsigned int i = 0; i < d_maxlines; i++) { 102 | d_lines[i] = new QLabel(d_d_display_box); 103 | d_lines_layout->addWidget(d_lines[i]); 104 | } 105 | } 106 | 107 | void show_text_window::set_text(const char* c, int count) 108 | { 109 | if (count == 0) { 110 | return; 111 | } 112 | 113 | d_line = QString::fromLatin1(c, count); 114 | if (d_line_to_be_continued) 115 | d_line.prepend(d_lines[d_linecount]->text()); 116 | if (d_splitlength <= 0) 117 | move_input2lines(); 118 | else { 119 | int nl_pos = d_line.indexOf(QChar('\n'), 0); 120 | if (nl_pos < 0) { // No newline found 121 | insert_nl_into_line(0); 122 | } else { 123 | int prev_pos = 0; 124 | while (nl_pos > 0) { 125 | if ((nl_pos - prev_pos) > d_splitlength) { 126 | // add additional nls 127 | prev_pos = prev_pos + d_splitlength; 128 | d_line.insert(prev_pos, QChar('\n')); 129 | // line_length++; 130 | prev_pos++; 131 | } else { 132 | prev_pos = nl_pos + 1; 133 | } 134 | nl_pos = d_line.indexOf(QChar('\n'), prev_pos); 135 | } 136 | 137 | if (prev_pos < d_line.length()) 138 | insert_nl_into_line(prev_pos + 1); 139 | } 140 | move_input2lines(); 141 | } 142 | 143 | if (d_autofocus && (d_linecount > 2)) { 144 | d_display_area->ensureWidgetVisible(d_lines[d_linecount], 50, 5); 145 | } 146 | 147 | update(); 148 | } 149 | void show_text_window::text2File() 150 | { 151 | QString file_name; 152 | QString dir = QDir::homePath(); 153 | 154 | file_name = QFileDialog::getSaveFileName(0, tr("Save Text"), dir, "*.txt"); 155 | if (!file_name.isEmpty()) { 156 | QFile file(file_name); 157 | if (file.open(QIODevice::WriteOnly)) { 158 | QTextStream stream(&file); 159 | for (unsigned int i; i < d_linecount; i++) 160 | stream << d_lines[i]->text() << '\n'; 161 | QMessageBox::information( 162 | 0, "gr-display", QString("Text saved to file: ") + file_name); 163 | } 164 | } 165 | } 166 | void show_text_window::setHeader(QString header) 167 | { 168 | if (header.isEmpty()) 169 | d_label->hide(); 170 | else { 171 | d_label->setText(header); 172 | d_label->show(); 173 | } 174 | } 175 | void show_text_window::clearText() 176 | { 177 | d_linecount = 0; 178 | for (unsigned int i = 0; i < d_maxlines; i++) 179 | d_lines[i]->clear(); 180 | } 181 | 182 | void show_text_window::autofocus_enable(bool b) { d_autofocus = b; } 183 | 184 | void show_text_window::insert_nl_into_line(int from) 185 | { 186 | int length = d_line.length(); 187 | if ((length - from) >= d_splitlength) // Must insert nl 188 | { 189 | int pos = from + d_splitlength; 190 | d_line.insert(pos, QChar('\n')); 191 | pos++; 192 | length++; 193 | while ((length - pos) >= d_splitlength) { 194 | pos += d_splitlength; 195 | d_line.insert(pos, QChar('\n')); 196 | length++; 197 | pos++; 198 | } 199 | // d_remaining_chars = length - pos; 200 | } // else 201 | // d_remaining_chars += length - from; 202 | } 203 | void show_text_window::move_input2lines() 204 | { 205 | QStringList lines = d_line.split('\n'); 206 | if (d_line.endsWith(QChar('\n'))) { 207 | lines.removeLast(); 208 | d_line_to_be_continued = false; 209 | } else 210 | d_line_to_be_continued = true; 211 | // Check, if there are enough free lines 212 | if ((lines.size() + d_linecount) >= 213 | d_maxlines) { // Actual lines + new lines overrun display buffer 214 | if ((unsigned int)lines.size() >= 215 | d_maxlines) { // There are even more lines than the display buffer can take 216 | // So remove those lines that would disappear at once. 217 | unsigned int remove = lines.size() - d_maxlines; 218 | for (unsigned int i = 0; i <= remove; i++) 219 | lines.removeFirst(); 220 | d_linecount = 0; 221 | 222 | // FIXME: add a statusbar and insert a warning, 223 | // that the number of lines to be displayed 224 | // should be increased 225 | } else { 226 | scroll_up(lines.size() + d_linecount - d_maxlines, false); 227 | } 228 | } 229 | for (int i = 0; i < lines.size(); i++) { 230 | d_lines[d_linecount]->setText(lines.at(i)); 231 | d_linecount++; 232 | if (d_linecount >= d_maxlines) { 233 | scroll_up(d_maxlines / 2, true); 234 | } 235 | } 236 | 237 | if (d_line_to_be_continued) { 238 | d_linecount--; 239 | } 240 | } 241 | void show_text_window::scroll_up(unsigned int rows, bool clear) 242 | { 243 | if (rows <= 0) 244 | return; 245 | 246 | for (unsigned int i = rows; i < d_maxlines; i++) 247 | d_lines[i - rows]->setText(d_lines[i]->text()); 248 | d_linecount -= rows; 249 | if (!clear) { 250 | return; 251 | } 252 | for (unsigned int i = d_maxlines - rows; i < d_maxlines; i++) 253 | d_lines[i]->clear(); 254 | } 255 | -------------------------------------------------------------------------------- /lib/show_text_window.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2022 by Volker Schroer, DL1KSV * 3 | * * 4 | * This program is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU General Public License as published by * 6 | * the Free Software Foundation; either version 2 of the License, or * 7 | * (at your option) any later version. * 8 | * * 9 | * This program is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 12 | * GNU General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | 20 | #ifndef SHOW_TEXT_WINDOWS_H 21 | #define SHOW_TEXT_WINDOWS_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | 33 | class show_text_window : public QWidget 34 | { 35 | Q_OBJECT 36 | 37 | public: 38 | explicit show_text_window(int splitlength, int maxlines, QWidget* parent = 0); 39 | void set_text(const char* c, int count); 40 | void setHeader(QString header); 41 | 42 | private: 43 | QVBoxLayout* d_vertical_layout; 44 | QLabel* d_label; 45 | QScrollArea* d_display_area; 46 | QHBoxLayout* d_horizontal_layout; 47 | QPushButton* d_clear; 48 | QSpacerItem* d_horizontal_spacer; 49 | QRadioButton* d_auto_focus; 50 | QSpacerItem* d_horizontal_spacer_2; 51 | QPushButton* d_save; 52 | QVBoxLayout* d_lines_layout; 53 | 54 | QString d_line; 55 | 56 | int d_splitlength; 57 | unsigned int d_linecount; 58 | unsigned int d_maxlines; 59 | bool d_line_to_be_continued; 60 | 61 | QWidget* d_d_display_box; 62 | QLabel** d_lines; 63 | bool d_autofocus; 64 | void insert_nl_into_line(int from); 65 | void move_input2lines(); 66 | void scroll_up(unsigned int rows, bool d_clear); 67 | 68 | private slots: 69 | void text2File(); 70 | void clearText(); 71 | void autofocus_enable(bool); 72 | }; 73 | 74 | #endif // SHOW_TEXT_WINDOWS_H 75 | -------------------------------------------------------------------------------- /lib/showpngpicture.cc: -------------------------------------------------------------------------------- 1 | #include "showpngpicture.h" 2 | #include "ui_showpngpicture.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | ShowPngPicture::ShowPngPicture(int width, int height, QWidget* parent) 11 | : QWidget(parent), ui(new Ui::ShowPngPicture) 12 | { 13 | ui->setupUi(this); 14 | picWidth = width; 15 | picHeight = height; 16 | 17 | ui->displayWidget->setFixedSize(picWidth + 20, picHeight + 20); 18 | 19 | p = new QImage(picWidth, picHeight, QImage::Format_RGB32); 20 | p->fill(64); 21 | row = 0; 22 | col = 0; 23 | line = (QRgb*)p->scanLine(row); 24 | reverseOrder = false; 25 | 26 | // displayTimer = new QTimer(this); 27 | // connect(displayTimer, SIGNAL(timeout()),this,SLOT(update())); 28 | connect(ui->saveButton, SIGNAL(clicked()), this, SLOT(saveImage2File())); 29 | connect(ui->reverse, SIGNAL(clicked(bool)), this, SLOT(storeReverse(bool))); 30 | // displayTimer->start(500); 31 | } 32 | 33 | ShowPngPicture::~ShowPngPicture() { delete ui; } 34 | 35 | void ShowPngPicture::setPixel(const unsigned char* c, int items) 36 | { 37 | int j; 38 | for (int i = 0; i < items; i++) { 39 | j = c[i]; 40 | setNextPixel(j); 41 | } 42 | } 43 | void ShowPngPicture::saveImage2File() 44 | { 45 | QString fileName; 46 | QString dir; 47 | bool ok; 48 | dir = QDir::homePath(); 49 | 50 | fileName = QFileDialog::getSaveFileName(0, tr("Save Image"), dir, "*.png"); 51 | if (!fileName.isEmpty()) { 52 | ok = saveImage(fileName); 53 | if (ok) { 54 | QMessageBox::information( 55 | 0, "gr-display", QString("Image saved to file: ") + fileName); 56 | } 57 | } 58 | } 59 | 60 | void ShowPngPicture::setNextPixel(int i) 61 | { 62 | 63 | line[col] = qRgb(i, i, i); 64 | if (!reverseOrder) { 65 | col++; 66 | if (col >= picWidth) { 67 | col = 0; 68 | row++; 69 | if (row >= picHeight) 70 | row = picHeight - 1; // Later scroll up 71 | line = (QRgb*)p->scanLine(row); 72 | update(); 73 | } 74 | } else { 75 | col--; 76 | if (col < 0) { 77 | col = picWidth - 1; 78 | row--; 79 | if (row < 0) 80 | row = 0; 81 | line = (QRgb*)p->scanLine(row); 82 | update(); 83 | } 84 | } 85 | } 86 | void ShowPngPicture::paintEvent(QPaintEvent*) 87 | { 88 | 89 | if (p != nullptr) 90 | ui->displayWidget->setPixmap(QPixmap::fromImage(*p)); 91 | } 92 | bool ShowPngPicture::saveImage(QString datei) { return p->save(datei, "PNG"); } 93 | void ShowPngPicture::storeReverse(bool order) 94 | { 95 | if (reverseOrder == order) 96 | return; 97 | reverseOrder = order; 98 | p->fill(64); 99 | if (reverseOrder) { 100 | row = picHeight - 1; 101 | col = picWidth - 1; 102 | } else { 103 | row = 0; 104 | col = 0; 105 | } 106 | line = (QRgb*)p->scanLine(row); 107 | } 108 | 109 | 110 | void ShowPngPicture::presetBottomUp(bool order) 111 | { 112 | ui->reverse->setChecked(order); 113 | storeReverse(order); 114 | } 115 | -------------------------------------------------------------------------------- /lib/showpngpicture.h: -------------------------------------------------------------------------------- 1 | #ifndef SHOWPNGPICTURE_HH 2 | #define SHOWPNGPICTURE_HH 3 | 4 | #include 5 | 6 | class QTimer; 7 | class QImage; 8 | 9 | namespace Ui { 10 | class ShowPngPicture; 11 | } 12 | 13 | class ShowPngPicture : public QWidget 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit ShowPngPicture(int width, int height, QWidget* parent = 0); 19 | ~ShowPngPicture(); 20 | 21 | void presetBottomUp(bool order); 22 | 23 | private: 24 | Ui::ShowPngPicture* ui; 25 | int picWidth; 26 | int picHeight; 27 | int col; 28 | int row; 29 | bool reverseOrder; 30 | 31 | QImage* p; 32 | QRgb* line; 33 | QWidget* displayWidget; 34 | // QTimer *displayTimer; 35 | 36 | void setNextPixel(int); 37 | bool saveImage(QString); 38 | 39 | 40 | public slots: 41 | void setPixel(const unsigned char*, int); 42 | void saveImage2File(); 43 | void storeReverse(bool order); 44 | 45 | protected: 46 | void paintEvent(QPaintEvent*); 47 | }; 48 | 49 | #endif // SHOWPNGPICTURE_HH 50 | -------------------------------------------------------------------------------- /lib/showpngpicture.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ShowPngPicture 4 | 5 | 6 | 7 | 0 8 | 0 9 | 447 10 | 383 11 | 12 | 13 | 14 | Image Display 15 | 16 | 17 | 18 | 19 | 20 | Qt::ScrollBarAsNeeded 21 | 22 | 23 | true 24 | 25 | 26 | 27 | 28 | 0 29 | 0 30 | 427 31 | 326 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Display from bottom up 43 | 44 | 45 | 46 | 47 | 48 | 49 | Qt::Horizontal 50 | 51 | 52 | 53 | 68 54 | 20 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Save Image to File 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /python/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-display 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | ######################################################################## 10 | # Include python install macros 11 | ######################################################################## 12 | include(GrPython) 13 | if(NOT PYTHONINTERP_FOUND) 14 | return() 15 | endif() 16 | 17 | add_subdirectory(bindings) 18 | 19 | ######################################################################## 20 | # Install python sources 21 | ######################################################################## 22 | GR_PYTHON_INSTALL( 23 | FILES 24 | __init__.py 25 | DESTINATION ${GR_PYTHON_DIR}/display 26 | ) 27 | 28 | ######################################################################## 29 | # Handle the unit tests 30 | ######################################################################## 31 | include(GrTest) 32 | 33 | set(GR_TEST_TARGET_DEPS gnuradio-display) 34 | set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/python/bindings) 35 | GR_ADD_TEST(qa_display_text_msg ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_display_text_msg.py) 36 | GR_ADD_TEST(qa_show_image ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_show_image.py) 37 | GR_ADD_TEST(qa_show_text ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_show_text.py) 38 | -------------------------------------------------------------------------------- /python/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2008,2009 Free Software Foundation, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-3.0-or-later 5 | # 6 | 7 | # The presence of this file turns this directory into a Python package 8 | 9 | ''' 10 | This is the GNU Radio DISPLAY module. Place your Python package 11 | description here (python/__init__.py). 12 | ''' 13 | from __future__ import unicode_literals 14 | import os 15 | 16 | # import pybind11 generated symbols into the display namespace 17 | try: 18 | from .display_python import * 19 | except ImportError: 20 | dirname, filename = os.path.split(os.path.abspath(__file__)) 21 | __path__.append(os.path.join(dirname, "bindings")) 22 | from .display_python import * 23 | 24 | # import any pure python here 25 | # 26 | -------------------------------------------------------------------------------- /python/bindings/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # SPDX-License-Identifier: GPL-3.0-or-later 6 | # 7 | 8 | GR_PYTHON_CHECK_MODULE_RAW( 9 | "pygccxml" 10 | "import pygccxml" 11 | PYGCCXML_FOUND 12 | ) 13 | 14 | include(GrPybind) 15 | 16 | ######################################################################## 17 | # Python Bindings 18 | ######################################################################## 19 | message(STATUS "Extra includes: ${Qt5Widgets_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS} ") 20 | set(extra_includes ${Qt5Widgets_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS}) 21 | get_directory_property( DirDefs COMPILE_DEFINITIONS ) 22 | message(STATUS "COMPILE_DEFINITIONS = ${DirDefs}" ) 23 | set(define_symbols ${DirDefs};__PIC__) 24 | message(STATUS "OLd defines: $CACHE{OLD_DEFINES}" ) 25 | message(STATUS "Definitions = ${define_symbols}" ) 26 | string(COMPARE NOTEQUAL "$CACHE{OLD_DEFINES}" "${define_symbols}" FORCE_REBUILD ) 27 | set(OLD_DEFINES "${define_symbols}" CACHE STRING "Save old defines" FORCE) 28 | 29 | list(APPEND display_python_files 30 | display_text_msg_python.cc 31 | show_text_python.cc 32 | show_image_python.cc 33 | python_bindings.cc) 34 | 35 | GR_PYBIND_MAKE_OOT(display 36 | ../.. 37 | gr::display 38 | "${display_python_files}") 39 | 40 | install(TARGETS display_python DESTINATION ${GR_PYTHON_DIR}/display COMPONENT pythonapi) 41 | -------------------------------------------------------------------------------- /python/bindings/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dl1ksv/gr-display/41895ee298eaa62cd56fc8ec3efad948568743ce/python/bindings/README.md -------------------------------------------------------------------------------- /python/bindings/bind_oot_file.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | import argparse 3 | import os 4 | from gnuradio.bindtool import BindingGenerator 5 | import pathlib 6 | import sys 7 | 8 | parser = argparse.ArgumentParser(description='Bind a GR Out of Tree Block') 9 | parser.add_argument('--module', type=str, 10 | help='Name of gr module containing file to bind (e.g. fft digital analog)') 11 | 12 | parser.add_argument('--output_dir', default='/tmp', 13 | help='Output directory of generated bindings') 14 | parser.add_argument('--prefix', help='Prefix of Installed GNU Radio') 15 | parser.add_argument('--src', help='Directory of gnuradio source tree', 16 | default=os.path.dirname(os.path.abspath(__file__))+'/../../..') 17 | 18 | parser.add_argument( 19 | '--filename', help="File to be parsed") 20 | 21 | parser.add_argument( 22 | '--defines', help='Set additional defines for precompiler',default=(), nargs='*') 23 | parser.add_argument( 24 | '--include', help='Additional Include Dirs, separated', default=(), nargs='*') 25 | 26 | parser.add_argument( 27 | '--status', help='Location of output file for general status (used during cmake)', default=None 28 | ) 29 | parser.add_argument( 30 | '--flag_automatic', default='0' 31 | ) 32 | parser.add_argument( 33 | '--flag_pygccxml', default='0' 34 | ) 35 | 36 | args = parser.parse_args() 37 | 38 | prefix = args.prefix 39 | output_dir = args.output_dir 40 | defines = tuple(','.join(args.defines).split(',')) 41 | includes = ','.join(args.include) 42 | name = args.module 43 | 44 | namespace = ['gr', name] 45 | prefix_include_root = name 46 | 47 | with warnings.catch_warnings(): 48 | warnings.filterwarnings("ignore", category=DeprecationWarning) 49 | 50 | bg = BindingGenerator(prefix, namespace, 51 | prefix_include_root, output_dir, define_symbols=defines, addl_includes=includes, 52 | catch_exceptions=False, write_json_output=False, status_output=args.status, 53 | flag_automatic=True if args.flag_automatic.lower() in [ 54 | '1', 'true'] else False, 55 | flag_pygccxml=True if args.flag_pygccxml.lower() in ['1', 'true'] else False) 56 | bg.gen_file_binding(args.filename) 57 | -------------------------------------------------------------------------------- /python/bindings/display_text_msg_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | /***********************************************************************************/ 11 | /* This file is automatically generated using bindtool and can be manually edited */ 12 | /* The following lines can be configured to regenerate this file during cmake */ 13 | /* If manual edits are made, the following tags should be modified accordingly. */ 14 | /* BINDTOOL_GEN_AUTOMATIC(0) */ 15 | /* BINDTOOL_USE_PYGCCXML(0) */ 16 | /* BINDTOOL_HEADER_FILE(display_text_msg.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(0056d519c37c1ee2362d03fba3fc427e) */ 18 | /***********************************************************************************/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace py = pybind11; 25 | 26 | #include 27 | // pydoc.h is automatically generated in the build directory 28 | #include 29 | 30 | void bind_display_text_msg(py::module& m) 31 | { 32 | 33 | using text_msg = ::gr::display::text_msg; 34 | 35 | 36 | py::class_>( 37 | m, "text_msg", D(text_msg)) 38 | 39 | .def(py::init(&text_msg::make), 40 | py::arg("label"), 41 | py::arg("message_key"), 42 | py::arg("splitlength") = 80, 43 | py::arg("maxlines") = 100, 44 | py::arg("parent") = nullptr, 45 | D(text_msg, make)) 46 | 47 | 48 | .def("exec_", &text_msg::exec_, D(text_msg, exec_)) 49 | 50 | 51 | .def( 52 | "qwidget", 53 | [](text_msg& self) { return reinterpret_cast(self.qwidget()); }, 54 | D(text_msg, qwidget)) 55 | 56 | ; 57 | } 58 | -------------------------------------------------------------------------------- /python/bindings/docstrings/README.md: -------------------------------------------------------------------------------- 1 | This directory stores templates for docstrings that are scraped from the include header files for each block -------------------------------------------------------------------------------- /python/bindings/docstrings/display_text_msg_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr, display, __VA_ARGS__) 11 | /* 12 | This file contains placeholders for docstrings for the Python bindings. 13 | Do not edit! These were automatically extracted during the binding process 14 | and will be overwritten during the build process 15 | */ 16 | 17 | 18 | static const char* __doc_gr_display_text_msg = R"doc()doc"; 19 | 20 | 21 | static const char* __doc_gr_display_text_msg_text_msg_0 = R"doc()doc"; 22 | 23 | 24 | static const char* __doc_gr_display_text_msg_text_msg_1 = R"doc()doc"; 25 | 26 | 27 | static const char* __doc_gr_display_text_msg_make = R"doc()doc"; 28 | 29 | 30 | static const char* __doc_gr_display_text_msg_exec_ = R"doc()doc"; 31 | 32 | 33 | static const char* __doc_gr_display_text_msg_qwidget = R"doc()doc"; 34 | -------------------------------------------------------------------------------- /python/bindings/docstrings/show_image_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr, display, __VA_ARGS__) 11 | /* 12 | This file contains placeholders for docstrings for the Python bindings. 13 | Do not edit! These were automatically extracted during the binding process 14 | and will be overwritten during the build process 15 | */ 16 | 17 | 18 | static const char* __doc_gr_display_show_image = R"doc()doc"; 19 | 20 | 21 | static const char* __doc_gr_display_show_image_show_image_0 = R"doc()doc"; 22 | 23 | 24 | static const char* __doc_gr_display_show_image_show_image_1 = R"doc()doc"; 25 | 26 | 27 | static const char* __doc_gr_display_show_image_make = R"doc()doc"; 28 | 29 | 30 | static const char* __doc_gr_display_show_image_exec_ = R"doc()doc"; 31 | 32 | 33 | static const char* __doc_gr_display_show_image_qwidget = R"doc()doc"; 34 | 35 | 36 | static const char* __doc_gr_display_show_image_displayBottomUp = R"doc()doc"; 37 | -------------------------------------------------------------------------------- /python/bindings/docstrings/show_text_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr, display, __VA_ARGS__) 11 | /* 12 | This file contains placeholders for docstrings for the Python bindings. 13 | Do not edit! These were automatically extracted during the binding process 14 | and will be overwritten during the build process 15 | */ 16 | 17 | 18 | static const char* __doc_gr_display_show_text = R"doc()doc"; 19 | 20 | 21 | static const char* __doc_gr_display_show_text_show_text_0 = R"doc()doc"; 22 | 23 | 24 | static const char* __doc_gr_display_show_text_show_text_1 = R"doc()doc"; 25 | 26 | 27 | static const char* __doc_gr_display_show_text_make = R"doc()doc"; 28 | 29 | 30 | static const char* __doc_gr_display_show_text_qwidget = R"doc()doc"; 31 | 32 | 33 | static const char* __doc_gr_display_show_text_exec_ = R"doc()doc"; 34 | -------------------------------------------------------------------------------- /python/bindings/header_utils.py: -------------------------------------------------------------------------------- 1 | # Utilities for reading values in header files 2 | 3 | from argparse import ArgumentParser 4 | import re 5 | 6 | 7 | class PybindHeaderParser: 8 | def __init__(self, pathname): 9 | with open(pathname,'r') as f: 10 | self.file_txt = f.read() 11 | 12 | def get_flag_automatic(self): 13 | # p = re.compile(r'BINDTOOL_GEN_AUTOMATIC\(([^\s])\)') 14 | # m = p.search(self.file_txt) 15 | m = re.search(r'BINDTOOL_GEN_AUTOMATIC\(([^\s])\)', self.file_txt) 16 | if (m and m.group(1) == '1'): 17 | return True 18 | else: 19 | return False 20 | 21 | def get_flag_pygccxml(self): 22 | # p = re.compile(r'BINDTOOL_USE_PYGCCXML\(([^\s])\)') 23 | # m = p.search(self.file_txt) 24 | m = re.search(r'BINDTOOL_USE_PYGCCXML\(([^\s])\)', self.file_txt) 25 | if (m and m.group(1) == '1'): 26 | return True 27 | else: 28 | return False 29 | 30 | def get_header_filename(self): 31 | # p = re.compile(r'BINDTOOL_HEADER_FILE\(([^\s]*)\)') 32 | # m = p.search(self.file_txt) 33 | m = re.search(r'BINDTOOL_HEADER_FILE\(([^\s]*)\)', self.file_txt) 34 | if (m): 35 | return m.group(1) 36 | else: 37 | return None 38 | 39 | def get_header_file_hash(self): 40 | # p = re.compile(r'BINDTOOL_HEADER_FILE_HASH\(([^\s]*)\)') 41 | # m = p.search(self.file_txt) 42 | m = re.search(r'BINDTOOL_HEADER_FILE_HASH\(([^\s]*)\)', self.file_txt) 43 | if (m): 44 | return m.group(1) 45 | else: 46 | return None 47 | 48 | def get_flags(self): 49 | return f'{self.get_flag_automatic()};{self.get_flag_pygccxml()};{self.get_header_filename()};{self.get_header_file_hash()};' 50 | 51 | 52 | 53 | def argParse(): 54 | """Parses commandline args.""" 55 | desc='Reads the parameters from the comment block in the pybind files' 56 | parser = ArgumentParser(description=desc) 57 | 58 | parser.add_argument("function", help="Operation to perform on comment block of pybind file", choices=["flag_auto","flag_pygccxml","header_filename","header_file_hash","all"]) 59 | parser.add_argument("pathname", help="Pathname of pybind c++ file to read, e.g. blockname_python.cc") 60 | 61 | return parser.parse_args() 62 | 63 | if __name__ == "__main__": 64 | # Parse command line options and set up doxyxml. 65 | args = argParse() 66 | 67 | pbhp = PybindHeaderParser(args.pathname) 68 | 69 | if args.function == "flag_auto": 70 | print(pbhp.get_flag_automatic()) 71 | elif args.function == "flag_pygccxml": 72 | print(pbhp.get_flag_pygccxml()) 73 | elif args.function == "header_filename": 74 | print(pbhp.get_header_filename()) 75 | elif args.function == "header_file_hash": 76 | print(pbhp.get_header_file_hash()) 77 | elif args.function == "all": 78 | print(pbhp.get_flags()) -------------------------------------------------------------------------------- /python/bindings/python_bindings.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | #include 11 | 12 | #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION 13 | #include 14 | 15 | namespace py = pybind11; 16 | 17 | 18 | // Headers for binding functions 19 | /**************************************/ 20 | // The following comment block is used for 21 | // gr_modtool to insert function prototypes 22 | // Please do not delete 23 | /**************************************/ 24 | // BINDING_FUNCTION_PROTOTYPES( 25 | void bind_display_text_msg(py::module&); 26 | void bind_show_image(py::module&); 27 | void bind_show_text(py::module&); 28 | // ) END BINDING_FUNCTION_PROTOTYPES 29 | 30 | 31 | // We need this hack because import_array() returns NULL 32 | // for newer Python versions. 33 | // This function is also necessary because it ensures access to the C API 34 | // and removes a warning. 35 | void* init_numpy() 36 | { 37 | import_array(); 38 | return NULL; 39 | } 40 | 41 | PYBIND11_MODULE(display_python, m) 42 | { 43 | // Initialize the numpy C API 44 | // (otherwise we will see segmentation faults) 45 | init_numpy(); 46 | 47 | // Allow access to base block methods 48 | py::module::import("gnuradio.gr"); 49 | py::module::import("gnuradio.qtgui.qtgui_python"); 50 | /**************************************/ 51 | /* The following comment block is used for 52 | * gr_modtool to insert binding function calls 53 | * Please do not delete 54 | **************************************/ 55 | // BINDING_FUNCTION_CALLS( 56 | bind_display_text_msg(m); 57 | bind_show_image(m); 58 | bind_show_text(m); 59 | // ) END BINDING_FUNCTION_CALLS 60 | } 61 | -------------------------------------------------------------------------------- /python/bindings/show_image_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | /***********************************************************************************/ 11 | /* This file is automatically generated using bindtool and can be manually edited */ 12 | /* The following lines can be configured to regenerate this file during cmake */ 13 | /* If manual edits are made, the following tags should be modified accordingly. */ 14 | /* BINDTOOL_GEN_AUTOMATIC(0) */ 15 | /* BINDTOOL_USE_PYGCCXML(0) */ 16 | /* BINDTOOL_HEADER_FILE(show_image.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(bd77911a08c388a4b9dc803945c8873a) */ 18 | /***********************************************************************************/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace py = pybind11; 25 | 26 | #include 27 | // pydoc.h is automatically generated in the build directory 28 | #include 29 | 30 | void bind_show_image(py::module& m) 31 | { 32 | 33 | using show_image = ::gr::display::show_image; 34 | 35 | 36 | py::class_>(m, "show_image", D(show_image)) 41 | 42 | .def(py::init(&show_image::make), 43 | py::arg("imagewidth"), 44 | py::arg("imageheight"), 45 | py::arg("parent") = nullptr, 46 | D(show_image, make)) 47 | 48 | 49 | .def("exec_", &show_image::exec_, D(show_image, exec_)) 50 | 51 | 52 | .def( 53 | "qwidget", 54 | [](show_image& self) { return reinterpret_cast(self.qwidget()); }, 55 | D(show_image, qwidget)) 56 | 57 | 58 | .def("displayBottomUp", 59 | &show_image::displayBottomUp, 60 | py::arg("direction"), 61 | D(show_image, displayBottomUp)) 62 | 63 | ; 64 | } 65 | -------------------------------------------------------------------------------- /python/bindings/show_text_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | /***********************************************************************************/ 11 | /* This file is automatically generated using bindtool and can be manually edited */ 12 | /* The following lines can be configured to regenerate this file during cmake */ 13 | /* If manual edits are made, the following tags should be modified accordingly. */ 14 | /* BINDTOOL_GEN_AUTOMATIC(0) */ 15 | /* BINDTOOL_USE_PYGCCXML(0) */ 16 | /* BINDTOOL_HEADER_FILE(show_text.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(dd84b7dc723e5c7d9aa05611de52defd) */ 18 | /***********************************************************************************/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace py = pybind11; 25 | 26 | #include 27 | // pydoc.h is automatically generated in the build directory 28 | #include 29 | 30 | void bind_show_text(py::module& m) 31 | { 32 | 33 | using show_text = ::gr::display::show_text; 34 | 35 | 36 | py::class_>(m, "show_text", D(show_text)) 41 | 42 | .def(py::init(&show_text::make), 43 | py::arg("label"), 44 | py::arg("splitlength") = 80, 45 | py::arg("maxlines") = 100, 46 | py::arg("parent") = nullptr, 47 | D(show_text, make)) 48 | 49 | 50 | .def( 51 | "qwidget", 52 | [](show_text& self) { return reinterpret_cast(self.qwidget()); }, 53 | D(show_text, qwidget)) 54 | 55 | 56 | .def("exec_", &show_text::exec_, D(show_text, exec_)) 57 | 58 | ; 59 | } 60 | -------------------------------------------------------------------------------- /python/qa_display_text_msg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright 2020 dl1ksv. 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | from gnuradio import gr, gr_unittest 10 | from PyQt5 import Qt 11 | import sip 12 | # from gnuradio import blocks 13 | try: 14 | from display_python import text_msg 15 | except ImportError: 16 | import os 17 | import sys 18 | dirname, filename = os.path.split(os.path.abspath(__file__)) 19 | sys.path.append(os.path.join(dirname, "bindings")) 20 | from display import text_msg 21 | 22 | class qa_display_text_msg(gr_unittest.TestCase): 23 | 24 | def setUp(self): 25 | self.tb = gr.top_block() 26 | 27 | def tearDown(self): 28 | self.tb = None 29 | 30 | def test_instance(self): 31 | instance = text_msg('TestString','test',80,10,None) 32 | b = sip.wrapinstance(instance.qwidget(),Qt.QWidget) 33 | 34 | def test_001_descriptive_test_name(self): 35 | # set up fg 36 | self.tb.run() 37 | # check data 38 | 39 | 40 | if __name__ == '__main__': 41 | gr_unittest.run(qa_display_text_msg) 42 | -------------------------------------------------------------------------------- /python/qa_show_image.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright 2020 dl1ksv. 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | from gnuradio import gr, gr_unittest 10 | from PyQt5 import Qt 11 | import sip 12 | 13 | try: 14 | from display_python import show_image 15 | except ImportError: 16 | import os 17 | import sys 18 | dirname, filename = os.path.split(os.path.abspath(__file__)) 19 | sys.path.append(os.path.join(dirname, "bindings")) 20 | from display import show_image 21 | 22 | class qa_show_image(gr_unittest.TestCase): 23 | 24 | def setUp(self): 25 | self.tb = gr.top_block() 26 | 27 | def tearDown(self): 28 | self.tb = None 29 | 30 | def test_instance(self): 31 | instance = show_image(1024 ,512,None) 32 | b = sip.wrapinstance(instance.qwidget(),Qt.QWidget) 33 | 34 | def test_001_descriptive_test_name(self): 35 | # set up fg 36 | self.tb.run() 37 | # check data 38 | 39 | 40 | if __name__ == '__main__': 41 | gr_unittest.run(qa_show_image) 42 | -------------------------------------------------------------------------------- /python/qa_show_text.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright 2020 dl1ksv. 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | from gnuradio import gr, gr_unittest 10 | from PyQt5 import Qt 11 | import sip 12 | 13 | try: 14 | from display_python import show_text 15 | except ImportError: 16 | import os 17 | import sys 18 | dirname, filename = os.path.split(os.path.abspath(__file__)) 19 | sys.path.append(os.path.join(dirname, "bindings")) 20 | from display import show_text 21 | 22 | class qa_show_text(gr_unittest.TestCase): 23 | 24 | def setUp(self): 25 | self.tb = gr.top_block() 26 | 27 | def tearDown(self): 28 | self.tb = None 29 | 30 | def test_instance(self): 31 | # FIXME: Test will fail until you pass sensible arguments to the constructor 32 | instance = show_text('Header', 80, 10, None) 33 | b = sip.wrapinstance(instance.qwidget(),Qt.QWidget) 34 | 35 | def test_001_descriptive_test_name(self): 36 | # set up fg 37 | self.tb.run() 38 | # check data 39 | 40 | 41 | if __name__ == '__main__': 42 | gr_unittest.run(qa_show_text) 43 | --------------------------------------------------------------------------------