Compare commits
18 Commits
b92a1fa558
...
release
| Author | SHA1 | Date | |
|---|---|---|---|
| 75b3bb46ac | |||
| 75c6b5abcc | |||
| 97c6ddeaea | |||
| 235eb2acb8 | |||
| bd5579b8f1 | |||
| 7f820c8f67 | |||
| 9130496887 | |||
| cca2e0f2d7 | |||
| 5ae5034145 | |||
| 016753fb4d | |||
| b71db0530f | |||
| bb645bd71b | |||
| 12664842c7 | |||
| c41e92a9f5 | |||
| 6e4cdccc94 | |||
| e59bf65294 | |||
| 2e5d64f258 | |||
| 5382c54d6a |
3
.gitignore
vendored
@@ -1,2 +1,5 @@
|
|||||||
/.svn
|
/.svn
|
||||||
CMakeLists.txt.user*
|
CMakeLists.txt.user*
|
||||||
|
/project_fs_build
|
||||||
|
/qad/qad_version.h
|
||||||
|
/qglengine/core/qglengine_version.h
|
||||||
|
|||||||
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "pip"]
|
||||||
|
path = pip
|
||||||
|
url = https://git.shs.tools/SHS/pip.git
|
||||||
281
CMakeLists.txt
@@ -1,12 +1,29 @@
|
|||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
cmake_policy(SET CMP0011 NEW) # don`t affect includer policies
|
||||||
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
||||||
project(qad)
|
cmake_policy(SET CMP0020 NEW) # Automatically link Qt executables to qtmain target on Windows
|
||||||
|
if (POLICY CMP0053)
|
||||||
find_package(MinGW REQUIRED)
|
cmake_policy(SET CMP0053 NEW) # simpler variable expansion and escape sequence evaluation rules
|
||||||
if (NOT DEFINED ANDROID_PLATFORM)
|
|
||||||
find_package(OpenGL REQUIRED)
|
|
||||||
endif()
|
endif()
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
project(libs)
|
||||||
|
set(PIP_CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/pip/cmake")
|
||||||
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${PIP_CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/qad/cmake")
|
||||||
|
set(LIBPROJECT 1)
|
||||||
|
set(_qt_libs )
|
||||||
|
set(_qt_apps )
|
||||||
|
set(_qt_plugs)
|
||||||
|
include(GenerateExportHeader)
|
||||||
|
include(SDKMacros)
|
||||||
|
include(QADMacros)
|
||||||
|
include(DeployMacros)
|
||||||
|
|
||||||
|
if(NOT DEFINED BUILD_NUMBER)
|
||||||
|
set(BUILD_NUMBER 9999)
|
||||||
|
endif()
|
||||||
|
if("x${BUILD_NUMBER}" STREQUAL "x")
|
||||||
|
set(BUILD_NUMBER 0)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if(STATIC_LIB)
|
if(STATIC_LIB)
|
||||||
set(QAD_LIB_TYPE STATIC)
|
set(QAD_LIB_TYPE STATIC)
|
||||||
@@ -18,7 +35,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(_QAD_MAJOR 1)
|
set(_QAD_MAJOR 1)
|
||||||
set(_QAD_MINOR 7)
|
set(_QAD_MINOR 9)
|
||||||
set(_QAD_REVISION 0)
|
set(_QAD_REVISION 0)
|
||||||
set(_QAD_SUFFIX )
|
set(_QAD_SUFFIX )
|
||||||
set(_QAD_COMPANY SHS)
|
set(_QAD_COMPANY SHS)
|
||||||
@@ -35,29 +52,249 @@ set_deploy_property(QAD ${QAD_LIB_TYPE}
|
|||||||
FULLNAME "${_QAD_DOMAIN}.*"
|
FULLNAME "${_QAD_DOMAIN}.*"
|
||||||
COMPANY "${_QAD_COMPANY}")
|
COMPANY "${_QAD_COMPANY}")
|
||||||
|
|
||||||
# Version
|
|
||||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/qad_version.h")
|
|
||||||
file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/qad_version.h")
|
|
||||||
endif()
|
|
||||||
#message(STATUS "Building QAD version ${QAD_VERSION} (${QAD_LIB_TYPE})")
|
|
||||||
|
|
||||||
file(GLOB CMAKES "cmake/*.cmake" "cmake/*.in")
|
if(STATIC_LIB)
|
||||||
|
set(PIQt_LIB_TYPE STATIC)
|
||||||
|
add_definitions(-DPIQt_STATIC_DEFINE)
|
||||||
|
set(PIQt_LIB_TYPE_MSG "Static")
|
||||||
|
else()
|
||||||
|
set(PIQt_LIB_TYPE SHARED)
|
||||||
|
set(PIQt_LIB_TYPE_MSG "Shared")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_PIQt_MAJOR 1)
|
||||||
|
set(_PIQt_MINOR 0)
|
||||||
|
set(_PIQt_REVISION 0)
|
||||||
|
set(_PIQt_SUFFIX )
|
||||||
|
set(_PIQt_COMPANY SHS)
|
||||||
|
set(_PIQt_DOMAIN org.SHS)
|
||||||
|
if(NOT DEFINED BUILD_NUMBER)
|
||||||
|
set(BUILD_NUMBER 9999)
|
||||||
|
endif()
|
||||||
|
set(PIQt_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/piqt/piqt_version.h")
|
||||||
|
set_version(PIQt
|
||||||
|
MAJOR "${_PIQt_MAJOR}"
|
||||||
|
MINOR "${_PIQt_MINOR}"
|
||||||
|
REVISION "${_PIQt_REVISION}"
|
||||||
|
BUILD "${BUILD_NUMBER}"
|
||||||
|
SUFFIX "${_PIQt_SUFFIX}"
|
||||||
|
OUTPUT "${PIQt_VERSION_FILE}")
|
||||||
|
set_deploy_property(PIQt ${_PIQt_LIB_TYPE}
|
||||||
|
FULLNAME "${_PIQt_DOMAIN}.*"
|
||||||
|
COMPANY "${_PIQt_COMPANY}")
|
||||||
|
|
||||||
|
|
||||||
|
include_directories(${CMAKE_CURRENT_BINARY_DIR}/pip)
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/qad)
|
||||||
|
include_directories(${CMAKE_CURRENT_BINARY_DIR}/piqt)
|
||||||
|
if(MINGW)
|
||||||
|
find_package(MinGW REQUIRED)
|
||||||
|
else()
|
||||||
|
if(APPLE)
|
||||||
|
set(CMAKE_INSTALL_RPATH "@executable_path/../Frameworks;@executable_path/lib;@loader_path/../lib")
|
||||||
|
set(CMAKE_MACOSX_RPATH TRUE)
|
||||||
|
if(CMAKE_CROSSCOMPILING)
|
||||||
|
set(CMAKE_INSTALL_NAME_DIR "@rpath")
|
||||||
|
else()
|
||||||
|
include_directories(/usr/local/include)
|
||||||
|
link_directories(/usr/local/lib)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(CMAKE_INSTALL_RPATH "\$ORIGIN;\$ORIGIN/lib")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if (DEFINED ANDROID_PLATFORM)
|
||||||
|
include_directories(${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include)
|
||||||
|
#set(TARGET_INSTALL_PATH "${ANDROID_SYSTEM_LIBRARY_PATH}/usr/")
|
||||||
|
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${ANDROID_NDK}/sysroot/usr/include")
|
||||||
|
#message("${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include")
|
||||||
|
#message("${ANDROID_NDK}/sysroot/usr/include")
|
||||||
|
endif()
|
||||||
|
set(INSTALL_PREFIX "")
|
||||||
|
set(_plugins_default_ ON)
|
||||||
|
if(CMAKE_CROSSCOMPILING)
|
||||||
|
if (DEFINED ANDROID_PLATFORM)
|
||||||
|
set(_plugins_default_ OFF)
|
||||||
|
set(INSTALL_PREFIX "${CMAKE_FIND_ROOT_PATH}/")
|
||||||
|
else()
|
||||||
|
set(INSTALL_PREFIX "${CMAKE_STAGING_PREFIX}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
option(CROSSTOOLS "Crosstools minimal build" OFF)
|
||||||
|
option(LIB "System install" ON)
|
||||||
|
option(QGLVIEW "Build QGLview library and utils" OFF)
|
||||||
|
option(QGLENGINE "Build QGLENGINE library and utils" OFF)
|
||||||
|
option(UTILS "Build various utils" ${_plugins_default_})
|
||||||
|
option(DESIGNER_PLUGINS "Build qt designer plugins" ${_plugins_default_})
|
||||||
|
option(STATIC_LIB OFF)
|
||||||
|
if (CROSSTOOLS)
|
||||||
|
set(LIB 1)
|
||||||
|
set(QGLVIEW 0)
|
||||||
|
set(QGLENGINE 0)
|
||||||
|
set(UTILS 0)
|
||||||
|
set(DESIGNER_PLUGINS 0)
|
||||||
|
endif()
|
||||||
|
if (CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -Wall")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3 -Wall")
|
||||||
|
else()
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wall")
|
||||||
|
endif()
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
|
set(PIP_LIBRARY pip)
|
||||||
|
set(PIP_INCLUDES)
|
||||||
|
|
||||||
if(LIB)
|
if(LIB)
|
||||||
install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules)
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
install(FILES ${QAD_VERSION_FILE} DESTINATION ${MINGW_INCLUDE}/qad)
|
if(MINGW)
|
||||||
else()
|
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
|
||||||
install(FILES ${QAD_VERSION_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/qad)
|
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
install(FILES ${QAD_VERSION_FILE} DESTINATION include/qad)
|
if (DEFINED ANDROID_PLATFORM)
|
||||||
|
set(CMAKE_INSTALL_PREFIX ${ANDROID_SYSTEM_LIBRARY_PATH}/usr)
|
||||||
|
else()
|
||||||
|
if(CMAKE_CROSSCOMPILING)
|
||||||
|
set(CMAKE_INSTALL_PREFIX ${CMAKE_STAGING_PREFIX})
|
||||||
|
else()
|
||||||
|
set(CMAKE_INSTALL_PREFIX ${INSTALL_PREFIX}/usr/local)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"")
|
||||||
|
else()
|
||||||
|
message(STATUS "Install ${PROJECT_NAME} to local \"bin\", \"lib\" and \"include\"")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(libs)
|
#message(${PIP_INCLUDES})
|
||||||
if (UTILS)
|
if(CMAKE_CROSSCOMPILING OR (DEFINED ANDROID_PLATFORM))
|
||||||
add_subdirectory(utils)
|
set(PIP_CMG "pip_cmg")
|
||||||
|
set(PIP_RC "pip_rc")
|
||||||
|
set(PIP_DEPLOY_TOOL "deploy_tool")
|
||||||
|
else()
|
||||||
|
set(PIP_CMG "${CMAKE_CURRENT_BINARY_DIR}/pip/utils/code_model_generator/pip_cmg")
|
||||||
|
set(PIP_RC "${CMAKE_CURRENT_BINARY_DIR}/pip/utils/resources_compiler/pip_rc")
|
||||||
|
set(PIP_DEPLOY_TOOL "${CMAKE_CURRENT_BINARY_DIR}/pip/utils/deploy_tool/deploy_tool")
|
||||||
|
endif()
|
||||||
|
if(WIN32)
|
||||||
|
set(PIP_DLL_DIR "${CMAKE_CURRENT_BINARY_DIR}/pip")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
copy_to_parent(qad_includes)
|
set(QAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/qad)
|
||||||
|
set(ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
if (CROSSTOOLS)
|
||||||
|
|
||||||
|
add_subdirectory(pip)
|
||||||
|
file(GLOB CMAKES "qad/cmake/*.cmake" "qad/cmake/*.in")
|
||||||
|
install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules)
|
||||||
|
|
||||||
|
else()
|
||||||
|
|
||||||
|
include(QtWraps)
|
||||||
|
find_qt(Core QUIET)
|
||||||
|
set(QtVersions)
|
||||||
|
set(SomeQtFound 0)
|
||||||
|
foreach(_v ${_QT_VERSIONS_})
|
||||||
|
option(Qt${_v} "Build for Qt${_v}" 1)
|
||||||
|
if (Qt${_v})
|
||||||
|
#message("Qt${_v} -> ${LOCAL_FOUND${_v}}")
|
||||||
|
if (LOCAL_FOUND${_v})
|
||||||
|
list(APPEND QtVersions Qt${_v})
|
||||||
|
set(SomeQtFound 1)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
#if(UTILS)
|
||||||
|
# message(STATUS "Building with utils")
|
||||||
|
#else()
|
||||||
|
# message(STATUS "Building only libraries")
|
||||||
|
#endif()
|
||||||
|
|
||||||
|
add_subdirectory(pip)
|
||||||
|
foreach(F ${PIP_MAIN_FOLDERS})
|
||||||
|
list(APPEND PIP_INCLUDES "${F}")
|
||||||
|
endforeach(F)
|
||||||
|
add_subdirectory(cd_utils)
|
||||||
|
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/cd_utils" "${CMAKE_CURRENT_BINARY_DIR}/cd_utils")
|
||||||
|
set(_DIRS)
|
||||||
|
if (SomeQtFound)
|
||||||
|
#message(STATUS "Building Qt-derived targets for ${QtVersions}")
|
||||||
|
add_subdirectory(qad)
|
||||||
|
include_directories(${qad_includes})
|
||||||
|
add_subdirectory(piqt)
|
||||||
|
include_directories(${piqt_includes})
|
||||||
|
set(_DIRS)
|
||||||
|
if (Qt5)
|
||||||
|
if (QGLVIEW)
|
||||||
|
list(APPEND _DIRS qglview)
|
||||||
|
endif()
|
||||||
|
if (QGLENGINE)
|
||||||
|
list(APPEND _DIRS qglengine)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
foreach(_D ${_DIRS})
|
||||||
|
list(APPEND QT_MULTILIB_LIST ${_D})
|
||||||
|
add_subdirectory(${_D})
|
||||||
|
endforeach(_D)
|
||||||
|
|
||||||
|
macro(align_list _list _out)
|
||||||
|
set(_max_len 0)
|
||||||
|
foreach(_m ${_list})
|
||||||
|
string(LENGTH "${_m}" _clen)
|
||||||
|
if (_clen GREATER _max_len)
|
||||||
|
set(_max_len ${_clen})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
set(${_out})
|
||||||
|
foreach(_m ${_list})
|
||||||
|
set(_am "${_m}")
|
||||||
|
while(TRUE)
|
||||||
|
string(LENGTH "${_am}" _clen)
|
||||||
|
if (_clen GREATER_EQUAL ${_max_len})
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
string(APPEND _am " ")
|
||||||
|
endwhile()
|
||||||
|
list(APPEND ${_out} "${_am}")
|
||||||
|
endforeach()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(print_list _list _name)
|
||||||
|
if (NOT "x${_list}" STREQUAL "x")
|
||||||
|
message("")
|
||||||
|
message(" ${_name}:")
|
||||||
|
#align_list("${_list}" _alist)
|
||||||
|
foreach(_m ${_list})
|
||||||
|
message(" * ${_m}")
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
message("----------QAD-----------")
|
||||||
|
message(" Build for ${QtVersions}")
|
||||||
|
message(" QAD Version: ${QAD_VERSION}")
|
||||||
|
message(" QAD Linkage: ${QAD_LIB_TYPE_MSG}")
|
||||||
|
message(" PIQt Version: ${PIQt_VERSION}")
|
||||||
|
message(" PIQt Linkage: ${PIQt_LIB_TYPE_MSG}")
|
||||||
|
print_list("${_qt_libs}" "Libraries")
|
||||||
|
print_list("${_qt_apps}" "Applications")
|
||||||
|
print_list("${_qt_plugs}" "Plugins")
|
||||||
|
message("-----------------------")
|
||||||
|
message("")
|
||||||
|
|
||||||
|
else()
|
||||||
|
message(STATUS "None of Qt found, skip Qt-derived targets")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
foreach(PIP_LT ${PIP_MODULES})
|
||||||
|
if (SomeQtFound)
|
||||||
|
qt_install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pip/lib${PIP_LT}.dll" DESTINATION QtBin)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|||||||
62
Jenkinsfile
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
def build_docker(name) {
|
||||||
|
def image = "${name}-libs"
|
||||||
|
echo "Build image ${image}"
|
||||||
|
def pref = ""
|
||||||
|
if (env.DOCKER_PREFIX) {
|
||||||
|
pref = "--build-arg DOCKER_PREFIX=${env.DOCKER_PREFIX}/"
|
||||||
|
}
|
||||||
|
def jobs = 4
|
||||||
|
if (env.JOBS_COUNT) {
|
||||||
|
jobs = "${env.JOBS_COUNT}"
|
||||||
|
}
|
||||||
|
def args = "${pref} --build-arg LIBS_BUILD_NUMBER=${env.BUILD_NUMBER} --build-arg JOBS_COUNT=${jobs}"
|
||||||
|
dir ("docker/${image}") {
|
||||||
|
sh "docker build ${args} --no-cache -t ${image} ."
|
||||||
|
}
|
||||||
|
return "\n - ${image}"
|
||||||
|
}
|
||||||
|
node {
|
||||||
|
stage("checkout") {
|
||||||
|
checkout scm
|
||||||
|
}
|
||||||
|
def _envmap = [:]
|
||||||
|
def _env = sh(script: "env", returnStdout: true).trim().split("\n")
|
||||||
|
_env.each{ l ->
|
||||||
|
def _ind = l.indexOf('=');
|
||||||
|
def _n = l.substring(0, _ind);
|
||||||
|
def _v = l.substring(_ind + 1);
|
||||||
|
_envmap["${_n}"] = "${_v}";
|
||||||
|
}
|
||||||
|
def _msg = "Built images:"
|
||||||
|
def platforms = ['debian', 'osx', 'windows', 'android', 'pi']
|
||||||
|
for (int i = 0; i < platforms.size(); ++i) {
|
||||||
|
if (_envmap["BUILD_${platforms[i]}"] == "1") {
|
||||||
|
stage("${platforms[i]}-libs") {
|
||||||
|
_msg += build_docker("${platforms[i]}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sh "docker system prune -f"
|
||||||
|
echo "${_msg}"
|
||||||
|
}
|
||||||
|
pipeline {
|
||||||
|
agent {
|
||||||
|
label 'master'
|
||||||
|
}
|
||||||
|
stages {
|
||||||
|
stage("PIP doc") {
|
||||||
|
steps {
|
||||||
|
checkout scm
|
||||||
|
sh "rm -rf share"
|
||||||
|
sh "rm -vf *.zip"
|
||||||
|
sh "mkdir -p build"
|
||||||
|
sh "cd build && cmake -DLIB=0 -DCMAKE_INSTALL_PREFIX=`pwd` ../"
|
||||||
|
sh "cd build && make doc"
|
||||||
|
sh "cd share/doc && zip -r ../../pip_doc.zip pip"
|
||||||
|
sh "cp share/doc/pip/html/pip.qch ./"
|
||||||
|
archiveArtifacts 'pip_doc.zip'
|
||||||
|
archiveArtifacts 'pip.qch'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
README.md
@@ -1,10 +1,54 @@
|
|||||||
# Qt for ADvanced
|
# Main SHS SDK libraries repo
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
This repo contains QAD and PIQt projects:
|
This repo contains PIP, QAD and derived projects:
|
||||||
|
* cd_utils - PIP-based client/server library for read, transmit and use custom structures of coefficients
|
||||||
* qcd_utils - Qt bindings to CDUtils and "CD Pult" executable - full-featured CD client
|
* qcd_utils - Qt bindings to CDUtils and "CD Pult" executable - full-featured CD client
|
||||||
* piqt - helpers to convert PIP <-> Qt types
|
* piqt - helpers to convert PIP <-> Qt types
|
||||||
* piqt_utils - Gui libraries and executables to edit PIConnection configs and watch PIIntrospection
|
* piqt_utils - Gui libraries and executables to edit PIConnection configs and watch PIIntrospection
|
||||||
* qglview - old Qt-base OpenGL engine
|
* qglview - old Qt-base OpenGL engine
|
||||||
|
* qglengine - new Qt-base OpenGL engine
|
||||||
|
|
||||||
|
## Compile
|
||||||
|
This repo can be compile with GCC/MinGW/Clang, for Qt 4/5.
|
||||||
|
|
||||||
|
If there is no Qt found, builds only PIP and cd_utils.
|
||||||
|
|
||||||
|
CMake options:
|
||||||
|
* **LIB** - if 1 then install to system directories: MinGW on Windows, /usr/local on Linux/MacOS, ${ANDROID_SYSTEM_LIBRARY_PATH} on Android. If 0 then install to ${CMAKE_INSTALL_PREFIX}. Enabled by default
|
||||||
|
* **UTILS** - build or not executable utilites, enabled by default
|
||||||
|
* **DESIGNER_PLUGINS** - build or not Qt Designer plugins, enabled by default
|
||||||
|
* **QGLVIEW** - build or not QGLView, disabled by default
|
||||||
|
* **QGLENGINE** - build or not QGLEngine, disabled by default
|
||||||
|
|
||||||
|
## Windows scripts
|
||||||
|
Build steps for i686 architecture:
|
||||||
|
1. unzip mingw.7z to C:\mingw
|
||||||
|
2. unzip qt.7z to C:\qt
|
||||||
|
3. download and install cmake from https://cmake.org/download/
|
||||||
|
4. Prepare environment
|
||||||
|
- set prefix for mingw e.g.: for C:\mingw\7_1_x32\
|
||||||
|
set SDK_MINGW_DIR=C:\mingw\7_1_x
|
||||||
|
- set prefix for Qt5 e.g.: for C:\qt\qt5120_win32\
|
||||||
|
set SDK_QT5_DIR=C:\qt\qt5120_win
|
||||||
|
- set SDK_CMAKE_DIR=C:\cmake
|
||||||
|
5. run make_libs32.bat
|
||||||
|
|
||||||
|
Build steps for amd64 architecture:
|
||||||
|
-- follow previos steps, but replace '32' to '64'
|
||||||
|
|
||||||
|
Build steps for both architectures:
|
||||||
|
-- follow previos steps, but on '4' state run make_libs_all.bat
|
||||||
|
|
||||||
|
## Non-Windows scripts
|
||||||
|
Script "make_libs.sh" compile and install SDK for current environment, e.g.
|
||||||
|
`./make_libs.sh -j4`
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
This repo provide Dockerfile, so you can exec `docker build -t libs .` in this directory
|
||||||
|
and make docker image "libs" with installed SHS SDK for:
|
||||||
|
* Debian 10
|
||||||
|
* Windows x64
|
||||||
|
* MacOS
|
||||||
|
* Android ndk 21 armeabi-v71, arm64-v8a, x86, x86_64
|
||||||
|
|||||||
107
SDKMacros.cmake
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
|
||||||
|
macro(sdk_install _DIR IS_APP _TARGET _H_FILES _QM_FILES)
|
||||||
|
#message("QM=${_QM_FILES}")
|
||||||
|
if((NOT ${IS_APP}) AND (NOT "${_H_FILES}" STREQUAL ""))
|
||||||
|
if(LIB)
|
||||||
|
if(WIN32)
|
||||||
|
install(FILES ${_H_FILES} DESTINATION ${MINGW_INCLUDE}/${_DIR})
|
||||||
|
else()
|
||||||
|
install(FILES ${_H_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${_DIR})
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
install(FILES ${_H_FILES} DESTINATION include/${_DIR})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if (NOT "${_TARGET}" STREQUAL "")
|
||||||
|
if(LIB)
|
||||||
|
if(WIN32)
|
||||||
|
if (${IS_APP})
|
||||||
|
qt_install(TARGETS ${_TARGET} DESTINATION ${MINGW_BIN})
|
||||||
|
qt_install(TARGETS ${_TARGET} DESTINATION QtBin)
|
||||||
|
else()
|
||||||
|
qt_install(TARGETS ${_TARGET} ARCHIVE DESTINATION ${MINGW_LIB})
|
||||||
|
qt_install(TARGETS ${_TARGET} RUNTIME DESTINATION ${MINGW_BIN})
|
||||||
|
qt_install(TARGETS ${_TARGET} RUNTIME DESTINATION QtBin)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if (${IS_APP})
|
||||||
|
qt_install(TARGETS ${_TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||||
|
else()
|
||||||
|
qt_install(TARGETS ${_TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(NOT "x${_QM_FILES}" STREQUAL "x")
|
||||||
|
qt_install(LANG ${_QM_FILES} DESTINATION QtLang)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(${IS_APP})
|
||||||
|
qt_install(TARGETS ${_TARGET} DESTINATION bin)
|
||||||
|
else()
|
||||||
|
if(WIN32)
|
||||||
|
qt_install(TARGETS ${_TARGET} RUNTIME DESTINATION bin)
|
||||||
|
qt_install(TARGETS ${_TARGET} ARCHIVE DESTINATION lib)
|
||||||
|
else()
|
||||||
|
qt_install(TARGETS ${_TARGET} DESTINATION lib)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(NOT "x${_QM_FILES}" STREQUAL "x")
|
||||||
|
qt_install(LANG ${_QM_FILES} DESTINATION lang)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
|
||||||
|
macro(copy_to_parent _inc_var)
|
||||||
|
set(QT_MULTILIB_LIST ${QT_MULTILIB_LIST} PARENT_SCOPE)
|
||||||
|
set(_qt_libs ${_qt_libs} PARENT_SCOPE)
|
||||||
|
set(_qt_apps ${_qt_apps} PARENT_SCOPE)
|
||||||
|
set(_qt_plugs ${_qt_plugs} PARENT_SCOPE)
|
||||||
|
if (NOT "x${_inc_var}" STREQUAL "x")
|
||||||
|
set(${_inc_var} ${${_inc_var}} PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
if (LIB)
|
||||||
|
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
|
||||||
|
macro(add_directories_with_include multilib_prefix)
|
||||||
|
set(DIRS)
|
||||||
|
file(GLOB _dl "[^.]*")
|
||||||
|
foreach(_d ${_dl})
|
||||||
|
if(IS_DIRECTORY ${_d})
|
||||||
|
list(APPEND DIRS ${_d})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(inc_var ${multilib_prefix}includes)
|
||||||
|
set(${inc_var})
|
||||||
|
foreach(_d ${DIRS})
|
||||||
|
get_filename_component(_dname "${_d}" NAME)
|
||||||
|
list(APPEND QT_MULTILIB_LIST ${multilib_prefix}${_dname})
|
||||||
|
list(APPEND ${inc_var} "${_d}")
|
||||||
|
list(APPEND ${inc_var} "${CMAKE_CURRENT_BINARY_DIR}/${_dname}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
include_directories(${${inc_var}})
|
||||||
|
foreach(_d ${DIRS})
|
||||||
|
add_subdirectory(${_d})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
copy_to_parent(${inc_var})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
|
||||||
|
macro(add_directories multilib_prefix)
|
||||||
|
include_directories(${${multilib_prefix}includes})
|
||||||
|
file(GLOB _dl "[^.]*")
|
||||||
|
foreach(_d ${_dl})
|
||||||
|
if(IS_DIRECTORY ${_d})
|
||||||
|
add_subdirectory(${_d})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
copy_to_parent(${multilib_prefix}includes)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
37
cd_utils/CMakeLists.txt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(cd_utils)
|
||||||
|
find_package(MinGW REQUIRED)
|
||||||
|
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES})
|
||||||
|
file(GLOB CPPS_UTILS "cdutils_*.cpp")
|
||||||
|
file(GLOB HDRS_UTILS "cdutils_*.h")
|
||||||
|
add_library(${PROJECT_NAME} SHARED ${CPPS_UTILS} ${HDRS_UTILS})
|
||||||
|
target_link_libraries(${PROJECT_NAME} ${PIP_LIBRARY})
|
||||||
|
generate_export_header(${PROJECT_NAME})
|
||||||
|
list(APPEND HDRS_UTILS "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_export.h")
|
||||||
|
|
||||||
|
add_executable(cdutilstest "cdutilstest.cpp" "cdtest.h")
|
||||||
|
target_link_libraries(cdutilstest ${PIP_LIBRARY} ${PROJECT_NAME})
|
||||||
|
message(STATUS "Building ${PROJECT_NAME}")
|
||||||
|
|
||||||
|
if(LIB)
|
||||||
|
list(APPEND _ALL_TARGETS ${PROJECT_NAME})
|
||||||
|
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
|
||||||
|
if(WIN32)
|
||||||
|
install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE})
|
||||||
|
install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION ${MINGW_LIB})
|
||||||
|
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${MINGW_BIN})
|
||||||
|
else()
|
||||||
|
install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
|
||||||
|
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
|
||||||
|
endif()
|
||||||
|
#message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"")
|
||||||
|
else()
|
||||||
|
if(WIN32)
|
||||||
|
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
|
||||||
|
install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION lib)
|
||||||
|
else()
|
||||||
|
install(TARGETS ${PROJECT_NAME} DESTINATION lib)
|
||||||
|
endif()
|
||||||
|
install(FILES ${HDRS_UTILS} DESTINATION include)
|
||||||
|
#message(STATUS "Install ${PROJECT_NAME} to local \"bin\"")
|
||||||
|
endif()
|
||||||
10
cd_utils/cdtest.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef CDTEST_H
|
||||||
|
#define CDTEST_H
|
||||||
|
|
||||||
|
|
||||||
|
enum KDescription {
|
||||||
|
First, //f Первый
|
||||||
|
Second, //b Второй
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CDTEST_H
|
||||||
41
cd_utils/cdutils_c.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "cdutils_c.h"
|
||||||
|
#include "cdutils_core.h"
|
||||||
|
|
||||||
|
using namespace CDUtils;
|
||||||
|
|
||||||
|
CInterface C;
|
||||||
|
|
||||||
|
|
||||||
|
CInterface::CInterface(): Interface(CDType::cdC) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CInterface::sendCommand(const CDType & c) {
|
||||||
|
core->sendCommand(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CInterface::connect(const CDType & c, PIObject * o, Handler eh) {
|
||||||
|
core->registerCHandler(c, o, eh);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CInterface::autoConnect(PIObject * o, const PIString & prefix) {
|
||||||
|
if (!o) return;
|
||||||
|
uint cid = o->classNameID();
|
||||||
|
if (!PIObject::__meta_data().contains(cid)) return;
|
||||||
|
PIMap<PIString, Handler> eh_map;
|
||||||
|
PIObject::__MetaData & md(PIObject::__meta_data()[cid]);
|
||||||
|
PIMap<const void * , __MetaFunc>::const_iterator it;
|
||||||
|
for (it = md.eh_func.constBegin(); it != md.eh_func.constEnd(); ++it) {
|
||||||
|
eh_map[it.value().func_name] = (Handler)it.value().addr;
|
||||||
|
//piCout << "func" << it.value().func_name;
|
||||||
|
}
|
||||||
|
PIVector<CDType * > cl = C.root().children();
|
||||||
|
piForeachC (CDType * c, cl) {
|
||||||
|
PIString cp = prefix + c->pathString().join("_");
|
||||||
|
if (cp.isEmpty()) continue;
|
||||||
|
if (!eh_map.contains(cp)) continue;
|
||||||
|
connect(*c, o, eh_map[cp]);
|
||||||
|
}
|
||||||
|
}
|
||||||
46
cd_utils/cdutils_c.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
CD Utils - Control-Debug utilites
|
||||||
|
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CDUTILS_C_H
|
||||||
|
#define CDUTILS_C_H
|
||||||
|
|
||||||
|
#include "cdutils_interface.h"
|
||||||
|
#include "cd_utils_export.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace CDUtils {
|
||||||
|
|
||||||
|
|
||||||
|
class CD_UTILS_EXPORT CInterface: public Interface
|
||||||
|
{
|
||||||
|
PIOBJECT_SUBCLASS(CInterface, Interface)
|
||||||
|
public:
|
||||||
|
CInterface();
|
||||||
|
|
||||||
|
void sendCommand(const CDType & c);
|
||||||
|
void connect(const CDType & c, PIObject * o, Handler eh);
|
||||||
|
void autoConnect(PIObject * o, const PIString & prefix = PIStringAscii("c_"));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern CD_UTILS_EXPORT CDUtils::CInterface C;
|
||||||
|
|
||||||
|
#endif // CDUTILS_C_H
|
||||||
606
cd_utils/cdutils_core.cpp
Normal file
@@ -0,0 +1,606 @@
|
|||||||
|
#include "cdutils_core.h"
|
||||||
|
#include "cdutils_parser.h"
|
||||||
|
#include "piconfig.h"
|
||||||
|
#include "piiobytearray.h"
|
||||||
|
#include "piiostring.h"
|
||||||
|
#include "pifile.h"
|
||||||
|
|
||||||
|
using namespace CDUtils;
|
||||||
|
|
||||||
|
const char CDCore::app_config[] =
|
||||||
|
"include = cd_ip.conf\n\
|
||||||
|
port_rec = 2\n\
|
||||||
|
port_send = 1\n\
|
||||||
|
[connection]\n\
|
||||||
|
device.cd = peer://cd_app:cd_pult #s\n\
|
||||||
|
[]\n\
|
||||||
|
connectionmodel = AAAM2Xja7VXLTttAFD12QpsikKjUSixYlLbKEpIUtVIlVEfqhk2FWuiGRRolUYtoHgrmpYiv6IItf8AveMMH9E/YsG6Ph3sde5hGoQoblLGuPHfunTPjc49nADxDA110+LTYC7FrPCAPeAO+vZu+aX7c/8PGd45WCJC0OGcfT6FDnmfSTPtwhZFt3HjgDs/Qtu5jPbZHtI/x50XfIzMQbdwEolbg9INP4ku++myPaUtCHYRaT2j1ldIh3VP60/Qff8vSfXLu9BP6JX9K/0TVH6jqVe22P1X/fao/oddWu/paDs1vBf9Jv/EZ91clbyHqv7BL6sscDOd4v4WTqs6jzaHGJ8QJerxlpJSpdZ7IWFJvDW7I2JxZqIM62k6A57RZmMQGmlyrxdV+WGBnmR01mXPI267hBKwp4FeBeo9VPtssxyb7rzHg1B7T9nCMU45U8BZlWuVWtIcD/CRGOqtsbW09851tXsHN0UTlLIAdASjSXnLyLn+H7L2+xbGYvC63Ezqg543egkLmn8qnRF6USbM4Qp9godkhzI777Ne5bCIt/5UtGz2o/yGby0nKpjqmbOa1ynkjmyzIrzvIZUeBPjvlUmbh32EFJbGyJZhR8YcvlS+3TpjhqeWSyvUkpbI9plSWtcKLcsK05beOJVEnhaEFfHEH+RwpeMcpn1JKGqWMNOL+G6wZyahlpdVOtufKfbDS+guLke9O\n\
|
||||||
|
";
|
||||||
|
|
||||||
|
const char CDCore::pult_config[] =
|
||||||
|
"include = cd_ip.conf\n\
|
||||||
|
port_rec = 1\n\
|
||||||
|
port_send = 2\n\
|
||||||
|
[connection]\n\
|
||||||
|
device.cd = peer://cd_pult:cd_app #s\n\
|
||||||
|
[]\n\
|
||||||
|
connectionmodel = AAAM2Xja7VXLTttAFD12QpsikKjUSixYlLbKEpIUtVIlVEfqhk2FWuiGRRolUYtoHgrmpYiv6IItf8AveMMH9E/YsG6Ph3sde5hGoQoblLGuPHfunTPjc49nADxDA110+LTYC7FrPCAPeAO+vZu+aX7c/8PGd45WCJC0OGcfT6FDnmfSTPtwhZFt3HjgDs/Qtu5jPbZHtI/x50XfIzMQbdwEolbg9INP4ku++myPaUtCHYRaT2j1ldIh3VP60/Qff8vSfXLu9BP6JX9K/0TVH6jqVe22P1X/fao/oddWu/paDs1vBf9Jv/EZ91clbyHqv7BL6sscDOd4v4WTqs6jzaHGJ8QJerxlpJSpdZ7IWFJvDW7I2JxZqIM62k6A57RZmMQGmlyrxdV+WGBnmR01mXPI267hBKwp4FeBeo9VPtssxyb7rzHg1B7T9nCMU45U8BZlWuVWtIcD/CRGOqtsbW09851tXsHN0UTlLIAdASjSXnLyLn+H7L2+xbGYvC63Ezqg543egkLmn8qnRF6USbM4Qp9godkhzI777Ne5bCIt/5UtGz2o/yGby0nKpjqmbOa1ynkjmyzIrzvIZUeBPjvlUmbh32EFJbGyJZhR8YcvlS+3TpjhqeWSyvUkpbI9plSWtcKLcsK05beOJVEnhaEFfHEH+RwpeMcpn1JKGqWMNOL+G6wZyahlpdVOtufKfbDS+guLke9O\n\
|
||||||
|
";
|
||||||
|
|
||||||
|
|
||||||
|
int __Core_Initializer__::count_(0);
|
||||||
|
CDCore * __Core_Initializer__::__instance__(0);
|
||||||
|
const uchar header_direct = 0x80;
|
||||||
|
const uchar header_transfer = 0x81;
|
||||||
|
|
||||||
|
|
||||||
|
__Core_Initializer__::__Core_Initializer__() {
|
||||||
|
count_++;
|
||||||
|
if (count_ > 1) return;
|
||||||
|
__instance__ = new CDCore();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__Core_Initializer__::~__Core_Initializer__() {
|
||||||
|
count_--;
|
||||||
|
if (count_ < 0) {
|
||||||
|
count_ = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (count_ > 0) return;
|
||||||
|
if (__instance__) {
|
||||||
|
delete __instance__;
|
||||||
|
__instance__ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CDCore::CDCore() {
|
||||||
|
setName("CDCore");
|
||||||
|
x_timer.setName("__S__.CDCore.x_timer");
|
||||||
|
datatr.setPacketSize(960);
|
||||||
|
CONNECTU(&connection, dataReceivedEvent, this, dataReceived);
|
||||||
|
CONNECTU(PICout::Notifier::object(), finished, this, piCoutFinished);
|
||||||
|
/*PIString s(app_config);
|
||||||
|
connection.configureFromString(&s);
|
||||||
|
connection.start();*/
|
||||||
|
need_rebuild_x = x_pult_side = false;
|
||||||
|
k_.cd_type_ = CDType::cdK;
|
||||||
|
x_.cd_type_ = CDType::cdX;
|
||||||
|
c_.cd_type_ = CDType::cdC;
|
||||||
|
m_.cd_type_ = CDType::cdM;
|
||||||
|
initRoot(&k_);
|
||||||
|
initRoot(&x_);
|
||||||
|
initRoot(&c_);
|
||||||
|
initRoot(&m_);
|
||||||
|
|
||||||
|
CONNECTU(&sendt, started, this, sendThread)
|
||||||
|
CONNECTU(&datatr, sendRequest, this, dtSendRequest)
|
||||||
|
CONNECTU(&datatr, receiveFinished, this, dtReceiveFinished)
|
||||||
|
CONNECTU(&x_timer, tickEvent, this, xTimerTick)
|
||||||
|
|
||||||
|
/*k_[1] = KType(1, "123", "120+3", "comment");
|
||||||
|
k_[2] = KType(2, "1", "2", "comm");
|
||||||
|
k_[4] = KType(4, "-0.6", "-6/10", "mment");
|
||||||
|
k_.section(10)[5] = KType(5, "8", "2*2*2", "88");
|
||||||
|
k_.section(10).section(50)[100] = KType(100, "8", "2*2*2", "88");
|
||||||
|
k_.section(11)[3] = KType(3, "1", "1", "88");
|
||||||
|
k_.section(11)[4] = KType(4, "0", "0", "88");
|
||||||
|
k_.section(11)[6] = KType(6, "0", "0", "88");*/
|
||||||
|
//piCout << s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDCore::~CDCore() {
|
||||||
|
x_timer.stop(true);
|
||||||
|
datatr.stop();
|
||||||
|
sendt.stop();
|
||||||
|
sendt.waitForFinish(10);
|
||||||
|
connection.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::cd_write(CDSection * cd, PIIODevice * d) {
|
||||||
|
cd->write(d, PIString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::cd_read(CDSection * cd, PIIODevice * d) {
|
||||||
|
PIConfig conf(d, PIIODevice::ReadOnly);
|
||||||
|
cd->read(&(conf.rootEntry()));
|
||||||
|
if (cd->cd_type_ == CDType::cdX)
|
||||||
|
x_selected = cd->collectX();
|
||||||
|
initRoot(cd);
|
||||||
|
raiseChangedGlobal(cd->cd_type_);
|
||||||
|
/*PIVector<PIIODevice * > ds = connection.allDevices();
|
||||||
|
piForeach(PIIODevice * d, ds) {
|
||||||
|
if (d)
|
||||||
|
piCoutObj << d->constructFullPath() << d->isOpened();
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::cd_parse(CDSection * cd, PIIODevice * d) {
|
||||||
|
*cd = CDParser::parse(d, cd->cd_type_);
|
||||||
|
initRoot(cd);
|
||||||
|
raiseChangedGlobal(cd->cd_type_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::cd_update(CDSection * cd, PIIODevice * d, UpdateModeFlags mode) {
|
||||||
|
CDSection ucd = *cd;
|
||||||
|
cd_parse(cd, d);
|
||||||
|
/*bool kn = true;
|
||||||
|
if (!ucd.isEmpty())
|
||||||
|
if (!ucd.isSameStructure(k_)) {
|
||||||
|
piCout << "ask for save names";
|
||||||
|
K_KeepNamesRequest(&kn);
|
||||||
|
}*/
|
||||||
|
ucd.update(*cd, mode);
|
||||||
|
//piCout << k_.count() << ucd.count();
|
||||||
|
*cd = ucd;
|
||||||
|
initRoot(cd);
|
||||||
|
raiseChangedGlobal(cd->cd_type_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::cd_calculate(CDSection * cd) {
|
||||||
|
cd->calculate();
|
||||||
|
raiseChangedGlobal(cd->cd_type_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::cd_send(CDSection * cd, CDPacketType pt, bool direct) {
|
||||||
|
if (!cd) return;
|
||||||
|
PIByteArray ba, sba;
|
||||||
|
PIIOByteArray iob(&ba, PIIODevice::ReadWrite);
|
||||||
|
cd_write(cd, &iob);
|
||||||
|
//piCoutObj << PIString(ba);
|
||||||
|
sba = makeHeader(pt, 0);
|
||||||
|
sba << ba;
|
||||||
|
if (direct)
|
||||||
|
sendDirect(sba);
|
||||||
|
else
|
||||||
|
sendThreaded(sba);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::send(CDType::cdT cdt) {
|
||||||
|
CDPacketType pt = CD_Ping;
|
||||||
|
switch (cdt) {
|
||||||
|
case CDType::cdK: pt = CD_KSend; break;
|
||||||
|
case CDType::cdX: pt = CD_XSend; break;
|
||||||
|
case CDType::cdC: pt = CD_CSend; break;
|
||||||
|
case CDType::cdM: pt = CD_MSend; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
piCoutObj << "send" << typeLetter(cdt);
|
||||||
|
cd_send(root(cdt), pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::request(CDType::cdT cdt) {
|
||||||
|
CDPacketType pt = CD_Ping;
|
||||||
|
switch (cdt) {
|
||||||
|
case CDType::cdK: pt = CD_KQuery; break;
|
||||||
|
case CDType::cdX: pt = CD_XQuery; break;
|
||||||
|
case CDType::cdC: pt = CD_CQuery; break;
|
||||||
|
case CDType::cdM: pt = CD_MQuery; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
piCoutObj << "request" << typeLetter(cdt);
|
||||||
|
PIByteArray sba = makeHeader(pt, 0);
|
||||||
|
sendThreaded(sba);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::initApp() {
|
||||||
|
init(appConfig(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::initPult() {
|
||||||
|
init(pultConfig(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::init(const PIString & configuration, bool pult) {
|
||||||
|
PIString c = configuration;
|
||||||
|
//piCoutObj << "init" << c;
|
||||||
|
connection.stop();
|
||||||
|
connection.removeAllDevices();
|
||||||
|
connection.configureFromString(&c);
|
||||||
|
connection.start();
|
||||||
|
x_pult_side = pult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::stop() {
|
||||||
|
x_timer.stop();
|
||||||
|
x_timer.waitForFinish(1000);
|
||||||
|
connection.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::release() {
|
||||||
|
stop();
|
||||||
|
connection.removeAllDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::startX(double freq) {
|
||||||
|
//piCout << "start x" << x_timer.isRunning() << freq;
|
||||||
|
if (!x_timer.isRunning())
|
||||||
|
x_timer.start(1000. / piMaxd(freq, 0.01));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::stopX() {
|
||||||
|
x_timer.stop();
|
||||||
|
x_timer.waitForFinish(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::sendCommand(const CDType & c) {
|
||||||
|
//piCoutObj << "C_sendCommand" << c;
|
||||||
|
PIByteArray sba = makeHeader(CD_Command, 0);
|
||||||
|
sba << c.path();
|
||||||
|
sendDirect(sba);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::registerCHandler(const CDType & c, PIObject * o, Handler h) {
|
||||||
|
PIString sp = pathToString(c.path());
|
||||||
|
if (sp.isEmpty() || !h) return;
|
||||||
|
//piCout << "register" << sp;
|
||||||
|
c_handlers[sp] = OHPair(o, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::sendMessage(const CDType & m, MessageType mt, const PIString & msg) {
|
||||||
|
if (msg.isEmpty() || (m.cd_type() != CDType::cdM)) return;
|
||||||
|
PIByteArray sba = makeHeader(CD_Message, 0);
|
||||||
|
sba << m.path() << int(mt) << msg;
|
||||||
|
sendDirect(sba);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDSection * CDCore::root(CDType::cdT cdt) {
|
||||||
|
switch (cdt) {
|
||||||
|
case CDType::cdK: return &k_; break;
|
||||||
|
case CDType::cdX: return &x_; break;
|
||||||
|
case CDType::cdC: return &c_; break;
|
||||||
|
case CDType::cdM: return &m_; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIString CDCore::typeLetter(CDType::cdT cdt) {
|
||||||
|
switch (cdt) {
|
||||||
|
case CDType::cdK: return PIStringAscii("k"); break;
|
||||||
|
case CDType::cdX: return PIStringAscii("x"); break;
|
||||||
|
case CDType::cdC: return PIStringAscii("c"); break;
|
||||||
|
case CDType::cdM: return PIStringAscii("m"); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return PIString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDCore * CDCore::instance() {
|
||||||
|
/*static CDCore * ret = new CDCore();
|
||||||
|
return ret;*/
|
||||||
|
return __Core_Initializer__::__instance__;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CDCore::destroy() {
|
||||||
|
if (!__Core_Initializer__::__instance__) return false;
|
||||||
|
// piCout << "delete Core ...";
|
||||||
|
delete __Core_Initializer__::__instance__;
|
||||||
|
// piCout << "delete Core ok";
|
||||||
|
__Core_Initializer__::__instance__ = 0;
|
||||||
|
__Core_Initializer__::count_ = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDUtils::CDCore::K_DirectChange(PIDeque<int> path, PIString value) {
|
||||||
|
// piCoutObj << "K_DirectChange";
|
||||||
|
PacketKDirectChange p;
|
||||||
|
p.path = path;
|
||||||
|
p.value = value;
|
||||||
|
PIByteArray sba = makeHeader(CD_KDirectChange, 0);
|
||||||
|
sba << p;
|
||||||
|
sendDirect(sba);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::sendThread() {
|
||||||
|
if (send_data.size_s() < 4) return;
|
||||||
|
PacketHeader h;
|
||||||
|
memcpy(&h, send_data.data(), sizeof(h));
|
||||||
|
bool ok = datatr.send(send_data);
|
||||||
|
switch (h.type) {
|
||||||
|
case CD_KSend:
|
||||||
|
if (ok) K_Sended();
|
||||||
|
else K_SendFail();
|
||||||
|
break;
|
||||||
|
case CD_KQuery:
|
||||||
|
if (!ok) K_ReceiveFail();
|
||||||
|
break;
|
||||||
|
case CD_XSend:
|
||||||
|
if (ok) X_Sended();
|
||||||
|
else X_SendFail();
|
||||||
|
break;
|
||||||
|
case CD_XQuery:
|
||||||
|
if (!ok) X_ReceiveFail();
|
||||||
|
break;
|
||||||
|
case CD_CSend:
|
||||||
|
if (ok) C_Sended();
|
||||||
|
else C_SendFail();
|
||||||
|
break;
|
||||||
|
case CD_CQuery:
|
||||||
|
if (!ok) C_ReceiveFail();
|
||||||
|
break;
|
||||||
|
case CD_MSend:
|
||||||
|
if (ok) M_Sended();
|
||||||
|
else M_SendFail();
|
||||||
|
break;
|
||||||
|
case CD_MQuery:
|
||||||
|
if (!ok) M_ReceiveFail();
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::xTimerTick() {
|
||||||
|
//piCout << "x tick" << x_pult_side;
|
||||||
|
PIByteArray ba;
|
||||||
|
x_mutex.lock();
|
||||||
|
if (x_pult_side) {
|
||||||
|
ba = makeHeader(CD_XRequest, 0);
|
||||||
|
if (need_rebuild_x) {
|
||||||
|
x_selected = x_.collectX();
|
||||||
|
//piCout << "collectX" << x_selected.size();
|
||||||
|
need_rebuild_x = false;
|
||||||
|
}
|
||||||
|
ba << x_selected;
|
||||||
|
//piCout << "x pult send" << x_selected.size();
|
||||||
|
} else {
|
||||||
|
ba = makeHeader(CD_XValues, 0);
|
||||||
|
ba << x_selected;
|
||||||
|
piForeachC (PIDeque<int> & p, x_selected) {
|
||||||
|
x_[p].writeX(ba);
|
||||||
|
}
|
||||||
|
//piCout << "x app" << x_selected.size();
|
||||||
|
}
|
||||||
|
x_mutex.unlock();
|
||||||
|
sendDirect(ba);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::piCoutFinished(int id, PIString * buffer) {
|
||||||
|
if (!buffer || !(id == 1)) return;
|
||||||
|
PIString sp = buffer->takeRange("[", "]");
|
||||||
|
PIDeque<int> p = CDCore::stringToPath(sp);
|
||||||
|
sendMessage(m_[p], Log, *buffer);
|
||||||
|
delete buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::initRoot(CDSection * r) {
|
||||||
|
r->name = "__root__";
|
||||||
|
r->alias = "root";
|
||||||
|
r->makePath();
|
||||||
|
r->calculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIByteArray CDCore::makeHeader(CDPacketType type, int session_id) const {
|
||||||
|
PacketHeader h;
|
||||||
|
h.type = type;
|
||||||
|
h.session_id = session_id;
|
||||||
|
PIByteArray ret; ret << h;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::sendDirect(PIByteArray & ba) {
|
||||||
|
ba.push_front(header_direct);
|
||||||
|
connection.writeByName("cd", ba);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::sendThreaded(PIByteArray & ba) {
|
||||||
|
if (sendt.isRunning()) {
|
||||||
|
piCoutObj << "Send in process, abort";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
send_data = ba;
|
||||||
|
sendt.startOnce();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::procReceivedPacket(PIByteArray & ba) {
|
||||||
|
PacketHeader h;
|
||||||
|
ba >> h;
|
||||||
|
switch(h.type) {
|
||||||
|
case CD_Ping:
|
||||||
|
//piCoutObj << "ping";
|
||||||
|
break;
|
||||||
|
case CD_KQuery:
|
||||||
|
send(CDType::cdK);
|
||||||
|
break;
|
||||||
|
case CD_KSend: {
|
||||||
|
PIByteArray k;
|
||||||
|
ba >> k;
|
||||||
|
k << uchar(0);
|
||||||
|
PIString s = PIString::fromUTF8((const char *)k.data());
|
||||||
|
PIIOString ios(&s);
|
||||||
|
cd_read(&k_, &ios);
|
||||||
|
K_Received();
|
||||||
|
piCoutObj << "K received";
|
||||||
|
} break;
|
||||||
|
case CD_KDirectChange: {
|
||||||
|
PacketKDirectChange p;
|
||||||
|
ba >> p;
|
||||||
|
k_[p.path].setValue(p.value);
|
||||||
|
} break;
|
||||||
|
case CD_XQuery:
|
||||||
|
send(CDType::cdX);
|
||||||
|
break;
|
||||||
|
case CD_XSend: {
|
||||||
|
PIByteArray x;
|
||||||
|
ba >> x;
|
||||||
|
x << uchar(0);
|
||||||
|
PIString s = PIString::fromUTF8((const char *)x.data());
|
||||||
|
PIIOString ios(&s);
|
||||||
|
cd_read(&x_, &ios);
|
||||||
|
x_selected = x_.collectX();
|
||||||
|
X_Received();
|
||||||
|
piCoutObj << "X received";
|
||||||
|
} break;
|
||||||
|
case CD_XRequest: {
|
||||||
|
if (x_pult_side) break;
|
||||||
|
//break;
|
||||||
|
x_mutex.lock();
|
||||||
|
x_selected.clear();
|
||||||
|
ba >> x_selected;
|
||||||
|
//piCout << "X req" << x_selected.size();
|
||||||
|
x_.setSelectedX(false);
|
||||||
|
piForeachC (PIDeque<int> & p, x_selected) {
|
||||||
|
x_[p].x_enabled = true;
|
||||||
|
}
|
||||||
|
x_mutex.unlock();
|
||||||
|
} break;
|
||||||
|
case CD_XValues: {
|
||||||
|
if (!x_pult_side) break;
|
||||||
|
PIVector<PIDeque<int> > x_vals;
|
||||||
|
ba >> x_vals;
|
||||||
|
x_mutex.lock();
|
||||||
|
piForeachC (PIDeque<int> & p, x_vals) {
|
||||||
|
x_[p].readX(ba);
|
||||||
|
}
|
||||||
|
x_mutex.unlock();
|
||||||
|
X_ReceivedX(x_vals);
|
||||||
|
} break;
|
||||||
|
case CD_CQuery:
|
||||||
|
send(CDType::cdC);
|
||||||
|
break;
|
||||||
|
case CD_CSend: {
|
||||||
|
piCoutObj << "C received";
|
||||||
|
PIByteArray c;
|
||||||
|
ba >> c;
|
||||||
|
c << uchar(0);
|
||||||
|
PIString s = PIString::fromUTF8((const char *)c.data());
|
||||||
|
PIIOString ios(&s);
|
||||||
|
cd_read(&c_, &ios);
|
||||||
|
C_Received();
|
||||||
|
} break;
|
||||||
|
case CD_Command: {
|
||||||
|
piCoutObj << "C command";
|
||||||
|
PIDeque<int> p;
|
||||||
|
ba >> p;
|
||||||
|
if (p.isEmpty()) return;
|
||||||
|
PIString sp = pathToString(p);
|
||||||
|
OHPair h = c_handlers.value(sp, OHPair(0, 0));
|
||||||
|
//piCoutObj << "found" << sp << h.first;
|
||||||
|
if (h.first && h.second) h.second(h.first);
|
||||||
|
} break;
|
||||||
|
case CD_MQuery:
|
||||||
|
send(CDType::cdM);
|
||||||
|
break;
|
||||||
|
case CD_MSend: {
|
||||||
|
piCoutObj << "M received";
|
||||||
|
PIByteArray c;
|
||||||
|
ba >> c;
|
||||||
|
c << uchar(0);
|
||||||
|
PIString s = PIString::fromUTF8((const char *)c.data());
|
||||||
|
PIIOString ios(&s);
|
||||||
|
cd_read(&m_, &ios);
|
||||||
|
M_Received();
|
||||||
|
} break;
|
||||||
|
case CD_Message: {
|
||||||
|
PIDeque<int> p;
|
||||||
|
ba >> p;
|
||||||
|
piCoutObj << "M message" << p;
|
||||||
|
if (p.isEmpty()) return;
|
||||||
|
int t = 0;
|
||||||
|
PIString msg;
|
||||||
|
ba >> t >> msg;
|
||||||
|
//piCoutObj << "found" << sp << h.first;
|
||||||
|
//piCoutObj << "M message invoke";
|
||||||
|
M_Message(p, t, msg);
|
||||||
|
} break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::raiseChangedGlobal(CDType::cdT cdt) {
|
||||||
|
switch (cdt) {
|
||||||
|
case CDType::cdK: K_ChangedGlobal(); break;
|
||||||
|
case CDType::cdX: X_ChangedGlobal(); break;
|
||||||
|
case CDType::cdC: C_ChangedGlobal(); break;
|
||||||
|
case CDType::cdM: M_ChangedGlobal(); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIString CDCore::pathToString(const PIDeque<int> & p) {
|
||||||
|
PIString ret;
|
||||||
|
for (int i = 0; i < p.size_s(); ++i) {
|
||||||
|
if (!ret.isEmpty()) ret += ".";
|
||||||
|
ret << p[i];
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIDeque<int> CDCore::stringToPath(const PIString & p) {
|
||||||
|
PIDeque<int> ret;
|
||||||
|
PIStringList sl = p.split(".");
|
||||||
|
piForeachC (PIString & s, sl)
|
||||||
|
ret << s.toInt();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDUtils::CDCore::dataReceived(const PIString & from, const PIByteArray & data) {
|
||||||
|
//piCoutObj << "dataReceived" << from << data.size();
|
||||||
|
PIIODevice * d = connection.deviceByName("cd");
|
||||||
|
if (d && d == connection.deviceByFullPath(from)) {
|
||||||
|
if (data.size() >= sizeof(4)) {
|
||||||
|
PIByteArray ba = data;
|
||||||
|
uchar header = ba.take_front();
|
||||||
|
if (header == header_transfer) {
|
||||||
|
datatr.received(ba);
|
||||||
|
}
|
||||||
|
if (header == header_direct) {
|
||||||
|
procReceivedPacket(ba);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::dtSendRequest(PIByteArray & data) {
|
||||||
|
data.push_front(header_transfer);
|
||||||
|
connection.writeByName("cd", data);
|
||||||
|
//piCoutObj << "send" << data.size() << ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDCore::dtReceiveFinished(bool ok) {
|
||||||
|
if (!ok) return;
|
||||||
|
PIByteArray ba = datatr.data();
|
||||||
|
procReceivedPacket(ba);
|
||||||
|
}
|
||||||
|
|
||||||
147
cd_utils/cdutils_core.h
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
CD Utils - Control-Debug utilites
|
||||||
|
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CDUTILS_CORE_H
|
||||||
|
#define CDUTILS_CORE_H
|
||||||
|
|
||||||
|
#include "cdutils_types.h"
|
||||||
|
#include "cdutils_protocol.h"
|
||||||
|
#include "piconnection.h"
|
||||||
|
#include "pidatatransfer.h"
|
||||||
|
#include "cd_utils_export.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace CDUtils {
|
||||||
|
|
||||||
|
class CDCore;
|
||||||
|
|
||||||
|
|
||||||
|
class CD_UTILS_EXPORT __Core_Initializer__ {
|
||||||
|
public:
|
||||||
|
__Core_Initializer__();
|
||||||
|
~__Core_Initializer__();
|
||||||
|
static int count_;
|
||||||
|
static CDCore * __instance__;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CD_UTILS_EXPORT CDCore: public PIObject
|
||||||
|
{
|
||||||
|
PIOBJECT(CDUtils::CDCore)
|
||||||
|
friend class __Core_Initializer__;
|
||||||
|
friend class CDSection;
|
||||||
|
friend class Interface;
|
||||||
|
friend class XInterface;
|
||||||
|
public:
|
||||||
|
static CDCore * instance();
|
||||||
|
static bool destroy();
|
||||||
|
|
||||||
|
EVENT(K_Sended)
|
||||||
|
EVENT(K_SendFail)
|
||||||
|
EVENT(K_Received)
|
||||||
|
EVENT(K_ReceiveFail)
|
||||||
|
EVENT(K_ChangedGlobal)
|
||||||
|
EVENT_HANDLER2(void, K_DirectChange, PIDeque<int>, path, PIString, value);
|
||||||
|
|
||||||
|
EVENT(X_Sended)
|
||||||
|
EVENT(X_SendFail)
|
||||||
|
EVENT(X_Received)
|
||||||
|
EVENT(X_ReceiveFail)
|
||||||
|
EVENT(X_ChangedGlobal)
|
||||||
|
EVENT1(X_ReceivedX, PIVector<PIDeque<int> >, pathes)
|
||||||
|
|
||||||
|
EVENT(C_Sended)
|
||||||
|
EVENT(C_SendFail)
|
||||||
|
EVENT(C_Received)
|
||||||
|
EVENT(C_ReceiveFail)
|
||||||
|
EVENT(C_ChangedGlobal)
|
||||||
|
|
||||||
|
EVENT(M_Sended)
|
||||||
|
EVENT(M_SendFail)
|
||||||
|
EVENT(M_Received)
|
||||||
|
EVENT(M_ReceiveFail)
|
||||||
|
EVENT(M_ChangedGlobal)
|
||||||
|
EVENT3(M_Message, PIDeque<int>, path, int, type, PIString, msg)
|
||||||
|
|
||||||
|
void cd_write (CDSection * cd, PIIODevice * d);
|
||||||
|
void cd_read (CDSection * cd, PIIODevice * d);
|
||||||
|
void cd_parse (CDSection * cd, PIIODevice * d);
|
||||||
|
void cd_update (CDSection * cd, PIIODevice * d, UpdateModeFlags mode);
|
||||||
|
void cd_calculate(CDSection * cd);
|
||||||
|
void cd_send (CDSection * cd, CDPacketType pt, bool direct = false);
|
||||||
|
void send(CDType::cdT cdt);
|
||||||
|
void request(CDType::cdT cdt);
|
||||||
|
void initApp();
|
||||||
|
void initPult();
|
||||||
|
void init(const PIString & configuration, bool pult = false);
|
||||||
|
void stop();
|
||||||
|
void release();
|
||||||
|
void startX(double freq = 20.);
|
||||||
|
void stopX();
|
||||||
|
void sendCommand(const CDType & c);
|
||||||
|
void registerCHandler(const CDType & c, PIObject * o, Handler h);
|
||||||
|
bool inProgress() {return sendt.isRunning();}
|
||||||
|
void sendMessage(const CDType & m, MessageType mt, const PIString & msg);
|
||||||
|
|
||||||
|
CDSection * root(CDType::cdT cdt);
|
||||||
|
PIString typeLetter(CDType::cdT cdt);
|
||||||
|
static PIString pathToString(const PIDeque<int> & p);
|
||||||
|
static PIDeque<int> stringToPath(const PIString & p);
|
||||||
|
|
||||||
|
static PIString pultConfig() {return PIString(pult_config);}
|
||||||
|
static PIString appConfig() {return PIString(app_config);}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CDCore();
|
||||||
|
~CDCore();
|
||||||
|
EVENT_HANDLER2(void, dataReceived, const PIString &, from, const PIByteArray &, data);
|
||||||
|
EVENT_HANDLER1(void, dtSendRequest, PIByteArray &, data);
|
||||||
|
EVENT_HANDLER1(void, dtReceiveFinished, bool, ok);
|
||||||
|
EVENT_HANDLER(void, sendThread);
|
||||||
|
EVENT_HANDLER(void, xTimerTick);
|
||||||
|
EVENT_HANDLER2(void, piCoutFinished, int, id, PIString*, buffer);
|
||||||
|
void initRoot(CDSection * r);
|
||||||
|
PIByteArray makeHeader(CDPacketType type, int session_id = 0) const;
|
||||||
|
void sendDirect(PIByteArray & ba);
|
||||||
|
void sendThreaded(PIByteArray & ba);
|
||||||
|
void procReceivedPacket(PIByteArray & ba);
|
||||||
|
void raiseChangedGlobal(CDType::cdT cdt);
|
||||||
|
|
||||||
|
typedef PIPair<PIObject * , Handler> OHPair;
|
||||||
|
|
||||||
|
static const char app_config[], pult_config[];
|
||||||
|
PIConnection connection;
|
||||||
|
PIDataTransfer datatr;
|
||||||
|
PIByteArray send_data;
|
||||||
|
PIThread sendt;
|
||||||
|
PITimer x_timer;
|
||||||
|
CDSection k_, x_, c_, m_;
|
||||||
|
PIMutex x_mutex;
|
||||||
|
PIVector<PIDeque<int> > x_selected;
|
||||||
|
PIMap<PIString, OHPair> c_handlers;
|
||||||
|
bool need_rebuild_x, x_pult_side;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static __Core_Initializer__ __Core_initializer__;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CDUTILS_CORE_H
|
||||||
217
cd_utils/cdutils_interface.cpp
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
#include "cdutils_interface.h"
|
||||||
|
#include "cdutils_core.h"
|
||||||
|
#include "piconfig.h"
|
||||||
|
#include "pifile.h"
|
||||||
|
|
||||||
|
using namespace CDUtils;
|
||||||
|
|
||||||
|
|
||||||
|
Interface::Interface(CDType::cdT type_) {
|
||||||
|
core = CDCore::instance();
|
||||||
|
s = core->root(type_);
|
||||||
|
type = type_;
|
||||||
|
//piCoutObj << (void*)this << core;
|
||||||
|
file_ = core->typeLetter(type_) + PIStringAscii(".dat");
|
||||||
|
file_size = 0;
|
||||||
|
switch (type) {
|
||||||
|
case CDType::cdK:
|
||||||
|
CONNECTU(core, K_Sended, this, sended);
|
||||||
|
CONNECTU(core, K_SendFail, this, sendFailed);
|
||||||
|
CONNECTU(core, K_Received, this, received);
|
||||||
|
CONNECTU(core, K_ReceiveFail, this, receiveFailed);
|
||||||
|
CONNECTU(core, K_ChangedGlobal, this, changedGlobal);
|
||||||
|
break;
|
||||||
|
case CDType::cdX:
|
||||||
|
CONNECTU(core, X_Sended, this, sended);
|
||||||
|
CONNECTU(core, X_SendFail, this, sendFailed);
|
||||||
|
CONNECTU(core, X_Received, this, received);
|
||||||
|
CONNECTU(core, X_ReceiveFail, this, receiveFailed);
|
||||||
|
CONNECTU(core, X_ChangedGlobal, this, changedGlobal);
|
||||||
|
break;
|
||||||
|
case CDType::cdC:
|
||||||
|
CONNECTU(core, C_Sended, this, sended);
|
||||||
|
CONNECTU(core, C_SendFail, this, sendFailed);
|
||||||
|
CONNECTU(core, C_Received, this, received);
|
||||||
|
CONNECTU(core, C_ReceiveFail, this, receiveFailed);
|
||||||
|
CONNECTU(core, C_ChangedGlobal, this, changedGlobal);
|
||||||
|
break;
|
||||||
|
case CDType::cdM:
|
||||||
|
CONNECTU(core, M_Sended, this, sended);
|
||||||
|
CONNECTU(core, M_SendFail, this, sendFailed);
|
||||||
|
CONNECTU(core, M_Received, this, received);
|
||||||
|
CONNECTU(core, M_ReceiveFail, this, receiveFailed);
|
||||||
|
CONNECTU(core, M_ChangedGlobal, this, changedGlobal);
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Interface::test(int v) {
|
||||||
|
return s->test(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDType & Interface::operator [](const PIString & name_) {
|
||||||
|
return (*s)[name_];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const CDType Interface::operator [](const PIString & name_) const {
|
||||||
|
return (*s)[name_];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDType & Interface::operator [](const PIDeque<int> & path_) {
|
||||||
|
return (*s)[path_];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const CDType Interface::operator [](const PIDeque<int> & path_) const {
|
||||||
|
return (*s)[path_];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDType & Interface::operator [](int v) {
|
||||||
|
//piCout << (void*)this << "[]" << core;
|
||||||
|
return (*s)[v];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const CDType Interface::operator [](int v) const {
|
||||||
|
//piCout << (void*)this << "[]" << core;
|
||||||
|
return (*s)[v];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDSection & Interface::section(int v) {
|
||||||
|
// CDSection & ret = s->section(v);
|
||||||
|
// piCout << "[get section]" << v << ret.name;
|
||||||
|
return s->section(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const CDSection Interface::section(int v) const {
|
||||||
|
return s->section(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDSection & Interface::section(const PIDeque<int> &path) {
|
||||||
|
PIDeque<int> spath = path;
|
||||||
|
CDSection * rs = s;
|
||||||
|
while (!spath.isEmpty()) {
|
||||||
|
rs = &(rs->section(spath.take_front()));
|
||||||
|
}
|
||||||
|
return *rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDSection & Interface::root() {
|
||||||
|
return *s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const CDSection & Interface::root() const {
|
||||||
|
return *s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Interface::count(bool recursive) const {
|
||||||
|
return s->count(recursive);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Interface::exists(PIDeque<int> path) const {
|
||||||
|
return s->exists(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Interface::setFileName(const PIString & _file) {
|
||||||
|
file_ = _file;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Interface::configure(const PIString & config) {
|
||||||
|
PIConfig conf(config, PIIODevice::ReadOnly);
|
||||||
|
PIConfig::Entry & e(conf.getValue(core->typeLetter(s->cd_type_)));
|
||||||
|
bool ret = false;
|
||||||
|
setFileName(e.getValue("file", file(), &ret).toString());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Interface::reinitConnection(const PIString & configuration) {
|
||||||
|
core->init(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Interface::releaseConnection() {
|
||||||
|
core->release();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Interface::write(PIIODevice * d) {
|
||||||
|
core->cd_write(s, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Interface::read(PIIODevice * d) {
|
||||||
|
core->cd_read(s, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Interface::parse(PIIODevice * d) {
|
||||||
|
core->cd_parse(s, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Interface::update(PIIODevice * d, UpdateModeFlags mode) {
|
||||||
|
core->cd_update(s, d, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Interface::calculate() {
|
||||||
|
core->cd_calculate(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIString Interface::appConfig() {
|
||||||
|
return core->appConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIString Interface::pultConfig() {
|
||||||
|
return core->pultConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Interface::readFile() {
|
||||||
|
if (file_.isEmpty()) return;
|
||||||
|
PIFile f(file_, PIIODevice::ReadOnly);
|
||||||
|
read(&f);
|
||||||
|
file_size = f.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Interface::writeFile() {
|
||||||
|
if (file_.isEmpty()) return;
|
||||||
|
PIFile f(file_, PIIODevice::ReadWrite);
|
||||||
|
f.clear();
|
||||||
|
write(&f);
|
||||||
|
file_size = f.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Interface::inProgress() {
|
||||||
|
return core->inProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Interface::send() {
|
||||||
|
core->send(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Interface::request() {
|
||||||
|
core->request(type);
|
||||||
|
}
|
||||||
96
cd_utils/cdutils_interface.h
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
CD Utils - Control-Debug utilites
|
||||||
|
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CDUTILS_INTERFACE_H
|
||||||
|
#define CDUTILS_INTERFACE_H
|
||||||
|
|
||||||
|
#include "cdutils_types.h"
|
||||||
|
#include "piobject.h"
|
||||||
|
#include "cd_utils_export.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace CDUtils {
|
||||||
|
|
||||||
|
class CDCore;
|
||||||
|
|
||||||
|
|
||||||
|
class CD_UTILS_EXPORT Interface: public PIObject
|
||||||
|
{
|
||||||
|
PIOBJECT(CDUtils::Interface)
|
||||||
|
public:
|
||||||
|
Interface(CDType::cdT type_);
|
||||||
|
|
||||||
|
bool test(int v);
|
||||||
|
CDType & operator [](int v);
|
||||||
|
const CDType operator [](int v) const;
|
||||||
|
CDType & operator [](const PIString & name_);
|
||||||
|
const CDType operator [](const PIString & name_) const;
|
||||||
|
CDType & operator [](const PIDeque<int> & path_);
|
||||||
|
const CDType operator [](const PIDeque<int> & path_) const;
|
||||||
|
CDSection & section(int v);
|
||||||
|
const CDSection section(int v) const;
|
||||||
|
CDSection & section(const PIDeque<int> & path);
|
||||||
|
CDSection & root();
|
||||||
|
const CDSection & root() const;
|
||||||
|
|
||||||
|
int count(bool recursive = true) const;
|
||||||
|
const PIString file() const {return file_;}
|
||||||
|
int fileSize() const {return file_size;}
|
||||||
|
CDType::cdT cdType() const {return type;}
|
||||||
|
bool exists(PIDeque<int> path) const;
|
||||||
|
|
||||||
|
void setFileName(const PIString & _file);
|
||||||
|
bool configure(const PIString & config);
|
||||||
|
void reinitConnection(const PIString & configuration);
|
||||||
|
void releaseConnection();
|
||||||
|
void write(PIIODevice * d);
|
||||||
|
void read(PIIODevice * d);
|
||||||
|
void parse(PIIODevice * d);
|
||||||
|
void update(PIIODevice * d, UpdateModeFlags mode = SaveByName);
|
||||||
|
void calculate();
|
||||||
|
|
||||||
|
PIString appConfig();
|
||||||
|
PIString pultConfig();
|
||||||
|
|
||||||
|
void readFile();
|
||||||
|
void writeFile();
|
||||||
|
bool inProgress();
|
||||||
|
|
||||||
|
EVENT(sended)
|
||||||
|
EVENT(sendFailed)
|
||||||
|
EVENT(received)
|
||||||
|
EVENT(receiveFailed)
|
||||||
|
EVENT(changedGlobal)
|
||||||
|
EVENT_HANDLER(void, send);
|
||||||
|
EVENT_HANDLER(void, request);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CDCore * core;
|
||||||
|
CDSection * s;
|
||||||
|
CDType::cdT type;
|
||||||
|
PIString file_;
|
||||||
|
int file_size;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CDUTILS_INTERFACE_H
|
||||||
20
cd_utils/cdutils_k.cpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include "cdutils_k.h"
|
||||||
|
#include "cdutils_core.h"
|
||||||
|
|
||||||
|
using namespace CDUtils;
|
||||||
|
|
||||||
|
KInterface K;
|
||||||
|
|
||||||
|
|
||||||
|
KInterface::KInterface(): Interface(CDType::cdK) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KInterface::directChange(const CDType & k) {
|
||||||
|
core->K_DirectChange(k.path(), k.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KInterface::directChange(const CDType & k, double v) {
|
||||||
|
core->K_DirectChange(k.path(), PIString::fromNumber(v));
|
||||||
|
}
|
||||||
47
cd_utils/cdutils_k.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
CD Utils - Control-Debug utilites
|
||||||
|
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CDUTILS_K_H
|
||||||
|
#define CDUTILS_K_H
|
||||||
|
|
||||||
|
#include "cdutils_interface.h"
|
||||||
|
#include "cd_utils_export.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace CDUtils {
|
||||||
|
|
||||||
|
|
||||||
|
class CD_UTILS_EXPORT KInterface: public Interface
|
||||||
|
{
|
||||||
|
PIOBJECT_SUBCLASS(KInterface, Interface)
|
||||||
|
public:
|
||||||
|
KInterface();
|
||||||
|
|
||||||
|
EVENT1(keepNamesRequest, bool*, kn)
|
||||||
|
|
||||||
|
void directChange(const CDType & k);
|
||||||
|
void directChange(const CDType & k, double v);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern CD_UTILS_EXPORT CDUtils::KInterface K;
|
||||||
|
|
||||||
|
#endif // CDUTILS_K_H
|
||||||
22
cd_utils/cdutils_m.cpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#include "cdutils_m.h"
|
||||||
|
#include "cdutils_core.h"
|
||||||
|
|
||||||
|
using namespace CDUtils;
|
||||||
|
|
||||||
|
MInterface M;
|
||||||
|
|
||||||
|
|
||||||
|
MInterface::MInterface(): Interface(CDType::cdM) {
|
||||||
|
CONNECTU(core, M_Message, this, messageReceived);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MInterface::messageBox(const CDType & m, const PIString & msg) {
|
||||||
|
core->sendMessage(m, MessageBox, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PICout MInterface::createPICout(const CDType & m) const {
|
||||||
|
PIString * buff = new PIString("[" + CDCore::pathToString(m.path()) + "]");
|
||||||
|
return PICout(buff, 1);
|
||||||
|
}
|
||||||
56
cd_utils/cdutils_m.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
CD Utils - Control-Debug utilites
|
||||||
|
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CDUTILS_M_H
|
||||||
|
#define CDUTILS_M_H
|
||||||
|
|
||||||
|
#include "cdutils_interface.h"
|
||||||
|
#include "cd_utils_export.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace CDUtils {
|
||||||
|
|
||||||
|
|
||||||
|
class CD_UTILS_EXPORT MInterface: public Interface
|
||||||
|
{
|
||||||
|
PIOBJECT_SUBCLASS(MInterface, Interface)
|
||||||
|
public:
|
||||||
|
MInterface();
|
||||||
|
|
||||||
|
PICout operator [](int v) {return createPICout((*s)[v]);}
|
||||||
|
PICout operator [](int v) const {return createPICout((*s)[v]);}
|
||||||
|
PICout operator [](const PIString & name_) {return createPICout((*s)[name_]);}
|
||||||
|
PICout operator [](const PIString & name_) const {return createPICout((*s)[name_]);}
|
||||||
|
PICout operator [](const PIDeque<int> & path_) {return createPICout((*s)[path_]);}
|
||||||
|
PICout operator [](const PIDeque<int> & path_) const {return createPICout((*s)[path_]);}
|
||||||
|
|
||||||
|
void messageBox(const CDType & m, const PIString & msg);
|
||||||
|
|
||||||
|
EVENT3(messageReceived, PIDeque<int>, path, int, type, PIString, msg)
|
||||||
|
|
||||||
|
private:
|
||||||
|
PICout createPICout(const CDType & m) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern CD_UTILS_EXPORT CDUtils::MInterface M;
|
||||||
|
|
||||||
|
#endif // CDUTILS_M_H
|
||||||
196
cd_utils/cdutils_parser.cpp
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
#include "cdutils_parser.h"
|
||||||
|
#include "cdutils_types.h"
|
||||||
|
#include "piiostring.h"
|
||||||
|
#include "piiobytearray.h"
|
||||||
|
#include "pifile.h"
|
||||||
|
|
||||||
|
using namespace CDUtils;
|
||||||
|
|
||||||
|
enum Phase {
|
||||||
|
eName = 1,
|
||||||
|
eBracketOpen,
|
||||||
|
eBracketClose,
|
||||||
|
eMemberName,
|
||||||
|
eMemberEqual,
|
||||||
|
eMemberValue,
|
||||||
|
eMemberComma,
|
||||||
|
eComment,
|
||||||
|
eMultiComment
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void removeComment(PIString & line, PIString * type, PIString * comment) {
|
||||||
|
int ci = line.find("//");
|
||||||
|
if (ci >= 0) {
|
||||||
|
if (comment) *comment = line.right(line.size_s() - ci - 2);
|
||||||
|
line.cutRight(line.size_s() - ci).trim();
|
||||||
|
if (type && comment && !line.isEmpty()) {
|
||||||
|
*type = comment->takeLeft(1);
|
||||||
|
comment->trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void parseEnumLine(PIString & line, int * value, PIString * type, PIString * comment) {
|
||||||
|
removeComment(line, type, comment);
|
||||||
|
int ci = line.find("=");
|
||||||
|
if (ci >= 0) {
|
||||||
|
if (value) *value = line.right(line.size_s() - ci - 1).trim().toInt();
|
||||||
|
line.cutRight(line.size_s() - ci).trim();
|
||||||
|
}
|
||||||
|
if (line.trim().endsWith(",")) line.cutRight(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void parseInsert(PIString line, PIString & alias, PIStringList & out) {
|
||||||
|
out.clear();
|
||||||
|
int ci = line.find("=");
|
||||||
|
if (ci < 0) return;
|
||||||
|
alias = line.right(line.size_s() - ci - 1).trim();
|
||||||
|
line.cutRight(line.size_s() - ci).trim();
|
||||||
|
while (line.find("[") > 0) {
|
||||||
|
int is = line.find("["), ie = line.find("]");
|
||||||
|
PIString arr = line.mid(is + 1, ie - is - 1);
|
||||||
|
out << arr;
|
||||||
|
line.cutMid(is, ie - is + 1);
|
||||||
|
}
|
||||||
|
if (!line.isEmpty()) out.insert(0, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIVector<int> enumValues(const PIString & e, const PIMap<PIString, CDSection> & sections, PIStringList & enames) {
|
||||||
|
PIVector<int> ret;
|
||||||
|
enames.clear();
|
||||||
|
if (sections.contains(e)) {
|
||||||
|
ret = sections[e].indexes();
|
||||||
|
enames = sections[e].index_names();
|
||||||
|
} else {
|
||||||
|
int v = e.toInt();
|
||||||
|
if (v < 2) return ret;
|
||||||
|
for (int i = 0; i < v; ++i) {
|
||||||
|
ret << i;
|
||||||
|
enames << "";//PIString::fromNumber(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDSection CDParser::parse(PIIODevice * d, int cdsection_type) {
|
||||||
|
CDType::cdT et = (CDType::cdT)cdsection_type;
|
||||||
|
if (!d) return CDSection(et);
|
||||||
|
if (!d->canRead()) return CDSection(et);
|
||||||
|
//piCout << "[CDSection] parse start";
|
||||||
|
CDSection cs(et);
|
||||||
|
CDType ck;
|
||||||
|
PIMap<PIString, CDSection> sections;
|
||||||
|
PIMap<PIString, int> enum_values;
|
||||||
|
PIString content, line, alias, type, comment;
|
||||||
|
PIStringList iarr;
|
||||||
|
if (PIStringAscii(d->className()) == PIStringAscii("PIFile")) {
|
||||||
|
PIByteArray c = ((PIFile*)d)->readAll();
|
||||||
|
c << uchar(0);
|
||||||
|
content = PIString::fromUTF8((const char *)c.data());
|
||||||
|
}
|
||||||
|
if (PIStringAscii(d->className()) == PIStringAscii("PIIOString")) content = *(((PIIOString*)d)->string());
|
||||||
|
if (PIStringAscii(d->className()) == PIStringAscii("PIIOByteArray")) content = PIString(*(((PIIOByteArray*)d)->byteArray()));
|
||||||
|
PIIOString ios(&content);
|
||||||
|
//int phase = 0;
|
||||||
|
int cind = -1;
|
||||||
|
while ((cind = content.find("enum", cind)) >= 0) {
|
||||||
|
ios.seek(cind);
|
||||||
|
line = ios.readLine().trim();
|
||||||
|
type.clear();
|
||||||
|
comment.clear();
|
||||||
|
removeComment(line, &type, &comment);
|
||||||
|
if (line.find("{") < 0) {
|
||||||
|
cind += 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
line.cutLeft(line.find("enum") + 4).trim();
|
||||||
|
line.cutRight(line.size_s() - line.find("{")).trim();
|
||||||
|
if (line.isEmpty()) {
|
||||||
|
cind += 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cs = CDSection(et);
|
||||||
|
cs.name = line;
|
||||||
|
//piCout << "enum" << cs.name;
|
||||||
|
int cev = 0;
|
||||||
|
// cevalues.clear();
|
||||||
|
while (!ios.isEnd()) {
|
||||||
|
line = ios.readLine().trim();
|
||||||
|
comment.clear();
|
||||||
|
removeComment(line, &type, &comment);
|
||||||
|
if (line.find("}") >= 0) break;
|
||||||
|
if (line.isEmpty()) {
|
||||||
|
if (comment.find("=") >= 0) {
|
||||||
|
parseInsert(comment, alias, iarr);
|
||||||
|
if (!iarr.isEmpty()) {
|
||||||
|
// piCout << "#" << enum_values;
|
||||||
|
if (!enum_values.contains(alias)) {
|
||||||
|
piCout << "Parse error: can`t find section alias \"" << alias << "\"!";
|
||||||
|
return CDSection(et);
|
||||||
|
}
|
||||||
|
if (!sections.contains(iarr.front())) {
|
||||||
|
piCout << "Parse error: can`t find section \"" << iarr.front() << "\"!";
|
||||||
|
return CDSection(et);
|
||||||
|
}
|
||||||
|
//piCout << "insert" << alias << iarr;
|
||||||
|
int aval = enum_values.value(alias);
|
||||||
|
CDSection is = sections.value(iarr.take_front()), ts;
|
||||||
|
int ibpos = is.name.size_s();
|
||||||
|
piForeachRC (PIString & a, iarr) {
|
||||||
|
PIStringList enames;
|
||||||
|
PIVector<int> evals = enumValues(a, sections, enames);
|
||||||
|
//piCout << a << evals;
|
||||||
|
for (int i = 0; i < evals.size_s(); ++i) {
|
||||||
|
ts.section(evals[i]) = is;
|
||||||
|
ts.section(evals[i]).alias = enames[i];
|
||||||
|
}
|
||||||
|
ts.name = is.name;
|
||||||
|
ts.name.insert(ibpos, PIString("[") << a << "]");
|
||||||
|
is = ts;
|
||||||
|
ts = CDSection(et);
|
||||||
|
}
|
||||||
|
is.alias = alias;
|
||||||
|
cs.section(aval) = is;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parseEnumLine(line, &cev, &type, &comment);
|
||||||
|
//piCout << line << "=" << cev << "//" << type << comment;
|
||||||
|
ck = CDType(cev, line, type, "", "", comment, et);
|
||||||
|
if (type == "e") {
|
||||||
|
if (comment.startsWith("${")) {
|
||||||
|
comment.cutLeft(1);
|
||||||
|
PIString en = comment.inBrackets('{', '}');
|
||||||
|
comment.cutLeft(en.size_s() + 2).trim();
|
||||||
|
ck.setEnumValues(sections.value(en).enumValues());
|
||||||
|
ck.setComment(comment);
|
||||||
|
//piCout << "enum" << en << ck.enumValues();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cs[cev] = ck;
|
||||||
|
//cevalues[line] = cev;
|
||||||
|
enum_values[line] = cev;
|
||||||
|
++cev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//piCout << cs.name << cs.k;
|
||||||
|
sections[cs.name] = cs;
|
||||||
|
// piCout << "#" << cevalues;
|
||||||
|
// enum_values << cevalues;
|
||||||
|
cind += 4;
|
||||||
|
}
|
||||||
|
// piCout << "[CDSection] parse end";
|
||||||
|
switch (et) {
|
||||||
|
case CDType::cdK: return sections.value("KDescription");
|
||||||
|
case CDType::cdX: return sections.value("XDescription");
|
||||||
|
case CDType::cdC: return sections.value("CDescription");
|
||||||
|
case CDType::cdM: return sections.value("MDescription");
|
||||||
|
default: return CDSection(et);
|
||||||
|
}
|
||||||
|
return CDSection(et);
|
||||||
|
}
|
||||||
39
cd_utils/cdutils_parser.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
CD Utils - Control-Debug utilites
|
||||||
|
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CDUTILS_PARSER_H
|
||||||
|
#define CDUTILS_PARSER_H
|
||||||
|
|
||||||
|
#include "cd_utils_export.h"
|
||||||
|
|
||||||
|
class PIIODevice;
|
||||||
|
|
||||||
|
namespace CDUtils {
|
||||||
|
|
||||||
|
class CDSection;
|
||||||
|
|
||||||
|
namespace CDParser {
|
||||||
|
|
||||||
|
CD_UTILS_EXPORT CDSection parse(PIIODevice * d, int cdsection_type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CDUTILS_PARSER_H
|
||||||
73
cd_utils/cdutils_protocol.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
CD Utils - Control-Debug utilites
|
||||||
|
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CDUTILS_PROTOCOL_H
|
||||||
|
#define CDUTILS_PROTOCOL_H
|
||||||
|
|
||||||
|
#include "pistring.h"
|
||||||
|
#include "cd_utils_export.h"
|
||||||
|
|
||||||
|
namespace CDUtils {
|
||||||
|
|
||||||
|
enum CDPacketType {
|
||||||
|
CD_Ping,
|
||||||
|
CD_Pong,
|
||||||
|
|
||||||
|
CD_KQuery,
|
||||||
|
CD_KSend,
|
||||||
|
CD_KDirectChange,
|
||||||
|
|
||||||
|
CD_XQuery,
|
||||||
|
CD_XSend,
|
||||||
|
CD_XRequest,
|
||||||
|
CD_XValues,
|
||||||
|
|
||||||
|
CD_CQuery,
|
||||||
|
CD_CSend,
|
||||||
|
CD_Command,
|
||||||
|
|
||||||
|
CD_MQuery,
|
||||||
|
CD_MSend,
|
||||||
|
CD_Message,
|
||||||
|
};
|
||||||
|
|
||||||
|
# pragma pack(push,1)
|
||||||
|
|
||||||
|
struct CD_UTILS_EXPORT PacketHeader {
|
||||||
|
int type; // CDPacketType
|
||||||
|
int session_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CD_UTILS_EXPORT PacketKDirectChange {
|
||||||
|
PIDeque<int> path;
|
||||||
|
PIString value;
|
||||||
|
};
|
||||||
|
|
||||||
|
# pragma pack(pop)
|
||||||
|
|
||||||
|
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PacketHeader & v) {s << v.type << v.session_id; return s;}
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PacketHeader & v) {s >> v.type >> v.session_id; return s;}
|
||||||
|
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PacketKDirectChange & v) {s << v.path << v.value; return s;}
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PacketKDirectChange & v) {s >> v.path >> v.value; return s;}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CDUTILS_PROTOCOL_H
|
||||||
762
cd_utils/cdutils_types.cpp
Normal file
@@ -0,0 +1,762 @@
|
|||||||
|
#include "cdutils_types.h"
|
||||||
|
#include "piconfig.h"
|
||||||
|
#include "pifile.h"
|
||||||
|
#include "pievaluator.h"
|
||||||
|
#include "cdutils_core.h"
|
||||||
|
|
||||||
|
using namespace CDUtils;
|
||||||
|
|
||||||
|
//int cdtype_debug_cnt = 1;
|
||||||
|
|
||||||
|
const int cd_x_history_max_size = 4000;
|
||||||
|
|
||||||
|
CDType::CDType() {
|
||||||
|
index_ = -1;
|
||||||
|
value_d = 0.;
|
||||||
|
value_i = 0;
|
||||||
|
value_b = calculated = x_enabled = false;
|
||||||
|
cd_type_ = cdNull;
|
||||||
|
parent = 0;
|
||||||
|
avg_size = 1;
|
||||||
|
mode_ = rmode_ = X_Current;
|
||||||
|
// debug_cnt = cdtype_debug_cnt;
|
||||||
|
// cdtype_debug_cnt++;
|
||||||
|
// piCout << "[CDType]" << "create Null" << debug_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CDType::CDType(int i, const PIString & n, const PIString & t, const PIString & v, const PIString & f, const PIString & c, cdT cd_t) {
|
||||||
|
index_ = i;
|
||||||
|
name_ = n.trimmed();
|
||||||
|
type_ = t.trimmed();
|
||||||
|
value_s = v.trimmed();
|
||||||
|
formula_ = f.trimmed();
|
||||||
|
comment_ = c.trimmed();
|
||||||
|
value_d = v.toDouble();
|
||||||
|
value_i = v.toInt();
|
||||||
|
value_b = v.toBool();
|
||||||
|
cd_type_ = cd_t;
|
||||||
|
calculated = x_enabled = false;
|
||||||
|
parent = 0;
|
||||||
|
avg_size = 1;
|
||||||
|
mode_ = rmode_ = X_Current;
|
||||||
|
if (type_ == "e") {
|
||||||
|
enum_values = parseEnumComment(comment_);
|
||||||
|
// piCout << enum_values.size() << enum_values;
|
||||||
|
}
|
||||||
|
// piCout << type_.size() << type_.toUTF8();
|
||||||
|
// piCout << formula_.size() << formula_.toUTF8();
|
||||||
|
// piCout << comment_.size() << comment_.toUTF8();
|
||||||
|
// debug_cnt = cdtype_debug_cnt;
|
||||||
|
// cdtype_debug_cnt++;
|
||||||
|
// piCout << "[CDType] create" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDType & CDType::operator =(double x) {
|
||||||
|
value_d = x;
|
||||||
|
value_i = x;
|
||||||
|
value_b = x > 0.;
|
||||||
|
if (mode_ == X_All_Avg) {
|
||||||
|
avg_h << x;
|
||||||
|
double val = 0;
|
||||||
|
if (avg_h.size_s() >= avg_size) {
|
||||||
|
for (int i = 0; i < avg_h.size_s(); i++)
|
||||||
|
val += avg_h[i];
|
||||||
|
val /= avg_h.size();
|
||||||
|
avg_h.clear();
|
||||||
|
if (history.size() < cd_x_history_max_size)
|
||||||
|
history << val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIString CDType::type() const {
|
||||||
|
if (type_.trimmed().isEmpty()) return "f";
|
||||||
|
// piCout << "type =" << type_.trimmed() << ";" << type_ << "#";
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIString CDType::value() const {
|
||||||
|
if (type_ == "b") return PIString::fromBool(value_b);
|
||||||
|
return value_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIVariant CDType::variantValue() const {
|
||||||
|
if (type_.isEmpty()) return PIVariant(value());
|
||||||
|
switch (type_[0].toAscii()) {
|
||||||
|
case 'b': return PIVariant(toBool()); break;
|
||||||
|
case 'n': return PIVariant(toInt()); break;
|
||||||
|
case 'f': return PIVariant(toDouble()); break;
|
||||||
|
case 'c': return PIVariant(PIVariantTypes::Color(toInt())); break;
|
||||||
|
case 'e': {
|
||||||
|
PIVariantTypes::Enum e = enum_values;
|
||||||
|
e.selectValue(toInt());
|
||||||
|
return PIVariant(e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return PIVariant(value());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDType::setValue(const PIString & value_) {
|
||||||
|
formula_ = value_;
|
||||||
|
value_d = formula_.toDouble();
|
||||||
|
value_i = formula_.toInt();
|
||||||
|
value_b = formula_.toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDType::setVariantValue(const PIVariant & value_) {
|
||||||
|
setValue(PIString::fromNumber(value_.toDouble()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDType::setFormula(const PIString & f) {
|
||||||
|
formula_ = f;
|
||||||
|
calculated = false;
|
||||||
|
//PIEvaluator e;
|
||||||
|
//calculate(&e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIStringList CDType::pathString() const {
|
||||||
|
PIStringList ret;
|
||||||
|
CDSection * ps = CDCore::instance()->root(cd_type_);
|
||||||
|
if (!ps) return ret;
|
||||||
|
for (int i = 0; i < path_.size_s() - 1; ++i) {
|
||||||
|
ps = &(ps->section(path_[i]));
|
||||||
|
if (!ps->alias.isEmpty()) ret << ps->alias;
|
||||||
|
else ret << PIString::fromNumber(path_[i]);
|
||||||
|
}
|
||||||
|
if (!name_.isEmpty()) ret << name_;
|
||||||
|
else ret << PIString::fromNumber(index_);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDType::readX(PIByteArray & ba) {
|
||||||
|
if (ba.size() < 5) return;
|
||||||
|
uchar t(0); ba >> t;
|
||||||
|
rmode_ = (XMode)t;
|
||||||
|
switch (rmode_) {
|
||||||
|
case X_Current:
|
||||||
|
ba >> value_d;
|
||||||
|
break;
|
||||||
|
case X_All_Avg: {
|
||||||
|
PIVector<double> ah;
|
||||||
|
ba >> ah;
|
||||||
|
history << ah;
|
||||||
|
if (!history.isEmpty())
|
||||||
|
value_d = history.back();
|
||||||
|
} break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
value_i = value_d;
|
||||||
|
value_b = value_d > 0.;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDType::writeX(PIByteArray & ba) {
|
||||||
|
ba << uchar(mode_);
|
||||||
|
switch (mode_) {
|
||||||
|
case X_Current:
|
||||||
|
ba << value_d;
|
||||||
|
break;
|
||||||
|
case X_All_Avg:
|
||||||
|
ba << history;
|
||||||
|
history.clear();
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CDType::calculate(PIEvaluator * e, PIVector<const CDType * > stack) {
|
||||||
|
if (stack.contains(this)) {
|
||||||
|
error_ = "Circular dependencies: ";
|
||||||
|
piForeachC (CDType * k, stack)
|
||||||
|
error_ << k->name() << " -> ";
|
||||||
|
error_ << name();
|
||||||
|
//piCout << error_;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
stack << this;
|
||||||
|
if (calculated) return true;
|
||||||
|
calculated = true;
|
||||||
|
error_.clear();
|
||||||
|
if (!parent) return true;
|
||||||
|
//piCout << "calc" << name_ << (parent ? parent->alias : "root");
|
||||||
|
value_s = formula_.trimmed();
|
||||||
|
for (;;) {
|
||||||
|
int ki = value_s.find("K[");
|
||||||
|
if (ki < 0) break;
|
||||||
|
int ke = value_s.find("]", ki + 2);
|
||||||
|
if (ke < 0) break;
|
||||||
|
PIString kp = value_s.mid(ki + 2, ke - ki - 2);
|
||||||
|
//piCout << kp;
|
||||||
|
CDType & k((*parent)[kp]);
|
||||||
|
k.calculate(e, stack);
|
||||||
|
value_s.replace(ki, ke - ki + 1, PIString::fromNumber(k.value_d));
|
||||||
|
}
|
||||||
|
value_d = formula_.toDouble();
|
||||||
|
value_i = formula_.toInt();
|
||||||
|
value_b = formula_.toBool();
|
||||||
|
double ev = 0.;
|
||||||
|
if (!e->check(value_s) && value_d == 0. && value_i == 0 && !value_b) {
|
||||||
|
PIString f = formula_.trimmed().toLowerCase();
|
||||||
|
if (f != "off" && f != "false" && f != "no" && !value_b) {
|
||||||
|
error_ = e->error();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (e->isCorrect())
|
||||||
|
ev = e->evaluate().real();
|
||||||
|
//piCout << value_s << value_i << value_d << ev;
|
||||||
|
//if ((value_d == 0.) || (piAbsd(value_d) < piAbsd(ev))) value_d = ev;
|
||||||
|
//if ((value_i == 0) || (piAbsd(value_i) < piAbsd(ev))) value_i = int(ev);
|
||||||
|
if ((value_d == 0.) || (ev != 0.)) value_d = ev;
|
||||||
|
if ((value_i == 0) || (ev != 0.)) value_i = int(ev);
|
||||||
|
value_b = value_b || (ev > 0.);
|
||||||
|
if (value_i != 0) {
|
||||||
|
if (value_d == 0.) value_d = value_i;
|
||||||
|
value_b = value_i > 0;
|
||||||
|
}
|
||||||
|
if (value_d != 0.) {
|
||||||
|
if (value_i == 0) value_i = value_d;
|
||||||
|
value_b = value_d > 0.;
|
||||||
|
}
|
||||||
|
if (value_b) {
|
||||||
|
if (value_d == 0.) value_d = 1.;
|
||||||
|
if (value_i == 0) value_i = 1;
|
||||||
|
}
|
||||||
|
value_s = PIString::fromNumber(value_d);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIVariantTypes::Enum CDType::parseEnumComment(PIString c) {
|
||||||
|
PIVariantTypes::Enum ret;
|
||||||
|
if (c.isEmpty()) return ret;
|
||||||
|
if (type_ == "e") {
|
||||||
|
PIStringList sl = c.inBrackets('{', '}').split(",");
|
||||||
|
int cval = 0;
|
||||||
|
piForeach (PIString & s, sl) {
|
||||||
|
s.trim();
|
||||||
|
if (s.isEmpty()) continue;
|
||||||
|
if (s[0].isDigit()) {
|
||||||
|
int ind = s.find("-");
|
||||||
|
if (ind > 0) {
|
||||||
|
cval = s.left(ind).toInt();
|
||||||
|
s.cutLeft(ind + 1).trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret << PIVariantTypes::Enumerator(cval, s);
|
||||||
|
++cval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//piCout << c << "=" << ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//CDType::CDType(const CDType &cdt) {
|
||||||
|
// index_ = cdt.index_;
|
||||||
|
// name_ = cdt.name_;
|
||||||
|
// type_ = cdt.type_;
|
||||||
|
// value_s = cdt.value_s;
|
||||||
|
// formula_ = cdt.formula_;
|
||||||
|
// comment_ = cdt.comment_;
|
||||||
|
// value_d = cdt.value_d;
|
||||||
|
// value_i = cdt.value_i;
|
||||||
|
// value_b = cdt.value_b;
|
||||||
|
// cd_type_ = cdt.cd_type_;
|
||||||
|
// debug_cnt = cdtype_debug_cnt;
|
||||||
|
// cdtype_debug_cnt++;
|
||||||
|
// piCout << "[CDType] copy" << debug_cnt << "->" << cdt.debug_cnt << index_ << ":" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK);
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
//CDType &CDType::operator =(const CDType &cdt) {
|
||||||
|
// index_ = cdt.index_;
|
||||||
|
// name_ = cdt.name_;
|
||||||
|
// type_ = cdt.type_;
|
||||||
|
// value_s = cdt.value_s;
|
||||||
|
// formula_ = cdt.formula_;
|
||||||
|
// comment_ = cdt.comment_;
|
||||||
|
// value_d = cdt.value_d;
|
||||||
|
// value_i = cdt.value_i;
|
||||||
|
// value_b = cdt.value_b;
|
||||||
|
// cd_type_ = cdt.cd_type_;
|
||||||
|
// piCout << "[CDType] assign" << debug_cnt << "=" << cdt.debug_cnt << index_ << ":" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK);
|
||||||
|
// //debug_cnt = cdt.debug_cnt;
|
||||||
|
// return *this;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
//CDType::~CDType() {
|
||||||
|
// piCout << "[CDType] delete" << debug_cnt << index_ << ":" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK);
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CDSection::CDSection(CDType::cdT type_) {
|
||||||
|
cd_type_ = type_;
|
||||||
|
null.cd_type_ = type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDSection & CDSection::section(int v) {
|
||||||
|
CDSection & ret(s[v]);
|
||||||
|
ret.cd_type_ = cd_type_;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const CDSection CDSection::section(int v) const {
|
||||||
|
CDSection & ret(s[v]);
|
||||||
|
ret.cd_type_ = cd_type_;
|
||||||
|
return s[v];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CDSection::exists(PIDeque<int> path) const {
|
||||||
|
if (path.isEmpty()) return false;
|
||||||
|
if (path.size_s() == 1) return cd.contains(path[0]);
|
||||||
|
int si = path[0];
|
||||||
|
if (!s.contains(si)) return false;
|
||||||
|
path.remove(0, 1);
|
||||||
|
return s[si].exists(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int CDSection::count(bool recursive) const {
|
||||||
|
int ret = cd.size_s();
|
||||||
|
if (recursive) {
|
||||||
|
PIMap<int, CDSection>::const_iterator i;
|
||||||
|
for (i = s.constBegin(); i != s.constEnd(); ++i)
|
||||||
|
ret += i->second.count(recursive);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int CDSection::sectionsCount() const {
|
||||||
|
return s.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIStringList CDSection::index_names() const {
|
||||||
|
PIStringList ret;
|
||||||
|
auto i = cd.makeIterator();
|
||||||
|
while (i.next())
|
||||||
|
ret << i.value().name();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDSection::calculate() {
|
||||||
|
prepareCalculate();
|
||||||
|
if (cd_type_ != CDType::cdK) return;
|
||||||
|
PIEvaluator e;
|
||||||
|
calculateRecursive(&e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDType & CDSection::getByName(const PIString & name_) {
|
||||||
|
PIStringList np = name_.split(".");
|
||||||
|
if (np.isEmpty()) return null;
|
||||||
|
//piCout << np;
|
||||||
|
CDSection * cs = this, * ns = 0;
|
||||||
|
if (np.front().isEmpty()) {
|
||||||
|
if (np.size_s() < 2) return null;
|
||||||
|
cs = CDCore::instance()->root(cd_type_);
|
||||||
|
np.pop_front();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < np.size_s() - 1; ++i) {
|
||||||
|
if (np[i].isEmpty()) return null;
|
||||||
|
bool isd = np[i][0].isDigit() || (np[i][0] == '-');
|
||||||
|
int dv = 0;
|
||||||
|
if (isd) dv = np[i].toInt();
|
||||||
|
ns = 0;
|
||||||
|
auto it = cs->s.makeIterator();
|
||||||
|
while (it.next()) {
|
||||||
|
bool f = false;
|
||||||
|
if (isd) f = (dv == it.key());
|
||||||
|
else f = (np[i] == it.value().alias);
|
||||||
|
//piCout << "s..." << it.key() << it.value().alias << f;
|
||||||
|
if (f) {
|
||||||
|
ns = &(it.valueRef());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//piCout << ns;
|
||||||
|
if (!ns) return null;
|
||||||
|
cs = ns;
|
||||||
|
}
|
||||||
|
if (np.back().isEmpty()) return null;
|
||||||
|
bool isd = np.back()[0].isDigit() || (np.back()[0] == '-');
|
||||||
|
int dv = 0;
|
||||||
|
if (isd) dv = np.back().toInt();
|
||||||
|
//piCout << np.back() << isd << dv;
|
||||||
|
auto it = cs->cd.makeIterator();
|
||||||
|
while (it.next()) {
|
||||||
|
bool f = false;
|
||||||
|
if (isd) f = (dv == it.key());
|
||||||
|
else f = (np.back() == it.value().name());
|
||||||
|
//piCout << "k..." << it.key() << it.value().name() << f;
|
||||||
|
if (f)
|
||||||
|
return cs->cd[it.key()];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CDType & CDSection::getByPath(const PIDeque<int> & path_) {
|
||||||
|
if (path_.isEmpty()) return null;
|
||||||
|
CDSection * s = this;
|
||||||
|
for (int i = 0; i < path_.size_s() - 1; ++i)
|
||||||
|
s = &(s->section(path_[i]));
|
||||||
|
if (!s) return null;
|
||||||
|
return (*s)[path_.back()];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDSection::write(PIIODevice * d, const PIString & prefix) {
|
||||||
|
if (!d) return;
|
||||||
|
if (cd.isEmpty() && s.isEmpty()) return;
|
||||||
|
// piCout << "[CDSection] write start";
|
||||||
|
PIString l;
|
||||||
|
PIStringList cdtl;
|
||||||
|
cdtl << "null" << "k" << "x" << "c" << "m";
|
||||||
|
if (prefix.isEmpty()) l = "[" + cdtl[cd_type_] + "]";
|
||||||
|
else l = "[" + prefix + "." + cdtl[cd_type_] + "]";
|
||||||
|
l += "\n";
|
||||||
|
d->write(l.toUTF8());
|
||||||
|
l = "name = " + name + " \n";
|
||||||
|
d->write(l.toUTF8());
|
||||||
|
l = "alias = " + alias + " \n";
|
||||||
|
d->write(l.toUTF8());
|
||||||
|
auto i = cd.makeIterator();
|
||||||
|
while (i.next()) {
|
||||||
|
const CDType & ck(i.value());
|
||||||
|
if (ck.cd_type() != cd_type_) continue;
|
||||||
|
switch (cd_type_) {
|
||||||
|
case CDType::cdNull: break;
|
||||||
|
case CDType::cdK:
|
||||||
|
l.clear(); l << ck.index() << ".f = " << ck.formula() << " #s " << ck.comment() << " \n";
|
||||||
|
d->write(l.toUTF8());
|
||||||
|
l.clear(); l << ck.index() << ".v = " << ck.value() << " #" << ck.type() << " " << ck.name() << " \n";
|
||||||
|
d->write(l.toUTF8());
|
||||||
|
if (!ck.enumValues().enum_list.isEmpty()) {
|
||||||
|
l.clear(); l << ck.index() << ".ev = {";
|
||||||
|
//PIVector<CDType::Enumerator> el = ck.enumValues();
|
||||||
|
piForeachC (PIVariantTypes::Enumerator & e, ck.enumValues().enum_list)
|
||||||
|
l << e.value << " - " << e.name << ", ";
|
||||||
|
l.cutRight(2);
|
||||||
|
l << "} \n";
|
||||||
|
d->write(l.toUTF8());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CDType::cdX:
|
||||||
|
l.clear(); l << ck.index() << ".name = " << ck.name() << " #s " << ck.comment() << " \n";
|
||||||
|
d->write(l.toUTF8());
|
||||||
|
l.clear(); l << ck.index() << ".mode = " << ck.xmode() << " #e (0 - cur, 1 - all_avg) " << "\n";
|
||||||
|
d->write(l.toUTF8());
|
||||||
|
l.clear(); l << ck.index() << ".avg = " << ck.avg() << " #n " << "\n";
|
||||||
|
d->write(l.toUTF8());
|
||||||
|
l.clear(); l << ck.index() << ".sel = " << (ck.isSelectedX() ? "1" : "0") << " #n " << "\n";
|
||||||
|
d->write(l.toUTF8());
|
||||||
|
break;
|
||||||
|
case CDType::cdC:
|
||||||
|
case CDType::cdM:
|
||||||
|
l.clear(); l << ck.index() << ".name = " << ck.name() << " #s " << ck.comment() << " \n";
|
||||||
|
d->write(l.toUTF8());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!s.isEmpty()) {
|
||||||
|
if (prefix.isEmpty()) l = "s";
|
||||||
|
else l = prefix + ".s";
|
||||||
|
auto j = s.makeIterator();
|
||||||
|
while (j.next()) {
|
||||||
|
j.valueRef().write(d, l + "." + PIString::fromNumber(j.key()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prefix.isEmpty()) {
|
||||||
|
l = "[]\n";
|
||||||
|
d->write(l.toUTF8());
|
||||||
|
}
|
||||||
|
// piCout << "[CDSection] write end";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDSection::read(const void * ep) {
|
||||||
|
// piCout << "[CDSection] read start";
|
||||||
|
PIStringList cdtl;
|
||||||
|
cdtl << "null" << "k" << "x" << "c" << "m";
|
||||||
|
cd.clear();
|
||||||
|
s.clear();
|
||||||
|
PIConfig::Entry & e(*(PIConfig::Entry*)ep);
|
||||||
|
name = e.getValue(cdtl[cd_type_] + ".name").value();
|
||||||
|
alias = e.getValue(cdtl[cd_type_] + ".alias").value();
|
||||||
|
PIConfig::Entry & cdl = e.getValue(cdtl[cd_type_]);
|
||||||
|
for (int i = 0; i < cdl.childCount(); ++i) {
|
||||||
|
const PIConfig::Entry * e(cdl.child(i));
|
||||||
|
bool ok = false;
|
||||||
|
int id = e->name().toInt(-1, &ok);
|
||||||
|
// piCout << "[read]" << ke->name() << ke->value() << ok;
|
||||||
|
// PIString n = ke->getValue("v").comment();
|
||||||
|
// PIString t = n.takeLeft(1);
|
||||||
|
if (ok) {
|
||||||
|
CDType c;
|
||||||
|
PIString ev;
|
||||||
|
switch (cd_type_) {
|
||||||
|
case CDType::cdNull: break;
|
||||||
|
case CDType::cdK:
|
||||||
|
c = CDType(id, e->getValue("v").comment(), e->getValue("v").type(), e->getValue("v").value(), e->getValue("f").value(), e->getValue("f").comment(), cd_type_);
|
||||||
|
ev = e->getValue("ev", "").value();
|
||||||
|
if (!ev.isEmpty())
|
||||||
|
c.enum_values = c.parseEnumComment(ev);
|
||||||
|
break;
|
||||||
|
case CDType::cdX:
|
||||||
|
c = CDType(id, e->getValue("name").value(), PIString(), PIString(), PIString() , e->getValue("name").comment(), cd_type_);
|
||||||
|
c.setXMode((CDType::XMode)e->getValue("mode", int(CDType::X_Current)).value().toInt());
|
||||||
|
c.setAvg((CDType::XMode)e->getValue("avg", 1).value().toInt());
|
||||||
|
c.x_enabled = e->getValue("sel", false).value().toBool();
|
||||||
|
break;
|
||||||
|
case CDType::cdC:
|
||||||
|
case CDType::cdM:
|
||||||
|
c = CDType(id, e->getValue("name").value(), PIString(), PIString(), PIString() , e->getValue("name").comment(), cd_type_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cd[id] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PIConfig::Entry & sl = e.getValue("s");
|
||||||
|
for (int i = 0; i < sl.childCount(); ++i) {
|
||||||
|
const PIConfig::Entry * se(sl.child(i));
|
||||||
|
int sid = se->name().toInt();
|
||||||
|
CDSection & rs(s[sid]);
|
||||||
|
rs.cd_type_ = cd_type_;
|
||||||
|
rs.read(se);
|
||||||
|
}
|
||||||
|
// piCout << "[CDSection] read end";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDSection::update(CDSection & v, UpdateModeFlags mode) {
|
||||||
|
if (mode[SaveByIndex] && mode[SaveByName]) {
|
||||||
|
piCout << "[CDSection] update error: SaveByIndex | SaveByName mode is denied!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//piCout << "[CDSection] update start";
|
||||||
|
//piCout << "before" << k.size() << v.k.size();
|
||||||
|
|
||||||
|
PIMap<int, PIString> prev_cd_f_bi;
|
||||||
|
PIMap<PIString, PIString> prev_cd_f_bn;
|
||||||
|
PIMap<int, CDType>::iterator i;
|
||||||
|
if (mode[SaveByIndex]) {
|
||||||
|
for (i = cd.begin(); i != cd.end(); ++i)
|
||||||
|
prev_cd_f_bi[i.key()] = i.value().formula();
|
||||||
|
}
|
||||||
|
if (mode[SaveByName]) {
|
||||||
|
for (i = cd.begin(); i != cd.end(); ++i)
|
||||||
|
prev_cd_f_bn[i.value().name_] = i.value().formula();
|
||||||
|
}
|
||||||
|
if (!mode[Merge])
|
||||||
|
cd.clear();
|
||||||
|
for (i = v.cd.begin(); i != v.cd.end(); ++i) {
|
||||||
|
int id = i.key();
|
||||||
|
PIString n = i.value().name();
|
||||||
|
cd[id] = i.value();
|
||||||
|
if (mode[SaveByIndex]) {
|
||||||
|
if (prev_cd_f_bi.contains(id))
|
||||||
|
cd[id].setFormula(prev_cd_f_bi[id]);
|
||||||
|
}
|
||||||
|
if (mode[SaveByName]) {
|
||||||
|
if (prev_cd_f_bn.contains(n))
|
||||||
|
cd[id].setFormula(prev_cd_f_bn[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PIMap<int, CDSection> prev_s_bi;
|
||||||
|
PIMap<PIString, CDSection> prev_s_bn;
|
||||||
|
PIMap<int, CDSection>::iterator j;
|
||||||
|
if (mode[SaveByIndex]) {
|
||||||
|
for (j = s.begin(); j != s.end(); ++j)
|
||||||
|
prev_s_bi[j.key()] = j.value();
|
||||||
|
}
|
||||||
|
if (mode[SaveByName]) {
|
||||||
|
for (j = s.begin(); j != s.end(); ++j)
|
||||||
|
prev_s_bn[j.value().alias] = j.value();
|
||||||
|
}
|
||||||
|
if (!mode[Merge])
|
||||||
|
s.clear();
|
||||||
|
for (j = v.s.begin(); j != v.s.end(); ++j) {
|
||||||
|
int id = j.key();
|
||||||
|
PIString n = j.value().alias;
|
||||||
|
s[id] = j.value();
|
||||||
|
if (mode[SaveByIndex]) {
|
||||||
|
if (prev_s_bi.contains(id))
|
||||||
|
s[id] = prev_s_bi[id];
|
||||||
|
}
|
||||||
|
if (mode[SaveByName]) {
|
||||||
|
if (prev_s_bn.contains(n))
|
||||||
|
s[id] = prev_s_bn[n];
|
||||||
|
}
|
||||||
|
s[id].update(j.value(), mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*PISet<int> used;
|
||||||
|
for (i = k.begin(); i != k.end(); ++i) {
|
||||||
|
if (v.k.contains(i.key())) {
|
||||||
|
PIString f = k[i.key()].formula_;
|
||||||
|
CDType & cdt = v.k[i.key()];
|
||||||
|
cdt.formula_ = f;
|
||||||
|
k[i.key()] = cdt;
|
||||||
|
used << i.key();
|
||||||
|
}
|
||||||
|
if (mode) {
|
||||||
|
CDType & ck(k[i.key()]);
|
||||||
|
if (prev_k_f_bn.contains(ck.name_))
|
||||||
|
ck.setFormula(prev_k_f_bn[ck.name_]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//piCout << " after" << k.size();
|
||||||
|
for (i = v.k.begin(); i != v.k.end(); ++i) {
|
||||||
|
if (!used.contains(i.key()))
|
||||||
|
k[i.key()] = i.value();
|
||||||
|
CDType & ck(k[i.key()]);
|
||||||
|
ck.setFormula(prev_k_f_bn.value(ck.name_));
|
||||||
|
}
|
||||||
|
used.clear();
|
||||||
|
PIMap<int, CDSection>::iterator j;
|
||||||
|
for (j = s.begin(); j != s.end(); ++j) {
|
||||||
|
if (v.s.contains(j.key()))
|
||||||
|
j.value().update(v.s[j.key()], mode);
|
||||||
|
used << j.key();
|
||||||
|
}
|
||||||
|
for (j = v.s.begin(); j != v.s.end(); ++j) {
|
||||||
|
if (!used.contains(j.key()))
|
||||||
|
s[j.key()] = j.value();
|
||||||
|
}*/
|
||||||
|
// piCout << "[CDSection] update end";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CDSection::isSameStructure(CDSection & v) {
|
||||||
|
PIMap<PIString, int> cd_ids;
|
||||||
|
PIMap<int, CDType>::iterator i;
|
||||||
|
for (i = cd.begin(); i != cd.end(); ++i)
|
||||||
|
cd_ids[i.value().name()] = i.key();
|
||||||
|
for (i = v.cd.begin(); i != v.cd.end(); ++i) {
|
||||||
|
if (!cd_ids.contains(i.value().name())) continue;
|
||||||
|
//piCout << i.key() << k[i.key()].name() << i.value().name();
|
||||||
|
if (cd[cd_ids[i.value().name()]].index() != i.key())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PIMap<int, CDSection>::iterator j;
|
||||||
|
for (j = v.s.begin(); j != v.s.end(); ++j) {
|
||||||
|
if (!s.contains(j.key())) continue;
|
||||||
|
if (!s[j.key()].isSameStructure(j.value()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDSection::prepareCalculate() {
|
||||||
|
PIMap<int, CDType>::iterator i;
|
||||||
|
for (i = cd.begin(); i != cd.end(); ++i) {
|
||||||
|
i.value().parent = this;
|
||||||
|
i.value().calculated = false;
|
||||||
|
}
|
||||||
|
PIMap<int, CDSection>::iterator j;
|
||||||
|
for (j = s.begin(); j != s.end(); ++j)
|
||||||
|
j.value().prepareCalculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDSection::calculateRecursive(PIEvaluator * e) {
|
||||||
|
PIMap<int, CDType>::iterator i;
|
||||||
|
for (i = cd.begin(); i != cd.end(); ++i)
|
||||||
|
i.value().calculate(e);
|
||||||
|
PIMap<int, CDSection>::iterator j;
|
||||||
|
for (j = s.begin(); j != s.end(); ++j)
|
||||||
|
j.value().calculateRecursive(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDSection::setSelectedX(bool yes) {
|
||||||
|
PIMap<int, CDType>::iterator i;
|
||||||
|
for (i = cd.begin(); i != cd.end(); ++i)
|
||||||
|
i.value().x_enabled = yes;
|
||||||
|
PIMap<int, CDSection>::iterator j;
|
||||||
|
for (j = s.begin(); j != s.end(); ++j)
|
||||||
|
j.value().setSelectedX(yes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIVector<PIDeque<int> > CDSection::collectX() const {
|
||||||
|
PIVector<PIDeque<int> > ret;
|
||||||
|
PIMap<int, CDType>::const_iterator i;
|
||||||
|
for (i = cd.begin(); i != cd.end(); ++i) {
|
||||||
|
if (i.value().x_enabled)
|
||||||
|
ret << i.value().path();
|
||||||
|
}
|
||||||
|
PIMap<int, CDSection>::const_iterator j;
|
||||||
|
for (j = s.constBegin(); j != s.constEnd(); ++j)
|
||||||
|
ret << j.value().collectX();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDSection::makePath(PIDeque<int> p) {
|
||||||
|
PIDeque<int> tp;
|
||||||
|
PIMap<int, CDType>::iterator i;
|
||||||
|
for (i = cd.begin(); i != cd.end(); ++i) {
|
||||||
|
tp = p;
|
||||||
|
tp << i.key();
|
||||||
|
i.value().path_ = tp;
|
||||||
|
//piCout << "path for" << i.value().name() << tp;
|
||||||
|
}
|
||||||
|
PIMap<int, CDSection>::iterator j;
|
||||||
|
for (j = s.begin(); j != s.end(); ++j) {
|
||||||
|
tp = p;
|
||||||
|
tp << j.key();
|
||||||
|
j.value().makePath(tp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIVector<CDType * > CDSection::children(bool recursive) const {
|
||||||
|
PIVector<CDType * > ret;
|
||||||
|
PIMap<int, CDType>::const_iterator i;
|
||||||
|
for (i = cd.begin(); i != cd.end(); ++i)
|
||||||
|
ret << const_cast<CDType * >(&(i.value()));
|
||||||
|
if (!recursive) return ret;
|
||||||
|
PIMap<int, CDSection>::const_iterator j;
|
||||||
|
for (j = s.constBegin(); j != s.constEnd(); ++j)
|
||||||
|
ret << j.value().children(true);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIVariantTypes::Enum CDSection::enumValues() const {
|
||||||
|
PIVariantTypes::Enum ret;
|
||||||
|
PIMap<int, CDType>::const_iterator i;
|
||||||
|
for (i = cd.constBegin(); i != cd.constEnd(); ++i)
|
||||||
|
ret << PIVariantTypes::Enumerator(i.key(), i.value().name());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
193
cd_utils/cdutils_types.h
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
CD Utils - Control-Debug utilites
|
||||||
|
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CDUTILS_TYPES_H
|
||||||
|
#define CDUTILS_TYPES_H
|
||||||
|
|
||||||
|
#include "pistring.h"
|
||||||
|
#include "pimap.h"
|
||||||
|
#include "pivariant.h"
|
||||||
|
#include "cd_utils_export.h"
|
||||||
|
|
||||||
|
class PIIODevice;
|
||||||
|
class PIEvaluator;
|
||||||
|
class CD_Pult;
|
||||||
|
class CDItem;
|
||||||
|
class CDItemModel;
|
||||||
|
|
||||||
|
namespace CDUtils {
|
||||||
|
|
||||||
|
class CDSection;
|
||||||
|
|
||||||
|
enum UpdateMode {
|
||||||
|
SaveByIndex = 0x01,
|
||||||
|
SaveByName = 0x02,
|
||||||
|
Merge = 0x04
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MessageType {
|
||||||
|
Log = 1,
|
||||||
|
MessageBox,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef PIFlags<UpdateMode> UpdateModeFlags;
|
||||||
|
|
||||||
|
class CD_UTILS_EXPORT CDType {
|
||||||
|
friend class CDSection;
|
||||||
|
friend class CDCore;
|
||||||
|
friend class Interface;
|
||||||
|
friend class XInterface;
|
||||||
|
public:
|
||||||
|
enum cdT {cdNull, cdK, cdX, cdC, cdM};
|
||||||
|
enum XMode {X_Current, X_All_Avg};
|
||||||
|
|
||||||
|
CDType();
|
||||||
|
CDType(int i, const PIString & n, const PIString & t, const PIString & v, const PIString & f, const PIString & c, cdT cd_t);
|
||||||
|
|
||||||
|
CDType & operator =(double x);
|
||||||
|
int index() const {return index_;}
|
||||||
|
PIString name() const {return name_;}
|
||||||
|
PIString type() const;
|
||||||
|
PIString value() const;
|
||||||
|
PIVariant variantValue() const;
|
||||||
|
PIString formula() const {return formula_;}
|
||||||
|
PIString comment() const {return comment_;}
|
||||||
|
double toDouble() const {return value_d;}
|
||||||
|
int toInt() const {return value_i;}
|
||||||
|
bool toBool() const {return value_b;}
|
||||||
|
cdT cd_type() const {return cd_type_;}
|
||||||
|
void setValue(const PIString & value_);
|
||||||
|
void setVariantValue(const PIVariant & value_);
|
||||||
|
void setFormula(const PIString & formula);
|
||||||
|
void setComment(const PIString & comment) {comment_ = comment;}
|
||||||
|
operator double() const {return value_d;}
|
||||||
|
const PIVariantTypes::Enum & enumValues() const {return enum_values;}
|
||||||
|
void setEnumValues(const PIVariantTypes::Enum & ev) {enum_values = ev;}
|
||||||
|
const PIString & errorString() const {return error_;}
|
||||||
|
PIDeque<int> path() const {return path_;}
|
||||||
|
PIStringList pathString() const;
|
||||||
|
|
||||||
|
void setXMode(XMode mode) {mode_ = mode;}
|
||||||
|
void setAvg(int avg) {avg_size = avg;}
|
||||||
|
XMode xmode() const {return mode_;}
|
||||||
|
XMode xmode_rec() const {return rmode_;}
|
||||||
|
int avg() const {return avg_size;}
|
||||||
|
bool isSelectedX() const {return x_enabled;}
|
||||||
|
void readX(PIByteArray & ba);
|
||||||
|
void writeX(PIByteArray & ba);
|
||||||
|
|
||||||
|
PIVector<double> history;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool calculate(PIEvaluator * e, PIVector<const CDType * > stack = PIVector<const CDType * >());
|
||||||
|
PIVariantTypes::Enum parseEnumComment(PIString c);
|
||||||
|
cdT cd_type_;
|
||||||
|
int index_;
|
||||||
|
PIString name_, type_;
|
||||||
|
PIString value_s, formula_, comment_, error_;
|
||||||
|
PIVariantTypes::Enum enum_values;
|
||||||
|
CDSection * parent;
|
||||||
|
PIDeque<int> path_;
|
||||||
|
double value_d;
|
||||||
|
int value_i;
|
||||||
|
bool value_b, calculated, x_enabled;
|
||||||
|
PIVector<double> avg_h;
|
||||||
|
int avg_size;
|
||||||
|
XMode mode_, rmode_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CD_UTILS_EXPORT CDSection {
|
||||||
|
friend class CDCore;
|
||||||
|
friend class Interface;
|
||||||
|
friend class XInterface;
|
||||||
|
friend class ::CD_Pult;
|
||||||
|
friend class ::CDItem;
|
||||||
|
friend class ::CDItemModel;
|
||||||
|
public:
|
||||||
|
|
||||||
|
CDSection(CDType::cdT type_ = CDType::cdNull);
|
||||||
|
|
||||||
|
bool test(int v) {return cd.value(v).toBool();}
|
||||||
|
// CDType & operator [](int v) {if (!k.contains(v)) k[v].index_ = v; return k[v];}
|
||||||
|
CDType & operator [](int v) {return cd[v];}
|
||||||
|
const CDType operator [](int v) const {return cd[v];}
|
||||||
|
CDType & operator [](const PIString & name_) {return getByName(name_);}
|
||||||
|
const CDType operator [](const PIString & name_) const {return const_cast<CDSection*>(this)->getByName(name_);}
|
||||||
|
CDType & operator [](const PIDeque<int> & path_) {return getByPath(path_);}
|
||||||
|
const CDType operator [](const PIDeque<int> & path_) const {return const_cast<CDSection*>(this)->getByPath(path_);}
|
||||||
|
CDSection & section(int v);
|
||||||
|
const CDSection section(int v) const;
|
||||||
|
|
||||||
|
bool isEmpty() const {return cd.isEmpty() && s.isEmpty();}
|
||||||
|
bool exists(PIDeque<int> path) const;
|
||||||
|
int count(bool recursive = true) const;
|
||||||
|
int sectionsCount() const;
|
||||||
|
PIVector<int> indexes() const {return cd.keys();}
|
||||||
|
PIStringList index_names() const;
|
||||||
|
void calculate();
|
||||||
|
void makePath(PIDeque<int> p = PIDeque<int>());
|
||||||
|
PIVector<CDType * > children(bool recursive = true) const;
|
||||||
|
PIVariantTypes::Enum enumValues() const;
|
||||||
|
|
||||||
|
PIString name;
|
||||||
|
PIString alias;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CDSection(PIMap<int, CDType> k_, PIMap<int, CDSection> s_) {
|
||||||
|
cd = k_;
|
||||||
|
s = s_;
|
||||||
|
}
|
||||||
|
CDType & getByName(const PIString & name_);
|
||||||
|
CDType & getByPath(const PIDeque<int> & path_);
|
||||||
|
void write(PIIODevice * d, const PIString & prefix = PIString());
|
||||||
|
void read(const void * ep);
|
||||||
|
void update(CDSection & v, UpdateModeFlags mode = SaveByName);
|
||||||
|
bool isSameStructure(CDSection & v);
|
||||||
|
void prepareCalculate();
|
||||||
|
void calculateRecursive(PIEvaluator * e);
|
||||||
|
void setSelectedX(bool yes);
|
||||||
|
PIVector<PIDeque<int> > collectX() const;
|
||||||
|
|
||||||
|
PIMap<int, CDType> cd;
|
||||||
|
mutable PIMap<int, CDSection> s;
|
||||||
|
CDType null;
|
||||||
|
CDType::cdT cd_type_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline PICout operator <<(PICout s, const CDUtils::CDType & v) {
|
||||||
|
s.space();
|
||||||
|
s.setControl(0, true);
|
||||||
|
switch (v.cd_type()) {
|
||||||
|
case CDUtils::CDType::cdK : s << "K["; break;
|
||||||
|
case CDUtils::CDType::cdX : s << "X["; break;
|
||||||
|
case CDUtils::CDType::cdC : s << "C["; break;
|
||||||
|
case CDUtils::CDType::cdM : s << "M["; break;
|
||||||
|
default : s << "Null["; break;
|
||||||
|
}
|
||||||
|
s << v.name() << "(" << v.index() << ")] = " << v.value();
|
||||||
|
s.restoreControl();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CDUTILS_TYPES_H
|
||||||
55
cd_utils/cdutils_x.cpp
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#include "cdutils_x.h"
|
||||||
|
#include "cdutils_core.h"
|
||||||
|
|
||||||
|
using namespace CDUtils;
|
||||||
|
|
||||||
|
XInterface X;
|
||||||
|
|
||||||
|
|
||||||
|
XInterface::XInterface(): Interface(CDType::cdX) {
|
||||||
|
CONNECTU(core, X_ReceivedX, this, receivedX);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void XInterface::setEnabled(const CDType & x, bool en) {
|
||||||
|
core->x_mutex.lock();
|
||||||
|
CDType & t((*s)[x.path()]);
|
||||||
|
if (t.cd_type() != CDType::cdX) {
|
||||||
|
core->x_mutex.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
t.x_enabled = en;
|
||||||
|
//piCout << t << "x_enabled" << en;
|
||||||
|
core->need_rebuild_x = true;
|
||||||
|
core->x_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIVector<PIDeque<int> > XInterface::enabledList() const {
|
||||||
|
return CDCore::instance()->x_selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void XInterface::setEnabledList(const PIVector<PIDeque<int> > & l) {
|
||||||
|
CDCore::instance()->x_selected = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void XInterface::lock() {
|
||||||
|
CDCore::instance()->x_mutex.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void XInterface::unlock() {
|
||||||
|
CDCore::instance()->x_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void XInterface::start(double freq) {
|
||||||
|
core->startX(freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void XInterface::stop() {
|
||||||
|
core->stopX();
|
||||||
|
}
|
||||||
57
cd_utils/cdutils_x.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
CD Utils - Control-Debug utilites
|
||||||
|
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CDUTILS_X_H
|
||||||
|
#define CDUTILS_X_H
|
||||||
|
|
||||||
|
#include "cdutils_interface.h"
|
||||||
|
#include "cd_utils_export.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace CDUtils {
|
||||||
|
|
||||||
|
|
||||||
|
class CD_UTILS_EXPORT XInterface: public Interface
|
||||||
|
{
|
||||||
|
PIOBJECT_SUBCLASS(XInterface, Interface)
|
||||||
|
public:
|
||||||
|
XInterface();
|
||||||
|
|
||||||
|
EVENT1(keepNamesRequest, bool*, xn)
|
||||||
|
EVENT1(receivedX, PIVector<PIDeque<int> >, pathes)
|
||||||
|
|
||||||
|
void enable(const CDType & x) {setEnabled(x, true);}
|
||||||
|
void disable(const CDType & x) {setEnabled(x, false);}
|
||||||
|
void setEnabled(const CDType & x, bool en);
|
||||||
|
void setDisabled(const CDType & x, bool dis) {setEnabled(x, !dis);}
|
||||||
|
PIVector<PIDeque<int> > enabledList() const;
|
||||||
|
void setEnabledList(const PIVector<PIDeque<int> > & l);
|
||||||
|
void lock();
|
||||||
|
void unlock();
|
||||||
|
|
||||||
|
void start(double freq = 20.);
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern CD_UTILS_EXPORT CDUtils::XInterface X;
|
||||||
|
|
||||||
|
#endif // CDUTILS_X_H
|
||||||
97
cd_utils/cdutilstest.cpp
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
#include "cdutils_k.h"
|
||||||
|
#include "cdutils_x.h"
|
||||||
|
#include "cdutils_c.h"
|
||||||
|
#include "cdutils_m.h"
|
||||||
|
#include "cdutils_core.h"
|
||||||
|
#include "cdtest.h"
|
||||||
|
#include "pip.h"
|
||||||
|
#include "k_description.h"
|
||||||
|
|
||||||
|
using namespace CDUtils;
|
||||||
|
|
||||||
|
class Core : public PIObject
|
||||||
|
{
|
||||||
|
PIOBJECT(Core)
|
||||||
|
public:
|
||||||
|
Core() {
|
||||||
|
CDCore::instance()->initApp();
|
||||||
|
// piCout << "testCore";
|
||||||
|
CONNECTU(&timer, tickEvent, this, timerDone);
|
||||||
|
CONNECTU(&X, received, this, xrecv);
|
||||||
|
CONNECTU(&C, received, this, crecv);
|
||||||
|
t = 0.;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load() {
|
||||||
|
rf.open("k.dat", PIIODevice::ReadWrite);
|
||||||
|
K.read(&rf);
|
||||||
|
rf.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void save() {
|
||||||
|
rf.open("k_out.txt", PIIODevice::ReadWrite);
|
||||||
|
rf.resize(0);
|
||||||
|
K.write(&rf);
|
||||||
|
rf.close();
|
||||||
|
// rf.open("k_out.txt", PIIODevice::ReadWrite);
|
||||||
|
// K.read(&rf);
|
||||||
|
// rf.close();
|
||||||
|
// rf.open("k_out2.txt", PIIODevice::ReadWrite);
|
||||||
|
// rf.resize(0);
|
||||||
|
// K.write(&rf);
|
||||||
|
// rf.close();
|
||||||
|
// rf.open("k_out2.txt", PIIODevice::ReadWrite);
|
||||||
|
// K.read(&rf);
|
||||||
|
// rf.close();
|
||||||
|
// rf.open("k_out3.txt", PIIODevice::ReadWrite);
|
||||||
|
// rf.resize(0);
|
||||||
|
// K.write(&rf);
|
||||||
|
// rf.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
X.lock();
|
||||||
|
X[KD::Frequency] = 100;
|
||||||
|
X.section(KD::Spectrometer)[KD::Temperature_default] = sin(t);
|
||||||
|
t += 0.01;
|
||||||
|
X.unlock();
|
||||||
|
/*piCout << "count" << K.count();
|
||||||
|
piCout << K[First];
|
||||||
|
piCout << K[Second];*/
|
||||||
|
}
|
||||||
|
|
||||||
|
EVENT_HANDLER(void, ksend) {piCout << "sended k";}
|
||||||
|
EVENT_HANDLER(void, crecv) {
|
||||||
|
piCout << "received c";
|
||||||
|
C.connect(C.section(KD::Logs).section(KD::Spec).section(KD::Formats)[KD::Binary], this, HANDLER(cmd));
|
||||||
|
C.autoConnect(this);
|
||||||
|
}
|
||||||
|
EVENT_HANDLER(void, xrecv) {
|
||||||
|
piCout << "received x";
|
||||||
|
if (!timer.isRunning()) timer.start(10);
|
||||||
|
X.start();
|
||||||
|
}
|
||||||
|
EVENT_HANDLER(void, timerDone) {test();}
|
||||||
|
EVENT_HANDLER(void, cmd) {piCout << "command cmd";}
|
||||||
|
EVENT_HANDLER(void, c_Pause) {
|
||||||
|
piCout << "command pause";
|
||||||
|
M[KD::Main] << "rec command" << C[KD::Pause];
|
||||||
|
M.messageBox(M.root()[KD::Core], "init successfull");
|
||||||
|
}
|
||||||
|
EVENT_HANDLER(void, c_Spectrometer_Connection) {piCout << "command spec_conn";}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PIFile rf;
|
||||||
|
PITimer timer;
|
||||||
|
double t;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
X.start();
|
||||||
|
piSleep(1);
|
||||||
|
//CDCore::instance()->destroy();
|
||||||
|
piCout << "DELETED";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
147
cd_utils/k_description.h
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
#ifndef K_DESCRIPTION_H
|
||||||
|
#define K_DESCRIPTION_H
|
||||||
|
|
||||||
|
namespace KD {
|
||||||
|
|
||||||
|
enum Sections {
|
||||||
|
Startup,
|
||||||
|
Spectrometer,
|
||||||
|
Switch,
|
||||||
|
Formats,
|
||||||
|
Logs,
|
||||||
|
Detector,
|
||||||
|
CoreOutput,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LogFormat {
|
||||||
|
Text, //b text
|
||||||
|
Binary, //b binary
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LogType {
|
||||||
|
Data, //b write data logs
|
||||||
|
Spec, //b write spectrogram logs
|
||||||
|
ARINC, //b ARINC
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KLogConfig {
|
||||||
|
// LogFormat = Formats
|
||||||
|
StartupWrite, //b
|
||||||
|
ApplyBinaryLogHeader, //b Apply settings under ID = 255 for binary log
|
||||||
|
MaximumWriteFrequency, //f Maximum frequency for log in Hz, or 0 for unlimited
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SwitchType {
|
||||||
|
BaySpec,
|
||||||
|
DiCon,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SpectrometerConnection {
|
||||||
|
TCP,
|
||||||
|
USB,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PeakSearchMode {
|
||||||
|
Left,
|
||||||
|
Max,
|
||||||
|
Right,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CoreMode {
|
||||||
|
ModeSpectrometer,
|
||||||
|
ModePlayer,
|
||||||
|
ModePeaks,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KSpectrometer {
|
||||||
|
Connection, //e ${SpectrometerConnection}
|
||||||
|
Temperature_compensation, //b Use temperature sensor or default temperature witout compensation
|
||||||
|
Temperature_default, //f Default temperature using if compensation disabled
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KSwitch {
|
||||||
|
Enabled, //b 0 or 1 Use optical switch or not
|
||||||
|
Wait, //n Delay after switching channel, ms
|
||||||
|
Autoscan, //e {0 - scan with our forces, 1 - SDK autoscan}
|
||||||
|
Autoscan_offset, //n Offset for SDK autoscan
|
||||||
|
Type, //e ${SwitchType}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KDetector {
|
||||||
|
Threshold_Min, //f
|
||||||
|
Threshold_Max, //f
|
||||||
|
SideSize, //f
|
||||||
|
SideOffset, //f
|
||||||
|
PeaksSearch, //e ${PeakSearchMode}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KCoreOutput {
|
||||||
|
SendSpectrum, //b Send spectrum data or empty vector
|
||||||
|
SendOnlyCurrentValue, //b Send current values or all stored in 20Hz
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CoreOutputChannel {
|
||||||
|
GUI,
|
||||||
|
SecGUI,
|
||||||
|
ThirdGUI,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KDescription {
|
||||||
|
// KSpectrometer = Spectrometer
|
||||||
|
// KSwitch = Switch
|
||||||
|
// KDetector = Detector
|
||||||
|
// KCoreOutput[CoreOutputChannel] = CoreOutput
|
||||||
|
// KLogConfig[LogType] = Logs
|
||||||
|
Gratings_history, //n Gratings peak values history, count
|
||||||
|
Amplitude_history_size, //n Count of history values to calculate sensors amplitude
|
||||||
|
Fourier_enabled, //b Global fourier enable flag
|
||||||
|
Fourier_size, //n Size of fourier window, in counts
|
||||||
|
Fourier_YScale, //f scale for fourier amplitude
|
||||||
|
Fourier_Max_or_Density, //n 0 - Maximum in fourier window, 1 - Density of fourier window
|
||||||
|
Mode, //e ${CoreMode} Work mode
|
||||||
|
SynchronizationEnabled, //b When enabled, start logs and reset time when sync signal received
|
||||||
|
SynchronizationMode, //e {0 - disabled, 1 - new file, 2 - column in log}
|
||||||
|
LambdasAutoReset, //b Set lambdas_0 to grating values on first data receive
|
||||||
|
Gauss_size, //n
|
||||||
|
//Peak_max_offset, //f in pixels
|
||||||
|
//Peak_LF_coeff, //f 1. - no filtering
|
||||||
|
GratingOverloadMax, //n
|
||||||
|
GratingOverloadMin, //n
|
||||||
|
SendLED, //b Send to LED Arduino serial port current state
|
||||||
|
SynchronizationClearValues, //b clear gratings and sensors values and history on sync
|
||||||
|
PeaksModeFrequency, //f
|
||||||
|
PeaksModeAdditionNm_1, //f Addition nm to peaks in ModePeaks, channel 1
|
||||||
|
PeaksModeAdditionNm_2, //f Addition nm to peaks in ModePeaks, channel 2
|
||||||
|
PeaksModeAdditionNm_3, //f Addition nm to peaks in ModePeaks, channel 3
|
||||||
|
PeaksModeAdditionNm_4, //f Addition nm to peaks in ModePeaks, channel 4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum XDescription {
|
||||||
|
// KSpectrometer = Spectrometer
|
||||||
|
// KSwitch = Switch
|
||||||
|
// KDetector = Detector
|
||||||
|
// KCoreOutput[CoreOutputChannel] = CoreOutput
|
||||||
|
// KLogConfig[LogType] = Logs
|
||||||
|
State, //b
|
||||||
|
Frequency, //n cur freq
|
||||||
|
//Fourier_enabled, //b Global fourier enable flag
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CDescription {
|
||||||
|
// KSpectrometer = Spectrometer
|
||||||
|
// KCoreOutput[CoreOutputChannel] = CoreOutput
|
||||||
|
// KLogConfig[LogType] = Logs
|
||||||
|
Halt, //b
|
||||||
|
Reboot, //n cur freq
|
||||||
|
Pause, //b Global fourier enable flag
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MDescription {
|
||||||
|
Main, //b
|
||||||
|
Core, //s
|
||||||
|
Warnings, //b Global fourier enable flag
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // K_DESCRIPTION_H
|
||||||
50
cmake_android.bat
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
@echo off
|
||||||
|
rem Please add to environment ANDROID_QT5_DIR (path to Qt directory) and ANDROID_NDK_HOME (path to android ndk directory)
|
||||||
|
rem Execute with Android API version and arch e. g. : #cmake_android.bat 24 arm ../libs
|
||||||
|
rem Arches: arm, arm64, x86, x86_64
|
||||||
|
set _usage_=0
|
||||||
|
if [%~1]==[] set _usage_=1
|
||||||
|
if [%~2]==[] set _usage_=1
|
||||||
|
if [%~3]==[] set _usage_=1
|
||||||
|
if %_usage_%==1 (
|
||||||
|
echo Usage: cmake_android.bat ^<API_LEVEL^> ^<ARCH^> ^<SRC^>
|
||||||
|
echo ^ ^ ^<API_LEVEL^> - number of API ^(e.g. 19^)
|
||||||
|
echo ^ ^ ^<ARCH^> - architecture ^(arm, arm64, x86, x86_64^)
|
||||||
|
echo ^ ^ ^<SRC^> - path to sources
|
||||||
|
echo.
|
||||||
|
echo You also have to set next env variables^:
|
||||||
|
echo ^ ^ ANDROID_QT5_DIR - path to Qt dir, contains subdirs for arch
|
||||||
|
echo ^ ^ ANDROID_NDK_HOME - path to android ndk directory
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
set QARCH=
|
||||||
|
set AARCH=
|
||||||
|
set _PLATFORM_=%~1
|
||||||
|
if %~2==arm (
|
||||||
|
set QARCH=armv7
|
||||||
|
set AARCH=armeabi-v7a
|
||||||
|
)
|
||||||
|
if %~2==arm64 (
|
||||||
|
set QARCH=arm64_v8a
|
||||||
|
set AARCH=arm64-v8a
|
||||||
|
if /i %_PLATFORM_% LSS 21 set _PLATFORM_=21
|
||||||
|
)
|
||||||
|
if %~2==x86 (
|
||||||
|
set QARCH=x86
|
||||||
|
set AARCH=x86
|
||||||
|
)
|
||||||
|
if %~2==x86_64 (
|
||||||
|
set QARCH=x86_64
|
||||||
|
set AARCH=x86_64
|
||||||
|
if /i %_PLATFORM_% LSS 21 set _PLATFORM_=21
|
||||||
|
)
|
||||||
|
rem set Qt5_ROOT=%ANDROID_QT5_DIR%\android_%QARCH%\lib\cmake
|
||||||
|
set Qt5_ROOT=%ANDROID_QT5_DIR%\lib\cmake
|
||||||
|
rem set Qt5_DIR=%Qt5_ROOT%\Qt5
|
||||||
|
if NOT [%QARCH%]==[] (
|
||||||
|
@echo on
|
||||||
|
cmake_mgw -Wno-dev -DCMAKE_TOOLCHAIN_FILE=%ANDROID_NDK_HOME%\build\cmake\android.toolchain.cmake -DANDROID_STL=c++_shared -DANDROID_PLATFORM=android-%_PLATFORM_% -DANDROID_ABI=%AARCH% -DICU=0 -DQt4=0 -DQt5=1 -DQGLVIEW=0 -DQGLENGINE=0 -DQt5_DIR=%Qt5_ROOT%\Qt5 -DQt5LinguistTools_DIR=%Qt5_ROOT%\Qt5LinguistTools -DQt5UiPlugin_DIR=%Qt5_ROOT%\Qt5UiPlugin -DQt5UiTools_DIR=%Qt5_ROOT%\Qt5UiTools -DQt5Widgets_DIR=%Qt5_ROOT%\Qt5Widgets -DQt5Core_DIR=%Qt5_ROOT%\Qt5Core -DQt5Gui_DIR=%Qt5_ROOT%\Qt5Gui -DQt5Sql_DIR=%Qt5_ROOT%\Qt5Sql -DQt5OpenGL_DIR=%Qt5_ROOT%\Qt5OpenGL -DQt5PrintSupport_DIR=%Qt5_ROOT%\Qt5PrintSupport -DQt5Script_DIR=%Qt5_ROOT%\Qt5Script -DQt5Positioning_DIR=%Qt5_ROOT%\Qt5Positioning -DQt5Network_DIR=%Qt5_ROOT%\Qt5Network -DQt5Qml_DIR=%Qt5_ROOT%\Qt5Qml -DQt5Quick_DIR=%Qt5_ROOT%\Qt5Quick -DQt5QuickWidgets_DIR=%Qt5_ROOT%\Qt5QuickWidgets -DQt5QmlModels_DIR=%Qt5_ROOT%\Qt5QmlModels -DQt5AndroidExtras_DIR=%Qt5_ROOT%\Qt5AndroidExtras %~3 %~4 %~5 %~6
|
||||||
|
) else (
|
||||||
|
@echo on
|
||||||
|
cmake_mgw -Wno-dev -DCMAKE_TOOLCHAIN_FILE=%ANDROID_NDK_HOME%\build\cmake\android.toolchain.cmake -DANDROID_STL=c++_shared -DANDROID_PLATFORM=android-%_PLATFORM_% -DANDROID_ABI=%AARCH% -DICU=0 -DQt4=0 -DQt5=0 -DQGLVIEW=0 %~3 %~4 %~5 %~6
|
||||||
|
)
|
||||||
3
cmake_android.sh
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export SDK_DIR=/usr/lib/android-sdk
|
||||||
|
export PREFIX=/soft/android
|
||||||
|
rm -rf * && cmake -DCMAKE_TOOLCHAIN_FILE=${SDK_DIR}/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_PLATFORM=android-21 -DQt4=0 -DQt5=1 -DQt5_DIR=${PREFIX}/qt/lib/cmake/Qt5 ../libs
|
||||||
43
docker/android-libs/Dockerfile
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
ARG DOCKER_PREFIX=wapmobil/
|
||||||
|
FROM ${DOCKER_PREFIX}android
|
||||||
|
|
||||||
|
ARG LIBS_BUILD_NUMBER=9999
|
||||||
|
ARG JOBS_COUNT=4
|
||||||
|
ENV PATH=/opt/cmake/bin:$PATH
|
||||||
|
ENV ANDROID_HOME=/usr/lib/android-sdk
|
||||||
|
ENV ANDROID_NDK_HOME=${ANDROID_HOME}/ndk-bundle
|
||||||
|
ENV ANDROID_TOOLCHAIN=${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake
|
||||||
|
ENV NDK_PLATFORM="android-21"
|
||||||
|
|
||||||
|
WORKDIR /soft
|
||||||
|
RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git
|
||||||
|
|
||||||
|
WORKDIR /soft/libs_build_host
|
||||||
|
RUN cmake -DICU=0 -DCROSSTOOLS=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \
|
||||||
|
&& make install -j${JOBS_COUNT} \
|
||||||
|
&& rm -rf * \
|
||||||
|
&& ldconfig
|
||||||
|
|
||||||
|
WORKDIR /soft/libs_build_anroid
|
||||||
|
ENV _ANDROID_TOOLCHAIN=/usr/lib/android-sdk/ndk-bundle/build/cmake/android.toolchain.cmake
|
||||||
|
|
||||||
|
ENV _CUR_ABI=armeabi-v7a
|
||||||
|
RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/android/${_CUR_ABI} -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=${_ANDROID_TOOLCHAIN} -DQt5_DIR=/soft/android/qt/lib/cmake/Qt5 -DANDROID_PLATFORM=${NDK_PLATFORM} -DANDROID_ABI=${_CUR_ABI} ../libs/ \
|
||||||
|
&& make install -j${JOBS_COUNT} && rm -rf *
|
||||||
|
|
||||||
|
ENV _CUR_ABI=arm64-v8a
|
||||||
|
WORKDIR /soft/libs_build_android_${_CUR_ABI}
|
||||||
|
RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/android/${_CUR_ABI} -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=${_ANDROID_TOOLCHAIN} -DQt5_DIR=/soft/android/qt/lib/cmake/Qt5 -DANDROID_PLATFORM=${NDK_PLATFORM} -DANDROID_ABI=${_CUR_ABI} ../libs/ \
|
||||||
|
&& make install -j${JOBS_COUNT} && rm -rf *
|
||||||
|
|
||||||
|
ENV _CUR_ABI=x86
|
||||||
|
WORKDIR /soft/libs_build_android_${_CUR_ABI}
|
||||||
|
RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/android/${_CUR_ABI} -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=${_ANDROID_TOOLCHAIN} -DQt5_DIR=/soft/android/qt/lib/cmake/Qt5 -DANDROID_PLATFORM=${NDK_PLATFORM} -DANDROID_ABI=${_CUR_ABI} ../libs/ \
|
||||||
|
&& make install -j${JOBS_COUNT} && rm -rf *
|
||||||
|
|
||||||
|
ENV _CUR_ABI=x86_64
|
||||||
|
WORKDIR /soft/libs_build_android_${_CUR_ABI}
|
||||||
|
RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/android/${_CUR_ABI} -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=${_ANDROID_TOOLCHAIN} -DQt5_DIR=/soft/android/qt/lib/cmake/Qt5 -DANDROID_PLATFORM=${NDK_PLATFORM} -DANDROID_ABI=${_CUR_ABI} ../libs/ \
|
||||||
|
&& make install -j${JOBS_COUNT} && rm -rf *
|
||||||
|
|
||||||
|
WORKDIR /soft/src
|
||||||
17
docker/debian-libs/Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
ARG DOCKER_PREFIX=wapmobil/
|
||||||
|
FROM ${DOCKER_PREFIX}debian
|
||||||
|
|
||||||
|
ARG LIBS_BUILD_NUMBER=9999
|
||||||
|
ARG JOBS_COUNT=4
|
||||||
|
ENV PATH=/opt/cmake/bin:$PATH
|
||||||
|
|
||||||
|
WORKDIR /soft
|
||||||
|
RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git
|
||||||
|
|
||||||
|
WORKDIR /soft/libs_build_debian
|
||||||
|
RUN cmake -DICU=0 -DLIB=1 -DQGLENGINE=1 -DQGLVIEW=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \
|
||||||
|
&& make install -j${JOBS_COUNT} \
|
||||||
|
&& rm -rf * \
|
||||||
|
&& ldconfig
|
||||||
|
|
||||||
|
WORKDIR /soft/src
|
||||||
21
docker/osx-libs/Dockerfile
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
ARG DOCKER_PREFIX=wapmobil/
|
||||||
|
FROM ${DOCKER_PREFIX}osx
|
||||||
|
|
||||||
|
ARG LIBS_BUILD_NUMBER=9999
|
||||||
|
ARG JOBS_COUNT=4
|
||||||
|
ENV PATH=/soft/osxcross/target/bin:/opt/cmake/bin:$PATH
|
||||||
|
|
||||||
|
WORKDIR /soft
|
||||||
|
RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git
|
||||||
|
|
||||||
|
WORKDIR /soft/libs_build_host
|
||||||
|
RUN cmake -DICU=0 -DCROSSTOOLS=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \
|
||||||
|
&& make install -j${JOBS_COUNT} \
|
||||||
|
&& rm -rf * \
|
||||||
|
&& ldconfig
|
||||||
|
|
||||||
|
WORKDIR /soft/libs_build_osx
|
||||||
|
RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/osx -DICU=0 -DLIB=0 -DQGLENGINE=1 -DQGLVIEW=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=/soft/toolchain-Darwin.cmake ../libs/ \
|
||||||
|
&& make install -j${JOBS_COUNT} && rm -rf *
|
||||||
|
|
||||||
|
WORKDIR /soft/src
|
||||||
21
docker/pi-libs/Dockerfile
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
ARG DOCKER_PREFIX=wapmobil/
|
||||||
|
FROM ${DOCKER_PREFIX}pi
|
||||||
|
|
||||||
|
ARG LIBS_BUILD_NUMBER=9999
|
||||||
|
ARG JOBS_COUNT=4
|
||||||
|
ENV PATH=/opt/cmake/bin:$PATH
|
||||||
|
|
||||||
|
WORKDIR /soft
|
||||||
|
RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git
|
||||||
|
|
||||||
|
WORKDIR /soft/libs_build_host
|
||||||
|
RUN cmake -DICU=0 -DCROSSTOOLS=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \
|
||||||
|
&& make install -j${JOBS_COUNT} \
|
||||||
|
&& rm -rf * \
|
||||||
|
&& ldconfig
|
||||||
|
|
||||||
|
WORKDIR /soft/libs_build_pi
|
||||||
|
RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/pi/usr -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=/soft/toolchain-RPi.cmake ../libs/ \
|
||||||
|
&& make install -j${JOBS_COUNT} && rm -rf *
|
||||||
|
|
||||||
|
WORKDIR /soft/src
|
||||||
21
docker/windows-libs/Dockerfile
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
ARG DOCKER_PREFIX=wapmobil/
|
||||||
|
FROM ${DOCKER_PREFIX}windows
|
||||||
|
|
||||||
|
ARG LIBS_BUILD_NUMBER=9999
|
||||||
|
ARG JOBS_COUNT=4
|
||||||
|
ENV PATH=/opt/cmake/bin:$PATH
|
||||||
|
|
||||||
|
WORKDIR /soft
|
||||||
|
RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git
|
||||||
|
|
||||||
|
WORKDIR /soft/libs_build_host
|
||||||
|
RUN cmake -DICU=0 -DCROSSTOOLS=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \
|
||||||
|
&& make install -j${JOBS_COUNT} \
|
||||||
|
&& rm -rf * \
|
||||||
|
&& ldconfig
|
||||||
|
|
||||||
|
WORKDIR /soft/libs_build_windows
|
||||||
|
RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/windows -DICU=0 -DLIB=0 -DQGLENGINE=1 -DQGLVIEW=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=/soft/toolchain-Windows.cmake ../libs/ \
|
||||||
|
&& make install -j${JOBS_COUNT} && rm -rf *
|
||||||
|
|
||||||
|
WORKDIR /soft/src
|
||||||
76
kx_utils/CMakeLists.txt
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(kx_utils)
|
||||||
|
if (POLICY CMP0017)
|
||||||
|
cmake_policy(SET CMP0017 NEW)
|
||||||
|
endif()
|
||||||
|
if (NOT LIBPROJECT)
|
||||||
|
find_package(PIP REQUIRED)
|
||||||
|
endif ()
|
||||||
|
if (MINGW)
|
||||||
|
find_package(MinGW REQUIRED)
|
||||||
|
endif()
|
||||||
|
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES})
|
||||||
|
set(KX_PULT_NAME "kx_pult")
|
||||||
|
option(KX_PULT "Build ${KX_PULT_NAME}" 1)
|
||||||
|
option(LIB "System install" 1)
|
||||||
|
option(DEBUG "Build with -g3" 0)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall")
|
||||||
|
if (DEBUG)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
|
||||||
|
endif()
|
||||||
|
set(CPPS_UTILS "kx_coeffs.cpp" "piprotocol.cpp")
|
||||||
|
set(HDRS_UTILS "kx_coeffs.h" "kx_protocol_x.h" "kx_protocol_c.h" "piprotocol.h")
|
||||||
|
if (DEFINED ENV{QNX_HOST})
|
||||||
|
add_library(${PROJECT_NAME} STATIC ${CPPS_UTILS})
|
||||||
|
else()
|
||||||
|
add_library(${PROJECT_NAME} SHARED ${CPPS_UTILS})
|
||||||
|
endif()
|
||||||
|
target_link_libraries(${PROJECT_NAME} ${PIP_LIBRARY})
|
||||||
|
message(STATUS "Building ${PROJECT_NAME}")
|
||||||
|
if (NOT DEFINED ENV{QNX_HOST})
|
||||||
|
if (KX_PULT)
|
||||||
|
find_package(Qt4 REQUIRED)
|
||||||
|
find_package(QAD REQUIRED)
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
include_directories(${QT_INCLUDES} ${QAD_INCLUDES})
|
||||||
|
set(CPPS "kx_pult.cpp" "kx_pult.h" "kx_pult.ui" "main_kx_pult.cpp")
|
||||||
|
set(MOCS "kx_pult.h")
|
||||||
|
file(GLOB UIS "*.ui")
|
||||||
|
file(GLOB RES "*.qrc")
|
||||||
|
qt4_wrap_cpp(CMOCS ${MOCS} OPTIONS -nw)
|
||||||
|
qt4_wrap_ui(CUIS ${UIS})
|
||||||
|
qt4_add_resources(RESS ${RES})
|
||||||
|
add_executable(${KX_PULT_NAME} WIN32 ${CPPS} ${CMOCS} ${CUIS} ${RESS} ${MOCS})
|
||||||
|
set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${OPENGL_LIBRARIES} ${PIP_LIBRARY} qad_graphic4 qad_utils4 qad_widgets4)
|
||||||
|
target_link_libraries(${KX_PULT_NAME} ${LIBS} ${PROJECT_NAME})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if (LIB)
|
||||||
|
list(APPEND _ALL_TARGETS ${PROJECT_NAME})
|
||||||
|
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
|
||||||
|
if (WIN32)
|
||||||
|
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
|
||||||
|
install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE})
|
||||||
|
install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_LIB})
|
||||||
|
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${MINGW_BIN})
|
||||||
|
else()
|
||||||
|
if (DEFINED ANDROID_PLATFORM)
|
||||||
|
set(CMAKE_INSTALL_PREFIX ${ANDROID_SYSTEM_LIBRARY_PATH}/usr)
|
||||||
|
else()
|
||||||
|
set(CMAKE_INSTALL_PREFIX /usr/local)
|
||||||
|
endif()
|
||||||
|
install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
|
||||||
|
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
|
||||||
|
endif()
|
||||||
|
message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"")
|
||||||
|
else()
|
||||||
|
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
|
||||||
|
install(TARGETS ${PROJECT_NAME} DESTINATION lib)
|
||||||
|
install(FILES ${HDRS_UTILS} DESTINATION include)
|
||||||
|
message(STATUS "Install ${PROJECT_NAME} to local \"bin\", \"lib\" and \"include\"")
|
||||||
|
endif()
|
||||||
|
if (NOT DEFINED ENV{QNX_HOST})
|
||||||
|
if (KX_PULT)
|
||||||
|
install(TARGETS ${KX_PULT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
4
kx_utils/clean
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
VERBOSE=1 make clean
|
||||||
|
rm -rvf CMakeFiles
|
||||||
|
rm -vf CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *.user* *~ *cxx moc_* ui_* qrc_* *.o
|
||||||
4
kx_utils/clean.bat
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#make clean
|
||||||
|
del /q /f /s CMakeFiles
|
||||||
|
rmdir /q /s CMakeFiles
|
||||||
|
del /q /f CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *.user* *~ *cxx moc_* ui_* qrc_* *.o *.exe *.a *.dll *.lib core *.qrc.depends
|
||||||
BIN
kx_utils/icons/accessories-calculator.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 158 B After Width: | Height: | Size: 158 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
kx_utils/icons/archive-extract.png
Normal file
|
After Width: | Height: | Size: 1005 B |
|
Before Width: | Height: | Size: 717 B After Width: | Height: | Size: 717 B |
|
Before Width: | Height: | Size: 813 B After Width: | Height: | Size: 813 B |
BIN
kx_utils/icons/document-export.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
kx_utils/icons/document-import.png
Normal file
|
After Width: | Height: | Size: 1017 B |
BIN
kx_utils/icons/document-open.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
kx_utils/icons/document-save-.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 563 B After Width: | Height: | Size: 563 B |
BIN
kx_utils/icons/edit-clear-.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 644 B After Width: | Height: | Size: 644 B |
|
Before Width: | Height: | Size: 802 B After Width: | Height: | Size: 802 B |
|
Before Width: | Height: | Size: 485 B After Width: | Height: | Size: 485 B |
|
Before Width: | Height: | Size: 640 B After Width: | Height: | Size: 640 B |
BIN
kx_utils/icons/edit-find-.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 634 B After Width: | Height: | Size: 634 B |
|
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 544 B |
|
Before Width: | Height: | Size: 529 B After Width: | Height: | Size: 529 B |
BIN
kx_utils/icons/expand_s_x.png
Normal file
|
After Width: | Height: | Size: 571 B |
BIN
kx_utils/icons/expand_s_y.png
Normal file
|
After Width: | Height: | Size: 577 B |
BIN
kx_utils/icons/expand_x.png
Normal file
|
After Width: | Height: | Size: 579 B |
BIN
kx_utils/icons/expand_y.png
Normal file
|
After Width: | Height: | Size: 577 B |
|
Before Width: | Height: | Size: 639 B After Width: | Height: | Size: 639 B |
|
Before Width: | Height: | Size: 448 B After Width: | Height: | Size: 448 B |
BIN
kx_utils/icons/layer-visible-off.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
kx_utils/icons/layer-visible-on.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 564 B After Width: | Height: | Size: 564 B |
BIN
kx_utils/icons/media-playback-pause.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
kx_utils/icons/media-playback-stop.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
kx_utils/icons/media-record.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 694 B After Width: | Height: | Size: 694 B |
|
Before Width: | Height: | Size: 658 B After Width: | Height: | Size: 658 B |
|
Before Width: | Height: | Size: 691 B After Width: | Height: | Size: 691 B |
BIN
kx_utils/icons/view-refresh.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 539 B After Width: | Height: | Size: 539 B |
BIN
kx_utils/icons/zoom-fit-height.png
Normal file
|
After Width: | Height: | Size: 929 B |
194
kx_utils/kx_coeffs.cpp
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
#include "kx_coeffs.h"
|
||||||
|
#include "kx_protocol_x.h"
|
||||||
|
|
||||||
|
double X[KX_X_COUNT];
|
||||||
|
PIVector<double> K;
|
||||||
|
|
||||||
|
|
||||||
|
KX_Coefficients::KX_Coefficients(const PIString & config, const PIString & name, bool _pult) {
|
||||||
|
setName("kx_coeffs");
|
||||||
|
PIConfig conf(config, PIIODevice::ReadOnly);
|
||||||
|
fname = conf.getValue(name).getValue("file", "k.dat");
|
||||||
|
readCoeffs();
|
||||||
|
int ns = piMaxi(conf.getValue(name).getValue("count", 0), K.size_s());
|
||||||
|
if (ns > K.size_s()) {
|
||||||
|
K.resize(ns, 0.f);
|
||||||
|
formulas.resize(ns);
|
||||||
|
writeCoeffs();
|
||||||
|
}
|
||||||
|
config_ = config;
|
||||||
|
name_ = name;
|
||||||
|
pult_ = _pult;
|
||||||
|
k_protocol = 0;
|
||||||
|
renew();
|
||||||
|
//readCoeffs();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KX_Coefficients::~KX_Coefficients() {
|
||||||
|
stop();
|
||||||
|
k_protocol->stop();
|
||||||
|
delete k_protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Coefficients::readCoeffs() {
|
||||||
|
{
|
||||||
|
PIConfig conf(fname, PIIODevice::ReadOnly);
|
||||||
|
int cnt = conf.rootEntry().childCount();
|
||||||
|
K.resize(cnt);
|
||||||
|
formulas.resize(cnt);
|
||||||
|
PIString kn, cf;
|
||||||
|
for (int i = 0; i < cnt; i++) {
|
||||||
|
kn = "k" + PIString::fromNumber(i);
|
||||||
|
K[i] = (double)conf.getValue(kn, 0.f);
|
||||||
|
cf = conf.getValue(kn + ".formula", "");
|
||||||
|
if (cf.isEmpty()) cf = PIString::fromNumber(K[i]);
|
||||||
|
formulas[i] = cf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
k_content = PIFile(fname, PIIODevice::ReadOnly).readAll();
|
||||||
|
//piCout << k_content.size();
|
||||||
|
piCoutObj << "Readed" << K.size_s() << "coefficients in" << k_content.size_s() << "bytes";
|
||||||
|
coeffs_cnt = K.size_s();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Coefficients::writeCoeffs() {
|
||||||
|
PIFile::remove(fname);
|
||||||
|
PIFile conf(fname, PIIODevice::ReadWrite);
|
||||||
|
//conf.clear();
|
||||||
|
for (int i = 0; i < K.size_s(); i++) {
|
||||||
|
conf << "k" + PIString::fromNumber(i) << " = " << PIString::fromNumber(K[i]).replaceAll(",", ".") << "\n";
|
||||||
|
conf << "k" + PIString::fromNumber(i) << ".formula = " << formulas[i] << "\n";
|
||||||
|
}
|
||||||
|
//conf.close();
|
||||||
|
//conf.writeAll();
|
||||||
|
k_content = conf.readAll();
|
||||||
|
//piCout << k_content.size();
|
||||||
|
piCoutObj << "Written" << K.size_s() << "coefficients in" << k_content.size_s() << "bytes";
|
||||||
|
coeffs_cnt = K.size_s();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Coefficients::setKFile(const PIString & f) {
|
||||||
|
fname = f;
|
||||||
|
readCoeffs();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Coefficients::sendCoeffs() {
|
||||||
|
stop();
|
||||||
|
int curcnt, pcnt = (k_content.size_s() - 1) / __BYTES_IN_PACKET + 1;
|
||||||
|
k_protocol->to_k.full_count = k_content.size_s();
|
||||||
|
for (int i = 0; i < pcnt; i++) {
|
||||||
|
k_protocol->to_k.first_index = i * __BYTES_IN_PACKET;
|
||||||
|
if (i == pcnt - 1) curcnt = k_content.size_s() % __BYTES_IN_PACKET;
|
||||||
|
else curcnt = __BYTES_IN_PACKET;
|
||||||
|
//cout << "send " << curcnt << " coeffs\n";
|
||||||
|
k_protocol->to_k.count = curcnt;
|
||||||
|
memcpy(k_protocol->to_k.coeffs, k_content.data(k_protocol->to_k.first_index), curcnt);
|
||||||
|
//for (int j = 0; j < curcnt; j++) k_protocol->to_k.coeffs[j] = K.at(k_protocol->to_k.first_index + j);
|
||||||
|
k_protocol->send();
|
||||||
|
piMSleep(5);
|
||||||
|
}
|
||||||
|
//cout << "waiting for commit ...\n";
|
||||||
|
waitingCommit = true;
|
||||||
|
tm.reset();
|
||||||
|
start(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Coefficients::receiveCoeffs() {
|
||||||
|
stop();
|
||||||
|
k_protocol->to_k.full_count = k_protocol->to_k.first_index = k_protocol->to_k.count = -6;
|
||||||
|
k_protocol->send();
|
||||||
|
//cout << "request send\n";
|
||||||
|
//cout << "waiting for receive ...\n";
|
||||||
|
waitingCommit = false;
|
||||||
|
tm.reset();
|
||||||
|
start(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Coefficients::received(bool correct) {
|
||||||
|
//cout << "kpi received " << correct << endl;
|
||||||
|
if (!correct) return;
|
||||||
|
k_syns = k_protocol->from_k;
|
||||||
|
if (waitingCommit) {
|
||||||
|
if (k_syns.first_index != -1 ||
|
||||||
|
k_syns.full_count != -1 ||
|
||||||
|
k_syns.count != -k_content.size_s()) return;
|
||||||
|
//cout << "commit received\n";
|
||||||
|
waitingCommit = false;
|
||||||
|
stop();
|
||||||
|
//cout << "send succeed\n";
|
||||||
|
//emit sendSucceed();
|
||||||
|
sendSucceed();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (k_syns.first_index == -6 && k_syns.full_count == -6 && k_syns.count == -6) {
|
||||||
|
//cout << "request received\n";
|
||||||
|
sendCoeffs();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (k_syns.first_index < 0 || k_syns.count < 0) return;
|
||||||
|
if (k_syns.first_index == 0) {
|
||||||
|
//cout << "first receive\n";
|
||||||
|
k_tmp.resize(k_syns.full_count);
|
||||||
|
received_cnt = 0;
|
||||||
|
}
|
||||||
|
//for (int i = 0; i < k_syns.count; i++) K.at(k_syns.first_index + i) = k_syns.coeffs[i];
|
||||||
|
//piCout << k_tmp.size() << k_syns.first_index << k_syns.count;
|
||||||
|
memcpy(k_tmp.data(k_syns.first_index), k_syns.coeffs, k_syns.count);
|
||||||
|
received_cnt += k_syns.count;
|
||||||
|
tm.reset();
|
||||||
|
//cout << "received " << k_syns.count << " bytes with " << k_syns.first_index << " first\n";
|
||||||
|
if (received_cnt < k_syns.full_count) return;
|
||||||
|
//cout << "finally received " << received_cnt << " bytes\n";
|
||||||
|
stop();
|
||||||
|
PIFile::remove(fname);
|
||||||
|
PIFile conf(fname, PIIODevice::ReadWrite);
|
||||||
|
conf.write(k_tmp.data(), k_tmp.size_s());
|
||||||
|
conf.close();
|
||||||
|
readCoeffs();
|
||||||
|
//writeCoeffs();
|
||||||
|
k_protocol->to_k.full_count = k_protocol->to_k.first_index = -1;
|
||||||
|
k_protocol->to_k.count = -received_cnt;
|
||||||
|
k_protocol->send();
|
||||||
|
waitingCommit = false;
|
||||||
|
//emit receiveSucceed();
|
||||||
|
receiveSucceed();
|
||||||
|
//cout << "receive succeed\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Coefficients::renew() {
|
||||||
|
if (k_protocol != 0) {
|
||||||
|
k_protocol->stop();
|
||||||
|
delete k_protocol;
|
||||||
|
}
|
||||||
|
k_protocol = new __KPi(config_, name_, pult_);
|
||||||
|
CONNECT1(void, bool, k_protocol, received, this, received)
|
||||||
|
waitingCommit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Coefficients::tick(void * , int ) {
|
||||||
|
//piCout << "timer" << tm.elapsed_s();
|
||||||
|
if (tm.elapsed_s() < 10.) return;
|
||||||
|
if (waitingCommit) {
|
||||||
|
//cout << "commit timeout\n";
|
||||||
|
//cout << "send failed\n";
|
||||||
|
//emit sendFailed();
|
||||||
|
sendFailed();
|
||||||
|
} else {
|
||||||
|
//cout << "receive timeout\n";
|
||||||
|
//cout << "receive failed\n";
|
||||||
|
//emit receiveFailed();
|
||||||
|
receiveFailed();
|
||||||
|
}
|
||||||
|
waitingCommit = false;
|
||||||
|
stop();
|
||||||
|
}
|
||||||
95
kx_utils/kx_coeffs.h
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#ifndef KX_COEFFS_H
|
||||||
|
#define KX_COEFFS_H
|
||||||
|
|
||||||
|
#include "piprotocol.h"
|
||||||
|
|
||||||
|
#define __BYTES_IN_PACKET 4000
|
||||||
|
|
||||||
|
extern PIVector<double> K;
|
||||||
|
|
||||||
|
class __KPi: public PIProtocol
|
||||||
|
{
|
||||||
|
PIOBJECT_SUBCLASS(__KPi, PIProtocol)
|
||||||
|
public:
|
||||||
|
#pragma pack (push, 1)
|
||||||
|
struct KX_K_Sync {
|
||||||
|
uchar type;
|
||||||
|
uchar addr_to;
|
||||||
|
int count;
|
||||||
|
int full_count;
|
||||||
|
int first_index;
|
||||||
|
uchar coeffs[__BYTES_IN_PACKET];
|
||||||
|
uint checksum;
|
||||||
|
};
|
||||||
|
#pragma pack (pop)
|
||||||
|
__KPi(const PIString & config, const PIString & name, bool _pult = false): PIProtocol(config, name, &from_k, 2, &(from_k.count), sizeof(from_k) - 2, &to_k, sizeof(to_k)) {
|
||||||
|
PIConfig conf(config, PIIODevice::ReadOnly);
|
||||||
|
PIConfig::Entry ce = conf.getValue(name);
|
||||||
|
to_k.type = from_k.type = ce.getValue("type", 0xA);
|
||||||
|
to_k.addr_to = ce.getValue("addr_k", 0x15);
|
||||||
|
from_k.addr_to = ce.getValue("addr_pult", 0x75);
|
||||||
|
if (_pult) piSwap<uchar>(to_k.addr_to, from_k.addr_to);
|
||||||
|
packetExtractor()->setHeader(PIByteArray(&from_k, 2));
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
KX_K_Sync to_k, from_k;
|
||||||
|
private:
|
||||||
|
bool validate() {
|
||||||
|
return (from_k.checksum == checksum_i(&from_k, sizeof(from_k) - 4));
|
||||||
|
}
|
||||||
|
bool aboutSend() {
|
||||||
|
to_k.checksum = checksum_i(&to_k, sizeof(to_k) - 4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class KX_Coefficients: public PITimer
|
||||||
|
{
|
||||||
|
PIOBJECT_SUBCLASS(KX_Coefficients, PITimer)
|
||||||
|
friend class KX_Pult;
|
||||||
|
public:
|
||||||
|
KX_Coefficients(const PIString & config, const PIString & name = "k", bool _pult = false);
|
||||||
|
~KX_Coefficients();
|
||||||
|
|
||||||
|
void readCoeffs();
|
||||||
|
void writeCoeffs();
|
||||||
|
|
||||||
|
void sendCoeffs();
|
||||||
|
void receiveCoeffs();
|
||||||
|
|
||||||
|
bool isReady() const {return !waitingCommit;}
|
||||||
|
const PIString & fileName() const {return fname;}
|
||||||
|
const PIString * fileName_ptr() const {return &fname;}
|
||||||
|
int coeffsCount() {coeffs_cnt = K.size_s(); return coeffs_cnt;}
|
||||||
|
const int * coeffsCount_ptr() const {return &coeffs_cnt;}
|
||||||
|
|
||||||
|
const PIString & formula(int index) const {return formulas[index];}
|
||||||
|
void setFormula(int index, const PIString & f) {formulas[index] = f;}
|
||||||
|
|
||||||
|
void setKFile(const PIString & f);
|
||||||
|
|
||||||
|
EVENT(sendSucceed)
|
||||||
|
EVENT(sendFailed)
|
||||||
|
EVENT(receiveSucceed)
|
||||||
|
EVENT(receiveFailed)
|
||||||
|
|
||||||
|
|
||||||
|
__KPi * k_protocol;
|
||||||
|
|
||||||
|
private:
|
||||||
|
EVENT_HANDLER1(void, received, bool, correct);
|
||||||
|
void renew();
|
||||||
|
void tick(void *, int);
|
||||||
|
|
||||||
|
__KPi::KX_K_Sync k_syns;
|
||||||
|
bool pult_, waitingCommit;
|
||||||
|
int received_cnt, coeffs_cnt;
|
||||||
|
PIString fname, config_, name_;
|
||||||
|
PIStringList formulas;
|
||||||
|
PIByteArray k_content, k_tmp;
|
||||||
|
PITimeMeasurer tm;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KX_COEFFS_H
|
||||||
126
kx_utils/kx_protocol_c.h
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
#ifndef KX_PROTOCOL_C_H
|
||||||
|
#define KX_PROTOCOL_C_H
|
||||||
|
|
||||||
|
#include "piprotocol.h"
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack (push, 1)
|
||||||
|
|
||||||
|
|
||||||
|
struct KX_C_Header {
|
||||||
|
uchar type;
|
||||||
|
uchar addr_to;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct KX_C_Command: KX_C_Header {
|
||||||
|
KX_C_Command() {command = -1;}
|
||||||
|
int command;
|
||||||
|
uint checksum;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct KX_C_Event: KX_C_Header {
|
||||||
|
KX_C_Event() {event = -1;}
|
||||||
|
PISystemTime time;
|
||||||
|
int event;
|
||||||
|
uint checksum;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack (pop)
|
||||||
|
|
||||||
|
|
||||||
|
// Client side
|
||||||
|
|
||||||
|
class KX_Protocol_C: public PIProtocol
|
||||||
|
{
|
||||||
|
PIOBJECT_SUBCLASS(KX_Protocol_C, PIProtocol)
|
||||||
|
public:
|
||||||
|
KX_Protocol_C(const PIString & config, const PIString & name = "c"): PIProtocol(config, name, &from_buff, 2, &(from_buff.command), sizeof(from_buff) - 2, &to_pult, sizeof(to_pult)) {
|
||||||
|
PIConfig conf(config, PIIODevice::ReadOnly);
|
||||||
|
PIConfig::Entry ce = conf.getValue(name);
|
||||||
|
to_pult.type = from_buff.type = ce.getValue("type", 0xC);
|
||||||
|
to_pult.addr_to = ce.getValue("addr_pult", 0x15);
|
||||||
|
from_buff.addr_to = ce.getValue("addr_c", 0x75);
|
||||||
|
from_pult = from_buff;
|
||||||
|
packetExtractor()->setSplitMode(PIPacketExtractor::Header);
|
||||||
|
packetExtractor()->setHeader(PIByteArray(&from_buff, 2));
|
||||||
|
startReceive();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendEvent(int ev) {
|
||||||
|
to_pult.time = PISystemTime::current();
|
||||||
|
to_pult.event = ev;
|
||||||
|
send();
|
||||||
|
}
|
||||||
|
EVENT1(commandReceived, int, command)
|
||||||
|
|
||||||
|
KX_C_Command from_pult;
|
||||||
|
KX_C_Event to_pult;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool validate() {
|
||||||
|
if (checksum_i(&from_buff, sizeof(from_buff) - 4) != from_buff.checksum) return false;
|
||||||
|
from_pult = from_buff;
|
||||||
|
commandReceived(from_pult.command);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool aboutSend() {
|
||||||
|
to_pult.checksum = checksum_i(&to_pult, sizeof(to_pult) - 4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
KX_C_Command from_buff;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Pult side
|
||||||
|
|
||||||
|
class __KX_Protocol_C: public PIProtocol
|
||||||
|
{
|
||||||
|
PIOBJECT_SUBCLASS(__KX_Protocol_C, PIProtocol)
|
||||||
|
public:
|
||||||
|
__KX_Protocol_C(const PIString & config, const PIString & name): PIProtocol(config, name, &from_buff, 2, &(from_buff.time), sizeof(from_buff) - 2, &to_c, sizeof(to_c)) {
|
||||||
|
PIConfig conf(config, PIIODevice::ReadOnly);
|
||||||
|
PIConfig::Entry ce = conf.getValue(name);
|
||||||
|
to_c.type = from_buff.type = ce.getValue("type", 0xC);
|
||||||
|
to_c.addr_to = ce.getValue("addr_c", 0x75);
|
||||||
|
from_buff.addr_to = ce.getValue("addr_pult", 0x15);
|
||||||
|
from_c = from_buff;
|
||||||
|
packetExtractor()->setSplitMode(PIPacketExtractor::Header);
|
||||||
|
packetExtractor()->setHeader(PIByteArray(&from_buff, 2));
|
||||||
|
startReceive();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendCommand(int cmd) {
|
||||||
|
to_c.command = cmd;
|
||||||
|
send();
|
||||||
|
}
|
||||||
|
EVENT2(eventReceived, int, event, PISystemTime, time)
|
||||||
|
|
||||||
|
KX_C_Event from_c;
|
||||||
|
KX_C_Command to_c;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool validate() {
|
||||||
|
if (checksum_i(&from_buff, sizeof(from_buff) - 4) != from_buff.checksum) return false;
|
||||||
|
from_c = from_buff;
|
||||||
|
eventReceived(from_c.event, from_c.time);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool aboutSend() {
|
||||||
|
//piCout << "send command" << to_c.command;
|
||||||
|
to_c.checksum = checksum_i(&to_c, sizeof(to_c) - 4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
KX_C_Event from_buff;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // KX_PROTOCOL_C_H
|
||||||
121
kx_utils/kx_protocol_x.h
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
#ifndef KX_PROTOCOL_X_H
|
||||||
|
#define KX_PROTOCOL_X_H
|
||||||
|
|
||||||
|
#include "piprotocol.h"
|
||||||
|
|
||||||
|
#define KX_X_PACKET_NUM 20
|
||||||
|
#define KX_X_COUNT 16384
|
||||||
|
|
||||||
|
extern double X[KX_X_COUNT];
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack (push, 1)
|
||||||
|
|
||||||
|
|
||||||
|
struct KX_X_Header {
|
||||||
|
uchar type;
|
||||||
|
uchar addr_to;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct KX_X_Numbers: KX_X_Header {
|
||||||
|
int x_num[KX_X_PACKET_NUM];
|
||||||
|
uint checksum;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct KX_X_Data: KX_X_Header {
|
||||||
|
int x_num[KX_X_PACKET_NUM];
|
||||||
|
double x_data[KX_X_PACKET_NUM];
|
||||||
|
uint checksum;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack (pop)
|
||||||
|
|
||||||
|
|
||||||
|
// Client side
|
||||||
|
|
||||||
|
class KX_Protocol_X: public PIProtocol
|
||||||
|
{
|
||||||
|
PIOBJECT_SUBCLASS(KX_Protocol_X, PIProtocol)
|
||||||
|
public:
|
||||||
|
KX_Protocol_X(const PIString & config, const PIString & name = "x"): PIProtocol(config, name, &from_buff, 2, &(from_buff.x_num[0]), sizeof(from_buff) - 2, &to_pult, sizeof(to_pult)) {
|
||||||
|
PIConfig conf(config, PIIODevice::ReadOnly);
|
||||||
|
PIConfig::Entry ce = conf.getValue(name);
|
||||||
|
to_pult.type = from_buff.type = ce.getValue("type", 0xB);
|
||||||
|
to_pult.addr_to = ce.getValue("addr_pult", 0x15);
|
||||||
|
from_buff.addr_to = ce.getValue("addr_x", 0x75);
|
||||||
|
from_pult = from_buff;
|
||||||
|
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
|
||||||
|
to_pult.x_num[i] = from_pult.x_num[i] = -1;
|
||||||
|
packetExtractor()->setSplitMode(PIPacketExtractor::Header);
|
||||||
|
packetExtractor()->setHeader(PIByteArray(&from_buff, 2));
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
KX_X_Numbers from_pult;
|
||||||
|
KX_X_Data to_pult;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool validate() {
|
||||||
|
if (checksum_i(&from_buff, sizeof(from_buff) - 4) != from_buff.checksum) return false;
|
||||||
|
from_pult = from_buff;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool aboutSend() {
|
||||||
|
for (int i = 0; i < KX_X_PACKET_NUM; ++i) {
|
||||||
|
to_pult.x_num[i] = from_pult.x_num[i];
|
||||||
|
to_pult.x_data[i] = from_pult.x_num[i] < 0 ? 0. : X[from_pult.x_num[i]];
|
||||||
|
}
|
||||||
|
to_pult.checksum = checksum_i(&to_pult, sizeof(to_pult) - 4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
KX_X_Numbers from_buff;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Pult side
|
||||||
|
|
||||||
|
class __KX_Protocol_X: public PIProtocol
|
||||||
|
{
|
||||||
|
PIOBJECT_SUBCLASS(__KX_Protocol_X, PIProtocol)
|
||||||
|
public:
|
||||||
|
__KX_Protocol_X(const PIString & config, const PIString & name): PIProtocol(config, name, &from_buff, 2, &(from_buff.x_num[0]), sizeof(from_buff) - 2, &to_x, sizeof(to_x)) {
|
||||||
|
PIConfig conf(config, PIIODevice::ReadOnly);
|
||||||
|
PIConfig::Entry ce = conf.getValue(name);
|
||||||
|
to_x.type = from_buff.type = ce.getValue("type", 0xB);
|
||||||
|
to_x.addr_to = ce.getValue("addr_x", 0x75);
|
||||||
|
from_buff.addr_to = ce.getValue("addr_pult", 0x15);
|
||||||
|
from_x = from_buff;
|
||||||
|
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
|
||||||
|
to_x.x_num[i] = -1;
|
||||||
|
packetExtractor()->setSplitMode(PIPacketExtractor::Header);
|
||||||
|
packetExtractor()->setHeader(PIByteArray(&from_buff, 2));
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
KX_X_Data from_x;
|
||||||
|
KX_X_Numbers to_x;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool validate() {
|
||||||
|
if (checksum_i(&from_buff, sizeof(from_buff) - 4) != from_buff.checksum) return false;
|
||||||
|
from_x = from_buff;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool aboutSend() {
|
||||||
|
to_x.checksum = checksum_i(&to_x, sizeof(to_x) - 4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
KX_X_Data from_buff;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // KX_PROTOCOL_X_H
|
||||||
0
kx_utils/kx_pult.conf
Normal file
848
kx_utils/kx_pult.cpp
Normal file
@@ -0,0 +1,848 @@
|
|||||||
|
#include <QScrollBar>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <math.h>
|
||||||
|
#include "kx_pult.h"
|
||||||
|
#include "ui_kx_pult.h"
|
||||||
|
#include "piqt.h"
|
||||||
|
#include "qpiconfig.h"
|
||||||
|
|
||||||
|
|
||||||
|
bool isNormalDouble(const double & v) {
|
||||||
|
#ifdef WINDOWS
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return !isnan(v) && !isinf(v);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
XCheck::XCheck(int index): QWidget() {
|
||||||
|
index_ = index;
|
||||||
|
setProperty("index", index);
|
||||||
|
setMouseTracking(true);
|
||||||
|
check.setText(QString::number(index + 1) + " ");
|
||||||
|
check.setAutoFillBackground(true);
|
||||||
|
spin.setMaximum(KX_X_COUNT - 1);
|
||||||
|
QBoxLayout * l = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||||
|
l->setMargin(0);
|
||||||
|
l->setSpacing(2);
|
||||||
|
l->addWidget(&check);
|
||||||
|
l->addWidget(&spin);
|
||||||
|
setLayout(l);
|
||||||
|
//check.installEventFilter(this);
|
||||||
|
//spin.installEventFilter(this);
|
||||||
|
connect(&spin, SIGNAL(valueChanged(int)), this, SLOT(spinChanged(int)));
|
||||||
|
connect(&check, SIGNAL(toggled(bool)), this, SLOT(checkChanged_(bool)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool XCheck::eventFilter(QObject * o, QEvent * e) {
|
||||||
|
if (e->type() == QEvent::Enter)
|
||||||
|
qApp->postEvent(this, new QEvent(e->type()));
|
||||||
|
return QWidget::eventFilter(o, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
KX_Pult::KX_Pult(): QMainWindow(), config_("kx_pult.conf"), name_x("x"), name_c("c"),
|
||||||
|
config(piqt(config_), QIODevice::ReadWrite), coeffs(config_, "k", true) {
|
||||||
|
//cout << sizeof(coeffsK.k_protocol->to_k) << endl;
|
||||||
|
ui = new Ui::KX_Pult();
|
||||||
|
ui->setupUi(this);
|
||||||
|
ui->configWidget->setQPIConfig(&config);
|
||||||
|
ui->configWidget->expandAll();
|
||||||
|
ui->list->viewport()->installEventFilter(this);
|
||||||
|
ui->treeK->viewport()->installEventFilter(this);
|
||||||
|
ui->scrollArea->setAutoFillBackground(false);
|
||||||
|
ui->scrollAreaWidgetContents->setAutoFillBackground(false);
|
||||||
|
ui->widget->setAutoFillBackground(false);
|
||||||
|
ui->label_17->setFixedSize(preferredIconSize(1.25, this));
|
||||||
|
log_menu.addAction(ui->actionClear);
|
||||||
|
prot_x = 0;
|
||||||
|
prot_c = 0;
|
||||||
|
show_x = config.getValue("show_x", true);
|
||||||
|
if (!show_x)
|
||||||
|
ui->tabWidget->removeTab(1);
|
||||||
|
session.setFile("session_KX_Pult.conf");
|
||||||
|
session.addEntry(this);
|
||||||
|
session.addEntry(ui->tabWidget);
|
||||||
|
session.addEntry(ui->checkKHideEmpty);
|
||||||
|
session.addEntry(ui->checkKHideNormal);
|
||||||
|
session.addEntry(ui->checkKHideExpressions);
|
||||||
|
session.addEntry(ui->checkKAutoCalculate);
|
||||||
|
needWrite = isPause = false;
|
||||||
|
timer = 0;
|
||||||
|
//x.resize(KX_X_PACKET_NUM);
|
||||||
|
//k.resize(K_NUM);
|
||||||
|
QPalette pal = palette();
|
||||||
|
QColor col;
|
||||||
|
ui->graphic->setGraphicsCount(0);
|
||||||
|
for (int i = 0; i < KX_X_PACKET_NUM; ++i) {
|
||||||
|
XCheck * xc = new XCheck(i);
|
||||||
|
xc->installEventFilter(this);
|
||||||
|
connect(xc, SIGNAL(valueChanged(int, int)), this, SLOT(changedX(int,int)));
|
||||||
|
connect(xc, SIGNAL(checkChanged(int, bool)), this, SLOT(toggledX(int, bool)));
|
||||||
|
col = QColor::fromHsv(360 / KX_X_PACKET_NUM * i, 255, 200);
|
||||||
|
pal.setColor(QPalette::Button, col);
|
||||||
|
pal.setColor(QPalette::Window, col);
|
||||||
|
pal.setColor(QPalette::WindowText, invertColor(col));
|
||||||
|
xc->check.setPalette(pal);
|
||||||
|
ui->graphic->addGraphic(QString::number(i), col);
|
||||||
|
ui->graphic->setGraphicVisible(false, i);
|
||||||
|
checks << xc;
|
||||||
|
((QGridLayout * )(ui->widgetChecks->layout()))->addWidget(xc, (i / 10) * 2, i % 10);
|
||||||
|
QLabel * lbl = new QLabel("0"); lbl->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
|
||||||
|
values << lbl;
|
||||||
|
((QGridLayout * )(ui->widgetChecks->layout()))->addWidget(lbl, (i / 10) * 2 + 1, i % 10);
|
||||||
|
//xc->show();
|
||||||
|
}
|
||||||
|
renew();
|
||||||
|
icon_record = QIcon(":/icons/media-record.png");
|
||||||
|
icon_stop = QIcon(":/icons/media-playback-stop.png");
|
||||||
|
outdir = dir.absolutePath();
|
||||||
|
if (!dir.exists()) dir.mkdir(outdir);
|
||||||
|
outdir += "/";
|
||||||
|
ui->treeK->setColumnWidth(0, 60);
|
||||||
|
ui->treeK->setColumnWidth(1, 250);
|
||||||
|
ui->treeK->setColumnWidth(3, 100);
|
||||||
|
ui->treeK->setColumnWidth(4, 100);
|
||||||
|
//ui->table->setK(coeffsK.k()->data(), coeffsK.count());
|
||||||
|
ui->spinSize->setValue(K.size_s());
|
||||||
|
addToList(trUtf8("Read K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta);
|
||||||
|
CONNECT(void, &coeffs, sendFailed, this, pip_sendFailed);
|
||||||
|
CONNECT(void, &coeffs, sendSucceed, this, pip_sendSucceed);
|
||||||
|
CONNECT(void, &coeffs, receiveFailed, this, pip_receiveFailed);
|
||||||
|
CONNECT(void, &coeffs, receiveSucceed, this, pip_receiveSucceed);
|
||||||
|
connect(this, SIGNAL(q_k_sendFailed()), this, SLOT(k_sendFailed()), Qt::QueuedConnection);
|
||||||
|
connect(this, SIGNAL(q_k_sendSucceed()), this, SLOT(k_sendSucceed()), Qt::QueuedConnection);
|
||||||
|
connect(this, SIGNAL(q_k_receiveFailed()), this, SLOT(k_receiveFailed()), Qt::QueuedConnection);
|
||||||
|
connect(this, SIGNAL(q_k_receiveSucceed()), this, SLOT(k_receiveSucceed()), Qt::QueuedConnection);
|
||||||
|
connect(&timer_diag, SIGNAL(timeout()), this, SLOT(updateDiag()));
|
||||||
|
connect(&session, SIGNAL(loading(QPIConfig&)), this, SLOT(loading(QPIConfig&)));
|
||||||
|
connect(&session, SIGNAL(saving(QPIConfig&)), this, SLOT(saving(QPIConfig&)));
|
||||||
|
connect(ui->checkKHideEmpty, SIGNAL(toggled(bool)), this, SLOT(filterTree()));
|
||||||
|
connect(ui->checkKHideNormal, SIGNAL(toggled(bool)), this, SLOT(filterTree()));
|
||||||
|
connect(ui->checkKHideExpressions, SIGNAL(toggled(bool)), this, SLOT(filterTree()));
|
||||||
|
connect(ui->lineKSearch, SIGNAL(textChanged(QString)), this, SLOT(filterTree()));
|
||||||
|
session.load();
|
||||||
|
updateKDesc();
|
||||||
|
updateCDesc();
|
||||||
|
timer_diag.start(40);
|
||||||
|
timer_update = startTimer(25);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KX_Pult::~KX_Pult() {
|
||||||
|
session.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::loading(QPIConfig & conf) {
|
||||||
|
kdesc_file = conf.getValue("kdesc_file").stringValue();
|
||||||
|
cdesc_file = conf.getValue("cdesc_file").stringValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::saving(QPIConfig & conf) {
|
||||||
|
conf.setValue("kdesc_file", kdesc_file);
|
||||||
|
conf.setValue("cdesc_file", cdesc_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool KX_Pult::eventFilter(QObject * o, QEvent * e) {
|
||||||
|
if (o == ui->list->viewport()) {
|
||||||
|
if (e->type() == QEvent::ContextMenu) {
|
||||||
|
clear_target = 0;
|
||||||
|
log_menu.popup(((QContextMenuEvent*)e)->globalPos());
|
||||||
|
}
|
||||||
|
return QMainWindow::eventFilter(o, e);
|
||||||
|
}
|
||||||
|
if (o == ui->treeK->viewport()) {
|
||||||
|
if (e->type() == QEvent::ContextMenu) {
|
||||||
|
clear_target = 1;
|
||||||
|
log_menu.popup(((QContextMenuEvent*)e)->globalPos());
|
||||||
|
}
|
||||||
|
return QMainWindow::eventFilter(o, e);
|
||||||
|
}
|
||||||
|
int ind = o->property("index").toInt();
|
||||||
|
//qDebug() << "event" << i << e->type();
|
||||||
|
switch (e->type()) {
|
||||||
|
case QEvent::Enter:
|
||||||
|
ui->graphic->setAutoUpdate(false);
|
||||||
|
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
|
||||||
|
ui->graphic->setGraphicLineWidth(ind == i ? 3. : 1., i);
|
||||||
|
ui->graphic->setAutoUpdate(true);
|
||||||
|
ui->graphic->update();
|
||||||
|
break;
|
||||||
|
case QEvent::Leave:
|
||||||
|
ui->graphic->setAutoUpdate(false);
|
||||||
|
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
|
||||||
|
ui->graphic->setGraphicLineWidth(1., i);
|
||||||
|
ui->graphic->setAutoUpdate(true);
|
||||||
|
ui->graphic->update();
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return QMainWindow::eventFilter(o, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::timerEvent(QTimerEvent * e) {
|
||||||
|
if (e->timerId() == timer_update) {
|
||||||
|
if (need_update) {
|
||||||
|
need_update = false;
|
||||||
|
ui->graphic->updateGraphics();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (e->timerId() == timer) {
|
||||||
|
static QString sPI = QString::number(atan(1) * 4., 'f', 14).leftJustified(14);
|
||||||
|
static int cnt = 0;
|
||||||
|
int si = qMax<int>(cnt - 6, 0);
|
||||||
|
++cnt;
|
||||||
|
cnt %= 23;
|
||||||
|
ui->labelWait->setText(QString(si, QChar(' ')) + sPI.mid(cnt - 6, 6).trimmed());
|
||||||
|
if (!coeffs.isReady()) return;
|
||||||
|
//ui->table->setK(coeffsK.k()->data(), coeffsK.count());
|
||||||
|
//ui->table->showK();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::setControlsEnable(bool enable) {
|
||||||
|
foreach (XCheck * i, checks)
|
||||||
|
i->setEnabled(enable);
|
||||||
|
ui->buttonShowAll->setEnabled(enable);
|
||||||
|
ui->buttonHideAll->setEnabled(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::setX(const KX_X_Data & data) {
|
||||||
|
if (!show_x) return;
|
||||||
|
//ui->graphic->lock();
|
||||||
|
for (int i = 0; i < KX_X_PACKET_NUM; ++i) {
|
||||||
|
if (!isNormalDouble(data.x_data[i])) continue;
|
||||||
|
ui->graphic->addPoint(data.x_data[i], i, false);
|
||||||
|
values[i]->setText(QString("(%1): %2").arg(data.x_num[i]).arg(data.x_data[i]));
|
||||||
|
}
|
||||||
|
//ui->graphic->unlock();
|
||||||
|
if (!isPause) {
|
||||||
|
need_update = true;
|
||||||
|
}
|
||||||
|
if (!needWrite) return;
|
||||||
|
stream << QString::number(tm.elapsed() / 1000., 'f', 3) << " " << QTime::currentTime().toString("hh:mm:ss") << " " << wcnt++;
|
||||||
|
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
|
||||||
|
stream << " " << QString::number(data.x_data[i], 'f', 4);
|
||||||
|
stream << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::addToList(const QString & s, const QColor & c) {
|
||||||
|
ui->list->addItem(QDateTime::currentDateTime().toString("dd/MM/yyyy hh:ss - ") + s);
|
||||||
|
ui->list->item(ui->list->count() - 1)->setTextColor(c);
|
||||||
|
ui->list->scrollToBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_buttonRecord_clicked() {
|
||||||
|
static bool isRec = false;
|
||||||
|
int cinc = 0;
|
||||||
|
QString str;
|
||||||
|
isRec = !isRec;
|
||||||
|
setControlsEnable(!isRec);
|
||||||
|
if (isRec) {
|
||||||
|
tm.restart();
|
||||||
|
file.close();
|
||||||
|
file.setFileName(outdir + getNewFileName(cinc));
|
||||||
|
while (file.exists())
|
||||||
|
file.setFileName(outdir + getNewFileName(cinc++));
|
||||||
|
file.open(QIODevice::ReadWrite);
|
||||||
|
stream.setDevice(&file);
|
||||||
|
stream << "T V C";
|
||||||
|
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
|
||||||
|
stream << " X" + QString::number(checks[i]->spin.value());
|
||||||
|
stream << "\n";
|
||||||
|
wcnt = 0;
|
||||||
|
needWrite = true;
|
||||||
|
ui->buttonRecord->setText(trUtf8("Finish record"));
|
||||||
|
ui->buttonRecord->setIcon(icon_stop);
|
||||||
|
emit recordStarted(QFileInfo(file).completeBaseName());
|
||||||
|
} else {
|
||||||
|
needWrite = false;
|
||||||
|
stream.setDevice(0);
|
||||||
|
file.close();
|
||||||
|
ui->buttonRecord->setText(trUtf8("Start record"));
|
||||||
|
ui->buttonRecord->setIcon(icon_record);
|
||||||
|
emit recordStopped(QFileInfo(file).completeBaseName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_actionClear_triggered() {
|
||||||
|
switch (clear_target) {
|
||||||
|
case 0:
|
||||||
|
ui->list->clear();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
clearSelected();
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::clearSelected() {
|
||||||
|
QList<QTreeWidgetItem * > si = ui->treeK->selectedItems();
|
||||||
|
ui->treeK->setUpdatesEnabled(false);
|
||||||
|
ui->treeK->blockSignals(true);
|
||||||
|
foreach (QTreeWidgetItem * i, si) {
|
||||||
|
int ki = i->text(0).toInt();
|
||||||
|
i->setText(2, "");
|
||||||
|
coeffs.setFormula(ki, "");
|
||||||
|
}
|
||||||
|
ui->treeK->blockSignals(false);
|
||||||
|
ui->treeK->setUpdatesEnabled(true);
|
||||||
|
if (ui->checkKAutoCalculate->isChecked()) {
|
||||||
|
QApplication::processEvents();
|
||||||
|
calculate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString KX_Pult::typeName(const QString & n) const {
|
||||||
|
if (n.isEmpty()) return "";
|
||||||
|
switch (n[0].toLatin1()) {
|
||||||
|
case 'l': return trUtf8("list"); break;
|
||||||
|
case 'b': return trUtf8("bool"); break;
|
||||||
|
case 'n': return trUtf8("int"); break;
|
||||||
|
case 'f': return trUtf8("double"); break;
|
||||||
|
case 'c': return trUtf8("color"); break;
|
||||||
|
case 'r': return trUtf8("rect"); break;
|
||||||
|
case 'a': return trUtf8("rect"); break;
|
||||||
|
case 'p': return trUtf8("point"); break;
|
||||||
|
case 'v': return trUtf8("vector"); break;
|
||||||
|
case 'i': return trUtf8("IP"); break;
|
||||||
|
case 'e': return trUtf8("enum"); break;
|
||||||
|
case 'F': return trUtf8("file"); break;
|
||||||
|
case 'D': return trUtf8("dir"); break;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::received(bool ok) {
|
||||||
|
if (!ok) return;
|
||||||
|
setX(prot_x->from_x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_treeK_itemClicked(QTreeWidgetItem * item, int column) {
|
||||||
|
Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||||
|
if (column == 2) f |= Qt::ItemIsEditable;
|
||||||
|
item->setFlags(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_treeK_itemChanged(QTreeWidgetItem * item, int column) {
|
||||||
|
if (column != 2) return;
|
||||||
|
int ki = item->text(0).toInt();
|
||||||
|
coeffs.setFormula(ki, piqt(item->text(column)));
|
||||||
|
if (ui->checkKAutoCalculate->isChecked())
|
||||||
|
calculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString KX_Pult::getNewFileName(int inc) {
|
||||||
|
dir.refresh();
|
||||||
|
dir.setNameFilters(QStringList("Experiment_*.txt"));
|
||||||
|
return "Experiment_" + QDateTime::currentDateTime().toString("dd_MM_yy__hh_mm_ss") + "__" +
|
||||||
|
QString::number(dir.entryList().count() + inc) + ".txt";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_buttonSendK_clicked() {
|
||||||
|
on_buttonWrite_clicked();
|
||||||
|
coeffs.sendCoeffs();
|
||||||
|
if (timer != 0) killTimer(timer);
|
||||||
|
timer = startTimer(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_buttonReceiveK_clicked() {
|
||||||
|
coeffs.receiveCoeffs();
|
||||||
|
if (timer != 0) killTimer(timer);
|
||||||
|
timer = startTimer(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_buttonShowAll_clicked() {
|
||||||
|
for (int i = 0; i < KX_X_PACKET_NUM; ++i) {
|
||||||
|
checks[i]->check.setChecked(true);
|
||||||
|
//ui->graphic->setGraphicVisible(true, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_buttonHideAll_clicked() {
|
||||||
|
for (int i = 0; i < KX_X_PACKET_NUM; ++i) {
|
||||||
|
checks[i]->check.setChecked(false);
|
||||||
|
//ui->graphic->setGraphicVisible(false, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_buttonRead_clicked() {
|
||||||
|
coeffs.readCoeffs();
|
||||||
|
addToList(trUtf8("Read K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta);
|
||||||
|
updateTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_buttonWrite_clicked() {
|
||||||
|
coeffs.writeCoeffs();
|
||||||
|
addToList(trUtf8("Write K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_buttonResize_clicked() {
|
||||||
|
K.resize(ui->spinSize->value());
|
||||||
|
coeffs.formulas.resize(ui->spinSize->value());
|
||||||
|
ui->spinSize->setStyleSheet("");
|
||||||
|
updateTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_buttonSetKDesc_clicked() {
|
||||||
|
QString ret = QFileDialog::getOpenFileName(this, trUtf8("Select *.h file with K description"), kdesc_file, "C/C++ header files(*.h *.hpp);;All files(*)");
|
||||||
|
if (ret.isEmpty()) return;
|
||||||
|
kdesc_file = QDir::current().relativeFilePath(ret);
|
||||||
|
updateKDesc(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_buttonSetCDesc_clicked() {
|
||||||
|
QString ret = QFileDialog::getOpenFileName(this, trUtf8("Select *.h file with C description"), cdesc_file, "C/C++ header files(*.h *.hpp);;All files(*)");
|
||||||
|
if (ret.isEmpty()) return;
|
||||||
|
cdesc_file = QDir::current().relativeFilePath(ret);
|
||||||
|
updateCDesc();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_spinSize_valueChanged(int) {
|
||||||
|
ui->spinSize->setStyleSheet("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::k_sendFailed() {
|
||||||
|
stopWait();
|
||||||
|
addToList(trUtf8("K not sended"), Qt::darkRed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::k_sendSucceed() {
|
||||||
|
stopWait();
|
||||||
|
addToList(trUtf8("K sended"), Qt::darkGreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::k_receiveFailed() {
|
||||||
|
stopWait();
|
||||||
|
addToList(trUtf8("K not received"), Qt::darkRed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::k_receiveSucceed() {
|
||||||
|
stopWait();
|
||||||
|
addToList(trUtf8("K received"), Qt::darkGreen);
|
||||||
|
addToList(trUtf8("Write K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta);
|
||||||
|
ui->spinSize->setValue(K.size_s());
|
||||||
|
updateTree();
|
||||||
|
//ui->table->setK(coeffsK.k()->data(), coeffsK.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::on_spinBuffer_editingFinished() {
|
||||||
|
ui->graphic->setHistorySize(ui->spinBuffer->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::stopWait() {
|
||||||
|
killTimer(timer);
|
||||||
|
timer = 0;
|
||||||
|
ui->labelWait->setText(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::updateGraph() {
|
||||||
|
ui->graphic->updateGraphics();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::updateDiag() {
|
||||||
|
ui->labelKReceiver->setText(piqt(coeffs.k_protocol->receiverDeviceName() + " - " + coeffs.k_protocol->receiverDeviceState()));
|
||||||
|
ui->labelKSender->setText(piqt(coeffs.k_protocol->senderDeviceName()));
|
||||||
|
ui->spinKSended->setValue(coeffs.k_protocol->sendCount());
|
||||||
|
ui->spinKReceived->setValue(coeffs.k_protocol->receiveCount());
|
||||||
|
ui->spinKWrong->setValue(coeffs.k_protocol->wrongCount());
|
||||||
|
ui->spinKMissed->setValue(coeffs.k_protocol->missedCount());
|
||||||
|
ui->labelKType->setText("0x" + QString::number(coeffs.k_protocol->from_k.type, 16).toUpper().rightJustified(2, '0'));
|
||||||
|
ui->labelKAddrPult->setText("0x" + QString::number(coeffs.k_protocol->from_k.addr_to, 16).toUpper().rightJustified(2, '0'));
|
||||||
|
ui->labelKAddr->setText("0x" + QString::number(coeffs.k_protocol->to_k.addr_to, 16).toUpper().rightJustified(2, '0'));
|
||||||
|
|
||||||
|
ui->labelXReceiver->setText(piqt(prot_x->receiverDeviceName() + " - " + prot_x->receiverDeviceState()));
|
||||||
|
ui->labelXSender->setText(piqt(prot_x->senderDeviceName()));
|
||||||
|
ui->spinXSended->setValue(prot_x->sendCount());
|
||||||
|
ui->spinXReceived->setValue(prot_x->receiveCount());
|
||||||
|
ui->spinXWrong->setValue(prot_x->wrongCount());
|
||||||
|
ui->spinXMissed->setValue(prot_x->missedCount());
|
||||||
|
ui->labelXType->setText("0x" + QString::number(prot_x->from_x.type, 16).toUpper().rightJustified(2, '0'));
|
||||||
|
ui->labelXAddrPult->setText("0x" + QString::number(prot_x->from_x.addr_to, 16).toUpper().rightJustified(2, '0'));
|
||||||
|
ui->labelXAddr->setText("0x" + QString::number(prot_x->to_x.addr_to, 16).toUpper().rightJustified(2, '0'));
|
||||||
|
|
||||||
|
ui->labelCReceiver->setText(piqt(prot_c->receiverDeviceName() + " - " + prot_c->receiverDeviceState()));
|
||||||
|
ui->labelCSender->setText(piqt(prot_c->senderDeviceName()));
|
||||||
|
ui->spinCSended->setValue(prot_c->sendCount());
|
||||||
|
ui->spinCReceived->setValue(prot_c->receiveCount());
|
||||||
|
ui->spinCWrong->setValue(prot_c->wrongCount());
|
||||||
|
ui->spinCMissed->setValue(prot_c->missedCount());
|
||||||
|
ui->labelCType->setText("0x" + QString::number(prot_c->from_c.type, 16).toUpper().rightJustified(2, '0'));
|
||||||
|
ui->labelCAddrPult->setText("0x" + QString::number(prot_c->from_c.addr_to, 16).toUpper().rightJustified(2, '0'));
|
||||||
|
ui->labelCAddr->setText("0x" + QString::number(prot_c->to_c.addr_to, 16).toUpper().rightJustified(2, '0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int KX_Pult::parseHeader(const QString & file, QMap<int, KX_Pult::KDesc> & map) {
|
||||||
|
map.clear();
|
||||||
|
QFile f(file);
|
||||||
|
if (!f.open(QIODevice::ReadOnly)) {
|
||||||
|
updateTree();
|
||||||
|
addToList(trUtf8("Update descriptions from \"%1\": error").arg(file), Qt::darkRed);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
addToList(trUtf8("Update descriptions from \"%1\"").arg(file), Qt::darkMagenta);
|
||||||
|
QTextStream s(&f);
|
||||||
|
int cind = -1;
|
||||||
|
bool found = false;
|
||||||
|
//qDebug() << "\nparse" << file;
|
||||||
|
while (!s.atEnd()) {
|
||||||
|
QString line = s.readLine().trimmed(), num, name, type, comment;
|
||||||
|
int i = line.indexOf("//");
|
||||||
|
if (i >= 0) {
|
||||||
|
comment = line.right(line.length() - i - 2);
|
||||||
|
type = comment.left(1);
|
||||||
|
comment = comment.right(comment.length() - 1).trimmed();
|
||||||
|
line = line.left(i).trimmed();
|
||||||
|
}
|
||||||
|
if (line.isEmpty()) continue;
|
||||||
|
if (line.contains("enum")) {
|
||||||
|
found = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!found) continue;
|
||||||
|
if (line.contains('}'))
|
||||||
|
break;
|
||||||
|
line.remove(',').remove(' ').remove('\t');
|
||||||
|
i = line.indexOf("=");
|
||||||
|
if (i >= 0) {
|
||||||
|
num = line.right(line.length() - i - 1).trimmed();
|
||||||
|
line = line.left(i).trimmed();
|
||||||
|
}
|
||||||
|
name = line;
|
||||||
|
if (num.isEmpty())
|
||||||
|
++cind;
|
||||||
|
else
|
||||||
|
cind = Q2PIString(num).toInt();
|
||||||
|
KDesc kd;
|
||||||
|
kd.index = cind;
|
||||||
|
kd.name = name;
|
||||||
|
kd.type = type;
|
||||||
|
kd.comment = comment;
|
||||||
|
map[kd.index] = kd;
|
||||||
|
//qDebug() << name << cind << type << comment;
|
||||||
|
}
|
||||||
|
cind++;
|
||||||
|
return cind;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::updateKDesc(bool ask_move) {
|
||||||
|
int cind = parseHeader(kdesc_file, kdesc);
|
||||||
|
if (K.size_s() < cind) {
|
||||||
|
ui->spinSize->setValue(cind);
|
||||||
|
ui->spinSize->setStyleSheet("background-color: rgb(220, 220, 255);");
|
||||||
|
}
|
||||||
|
bool move = false;
|
||||||
|
if (ask_move)
|
||||||
|
move = (QMessageBox::question(this, "KX Pult", "Save values at associated names?", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes);
|
||||||
|
updateTree(move);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::updateCDesc() {
|
||||||
|
parseHeader(cdesc_file, cdesc);
|
||||||
|
updateCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool stringComp(const QString & s1, const QString & s2) {
|
||||||
|
if (s1.size() != s2.size())
|
||||||
|
return s1.size() > s2.size();
|
||||||
|
return s1 > s2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::updateTree(bool move) {
|
||||||
|
int sp = ui->treeK->verticalScrollBar()->value();
|
||||||
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
|
//qDebug() << "fill tree ...";
|
||||||
|
QMap<QString, QString> prev_val;
|
||||||
|
if (move) {
|
||||||
|
for (int i = 0; i < ui->treeK->topLevelItemCount(); ++i) {
|
||||||
|
QTreeWidgetItem * ti = ui->treeK->topLevelItem(i);
|
||||||
|
if (!ti->text(1).isEmpty())
|
||||||
|
prev_val[ti->text(1)] = ti->text(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui->treeK->clear();
|
||||||
|
ui->treeK->setUpdatesEnabled(false);
|
||||||
|
eval.clearCustomVariables();
|
||||||
|
for (int i = 0; i < K.size_s(); ++i) {
|
||||||
|
QTreeWidgetItem * ti = new QTreeWidgetItem();
|
||||||
|
KDesc kd = kdesc[i];
|
||||||
|
QString kn = QString("k%1").arg(i);
|
||||||
|
knames[kn] = i;
|
||||||
|
knames_sort << kn;
|
||||||
|
if (eval.content.findVariable(kn) < 0)
|
||||||
|
eval.content.addVariable(kn, 0., false);
|
||||||
|
if (!kd.name.isEmpty()) {
|
||||||
|
knames[kd.name] = i;
|
||||||
|
knames_sort << kd.name;
|
||||||
|
eval.content.addVariable(kd.name, 0., false);
|
||||||
|
}
|
||||||
|
if (move && !kd.name.isEmpty()) {
|
||||||
|
if (prev_val.contains(kd.name))
|
||||||
|
coeffs.setFormula(i, Q2PIString(prev_val[kd.name]));
|
||||||
|
}
|
||||||
|
ti->setText(0, QString::number(i));
|
||||||
|
ti->setText(1, kd.name);
|
||||||
|
ti->setText(2, PI2QString(coeffs.formula(i)));
|
||||||
|
ti->setText(3, QString::number(K[i]));
|
||||||
|
ti->setText(4, typeName(kd.type));
|
||||||
|
ti->setText(5, kd.comment);
|
||||||
|
ui->treeK->addTopLevelItem(ti);
|
||||||
|
}
|
||||||
|
eval.content.sortVariables();
|
||||||
|
//qDebug() << "fill tree ok";
|
||||||
|
//qDebug() << "sort ...";
|
||||||
|
qSort(knames_sort.begin(), knames_sort.end(), stringComp);
|
||||||
|
//qDebug() << "names" << knames_sort;
|
||||||
|
//qDebug() << "sort ok";
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
ui->treeK->setUpdatesEnabled(true);
|
||||||
|
ui->treeK->verticalScrollBar()->setValue(sp);
|
||||||
|
calculate();
|
||||||
|
filterTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::updateCommands() {
|
||||||
|
while (ui->layoutCommands->count() > 0)
|
||||||
|
delete ui->layoutCommands->itemAt(0)->widget();
|
||||||
|
QMapIterator<int, KDesc> it(cdesc);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
KDesc kd = it.value();
|
||||||
|
QPushButton * b = new QPushButton();
|
||||||
|
QString text = kd.name;
|
||||||
|
if (!kd.comment.isEmpty())
|
||||||
|
text += QString("\n(%1)").arg(kd.comment);
|
||||||
|
b->setText(text);
|
||||||
|
b->setProperty("_command", kd.index);
|
||||||
|
connect(b, SIGNAL(clicked()), this, SLOT(commandClicked()));
|
||||||
|
ui->layoutCommands->addWidget(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::filterTree() {
|
||||||
|
bool he = ui->checkKHideEmpty->isChecked();
|
||||||
|
bool hn = ui->checkKHideNormal->isChecked();
|
||||||
|
bool hs = ui->checkKHideExpressions->isChecked();
|
||||||
|
bool ok = false;
|
||||||
|
QString fl = ui->lineKSearch->text();
|
||||||
|
int lc = ui->treeK->topLevelItemCount();
|
||||||
|
for (int i = 0; i < lc; ++i) {
|
||||||
|
QTreeWidgetItem * ti = ui->treeK->topLevelItem(i);
|
||||||
|
if (ti->text(1).isEmpty() && he)
|
||||||
|
ti->setHidden(true);
|
||||||
|
else
|
||||||
|
if (fl.isEmpty())
|
||||||
|
ti->setHidden(false);
|
||||||
|
else
|
||||||
|
ti->setHidden(!ti->text(0).contains(fl, Qt::CaseInsensitive) &&
|
||||||
|
!ti->text(1).contains(fl, Qt::CaseInsensitive) &&
|
||||||
|
!ti->text(2).contains(fl, Qt::CaseInsensitive) &&
|
||||||
|
!ti->text(3).contains(fl, Qt::CaseInsensitive) &&
|
||||||
|
!ti->text(4).contains(fl, Qt::CaseInsensitive));
|
||||||
|
if (hn)
|
||||||
|
if (ti->data(0, Qt::UserRole).toBool())
|
||||||
|
ti->setHidden(true);
|
||||||
|
if (hs) {
|
||||||
|
ti->data(2, Qt::DisplayRole).toDouble(&ok);
|
||||||
|
if (!ok)
|
||||||
|
ti->setHidden(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::calculate() {
|
||||||
|
calculated.clear();
|
||||||
|
ui->treeK->setUpdatesEnabled(false);
|
||||||
|
ui->treeK->blockSignals(true);
|
||||||
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
|
progress(0, 100);
|
||||||
|
ui->buttonCalculate->setEnabled(false);
|
||||||
|
QApplication::processEvents();
|
||||||
|
for (int i = 0; i < K.size_s(); ++i) {
|
||||||
|
ui->treeK->topLevelItem(i)->setToolTip(2, QString());
|
||||||
|
ui->treeK->topLevelItem(i)->setToolTip(3, QString());
|
||||||
|
}
|
||||||
|
for (int i = 0; i < K.size_s(); ++i) {
|
||||||
|
progress(i, K.size_s());
|
||||||
|
calculateExpression(i, QVector<int>());
|
||||||
|
}
|
||||||
|
ui->buttonCalculate->setEnabled(true);
|
||||||
|
ui->progress->setValue(100);
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
ui->treeK->blockSignals(false);
|
||||||
|
ui->treeK->setUpdatesEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool KX_Pult::calculateExpression(int i, QVector<int> trace) {
|
||||||
|
if (calculated.contains(i)) return true;
|
||||||
|
trace << i;
|
||||||
|
QTreeWidgetItem * ti = ui->treeK->topLevelItem(i);
|
||||||
|
QString expr = ti->text(2);
|
||||||
|
if (expr.isEmpty() || expr == "0" || expr == "0,00000000" || expr == "0.00000000") {
|
||||||
|
markNormal(ti);
|
||||||
|
calculated << i;
|
||||||
|
K[i] = 0.;
|
||||||
|
ti->setText(3, "0");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//ti->setToolTip(2, QString());
|
||||||
|
if (!eval.check(expr)) {
|
||||||
|
markError(ti, eval.error());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foreach (const QString & n, knames_sort) {
|
||||||
|
if (expr.contains(n)) {
|
||||||
|
int ki = knames.value(n, -1);
|
||||||
|
if (trace.contains(ki)) {
|
||||||
|
QString strace;
|
||||||
|
trace << ki;
|
||||||
|
for (int j = 0; j < trace.size(); ++j) {
|
||||||
|
//calculated << trace[j];
|
||||||
|
if (j > 0) strace += " -> ";
|
||||||
|
strace += "k" + QString::number(trace[j]);
|
||||||
|
}
|
||||||
|
for (int j = 0; j < trace.size(); ++j) {
|
||||||
|
QTreeWidgetItem * pti = ui->treeK->topLevelItem(trace[j]);
|
||||||
|
markError(pti, QString("Circular dependency: %1!").arg(strace));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ki < 0) {
|
||||||
|
markError(ti);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (calculated.contains(ki)) {
|
||||||
|
eval.setVariable(n, K[ki]);
|
||||||
|
} else {
|
||||||
|
if (calculateExpression(ki, trace))
|
||||||
|
eval.setVariable(n, K[ki]);
|
||||||
|
else {
|
||||||
|
markError(ti);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
markNormal(ti);
|
||||||
|
calculated << i;
|
||||||
|
complexd ret = eval.evaluate();
|
||||||
|
K[i] = ret.real();
|
||||||
|
ti->setText(3, QString::number(K[i]));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::markError(QTreeWidgetItem * item, const QString & tool_tip) {
|
||||||
|
int cc = item->columnCount();
|
||||||
|
for (int i = 0; i < cc; ++i)
|
||||||
|
item->setBackgroundColor(i, QColor(255, 200, 200));
|
||||||
|
if (item->toolTip(2).isEmpty())
|
||||||
|
item->setToolTip(2, tool_tip);
|
||||||
|
if (item->toolTip(3).isEmpty())
|
||||||
|
item->setToolTip(3, tool_tip);
|
||||||
|
item->setData(0, Qt::UserRole, false);
|
||||||
|
item->setText(3, "Error");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::markNormal(QTreeWidgetItem * item) {
|
||||||
|
int cc = item->columnCount();
|
||||||
|
for (int i = 0; i < cc; ++i)
|
||||||
|
item->setBackground(i, Qt::NoBrush);
|
||||||
|
item->setToolTip(2, QString());
|
||||||
|
item->setToolTip(3, QString());
|
||||||
|
item->setData(0, Qt::UserRole, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::progress(int val, int max) {
|
||||||
|
if (ctm.elapsed() < 50) return;
|
||||||
|
ctm.restart();
|
||||||
|
ui->progress->setValue(qRound(val * 100. / max));
|
||||||
|
QApplication::processEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::renew(bool write) {
|
||||||
|
addToList(trUtf8("Update settings from \"%1\"").arg(PI2QString(config_)), Qt::darkMagenta);
|
||||||
|
dir.setPath(config.getValue("x.output_dir", "./Experiments/").stringValue());
|
||||||
|
setWindowTitle(config.getValue("title", "Noname").stringValue() + trUtf8(" - KX Pult"));
|
||||||
|
//if (write) ui->configWidget->write();
|
||||||
|
if (prot_x != 0) {
|
||||||
|
prot_x->stop();
|
||||||
|
delete prot_x;
|
||||||
|
}
|
||||||
|
if (prot_c != 0) {
|
||||||
|
prot_c->stop();
|
||||||
|
delete prot_c;
|
||||||
|
}
|
||||||
|
prot_x = new __KX_Protocol_X(config_, name_x);
|
||||||
|
prot_c = new __KX_Protocol_C(config_, name_c);
|
||||||
|
ui->graphic->setAutoXIncrement(prot_x->expectedFrequency() > 0. ? 1. / prot_x->expectedFrequency() : 1.);
|
||||||
|
coeffs.renew();
|
||||||
|
CONNECT1(void, bool, prot_x, received, this, received);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::toggledX(int index, bool on) {
|
||||||
|
ui->graphic->setGraphicVisible(on, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::changedX(int index, int num) {
|
||||||
|
prot_x->to_x.x_num[index] = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void KX_Pult::commandClicked() {
|
||||||
|
QPushButton * b = qobject_cast<QPushButton*>(sender());
|
||||||
|
if (!b) return;
|
||||||
|
prot_c->sendCommand(b->property("_command").toInt());
|
||||||
|
}
|
||||||
170
kx_utils/kx_pult.h
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
#ifndef KX_PULT_H
|
||||||
|
#define KX_PULT_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QFont>
|
||||||
|
#include <QRect>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QVector>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QBoxLayout>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QTime>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QMetaObject>
|
||||||
|
#include <QTreeWidgetItem>
|
||||||
|
#include <QLabel>
|
||||||
|
#include "kx_coeffs.h"
|
||||||
|
#include "kx_protocol_x.h"
|
||||||
|
#include "kx_protocol_c.h"
|
||||||
|
#include "piqt.h"
|
||||||
|
#include "session_manager.h"
|
||||||
|
#include "qpievaluator.h"
|
||||||
|
|
||||||
|
|
||||||
|
class XCheck: public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit XCheck(int index);
|
||||||
|
QCheckBox check;
|
||||||
|
QSpinBox spin;
|
||||||
|
private:
|
||||||
|
bool eventFilter(QObject * o, QEvent * e);
|
||||||
|
int index_;
|
||||||
|
private slots:
|
||||||
|
void spinChanged(int value) {check.setChecked(true); emit valueChanged(index_, value);}
|
||||||
|
void checkChanged_(bool value) {emit checkChanged(index_, value);}
|
||||||
|
signals:
|
||||||
|
void valueChanged(int index, int value);
|
||||||
|
void checkChanged(int index, bool on);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class KX_Pult;
|
||||||
|
};
|
||||||
|
|
||||||
|
class KX_Pult: public QMainWindow, public PIObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
PIOBJECT(KX_Pult)
|
||||||
|
public:
|
||||||
|
KX_Pult();
|
||||||
|
~KX_Pult();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct KDesc {
|
||||||
|
KDesc() {index = -1;}
|
||||||
|
int index;
|
||||||
|
QString name;
|
||||||
|
QString type;
|
||||||
|
QString comment;
|
||||||
|
QString value;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool eventFilter(QObject * o, QEvent * e);
|
||||||
|
void timerEvent(QTimerEvent * );
|
||||||
|
void setControlsEnable(bool enable);
|
||||||
|
void setX(const KX_X_Data & data);
|
||||||
|
void addToList(const QString & s, const QColor & c);
|
||||||
|
QString getNewFileName(int inc);
|
||||||
|
QColor invertColor(QColor col) {return QColor(255 - col.red(), 255 - col.green(), 255 - col.blue());}
|
||||||
|
void stopWait();
|
||||||
|
bool calculateExpression(int i, QVector<int> trace);
|
||||||
|
void markError(QTreeWidgetItem * item, const QString & tool_tip = QString());
|
||||||
|
void markNormal(QTreeWidgetItem * item);
|
||||||
|
void progress(int val, int max);
|
||||||
|
void clearSelected();
|
||||||
|
QString typeName(const QString & n) const;
|
||||||
|
int parseHeader(const QString & file, QMap<int, KDesc> & map);
|
||||||
|
|
||||||
|
EVENT_HANDLER1(void, received, bool, ok);
|
||||||
|
EVENT_HANDLER(void, pip_sendFailed) {emit q_k_sendFailed();}
|
||||||
|
EVENT_HANDLER(void, pip_sendSucceed) {emit q_k_sendSucceed();}
|
||||||
|
EVENT_HANDLER(void, pip_receiveFailed) {emit q_k_receiveFailed();}
|
||||||
|
EVENT_HANDLER(void, pip_receiveSucceed) {emit q_k_receiveSucceed();}
|
||||||
|
|
||||||
|
QVector<XCheck * > checks;
|
||||||
|
QVector<QLabel * > values;
|
||||||
|
|
||||||
|
Ui::KX_Pult * ui;
|
||||||
|
PIString config_, name_x, name_c;
|
||||||
|
QDir dir;
|
||||||
|
QString outdir, kdesc_file, cdesc_file;
|
||||||
|
QFile file;
|
||||||
|
QTime tm, ctm;
|
||||||
|
QIcon icon_record, icon_stop;
|
||||||
|
QTextStream stream;
|
||||||
|
QTimer timer_diag;
|
||||||
|
QMap<int, KDesc> kdesc, cdesc;
|
||||||
|
QMap<QString, int> knames;
|
||||||
|
QSet<int> calculated;
|
||||||
|
QStringList knames_sort;
|
||||||
|
QPIEvaluator eval;
|
||||||
|
SessionManager session;
|
||||||
|
QPIConfig config;
|
||||||
|
QMenu log_menu;
|
||||||
|
//QVector<float> k, x;
|
||||||
|
KX_Coefficients coeffs;
|
||||||
|
__KX_Protocol_X * prot_x;
|
||||||
|
__KX_Protocol_C * prot_c;
|
||||||
|
int csize, wcnt, timer, timer_update, clear_target;
|
||||||
|
bool needWrite, isPause, need_update, show_x;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void loading(QPIConfig & conf);
|
||||||
|
void saving(QPIConfig & conf);
|
||||||
|
void updateGraph();
|
||||||
|
void updateDiag();
|
||||||
|
void updateKDesc(bool ask_move = false);
|
||||||
|
void updateCDesc();
|
||||||
|
void updateTree(bool move = false);
|
||||||
|
void updateCommands();
|
||||||
|
void filterTree();
|
||||||
|
void calculate();
|
||||||
|
void renew(bool write = true);
|
||||||
|
void toggledX(int index, bool on);
|
||||||
|
void changedX(int index, int num);
|
||||||
|
void commandClicked();
|
||||||
|
void k_sendFailed();
|
||||||
|
void k_sendSucceed();
|
||||||
|
void k_receiveFailed();
|
||||||
|
void k_receiveSucceed();
|
||||||
|
void on_spinBuffer_editingFinished();
|
||||||
|
void on_buttonSendK_clicked();
|
||||||
|
void on_buttonReceiveK_clicked();
|
||||||
|
void on_buttonShowAll_clicked();
|
||||||
|
void on_buttonHideAll_clicked();
|
||||||
|
void on_buttonRead_clicked();
|
||||||
|
void on_buttonWrite_clicked();
|
||||||
|
void on_buttonResize_clicked();
|
||||||
|
void on_buttonSetKDesc_clicked();
|
||||||
|
void on_buttonReparseKDesc_clicked() {updateKDesc(true);}
|
||||||
|
void on_buttonSetCDesc_clicked();
|
||||||
|
void on_buttonReparseCDesc_clicked() {updateCDesc();}
|
||||||
|
void on_buttonCalculate_clicked() {calculate();}
|
||||||
|
void on_buttonApply_clicked() {renew();}
|
||||||
|
void on_spinSize_valueChanged(int);
|
||||||
|
void on_buttonPause_toggled(bool on) {isPause = on;}
|
||||||
|
void on_buttonRecord_clicked();
|
||||||
|
void on_treeK_itemClicked(QTreeWidgetItem * item, int column);
|
||||||
|
void on_treeK_itemChanged(QTreeWidgetItem * item, int column);
|
||||||
|
void on_actionClear_triggered();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void q_k_sendFailed();
|
||||||
|
void q_k_sendSucceed();
|
||||||
|
void q_k_receiveFailed();
|
||||||
|
void q_k_receiveSucceed();
|
||||||
|
void recordStarted(const QString & fileName);
|
||||||
|
void recordStopped(const QString & fileName);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KX_PULT_H
|
||||||
|
|
||||||
40
kx_utils/kx_pult.qrc
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>icons/dialog-close.png</file>
|
||||||
|
<file>icons/edit-clear-.png</file>
|
||||||
|
<file>icons/edit-guides.png</file>
|
||||||
|
<file>icons/view-grid.png</file>
|
||||||
|
<file>icons/zoom-fit-best.png</file>
|
||||||
|
<file>icons/configure.png</file>
|
||||||
|
<file>icons/alpha.png</file>
|
||||||
|
<file>icons/document-save.png</file>
|
||||||
|
<file>icons/edit-clear-locationbar-rtl.png</file>
|
||||||
|
<file>icons/edit-find.png</file>
|
||||||
|
<file>icons/list-add.png</file>
|
||||||
|
<file>icons/edit-delete.png</file>
|
||||||
|
<file>icons/item-add.png</file>
|
||||||
|
<file>icons/item.png</file>
|
||||||
|
<file>icons/node-add.png</file>
|
||||||
|
<file>icons/node.png</file>
|
||||||
|
<file>icons/edit-copy.png</file>
|
||||||
|
<file>icons/edit-paste.png</file>
|
||||||
|
<file>icons/expand_s_x.png</file>
|
||||||
|
<file>icons/expand_s_y.png</file>
|
||||||
|
<file>icons/expand_x.png</file>
|
||||||
|
<file>icons/expand_y.png</file>
|
||||||
|
<file>icons/media-playback-pause.png</file>
|
||||||
|
<file>icons/media-playback-stop.png</file>
|
||||||
|
<file>icons/media-record.png</file>
|
||||||
|
<file>icons/application-exit.png</file>
|
||||||
|
<file>icons/document-save-.png</file>
|
||||||
|
<file>icons/view-refresh.png</file>
|
||||||
|
<file>icons/document-open.png</file>
|
||||||
|
<file>icons/archive-extract.png</file>
|
||||||
|
<file>icons/document-export.png</file>
|
||||||
|
<file>icons/document-import.png</file>
|
||||||
|
<file>icons/zoom-fit-height.png</file>
|
||||||
|
<file>icons/layer-visible-off.png</file>
|
||||||
|
<file>icons/layer-visible-on.png</file>
|
||||||
|
<file>icons/accessories-calculator.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
1311
kx_utils/kx_pult.ui
Normal file
@@ -0,0 +1,1311 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>KX_Pult</class>
|
||||||
|
<widget class="QMainWindow" name="KX_Pult">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1759</width>
|
||||||
|
<height>852</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>KX Pult</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="page_2">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="tab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Coefficients (K)</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QPushButton" name="buttonReparseKDesc">
|
||||||
|
<property name="text">
|
||||||
|
<string>Reparse K desc</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/view-refresh.png</normaloff>:/icons/view-refresh.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QPushButton" name="buttonResize">
|
||||||
|
<property name="text">
|
||||||
|
<string>Resize</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/zoom-fit-height.png</normaloff>:/icons/zoom-fit-height.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QPushButton" name="buttonRead">
|
||||||
|
<property name="text">
|
||||||
|
<string>Read file K</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/archive-extract.png</normaloff>:/icons/archive-extract.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QPushButton" name="buttonSendK">
|
||||||
|
<property name="text">
|
||||||
|
<string>Send</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/document-export.png</normaloff>:/icons/document-export.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QPushButton" name="buttonWrite">
|
||||||
|
<property name="text">
|
||||||
|
<string>Write file K</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/document-save-.png</normaloff>:/icons/document-save-.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2" rowspan="5">
|
||||||
|
<widget class="QListWidget" name="list">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::CustomContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::NoSelection</enum>
|
||||||
|
</property>
|
||||||
|
<property name="verticalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="horizontalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QPushButton" name="buttonReceiveK">
|
||||||
|
<property name="text">
|
||||||
|
<string>Receive</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/document-import.png</normaloff>:/icons/document-import.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QPushButton" name="buttonSetKDesc">
|
||||||
|
<property name="text">
|
||||||
|
<string>Set K desc file ...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/document-open.png</normaloff>:/icons/document-open.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinSize">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>65536</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="2">
|
||||||
|
<widget class="QLabel" name="labelWait">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkKHideEmpty">
|
||||||
|
<property name="text">
|
||||||
|
<string>Hide empty</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_5">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Preferred</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkKHideExpressions">
|
||||||
|
<property name="text">
|
||||||
|
<string>Hide expressions</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_9">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Preferred</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkKHideNormal">
|
||||||
|
<property name="text">
|
||||||
|
<string>Hide without errors</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_8">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Preferred</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_17">
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="kx_pult.qrc">:/icons/edit-find.png</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_16">
|
||||||
|
<property name="text">
|
||||||
|
<string> Search:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="CLineEdit" name="lineKSearch">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_7">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Preferred</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkKAutoCalculate">
|
||||||
|
<property name="text">
|
||||||
|
<string>Auto calculate</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_6">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Preferred</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="buttonCalculate">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Calculate</string>
|
||||||
|
</property>
|
||||||
|
<property name="statusTip">
|
||||||
|
<string>Calculate</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/accessories-calculator.png</normaloff>:/icons/accessories-calculator.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QProgressBar" name="progress">
|
||||||
|
<property name="value">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="format">
|
||||||
|
<string>Calculate %p%</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeWidget" name="treeK">
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::CustomContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||||
|
</property>
|
||||||
|
<property name="verticalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="horizontalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="rootIsDecorated">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="itemsExpandable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="columnCount">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<attribute name="headerDefaultSectionSize">
|
||||||
|
<number>200</number>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="headerMinimumSectionSize">
|
||||||
|
<number>20</number>
|
||||||
|
</attribute>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Index</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Name</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Expression</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Calculated</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Type</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Comment</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_4">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Commands (C)</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonSetCDesc">
|
||||||
|
<property name="text">
|
||||||
|
<string>Set C desc file ...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/document-open.png</normaloff>:/icons/document-open.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonReparseCDesc">
|
||||||
|
<property name="text">
|
||||||
|
<string>Reparse C desc</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/view-refresh.png</normaloff>:/icons/view-refresh.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupCommands">
|
||||||
|
<property name="title">
|
||||||
|
<string>Commands</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="layout_">
|
||||||
|
<item>
|
||||||
|
<widget class="QScrollArea" name="scrollArea">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="widgetResizable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1370</width>
|
||||||
|
<height>655</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="margin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget" native="true">
|
||||||
|
<layout class="QVBoxLayout" name="layoutCommands"/>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Expanding</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>66</width>
|
||||||
|
<height>441</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_2">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Graphics (X)</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widgetChecks" native="true">
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<property name="horizontalSpacing">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonShowAll">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Show all</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/layer-visible-on.png</normaloff>:/icons/layer-visible-on.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonHideAll">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Hide all</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/layer-visible-off.png</normaloff>:/icons/layer-visible-off.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonRecord">
|
||||||
|
<property name="text">
|
||||||
|
<string>Start record</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/media-record.png</normaloff>:/icons/media-record.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonPause">
|
||||||
|
<property name="text">
|
||||||
|
<string>Pause</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/media-playback-pause.png</normaloff>:/icons/media-playback-pause.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDoubleSpinBox" name="spinHistory">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string> с</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>9999.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>10.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Preferred</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDoubleSpinBox" name="spinBuffer">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string> с</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>9999.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>60.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Graphic" name="graphic">
|
||||||
|
<property name="buttons">
|
||||||
|
<set>Graphic::Autofit|Graphic::BorderInputs|Graphic::Clear|Graphic::Configure|Graphic::CursorAxis|Graphic::Grid|Graphic::OnlyExpandX|Graphic::OnlyExpandY|Graphic::Save</set>
|
||||||
|
</property>
|
||||||
|
<property name="borderInputsVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="legendVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="historySize">
|
||||||
|
<double>60.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maxVisibleTime">
|
||||||
|
<double>10.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_3">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Configuration</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>K</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<property name="fieldGrowthPolicy">
|
||||||
|
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||||
|
</property>
|
||||||
|
<property name="labelAlignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="formAlignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>receiver:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLabel" name="labelKReceiver">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>sender:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="labelKSender">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>sended count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinKSended">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>received count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinKReceived">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>wrong received count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinKWrong">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_13">
|
||||||
|
<property name="text">
|
||||||
|
<string>type:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="labelKType">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="labelKType_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>address K:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLabel" name="labelKAddr">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLabel" name="labelKAddrPult">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="label_14">
|
||||||
|
<property name="text">
|
||||||
|
<string>missed received count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinKMissed">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="labelKType_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>address pult:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string>X</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
|
<property name="fieldGrowthPolicy">
|
||||||
|
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||||
|
</property>
|
||||||
|
<property name="labelAlignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="formAlignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>receiver:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLabel" name="labelXReceiver">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="text">
|
||||||
|
<string>sender:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="labelXSender">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="labelKType_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>type:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="labelXType">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="labelKType_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>address X:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="labelKType_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>address pult:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLabel" name="labelXAddrPult">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="text">
|
||||||
|
<string>sended count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinXSended">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="label_12">
|
||||||
|
<property name="text">
|
||||||
|
<string>received count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinXReceived">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>wrong received count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinXWrong">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLabel" name="labelXAddr">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="label_15">
|
||||||
|
<property name="text">
|
||||||
|
<string>missed received count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinXMissed">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_3">
|
||||||
|
<property name="title">
|
||||||
|
<string>C</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout_3">
|
||||||
|
<property name="fieldGrowthPolicy">
|
||||||
|
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||||
|
</property>
|
||||||
|
<property name="labelAlignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="formAlignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_18">
|
||||||
|
<property name="text">
|
||||||
|
<string>receiver:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLabel" name="labelCReceiver">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_19">
|
||||||
|
<property name="text">
|
||||||
|
<string>sender:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="labelCSender">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="labelKType_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>type:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="labelCType">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="labelKType_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>address C:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="labelKType_9">
|
||||||
|
<property name="text">
|
||||||
|
<string>address pult:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLabel" name="labelCAddrPult">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_20">
|
||||||
|
<property name="text">
|
||||||
|
<string>sended count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinCSended">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="label_21">
|
||||||
|
<property name="text">
|
||||||
|
<string>received count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinCReceived">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label_22">
|
||||||
|
<property name="text">
|
||||||
|
<string>wrong received count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinCWrong">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLabel" name="labelCAddr">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="label_23">
|
||||||
|
<property name="text">
|
||||||
|
<string>missed received count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinCMissed">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QPIConfigWidget" name="configWidget">
|
||||||
|
<property name="readOnlyName">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="readOnlyType">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="readOnlyComment">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="columnTypeVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="headerMinimumSectionSize">
|
||||||
|
<number>20</number>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonApply">
|
||||||
|
<property name="text">
|
||||||
|
<string>Apply</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/document-save-.png</normaloff>:/icons/document-save-.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<action name="actionClear">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="kx_pult.qrc">
|
||||||
|
<normaloff>:/icons/edit-clear-.png</normaloff>:/icons/edit-clear-.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>Graphic</class>
|
||||||
|
<extends>QFrame</extends>
|
||||||
|
<header>graphic.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>CLineEdit</class>
|
||||||
|
<extends>QLineEdit</extends>
|
||||||
|
<header>clineedit.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>QPIConfigWidget</class>
|
||||||
|
<extends>QTreeWidget</extends>
|
||||||
|
<header>qpiconfigwidget.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources>
|
||||||
|
<include location="kx_pult.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>spinHistory</sender>
|
||||||
|
<signal>valueChanged(double)</signal>
|
||||||
|
<receiver>graphic</receiver>
|
||||||
|
<slot>setMaxVisibleTime(double)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>919</x>
|
||||||
|
<y>107</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>932</x>
|
||||||
|
<y>132</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
||||||
10
kx_utils/main_kx_pult.cpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include <QtGui/QApplication>
|
||||||
|
#include "kx_pult.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
KX_Pult w;
|
||||||
|
w.show();
|
||||||
|
return a.exec();
|
||||||
|
}
|
||||||
1
kx_utils/make_lib.bat
Normal file
@@ -0,0 +1 @@
|
|||||||
|
cmake -G "MinGW Makefiles" -DLIB=1 && make install . %*
|
||||||
718
kx_utils/piprotocol.cpp
Normal file
@@ -0,0 +1,718 @@
|
|||||||
|
/*
|
||||||
|
PIP - Platform Independent Primitives
|
||||||
|
Protocol, input/output channel (COM, UDP)
|
||||||
|
Copyright (C) 2020 Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "piprotocol.h"
|
||||||
|
|
||||||
|
/** \class PIProtocol
|
||||||
|
* \brief
|
||||||
|
* \details
|
||||||
|
* \section PIProtocol_sec0 Synopsis
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
|
||||||
|
/// DEPRECATED
|
||||||
|
PIProtocol::PIProtocol(const PIString & config, const PIString & name_, void * recHeaderPtr, int recHeaderSize, void * recDataPtr, int recDataSize, void * sendDataPtr_, int sendDataSize_): PIObject() {
|
||||||
|
init();
|
||||||
|
protName = name_;
|
||||||
|
PIObject::setName(name_);
|
||||||
|
PIConfig conf(config, PIIODevice::ReadOnly);
|
||||||
|
if (!conf.isOpened()) {
|
||||||
|
piCoutObj << "Can`t open \"" << config << "\"!";
|
||||||
|
devReceiverState = devSenderState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PIConfig::Entry & b(conf.getValue(name_)),
|
||||||
|
& rb(b.getValue("receiver")),
|
||||||
|
& sb(b.getValue("sender"));
|
||||||
|
|
||||||
|
init_receiver(b, rb, config);
|
||||||
|
init_sender(b, sb, config);
|
||||||
|
|
||||||
|
headerPtr = (uchar * )recHeaderPtr;
|
||||||
|
headerSize = recHeaderSize;
|
||||||
|
dataPtr = (uchar * )recDataPtr;
|
||||||
|
dataSize = recDataSize;
|
||||||
|
sendDataPtr = (uchar * )sendDataPtr_;
|
||||||
|
sendDataSize = sendDataSize_;
|
||||||
|
packet_ext->setHeader(PIByteArray(recHeaderPtr, recHeaderSize));
|
||||||
|
packet_ext->setPayloadSize(recDataSize);
|
||||||
|
packet_ext->setPacketSize(recDataSize);
|
||||||
|
packet_ext->setSplitMode(PIPacketExtractor::Header);
|
||||||
|
bool null_h = (recHeaderPtr == 0 || recHeaderSize == 0), null_d = (recDataPtr == 0 || recDataSize == 0);
|
||||||
|
if (null_h && null_d) packet_ext->setSplitMode(PIPacketExtractor::None);
|
||||||
|
else {
|
||||||
|
if (null_h) packet_ext->setSplitMode(PIPacketExtractor::Size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIProtocol::~PIProtocol() {
|
||||||
|
delete diagTimer;
|
||||||
|
delete sendTimer;
|
||||||
|
delete secTimer;
|
||||||
|
delete packet_ext;
|
||||||
|
if (eth != 0) delete eth;
|
||||||
|
if (ser != 0) delete ser;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::init() {
|
||||||
|
packet_ext = new PIPacketExtractor(0, PIPacketExtractor::None);
|
||||||
|
packet_ext->setThreadedReadData(this);
|
||||||
|
packet_ext->setThreadedReadSlot(receiveEvent);
|
||||||
|
packet_ext->setHeaderCheckSlot(headerValidateEvent);
|
||||||
|
packet_ext->setName("__S__PIProtocol::packet_ext");
|
||||||
|
work = new_mp_prot = false;
|
||||||
|
eth = 0;
|
||||||
|
ser = 0;
|
||||||
|
ret_func = 0;
|
||||||
|
mp_owner = 0;
|
||||||
|
net_diag = PIProtocol::Unknown;
|
||||||
|
cur_pckt = 0;
|
||||||
|
packets[0] = packets[1] = pckt_cnt = pckt_cnt_max = 0;
|
||||||
|
diagTimer = 0;
|
||||||
|
timeout_ = 3.f;
|
||||||
|
sendTimer = new PITimer(sendEvent, this);
|
||||||
|
diagTimer = new PITimer(diagEvent, this);
|
||||||
|
secTimer = new PITimer(secEvent, this);
|
||||||
|
sendTimer->setName("__S__PIProtocol::sendTimer");
|
||||||
|
diagTimer->setName("__S__PIProtocol::diagTimer");
|
||||||
|
secTimer->setName("__S__PIProtocol::secTimer");
|
||||||
|
wrong_count = receive_count = send_count = missed_count = 0;
|
||||||
|
packets_in_sec = packets_out_sec = bytes_in_sec = bytes_out_sec = 0;
|
||||||
|
immediate_freq = integral_freq = ifreq = 0.f;
|
||||||
|
headerPtr = dataPtr = sendDataPtr = 0;
|
||||||
|
headerSize = dataSize = sendDataSize = 0;
|
||||||
|
type_rec = type_send = PIProtocol::None;
|
||||||
|
devSenderState = devReceiverState = "Unknown";
|
||||||
|
devSenderName = devReceiverName = "no device";
|
||||||
|
secTimer->start(1000.);
|
||||||
|
/*addEvent("receiver started");
|
||||||
|
addEvent("receiver stopped");
|
||||||
|
addEvent("sender started");
|
||||||
|
addEvent("sender stopped");
|
||||||
|
addEvent<bool>("received");
|
||||||
|
addEvent<PIProtocol::Quality>("quality changed");
|
||||||
|
addEventHandler<float>(HANDLER(PIProtocol, startReceive));
|
||||||
|
addEventHandler<float>(HANDLER(PIProtocol, startSend));
|
||||||
|
addEventHandler(HANDLER(PIProtocol, start));
|
||||||
|
addEventHandler(HANDLER(PIProtocol, stopReceive));
|
||||||
|
addEventHandler(HANDLER(PIProtocol, stopSend));
|
||||||
|
addEventHandler(HANDLER(PIProtocol, stop));*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PIString & config) {
|
||||||
|
int ps, gps;
|
||||||
|
bool ok, gok, flag, gflag, has_dev = false;
|
||||||
|
float freq, gfreq;
|
||||||
|
PIFlags<PISerial::Parameters> pp(0);
|
||||||
|
PIString dev, gdev;
|
||||||
|
|
||||||
|
if (sb.isEntryExists("ip") && sb.isEntryExists("device")) {
|
||||||
|
piCoutObj << "Ambiguous sender type in \"" << config << "\"!";
|
||||||
|
devSenderState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dev = sb.getValue("ip", "", &ok);
|
||||||
|
gdev = b.getValue("ip", "", &gok);
|
||||||
|
has_dev = false;
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) dev = gdev;
|
||||||
|
if (gok && ok && (dev != gdev)) {
|
||||||
|
piCoutObj << "Ambiguous sender type in \"" << config << "\"!";
|
||||||
|
devSenderState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ps = sb.getValue("port", 0, &ok);
|
||||||
|
gps = b.getValue("port", 0, &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) ps = gps;
|
||||||
|
if (gok && ok && (ps != gps)) {
|
||||||
|
piCoutObj << "Ambiguous send port in \"" << config << "\"!";
|
||||||
|
devSenderState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
type_send = PIProtocol::Ethernet;
|
||||||
|
if (eth == 0) eth = new PIEthernet();
|
||||||
|
eth->setName("__S__PIProtocol::eth");
|
||||||
|
setSenderAddress(dev, ps);
|
||||||
|
//setReceiverAddress(dev, ps);
|
||||||
|
has_dev = true;
|
||||||
|
flag = sb.getValue("reconnectEnabled", true, &ok);
|
||||||
|
gflag = b.getValue("reconnectEnabled", true, &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) flag = gflag;
|
||||||
|
if (gok && ok && (flag != gflag)) {
|
||||||
|
piCoutObj << "Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eth->setReopenEnabled(flag);
|
||||||
|
}
|
||||||
|
freq = sb.getValue("reconnectTimeout", 1., &ok);
|
||||||
|
gfreq = b.getValue("reconnectTimeout", 1., &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) freq = gfreq;
|
||||||
|
if (gok && ok && (freq != gfreq)) {
|
||||||
|
piCoutObj << "Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eth->setReopenTimeout(freq * 1000);
|
||||||
|
}
|
||||||
|
/*if (sendDataPtr_ == 0)
|
||||||
|
piCoutObj << "Warning: null send data pointer!";
|
||||||
|
if (sendDataSize_ == 0)
|
||||||
|
piCoutObj << "Warning: null send data size!";*/
|
||||||
|
} else {
|
||||||
|
piCoutObj << "Can`t find \"" << name() << ".sender.port\" or \"" << name() << ".port\" in \"" << config << "\"!";
|
||||||
|
devSenderState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dev = sb.getValue("device", "", &ok);
|
||||||
|
gdev = b.getValue("device", "", &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) dev = gdev;
|
||||||
|
if (gok && ok && (dev != gdev)) {
|
||||||
|
piCoutObj << "Ambiguous sender type in \"" << config << "\"!";
|
||||||
|
devSenderState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ps = sb.getValue("speed", 0, &ok);
|
||||||
|
gps = b.getValue("speed", 0, &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) ps = gps;
|
||||||
|
if (gok && ok && (ps != gps)) {
|
||||||
|
piCoutObj << "Ambiguous send \"speed\" in \"" << config << "\"!";
|
||||||
|
devSenderState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flag = sb.getValue("parity", false, &ok);
|
||||||
|
gflag = b.getValue("parity", false, &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) flag = gflag;
|
||||||
|
if (gok && ok && (flag != gflag)) {
|
||||||
|
piCoutObj << "Ambiguous send \"parity\" in \"" << config << "\"!";
|
||||||
|
devSenderState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pp.setFlag(PISerial::ParityControl, flag);
|
||||||
|
}
|
||||||
|
flag = sb.getValue("twoStopBits", false, &ok);
|
||||||
|
gflag = b.getValue("twoStopBits", false, &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) flag = gflag;
|
||||||
|
if (gok && ok && (flag != gflag)) {
|
||||||
|
piCoutObj << "Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!";
|
||||||
|
devSenderState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pp.setFlag(PISerial::TwoStopBits, flag);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
piCoutObj << "Can`t find \"" << name() << ".sender.speed\" or \"" << name() << ".speed\" in \"" << config << "\"!";
|
||||||
|
devSenderState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
type_send = PIProtocol::Serial;
|
||||||
|
if (ser == 0) ser = new PISerial(dev);
|
||||||
|
ser->setName("__S__PIProtocol::ser");
|
||||||
|
setSenderDevice(dev, (PISerial::Speed)ps);
|
||||||
|
ser->setOutSpeed((PISerial::Speed)ps);
|
||||||
|
ser->setParameters(pp);
|
||||||
|
has_dev = true;
|
||||||
|
/*if (sendDataPtr_ == 0)
|
||||||
|
piCoutObj << "Warning: null send data pointer!";
|
||||||
|
if (sendDataSize_ == 0)
|
||||||
|
piCoutObj << "Warning: null send data size!";*/
|
||||||
|
}
|
||||||
|
freq = sb.getValue("frequency", -1.f, &ok);
|
||||||
|
gfreq = b.getValue("frequency", -1.f, &gok);
|
||||||
|
if (gok && !ok) freq = gfreq;
|
||||||
|
if (gok && ok && (freq != gfreq)) {
|
||||||
|
piCoutObj << "Ambiguous sender frequency in \"" << config << "\"!";
|
||||||
|
devSenderState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (freq > 0.f && !has_dev)
|
||||||
|
piCoutObj << "Warning: no sender device and not null send frequency!";
|
||||||
|
setSenderFrequency(freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const PIString & config) {
|
||||||
|
int ps, gps;
|
||||||
|
bool ok, gok, flag, gflag, has_dev = false;
|
||||||
|
float freq, gfreq;
|
||||||
|
PIFlags<PISerial::Parameters> pp(0);
|
||||||
|
PIString dev, gdev;
|
||||||
|
|
||||||
|
if (rb.isEntryExists("ip") && rb.isEntryExists("device")) {
|
||||||
|
piCoutObj << "Ambiguous receiver type in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dev = rb.getValue("ip", "", &ok);
|
||||||
|
gdev = b.getValue("ip", "", &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) dev = gdev;
|
||||||
|
if (gok && ok && (dev != gdev)) {
|
||||||
|
piCoutObj << "Ambiguous receiver type in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ps = rb.getValue("port", 0, &ok);
|
||||||
|
gps = b.getValue("port", 0, &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) ps = gps;
|
||||||
|
if (gok && ok && (ps != gps)) {
|
||||||
|
piCoutObj << "Ambiguous receive port in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
type_rec = PIProtocol::Ethernet;
|
||||||
|
eth = new PIEthernet();
|
||||||
|
eth->setName("__S__PIProtocol::eth");
|
||||||
|
packet_ext->setDevice(eth);
|
||||||
|
//setSenderAddress(dev, ps);
|
||||||
|
setReceiverAddress(dev, ps);
|
||||||
|
has_dev = true;
|
||||||
|
flag = rb.getValue("reconnectEnabled", true, &ok);
|
||||||
|
gflag = b.getValue("reconnectEnabled", true, &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) flag = gflag;
|
||||||
|
if (gok && ok && (flag != gflag)) {
|
||||||
|
piCoutObj << "Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eth->setReopenEnabled(flag);
|
||||||
|
}
|
||||||
|
freq = rb.getValue("reconnectTimeout", 1., &ok);
|
||||||
|
gfreq = b.getValue("reconnectTimeout", 1., &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) freq = gfreq;
|
||||||
|
if (gok && ok && (freq != gfreq)) {
|
||||||
|
piCoutObj << "Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eth->setReopenTimeout(freq * 1000);
|
||||||
|
}
|
||||||
|
/*if (recDataPtr == 0)
|
||||||
|
piCoutObj << "Warning: null receive data pointer!";
|
||||||
|
if (recDataSize == 0)
|
||||||
|
piCoutObj << "Warning: null receive data size!";*/
|
||||||
|
} else {
|
||||||
|
piCoutObj << "Can`t find \"" << name() << ".receiver.port\" or \"" << name() << ".port\" in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dev = rb.getValue("device", "", &ok);
|
||||||
|
gdev = b.getValue("device", "", &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) dev = gdev;
|
||||||
|
if (gok && ok && (dev != gdev)) {
|
||||||
|
piCoutObj << "Ambiguous receiver type in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ps = rb.getValue("speed", 0, &ok);
|
||||||
|
gps = b.getValue("speed", 0, &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) ps = gps;
|
||||||
|
if (gok && ok && (ps != gps)) {
|
||||||
|
piCoutObj << "Ambiguous receive \"speed\" in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flag = rb.getValue("parity", false, &ok);
|
||||||
|
gflag = b.getValue("parity", false, &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) flag = gflag;
|
||||||
|
if (gok && ok && (flag != gflag)) {
|
||||||
|
piCoutObj << "Ambiguous receive \"parity\" in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pp.setFlag(PISerial::ParityControl, flag);
|
||||||
|
}
|
||||||
|
flag = rb.getValue("twoStopBits", false, &ok);
|
||||||
|
gflag = b.getValue("twoStopBits", false, &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) flag = gflag;
|
||||||
|
if (gok && ok && (flag != gflag)) {
|
||||||
|
piCoutObj << "Ambiguous receive \"twoStopBits\" parity in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pp.setFlag(PISerial::TwoStopBits, flag);
|
||||||
|
}
|
||||||
|
type_rec = PIProtocol::Serial;
|
||||||
|
type_send = PIProtocol::Serial;
|
||||||
|
ser = new PISerial(dev);
|
||||||
|
ser->setName("__S__PIProtocol::ser");
|
||||||
|
packet_ext->setDevice(ser);
|
||||||
|
//setSenderDevice(dev, (PISerial::Speed)ps);
|
||||||
|
setReceiverDevice(dev, (PISerial::Speed)ps);
|
||||||
|
ser->setInSpeed((PISerial::Speed)ps);
|
||||||
|
ser->setParameters(pp);
|
||||||
|
ps = rb.getValue("vtime", 1, &ok);
|
||||||
|
gps = b.getValue("vtime", 1, &gok);
|
||||||
|
if (ok || gok) {
|
||||||
|
if (gok && !ok) ps = gps;
|
||||||
|
if (gok && ok && (ps != gps)) {
|
||||||
|
piCoutObj << "Ambiguous receive \"vtime\" in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ser->setVTime(ps);
|
||||||
|
}
|
||||||
|
has_dev = true;
|
||||||
|
/*if (recDataPtr == 0)
|
||||||
|
piCoutObj << "Warning: null receive data pointer!";
|
||||||
|
if (recDataSize == 0)
|
||||||
|
piCoutObj << "Warning: null receive data size!";*/
|
||||||
|
} else {
|
||||||
|
piCoutObj << "Can`t find \"" << name() << ".receiver.speed\" or \"" << name() << ".speed\" in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
freq = rb.getValue("frequency", -1.f, &ok);
|
||||||
|
gfreq = b.getValue("frequency", -1.f, &gok);
|
||||||
|
if (gok && !ok) freq = gfreq;
|
||||||
|
if (gok && ok && (freq != gfreq)) {
|
||||||
|
piCoutObj << "Ambiguous expected frequency in \"" << config << "\"!";
|
||||||
|
devReceiverState = "Config error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (freq > 0.f && !has_dev)
|
||||||
|
piCoutObj << "Warning: no receiver device and not null expected frequency!";
|
||||||
|
float tm = b.getValue("disconnectTimeout", 3.f);
|
||||||
|
if (tm <= 0.f)
|
||||||
|
piCoutObj << "Warning: diconnect timeout <= 0 s!";
|
||||||
|
timeout_ = (tm < 0.f) ? 0.f : tm;
|
||||||
|
setExpectedFrequency(freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force) {
|
||||||
|
if (force) {
|
||||||
|
type_send = type_rec = PIProtocol::Serial;
|
||||||
|
if (ser == 0) {
|
||||||
|
ser = new PISerial();
|
||||||
|
ser->setName("__S__PIProtocol::ser");
|
||||||
|
packet_ext->setDevice(ser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type_rec == PIProtocol::Serial && ser != 0) {
|
||||||
|
ser->setDevice(device);
|
||||||
|
ser->setSpeed(speed);
|
||||||
|
devReceiverName = device;
|
||||||
|
devSenderName = device;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::setReceiverAddress(const PIString & ip, int port, bool force) {
|
||||||
|
if (force) {
|
||||||
|
type_rec = PIProtocol::Ethernet;
|
||||||
|
if (eth == 0) {
|
||||||
|
eth = new PIEthernet();
|
||||||
|
eth->setName("__S__PIProtocol::eth");
|
||||||
|
packet_ext->setDevice(eth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type_rec == PIProtocol::Ethernet && eth != 0) {
|
||||||
|
eth->setReadAddress(ip, port);
|
||||||
|
if (ip.trimmed().isEmpty()) devReceiverName = "no ip";
|
||||||
|
else devReceiverName = ip + ":" + PIString::fromNumber(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::setSenderDevice(const PIString & device, PISerial::Speed speed, bool force) {
|
||||||
|
if (force) {
|
||||||
|
type_send = type_rec = PIProtocol::Serial;
|
||||||
|
if (ser == 0) ser = new PISerial();
|
||||||
|
ser->setName("__S__PIProtocol::ser");
|
||||||
|
}
|
||||||
|
if (type_send == PIProtocol::Serial && ser != 0) {
|
||||||
|
ser->setDevice(device);
|
||||||
|
ser->setSpeed(speed);
|
||||||
|
ser->open();
|
||||||
|
devSenderName = device;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::setSenderAddress(const PIString & ip, int port, bool force) {
|
||||||
|
if (force) {
|
||||||
|
type_send = PIProtocol::Ethernet;
|
||||||
|
if (eth == 0) eth = new PIEthernet();
|
||||||
|
eth->setName("__S__PIProtocol::eth");
|
||||||
|
}
|
||||||
|
if (type_send == PIProtocol::Ethernet && eth != 0) {
|
||||||
|
eth->setSendAddress(ip, port);
|
||||||
|
if (ip.isEmpty()) devSenderName = "no ip";
|
||||||
|
else devSenderName = ip + ":" + PIString::fromNumber(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::setSenderIP(const PIString & ip, bool force) {
|
||||||
|
if (force) {
|
||||||
|
type_send = PIProtocol::Ethernet;
|
||||||
|
if (eth == 0) eth = new PIEthernet();
|
||||||
|
}
|
||||||
|
if (type_send == PIProtocol::Ethernet && eth != 0) {
|
||||||
|
eth->setSendIP(ip);
|
||||||
|
if (ip.isEmpty()) devSenderName = "no ip";
|
||||||
|
else devSenderName = ip + ":" + PIString::fromNumber(eth->sendPort());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::setSenderPort(int port, bool force) {
|
||||||
|
if (force) {
|
||||||
|
type_send = PIProtocol::Ethernet;
|
||||||
|
if (eth == 0) eth = new PIEthernet();
|
||||||
|
eth->setName("__S__PIProtocol::eth");
|
||||||
|
}
|
||||||
|
if (type_send == PIProtocol::Ethernet && eth != 0) {
|
||||||
|
eth->setSendPort(port);
|
||||||
|
if (eth->sendIP().isEmpty()) devSenderName = "no ip";
|
||||||
|
else devSenderName = eth->sendIP() + ":" + PIString::fromNumber(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::setExpectedFrequency(float frequency) {
|
||||||
|
exp_freq = frequency;
|
||||||
|
changeDisconnectTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::changeDisconnectTimeout() {
|
||||||
|
pckt_cnt_max = int(piRound(timeout_ * exp_freq));
|
||||||
|
if (pckt_cnt_max < 3) pckt_cnt_max = 3;
|
||||||
|
last_packets.resize(pckt_cnt_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::startReceive(float exp_frequency) {
|
||||||
|
if (exp_frequency > 0.f) exp_freq = exp_frequency;
|
||||||
|
//if (type_rec == PIProtocol::Serial) ser->start();
|
||||||
|
//if (type_rec == PIProtocol::Ethernet) eth->start();
|
||||||
|
packet_ext->startThreadedRead();
|
||||||
|
msleep(1);
|
||||||
|
check_state();
|
||||||
|
if (exp_freq <= 0.f) return;
|
||||||
|
setExpectedFrequency(exp_freq);
|
||||||
|
diagTimer->start(1000. / exp_freq);
|
||||||
|
diag_tm.reset();
|
||||||
|
receiverStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::startSend(float frequency) {
|
||||||
|
//cout << "** start send " << send_freq << ", " << frequency << endl;
|
||||||
|
if (frequency > 0.f) send_freq = frequency;
|
||||||
|
msleep(1);
|
||||||
|
check_state();
|
||||||
|
if (send_freq <= 0.f) return;
|
||||||
|
sendTimer->start(1000. / send_freq);
|
||||||
|
diag_tm.reset();
|
||||||
|
senderStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::stopReceive() {
|
||||||
|
//if (type_rec == PIProtocol::Serial) ser->stop();
|
||||||
|
//if (type_rec == PIProtocol::Ethernet) eth->stop();
|
||||||
|
packet_ext->stop();
|
||||||
|
diagTimer->stop();
|
||||||
|
receiverStopped();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIProtocol::receiveEvent(void * t, uchar * data, int size) {
|
||||||
|
PIProtocol * p = (PIProtocol * )t;
|
||||||
|
if (!p->receive(data, size)) return false;
|
||||||
|
p->work = true;
|
||||||
|
//p->lock();
|
||||||
|
if (p->validate()) {
|
||||||
|
p->received(true);
|
||||||
|
//p->unlock();
|
||||||
|
p->ifreq = p->diag_tm.elapsed_m();
|
||||||
|
if (p->ifreq > 0.) p->ifreq = 1000. / p->ifreq;
|
||||||
|
p->diag_tm.reset();
|
||||||
|
p->receive_count++;
|
||||||
|
p->packets_in_sec++;
|
||||||
|
p->bytes_in_sec += size;
|
||||||
|
p->cur_pckt = 1;
|
||||||
|
if (p->ret_func != 0) p->ret_func(p);
|
||||||
|
if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, true, data, size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
p->received(false);
|
||||||
|
//p->unlock();
|
||||||
|
p->wrong_count++;
|
||||||
|
if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, false, data, size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::diagEvent(void * t, int) {
|
||||||
|
PIProtocol * p = (PIProtocol * )t;
|
||||||
|
p->calc_freq();
|
||||||
|
p->calc_diag();
|
||||||
|
p->check_state();
|
||||||
|
if (p->ser != 0) p->missed_count = p->packet_ext->missedPackets();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::secEvent(void * t, int ) {
|
||||||
|
PIProtocol * p = (PIProtocol * )t;
|
||||||
|
p->speedIn = PIString::readableSize(p->bytes_in_sec) + "/s";
|
||||||
|
p->speedOut = PIString::readableSize(p->bytes_out_sec) + "/s";
|
||||||
|
p->bytes_in_sec = p->bytes_out_sec = p->packets_in_sec = p->packets_out_sec = 0;
|
||||||
|
if (p->ser != 0) p->missed_count = p->packet_ext->missedPackets();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::calc_diag() {
|
||||||
|
PIProtocol::Quality diag;
|
||||||
|
if (!work) {
|
||||||
|
diag = PIProtocol::Unknown;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pckt_cnt < pckt_cnt_max) {
|
||||||
|
last_packets[pckt_cnt] = cur_pckt;
|
||||||
|
pckt_cnt++;
|
||||||
|
} else {
|
||||||
|
packets[(int)last_packets.back()]--;
|
||||||
|
if (!last_packets.isEmpty()) last_packets.pop_back();
|
||||||
|
last_packets.push_front(cur_pckt);
|
||||||
|
}
|
||||||
|
packets[(int)cur_pckt]++;
|
||||||
|
cur_pckt = 0;
|
||||||
|
float good_percents;
|
||||||
|
good_percents = (float)packets[1] / pckt_cnt * 100.f;
|
||||||
|
if (good_percents == 0.f) diag = PIProtocol::Failure;
|
||||||
|
else if (good_percents <= 20.f) diag = PIProtocol::Bad;
|
||||||
|
else if (good_percents > 20.f && good_percents <= 80.f) diag = PIProtocol::Average;
|
||||||
|
else diag = PIProtocol::Good;
|
||||||
|
if (diag != net_diag) {
|
||||||
|
qualityChanged(diag, net_diag);
|
||||||
|
net_diag = diag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::calc_freq() {
|
||||||
|
float tf;// = float(1000.f / diagTimer->elapsed_m());
|
||||||
|
tf = immediate_freq = ifreq;
|
||||||
|
ifreq = 0.f;
|
||||||
|
if (last_freq.size_s() >= pckt_cnt_max && last_freq.size_s() > 0) last_freq.pop_front();
|
||||||
|
last_freq.push_back(tf);
|
||||||
|
tf = last_freq[0];
|
||||||
|
for (uint i = 1; i < last_freq.size(); ++i)
|
||||||
|
tf += last_freq[i];
|
||||||
|
integral_freq = tf / last_freq.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::check_state() {
|
||||||
|
if (type_rec == PIProtocol::Serial) {
|
||||||
|
if (ser != 0) {
|
||||||
|
if (ser->isOpened()) devReceiverState = "Opened";
|
||||||
|
else devReceiverState = "Not opened";
|
||||||
|
}
|
||||||
|
else devReceiverState = "Not exists";
|
||||||
|
}
|
||||||
|
if (type_rec == PIProtocol::Ethernet) {
|
||||||
|
if (eth != 0) {
|
||||||
|
if (eth->isOpened()) devReceiverState = "Opened";
|
||||||
|
else devReceiverState = "Not opened";
|
||||||
|
}
|
||||||
|
else devReceiverState = "Not exists";
|
||||||
|
}
|
||||||
|
if (type_send == PIProtocol::Serial) {
|
||||||
|
if (ser != 0) {
|
||||||
|
if (ser->isOpened()) devSenderState = "Opened";
|
||||||
|
else devSenderState = "Not opened";
|
||||||
|
}
|
||||||
|
else devSenderState = "Not exists";
|
||||||
|
}
|
||||||
|
if (type_send == PIProtocol::Ethernet) {
|
||||||
|
if (eth != 0) {
|
||||||
|
if (eth->isOpened()) devSenderState = "Opened";
|
||||||
|
else devSenderState = "Not opened";
|
||||||
|
}
|
||||||
|
else devSenderState = "Not exists";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::send(const void * data, int size, bool direct) {
|
||||||
|
if (!direct) {
|
||||||
|
if (data == 0 || size == 0) return;
|
||||||
|
if (!aboutSend()) return;
|
||||||
|
}
|
||||||
|
if (type_send == PIProtocol::Serial)
|
||||||
|
if (ser->send(data, size)) {
|
||||||
|
send_count++;
|
||||||
|
packets_out_sec++;
|
||||||
|
bytes_out_sec += size;
|
||||||
|
}
|
||||||
|
if (type_send == PIProtocol::Ethernet)
|
||||||
|
if (eth->send(data, size)) {
|
||||||
|
send_count++;
|
||||||
|
packets_out_sec++;
|
||||||
|
bytes_out_sec += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIProtocol::send() {
|
||||||
|
//lock();
|
||||||
|
//memcpy(packet, sendDataPtr, sendDataSize);
|
||||||
|
//unlock();
|
||||||
|
if (!aboutSend()) return;
|
||||||
|
if (sendDataPtr == 0 || sendDataSize == 0) return;
|
||||||
|
if (type_send == PIProtocol::Serial)
|
||||||
|
if (ser->send(sendDataPtr, sendDataSize)) {
|
||||||
|
send_count++;
|
||||||
|
packets_out_sec++;
|
||||||
|
bytes_out_sec += sendDataSize;
|
||||||
|
}
|
||||||
|
if (type_send == PIProtocol::Ethernet)
|
||||||
|
if (eth->send(sendDataPtr, sendDataSize)) {
|
||||||
|
send_count++;
|
||||||
|
packets_out_sec++;
|
||||||
|
bytes_out_sec += sendDataSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
238
kx_utils/piprotocol.h
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
/*! \file piprotocol.h
|
||||||
|
* \brief Highly configurable from file I/O channel
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
PIP - Platform Independent Primitives
|
||||||
|
Protocol, input/output channel (COM, UDP)
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PIPROTOCOL_H
|
||||||
|
#define PIPROTOCOL_H
|
||||||
|
|
||||||
|
#include "piserial.h"
|
||||||
|
#include "piethernet.h"
|
||||||
|
#include "pipacketextractor.h"
|
||||||
|
#include "pitimer.h"
|
||||||
|
#include "piconfig.h"
|
||||||
|
#include "pifile.h"
|
||||||
|
|
||||||
|
class PIProtocol; /// DEPRECATED
|
||||||
|
|
||||||
|
class PIP_EXPORT PIMultiProtocolBase: protected PIObject /// DEPRECATED
|
||||||
|
{
|
||||||
|
PIOBJECT_SUBCLASS(PIMultiProtocolBase, PIObject)
|
||||||
|
friend class PIProtocol;
|
||||||
|
public:
|
||||||
|
PIMultiProtocolBase() {;} /// DEPRECATED
|
||||||
|
virtual ~PIMultiProtocolBase() {;}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void received(PIProtocol * prot, bool corrected, uchar * data, int size) {;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void receiveEvent(PIMultiProtocolBase * p, PIProtocol * prot, bool corrected, uchar * data, int size) {p->mutex_receive.lock(); p->received(prot, corrected, data, size); p->mutex_receive.unlock();}
|
||||||
|
|
||||||
|
PIMutex mutex_receive;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*ReceiveFunc)(void * );
|
||||||
|
|
||||||
|
/// events:
|
||||||
|
/// void receiverStarted()
|
||||||
|
/// void receiverStopped()
|
||||||
|
/// void senderStarted()
|
||||||
|
/// void senderStopped()
|
||||||
|
/// void received(bool validate_is_ok)
|
||||||
|
/// void qualityChanged(PIProtocol::Quality old_quality, PIProtocol::Quality new_quality)
|
||||||
|
///
|
||||||
|
/// handlers:
|
||||||
|
/// void startReceive(float exp_frequency = -1.f)
|
||||||
|
/// void stopReceive()
|
||||||
|
/// void startSend(float frequency = -1.f)
|
||||||
|
/// void stopSend()
|
||||||
|
/// void start()
|
||||||
|
/// void stop()
|
||||||
|
/// void send()
|
||||||
|
/// void send(const void * data, int size, bool direct = false)
|
||||||
|
class PIP_EXPORT PIProtocol: public PIObject /// DEPRECATED
|
||||||
|
{
|
||||||
|
PIOBJECT_SUBCLASS(PIProtocol, PIObject)
|
||||||
|
friend class PIMultiProtocolBase;
|
||||||
|
friend class PIMultiProtocol;
|
||||||
|
enum Type {None, Serial, Ethernet};
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Contructs an empty unconfigured protocol
|
||||||
|
PIProtocol(): PIObject() {init();} /// DEPRECATED
|
||||||
|
|
||||||
|
//! Contructs protocol configured from file "config", config file section "name"
|
||||||
|
PIProtocol(const PIString & config, const PIString & name, void * recHeaderPtr = 0, int recHeaderSize = 0,
|
||||||
|
void * recDataPtr = 0, int recDataSize = 0, void * sendDataPtr = 0, int sendDataSize = 0); // from config
|
||||||
|
|
||||||
|
virtual ~PIProtocol();
|
||||||
|
|
||||||
|
//! Connection quality
|
||||||
|
enum Quality {
|
||||||
|
Unknown /** Unknown, no one packet received yet */ = 1,
|
||||||
|
Failure /** No connection, no one correct packet received for last period */ = 2,
|
||||||
|
Bad /** Bad connection, correct packets received <= 20% */ = 3,
|
||||||
|
Average /** Average connection, correct packets received > 20% and <= 80% */ = 4,
|
||||||
|
Good /** Good connection, correct packets received > 80% */ = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
EVENT_HANDLER0(void, startReceive) {startReceive(-1.f);}
|
||||||
|
EVENT_HANDLER1(void, startReceive, float, exp_frequency); // if "frequency = -1" used last passed value
|
||||||
|
EVENT_HANDLER0(void, stopReceive);
|
||||||
|
void setExpectedFrequency(float frequency); // for connection quality diagnostic
|
||||||
|
void setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial
|
||||||
|
void setReceiverData(void * dataPtr, int dataSize) {this->dataPtr = (uchar * )dataPtr; this->dataSize = dataSize; packet_ext->setHeader(PIByteArray(headerPtr, headerSize)); packet_ext->setPayloadSize(dataSize); packet_ext->setPacketSize(dataSize);}
|
||||||
|
void setReceiverDataHeader(void * headerPtr, int headerSize) {this->headerPtr = (uchar * )headerPtr; this->headerSize = headerSize; packet_ext->setHeader(PIByteArray(headerPtr, headerSize)); packet_ext->setPayloadSize(dataSize); packet_ext->setPacketSize(dataSize);}
|
||||||
|
void setReceiverAddress(const PIString & ip, int port, bool force = false); // for Ethernet
|
||||||
|
void setReceiverParameters(PIFlags<PISerial::Parameters> parameters) {if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial
|
||||||
|
void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;}
|
||||||
|
float expectedFrequency() const {return exp_freq;}
|
||||||
|
|
||||||
|
EVENT_HANDLER0(void, startSend) {startSend(-1.f);} // if "frequency = -1" used last passed value
|
||||||
|
EVENT_HANDLER1(void, startSend, float, frequency); // if "frequency = -1" used last passed value
|
||||||
|
EVENT_HANDLER0(void, stopSend) {sendTimer->stop(); senderStopped();}
|
||||||
|
void setSenderFrequency(float frequency) {send_freq = frequency;}
|
||||||
|
void setSenderDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial
|
||||||
|
void setSenderData(void * dataPtr, int dataSize) {sendDataPtr = (uchar * )dataPtr; sendDataSize = dataSize;}
|
||||||
|
void setSenderAddress(const PIString & ip, int port, bool force = false); // for Ethernet
|
||||||
|
void setSenderIP(const PIString & ip, bool force = false); // for Ethernet
|
||||||
|
void setSenderPort(int port, bool force = false); // for Ethernet
|
||||||
|
void setSenderParameters(PIFlags<PISerial::Parameters> parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial
|
||||||
|
float senderFrequency() const {return send_freq;}
|
||||||
|
|
||||||
|
EVENT_HANDLER0(void, start) {startReceive(); startSend();}
|
||||||
|
EVENT_HANDLER0(void, stop) {stopReceive(); stopSend();}
|
||||||
|
EVENT_HANDLER0(void, send);
|
||||||
|
EVENT_HANDLER2(void, send, const void *, data, int, size) {send(data, size, false);}
|
||||||
|
EVENT_HANDLER3(void, send, const void *, data, int, size, bool, direct);
|
||||||
|
|
||||||
|
void setName(const PIString & name) {protName = name; PIObject::setName(name);}
|
||||||
|
PIString name() const {return protName;}
|
||||||
|
void setDisconnectTimeout(float timeout) {timeout_ = timeout; changeDisconnectTimeout();}
|
||||||
|
float disconnectTimeout() const {return timeout_;}
|
||||||
|
const float * disconnectTimeout_ptr() const {return &timeout_;}
|
||||||
|
float immediateFrequency() const {return immediate_freq;}
|
||||||
|
float integralFrequency() const {return integral_freq;}
|
||||||
|
const float * immediateFrequency_ptr() const {return &immediate_freq;}
|
||||||
|
const float * integralFrequency_ptr() const {return &integral_freq;}
|
||||||
|
ullong receiveCountPerSec() const {return packets_in_sec;}
|
||||||
|
const ullong * receiveCountPerSec_ptr() const {return &packets_in_sec;}
|
||||||
|
ullong sendCountPerSec() const {return packets_out_sec;}
|
||||||
|
const ullong * sendCountPerSec_ptr() const {return &packets_out_sec;}
|
||||||
|
ullong receiveBytesPerSec() const {return bytes_in_sec;}
|
||||||
|
const ullong * receiveBytesPerSec_ptr() const {return &bytes_in_sec;}
|
||||||
|
ullong sendBytesPerSec() const {return bytes_out_sec;}
|
||||||
|
const ullong * sendBytesPerSec_ptr() const {return &bytes_out_sec;}
|
||||||
|
ullong receiveCount() const {return receive_count;}
|
||||||
|
const ullong * receiveCount_ptr() const {return &receive_count;}
|
||||||
|
ullong wrongCount() const {return wrong_count;}
|
||||||
|
const ullong * wrongCount_ptr() const {return &wrong_count;}
|
||||||
|
ullong sendCount() const {return send_count;}
|
||||||
|
const ullong * sendCount_ptr() const {return &send_count;}
|
||||||
|
ullong missedCount() const {return missed_count;}
|
||||||
|
const ullong * missedCount_ptr() const {return &missed_count;}
|
||||||
|
PIProtocol::Quality quality() const {return net_diag;} // receive quality
|
||||||
|
const int * quality_ptr() const {return (int * )&net_diag;} // receive quality pointer
|
||||||
|
PIString receiverDeviceName() const {return devReceiverName;}
|
||||||
|
PIString senderDeviceName() const {return devSenderName;}
|
||||||
|
PIString receiverDeviceState() const {return devReceiverState;}
|
||||||
|
const PIString * receiverDeviceState_ptr() const {return &devReceiverState;}
|
||||||
|
PIString senderDeviceState() const {return devSenderState;}
|
||||||
|
const PIString * senderDeviceState_ptr() const {return &devSenderState;}
|
||||||
|
PIString receiveSpeed() const {return speedIn;}
|
||||||
|
const PIString * receiveSpeed_ptr() const {return &speedIn;}
|
||||||
|
PIString sendSpeed() const {return speedOut;}
|
||||||
|
const PIString * sendSpeed_ptr() const {return &speedOut;}
|
||||||
|
|
||||||
|
void * receiveData() {return dataPtr;}
|
||||||
|
void * sendData() {return sendDataPtr;}
|
||||||
|
|
||||||
|
PIPacketExtractor * packetExtractor() {return packet_ext;}
|
||||||
|
// PIByteArray lastHeader() {return packet_ext->lastHeader();}
|
||||||
|
|
||||||
|
EVENT0(receiverStarted)
|
||||||
|
EVENT0(receiverStopped)
|
||||||
|
EVENT0(senderStarted)
|
||||||
|
EVENT0(senderStopped)
|
||||||
|
EVENT1(received, bool, validate_is_ok)
|
||||||
|
EVENT2(qualityChanged, PIProtocol::Quality, new_quality, PIProtocol::Quality, old_quality)
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool receive(uchar * data, int size) {if (dataPtr != 0) memcpy(dataPtr, data, size); return true;} // executed when raw data received, break if 'false' return
|
||||||
|
virtual bool validate() {return true;} // function for validate algorithm and save data from dataPtr to external struct
|
||||||
|
virtual bool headerValidate(uchar * src, uchar * rec, int size) {for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;} // function for validate header (COM-port and headerSize > 0)
|
||||||
|
virtual uint checksum_i(void * data, int size) { // function for checksum (uint)
|
||||||
|
uint c = 0;
|
||||||
|
for (int i = 0; i < size; ++i)
|
||||||
|
c += ((uchar*)data)[i];
|
||||||
|
return ~(c + 1);
|
||||||
|
}
|
||||||
|
virtual uchar checksum_c(void * data, int size) { // function for checksum (uchar)
|
||||||
|
uchar c = 0;
|
||||||
|
for (int i = 0; i < size; ++i)
|
||||||
|
c += ((uchar*)data)[i];
|
||||||
|
return ~(c + 1);
|
||||||
|
}
|
||||||
|
virtual bool aboutSend() {return true;} // executed before send data, if return 'false' then data is not sending
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PIString & config);
|
||||||
|
void init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const PIString & config);
|
||||||
|
void check_state();
|
||||||
|
void calc_freq();
|
||||||
|
void calc_diag();
|
||||||
|
|
||||||
|
PISerial * ser;
|
||||||
|
PIEthernet * eth;
|
||||||
|
uint dataSize, headerSize, sendDataSize;
|
||||||
|
uchar * dataPtr, * headerPtr, * sendDataPtr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void sendEvent(void * e, int) {((PIProtocol * )e)->send();}
|
||||||
|
static bool receiveEvent(void * t, uchar * data, int size);
|
||||||
|
static bool headerValidateEvent(void * t, uchar * src, uchar * rec, int size) {return ((PIProtocol * )t)->headerValidate(src, rec, size);}
|
||||||
|
static void diagEvent(void * t, int);
|
||||||
|
static void secEvent(void * t, int);
|
||||||
|
|
||||||
|
void setMultiProtocolOwner(PIMultiProtocolBase * mp) {mp_owner = mp;}
|
||||||
|
PIMultiProtocolBase * multiProtocolOwner() const {return mp_owner;}
|
||||||
|
void changeDisconnectTimeout();
|
||||||
|
|
||||||
|
ReceiveFunc ret_func;
|
||||||
|
PIPacketExtractor * packet_ext;
|
||||||
|
PITimer * diagTimer, * sendTimer, * secTimer;
|
||||||
|
PITimeMeasurer diag_tm;
|
||||||
|
PIMultiProtocolBase * mp_owner;
|
||||||
|
PIProtocol::Type type_send, type_rec;
|
||||||
|
PIProtocol::Quality net_diag;
|
||||||
|
PIDeque<float> last_freq;
|
||||||
|
PIDeque<char> last_packets;
|
||||||
|
PIString protName, devReceiverName, devReceiverState, devSenderName, devSenderState, speedIn, speedOut;
|
||||||
|
bool work, new_mp_prot;
|
||||||
|
float exp_freq, send_freq, ifreq, immediate_freq, integral_freq, timeout_;
|
||||||
|
int packets[2], pckt_cnt, pckt_cnt_max;
|
||||||
|
char cur_pckt;
|
||||||
|
ullong wrong_count, receive_count, send_count, missed_count, packets_in_sec, packets_out_sec, bytes_in_sec, bytes_out_sec;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PIPROTOCOL_H
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
<RCC>
|
|
||||||
<qresource prefix="/">
|
|
||||||
<file>../../icons/application-exit.png</file>
|
|
||||||
<file>../../icons/dialog-close.png</file>
|
|
||||||
<file>../../icons/configure.png</file>
|
|
||||||
<file>../../icons/document-edit.png</file>
|
|
||||||
<file>../../icons/document-new.png</file>
|
|
||||||
<file>../../icons/document-save.png</file>
|
|
||||||
<file>../../icons/document-save-all.png</file>
|
|
||||||
<file>../../icons/document-save-as.png</file>
|
|
||||||
<file>../../icons/document-open.png</file>
|
|
||||||
<file>../../icons/document-open-recent.png</file>
|
|
||||||
<file>../../icons/document-close.png</file>
|
|
||||||
<file>../../icons/edit-clear.png</file>
|
|
||||||
<file>../../icons/edit-clear-locationbar-rtl.png</file>
|
|
||||||
<file>../../icons/edit-find.png</file>
|
|
||||||
<file>../../icons/list-add.png</file>
|
|
||||||
<file>../../icons/edit-delete.png</file>
|
|
||||||
<file>../../icons/edit-copy.png</file>
|
|
||||||
<file>../../icons/edit-paste.png</file>
|
|
||||||
<file>../../icons/edit-undo.png</file>
|
|
||||||
<file>../../icons/edit-redo.png</file>
|
|
||||||
<file>../../icons/border-line.png</file>
|
|
||||||
<file>../../icons/edockwidget.png</file>
|
|
||||||
<file>../../icons/historyview.png</file>
|
|
||||||
<file>../../icons/clear-history.png</file>
|
|
||||||
<file>../../icons/layer-visible-off.png</file>
|
|
||||||
<file>../../icons/layer-visible-on.png</file>
|
|
||||||
<file>../../icons/logview.png</file>
|
|
||||||
<file>../../icons/qt.png</file>
|
|
||||||
<file>../../icons/select-all.png</file>
|
|
||||||
<file>../../icons/select-none.png</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
<RCC>
|
|
||||||
<qresource prefix="/">
|
|
||||||
<file>../../icons/edit-table-insert-row-below.png</file>
|
|
||||||
<file>../../icons/dialog-close.png</file>
|
|
||||||
<file>../../icons/edit-clear.png</file>
|
|
||||||
<file>../../icons/edit-guides.png</file>
|
|
||||||
<file>../../icons/view-grid.png</file>
|
|
||||||
<file>../../icons/zoom-fit-best.png</file>
|
|
||||||
<file>../../icons/configure.png</file>
|
|
||||||
<file>../../icons/document-save.png</file>
|
|
||||||
<file>../../icons/edit-clear-locationbar-rtl.png</file>
|
|
||||||
<file>../../icons/edit-find.png</file>
|
|
||||||
<file>../../icons/list-add.png</file>
|
|
||||||
<file>../../icons/edit-delete.png</file>
|
|
||||||
<file>../../icons/item.png</file>
|
|
||||||
<file>../../icons/node-add.png</file>
|
|
||||||
<file>../../icons/node.png</file>
|
|
||||||
<file>../../icons/edit-copy.png</file>
|
|
||||||
<file>../../icons/edit-paste.png</file>
|
|
||||||
<file>../../icons/expand_s_x.png</file>
|
|
||||||
<file>../../icons/expand_s_y.png</file>
|
|
||||||
<file>../../icons/expand_x.png</file>
|
|
||||||
<file>../../icons/expand_y.png</file>
|
|
||||||
<file>../../icons/sql_table.png</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<RCC>
|
|
||||||
<qresource prefix="/">
|
|
||||||
<file>../../icons/edit-clear.png</file>
|
|
||||||
<file>../../icons/document-save.png</file>
|
|
||||||
<file>../../icons/edit-clear-locationbar-rtl.png</file>
|
|
||||||
<file>../../icons/edit-find.png</file>
|
|
||||||
<file>../../icons/list-add.png</file>
|
|
||||||
<file>../../icons/edit-delete.png</file>
|
|
||||||
<file>../../icons/item-add.png</file>
|
|
||||||
<file>../../icons/item.png</file>
|
|
||||||
<file>../../icons/node-add.png</file>
|
|
||||||
<file>../../icons/node.png</file>
|
|
||||||
<file>../../icons/edit-copy.png</file>
|
|
||||||
<file>../../icons/edit-paste.png</file>
|
|
||||||
<file>../../icons/document-open_16.png</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
<RCC>
|
|
||||||
<qresource prefix="/">
|
|
||||||
<file>../../icons/go-next.png</file>
|
|
||||||
<file>../../icons/go-previous.png</file>
|
|
||||||
<file>../../icons/dialog-close.png</file>
|
|
||||||
<file>../../icons/edit-clear.png</file>
|
|
||||||
<file>../../icons/edit-guides.png</file>
|
|
||||||
<file>../../icons/view-grid.png</file>
|
|
||||||
<file>../../icons/zoom-fit-best.png</file>
|
|
||||||
<file>../../icons/configure.png</file>
|
|
||||||
<file>../../icons/alpha.png</file>
|
|
||||||
<file>../../icons/document-save.png</file>
|
|
||||||
<file>../../icons/edit-clear-locationbar-rtl.png</file>
|
|
||||||
<file>../../icons/edit-find.png</file>
|
|
||||||
<file>../../icons/list-add.png</file>
|
|
||||||
<file>../../icons/edit-delete.png</file>
|
|
||||||
<file>../../icons/item-add.png</file>
|
|
||||||
<file>../../icons/item.png</file>
|
|
||||||
<file>../../icons/node-add.png</file>
|
|
||||||
<file>../../icons/node.png</file>
|
|
||||||
<file>../../icons/edit-copy.png</file>
|
|
||||||
<file>../../icons/edit-paste.png</file>
|
|
||||||
<file>../../icons/expand_s_x.png</file>
|
|
||||||
<file>../../icons/expand_s_y.png</file>
|
|
||||||
<file>../../icons/expand_x.png</file>
|
|
||||||
<file>../../icons/expand_y.png</file>
|
|
||||||
<file>../../icons/border-line.png</file>
|
|
||||||
<file>../../icons/legend.png</file>
|
|
||||||
<file>../../icons/chardialog.png</file>
|
|
||||||
<file>../../icons/clineedit.png</file>
|
|
||||||
<file>../../icons/colorbutton.png</file>
|
|
||||||
<file>../../icons/ecombobox.png</file>
|
|
||||||
<file>../../icons/qpiconsole.png</file>
|
|
||||||
<file>../../icons/spinslider.png</file>
|
|
||||||
<file>../../icons/etabwidget.png</file>
|
|
||||||
<file>../../icons/qcodeedit.png</file>
|
|
||||||
<file>../../icons/qvariantedit.png</file>
|
|
||||||
<file>../../icons/code-word.png</file>
|
|
||||||
<file>../../icons/f1.png</file>
|
|
||||||
<file>../../icons/dialog-ok-apply.png</file>
|
|
||||||
<file>../../icons/dialog-warning.png</file>
|
|
||||||
<file>../../icons/tools-wizard.png</file>
|
|
||||||
<file>../../icons/evalspinbox.png</file>
|
|
||||||
<file>../../icons/scroll_spin.png</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
||||||
BIN
logo.png
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 14 KiB |
6
make_libs.bat
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
@echo off
|
||||||
|
set ARCH=%~1
|
||||||
|
set PATH=%SDK_MINGW_DIR%%ARCH%\bin;%SDK_QT4_DIR%%ARCH%\bin;%SDK_CMAKE_DIR%\bin
|
||||||
|
if defined SDK_QT5_DIR set Qt5_DIR=%SDK_QT5_DIR%%ARCH%
|
||||||
|
mkdir ..\libs_build_win%ARCH%
|
||||||
|
cd ../libs_build_win%ARCH% && cmake_mgw -Wno-dev -DQGLVIEW=1 -DQGLENGINE=1 -DQT4=0 ../libs && make install -j4 && cd ../libs && pause
|
||||||
6
make_libs.sh
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
cd ..
|
||||||
|
mkdir libs_build_linux
|
||||||
|
cd libs_build_linux
|
||||||
|
cmake ../libs
|
||||||
|
make install $@
|
||||||
1
make_libs32.bat
Normal file
@@ -0,0 +1 @@
|
|||||||
|
make_libs.bat 32
|
||||||
1
make_libs64.bat
Normal file
@@ -0,0 +1 @@
|
|||||||
|
make_libs.bat 64
|
||||||
2
make_libs_all.bat
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
start cmd /C make_libs32.bat
|
||||||
|
start cmd /C make_libs64.bat
|
||||||
6
make_libs_android.bat
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
@echo off
|
||||||
|
mkdir ..\libs_build_android_%~1
|
||||||
|
cd ..\libs_build_android_%~1
|
||||||
|
call ..\libs\cmake_android 21 %~1 ..\libs "-DUTILS=0 -DDEBUG=0 -DCMAKE_BUILD_TYPE=Release"
|
||||||
|
call make install -j4
|
||||||
|
cd ..\libs
|
||||||