commit 5a49104273734148f7f9c1aedeb91cf8ad70ee3c Author: Ivan Pelipenko Date: Fri Sep 4 22:21:23 2020 +0300 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a2cb3e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.svn +CMakeLists.txt.user* diff --git a/AUTHORS.txt b/AUTHORS.txt new file mode 100644 index 0000000..7dd5dfb --- /dev/null +++ b/AUTHORS.txt @@ -0,0 +1,2 @@ +peri4 = Пелипенко Иван +andrey = Бычков Андрей diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..965866f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,76 @@ +cmake_minimum_required(VERSION 3.0) +cmake_policy(SET CMP0017 NEW) # need include() with .cmake +project(qad) +set(qad_MAJOR 1) +set(qad_MINOR 9) +set(qad_REVISION 0) +set(qad_SUFFIX ) +set(qad_COMPANY SHS) +set(qad_DOMAIN org.SHS) + +if ("x${CMAKE_MODULE_PATH}" STREQUAL "x") + set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +endif() + +include(SHSTKMacros) +include(QtWraps) +shstk_begin_project(qad QAD) +include(SHSTKQtMacros) + +shstk_qt_founded(QtVersions) +foreach(_v ${_QT_VERSIONS_}) + #message("Qt ${_v} -> ${QtVersions}") + option(Qt${_v} "Build for Qt${_v}" ON) +endforeach() + +if (NOT DEFINED ANDROID_PLATFORM) + find_package(OpenGL REQUIRED) +endif() +#include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +option(UTILS "Build various utils" ${_plugins_default_}) +option(DESIGNER_PLUGINS "Build Qt designer plugins" ${_plugins_default_}) + +macro(qad_library NAME _MODULES _LIBS) + shstk_qt_project(qad_${NAME} FALSE "qad" "${_MODULES}" "${_LIBS}" ${ARGN}) + shstk_qt_install("qad" FALSE qad_${NAME} "${out_HDR}" "${out_QM}") +endmacro() + +macro(qad_application NAME _MODULES _LIBS) + shstk_qt_project(${NAME} TRUE "qad" "${_MODULES}" "${_LIBS}" ${ARGN}) + shstk_qt_install("qad" TRUE ${NAME} "" "${out_QM}") +endmacro() + +macro(qad_plugin NAME _MODULES _LIBS) + shstk_qt_plugin(qad_${NAME} "${_MODULES}" "qad_${NAME};${_LIBS}") +endmacro() + +shstk_install(qad FALSE "" "${QAD_VERSION_FILE}") +if (NOT LOCAL) + file(GLOB CMAKES "cmake/*.cmake" "cmake/*.in") + install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules) +endif() + +add_subdirectory(libs) +if (UTILS) + add_subdirectory(utils) +endif() + +message("----------QAD----------") +message(" Build for ${QtVersions}") +message(" Linkage: ${qad_LIB_TYPE_MSG}") +message(" Type : ${qad_BUILD_TYPE}") +message(" Install: \"${CMAKE_INSTALL_PREFIX}\"") +message("") +print_list("${_qt_libs}" " Libraries:" " * ") +if (NOT "x${_qt_plugs}" STREQUAL "x") + message("") + print_list("${_qt_plugs}" " Plugins:" " * ") +endif() +if (NOT "x${_qt_apps}" STREQUAL "x") + message("") + print_list("${_qt_apps}" " Applications:" " * ") +endif() +message("-----------------------") + +shstk_copy_to_parent() diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d5ea707 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Control & Debug library + +## Introduction diff --git a/cmake/FindCD.cmake b/cmake/FindCD.cmake new file mode 100644 index 0000000..fdd53d2 --- /dev/null +++ b/cmake/FindCD.cmake @@ -0,0 +1,141 @@ +#[[ + +Create imported targets: + * QAD::Utils + * QAD::Widgets + * QAD::Application + * QAD::Blockview + * QAD::Graphic + * QAD::SQLTable + * QAD::TouchWidgets + * QAD::Doc + * QAD::PIQt + * QAD::PIQtUtils + +These targets include directories and dependencies + +]] + +cmake_policy(SET CMP0011 NEW) # don`t affect includer policies +cmake_policy(SET CMP0020 NEW) # Automatically link Qt executables to qtmain target on Windows +if(NOT BUILDING_qad) + find_package(PIP QUIET) + include(QtWraps) + include(SHSTKMacros) +endif() + +shstk_is_parent_exists(hasParent PARENT_DIRECTORY) +set(_SEARCH_DIR) +if(WIN32) + find_package(MinGW REQUIRED) +endif() + +shstk_set_find_dirs(qad) + +if (NOT BUILDING_qad) + + find_file(QAD_H_INCLUDE "qad_types.h" HINTS ${PIP_DIR}/include/qad ${qad_INCDIR} $ENV{SMSDK_DIR}/include/qad) + #if (DEFINED ANDROID_PLATFORM) + # set(QAD_INCLUDES ${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include/qad) + #else() + get_filename_component(QAD_INCLUDES ${QAD_H_INCLUDE} PATH) + #endif() + set(_SEARCH_DIR ${qad_LIBDIR} $ENV{SMSDK_DIR}/lib) + shstk_find_header(QAD "qad_version.h" "") + +endif() + +if(QAD_FIND_VERSION VERSION_GREATER QAD_VERSION) + message(FATAL_ERROR "QAD version ${QAD_VERSION} is available, but ${QAD_FIND_VERSION} requested!") +endif() + +set(__libs "utils;widgets;application;blockview;graphic;sql_table;touch_widgets;doc") +if (PIP_FOUND OR BUILDING_pip) + list(APPEND __libs "piqt;piqt_utils") +endif() + +set(__module_utils Utils ) +set(__module_widgets Widgets ) +set(__module_application Application ) +set(__module_blockview Blockview ) +set(__module_graphic Graphic ) +set(__module_sql_table SQLTable ) +set(__module_touch_widgets TouchWidgets ) +set(__module_doc Doc ) +set(__module_piqt PIQt ) +set(__module_piqt_utils PIQtUtils ) + +foreach (_l ${__libs}) + set( __inc_${_l} "") + set(__deps_${_l} "") + set(__libs_${_l} "") +endforeach() + +set(__deps_widgets "QAD::Utils") +set(__deps_application "QAD::Widgets") +set(__deps_blockview "QAD::Widgets") +set(__deps_graphic "QAD::Widgets") +set(__deps_sql_table "QAD::Widgets") +set(__deps_piqt "QAD::Widgets;PIP") +set(__deps_piqt_utils "QAD::Blockview;QAD::PIQt") + +#message("find QAD ${BUILDING_qad}") + +if (BUILDING_qad) + + if (NOT SET_TARGETS_qad) + set(SET_TARGETS_qad ON CACHE BOOL "") + #message("create aliases") + foreach(_l ${__libs}) + foreach(_v ${_QT_VERSIONS_}) + set(_m ${__module_${_l}}) + string(REPLACE ":" "_" _m_str "${_m}") + if((NOT TARGET QAD::${_m}${_v}) AND TARGET qad_${_l}${_v}) + #message("alias QAD::${_m}${_v} = qad_${_l}${_v}") + set(MULTILIB_qad_${_l}_SUFFIX_Qt${_v} ${_v} CACHE STRING "") + add_library(QAD::${_m}${_v} ALIAS qad_${_l}${_v}) + endif() + endforeach() + list(APPEND QT_MULTILIB_LIST QAD::${_m}) + endforeach() + endif() + + set(QAD_FOUND ON CACHE BOOL "") + +else() + + #message("create interfaces") + foreach(_l ${__libs}) + foreach(_v ${_QT_VERSIONS_}) + set(_m ${__module_${_l}}) + string(REPLACE ":" "_" _m_str "${_m}") + find_library(QAD_LIBRARY_${_l}${_v} qad_${_l}${_v} HINTS ${qad_LIBDIR}) + #message("found ${_l}${_v} = ${QAD_LIBRARY_${_l}${_v}}") + if((NOT TARGET QAD::${_m}${_v}) AND QAD_LIBRARY_${_l}${_v}) + #message("imported QAD::${_m}${_v} = ${QAD_LIBRARY_${_l}${_v}}") + set(MULTILIB_qad_${_l}_SUFFIX_Qt${_v} ${_v} CACHE STRING "") + add_library(QAD::${_m}${_v} UNKNOWN IMPORTED) + set(_deps) + foreach (_d ${__deps_${_l}}) + if (${_d} MATCHES "QAD::*") + list(APPEND _deps ${_d}${_v}) + else() + list(APPEND _deps ${_d}) + endif() + endforeach() + set_target_properties(QAD::${_m}${_v} PROPERTIES + IMPORTED_LOCATION "${QAD_LIBRARY_${_l}${_v}}" + INTERFACE_INCLUDE_DIRECTORIES "${QAD_INCLUDES}" + INTERFACE_LINK_LIBRARIES "${_deps}") + endif() + endforeach() + list(APPEND QT_MULTILIB_LIST QAD::${_m}) + endforeach() + +endif() + +if(hasParent) + set(QT_MULTILIB_LIST ${QT_MULTILIB_LIST} PARENT_SCOPE) +endif() + +set(QAD_FOUND ON CACHE BOOL "") diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt new file mode 100644 index 0000000..0d911f8 --- /dev/null +++ b/libs/CMakeLists.txt @@ -0,0 +1 @@ +add_directories_with_include("qad_") diff --git a/libs/cd_utils/CMakeLists.txt b/libs/cd_utils/CMakeLists.txt new file mode 100644 index 0000000..e399d88 --- /dev/null +++ b/libs/cd_utils/CMakeLists.txt @@ -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() diff --git a/libs/cd_utils/cdtest.h b/libs/cd_utils/cdtest.h new file mode 100644 index 0000000..f707548 --- /dev/null +++ b/libs/cd_utils/cdtest.h @@ -0,0 +1,10 @@ +#ifndef CDTEST_H +#define CDTEST_H + + +enum KDescription { + First, //f Первый + Second, //b Второй +}; + +#endif // CDTEST_H diff --git a/libs/cd_utils/cdutils_c.cpp b/libs/cd_utils/cdutils_c.cpp new file mode 100644 index 0000000..6ff28ac --- /dev/null +++ b/libs/cd_utils/cdutils_c.cpp @@ -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 eh_map; + PIObject::__MetaData & md(PIObject::__meta_data()[cid]); + PIMap::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 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]); + } +} diff --git a/libs/cd_utils/cdutils_c.h b/libs/cd_utils/cdutils_c.h new file mode 100644 index 0000000..80082f9 --- /dev/null +++ b/libs/cd_utils/cdutils_c.h @@ -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 . +*/ + +#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 diff --git a/libs/cd_utils/cdutils_core.cpp b/libs/cd_utils/cdutils_core.cpp new file mode 100644 index 0000000..685694d --- /dev/null +++ b/libs/cd_utils/cdutils_core.cpp @@ -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 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 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 & 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 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 & p, x_selected) { + x_[p].x_enabled = true; + } + x_mutex.unlock(); + } break; + case CD_XValues: { + if (!x_pult_side) break; + PIVector > x_vals; + ba >> x_vals; + x_mutex.lock(); + piForeachC (PIDeque & 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 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 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 & p) { + PIString ret; + for (int i = 0; i < p.size_s(); ++i) { + if (!ret.isEmpty()) ret += "."; + ret << p[i]; + } + return ret; +} + + +PIDeque CDCore::stringToPath(const PIString & p) { + PIDeque 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); +} + diff --git a/libs/cd_utils/cdutils_core.h b/libs/cd_utils/cdutils_core.h new file mode 100644 index 0000000..d7c357f --- /dev/null +++ b/libs/cd_utils/cdutils_core.h @@ -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 . +*/ + +#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, path, PIString, value); + + EVENT(X_Sended) + EVENT(X_SendFail) + EVENT(X_Received) + EVENT(X_ReceiveFail) + EVENT(X_ChangedGlobal) + EVENT1(X_ReceivedX, PIVector >, 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, 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 & p); + static PIDeque 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 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 > x_selected; + PIMap c_handlers; + bool need_rebuild_x, x_pult_side; + +}; + + +static __Core_Initializer__ __Core_initializer__; + +} + +#endif // CDUTILS_CORE_H diff --git a/libs/cd_utils/cdutils_interface.cpp b/libs/cd_utils/cdutils_interface.cpp new file mode 100644 index 0000000..e1688c4 --- /dev/null +++ b/libs/cd_utils/cdutils_interface.cpp @@ -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 & path_) { + return (*s)[path_]; +} + + +const CDType Interface::operator [](const PIDeque & 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 &path) { + PIDeque 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 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); +} diff --git a/libs/cd_utils/cdutils_interface.h b/libs/cd_utils/cdutils_interface.h new file mode 100644 index 0000000..79f0aa1 --- /dev/null +++ b/libs/cd_utils/cdutils_interface.h @@ -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 . +*/ + +#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 & path_); + const CDType operator [](const PIDeque & path_) const; + CDSection & section(int v); + const CDSection section(int v) const; + CDSection & section(const PIDeque & 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 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 diff --git a/libs/cd_utils/cdutils_k.cpp b/libs/cd_utils/cdutils_k.cpp new file mode 100644 index 0000000..313a6fe --- /dev/null +++ b/libs/cd_utils/cdutils_k.cpp @@ -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)); +} diff --git a/libs/cd_utils/cdutils_k.h b/libs/cd_utils/cdutils_k.h new file mode 100644 index 0000000..e699f07 --- /dev/null +++ b/libs/cd_utils/cdutils_k.h @@ -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 . +*/ + +#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 diff --git a/libs/cd_utils/cdutils_m.cpp b/libs/cd_utils/cdutils_m.cpp new file mode 100644 index 0000000..95c4151 --- /dev/null +++ b/libs/cd_utils/cdutils_m.cpp @@ -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); +} diff --git a/libs/cd_utils/cdutils_m.h b/libs/cd_utils/cdutils_m.h new file mode 100644 index 0000000..9d9a00c --- /dev/null +++ b/libs/cd_utils/cdutils_m.h @@ -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 . +*/ + +#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 & path_) {return createPICout((*s)[path_]);} + PICout operator [](const PIDeque & path_) const {return createPICout((*s)[path_]);} + + void messageBox(const CDType & m, const PIString & msg); + + EVENT3(messageReceived, PIDeque, path, int, type, PIString, msg) + +private: + PICout createPICout(const CDType & m) const; + +}; + +} + +extern CD_UTILS_EXPORT CDUtils::MInterface M; + +#endif // CDUTILS_M_H diff --git a/libs/cd_utils/cdutils_parser.cpp b/libs/cd_utils/cdutils_parser.cpp new file mode 100644 index 0000000..2a41c07 --- /dev/null +++ b/libs/cd_utils/cdutils_parser.cpp @@ -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 enumValues(const PIString & e, const PIMap & sections, PIStringList & enames) { + PIVector 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 sections; + PIMap 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 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); +} diff --git a/libs/cd_utils/cdutils_parser.h b/libs/cd_utils/cdutils_parser.h new file mode 100644 index 0000000..d85d609 --- /dev/null +++ b/libs/cd_utils/cdutils_parser.h @@ -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 . +*/ + +#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 diff --git a/libs/cd_utils/cdutils_protocol.h b/libs/cd_utils/cdutils_protocol.h new file mode 100644 index 0000000..18b9164 --- /dev/null +++ b/libs/cd_utils/cdutils_protocol.h @@ -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 . +*/ + +#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 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 diff --git a/libs/cd_utils/cdutils_types.cpp b/libs/cd_utils/cdutils_types.cpp new file mode 100644 index 0000000..c722270 --- /dev/null +++ b/libs/cd_utils/cdutils_types.cpp @@ -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 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 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 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::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 & 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 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 prev_cd_f_bi; + PIMap prev_cd_f_bn; + PIMap::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 prev_s_bi; + PIMap prev_s_bn; + PIMap::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 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::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 cd_ids; + PIMap::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::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::iterator i; + for (i = cd.begin(); i != cd.end(); ++i) { + i.value().parent = this; + i.value().calculated = false; + } + PIMap::iterator j; + for (j = s.begin(); j != s.end(); ++j) + j.value().prepareCalculate(); +} + + +void CDSection::calculateRecursive(PIEvaluator * e) { + PIMap::iterator i; + for (i = cd.begin(); i != cd.end(); ++i) + i.value().calculate(e); + PIMap::iterator j; + for (j = s.begin(); j != s.end(); ++j) + j.value().calculateRecursive(e); +} + + +void CDSection::setSelectedX(bool yes) { + PIMap::iterator i; + for (i = cd.begin(); i != cd.end(); ++i) + i.value().x_enabled = yes; + PIMap::iterator j; + for (j = s.begin(); j != s.end(); ++j) + j.value().setSelectedX(yes); +} + + +PIVector > CDSection::collectX() const { + PIVector > ret; + PIMap::const_iterator i; + for (i = cd.begin(); i != cd.end(); ++i) { + if (i.value().x_enabled) + ret << i.value().path(); + } + PIMap::const_iterator j; + for (j = s.constBegin(); j != s.constEnd(); ++j) + ret << j.value().collectX(); + return ret; +} + + +void CDSection::makePath(PIDeque p) { + PIDeque tp; + PIMap::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::iterator j; + for (j = s.begin(); j != s.end(); ++j) { + tp = p; + tp << j.key(); + j.value().makePath(tp); + } +} + + +PIVector CDSection::children(bool recursive) const { + PIVector ret; + PIMap::const_iterator i; + for (i = cd.begin(); i != cd.end(); ++i) + ret << const_cast(&(i.value())); + if (!recursive) return ret; + PIMap::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::const_iterator i; + for (i = cd.constBegin(); i != cd.constEnd(); ++i) + ret << PIVariantTypes::Enumerator(i.key(), i.value().name()); + return ret; +} + + diff --git a/libs/cd_utils/cdutils_types.h b/libs/cd_utils/cdutils_types.h new file mode 100644 index 0000000..f2fd7fe --- /dev/null +++ b/libs/cd_utils/cdutils_types.h @@ -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 . +*/ + +#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 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 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 history; + +protected: + bool calculate(PIEvaluator * e, PIVector stack = PIVector()); + 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 path_; + double value_d; + int value_i; + bool value_b, calculated, x_enabled; + PIVector 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(this)->getByName(name_);} + CDType & operator [](const PIDeque & path_) {return getByPath(path_);} + const CDType operator [](const PIDeque & path_) const {return const_cast(this)->getByPath(path_);} + CDSection & section(int v); + const CDSection section(int v) const; + + bool isEmpty() const {return cd.isEmpty() && s.isEmpty();} + bool exists(PIDeque path) const; + int count(bool recursive = true) const; + int sectionsCount() const; + PIVector indexes() const {return cd.keys();} + PIStringList index_names() const; + void calculate(); + void makePath(PIDeque p = PIDeque()); + PIVector children(bool recursive = true) const; + PIVariantTypes::Enum enumValues() const; + + PIString name; + PIString alias; + +protected: + CDSection(PIMap k_, PIMap s_) { + cd = k_; + s = s_; + } + CDType & getByName(const PIString & name_); + CDType & getByPath(const PIDeque & 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 > collectX() const; + + PIMap cd; + mutable PIMap 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 diff --git a/libs/cd_utils/cdutils_x.cpp b/libs/cd_utils/cdutils_x.cpp new file mode 100644 index 0000000..e647377 --- /dev/null +++ b/libs/cd_utils/cdutils_x.cpp @@ -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 > XInterface::enabledList() const { + return CDCore::instance()->x_selected; +} + + +void XInterface::setEnabledList(const PIVector > & 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(); +} diff --git a/libs/cd_utils/cdutils_x.h b/libs/cd_utils/cdutils_x.h new file mode 100644 index 0000000..72e9974 --- /dev/null +++ b/libs/cd_utils/cdutils_x.h @@ -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 . +*/ + +#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 >, 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 > enabledList() const; + void setEnabledList(const PIVector > & l); + void lock(); + void unlock(); + + void start(double freq = 20.); + void stop(); + +}; + +} + +extern CD_UTILS_EXPORT CDUtils::XInterface X; + +#endif // CDUTILS_X_H diff --git a/libs/cd_utils/cdutilstest.cpp b/libs/cd_utils/cdutilstest.cpp new file mode 100644 index 0000000..d284b49 --- /dev/null +++ b/libs/cd_utils/cdutilstest.cpp @@ -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; +} + diff --git a/libs/cd_utils/k_description.h b/libs/cd_utils/k_description.h new file mode 100644 index 0000000..09d53ce --- /dev/null +++ b/libs/cd_utils/k_description.h @@ -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 diff --git a/libs/qcd_utils/CMakeLists.txt b/libs/qcd_utils/CMakeLists.txt new file mode 100644 index 0000000..f3e84e8 --- /dev/null +++ b/libs/qcd_utils/CMakeLists.txt @@ -0,0 +1 @@ +piqt_library(qcd_utils "Gui" "pip;qad_utils;qad_widgets;qad_graphic;cd_utils;piqt") diff --git a/libs/qcd_utils/qcd_core.cpp b/libs/qcd_utils/qcd_core.cpp new file mode 100644 index 0000000..95511a8 --- /dev/null +++ b/libs/qcd_utils/qcd_core.cpp @@ -0,0 +1,297 @@ +#include "qcd_core.h" +#include "cdutils_k.h" +#include "cdutils_core.h" +#include "piqt.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace CDUtils; + + +int __QCore_Initializer__::count_(0); +QCDCore * __QCore_Initializer__::__instance__(0); + + +__QCore_Initializer__::__QCore_Initializer__() { + count_++; + if (count_ > 1) return; + __instance__ = new QCDCore(); +} + + +__QCore_Initializer__::~__QCore_Initializer__() { + count_--; + if (count_ > 0) return; + if (__instance__ != 0) { + delete __instance__; + __instance__ = 0; + } +} + + + + +QCDCore::QCDCore() { + setObjectName("QCDCore"); + setName("QCDCore"); + CONNECTU(&K, changedGlobal, this, K_ChangedGlobal); + updating = direct_on = false; +} + + +QCDCore::~QCDCore() { +} + + +void QCDCore::K_ChangedGlobal() { + QMetaObject::invokeMethod(this, "updateBindedWidgets", Qt::QueuedConnection); +} + + +void QCDCore::slotBool(bool v) { + QWidget * w = (QWidget*)sender(); + if (!w || updating) return; + QList > pathes = binded_widgets.values(w); + foreach (const PIDeque & path, pathes) + K[path].setValue(PIString::fromBool(v)); + K.calculate(); + emit updateViewRequest(); +} + + +void QCDCore::slotInt(int v) { + QWidget * w = (QWidget*)sender(); + if (!w || updating) return; + QList > pathes = binded_widgets.values(w); + foreach (const PIDeque & path, pathes) + K[path].setValue(PIString::fromNumber(v)); + finishEdit(pathes); +} + + +void QCDCore::slotDouble(double v) { + QWidget * w = (QWidget*)sender(); + if (!w || updating) return; + QList > pathes = binded_widgets.values(w); + foreach (const PIDeque & path, pathes) + K[path].setValue(PIString::fromNumber(v)); + finishEdit(pathes); +} + + +void QCDCore::slotText(QString v) { + QWidget * w = (QWidget*)sender(); + if (!w || updating) return; + QList > pathes = binded_widgets.values(w); + foreach (const PIDeque & path, pathes) + K[path].setValue(Q2PIString(v)); + finishEdit(pathes); +} + + +void QCDCore::slotVariant(QVariant v) { + QWidget * w = (QWidget*)sender(); + if (!w || updating) return; + QList > pathes = binded_widgets.values(w); + foreach (const PIDeque & path, pathes) + K[path].setVariantValue(Q2PIVariant(v)); + finishEdit(pathes); +} + + +void QCDCore::slotDestroyed(QObject * o) { + if (!o) return; + if (!binded_widgets.contains((QWidget*)o)) return; + binded_widgets.remove((QWidget*)o); +} + + +int QCDCore::bindWindow(QWidget * wnd) { + if (!wnd) return 0; + //K.root().makePath(); + return bindWidgets(wnd->findChildren()); +} + + +int QCDCore::bindWidgets(QList wl) { + int ret = 0; + foreach (QWidget * w, wl) + if (bindWidget(w)) ++ret; + return ret; +} + + +bool QCDCore::bindWidget(QWidget * w) { + if (!w) return false; + QString on = w->objectName(); + QString cn = w->metaObject()->className(); + if (cn == "CDView") { + bindView(w); + return false; + } + PIVector ak = K.root().children(); + piForeachC (CDType * k, ak) { + if (!on.endsWith(PI2QString(k->pathString().join("_")))) continue; + if (bindWidget(w, *k)) return true; + } + return false; +} + + +bool QCDCore::bindWidget(QWidget * w, const CDType & k) { + if (!w) return false; + //piCout << "bind..." << k.name() << k.path(); + QString cn = w->metaObject()->className(); + bool ok = false; + if (cn == "QCheckBox" || cn == "QGroupBox") { + connect(w, SIGNAL(toggled(bool)), this, SLOT(slotBool(bool)), Qt::UniqueConnection); + ok = true; + } + if (cn == "QSpinBox" || cn == "QSlider" || cn == "QScrollBar") { + connect(w, SIGNAL(valueChanged(int)), this, SLOT(slotInt(int)), Qt::UniqueConnection); + ok = true; + } + if (cn == "QDoubleSpinBox" || cn == "SpinSlider" || cn == "EvalSpinBox") { + connect(w, SIGNAL(valueChanged(double)), this, SLOT(slotDouble(double)), Qt::UniqueConnection); + ok = true; + } + if (cn == "QLineEdit" || cn == "CLineEdit") { + connect(w, SIGNAL(textChanged(QString)), this, SLOT(slotText(QString)), Qt::UniqueConnection); + ok = true; + } + if (cn == "QVariantEdit") { + connect(w, SIGNAL(valueChanged(QVariant)), this, SLOT(slotVariant(QVariant)), Qt::UniqueConnection); + ok = true; + } + if (cn == "CDView") { + bindView(w); + } + connect(w, SIGNAL(destroyed(QObject*)), this, SLOT(slotDestroyed(QObject*)), Qt::UniqueConnection); + setWidgetValue(w, k); + if (!ok) return false; + //piCout << k.name() << k.path() << "ok"; + binded_widgets.insert(w, k.path()); + return true; +} + + +void QCDCore::updateBindedWidgets() { + QMapIterator > it(binded_widgets); + QWidgetList to_remove; + updating = true; + while (it.hasNext()) { + QWidget * w = it.next().key(); + if (!K.exists(it.value())) + to_remove << w; + else + setWidgetValue(w, K[it.value()]); + } + foreach (QWidget * w, to_remove) + unbindWidget(w); + updating = false; +} + + +void QCDCore::bindView(QWidget * v) { + CDView * w = qobject_cast(v); + if (!w) return; + connect(this, SIGNAL(updateViewRequest()), w, SLOT(refreshValues()), Qt::UniqueConnection); +} + + +void QCDCore::setWidgetValue(QWidget * w, const CDType & k) { + if (!w) return; + QString cn = w->metaObject()->className(); + if (cn == "QCheckBox") qobject_cast(w)->setChecked(k.toBool()); + if (cn == "QGroupBox") qobject_cast(w)->setChecked(k.toBool()); + if (cn == "QSpinBox") qobject_cast(w)->setValue(k.toInt()); + if (cn == "QSlider") qobject_cast(w)->setValue(k.toInt()); + if (cn == "QScrollBar") qobject_cast(w)->setValue(k.toInt()); + if (cn == "QDoubleSpinBox") qobject_cast(w)->setValue(k.toDouble()); + if (cn == "SpinSlider") qobject_cast(w)->setValue(k.toDouble()); + if (cn == "QLineEdit") qobject_cast(w)->setText(PI2QString(k.value())); + if (cn == "CLineEdit") qobject_cast(w)->setText(PI2QString(k.value())); + if (cn == "EvalSpinBox") qobject_cast(w)->setValue(k.toDouble()); + if (cn == "QVariantEdit") qobject_cast(w)->setValue(PI2QVariant(k.variantValue())); +} + + +void QCDCore::finishEdit(const QList > & pathes) { + K.calculate(); + if (direct_on) { + foreach (const PIDeque & path, pathes) + K.directChange(K[path]); + } + emit updateViewRequest(); +} + + +int QCDCore::unbindWindow(QWidget * wnd) { + if (!wnd) return 0; + return unbindWidgets(wnd->findChildren()); +} + + +int QCDCore::unbindWidgets(QList wl) { + int ret = 0; + foreach (QWidget * w, wl) + if (unbindWidget(w)) ++ret; + return ret; +} + + +bool QCDCore::unbindWidget(QWidget * w) { + if (!w) return false; + //qDebug() << "unbind" << w; + if (!binded_widgets.contains(w)) return false; + QString cn = w->metaObject()->className(); + if (cn == "QCheckBox" || cn == "QGroupBox") + disconnect(w, SIGNAL(toggled(bool)), this, SLOT(slotBool(bool))); + if (cn == "QSpinBox" || cn == "QSlider" || cn == "QScrollBar") + disconnect(w, SIGNAL(valueChanged(int)), this, SLOT(slotInt(int))); + if (cn == "QDoubleSpinBox" || cn == "SpinSlider" || cn == "EvalSpinBox") + disconnect(w, SIGNAL(valueChanged(double)), this, SLOT(slotDouble(double))); + if (cn == "QLineEdit" || cn == "CLineEdit") + disconnect(w, SIGNAL(textChanged(QString)), this, SLOT(slotText(QString))); + if (cn == "QVariantEdit") + disconnect(w, SIGNAL(valueChanged(QVariant)), this, SLOT(slotVariant(QVariant))); + //qDebug() << "remove b" << binded_widgets.size(); + binded_widgets.remove(w); + //qDebug() << "remove a" << binded_widgets.size(); + return true; +} + + +void QCDCore::unbindAllWidgets() { + QMap > bwm = binded_widgets; + QMapIterator > it(bwm); + while (it.hasNext()) { + QWidget * w = it.next().key(); + unbindWidget(w); + } + binded_widgets.clear(); +} + + +void QCDCore::updateBindedWidget(const CDType & k_) { + QMapIterator > it(binded_widgets); + updating = true; + while (it.hasNext()) { + QWidget * w = it.next().key(); + const CDType & k(K[it.value()]); + if (k.path() != k_.path()) continue; + setWidgetValue(w, k); + } + updating = false; +} diff --git a/libs/qcd_utils/qcd_core.h b/libs/qcd_utils/qcd_core.h new file mode 100644 index 0000000..64695ff --- /dev/null +++ b/libs/qcd_utils/qcd_core.h @@ -0,0 +1,97 @@ +/* + QCD Utils - Qt bindings/utilites for CD Utils + + 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 . +*/ + +#ifndef QCD_CORE_H +#define QCD_CORE_H + +#include +#include +#include +#include "piobject.h" +#include "cdutils_types.h" +#include "qcd_utils_export.h" + + +class QCDCore; + + +class QCD_UTILS_EXPORT __QCore_Initializer__ { +public: + __QCore_Initializer__(); + ~__QCore_Initializer__(); + static int count_; + static QCDCore * __instance__; +}; + + +class QCD_UTILS_EXPORT QCDCore: public QObject, public PIObject +{ + Q_OBJECT + PIOBJECT(QCDCore) + friend class __QCore_Initializer__; +public: + static QCDCore * instance() {return __QCore_Initializer__::__instance__;} + + int bindWindow(QWidget * wnd); + int bindWidgets(QList wl); + bool bindWidget(QWidget * w); + bool bindWidget(QWidget * w, const CDUtils::CDType & k); + + int unbindWindow(QWidget * wnd); + int unbindWidgets(QList wl); + bool unbindWidget(QWidget * w); + void unbindAllWidgets(); + + void updateBindedWidget(const CDUtils::CDType & k_); + void setDirectKEnabled(bool yes) {direct_on = yes;} + bool isDirectKEnabled() const {return direct_on;} + +private: + QCDCore(); + ~QCDCore(); + + void bindView(QWidget * v); + void setWidgetValue(QWidget * w, const CDUtils::CDType & k); + void finishEdit(const QList > & pathes); + EVENT_HANDLER(void, K_ChangedGlobal); + + QMultiMap > binded_widgets; + bool updating, direct_on; + +private slots: + void slotBool(bool v); + void slotInt(int v); + void slotDouble(double v); + void slotText(QString v); + void slotVariant(QVariant v); + void slotDestroyed(QObject * ); + +public slots: + void updateBindedWidgets(); + +signals: + void updateViewRequest(); + +}; + + +static __QCore_Initializer__ __QCore_initializer__; + + +#endif // QCD_CORE_H diff --git a/libs/qcd_utils/qcd_graphic.cpp b/libs/qcd_utils/qcd_graphic.cpp new file mode 100644 index 0000000..c53a9ae --- /dev/null +++ b/libs/qcd_utils/qcd_graphic.cpp @@ -0,0 +1,40 @@ +#include "qcd_graphic.h" +#include "ui_qcd_graphic.h" +#include "cdutils_core.h" +#include "cdutils_x.h" +#include "graphic.h" +#include "piqt.h" + +using namespace CDUtils; + + +CDGraphicWidget::CDGraphicWidget(QWidget * p): QWidget(p) { + ui = new Ui::CDGraphicWidget(); + ui->setupUi(this); + ui->graphic->setGraphicsCount(0); +} + + +Graphic * CDGraphicWidget::graphic() const { + return ui->graphic; +} + + +void CDGraphicWidget::setConfigVisible(bool on) { + ui->widgetConfig->setVisible(on); +} + + +bool CDGraphicWidget::isConfigVisible() const { + return ui->widgetConfig->isVisible(); +} + + +EvalSpinBox * CDGraphicWidget::evalSpinBoxHistory() { + return ui->evalHistory; +} + + +EvalSpinBox * CDGraphicWidget::evalSpinBoxVisible() { + return ui->evalVisible; +} diff --git a/libs/qcd_utils/qcd_graphic.h b/libs/qcd_utils/qcd_graphic.h new file mode 100644 index 0000000..68b7fd8 --- /dev/null +++ b/libs/qcd_utils/qcd_graphic.h @@ -0,0 +1,67 @@ +/* + QCD Utils - Qt bindings/utilites for CD Utils + + 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 . +*/ + +#ifndef QCD_GRAPHIC_H +#define QCD_GRAPHIC_H + +#include +#include +#include +#include "qcd_utils_export.h" + +namespace CDUtils { + class CDType; + class CDSection; +} + +namespace Ui { + class CDGraphicWidget; +} + +class Graphic; +class Graphic; + + +class QCD_UTILS_EXPORT CDGraphicWidget: public QWidget { + Q_OBJECT + friend class CDGraphics; + friend class GDockWidget; +public: + CDGraphicWidget(QWidget * p = 0); + + Graphic * graphic() const; + bool isConfigVisible() const; + + EvalSpinBox * evalSpinBoxHistory(); + EvalSpinBox * evalSpinBoxVisible(); + +public slots: + void setConfigVisible(bool on); + +private: + Ui::CDGraphicWidget * ui; + +private slots: + +signals: + +}; + + +#endif // QCD_GRAPHIC_H diff --git a/libs/qcd_utils/qcd_graphic.ui b/libs/qcd_utils/qcd_graphic.ui new file mode 100644 index 0000000..658977d --- /dev/null +++ b/libs/qcd_utils/qcd_graphic.ui @@ -0,0 +1,169 @@ + + + CDGraphicWidget + + + + 0 + 0 + 470 + 380 + + + + CD Pult + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Graphic::Autofit|Graphic::BorderInputs|Graphic::Clear|Graphic::Configure|Graphic::CursorAxis|Graphic::Fullscreen|Graphic::Legend|Graphic::Pause|Graphic::Save + + + false + + + false + + + 100.000000000000000 + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + History: + + + + + + + 100.000000000000000 + + + + + + + Qt::Horizontal + + + + 1 + 20 + + + + + + + + Visible: + + + + + + + -1.000000000000000 + + + + + + + Qt::Horizontal + + + + 1 + 20 + + + + + + + + + + + + Graphic + QFrame +
graphic.h
+
+ + EvalSpinBox + QWidget +
evalspinbox.h
+
+
+ + + + evalHistory + valueChanged(double) + graphic + setHistorySize(double) + + + 148 + 363 + + + 156 + 297 + + + + + evalVisible + valueChanged(double) + graphic + setMaxVisibleTime(double) + + + 345 + 361 + + + 342 + 337 + + + + +
diff --git a/libs/qcd_utils/qcd_modedialog.cpp b/libs/qcd_utils/qcd_modedialog.cpp new file mode 100644 index 0000000..c6e2bb6 --- /dev/null +++ b/libs/qcd_utils/qcd_modedialog.cpp @@ -0,0 +1,46 @@ +#include "qcd_modedialog.h" +#include "ui_qcd_modedialog.h" + + +QCDModeDialog::QCDModeDialog(QWidget * parent): QDialog(parent) { + ui = new Ui::QCDModeDialog(); + ui->setupUi(this); +} + + +QCDModeDialog::~QCDModeDialog() { + delete ui; +} + + +CDUtils::UpdateModeFlags QCDModeDialog::mode() const { + CDUtils::UpdateModeFlags ret = 0; + if (ui->checkSaveIndex->isChecked()) ret |= CDUtils::SaveByIndex; + if (ui->checkSaveName->isChecked()) ret |= CDUtils::SaveByName; + if (ui->checkMerge->isChecked()) ret |= CDUtils::Merge; + return ret; +} + + +void QCDModeDialog::changeEvent(QEvent *e) { + QDialog::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } +} + + +void QCDModeDialog::on_checkSaveIndex_clicked(bool checked) { + if (!checked) return; + ui->checkSaveName->setChecked(false); +} + + +void QCDModeDialog::on_checkSaveName_clicked(bool checked) { + if (!checked) return; + ui->checkSaveIndex->setChecked(false); +} diff --git a/libs/qcd_utils/qcd_modedialog.h b/libs/qcd_utils/qcd_modedialog.h new file mode 100644 index 0000000..dc57713 --- /dev/null +++ b/libs/qcd_utils/qcd_modedialog.h @@ -0,0 +1,51 @@ +/* + QCD Utils - Qt bindings/utilites for CD Utils + + 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 . +*/ + +#ifndef QCD_MODEDIALOG_H +#define QCD_MODEDIALOG_H + +#include +#include +#include "qcd_utils_export.h" + +namespace Ui { + class QCDModeDialog; +} + +class QCD_UTILS_EXPORT QCDModeDialog: public QDialog +{ + Q_OBJECT +public: + explicit QCDModeDialog(QWidget * parent = 0); + ~QCDModeDialog(); + + CDUtils::UpdateModeFlags mode() const; + +protected: + void changeEvent(QEvent *e); + + Ui::QCDModeDialog * ui; + +private slots: + void on_checkSaveIndex_clicked(bool checked); + void on_checkSaveName_clicked(bool checked); + +}; + +#endif // QCD_MODEDIALOG_H diff --git a/libs/qcd_utils/qcd_modedialog.ui b/libs/qcd_utils/qcd_modedialog.ui new file mode 100644 index 0000000..38c2dff --- /dev/null +++ b/libs/qcd_utils/qcd_modedialog.ui @@ -0,0 +1,98 @@ + + + QCDModeDialog + + + + 0 + 0 + 251 + 152 + + + + Update description mode + + + + + + Save by index + + + + + + + Save by name + + + + + + + Merge + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + QCDModeDialog + accept() + + + 106 + 131 + + + 101 + 146 + + + + + buttonBox + rejected() + QCDModeDialog + reject() + + + 182 + 127 + + + 169 + 146 + + + + + diff --git a/libs/qcd_utils/qcd_model.cpp b/libs/qcd_utils/qcd_model.cpp new file mode 100644 index 0000000..2b1f203 --- /dev/null +++ b/libs/qcd_utils/qcd_model.cpp @@ -0,0 +1,460 @@ +#include "qcd_model.h" +#include "cdutils_interface.h" +#include "cdutils_core.h" +#include "cdutils_x.h" +#include "piqt.h" +#include +#include +#include +#include +#include "qvariantedit.h" +#include "qad_types.h" + + +using namespace CDUtils; + +// CDKItem + +CDItem::CDItem(CDUtils::Interface * i, int _index, CDItem::CDItemType type, CDItem *parent) { + interface = i; + index_ = _index; + parent_ = parent; + type_ = type; + item_count = 0; + expanded = true; +} + + +CDItem::~CDItem() { + qDeleteAll(childs); +} + + +QVariant CDItem::data(int column, int role) const { + if (role == Qt::BackgroundRole) { + switch (type_) { + case ItemCDType: { + CDType & t(interface->section(buildPath())[index_]); + if (t.errorString().isEmpty()) return QBrush(QColor(255, 250, 230)); + else return QBrush(QColor(255, 128, 128)); + } + case ItemCDSection: return QBrush(QColor(230, 250, 230)); + } + } + if (role == Qt::CheckStateRole && type_ == ItemCDType) { + CDType & t(interface->section(buildPath())[index_]); + if (column == cValue && t.cd_type() == CDType::cdK) { + if (t.type() == "b") return t.toBool() ? Qt::Checked : Qt::Unchecked; + else QVariant(); + } + if (column == cName_Cmd && t.cd_type() == CDType::cdX) { + return t.isSelectedX() ? Qt::Checked : Qt::Unchecked; + } + } + if (role == Qt::ToolTipRole && type_ == ItemCDType) { + CDType & t(interface->section(buildPath())[index_]); + return PI2QString(t.errorString()); + } + if (role != Qt::DisplayRole && role != Qt::EditRole) return QVariant(); + PIDeque path = buildPath(); + CDSection & rs = interface->section(path); + CDSection s; + switch (type_) { + case ItemCDType: + switch (column) { + case cID: return QString::number(index_); + case cName_Cmd: return PI2QString(rs[index_].name()); + case cType: return stringType(rs[index_].type()); + case cXMode: return QVariant::fromValue(xModeEnum(rs[index_].xmode())); + case cXAvg: return rs[index_].avg(); + case cExpression: return PI2QString(rs[index_].formula()); + case cValue: return value(rs[index_], role); + case cComment: return PI2QString(rs[index_].comment()); + default: break; + } + break; + case ItemCDSection: + s = rs.section(index_); +// piCout << rs.name << rs.alias << s.name << s.alias; + switch (column) { + case cID: return QString("[") + QString::number(index_) + QString("]"); + case cName_Cmd: return PI2QString(s.alias); + case cType: return PI2QString(s.name); + default: break; + } + break; + } + return QVariant(); +} + + +QVariant CDItem::value(CDType & t, int role) const { + if (t.type() == "f") return t.toDouble(); + if (t.type() == "n") return t.toInt(); + if (t.type() == "b") return t.toBool(); + if (t.type() == "e") { + QAD::Enum et = PI2QADEnum(t.enumValues()); + et.selectValue(t.toInt()); + if (role == Qt::EditRole) return QVariant::fromValue(et); + else return et.selectedName(); + } + return PI2QString(t.value()); +} + + +bool CDItem::setData(int column, const QVariant & value) { + if (type_ == ItemCDType) { + CDType & t(interface->section(buildPath())[index_]); + if ((column == cExpression || column == cValue) && (t.cd_type() == CDType::cdK)) { + interface->section(buildPath())[index_].setValue(Q2PIString(value.toString())); + interface->calculate(); + return true; + } + if (t.cd_type() == CDType::cdX) { + switch (column) { + case cName_Cmd: + X.setEnabled(t, value.toBool()); + return true; + case cXMode: + t.setXMode((CDType::XMode)value.toInt()); + return true; + case cXAvg: + t.setAvg(piMax(value.toInt(), 1)); + return true; + default: break; + } + } + } + return false; +} + + +PIDeque CDItem::buildPath() const { + PIDeque path; + CDItem * p = parent_; + while (p) { + path.push_front(p->index_); + p = p->parent_; + } + path.take_front(); + return path; +} + + +QString CDItem::stringType(const PIString & t) const { + QString n = PI2QString(t); + if (n.isEmpty()) return QString(""); + switch (n[0].toLatin1()) { + case 'l': return QString("list"); break; + case 'b': return QString("bool"); break; + case 'n': return QString("int"); break; + case 'f': return QString("double"); break; + case 'c': return QString("color"); break; + case 'r': return QString("rect"); break; + case 'a': return QString("rect"); break; + case 'p': return QString("point"); break; + case 'v': return QString("vector"); break; + case 'i': return QString("IP"); break; + case 'e': return QString("enum"); break; + case 'F': return QString("file"); break; + case 'D': return QString("dir"); break; + } + return QString("string"); +} + + +QAD::Enum CDItem::xModeEnum(int v) const { + QAD::Enum ret; + ret << QAD::Enumerator(CDType::X_Current, "Current") + << QAD::Enumerator(CDType::X_All_Avg, "All, Averaging"); + ret.selectValue(v); + return ret; +} + + +// CDKDelegate + +CDDelegate::CDDelegate(QObject *parent) : QStyledItemDelegate(parent) { +} + + +void CDDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { + CDItem * item = ((CDItemModel*)index.model())->getItem(index); + if (item) { + if (item->itemType() == CDItem::ItemCDType && item->interface->cdType() == CDType::cdC) { + QStyleOptionButton bo; + bo.direction = option.direction; + bo.fontMetrics = option.fontMetrics; + bo.palette = option.palette; + bo.rect = option.rect; + bo.state = option.state;// & ~(QStyle::State_HasFocus | QStyle::State_MouseOver); + bo.text = item->data(1, Qt::DisplayRole).toString(); + QWidget * v = (QWidget*)(painter->device()); + if (v) { + QPoint cp = v->mapFromGlobal(QCursor::pos()); + if (bo.rect.contains(cp, true)) { + //bo.state |= QStyle::State_MouseOver; + if (qApp->mouseButtons().testFlag(Qt::LeftButton)) + bo.state |= QStyle::State_On; + } + } + qApp->style()->drawControl(QStyle::CE_PushButton, &bo, painter); + return; + } + } + QStyledItemDelegate::paint(painter, option, index); + +} + + +QWidget * CDDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { + return new QVariantEdit(parent); +} + + +void CDDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { + QVariantEdit *edit = static_cast(editor); + edit->setValue(index.model()->data(index, Qt::EditRole)); +} + + +void CDDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { + QVariantEdit *edit = static_cast(editor); + QVariant v = edit->value(); + if (v.canConvert()) { + QAD::Enum et = v.value(); + model->setData(index, et.selectedValue(), Qt::EditRole); + } else model->setData(index, v, Qt::EditRole); +} + + +void CDDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { + editor->setGeometry(option.rect); +} + + +QSize CDDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { + QSize s = QStyledItemDelegate::sizeHint(option, index); + s.setWidth(s.width() + 20); + return s; +} + + +// CDItemModel + +CDItemModel::CDItemModel(int type_, QObject *parent) : QAbstractItemModel(parent) { + interface = new Interface((CDType::cdT)type_); + root = 0; + internalRebuild(); +} + + +CDItemModel::~CDItemModel() { + delete root; + delete interface; +} + + +QVariant CDItemModel::data(const QModelIndex &index, int role) const { + if (!index.isValid()) return QVariant(); + CDItem * item = getItem(index); + return item->data(index.column(), role); +} + + +QVariant CDItemModel::headerData(int section, Qt::Orientation orientation, int role) const { + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + switch (section) { + case cID: return tr("Index"); + case cName_Cmd: return interface->cdType() == CDType::cdC ? tr("Command") : tr("Name"); + case cType: return tr("Type"); + case cXMode: return tr("Mode"); + case cXAvg: return tr("Averaging"); + case cExpression: return tr("Expression"); + case cValue: return tr("Value"); + case cComment: return tr("Comment"); + } + } + return QVariant(); +} + + +QModelIndex CDItemModel::index(int row, int column, const QModelIndex &parent) const { + if (parent.isValid() && parent.column() != cID) return QModelIndex(); + CDItem * p = getItem(parent); + CDItem * c = p->childs.value(row, 0); + if (c) return createIndex(row, column, c); + else return QModelIndex(); +} + + +QModelIndex CDItemModel::parent(const QModelIndex &index) const { + if (!index.isValid()) return QModelIndex(); + CDItem * c = getItem(index); + CDItem * p = c->parent_; + if (p == root) return QModelIndex(); + return createIndex(p->parent_->childs.indexOf(p), cID, p); +} + + +int CDItemModel::rowCount(const QModelIndex &parent) const { + CDItem * p = getItem(parent); + return p->childs.count(); +} + + +int CDItemModel::columnCount(const QModelIndex &parent) const { + return cLastColumn; +} + + +Qt::ItemFlags CDItemModel::flags(const QModelIndex & index) const { + if (!index.isValid()) return Qt::ItemFlags(); + Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + CDItem * item = getItem(index); + if (!item) return Qt::ItemFlags(); + if (item->type_ == CDItem::ItemCDType) { + CDType & t(interface->section(item->buildPath())[item->index_]); + if (t.cd_type() == CDType::cdK) { + if (index.column() == cExpression || index.column() == cValue) + f |= Qt::ItemIsEditable; + if (index.column() == cValue && t.type() == "b") + f |= Qt::ItemIsUserCheckable; + if (index.column() == cName_Cmd) + f |= Qt::ItemIsDragEnabled; + } + if (t.cd_type() == CDType::cdX) { + if (index.column() == cXMode || index.column() == cXAvg) + f |= Qt::ItemIsEditable; + if (index.column() == cName_Cmd) + f |= Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled; + } + } + return f; +} + + +bool CDItemModel::setData(const QModelIndex & index, const QVariant & value, int role) { + if (role == Qt::CheckStateRole && (index.column() == cName_Cmd || index.column() == cValue)) { + CDItem * item = getItem(index); + if (item->type_ == CDItem::ItemCDType) { + CDType & t(interface->section(item->buildPath())[item->index_]); + if (index.column() == cValue && (t.cd_type() == CDType::cdK)) { + if (t.type() == "b") { + bool result = item->setData(index.column(), PI2QString(PIString::fromBool(value.toBool()))); + QModelIndex rin(CDItemModel::index(index.row(), cExpression, index.parent())); + emit dataChanged(rin, rin); + return result; + } + } + if (index.column() == cName_Cmd && (t.cd_type() == CDType::cdX)) { + bool result = item->setData(index.column(), value); + //QModelIndex rin(CDItemModel::index(index.row(), 1, index.parent())); + //emit dataChanged(rin, rin); + return result; + } + } + } + if (role != Qt::EditRole) return false; + CDItem * item = getItem(index); + bool result = item->setData(index.column(), value); + if (result) { + QModelIndex rin(CDItemModel::index(index.row(), cExpression, index.parent())); + emit dataChanged(rin, rin); + emit dataChanged(index, index); + } + return result; +} + + +QMimeData * CDItemModel::mimeData(const QModelIndexList & indexes) const { + if (indexes.size() == 1) { + QModelIndex index = indexes[0]; + if (index.isValid()/* && interface->cdType() == CDType::cdX*/) { + CDItem * item = getItem(index); + if (item) { + CDType & t(interface->section(item->buildPath())[item->index_]); + QMimeData * mime = new QMimeData(); + mime->setText(PI2QString(CDCore::instance()->typeLetter(interface->cdType()) + + CDCore::pathToString(t.path()))); + return mime; + } + } + } + return QAbstractItemModel::mimeData(indexes); +} + + +void CDItemModel::rebuildModel() { + beginResetModel(); + internalRebuild(); + endResetModel(); +} + + +void CDItemModel::buildItem(CDItem * it, CDSection & r) { + //piCout << "build item" << r.name << r.alias; + auto i = r.cd.makeIterator(); + while (i.next()) { + it->childs << new CDItem(interface, i.key(), CDItem::ItemCDType, it); + } + it->item_count = it->childs.size(); + auto j = r.s.makeIterator(); + while (j.next()) { + it->childs << new CDItem(interface, j.key(), CDItem::ItemCDSection, it); + buildItem(it->childs.back(), j.valueRef()); + } +} + + +void CDItemModel::updateModel() { + beginResetModel(); + endResetModel(); +} + + +void CDItemModel::internalRebuild() { + //qDebug() << "[CDKItemModel]" << "internalRebuild()"; + if (root) delete root; + root = new CDItem(interface, 0, CDItem::ItemCDSection, 0); + CDSection & r = interface->root(); + buildItem(root, r); +} + + +CDItem * CDItemModel::getItem(const QModelIndex &index) const { + if (index.isValid()) { + CDItem * item = static_cast(index.internalPointer()); + if (item) return item; + } + return root; +} + + +QModelIndex CDItemModel::indexByPath(const PIDeque & path, int column) const { + if (path.isEmpty()) return QModelIndex(); + CDItem * item = root; + //piCout << path << "..."; + bool ok = false; + for (int i = 0; i < path.size_s() - 1; ++i) { + ok = false; + foreach (CDItem * j, item->childs) + if (j->type_ == CDItem::ItemCDSection && j->index_ == path[i]) { + item = j; + ok = true; + break; + } + if (!ok) return QModelIndex(); + } + ok = false; + foreach (CDItem * j, item->childs) + if (j->type_ == CDItem::ItemCDType && j->index_ == path.back()) { + item = j; + ok = true; + break; + } + if (!ok || !item->parent_) return QModelIndex(); + QModelIndex ret = createIndex(item->parent_->childs.indexOf(item), column, item); + //piCout << path << Q2PIString(item->data(cName_Cmd, Qt::DisplayRole).toString()) << getItem(ret)->buildPath(); + return ret; +} diff --git a/libs/qcd_utils/qcd_model.h b/libs/qcd_utils/qcd_model.h new file mode 100644 index 0000000..506f0f0 --- /dev/null +++ b/libs/qcd_utils/qcd_model.h @@ -0,0 +1,133 @@ +/* + QCD Utils - Qt bindings/utilites for CD Utils + + 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 . +*/ + +#ifndef QCD_MODEL_H +#define QCD_MODEL_H + +#include +#include +#include +#include "pistring.h" +#include "qcd_utils_export.h" + +namespace CDUtils { + class CDType; + class CDSection; + class Interface; + + enum Column { + cID , + cName_Cmd , + cType , + cXMode , + cXAvg , + cExpression, + cValue , + cComment , + cLastColumn, + }; +} + +namespace QAD { + struct Enum; +} + +class CDItemModel; + + +class QCD_UTILS_EXPORT CDItem { + friend class CDItemModel; + friend class CDView; +public: + enum CDItemType{ItemCDType, ItemCDSection}; + CDItem(CDUtils::Interface * interface, int _index, CDItemType type, CDItem * parent); + ~CDItem(); + QVariant data(int column, int role) const; + QVariant value(CDUtils::CDType & t, int role) const; + bool setData(int column, const QVariant & value); + CDItemType itemType() const {return type_;} + PIDeque buildPath() const; + int index() const {return index_;} + + CDUtils::Interface * interface; + bool expanded; + +private: + QString stringType(const PIString & t) const; + QAD::Enum xModeEnum(int v) const; + + CDItem * parent_; + int index_, item_count; + CDItemType type_; + QList childs; +}; + + +class QCD_UTILS_EXPORT CDDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + CDDelegate(QObject *parent = 0); + + void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; + QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; + void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + +}; + + +class QCD_UTILS_EXPORT CDItemModel : public QAbstractItemModel { + Q_OBJECT + friend class CDView; +public: + explicit CDItemModel(int type_, QObject *parent = 0); + ~CDItemModel(); + + QVariant data(const QModelIndex & index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + QMimeData * mimeData(const QModelIndexList & indexes) const; + CDItem * getItem(const QModelIndex & index) const; + QModelIndex indexByPath(const PIDeque & path, int column = CDUtils::cID) const; + + void buildItem(CDItem * it, CDUtils::CDSection &r); + +public slots: + void rebuildModel(); + void updateModel(); + +private: + void internalRebuild(); + + CDUtils::Interface * interface; + CDItem * root; + +signals: + +}; + +#endif // QCD_MODEL_H diff --git a/libs/qcd_utils/qcd_view.cpp b/libs/qcd_utils/qcd_view.cpp new file mode 100644 index 0000000..619c46e --- /dev/null +++ b/libs/qcd_utils/qcd_view.cpp @@ -0,0 +1,371 @@ +#include +#include +#include +#include "cdutils_k.h" +#include "cdutils_x.h" +#include "cdutils_c.h" +#include "cdutils_m.h" +#include "cdutils_core.h" +#include "qcd_view.h" +#include "qcd_model.h" +#include "piqt.h" +#include "pifile.h" + +using namespace CDUtils; + + +CDView::CDView(QWidget * parent) : QTreeView(parent) { + type_ = -1; + model_ = 0; + proxy_ = 0; + connect(this, SIGNAL(clicked(QModelIndex)), this, SLOT(indexClicked(QModelIndex))); + connect(this, SIGNAL(_qcd_sendFailed()), this, SLOT(cd_sendFailed()), Qt::QueuedConnection); + connect(this, SIGNAL(_qcd_sendSucceed()), this, SLOT(cd_sendSucceed()), Qt::QueuedConnection); + connect(this, SIGNAL(_qcd_receiveFailed()), this, SLOT(cd_receiveFailed()), Qt::QueuedConnection); + connect(this, SIGNAL(_qcd_receiveSucceed()), this, SLOT(cd_receiveSucceed()), Qt::QueuedConnection); + connect(this, SIGNAL(_qcd_receivedX()), this, SLOT(cd_receivedX()), Qt::QueuedConnection); + connect(this, SIGNAL(_qcd_changedGlobal()), this, SLOT(cd_changedGlobal()), Qt::QueuedConnection); +} + + +CDView::~CDView() { + if (model_) { + delete model_; + delete proxy_; + } + model_ = 0; + proxy_ = 0; +} + + +void CDView::setType(int cdt) { + if (cdt < 0) return; + if (type_ >= 0) return; + type_ = cdt; + switch ((CDType::cdT)type_) { + case CDType::cdK: + CONNECTU(&K, sended, this, pi_cd_sendSucceed); + CONNECTU(&K, sendFailed, this, pi_cd_sendFailed); + CONNECTU(&K, received, this, pi_cd_receiveSucceed); + CONNECTU(&K, receiveFailed, this, pi_cd_receiveFailed); + CONNECTU(&K, changedGlobal, this, pi_cd_changedGlobal); + break; + case CDType::cdX: + CONNECTU(&X, sended, this, pi_cd_sendSucceed); + CONNECTU(&X, sendFailed, this, pi_cd_sendFailed); + CONNECTU(&X, received, this, pi_cd_receiveSucceed); + CONNECTU(&X, receiveFailed, this, pi_cd_receiveFailed); + CONNECTU(&X, receivedX, this, pi_cd_receivedX); + CONNECTU(&X, changedGlobal, this, pi_cd_changedGlobal); + break; + case CDType::cdC: + CONNECTU(&C, sended, this, pi_cd_sendSucceed); + CONNECTU(&C, sendFailed, this, pi_cd_sendFailed); + CONNECTU(&C, received, this, pi_cd_receiveSucceed); + CONNECTU(&C, receiveFailed, this, pi_cd_receiveFailed); + CONNECTU(&C, changedGlobal, this, pi_cd_changedGlobal); + break; + case CDType::cdM: + CONNECTU(&M, sended, this, pi_cd_sendSucceed); + CONNECTU(&M, sendFailed, this, pi_cd_sendFailed); + CONNECTU(&M, received, this, pi_cd_receiveSucceed); + CONNECTU(&M, receiveFailed, this, pi_cd_receiveFailed); + CONNECTU(&M, changedGlobal, this, pi_cd_changedGlobal); + CONNECTU(&M, messageReceived, this, pi_cd_messageReceived); + break; + default: break; + } + +} + + +void CDView::mousePressEvent(QMouseEvent * e) { + if (type_ == CDType::cdC) { + QModelIndex i = indexAt(e->pos()); + if (i.isValid() && i.column() == cName_Cmd) + update(i); + } + QTreeView::mousePressEvent(e); +} + + +void CDView::mouseReleaseEvent(QMouseEvent * e) { + if (type_ == CDType::cdC) { + QModelIndex i = indexAt(e->pos()); + if (i.isValid() && i.column() == cName_Cmd) + update(i); + } + QTreeView::mouseReleaseEvent(e); +} + + +void CDView::currentChanged(const QModelIndex & cur, const QModelIndex & prev) { + if (type_ == CDType::cdC) { + if (prev.isValid() && prev.column() == cName_Cmd) + update(prev); + } + QTreeView::currentChanged(cur, prev); +} + + +void CDView::refresh() { + if (type_ < 0) return; + if (!model_) { + model_ = new CDItemModel(type_); + proxy_ = new QSortFilterProxyModel(); +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) + proxy_->setRecursiveFilteringEnabled(true); +#endif + proxy_->setFilterKeyColumn(-1); + proxy_->setFilterCaseSensitivity(Qt::CaseInsensitive); + proxy_->setSourceModel(model_); + setModel(proxy_); + setItemDelegateForColumn(type_ == CDType::cdC ? cName_Cmd : cValue, new CDDelegate()); + if (type_ == CDType::cdX) + setItemDelegateForColumn(cXMode, new CDDelegate()); + } + model_->rebuildModel(); + switch ((CDType::cdT)type_) { + case CDType::cdK: + setColumnHidden(cXMode, true); + setColumnHidden(cXAvg, true); + break; + case CDType::cdX: + setColumnHidden(cExpression, true); + break; + case CDType::cdC: + case CDType::cdM: + setColumnHidden(cType, true); + setColumnHidden(cXMode, true); + setColumnHidden(cXAvg, true); + setColumnHidden(cExpression, true); + setColumnHidden(cValue, true); + break; + default: break; + } + expandAll(); + for (int i = 0; i < model_->columnCount(); i++) resizeColumnToContents(i); +} + + +void CDView::refreshValues() { + if (!model_) return; + model_->dataChanged(model_->index(0, 0), model_->index(model_->columnCount() - 1, model_->rowCount() - 1)); +} + + +void CDView::setFile(const QString & filename) { + switch ((CDType::cdT)type_) { + case CDType::cdK: K.setFileName(Q2PIString(filename)); break; + case CDType::cdX: X.setFileName(Q2PIString(filename)); break; + case CDType::cdC: C.setFileName(Q2PIString(filename)); break; + case CDType::cdM: M.setFileName(Q2PIString(filename)); break; + default: break; + } +} + + +bool CDView::inProgress() const { + switch ((CDType::cdT)type_) { + case CDType::cdK: return K.inProgress(); break; + case CDType::cdX: return X.inProgress(); break; + case CDType::cdC: return C.inProgress(); break; + case CDType::cdM: return M.inProgress(); break; + default: break; + } + return false; +} + + +void CDView::startX(double freq) { + switch ((CDType::cdT)type_) { + case CDType::cdX: X.start(freq); break; + default: break; + } +} + + +CDSection * CDView::root() { + return CDCore::instance()->root((CDType::cdT)type_); +} + + +QString CDView::typeLetter() const { + return PI2QString(CDCore::instance()->typeLetter((CDType::cdT)type_)); +} + + +void CDView::send() { + busyStatusChanged(true); + switch ((CDType::cdT)type_) { + case CDType::cdK: K.send(); break; + case CDType::cdX: X.send(); break; + case CDType::cdC: C.send(); break; + case CDType::cdM: M.send(); break; + default: break; + } +} + + +void CDView::receive() { + busyStatusChanged(true); + switch ((CDType::cdT)type_) { + case CDType::cdK: K.request(); break; + case CDType::cdX: X.request(); break; + case CDType::cdC: C.request(); break; + case CDType::cdM: M.request(); break; + default: break; + } +} + + +void CDView::save() { + switch ((CDType::cdT)type_) { + case CDType::cdK: K.writeFile(); break; + case CDType::cdX: X.writeFile(); break; + case CDType::cdC: C.writeFile(); break; + case CDType::cdM: M.writeFile(); break; + default: break; + } +} + + +void CDView::load() { + switch ((CDType::cdT)type_) { + case CDType::cdK: + K.readFile(); + K.calculate(); + break; + case CDType::cdX: + X.readFile(); + X.calculate(); + break; + case CDType::cdC: + C.readFile(); + C.calculate(); + break; + case CDType::cdM: + M.readFile(); + M.calculate(); + break; + default: break; + } + refresh(); +} + + +void CDView::clear() { + //piCout << "clearK"; + switch ((CDType::cdT)type_) { + case CDType::cdK: K.root() = CDSection(); break; + case CDType::cdX: X.root() = CDSection(); break; + case CDType::cdC: C.root() = CDSection(); break; + case CDType::cdM: M.root() = CDSection(); break; + default: break; + } + refresh(); +} + + +void CDView::buildFromHeader(const QString & description, int mode) { + if (description.isEmpty()) return; + PIString desc_file = Q2PIString(QDir::current().relativeFilePath(description)); + PIFile f(desc_file, PIIODevice::ReadOnly); + switch ((CDType::cdT)type_) { + case CDType::cdK: K.update(&f, mode); break; + case CDType::cdX: X.update(&f, mode); break; + case CDType::cdC: C.update(&f, mode); break; + case CDType::cdM: M.update(&f, mode); break; + default: break; + } + refresh(); +} + + +void CDView::calculate() { + switch ((CDType::cdT)type_) { + case CDType::cdK: K.calculate(); break; + case CDType::cdX: X.calculate(); break; + case CDType::cdC: C.calculate(); break; + case CDType::cdM: M.calculate(); break; + default: break; + } +} + + +void CDView::filter(const QString & f) { + proxy_->setFilterRegExp(QRegExp(f, Qt::CaseInsensitive)); +} + + +void CDView::indexClicked(const QModelIndex & i) { + if (!model_ || !i.isValid() || type_ != CDType::cdC || i.column() != cName_Cmd) return; + CDItem * item = model_->getItem(i); + if (!item) return; + if (item->itemType() != CDItem::ItemCDType) return; + CDType & t(model_->interface->section(item->buildPath())[item->index()]); + C.sendCommand(t); + emit commandSended(PI2QString(t.pathString().join("."))); + //piCout << t; + qDebug() << PI2QString(t.pathString().join(".")); +} + + +void CDView::cd_sendFailed() { + busyStatusChanged(false); + emit messageStatus("send failed"); + emit sendFailed(); +} + + +void CDView::cd_sendSucceed() { + busyStatusChanged(false); + emit messageStatus("send success"); + emit sendSucceed(); +} + + +void CDView::cd_receiveFailed() { + busyStatusChanged(false); + emit messageStatus("receive failed"); + emit receiveFailed(); +} + + +void CDView::cd_receiveSucceed() { + refresh(); + busyStatusChanged(false); + emit messageStatus("receive success"); + emit receiveSucceed(); +} + + +void CDView::cd_receivedX() { + X.lock(); + PIVector > xl = X.enabledList(); + //piCout << "X" << xl.size(); + piForeachC (PIDeque & x, xl) { + CDType & t(X[x]); + //piCout << t; + //piCout << t.path(); + if (t.cd_type() != CDType::cdX) continue; + update(model_->indexByPath(t.path(), cValue)); + //piCout << CDCore::pathToString(t.path()) << t.toDouble() << "model"; + //qDebug() << "val" << model_->data(model_->indexByPath(t.path(), cValue), Qt::DisplayRole).toDouble(); + } + X.unlock(); + emit receivedX(); +} + + +void CDView::cd_changedGlobal() { + emit changedGlobal(); +} + + +void CDView::pi_cd_messageReceived(PIDeque path, int type, PIString msg) { + QMetaObject::invokeMethod(this, "messageReceived", Qt::QueuedConnection, + Q_ARG(QString, PI2QString(CDCore::pathToString(path))), + Q_ARG(int, type), + Q_ARG(QString, PI2QString(msg))); +} diff --git a/libs/qcd_utils/qcd_view.h b/libs/qcd_utils/qcd_view.h new file mode 100644 index 0000000..ff3d68a --- /dev/null +++ b/libs/qcd_utils/qcd_view.h @@ -0,0 +1,113 @@ +/* + QCD Utils - Qt bindings/utilites for CD Utils + + 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 . +*/ + +#ifndef QCD_VIEW_H +#define QCD_VIEW_H + +#include +#include "piobject.h" +#include "qcd_utils_export.h" + +namespace CDUtils { + class CDType; + class CDSection; +} + +class CDItemModel; +class QSortFilterProxyModel; + +class QCD_UTILS_EXPORT CDView: public QTreeView, public PIObject +{ + Q_OBJECT + PIOBJECT(CDView) +public: + explicit CDView(QWidget *parent = 0); + ~CDView(); + + void setType(int cdt); + void setFile(const QString & filename); + bool inProgress() const; + void startX(double freq = 20.); + CDUtils::CDSection * root(); + QString typeLetter() const; + + CDItemModel * CDModel() {return model_;} + +protected: + void mousePressEvent(QMouseEvent * ); + void mouseReleaseEvent(QMouseEvent * ); + void currentChanged(const QModelIndex & cur, const QModelIndex & prev); + +public slots: + void refresh(); + void refreshValues(); + void send(); + void receive(); + void save(); + void load(); + void clear(); + void buildFromHeader(const QString & description, int mode = 2); + void calculate(); + void filter(const QString & f); + +private slots: + void indexClicked(const QModelIndex & i); + void cd_sendFailed(); + void cd_sendSucceed(); + void cd_receiveFailed(); + void cd_receiveSucceed(); + void cd_receivedX(); + void cd_changedGlobal(); + +private: + bool filterTree(const QModelIndex & ti, const QString & filter); + EVENT_HANDLER(void, pi_cd_sendFailed) {emit _qcd_sendFailed();} + EVENT_HANDLER(void, pi_cd_sendSucceed) {emit _qcd_sendSucceed();} + EVENT_HANDLER(void, pi_cd_receiveFailed) {emit _qcd_receiveFailed();} + EVENT_HANDLER(void, pi_cd_receiveSucceed) {emit _qcd_receiveSucceed();} + EVENT_HANDLER(void, pi_cd_receivedX) {emit _qcd_receivedX();} + EVENT_HANDLER(void, pi_cd_changedGlobal) {emit _qcd_changedGlobal();} + EVENT_HANDLER3(void, pi_cd_messageReceived, PIDeque, path, int, type, PIString, msg); + + CDItemModel * model_; + QSortFilterProxyModel * proxy_; + int type_; + +signals: + void sendFailed(); + void sendSucceed(); + void receiveFailed(); + void receiveSucceed(); + void receivedX(); + void changedGlobal(); + void messageStatus(QString msg); + void commandSended(QString msg); + void messageReceived(QString path, int type, QString msg); + void busyStatusChanged(bool busy); + + void _qcd_sendFailed(); // PRIVATE + void _qcd_sendSucceed(); // PRIVATE + void _qcd_receiveFailed(); // PRIVATE + void _qcd_receiveSucceed(); // PRIVATE + void _qcd_receivedX(); // PRIVATE + void _qcd_changedGlobal(); // PRIVATE + +}; + +#endif // QCD_VIEW_H diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..9bd0225 Binary files /dev/null and b/logo.png differ diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt new file mode 100644 index 0000000..dc9a712 --- /dev/null +++ b/utils/CMakeLists.txt @@ -0,0 +1 @@ +add_directories("qad_") diff --git a/utils/cd_pult/CMakeLists.txt b/utils/cd_pult/CMakeLists.txt new file mode 100644 index 0000000..1ffaae3 --- /dev/null +++ b/utils/cd_pult/CMakeLists.txt @@ -0,0 +1,14 @@ +project(cd_pult) +if(APPLE) + set(APP_ICON "") +elseif(WIN32) + set(APP_ICON "") +else() + set(APP_ICON "") +endif() +set(APP_INFO "CD Pult") +piqt_application(${PROJECT_NAME} "Gui;Widgets" "qad_utils;qad_widgets;qad_graphic;qad_application;qcd_utils;piqt_utils") +if (Qt5_FOUND) + import_version(${PROJ_NAME}5 ${PROJECT_NAME}) + deploy_target(${PROJECT_NAME}5 DEPLOY_DIR ${CMAKE_CURRENT_BINARY_DIR} DESTINATION ${ROOT_DIR}/release) +endif() diff --git a/utils/cd_pult/cddirectk.cpp b/utils/cd_pult/cddirectk.cpp new file mode 100644 index 0000000..ce7e756 --- /dev/null +++ b/utils/cd_pult/cddirectk.cpp @@ -0,0 +1,312 @@ +#include "cddirectk.h" +#include "ui_cddirectk_type_dialog.h" +#include "cdutils_core.h" +#include "cdutils_k.h" +#include "qcd_core.h" +#include "qcd_model.h" +#include "graphic.h" +#include "piqt.h" +#include "qvariantedit.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace CDUtils; + + +KDockWidget::KDockWidget(QString title, QMainWindow * p): QDockWidget(title, p) { + da = p; + menu = new QMenu(this); + QAction * a = new QAction(QIcon(":/icons/document-edit.png"), "Rename ...", this); + connect(a, SIGNAL(triggered(bool)), this, SLOT(rename())); + dactions << a; + a = new QAction(QIcon(":/icons/edit-delete.png"), "Remove", this); + connect(a, SIGNAL(triggered(bool)), this, SIGNAL(removeRequest())); + dactions << a; + menu_k = new QMenu(this); + menu_k->setTitle(tr("Remove K")); + lay = new QFormLayout(); + lay->setContentsMargins(0, qApp->style()->pixelMetric(QStyle::PM_LayoutTopMargin), 0, 0); + lay->setLabelAlignment(Qt::AlignRight | Qt::AlignVCenter); + QWidget * w = new QWidget(); + w->setAcceptDrops(true); + w->installEventFilter(this); + w->setLayout(lay); + setWidget(w); + type_dialog = new CDDirectKTypeDialog(); +} + + +void KDockWidget::addK(const CDType & t, CDDirectKTypeDialog::TypeInfo ti) { + if (t.cd_type() != CDType::cdK) return; + PIDeque xp = t.path(); + if (k_list.contains(xp)) return; + k_list << xp; + info_list << ti; + //piCout << "add" << xp; + QWidget * ve = ti.create(); + //qDebug() << "add" << ve; + lay->addRow(PI2QString(t.pathString().join(".")) + ":", ve); + QCDCore::instance()->bindWidget(ve, t); + //ve->setValue(); +} + + +QByteArray KDockWidget::save() const { + ChunkStream cs; + cs.add(1, windowTitle()) + .add(2, getList(k_list)) + .add(3, info_list); + return cs.data(); +} + + +void KDockWidget::load(QByteArray ba) { + clear(); + if (ba.isEmpty()) return; + ChunkStream cs(ba); + PIVector > list; + QVector ilist; + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: setWindowTitle(cs.getData()); break; + case 2: list = setList(cs.getData()); break; + case 3: ilist = cs.getData >(); break; + default: break; + } + } + ilist.resize(list.size()); + for (int i = 0; i < list.size_s(); ++i) { + addK(K[list[i]], ilist[i]); + } +} + + +void KDockWidget::clear() { + while (lay->rowCount() > 0) + removeRow(0); + k_list.clear(); + info_list.clear(); +} + + +void KDockWidget::changedGlobal() { + //piCout << "changedGlobal ..." << k_list.size_s() << info_list.size() << lay->count() << lay->rowCount(); + for (int i = 0; i < k_list.size_s(); ++i) { + //piCout << "update" << i << "0"; + if (!K.exists(k_list[i])) { + k_list.remove(i); + info_list.remove(i); + removeRow(i); + --i; + continue; + } + //piCout << "update" << i << "1"; + QLabel * lbl = qobject_cast(lay->itemAt(i, QFormLayout::LabelRole)->widget()); + //piCout << "update" << i << "2"; + if (lbl) lbl->setText(PI2QString(K[k_list[i]].pathString().join(".")) + ":"); + //piCout << "update" << i << "3"; + } + //piCout << "changedGlobal ok"; +} + + +bool KDockWidget::eventFilter(QObject * o, QEvent * e) { + //if (o == graphic->viewport()) { + switch (e->type()) { + case QEvent::DragMove: { + QDragMoveEvent * de = (QDragMoveEvent*)e; + const QMimeData * mime = de->mimeData(); + if (!mime) break; + if (!mime->text().startsWith("k")) break; + de->setDropAction(Qt::CopyAction); + de->accept(); + return true; + } break; + case QEvent::DragEnter: { + QDragEnterEvent * de = (QDragEnterEvent*)e; + const QMimeData * mime = de->mimeData(); + if (!mime) break; + if (!mime->text().startsWith("k")) break; + de->setDropAction(Qt::CopyAction); + de->accept(); + return true; + } break; + case QEvent::Drop: { + QDropEvent * de = (QDropEvent*)e; + const QMimeData * mime = de->mimeData(); + if (!mime) break; + //qDebug() << "drop" << mime->text(); + if (!mime->text().startsWith("k")) break; + CDDirectKTypeDialog::TypeInfo ti; + CDType & k(K[CDCore::stringToPath(Q2PIString(mime->text().mid(1)))]); + if (k.type().left(1) == "n" || k.type().left(1) == "f") { + if (type_dialog->exec() == QDialog::Accepted) + ti = type_dialog->getType(); + else + return true; + } + addK(k, ti); + de->accept(); + return true; + } break; + default: break; + } + //} + return QWidget::eventFilter(o, e); +} + + +void KDockWidget::contextMenuEvent(QContextMenuEvent * e) { + qDeleteAll(menu_k->actions()); + menu_k->clear(); + for (int i = 0; i < k_list.size_s(); ++i) { + QAction * a = new QAction(PI2QString(K[k_list[i]].pathString().join(".")), this); + a->setData(i); + connect(a, SIGNAL(triggered(bool)), this, SLOT(removeK())); + menu_k->addAction(a); + } + QMenu * mwm = da->createPopupMenu(); + menu->clear(); + menu->addActions(dactions); + menu->addMenu(menu_k); + menu->addSeparator(); + menu->addActions(mwm->actions()); + menu->popup(e->globalPos()); + mwm->deleteLater(); +} + + +void KDockWidget::removeRow(int r) { + if (r < 0 || r >= lay->rowCount()) return; +#if QT_VERSION >= 0x050800 + QFormLayout::TakeRowResult rr = lay->takeRow(r); + if (rr.fieldItem) {delete rr.fieldItem->widget(); delete rr.fieldItem;} + if (rr.labelItem) {delete rr.labelItem->widget(); delete rr.labelItem;} +#else + piForTimes (2) { + QLayoutItem * i = lay->itemAt(r+r); + lay->removeItem(i); + if (i) {delete i->widget(); delete i;} + } +#endif +} + + +void KDockWidget::rename() { + QString nn = QInputDialog::getText(this, tr("Rename area"), tr("New area name:"), + QLineEdit::Normal, windowTitle()); + if (nn.isEmpty()) return; + setWindowTitle(nn); +} + + +void KDockWidget::removeK() { + QAction * a = qobject_cast(sender()); + if (!a) return; + int ind = a->data().toInt(); + if (ind < 0 || ind >= k_list.size_s()) return; + k_list.remove(ind); + if (ind >= 0 && ind < info_list.size()) + info_list.remove(ind); + removeRow(ind); +} + + + + +CDDirectK::CDDirectK(QWidget * parent) : QWidget(parent), Ui::CDDirectK() { + setupUi(this); + da = new QMainWindow(); + da->setWindowFlags(frame->windowFlags()); + da->setDockNestingEnabled(true); + layoutMain->addWidget(da); +} + + +CDDirectK::~CDDirectK() { +} + + +void CDDirectK::reset() { + qDeleteAll(docks); + docks.clear(); +} + + +QByteArray CDDirectK::save() const { + ChunkStream cs; + QVector dstates; + foreach (KDockWidget * d, docks) { + dstates << d->save(); + } + cs.add(1, docks.size()) + .add(2, dstates) + .add(3, da->saveState()); + return cs.data(); +} + + +void CDDirectK::load(QByteArray ba) { + reset(); + if (ba.isEmpty()) return; + ChunkStream cs(ba); + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: { + int s = cs.getData(); + piForTimes (s) + addArea(); + } break; + case 2: { + QVector dstates = cs.getData >(); + for (int i = 0; i < piMini(dstates.size(), docks.size()); ++i) + docks[i]->load(dstates[i]); + } break; + case 3: da->restoreState(cs.getData()); break; + default: break; + } + } +} + + +void CDDirectK::addArea() { + KDockWidget * dw = new KDockWidget(QString("area %1").arg(docks.size()), da); + connect(dw, SIGNAL(removeRequest()), this, SLOT(removeArea())); + da->addDockWidget(Qt::RightDockWidgetArea, dw); + docks << dw; + for (int i = 0; i < docks.size(); ++i) + docks[i]->setObjectName(QString("dock_%1").arg(i)); +} + + +void CDDirectK::changedGlobal() { + foreach (KDockWidget * d, docks) + d->changedGlobal(); +} + + +void CDDirectK::removeArea() { + KDockWidget * d = qobject_cast(sender()); + if (!d) return; + docks.removeAll(d); + d->deleteLater(); + for (int i = 0; i < docks.size(); ++i) + docks[i]->setObjectName(QString("dock_%1").arg(i)); +} + + +void CDDirectK::on_buttonAdd_clicked() { + addArea(); +} + + +void CDDirectK::on_buttonRemoveAll_clicked() { + qDeleteAll(docks); + docks.clear(); +} diff --git a/utils/cd_pult/cddirectk.h b/utils/cd_pult/cddirectk.h new file mode 100644 index 0000000..47ade06 --- /dev/null +++ b/utils/cd_pult/cddirectk.h @@ -0,0 +1,77 @@ +#ifndef CDDIRECTK_H +#define CDDIRECTK_H + +#include "cdgraphics.h" +#include "ui_cddirectk.h" +#include "cddirectk_type_dialog.h" + +class QFormLayout; + + +class KDockWidget: public QDockWidget { + Q_OBJECT +public: + KDockWidget(QString title = QString(), QMainWindow * p = 0); + + void addK(const CDUtils::CDType & t, CDDirectKTypeDialog::TypeInfo ti); + QByteArray save() const; + void load(QByteArray ba); + void clear(); + void changedGlobal(); + + QFormLayout * lay; + +private: + bool eventFilter(QObject * o, QEvent * e); + void contextMenuEvent(QContextMenuEvent * e); + void removeRow(int r); + + QMenu * menu, * menu_k; + QList dactions; + QMainWindow * da; + CDDirectKTypeDialog * type_dialog; + PIVector > k_list; + QVector info_list; + +private slots: + void rename(); + void removeK(); + +signals: + void removeRequest(); + +}; + + + + +class CDDirectK: public QWidget, public Ui::CDDirectK +{ + Q_OBJECT +public: + explicit CDDirectK(QWidget *parent = 0); + ~CDDirectK(); + + void reset(); + QByteArray save() const; + void load(QByteArray ba); + +private: + void addArea(); + + QList docks; + QMainWindow * da; + +public slots: + void changedGlobal(); + +private slots: + void removeArea(); + void on_buttonAdd_clicked(); + void on_buttonRemoveAll_clicked(); + +signals: + +}; + +#endif // CDDIRECTK_H diff --git a/utils/cd_pult/cddirectk.ui b/utils/cd_pult/cddirectk.ui new file mode 100644 index 0000000..731498b --- /dev/null +++ b/utils/cd_pult/cddirectk.ui @@ -0,0 +1,85 @@ + + + CDDirectK + + + + 0 + 0 + 624 + 411 + + + + CD Pult + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + + 0 + + + 0 + + + + + Add new + + + + :/icons/list-add.png:/icons/list-add.png + + + + + + + Remove all + + + + :/icons/edit-delete.png:/icons/edit-delete.png + + + + + + + Qt::Horizontal + + + + 1 + 20 + + + + + + + + + + + + + + diff --git a/utils/cd_pult/cddirectk_type_dialog.cpp b/utils/cd_pult/cddirectk_type_dialog.cpp new file mode 100644 index 0000000..c6be2fa --- /dev/null +++ b/utils/cd_pult/cddirectk_type_dialog.cpp @@ -0,0 +1,76 @@ +#include "cddirectk_type_dialog.h" +#include "cdutils_core.h" +#include "qcd_core.h" +#include "qcd_model.h" +#include "piqt.h" +#include "spinslider.h" +#include "qvariantedit.h" + + +CDDirectKTypeDialog::CDDirectKTypeDialog(QWidget * parent) : QDialog(parent), Ui::CDDirectKTypeDialog() { + setupUi(this); +} + + +CDDirectKTypeDialog::~CDDirectKTypeDialog() { +} + + +CDDirectKTypeDialog::TypeInfo CDDirectKTypeDialog::getType() const { + if (!groupBox->isChecked()) return TypeInfo(); + TypeInfo ret; + ret.type = comboType->currentIndex(); + ret.params_d[0] = evalMin->value(); + ret.params_d[1] = evalMax->value(); + ret.params_d[2] = spinDecimals->value(); + ret.params_d[3] = evalStep->value(); + ret.params_s[0] = linePrefix->text(); + ret.params_s[1] = lineSuffix->text(); + return ret; +} + + + + +CDDirectKTypeDialog::TypeInfo::TypeInfo(int type_) { + type = type_; + params_d.resize(4); + params_s.resize(2); +} + + +QWidget * CDDirectKTypeDialog::TypeInfo::create() { + params_d.resize(4); + params_s.resize(2); + switch (type) { + case 0: { + QDoubleSpinBox * ret = new QDoubleSpinBox(); + ret->setMinimum(params_d[0]); + ret->setMaximum(params_d[1]); + ret->setDecimals(params_d[2]); + ret->setSingleStep(params_d[3]); + ret->setPrefix(params_s[0]); + ret->setSuffix(params_s[1]); + return ret; + } break; + case 1: { + QSlider * ret = new QSlider(Qt::Horizontal); + ret->setMinimum(params_d[0]); + ret->setMaximum(params_d[1]); + ret->setSingleStep(params_d[3]); + return ret; + } break; + case 2: { + SpinSlider * ret = new SpinSlider(); + ret->setMinimum(params_d[0]); + ret->setMaximum(params_d[1]); + ret->setDecimals(params_d[2]); + ret->setSingleStep(params_d[3]); + ret->setPrefix(params_s[0]); + ret->setSuffix(params_s[1]); + return ret; + } break; + default: break; + } + return new QVariantEdit(); +} diff --git a/utils/cd_pult/cddirectk_type_dialog.h b/utils/cd_pult/cddirectk_type_dialog.h new file mode 100644 index 0000000..9881864 --- /dev/null +++ b/utils/cd_pult/cddirectk_type_dialog.h @@ -0,0 +1,44 @@ +#ifndef CDDIRECTK_TYPE_DIALOG_H +#define CDDIRECTK_TYPE_DIALOG_H + +#include +#include "ui_cddirectk_type_dialog.h" + + +class CDDirectKTypeDialog: public QDialog, public Ui::CDDirectKTypeDialog +{ + Q_OBJECT +public: + explicit CDDirectKTypeDialog(QWidget * parent = 0); + ~CDDirectKTypeDialog(); + + struct TypeInfo { + TypeInfo(int type_ = -1); + QWidget * create(); + int type; + QVector params_d; + QVector params_s; + }; + + TypeInfo getType() const; + +private: + +public slots: + +private slots: + +signals: + +}; + +inline QDataStream & operator <<(QDataStream & s, const CDDirectKTypeDialog::TypeInfo & v) { + s << v.type << v.params_d << v.params_s; + return s; +} +inline QDataStream & operator >>(QDataStream & s, CDDirectKTypeDialog::TypeInfo & v) { + s >> v.type >> v.params_d >> v.params_s; + return s; +} + +#endif // CDDIRECTK_TYPE_DIALOG_H diff --git a/utils/cd_pult/cddirectk_type_dialog.ui b/utils/cd_pult/cddirectk_type_dialog.ui new file mode 100644 index 0000000..0b5ec15 --- /dev/null +++ b/utils/cd_pult/cddirectk_type_dialog.ui @@ -0,0 +1,232 @@ + + + CDDirectKTypeDialog + + + + 0 + 0 + 275 + 310 + + + + CD Pult + + + + + + Custom + + + true + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Type: + + + + + + + + Spin + + + + + Slider + + + + + SpinSlider + + + + + + + + Min: + + + + + + + + + + Max: + + + + + + + 100.000000000000000 + + + + + + + Decimals: + + + + + + + + + + Single step: + + + + + + + 1.000000000000000 + + + + + + + Prefix: + + + + + + + + + + Suffix: + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + CLineEdit + QLineEdit +
clineedit.h
+
+ + EvalSpinBox + QWidget +
evalspinbox.h
+
+
+ + + + groupBox + toggled(bool) + widget + setEnabled(bool) + + + 86 + 49 + + + 94 + 91 + + + + + buttonBox + accepted() + CDDirectKTypeDialog + accept() + + + 297 + 285 + + + 315 + 280 + + + + + buttonBox + rejected() + CDDirectKTypeDialog + reject() + + + 281 + 290 + + + 283 + 307 + + + + +
diff --git a/utils/cd_pult/cdgraphics.cpp b/utils/cd_pult/cdgraphics.cpp new file mode 100644 index 0000000..b067683 --- /dev/null +++ b/utils/cd_pult/cdgraphics.cpp @@ -0,0 +1,354 @@ +#include "cdgraphics.h" +//#include "ui_qcd_graphic.h" +#include "cdutils_core.h" +#include "cdutils_x.h" +#include "qcd_core.h" +#include "qcd_model.h" +#include "qcd_graphic.h" +#include "graphic.h" +#include "piqt.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace CDUtils; + + +QStringList CDUtils::getList(const PIVector > & x_list) { + QStringList ret; + piForeachC (PIDeque & p, x_list) + ret << PI2QString(CDCore::pathToString(p)); + return ret; +} + + +PIVector > CDUtils::setList(const QStringList & l) { + PIVector > ret; + foreach (QString s, l) + ret << CDCore::stringToPath(Q2PIString(s)); + return ret; +} + + + + +GDockWidget::GDockWidget(QString title, QMainWindow * p): QDockWidget(title, p) { + da = p; + menu = new QMenu(this); + QAction * a = new QAction(QIcon(":/icons/document-edit.png"), "Rename ...", this); + connect(a, SIGNAL(triggered(bool)), this, SLOT(rename())); + dactions << a; + a = new QAction(QIcon(":/icons/edit-delete.png"), "Remove", this); + connect(a, SIGNAL(triggered(bool)), this, SIGNAL(removeRequest())); + dactions << a; + menu_x = new QMenu(this); + menu_x->setTitle(tr("Remove X")); + graphic = new CDGraphicWidget(); + graphic->graphic()->viewport()->setAcceptDrops(true); + graphic->graphic()->viewport()->installEventFilter(this); + setWidget(graphic); +} + + +void GDockWidget::addX(const CDType & t) { + if (t.cd_type() != CDType::cdX) return; + PIDeque xp = t.path(); + if (x_list.contains(xp)) return; + x_list << xp; + int gind = graphic->graphic()->graphicsCount(); + graphic->graphic()->setGraphicsCount(gind + 1); + graphic->graphic()->setGraphicName(PI2QString(t.pathString().join(".")), gind); +} + + +void GDockWidget::drawX(const PIMap > & data) { + for (int i = 0; i < x_list.size_s(); ++i) { + PIString sp = CDCore::pathToString(x_list[i]); + const PIVector & ch(data[sp]); + for (int j = 0; j < ch.size_s(); ++j) + graphic->graphic()->addPoint(ch[j], i, false); + } + graphic->graphic()->updateGraphics(); +} + + +QByteArray GDockWidget::save() const { + ChunkStream cs; + cs.add(1, windowTitle()) + .add(2, getList(x_list)) + .add(3, graphic->graphic()->save()) + .add(4, graphic->evalSpinBoxHistory()->expression()) + .add(5, graphic->evalSpinBoxVisible()->expression()); + return cs.data(); +} + + +void GDockWidget::load(QByteArray ba) { + if (ba.isEmpty()) return; + ChunkStream cs(ba); + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: setWindowTitle(cs.getData()); break; + case 2: x_list = setList(cs.getData()); break; + case 3: graphic->graphic()->load(cs.getData()); break; + case 4: graphic->evalSpinBoxHistory()->setExpression(cs.getData()); break; + case 5: graphic->evalSpinBoxVisible()->setExpression(cs.getData()); break; + default: break; + } + } +} + + +void GDockWidget::changedGlobal() { + for (int i = 0; i < x_list.size_s(); ++i) { + if (!X.exists(x_list[i])) { + x_list.remove(i); + graphic->graphic()->removeGraphic(i); + --i; + continue; + } + graphic->graphic()->setGraphicName(PI2QString(X[x_list[i]].pathString().join(".")), i); + } +} + + +bool GDockWidget::eventFilter(QObject * o, QEvent * e) { + //if (o == graphic->viewport()) { + switch (e->type()) { + case QEvent::DragMove: { + QDragMoveEvent * de = (QDragMoveEvent*)e; + const QMimeData * mime = de->mimeData(); + //qDebug() << "enter" << mime; + if (!mime) break; + if (!mime->text().startsWith("x")) break; + de->setDropAction(Qt::CopyAction); + de->accept(); + return true; + } break; + case QEvent::DragEnter: { + QDragEnterEvent * de = (QDragEnterEvent*)e; + const QMimeData * mime = de->mimeData(); + //qDebug() << "enter" << mime; + if (!mime) break; + if (!mime->text().startsWith("x")) break; + de->setDropAction(Qt::CopyAction); + de->accept(); + return true; + } break; + case QEvent::Drop: { + QDropEvent * de = (QDropEvent*)e; + const QMimeData * mime = de->mimeData(); + if (!mime) break; + //qDebug() << "drop" << mime->text(); + if (!mime->text().startsWith("x")) break; + addX(X[CDCore::stringToPath(Q2PIString(mime->text().mid(1)))]); + de->accept(); + return true; + } break; + default: break; + } + //} + return QWidget::eventFilter(o, e); +} + + +void GDockWidget::contextMenuEvent(QContextMenuEvent * e) { + if (graphic->graphic()->underMouse()) return; + qDeleteAll(menu_x->actions()); + menu_x->clear(); + for (int i = 0; i < graphic->graphic()->graphicsCount(); ++i) { + QPixmap icon(da->iconSize()); + icon.fill(graphic->graphic()->graphic(i).pen.color()); + QAction * a = new QAction(QIcon(icon), graphic->graphic()->graphic(i).name, this); + a->setData(i); + connect(a, SIGNAL(triggered(bool)), this, SLOT(removeX())); + menu_x->addAction(a); + } + QMenu * mwm = da->createPopupMenu(); + menu->clear(); + menu->addActions(dactions); + menu->addMenu(menu_x); + menu->addSeparator(); + menu->addActions(mwm->actions()); + menu->popup(e->globalPos()); + mwm->deleteLater(); +} + + +CDGraphicWidget * GDockWidget::viewportGraphic(QObject * o) const { + if (!o) return 0; + while (!qobject_cast(o) && o) + o = o->parent(); + return qobject_cast(o); +} + + +void GDockWidget::rename() { + QString nn = QInputDialog::getText(this, tr("Rename area"), tr("New area name:"), + QLineEdit::Normal, windowTitle()); + if (nn.isEmpty()) return; + setWindowTitle(nn); +} + + +void GDockWidget::removeX() { + QAction * a = qobject_cast(sender()); + if (!a) return; + int ind = a->data().toInt(); + if (ind < 0 || ind >= x_list.size_s()) return; + x_list.remove(ind); + graphic->graphic()->removeGraphic(ind); +} + + + + +CDGraphics::CDGraphics(QWidget * parent) : QWidget(parent), Ui::CDGraphics() { + setupUi(this); + da = new QMainWindow(); + da->setWindowFlags(frame->windowFlags()); + da->setDockNestingEnabled(true); + layoutMain->addWidget(da); +} + + +CDGraphics::~CDGraphics() { +} + + +void CDGraphics::reset() { + qDeleteAll(docks); + docks.clear(); +} + + +QByteArray CDGraphics::save() const { + ChunkStream cs; + QVector dstates; + foreach (GDockWidget * d, docks) { + dstates << d->save(); + } + cs.add(1, docks.size()) + .add(2, dstates) + .add(3, da->saveState()); + X.lock(); + cs.add(4, getList(X.enabledList())); + X.unlock(); + cs.add(5, buttonConfigVisible->isChecked()); + return cs.data(); +} + + +void CDGraphics::load(QByteArray ba) { + reset(); + if (ba.isEmpty()) return; + ChunkStream cs(ba); + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: { + int s = cs.getData(); + piForTimes (s) + addGraphic(); + } break; + case 2: { + QVector dstates = cs.getData >(); + for (int i = 0; i < piMini(dstates.size(), docks.size()); ++i) + docks[i]->load(dstates[i]); + } break; + case 3: da->restoreState(cs.getData()); break; + case 4: + X.lock(); + X.setEnabledList(setList(cs.getData())); + X.unlock(); + break; + case 5: + buttonConfigVisible->setChecked(cs.getData()); + break; + default: break; + } + } +} + + +GDockWidget * CDGraphics::graphicDock(Graphic * o) const { + if (!o) return 0; + foreach (GDockWidget * d, docks) + if (d->widget() == o) + return d; + return 0; +} + + +void CDGraphics::addGraphic() { + GDockWidget * dw = new GDockWidget(QString("area %1").arg(docks.size()), da); + connect(dw, SIGNAL(removeRequest()), this, SLOT(removeGraphic())); + connect(buttonConfigVisible, SIGNAL(toggled(bool)), dw->graphic, SLOT(setConfigVisible(bool))); + connect(buttonLegendVisible, SIGNAL(clicked(bool)), dw->graphic->graphic(), SLOT(setLegendVisible(bool))); + connect(buttonBorderInputsVisible, SIGNAL(clicked(bool)), dw->graphic->graphic(), SLOT(setBorderInputsVisible(bool))); + connect(buttonPause, SIGNAL(clicked(bool)), dw->graphic->graphic(), SLOT(setPaused(bool))); + dw->graphic->setConfigVisible(buttonConfigVisible->isChecked()); + dw->graphic->graphic()->setLegendVisible(buttonLegendVisible->isChecked()); + dw->graphic->graphic()->setBorderInputsVisible(buttonBorderInputsVisible->isChecked()); + da->addDockWidget(Qt::RightDockWidgetArea, dw); + docks << dw; + for (int i = 0; i < docks.size(); ++i) + docks[i]->setObjectName(QString("dock_%1").arg(i)); +} + + +void CDGraphics::receivedX() { + PIMap > data; + X.lock(); + PIVector > x_list = X.enabledList(); + PIVector ch; + piForeachC (PIDeque & p, x_list) { + CDType & t(X[p]); + if (t.xmode_rec() == CDType::X_Current) + ch.resize(1).fill(t.toDouble()); + else + ch = t.history; + t.history.clear(); + data[CDCore::pathToString(t.path())] = ch; + } + //piCout << data; + X.unlock(); + foreach (GDockWidget * d, docks) + d->drawX(data); +} + + +void CDGraphics::changedGlobal() { + foreach (GDockWidget * d, docks) + d->changedGlobal(); +} + + +void CDGraphics::removeGraphic() { + GDockWidget * d = qobject_cast(sender()); + if (!d) return; + docks.removeAll(d); + d->deleteLater(); + for (int i = 0; i < docks.size(); ++i) + docks[i]->setObjectName(QString("dock_%1").arg(i)); +} + + +void CDGraphics::on_buttonAdd_clicked() { + addGraphic(); +} + + +void CDGraphics::on_buttonClear_clicked() { + foreach (GDockWidget * d, docks) + d->graphic->graphic()->clear(); +} + + +void CDGraphics::on_buttonRemoveAll_clicked() { + qDeleteAll(docks); + docks.clear(); +} diff --git a/utils/cd_pult/cdgraphics.h b/utils/cd_pult/cdgraphics.h new file mode 100644 index 0000000..51e3483 --- /dev/null +++ b/utils/cd_pult/cdgraphics.h @@ -0,0 +1,92 @@ +#ifndef CDGRAPHICS_H +#define CDGRAPHICS_H + +#include +#include +#include +#include "ui_cdgraphics.h" +#include "qcd_graphic.h" +#include + +namespace CDUtils { + class CDType; + class CDSection; + QStringList getList(const PIVector > & x_list); + PIVector > setList(const QStringList & l); +} + +class QMainWindow; +class Graphic; + + + + +class GDockWidget: public QDockWidget { + Q_OBJECT +public: + GDockWidget(QString title = QString(), QMainWindow * p = 0); + + void addX(const CDUtils::CDType & t); + void drawX(const PIMap > & data); + QByteArray save() const; + void load(QByteArray ba); + void changedGlobal(); + + CDGraphicWidget * graphic; + +private: + bool eventFilter(QObject * o, QEvent * e); + void contextMenuEvent(QContextMenuEvent * e); + CDGraphicWidget * viewportGraphic(QObject * o) const; + + QMenu * menu, * menu_x; + QList dactions; + QMainWindow * da; + PIVector > x_list; + +private slots: + void rename(); + void removeX(); + +signals: + void removeRequest(); + +}; + + + + +class CDGraphics : public QWidget, public Ui::CDGraphics +{ + Q_OBJECT +public: + explicit CDGraphics(QWidget *parent = 0); + ~CDGraphics(); + + void reset(); + QByteArray save() const; + void load(QByteArray ba); + +private: + GDockWidget * graphicDock(Graphic * o) const; + void addXToGraphic(const QString & xp, Graphic * g); + void addGraphic(); + + QList docks; + QMainWindow * da; + +public slots: + void receivedX(); + void changedGlobal(); + +private slots: + void removeGraphic(); + void on_buttonAdd_clicked(); + void on_buttonClear_clicked(); + void on_buttonRemoveAll_clicked(); + +signals: + +}; + +#endif // CDGRAPHICS_H diff --git a/utils/cd_pult/cdgraphics.ui b/utils/cd_pult/cdgraphics.ui new file mode 100644 index 0000000..6a40b06 --- /dev/null +++ b/utils/cd_pult/cdgraphics.ui @@ -0,0 +1,168 @@ + + + CDGraphics + + + + 0 + 0 + 624 + 411 + + + + CD Pult + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + + 0 + + + 0 + + + + + Add new + + + + :/icons/list-add.png:/icons/list-add.png + + + + + + + Clear all + + + + :/icons/edit-clear.png:/icons/edit-clear.png + + + + + + + Remove all + + + + :/icons/edit-delete.png:/icons/edit-delete.png + + + + + + + Remove all + + + + :/icons/layer-visible-off.png + :/icons/layer-visible-on.png:/icons/layer-visible-off.png + + + true + + + true + + + + + + + Remove all + + + + :/icons/legend.png:/icons/legend.png + + + true + + + true + + + + + + + Remove all + + + + :/icons/media-playback-pause.png:/icons/media-playback-pause.png + + + true + + + false + + + + + + + Remove all + + + + :/icons/border-line.png:/icons/border-line.png + + + true + + + false + + + + + + + Qt::Horizontal + + + + 1 + 20 + + + + + + + + + + + + + + + + + diff --git a/utils/cd_pult/cdpult.qrc b/utils/cd_pult/cdpult.qrc new file mode 100644 index 0000000..9fd497f --- /dev/null +++ b/utils/cd_pult/cdpult.qrc @@ -0,0 +1,10 @@ + + + icons/db-export.png + icons/db-import.png + icons/timer.png + icons/flame.png + icons/accessories-calculator.png + icons/accessories-text-editor.png + + diff --git a/utils/cd_pult/cdpultwindow.cpp b/utils/cd_pult/cdpultwindow.cpp new file mode 100644 index 0000000..c388c5a --- /dev/null +++ b/utils/cd_pult/cdpultwindow.cpp @@ -0,0 +1,292 @@ +#include "edockwidget.h" +#include "cdpultwindow.h" +#include "cdutils_core.h" +#include "cdutils_k.h" +#include "cdutils_x.h" +#include "cdutils_m.h" +#include "qcd_core.h" +#include "qcd_view.h" +#include "qcd_model.h" +#include "qcd_modedialog.h" +#include "chunkstream.h" +#include "qvariantedit.h" +#include "piqt.h" +#include "piqt_highlighter.h" +#include "qcodeedit.h" +#include +#include +#include +#include + +using namespace CDUtils; + + +CDPultWindow::CDPultWindow(QWidget *parent) : EMainWindow(parent), Ui::CDPultWindow() { + setupUi(this); + centralWidget()->hide(); + setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); + CDCore::instance()->initPult(); + def_config = codeConfig->text(); + checkDefaultConfig->setChecked(true); + new ConfigHighlighter(codeConfig->document()); + widgetK->setType(CDUtils::CDType::cdK); + widgetX->setType(CDUtils::CDType::cdX); + widgetC->setType(CDUtils::CDType::cdC); + widgetM->setType(CDUtils::CDType::cdM); + editFileK->setValue(QVariant::fromValue(QAD::File("", "*.dat"))); + editFileX->setValue(QVariant::fromValue(QAD::File("", "*.dat"))); + editFileC->setValue(QVariant::fromValue(QAD::File("", "*.dat"))); + editFileM->setValue(QVariant::fromValue(QAD::File("", "*.dat"))); + log_icons[CDViewWidget::OKIcon] = QIcon(":/icons/dialog-ok-apply.png"); + log_icons[CDViewWidget::FailIcon] = QIcon(":/icons/dialog-cancel.png"); + log_icons[CDViewWidget::WaitIcon] = QIcon(":/icons/timer.png"); + setRecentMenu(menuOpen_recent); + ribbon = new Ribbon(this); + session.setFile("session_cdpult.conf"); + session.addEntry(this); + session.addEntry(ribbon->tabWidget()); + session.load(); + reset(); + connect(widgetK, SIGNAL(addToLog(CDViewWidget::LogIcon,QString)), this, SLOT(addToLog(CDViewWidget::LogIcon,QString))); + connect(widgetX, SIGNAL(addToLog(CDViewWidget::LogIcon,QString)), this, SLOT(addToLog(CDViewWidget::LogIcon,QString))); + connect(widgetC, SIGNAL(addToLog(CDViewWidget::LogIcon,QString)), this, SLOT(addToLog(CDViewWidget::LogIcon,QString))); + connect(widgetM, SIGNAL(addToLog(CDViewWidget::LogIcon,QString)), this, SLOT(addToLog(CDViewWidget::LogIcon,QString))); + connect(widgetK->view, SIGNAL(changedGlobal()), widgetDirectK, SLOT(changedGlobal())); + connect(widgetX->view, SIGNAL(changedGlobal()), widgetGraphics, SLOT(changedGlobal())); + connect(widgetX->view, SIGNAL(receivedX()), widgetGraphics, SLOT(receivedX())); + connect(widgetM->view, SIGNAL(messageReceived(QString,int,QString)), this, SLOT(messageReceived(QString,int,QString))); + QCDCore::instance()->bindWidget(widgetK->view); + QCDCore::instance()->setDirectKEnabled(true); + X.start(); + if (windowState() == Qt::WindowMinimized) + setWindowState(Qt::WindowNoState); +} + + +CDPultWindow::~CDPultWindow() { +} + + +void CDPultWindow::loadFile(const QString & fp) { + load(fp); +} + + +void CDPultWindow::apply(bool sessions) { + CDCore::instance()->stop(); + widgetK->setFile(editFileK->value().value().file); + widgetX->setFile(editFileX->value().value().file); + widgetC->setFile(editFileC->value().value().file); + widgetM->setFile(editFileM->value().value().file); + if (checkDefaultConfig->isChecked()) + CDCore::instance()->initPult(); + else + CDCore::instance()->init(Q2PIString(codeConfig->text()), true); + widgetX->view->startX(); + if (sessions) { + widgetGraphics->load(session_gr); + widgetDirectK->load(session_dk); + if (!session_mw.isEmpty()) + restoreState(session_mw); + X.lock(); + PIVector > x_list = X.enabledList(); + X.unlock(); + piForeachC (PIDeque & p, x_list) + X.enable(X[p]); + ((CDItemModel*)widgetX->view->model())->updateModel(); + widgetX->view->expandAll(); + } + dockCDKView->setVisible(checkHasK->isChecked()); + dockCDXView->setVisible(checkHasX->isChecked()); + dockCDCView->setVisible(checkHasC->isChecked()); + dockCDMView->setVisible(checkHasM->isChecked()); + QMetaObject::invokeMethod(this, "changedDock", Qt::QueuedConnection); +} + + +void CDPultWindow::closeEvent(QCloseEvent *e) { + EMainWindow::closeEvent(e); + if (!e->isAccepted()) + return; + QApplication::closeAllWindows(); + session.save(); + session.setFile(QString()); +} + + +void CDPultWindow::reset(bool full) { + setWindowTitle(QString("CD Pult")); + widgetK->reset(); + setChanged(false); +} + + +bool CDPultWindow::load(const QString & path) { + qApp->setOverrideCursor(Qt::WaitCursor); + QPIConfig conf(path, QIODevice::ReadOnly); + QAD::File f = editFileK->value().value(); + checkSyncFiles->setChecked(false); + editFileK->setValue(QVariant::fromValue(QAD::File(conf.getValue("file_k").toString(), f.filter))); + editFileX->setValue(QVariant::fromValue(QAD::File(conf.getValue("file_x").toString(), f.filter))); + editFileC->setValue(QVariant::fromValue(QAD::File(conf.getValue("file_c").toString(), f.filter))); + editFileM->setValue(QVariant::fromValue(QAD::File(conf.getValue("file_m").toString(), f.filter))); + checkSyncFiles->setChecked(conf.getValue("sync_files").toBool()); + lineSessionName->setText(conf.getValue("session_name").toString()); + last_icon = conf.getValue("icon_path").toString(); + setAppIcon(conf.getValue("icon").toByteArray()); + checkHasK->setChecked(conf.getValue("has_k").toBool()); + checkHasX->setChecked(conf.getValue("has_x").toBool()); + checkHasC->setChecked(conf.getValue("has_c").toBool()); + checkHasM->setChecked(conf.getValue("has_m").toBool()); + checkDefaultConfig->setChecked(conf.getValue("default_config").toBool()); + codeConfig->setText(QByteArray2QString(conf.getValue("config").toByteArray())); + if (codeConfig->text().isEmpty()) + codeConfig->setText(def_config); + session_gr = conf.getValue("session_gr").toByteArray(); + session_dk = conf.getValue("session_dk").toByteArray(); + session_mw = conf.getValue("session_mw").toByteArray(); + setChanged(false); + file_name = path; + apply(true); + qApp->restoreOverrideCursor(); + return true; +} + + +bool CDPultWindow::save(const QString & path) { + session_gr = widgetGraphics->save(); + session_dk = widgetDirectK->save(); + session_mw = saveState(); + QPIConfig conf(path, QIODevice::ReadWrite); + conf.clear(); + conf.setValue("file_k", editFileK->value().value().file); + conf.setValue("file_x", editFileX->value().value().file); + conf.setValue("file_c", editFileC->value().value().file); + conf.setValue("file_m", editFileM->value().value().file); + conf.setValue("sync_files", checkSyncFiles->isChecked()); + conf.setValue("session_name", lineSessionName->text()); + conf.setValue("icon_path", last_icon); + conf.setValue("icon", appIcon()); + conf.setValue("has_k", checkHasK->isChecked()); + conf.setValue("has_x", checkHasX->isChecked()); + conf.setValue("has_c", checkHasC->isChecked()); + conf.setValue("has_m", checkHasM->isChecked()); + conf.setValue("default_config", checkDefaultConfig->isChecked()); + conf.setValue("config", QString2QByteArray(codeConfig->text())); + conf.setValue("session_gr", session_gr); + conf.setValue("session_dk", session_dk); + conf.setValue("session_mw", session_mw); + file_name = path; + return true; + + //widgetK->setFile(path); + //widgetK->save(); +} + + +void CDPultWindow::loadingSession(QPIConfig & conf) { + setRecentFiles(conf.getValue("recent files").toStringList()); +} + + +void CDPultWindow::savingSession(QPIConfig & conf) { + conf.setValue("recent files", recentFiles()); +} + + +QByteArray CDPultWindow::appIcon() const { + QByteArray ret; + if (icon.isNull()) return ret; + QBuffer buff(&ret); + buff.open(QIODevice::WriteOnly); + icon.save(&buff, "png"); + //qDebug() << "s" << ret.size(); + return ret; +} + + +void CDPultWindow::setAppIcon(QByteArray ba) { + if (ba.isEmpty()) { + icon = QImage(); + setWindowIcon(QIcon()); + return; + } + //qDebug() << "l" << ba.size(); + icon = QImage::fromData(ba); + setWindowIcon(QIcon(QPixmap::fromImage(icon))); + //qDebug() << QApplication::windowIcon().availableSizes(); +} + + +void CDPultWindow::addToLog(CDViewWidget::LogIcon icon, const QString & msg) { + QListWidgetItem * ni = new QListWidgetItem(log_icons[icon], "(" + QTime::currentTime().toString() + ") " + msg); + bool s = listLog->verticalScrollBar()->value() == listLog->verticalScrollBar()->maximum(); + listLog->addItem(ni); + if (s) listLog->scrollToBottom(); +} + + +void CDPultWindow::messageReceived(QString path, int type, QString msg) { + MessageType mt = (MessageType)type; + const CDType & t(M.root()[CDCore::stringToPath(Q2PIString(path))]); + if (t.cd_type() != CDType::cdM) return; + if (mt == MessageBox) + QMessageBox::information(this, windowTitle(), QString("[%1]\n%2").arg(PI2QString(t.name()), msg)); +} + + +void CDPultWindow::on_editFileK_valueChanged(const QVariant & p) { + if (!checkSyncFiles->isChecked()) return; + QFileInfo fi(p.value().file); + if (fi.path().isEmpty()) return; + QString n = fi.baseName(); + QString xn(n), cn(n), mn(n); + if (n.contains("k")) { + xn.replace(n.indexOf("k"), 1, "x"); + cn.replace(n.indexOf("k"), 1, "c"); + mn.replace(n.indexOf("k"), 1, "m"); + } else { + xn += "_x"; + cn += "_c"; + mn += "_m"; + } + QString ext = fi.suffix(), dot, dir; + QString kfn(fi.filePath()); + if (!ext.isEmpty()) { + kfn.chop(ext.size()); + if (kfn.endsWith(".")) { + kfn.chop(1); + dot = "."; + } + } + if (!fi.path().isEmpty() && fi.path() != ".") { + dir = fi.path(); + if (!dir.endsWith("/")) + dir += "/"; + } + QAD::File f = editFileK->value().value(); + f.file = dir + xn + dot + ext; editFileX->setValue(QVariant::fromValue(f)); + f.file = dir + cn + dot + ext; editFileC->setValue(QVariant::fromValue(f)); + f.file = dir + mn + dot + ext; editFileM->setValue(QVariant::fromValue(f)); +} + + +void CDPultWindow::on_buttonSessionApply_clicked() { + apply(false); +} + + +void CDPultWindow::on_lineSessionName_textChanged(const QString & t) { + setWindowTitle(QString("CD Pult - %1").arg(t)); +} + + +void CDPultWindow::on_buttonIcon_clicked() { + QList ifl = QImageReader::supportedImageFormats(); + QStringList sfl; foreach (QByteArray s, ifl) sfl << ("*." + QString(s).toLower()); + QString f = QFileDialog::getOpenFileName(this, tr("Select icon"), last_icon, tr("Images") + " (" + sfl.join(" ") + ")"); + if (f.isEmpty()) return; + last_icon = f; + icon = QImage(last_icon); + setWindowIcon(QIcon(QPixmap::fromImage(icon))); +} diff --git a/utils/cd_pult/cdpultwindow.h b/utils/cd_pult/cdpultwindow.h new file mode 100644 index 0000000..dad2c2b --- /dev/null +++ b/utils/cd_pult/cdpultwindow.h @@ -0,0 +1,53 @@ +#ifndef CDPULTWINDOW_H +#define CDPULTWINDOW_H + +#include "emainwindow.h" +#include "ui_cdpultwindow.h" +#include "cdviewwidget.h" +#include "ribbon.h" +#include "piobject.h" + + +class CDPultWindow : public EMainWindow, public Ui::CDPultWindow +{ + Q_OBJECT + Q_ENUMS(LogIcon) +public: + + explicit CDPultWindow(QWidget *parent = 0); + ~CDPultWindow(); + void loadFile(const QString & fp); + void apply(bool sessions); + +private: + + void closeEvent(QCloseEvent *); + void reset(bool full = false); + bool load(const QString & path); + bool save(const QString & path); + QString loadFilter() {return "Pult session(*.conf)";} + QString saveFilter() {return loadFilter();} + void loadingSession(QPIConfig & conf); + void savingSession(QPIConfig & conf); + + QByteArray appIcon() const; + void setAppIcon(QByteArray ba); + + Ribbon * ribbon; + QMap log_icons; + QByteArray session_gr, session_dk, session_mw; + QString def_config, last_icon; + QImage icon; + +private slots: + void addToLog(CDViewWidget::LogIcon icon, const QString & msg); + void messageReceived(QString path, int type, QString msg); + + void on_editFileK_valueChanged(const QVariant & p); + void on_buttonSessionApply_clicked(); + + void on_lineSessionName_textChanged(const QString & t); + void on_buttonIcon_clicked(); +}; + +#endif // CDPULTWINDOW_H diff --git a/utils/cd_pult/cdpultwindow.ui b/utils/cd_pult/cdpultwindow.ui new file mode 100644 index 0000000..ee0273c --- /dev/null +++ b/utils/cd_pult/cdpultwindow.ui @@ -0,0 +1,612 @@ + + + CDPultWindow + + + + 0 + 0 + 798 + 593 + + + + CD Pult + + + true + + + QMainWindow::AllowNestedDocks|QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks + + + + + + 0 + 0 + 798 + 24 + + + + + Main + + + + Open recent + + + + :/icons/document-open-recent.png:/icons/document-open-recent.png + + + + + + + + + + + + + :/icons/document-edit.png:/icons/document-edit.png + + + K + + + 1 + + + + + 0 + + + + + + + + + + + :/icons/dialog-information.png:/icons/dialog-information.png + + + Log + + + 8 + + + + + + + QAbstractItemView::NoEditTriggers + + + false + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + + + + + + + + + + :/icons/qvariantedit.png:/icons/qvariantedit.png + + + X + + + 1 + + + + + + + + + + + + + :/icons/configure.png:/icons/configure.png + + + Session + + + 2 + + + + + + + Apply + + + + :/icons/dialog-ok-apply.png:/icons/dialog-ok-apply.png + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Name: + + + + + + + + + + + + Select icon... + + + + :/icons/view-preview.png:/icons/view-preview.png + + + + + + + + + K file: + + + + + + + + + + X file: + + + + + + + + + + C file: + + + + + + + + + + Sync files + + + + + + + + + K + + + + + + + X + + + + + + + C + + + + + + + M + + + + + + + + + Default config + + + + + + + M file: + + + + + + + + + + + + + 0 + 0 + + + + include = ip.conf +[connection] +device.cd = eth://udp:${ip.pult}:27002:${ip.app}:27001 #s +[] + + + + + DejaVu Sans Mono + 9 + + + + + + + + + + + :/icons/legend.png:/icons/legend.png + + + C + + + 1 + + + + + + + + + + + + + :/icons/format-stroke-color.png:/icons/format-stroke-color.png + + + Graphics + + + 8 + + + + + + + + + + + + + :/icons/tools-wizard.png:/icons/tools-wizard.png + + + Direct K + + + 8 + + + + + + + + + + + + + :/icons/accessories-text-editor.png:/icons/accessories-text-editor.png + + + M + + + 1 + + + + + + + + + + + + + :/icons/document-open.png:/icons/document-open.png + + + Open... + + + Ctrl+O + + + + + + :/icons/document-save.png:/icons/document-save.png + + + Save + + + Ctrl+S + + + + + + :/icons/document-save-as.png:/icons/document-save-as.png + + + Save As... + + + Ctrl+Shift+S + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + EMainWindow + QMainWindow +
emainwindow.h
+ 1 +
+ + CLineEdit + QLineEdit +
clineedit.h
+
+ + QCodeEdit + QWidget +
qcodeedit.h
+
+ + QVariantEdit + QWidget +
qvariantedit.h
+
+ + EDockWidget + QDockWidget +
edockwidget.h
+ 1 +
+ + CDViewWidget + QWidget +
cdviewwidget.h
+ 1 +
+ + CDGraphics + QWidget +
cdgraphics.h
+ 1 +
+ + CDDirectK + QWidget +
cddirectk.h
+ 1 +
+
+ + + + + + + + + actionSave + triggered() + CDPultWindow + saveFile() + + + -1 + -1 + + + 399 + 299 + + + + + actionSaveAs + triggered() + CDPultWindow + saveAsFile() + + + -1 + -1 + + + 399 + 299 + + + + + actionOpen + triggered() + CDPultWindow + openFile() + + + -1 + -1 + + + 399 + 299 + + + + + checkSyncFiles + toggled(bool) + editFileX + setDisabled(bool) + + + 786 + 220 + + + 786 + 151 + + + + + checkSyncFiles + toggled(bool) + editFileC + setDisabled(bool) + + + 786 + 220 + + + 786 + 172 + + + + + checkDefaultConfig + toggled(bool) + codeConfig + setDisabled(bool) + + + 786 + 276 + + + 581 + 304 + + + + + checkSyncFiles + toggled(bool) + editFileM + setDisabled(bool) + + + 767 + 205 + + + 767 + 187 + + + + +
diff --git a/utils/cd_pult/cdviewwidget.cpp b/utils/cd_pult/cdviewwidget.cpp new file mode 100644 index 0000000..67fa124 --- /dev/null +++ b/utils/cd_pult/cdviewwidget.cpp @@ -0,0 +1,78 @@ +#include "cdviewwidget.h" +#include "cdutils_core.h" +#include "qcd_core.h" +#include "qcd_model.h" +#include "qcd_modedialog.h" +#include "qvariantedit.h" +#include + + +CDViewWidget::CDViewWidget(QWidget * parent) : QWidget(parent), Ui::CDViewWidget() { + qRegisterMetaType("CDViewWidget::LogIcon"); + setupUi(this); + connect(view, SIGNAL(sendSucceed()), this, SLOT(sended())); + connect(view, SIGNAL(receiveSucceed()), this, SLOT(received())); + connect(view, SIGNAL(sendFailed()), this, SLOT(sendFailed())); + connect(view, SIGNAL(receiveFailed()), this, SLOT(receiveFailed())); +} + + +CDViewWidget::~CDViewWidget() { +} + + +void CDViewWidget::reset() { + setFile(""); +} + + +void CDViewWidget::setType(int t) { + view->setType((CDUtils::CDType::cdT)t); + tl_u = view->typeLetter().toUpper(); + tl_l = view->typeLetter().toLower(); + view->refresh(); +} + + +void CDViewWidget::setFile(const QString & f) { + view->setFile(f); + view->load(); +} + + +void CDViewWidget::on_buttonSend_clicked() { + if (view->inProgress()) {addToLog(WaitIcon, "processing..."); return;} + addToLog(WaitIcon, "Sending " + tl_u + "..."); + view->send(); +} + + +void CDViewWidget::on_buttonReceive_clicked() { + if (view->inProgress()) {addToLog(WaitIcon, "processing..."); return;} + addToLog(WaitIcon, "Receiving " + tl_u + "..."); + view->receive(); +} + + +void CDViewWidget::on_buttonLoad_clicked() { + view->load(); +} + + +void CDViewWidget::on_buttonSave_clicked() { + view->save(); +} + + +void CDViewWidget::on_buttonParse_clicked() { + QString path = QFileDialog::getOpenFileName(this, "Select header file", "", + QString("%1 Description(%2_description.h);;Headers(*.h)").arg(tl_u, tl_l)); + if (path.isEmpty()) return; + CDUtils::UpdateModeFlags mode = CDUtils::SaveByName; + if (!view->root()->isEmpty()) { + QCDModeDialog cdm; + if (cdm.exec() != QDialog::Accepted) return; + mode = cdm.mode(); + } + view->buildFromHeader(path, mode); +} diff --git a/utils/cd_pult/cdviewwidget.h b/utils/cd_pult/cdviewwidget.h new file mode 100644 index 0000000..9b1abb1 --- /dev/null +++ b/utils/cd_pult/cdviewwidget.h @@ -0,0 +1,41 @@ +#ifndef CDVIEWWIDGET_H +#define CDVIEWWIDGET_H + +#include +#include "ui_cdviewwidget.h" + + +class CDViewWidget : public QWidget, public Ui::CDViewWidget +{ + Q_OBJECT +public: + explicit CDViewWidget(QWidget *parent = 0); + ~CDViewWidget(); + + enum LogIcon {NoIcon, OKIcon, FailIcon, WaitIcon}; + + void reset(); + void setType(int t); + void setFile(const QString & f); + +private: + QString tl_u, tl_l; + +private slots: + void sended() {addToLog(OKIcon, tl_u + " " + tr("sended succesfull"));} + void received() {addToLog(OKIcon, tl_u + " " + tr("received succesfull"));} + void sendFailed() {addToLog(FailIcon, tl_u + " " + tr("NOT sended"));} + void receiveFailed() {addToLog(FailIcon, tl_u + " " + tr("NOT received"));} + void on_buttonSend_clicked(); + void on_buttonReceive_clicked(); + void on_buttonLoad_clicked(); + void on_buttonSave_clicked(); + void on_buttonParse_clicked(); + //void on_buttonCalculate_clicked(); + +signals: + void addToLog(CDViewWidget::LogIcon icon, const QString & msg); + +}; + +#endif // CDVIEWWIDGET_H diff --git a/utils/cd_pult/cdviewwidget.ui b/utils/cd_pult/cdviewwidget.ui new file mode 100644 index 0000000..eb2d44c --- /dev/null +++ b/utils/cd_pult/cdviewwidget.ui @@ -0,0 +1,176 @@ + + + CDViewWidget + + + + 0 + 0 + 689 + 459 + + + + CD Pult + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + Send + + + + :/icons/flame.png:/icons/flame.png + + + + + + + Receive + + + + :/icons/document-revert.png:/icons/document-revert.png + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 20 + 20 + + + + + + + + Load + + + + :/icons/document-open.png:/icons/document-open.png + + + + + + + Save + + + + :/icons/document-save.png:/icons/document-save.png + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 20 + 20 + + + + + + + + Update description ... + + + + :/icons/view-refresh.png:/icons/view-refresh.png + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 1 + 20 + + + + + + + + + + + + Qt::CustomContextMenu + + + QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + + true + + + QAbstractItemView::DragOnly + + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + + + + + + + + CDView + QTreeView +
qcd_view.h
+
+
+ + + + + +
diff --git a/utils/cd_pult/icons/accessories-calculator.png b/utils/cd_pult/icons/accessories-calculator.png new file mode 100644 index 0000000..37a3035 Binary files /dev/null and b/utils/cd_pult/icons/accessories-calculator.png differ diff --git a/utils/cd_pult/icons/accessories-text-editor.png b/utils/cd_pult/icons/accessories-text-editor.png new file mode 100644 index 0000000..1d9dca2 Binary files /dev/null and b/utils/cd_pult/icons/accessories-text-editor.png differ diff --git a/utils/cd_pult/icons/db-export.png b/utils/cd_pult/icons/db-export.png new file mode 100644 index 0000000..7cfba88 Binary files /dev/null and b/utils/cd_pult/icons/db-export.png differ diff --git a/utils/cd_pult/icons/db-import.png b/utils/cd_pult/icons/db-import.png new file mode 100644 index 0000000..85bc121 Binary files /dev/null and b/utils/cd_pult/icons/db-import.png differ diff --git a/utils/cd_pult/icons/flame.png b/utils/cd_pult/icons/flame.png new file mode 100644 index 0000000..d267f72 Binary files /dev/null and b/utils/cd_pult/icons/flame.png differ diff --git a/utils/cd_pult/icons/pult.png b/utils/cd_pult/icons/pult.png new file mode 100644 index 0000000..9bd0225 Binary files /dev/null and b/utils/cd_pult/icons/pult.png differ diff --git a/utils/cd_pult/icons/timer.png b/utils/cd_pult/icons/timer.png new file mode 100644 index 0000000..c0b8361 Binary files /dev/null and b/utils/cd_pult/icons/timer.png differ diff --git a/utils/cd_pult/main.cpp b/utils/cd_pult/main.cpp new file mode 100644 index 0000000..505f4d0 --- /dev/null +++ b/utils/cd_pult/main.cpp @@ -0,0 +1,373 @@ +#include +#include "cdpultwindow.h" + +template +class PIHash { + //template friend PIByteArray & operator >>(PIByteArray & s, PIHash & v); + //template friend PIByteArray & operator <<(PIByteArray & s, const PIHash & v); +public: + PIHash() {;} + PIHash(const PIHash & other) {*this = other;} + virtual ~PIHash() {;} + + PIHash & operator =(const PIHash & other) { + if (this == &other) return *this; + clear(); + pih_content = other.pih_content; + return *this; + } + + typedef T mapped_type; + typedef Key key_type; + typedef PIPair value_type; +/* + class iterator { + friend class PIHash; + private: + iterator(const PIHash * v, ssize_t p): parent(v), pos(p) {} + const PIHash * parent; + ssize_t pos; + public: + iterator(): parent(0), pos(0) {} + const Key & key() const {return const_cast * >(parent)->_key(pos);} + T & value() {return const_cast * >(parent)->_value(pos);} + void operator ++() {++pos;} + void operator ++(int) {++pos;} + void operator --() {--pos;} + void operator --(int) {--pos;} + bool operator ==(const iterator & it) const {return (pos == it.pos);} + bool operator !=(const iterator & it) const {return (pos != it.pos);} + }; + + class reverse_iterator { + friend class PIHash; + private: + reverse_iterator(const PIHash * v, ssize_t p): parent(v), pos(p) {} + const PIHash * parent; + ssize_t pos; + public: + reverse_iterator(): parent(0), pos(0) {} + const Key & key() const {return const_cast * >(parent)->_key(pos);} + T & value() const {return const_cast * >(parent)->_value(pos);} + void operator ++() {--pos;} + void operator ++(int) {--pos;} + void operator --() {++pos;} + void operator --(int) {++pos;} + bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);} + bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);} + }; +*/ + class const_iterator { + friend class PIHash; + private: + const_iterator(const PIHash * v, ssize_t p): parent(v), pos(p), bpos(0) { + if (pos == 0) { + pos = -1; + nextPos(); + } + } + void nextPos() { + while (++pos < parent->pih_content.size_s()) { + if (!parent->pih_content[pos].isEmpty()) + return; + } + } + const PIHash * parent; + ssize_t pos, bpos; + public: + const_iterator(): parent(0), pos(0) {} + //const value_type operator *() const {return parent->_pair(pos);} + //const value_type* operator ->() const {cval = parent->_pair(pos); return &cval;} + const Key & key() const {return const_cast * >(parent)->pih_content[pos][bpos].key;} + const T & value() const {return const_cast * >(parent)->pih_content[pos][bpos].value;} + void operator ++() { + if (pos < parent->pih_content.size_s()) { + if (bpos >= parent->pih_content[pos].size_s() - 1) { + bpos = 0; + nextPos(); + } else + ++bpos; + } else { + bpos = 0; + ++pos; + } + printf(" ++: %d %d\n", pos, bpos); + } + //void operator ++(int) {++pos;} + void operator --() { + --pos; + } + //void operator --(int) {--pos;} + bool operator ==(const const_iterator & it) const {return (pos == it.pos && bpos == it.bpos);} + bool operator !=(const const_iterator & it) const {return !(*this == it);} + mutable value_type cval; + }; +/* + class const_reverse_iterator { + friend class PIHash; + private: + const_reverse_iterator(const PIHash * v, ssize_t p): parent(v), pos(p) {} + const PIHash * parent; + ssize_t pos; + public: + const_reverse_iterator(): parent(0), pos(0) {} + const value_type operator *() const {return parent->_pair(pos);} + const value_type* operator ->() const {cval = parent->_pair(pos); return &cval;} + void operator ++() {--pos;} + void operator ++(int) {--pos;} + void operator --() {++pos;} + void operator --(int) {++pos;} + bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);} + bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);} + mutable value_type cval; + }; +*/ + //iterator begin() {return iterator(this, 0);} + //iterator end() {return iterator(this, size());} + const_iterator begin() const {return const_iterator(this, 0);} + const_iterator end() const {return const_iterator(this, size());} + const_iterator constBegin() const {return const_iterator(this, 0);} + const_iterator constEnd() const {return const_iterator(this, size());} + //reverse_iterator rbegin() {return reverse_iterator(this, size() - 1);} + //reverse_iterator rend() {return reverse_iterator(this, -1);} + //const_reverse_iterator rbegin() const {return const_reverse_iterator(this, size() - 1);} + //const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);} + //const_reverse_iterator constRbegin() const {return const_reverse_iterator(this, size() - 1);} + //const_reverse_iterator constRend() const {return const_reverse_iterator(this, -1);} + + size_t size() const {return pih_content.size();} + int size_s() const {return pih_content.size_s();} + size_t length() const {return pih_content.size();} + size_t capacity() const {return pih_content.size();} + bool isEmpty() const {return (pih_content.size() == 0);} + + T & operator [](const Key & key) { + if (pih_content.isEmpty()) _rehash(1); + uint k = piHash(key); + int i = _index(k); + if (i < pih_content.size_s()) { + PIVector & hv(pih_content[i]); + if (hv.size_s() == 1) { + if (hv[0].key == k) + return hv[0].value; + } + for (int j = 0; j < hv.size_s(); ++j) + if (hv[j].key == k) + return hv[j].value; + } + if (pih_content[i].size_s() >= 4) + _rehash(pih_content.size_s() * 2); + i = _index(k); + pih_content[i] << HashEntry(k); + return pih_content[i].back().value; + } + const T operator [](const Key & key) const {return value(key);} + T & at(const Key & key) {return (*this)[key];} + const T at(const Key & key) const {return (*this)[key];} + + PIHash & operator <<(const PIHash & other) { + if (other.isEmpty()) return *this; + for (int i = 0; i < other.pih_content.size_s(); ++i) + for (int j = 0; j < other.pih_content[i].size_s(); ++j) + insert(other.pih_content[i][j].key, other.pih_content[i][j].value); + return *this; + } + + bool operator ==(const PIHash & t) const {return (pih_content == t.pih_content);} + bool operator !=(const PIHash & t) const {return (pih_content != t.pih_content);} + bool contains(const Key & key) const { + bool f(false); + _find(key, f); + return f; + } + + PIHash & reserve(size_t new_size) {_rehash(new_size); return *this;} + + PIHash & remove(const Key & key) { + uint k = piHash(key); + int i = _index(k); + if (i >= pih_content.size_s()) return *this; + PIVector & hv(pih_content[i]); + for (int j = 0; j < hv.size_s(); ++j) + if (hv[j].key == k) { + hv.remove(j); + --j; + } + return *this; + } + PIHash & erase(const Key & key) {return remove(key);} + PIHash & clear() {pih_content.clear(); return *this;} + + void swap(PIHash & other) { + pih_content.swap(other.pih_content); + } + + PIHash & insert(const Key & key, const T & value) { + (*this)[key] = value; + return *this; + } + const T value(const Key & key, const T & default_ = T()) const { + uint k = piHash(key); + int i = _index(k); + if (i >= pih_content.size_s()) return default_; + const PIVector & hv(pih_content[i]); + for (int j = 0; j < hv.size_s(); ++j) + if (hv[j].key == k) + return hv[j].value; + return default_; + } + PIVector values() const { + PIVector ret; + for (int i = 0; i < pih_content.size_s(); ++i) + for (int j = 0; j < pih_content[i].size_s(); ++j) + ret << pih_content[i][j].value; + return ret; + } + /*Key key(const T & value_, const Key & default_ = Key()) const { + for (int i = 0; i < pih_content.size_s(); ++i) + for (int j = 0; j < pih_content[i].size_s(); ++j) + if (pih_content[i][j].value == value_) + return pih_content[i][j].key; + return default_; + } + PIVector keys() const { + PIVector ret; + for (int i = 0; i < pih_content.size_s(); ++i) + for (int j = 0; j < pih_content[i].size_s(); ++j) + ret << pih_content[i][j].key; + return ret; + }*/ + + /*void dump() { + piCout << "PIHash" << size() << "entries" << PICoutManipulators::NewLine << "content:"; + for (size_t i = 0; i < pih_content.size(); ++i) + piCout << PICoutManipulators::Tab << i << ":" << pih_content[i]; + piCout << "index:"; + for (size_t i = 0; i < pim_index.size(); ++i) + piCout << PICoutManipulators::Tab << i << ":" << pim_index[i].key << "->" << pim_index[i].index; + }*/ + +protected: + struct HashEntry { + HashEntry(uint k = 0, const T & v = T()): key(k), value(v) {;} + uint key; + T value; + bool operator ==(const HashEntry & s) const {return key == s.key;} + bool operator !=(const HashEntry & s) const {return key != s.key;} + bool operator <(const HashEntry & s) const {return key < s.key;} + bool operator >(const HashEntry & s) const {return key > s.key;} + }; + /*template friend PIByteArray & operator >>(PIByteArray & s, PIDeque::HashEntry> & v); + template friend PIByteArray & operator <<(PIByteArray & s, const PIDeque::HashEntry> & v); + + const value_type _pair(ssize_t index) const { + if (index < 0 || index >= pim_index.size_s()) + return value_type(); + //piCout << "_pair" << index << pim_index[index].index; + return value_type(pim_index[index].key, pih_content[pim_index[index].index]); + } + Key & _key(ssize_t index) {return pim_index[index].key;} + T & _value(ssize_t index) {return pih_content[pim_index[index].index];}*/ + + inline size_t asize(size_t s) { + if (s == 0) return 0; + if (pih_content.size() + pih_content.size() >= s && pih_content.size() < s) + return pih_content.size() + pih_content.size(); + ssize_t t = 0, s_ = s - 1; + while (s_ >> t) ++t; + return (1 << t); + } + int _index(const uint & k) const { + return k % pih_content.size_s(); + } + void _rehash(int ns) { + ns = asize(ns); + if (pih_content.size_s() == ns) return; + PIVector > nhc; + nhc.resize(ns); + for (int i = 0; i < pih_content.size_s(); ++i) { + for (int j = 0; j < pih_content[i].size_s(); ++j) { + HashEntry & e(pih_content[i][j]); + int ni = e.key % ns; + nhc[ni] << e; + } + } + pih_content.swap(nhc); + } + + PIVector > pih_content; +}; + + +uint qHash(const PIString & v, uint seed = 0) {return piHash(v);} + + +#include "logview.h" +int main(int argc, char *argv[]) { + QApplication a(argc, argv); +#if QT_VERSION >= 0x050000 + a.setAttribute(Qt::AA_UseHighDpiPixmaps, true); +#endif + //################################ + /*QHash h2; + QMap m2; + PIString prefix = "1234567890"; + PITimeMeasurer tm; + double el = 0.; + + tm.reset(); + for (int i=0; i<10000; ++i) { + h2[prefix + PIString::fromNumber(i)+"1234567890"] = PIString::fromNumber(randomi()); + } + el = tm.elapsed_m(); piCout << el << h2.capacity(); + + tm.reset(); + for (int i=0; i<10000; ++i) { + m2[prefix + PIString::fromNumber(i)+"1234567890"] = PIString::fromNumber(randomi()); + } + el = tm.elapsed_m(); piCout << el; + piCout << "*********"; + + PIString _s; + tm.reset(); + for (int i=0; i<10000; ++i) { + _s = h2.value(prefix + PIString::fromNumber(i)+"1234567890"); + } + el = tm.elapsed_m(); piCout << el << h2.capacity(); + + tm.reset(); + for (int i=0; i<10000; ++i) { + _s = m2.value(prefix + PIString::fromNumber(i)+"1234567890"); + } + el = tm.elapsed_m(); piCout << el; + + return 0;*/ + //################################ +//1245hghgfhfdgshrgnhdsgfhjshdszdgsdgnjedghrbnlcvleabjmbassfdggfhbnsjkgnfdvfdsdfojbwasv213443gr2t4sfth + /*LogView lw; + lw.setLogFont(QFont("dejavu sans mono", 9)); + lw.registerCategory("Warning", "Warning", QImage(":/icons/flame.png"), Qt::darkYellow); + lw.registerCategory("Error", "Error", QImage(":/icons/dialog-cancel.png"), Qt::darkRed, true); + //lw.setLinesLimit(12); + lw.show(); + piForTimes(100) + lw.addText(QString("row %1").arg(_i100)); + lw.addText("-- Up-to-date: C:/sdk/MinGW/x32/i686-w64-mingw32/include/qglengine/scene_tree.h"); + lw.addText("-- Up-to-date: C:/sdk/MinGW/x32/i686-w64-mingw32/include/qglengine/scene_tree.h"); + lw.addText("-- Up-to-date: C:/sdk/MinGW/x32/i686-w64-mingw32/include/qglengine/view_editor.h"); + lw.addText("-- Up-to-date: C:/sdk/MinGW/x32/i686-w64-mingw32/include/qglengine/material_map_editor.h\n" + "-- Up-to-date: C:/sdk/MinGW/x32/i686-w64-mingw32/include/qglengine/materials_editor\n" + "-- Up-to-date: C:/sdk/MinGW/x32/i686-w64-mingw32/include/qglengine/object_editor.h"); + lw.addText("[Warning] sdfkjhdfgj"); + lw.addText("[Error] gbflknwed"); + QLineEdit * le = new QLineEdit(); + QObject::connect(le, &QLineEdit::returnPressed, [&](){lw.addText(le->text());}); + le->show(); + return a.exec();*/ + + CDPultWindow w; + w.show(); + if (a.arguments().size() > 1) + w.loadFile(a.arguments()[1]); + return a.exec(); +}